#include "APP/APP_UIWindow.h" #include "APP/APP_KeyButton.h" #include "APP/APP_UIWindow_Private.h" #include "DEBUG/Debug_Panel.h" #include #include #include #include #include #include #include #include #include namespace APP { namespace { bool App_Func_HasDebugSendRoute(const Lgc_Core_Struct_State& State) { return State.DriVendorPort.ReadPort.IsOpened || State.DriBlePort.IsConnected; } QString App_Func_GetDebugSendModeText(const Lgc_Core_Struct_State& State) { if (State.DriBlePort.IsConnected || State.DriVendorPort.IsBluetoothTransport) { return QStringLiteral("蓝牙模式"); } if (State.DriVendorPort.ReadPort.IsOpened) { return QStringLiteral("USB 模式"); } return QStringLiteral("未连接"); } QString App_Func_GetDebugConfigStatusText(const Lgc_Core_Struct_State& State) { return QStringLiteral("目标 USB 0x%1:0x%2 / 当前发包模式:%3") .arg(State.DeviceConfig.VendorId, 4, 16, QLatin1Char('0')) .arg(State.DeviceConfig.ProductId, 4, 16, QLatin1Char('0')) .arg(App_Func_GetDebugSendModeText(State)) .toUpper(); } } // namespace void App_UIWindow::App_Func_RefreshUi() { App_Func_RefreshKeypadButtons(); App_Func_RefreshFunctionStatus(); update(); } void App_UIWindow::App_Func_RefreshKeypadState() { appKeypadModel.App_Func_SetNumLockOn(appLgcState.IsSystemNumLockOn); const QVector* p_UsageList = appLgcState.IsPhysicalKeyStateValid ? &appLgcState.PhysicalUsageList : (appLgcState.IsVisibleKeyStateValid ? &appLgcState.VisibleUsageList : nullptr); if (p_UsageList != nullptr) { appKeypadModel.App_Func_SetPressedKeysFromUsageList(*p_UsageList); } else { 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 bool HasFeature = Lgc_FunctionButton_HasUsageFeature(appLgcState.FunctionButtonConfig, Usage); APP_KeyButton* p_Button = It.value(); p_Button->App_Func_SetLatched(appKeypadModel.App_Func_IsLatched(KeyId) || HasFeature); p_Button->App_Func_SetPressed(appKeypadModel.App_Func_IsPressed(KeyId)); p_Button->App_Func_SetHintText(App_Func_GetKeyHintText(KeyId)); p_Button->setToolTip(App_Func_GetFeatureDescriptionForUsage(Usage)); } } void App_UIWindow::App_Func_RefreshFeatureTable() { if (appFeatureTable == nullptr) { return; } const QVector FeatureIdList = Lgc_FunctionButton_GetFeatureIdList(appLgcState.FunctionButtonConfig); 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_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, FeatureId); QTableWidgetItem* p_NameItem = new QTableWidgetItem(Lgc_FunctionButton_GetFeatureName(Feature)); p_NameItem->setData(Qt::UserRole, FeatureId); appFeatureTable->setItem(Row, 0, p_NameItem); appFeatureTable->setItem(Row, 1, new QTableWidgetItem(App_Func_GetFeatureDescriptionById(FeatureId))); appFeatureTable->setItem(Row, 2, new QTableWidgetItem(Lgc_FunctionButton_GetFeatureTypeText(Feature.Type))); if (FeatureId == appSelectedFeatureId) { TargetRow = Row; } } appSelectedFeatureId = TargetRow >= 0 ? appSelectedFeatureId : (FeatureIdList.isEmpty() ? 0 : FeatureIdList.first()); TargetRow = TargetRow >= 0 ? TargetRow : (FeatureIdList.isEmpty() ? -1 : 0); if (TargetRow >= 0) { appFeatureTable->selectRow(TargetRow); } else { appFeatureTable->clearSelection(); } App_Func_UpdateFeatureEditorState(); } void App_UIWindow::App_Func_RefreshFunctionStatus() { if (appFunctionLabelStatus != nullptr) { appFunctionLabelStatus->setText( appLgcState.TextFunctionStatus.isEmpty() ? QStringLiteral("等待按键动作。") : appLgcState.TextFunctionStatus); } } void App_UIWindow::App_Func_RefreshDebugView() { #if APP_ENABLE_DEBUG_WINDOW appDebugPanel->Debug_Func_SetConfigStatusText( App_Func_GetDebugConfigStatusText(appLgcState), App_Func_HasDebugSendRoute(appLgcState)); appDebugPanel->Debug_Func_SetConnectionText( appLgcState.IsConnected ? QStringLiteral("连接成功") : QStringLiteral("连接失败"), appLgcState.IsConnected); appDebugPanel->Debug_Func_SetLogText(appLgcState.TextLog); #endif } void App_UIWindow::App_Func_RefreshAfterLogicChange() { App_Func_RefreshKeypadState(); App_Func_RefreshDebugView(); App_Func_RefreshUi(); } void App_UIWindow::App_Func_SelectFeature(int FeatureId, bool SwitchToFeaturePage) { if (appIsSequenceRecording && (FeatureId != appSelectedFeatureId)) { App_Func_StopSequenceRecording(); } appSelectedFeatureId = appLgcState.FunctionButtonConfig.FeatureMap.contains(FeatureId) ? FeatureId : 0; if ((appFeatureTable != nullptr) && (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 != nullptr)) { appPageTab->setCurrentIndex(appFeaturePageIndex); } } void App_UIWindow::App_Func_SaveFeatureFromUi() { if (appSelectedFeatureId <= 0) { return; } Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, 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_FunctionButton_SetFeature(&appLgcState.FunctionButtonConfig, Feature); appFeatureEditorStack->setCurrentIndex(App_Func_GetFeatureStackIndex(Feature.Type)); App_Func_UpdateFeatureEditorHeight(); App_Func_RefreshFeatureTable(); App_Func_RefreshUi(); } void App_UIWindow::App_Func_UpdateFeatureEditorHeight() { if (appFeatureEditorStack == nullptr) { return; } QWidget* p_CurrentPage = appFeatureEditorStack->currentWidget(); if (p_CurrentPage == nullptr) { return; } const int AvailableWidth = qMax( p_CurrentPage->contentsRect().width(), appFeatureEditorStack->contentsRect().width()); int Height = p_CurrentPage->minimumSizeHint().height(); if (QLayout* p_Layout = p_CurrentPage->layout()) { if ((AvailableWidth > 0) && p_Layout->hasHeightForWidth()) { Height = qMax(Height, p_Layout->totalHeightForWidth(AvailableWidth)); } Height = qMax(Height, p_Layout->sizeHint().height()); } else { if ((AvailableWidth > 0) && p_CurrentPage->hasHeightForWidth()) { Height = qMax(Height, p_CurrentPage->heightForWidth(AvailableWidth)); } Height = qMax(Height, p_CurrentPage->sizeHint().height()); } if (appFeatureEditorStack->height() != Height) { appFeatureEditorStack->setFixedHeight(Height); } } void App_UIWindow::App_Func_UpdateFeatureEditorState() { const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, 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); if (appFeatureDeleteButton != nullptr) { 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("当前还没有功能,请点击“添加功能”。")); 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("例如:Ctrl+C -> Ctrl+A") : QStringLiteral("例如:Ctrl+C")); App_Func_UpdateFeatureEditorHeight(); appFeatureBindingSummaryLabel->setText(App_Func_GetFeatureBindingSummary(Feature.Id)); appIsUpdatingFeatureUi = false; App_Func_UpdateSequenceRecordingUi(); } void App_UIWindow::App_Func_AddFeature() { const int FeatureId = Lgc_FunctionButton_AddFeature(&appLgcState.FunctionButtonConfig); App_Func_RefreshFeatureTable(); App_Func_SelectFeature(FeatureId, true); App_Func_RefreshUi(); } void App_UIWindow::App_Func_DeleteFeature() { if (appSelectedFeatureId <= 0) { return; } if (appIsSequenceRecording) { App_Func_StopSequenceRecording(); } const QString FeatureName = App_Func_GetFeatureNameById(appSelectedFeatureId); Lgc_FunctionButton_RemoveFeature(&appLgcState.FunctionButtonConfig, appSelectedFeatureId); appSelectedFeatureId = 0; Lgc_Core_ApplyFunctionConfig(&appLgcState); appLgcState.TextFunctionStatus = QStringLiteral("已删除功能:%1").arg(FeatureName); App_Func_RefreshFeatureTable(); App_Func_RefreshUi(); } void App_UIWindow::App_Func_AssignFeatureToUsage(quint16 Usage, int FeatureId) { if (FeatureId > 0 && !appLgcState.FunctionButtonConfig.FeatureMap.contains(FeatureId)) { return; } Lgc_FunctionButton_SetUsageFeatureId(&appLgcState.FunctionButtonConfig, Usage, FeatureId); Lgc_Core_ApplyFunctionConfig(&appLgcState); appLgcState.TextFunctionStatus = FeatureId > 0 ? QStringLiteral("已将按键 %1 绑定到 %2。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage), App_Func_GetFeatureNameById(FeatureId)) : QStringLiteral("已清除按键 %1 的功能绑定。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage)); App_Func_RefreshFeatureTable(); App_Func_RefreshUi(); } QString App_UIWindow::App_Func_GetKeyHintText(const QString& KeyId) const { const quint16 Usage = appKeypadModel.App_Func_GetUsageFromKeyId(KeyId); const int FeatureId = Lgc_FunctionButton_GetUsageFeatureId(appLgcState.FunctionButtonConfig, Usage); return FeatureId > 0 ? App_Func_GetFeatureNameById(FeatureId) : appKeypadModel.App_Func_GetDefaultHint(KeyId); } QString App_UIWindow::App_Func_GetFeatureNameById(int FeatureId) const { const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, FeatureId); return Feature.Id > 0 ? Lgc_FunctionButton_GetFeatureName(Feature) : QStringLiteral("无功能"); } QString App_UIWindow::App_Func_GetFeatureDescriptionById(int FeatureId) const { const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, FeatureId); if (Feature.Id <= 0) { return QStringLiteral("未绑定功能。"); } if (!Feature.Description.trimmed().isEmpty()) { return Feature.Description.trimmed(); } switch (Feature.Type) { case Lgc_FunctionFeature_Type::KeyCombination: return Feature.SequenceText.trimmed().isEmpty() ? QStringLiteral("输出一次快捷键,当前还没有配置快捷键。") : QStringLiteral("输出快捷键:%1").arg(Feature.SequenceText.trimmed()); case Lgc_FunctionFeature_Type::KeySequence: return Feature.SequenceText.trimmed().isEmpty() ? QStringLiteral("按顺序输出多组快捷键,当前还没有配置序列。") : QStringLiteral("输出快捷键序列:%1").arg(Feature.SequenceText.trimmed()); case Lgc_FunctionFeature_Type::Website: return Feature.WebsiteUrl.trimmed().isEmpty() ? QStringLiteral("打开网址,当前还没有配置链接。") : QStringLiteral("打开网址:%1").arg(Feature.WebsiteUrl.trimmed()); default: return QStringLiteral("未知功能。"); } } QString App_UIWindow::App_Func_GetFeatureDescriptionForUsage(quint16 Usage) const { const int FeatureId = Lgc_FunctionButton_GetUsageFeatureId(appLgcState.FunctionButtonConfig, Usage); return FeatureId > 0 ? App_Func_GetFeatureDescriptionById(FeatureId) : App_Func_GetDefaultKeyDescription(Usage); } QString App_UIWindow::App_Func_GetDefaultKeyDescription(quint16 Usage) const { return QStringLiteral("默认小键盘按键:%1。左键模拟真实按下,右键可以绑定功能。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage)); } QString App_UIWindow::App_Func_GetFeatureBindingSummary(int FeatureId) const { if (FeatureId <= 0) { return QStringLiteral("当前未绑定任何按键。"); } QStringList KeyList; for (quint16 Usage : Lgc_FunctionButton_GetConfigurableUsages()) { if (Lgc_FunctionButton_GetUsageFeatureId(appLgcState.FunctionButtonConfig, Usage) == FeatureId) { KeyList.append(Lgc_FunctionButton_GetUsageShortText(Usage)); } } return KeyList.isEmpty() ? QStringLiteral("当前未绑定任何按键。") : QStringLiteral("当前绑定按键:%1").arg(KeyList.join(QStringLiteral(", "))); } void App_UIWindow::App_Func_OnPollTimer() { if (Lgc_Core_Poll(&appLgcState)) { App_Func_RefreshAfterLogicChange(); } } #if APP_ENABLE_DEBUG_WINDOW void App_UIWindow::App_Func_RefreshDeviceConfigFromState() { appDebugPanel->Debug_Func_SetDeviceConfigText( appLgcState.DeviceConfig.VendorId, appLgcState.DeviceConfig.ProductId); appDebugPanel->Debug_Func_SetConfigStatusText( App_Func_GetDebugConfigStatusText(appLgcState), App_Func_HasDebugSendRoute(appLgcState)); } void App_UIWindow::App_Func_OnApplyDeviceConfigClicked() { quint16 VendorId = 0; quint16 ProductId = 0; if (!appDebugPanel->Debug_Func_TryGetDeviceConfig(&VendorId, &ProductId)) { appDebugPanel->Debug_Func_SetConfigStatusText( QStringLiteral("VID / PID 输入无效。请使用十六进制。"), false); return; } appLgcState.DeviceConfig.VendorId = VendorId; appLgcState.DeviceConfig.ProductId = ProductId; App_Func_OnRefreshDeviceClicked(); } void App_UIWindow::App_Func_OnRefreshDeviceClicked() { Lgc_Core_RefreshDevice(&appLgcState); App_Func_RefreshDeviceConfigFromState(); App_Func_RefreshAfterLogicChange(); } void App_UIWindow::App_Func_OnClearLogClicked() { Lgc_Core_ClearLog(&appLgcState); App_Func_RefreshDebugView(); } void App_UIWindow::App_Func_OnSyncTimeClicked() { Lgc_Core_SendTimeSync(&appLgcState); App_Func_RefreshAfterLogicChange(); } void App_UIWindow::App_Func_OnModeSwitchClicked() { Lgc_Core_SendThemeSwitch(&appLgcState); App_Func_RefreshAfterLogicChange(); } #endif } // namespace APP