first push

This commit is contained in:
2026-04-03 09:26:10 +08:00
parent 2937a44e07
commit 025b88e366
41 changed files with 6842 additions and 0 deletions

View File

@@ -0,0 +1,519 @@
#include "APP/APP_UIWindow.h"
#include "APP/APP_KeyButton.h"
#include "APP/APP_UIWindow_Private.h"
#include "DEBUG/Debug_Panel.h"
#include <QtCore/QSignalBlocker>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStackedWidget>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QTableWidgetItem>
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<quint16>* 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<int> 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<Lgc_FunctionFeature_Type>(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<int>(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