#include "APP/APP_UIWindow.h" #include "APP/APP_KeyButton.h" #include "APP/APP_UIWindow_Private.h" #include #include #include #include #include #include #include #include namespace APP { namespace { QString App_Func_GetDefaultKeyDescription(quint16 Usage) { return QStringLiteral( "Default numpad key: %1. Left click simulates a real press/release. " "Right click binds a function.") .arg(Lgc_Core_GetUsageShortText(Usage)); } } // namespace void App_UIWindow::App_Func_RefreshKeypadState() { const Lgc_Core_Struct_View View = Lgc_Core_GetView(&appLgcState); appKeypadModel.App_Func_SetNumLockOn(View.IsSystemNumLockOn); if (View.IsPhysicalKeyStateValid) { appKeypadModel.App_Func_SetPressedKeysFromUsageList(View.PhysicalUsageList); return; } if (View.IsVisibleKeyStateValid) { appKeypadModel.App_Func_SetPressedKeysFromUsageList(View.VisibleUsageList); return; } appKeypadModel.App_Func_ClearPressedKeys(); } void App_UIWindow::App_Func_RefreshKeypadButtons() { for (auto It = appKeypadButtonMap.begin(); It != appKeypadButtonMap.end(); ++It) { const QString KeyId = It.key(); const quint16 Usage = appKeypadModel.App_Func_GetUsageFromKeyId(KeyId); const int FeatureId = Lgc_Core_GetUsageFeatureId(&appLgcState, Usage); APP_KeyButton* p_Button = It.value(); p_Button->App_Func_SetLatched( appKeypadModel.App_Func_IsLatched(KeyId) || (FeatureId > 0)); p_Button->App_Func_SetPressed(appKeypadModel.App_Func_IsPressed(KeyId)); p_Button->App_Func_SetHintText( FeatureId > 0 ? Lgc_Core_GetFeatureNameById(&appLgcState, FeatureId) : appKeypadModel.App_Func_GetDefaultHint(KeyId)); p_Button->setToolTip( FeatureId > 0 ? Lgc_Core_GetFeatureDescriptionById(&appLgcState, FeatureId) : App_Func_GetDefaultKeyDescription(Usage)); } } void App_UIWindow::App_Func_RefreshFeatureTable() { const QVector FeatureIdList = Lgc_Core_GetFeatureIdList(&appLgcState); const bool HasFeatures = !FeatureIdList.isEmpty(); QSignalBlocker Blocker(appFeatureTable); appFeatureTable->clearContents(); appFeatureTable->setRowCount(FeatureIdList.size()); int TargetRow = -1; for (int Row = 0; Row < FeatureIdList.size(); ++Row) { const int FeatureId = FeatureIdList.at(Row); const Lgc_FunctionFeature_Definition Feature = Lgc_Core_GetFeature(&appLgcState, FeatureId); QTableWidgetItem* p_NameItem = new QTableWidgetItem(Lgc_Core_GetFeatureNameById(&appLgcState, FeatureId)); p_NameItem->setData(Qt::UserRole, FeatureId); appFeatureTable->setItem(Row, 0, p_NameItem); appFeatureTable->setItem( Row, 1, new QTableWidgetItem(Lgc_Core_GetFeatureDescriptionById(&appLgcState, FeatureId))); appFeatureTable->setItem( Row, 2, new QTableWidgetItem(Lgc_Core_GetFeatureTypeText(Feature.Type))); if (FeatureId == appSelectedFeatureId) { TargetRow = Row; } } appSelectedFeatureId = TargetRow >= 0 ? appSelectedFeatureId : (HasFeatures ? FeatureIdList.first() : 0); TargetRow = TargetRow >= 0 ? TargetRow : (HasFeatures ? 0 : -1); if (TargetRow >= 0) { appFeatureTable->selectRow(TargetRow); } else { appFeatureTable->clearSelection(); } App_Func_UpdateFeatureEditorState(); } void App_UIWindow::App_Func_RefreshFunctionStatus() { const Lgc_Core_Struct_View View = Lgc_Core_GetView(&appLgcState); appFunctionLabelStatus->setText( View.TextFunctionStatus.isEmpty() ? QStringLiteral("Waiting for function-key activity.") : View.TextFunctionStatus); } void App_UIWindow::App_Func_SelectFeature(int FeatureId, bool SwitchToFeaturePage) { if (appIsSequenceRecording && (FeatureId != appSelectedFeatureId)) { App_Func_StopSequenceRecording(); } appSelectedFeatureId = Lgc_Core_GetFeature(&appLgcState, FeatureId).Id > 0 ? FeatureId : 0; if (appSelectedFeatureId > 0) { for (int Row = 0; Row < appFeatureTable->rowCount(); ++Row) { QTableWidgetItem* p_Item = appFeatureTable->item(Row, 0); if ((p_Item != nullptr) && (p_Item->data(Qt::UserRole).toInt() == appSelectedFeatureId)) { QSignalBlocker Blocker(appFeatureTable); appFeatureTable->selectRow(Row); break; } } } App_Func_UpdateFeatureEditorState(); if (SwitchToFeaturePage) { appPageTab->setCurrentIndex(appFeaturePageIndex); } } void App_UIWindow::App_Func_SaveFeatureFromUi() { if (appSelectedFeatureId <= 0) { return; } Lgc_FunctionFeature_Definition Feature = Lgc_Core_GetFeature(&appLgcState, appSelectedFeatureId); if (Feature.Id <= 0) { return; } Feature.Name = appFeatureNameEdit->text(); Feature.Description = appFeatureDescriptionEdit->text(); Feature.Type = static_cast(appFeatureTypeCombo->currentData().toInt()); Feature.SequenceText = appFeatureSequenceEdit->text(); Feature.WebsiteUrl = appFeatureWebsiteEdit->text(); if ((Feature.Type == Lgc_FunctionFeature_Type::Website) && Feature.WebsiteUrl.trimmed().isEmpty()) { Feature.WebsiteUrl = QStringLiteral("https://"); QSignalBlocker Blocker(appFeatureWebsiteEdit); appFeatureWebsiteEdit->setText(Feature.WebsiteUrl); } Lgc_Core_UpdateFeature(&appLgcState, Feature); appFeatureEditorStack->setCurrentIndex(App_Func_GetFeatureStackIndex(Feature.Type)); App_Func_UpdateFeatureEditorHeight(); Lgc_Core_SaveFunctionConfig(&appLgcState); App_Func_RefreshAfterLogicChange(); // FIX: keep Device Test and status text aligned after feature edits. } void App_UIWindow::App_Func_UpdateFeatureEditorHeight() { if ((appFeatureEditorStack == nullptr) || (appFeatureEditorStack->currentWidget() == nullptr)) { return; } const int Height = appFeatureEditorStack->currentWidget()->sizeHint().height(); if (appFeatureEditorStack->height() != Height) { appFeatureEditorStack->setFixedHeight(Height); } } void App_UIWindow::App_Func_UpdateFeatureEditorState() { const Lgc_FunctionFeature_Definition Feature = Lgc_Core_GetFeature(&appLgcState, appSelectedFeatureId); const bool HasFeature = Feature.Id > 0; if (appIsSequenceRecording && (!HasFeature || !App_Func_IsKeyRecordFeatureType(Feature.Type))) { App_Func_StopSequenceRecording(); } appFeatureNameEdit->setEnabled(HasFeature); appFeatureDescriptionEdit->setEnabled(HasFeature); appFeatureTypeCombo->setEnabled(HasFeature); appFeatureEditorStack->setEnabled(HasFeature); appFeatureDeleteButton->setEnabled(HasFeature); appIsUpdatingFeatureUi = true; if (!HasFeature) { appFeatureNameEdit->clear(); appFeatureDescriptionEdit->clear(); appFeatureSequenceEdit->clear(); appFeatureWebsiteEdit->clear(); appFeatureTypeCombo->setCurrentIndex(0); appFeatureEditorStack->setCurrentIndex(0); App_Func_UpdateFeatureEditorHeight(); appFeatureBindingSummaryLabel->setText(QStringLiteral("No function selected yet.")); appIsUpdatingFeatureUi = false; App_Func_UpdateSequenceRecordingUi(); return; } appFeatureNameEdit->setText(Feature.Name); appFeatureDescriptionEdit->setText(Feature.Description); const int TypeIndex = appFeatureTypeCombo->findData(static_cast(Feature.Type)); if (TypeIndex >= 0) { appFeatureTypeCombo->setCurrentIndex(TypeIndex); } appFeatureSequenceEdit->setText(Feature.SequenceText); appFeatureWebsiteEdit->setText(App_Func_GetWebsiteEditText(Feature.WebsiteUrl)); appFeatureEditorStack->setCurrentIndex(App_Func_GetFeatureStackIndex(Feature.Type)); appFeatureSequenceEdit->setPlaceholderText( Feature.Type == Lgc_FunctionFeature_Type::KeySequence ? QStringLiteral("Example: Ctrl+C -> Ctrl+A") : QStringLiteral("Example: Ctrl+C")); App_Func_UpdateFeatureEditorHeight(); appFeatureBindingSummaryLabel->setText( Lgc_Core_GetFeatureBindingSummary(&appLgcState, Feature.Id)); appIsUpdatingFeatureUi = false; App_Func_UpdateSequenceRecordingUi(); } void App_UIWindow::App_Func_AddFeature() { const int FeatureId = Lgc_Core_AddFeature(&appLgcState); Lgc_Core_SaveFunctionConfig(&appLgcState); App_Func_RefreshFeatureTable(); // FIX: the feature table must update before reselection. App_Func_RefreshAfterLogicChange(); // FIX: refresh Device Test and current config state after add. App_Func_SelectFeature(FeatureId, true); } void App_UIWindow::App_Func_DeleteFeature() { if (appSelectedFeatureId <= 0) { return; } if (appIsSequenceRecording) { App_Func_StopSequenceRecording(); } Lgc_Core_DeleteFeature(&appLgcState, appSelectedFeatureId); appSelectedFeatureId = 0; Lgc_Core_SaveFunctionConfig(&appLgcState); App_Func_RefreshFeatureTable(); // FIX: rebuild the feature table after delete. App_Func_RefreshAfterLogicChange(); // FIX: refresh Device Test and current config state after delete. } } // namespace APP