添加项目文件。
This commit is contained in:
622
APP/APP_UIWindow.cpp
Normal file
622
APP/APP_UIWindow.cpp
Normal file
@@ -0,0 +1,622 @@
|
||||
#include "APP/APP_UIWindow.h"
|
||||
|
||||
#include "APP/APP_GlassCard.h"
|
||||
#include "APP/APP_KeyButton.h"
|
||||
#include "APP/APP_Theme.h"
|
||||
#include "LOGIC/Lgc_Func_Button.h"
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtWidgets/QButtonGroup>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QTabBar>
|
||||
#include <QtWidgets/QTabWidget>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace APP {
|
||||
|
||||
namespace {
|
||||
|
||||
class App_TabBar : public QTabBar
|
||||
{
|
||||
public:
|
||||
explicit App_TabBar(QWidget* parent = nullptr)
|
||||
: QTabBar(parent)
|
||||
{
|
||||
setDrawBase(false);
|
||||
setExpanding(true);
|
||||
setUsesScrollButtons(false);
|
||||
setElideMode(Qt::ElideNone);
|
||||
setMouseTracking(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
}
|
||||
|
||||
protected:
|
||||
QSize tabSizeHint(int index) const override
|
||||
{
|
||||
QSize Size = QTabBar::tabSizeHint(index);
|
||||
Size.rheight() = qMax(Size.height(), 38);
|
||||
Size.rwidth() += 18;
|
||||
return Size;
|
||||
}
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event) override
|
||||
{
|
||||
const int HoverIndex = tabAt(event->pos());
|
||||
if (appHoverIndex != HoverIndex)
|
||||
{
|
||||
appHoverIndex = HoverIndex;
|
||||
update();
|
||||
}
|
||||
|
||||
QTabBar::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void leaveEvent(QEvent* event) override
|
||||
{
|
||||
appHoverIndex = -1;
|
||||
update();
|
||||
QTabBar::leaveEvent(event);
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent* event) override
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
QPainter Painter(this);
|
||||
Painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
Painter.setFont(APP_Theme::App_Func_GetBodyFont());
|
||||
|
||||
for (int Index = 0; Index < count(); ++Index)
|
||||
{
|
||||
QRect TabRect = tabRect(Index).adjusted(3, 5, -3, 0);
|
||||
const bool IsSelected = (Index == currentIndex());
|
||||
const bool IsHovered = (Index == appHoverIndex);
|
||||
|
||||
QColor FillColor(36, 40, 48);
|
||||
QColor BorderColor(92, 102, 114);
|
||||
QColor TextColor(214, 222, 232);
|
||||
|
||||
if (IsHovered)
|
||||
{
|
||||
FillColor = QColor(48, 54, 64);
|
||||
}
|
||||
|
||||
if (IsSelected)
|
||||
{
|
||||
FillColor = QColor(58, 64, 74);
|
||||
BorderColor = QColor(120, 132, 146);
|
||||
TextColor = QColor(238, 242, 247);
|
||||
}
|
||||
|
||||
Painter.setPen(QPen(BorderColor, 1.0));
|
||||
Painter.setBrush(FillColor);
|
||||
Painter.drawRoundedRect(TabRect, 8.0, 8.0);
|
||||
|
||||
Painter.setPen(TextColor);
|
||||
Painter.drawText(TabRect, Qt::AlignCenter, tabText(Index));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int appHoverIndex = -1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Qt 把 setTabBar() 设成 protected,
|
||||
* 所以这里保留一个最小子类,只负责注入我们自绘的页签栏。
|
||||
* 这层不是业务封装,而是 Qt API 访问限制带来的必要适配。
|
||||
*/
|
||||
class App_PageTabWidget : public QTabWidget
|
||||
{
|
||||
public:
|
||||
explicit App_PageTabWidget(QWidget* parent = nullptr)
|
||||
: QTabWidget(parent)
|
||||
{
|
||||
setTabBar(new App_TabBar(this));
|
||||
setDocumentMode(true);
|
||||
tabBar()->setExpanding(true);
|
||||
}
|
||||
};
|
||||
|
||||
QLabel* App_Func_CreateLabel(QWidget* parent, const QString& text, const QFont& font, bool wordWrap = false)
|
||||
{
|
||||
QLabel* label = new QLabel(text, parent);
|
||||
label->setFont(font);
|
||||
label->setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
label->setWordWrap(wordWrap);
|
||||
return label;
|
||||
}
|
||||
|
||||
APP_GlassCard* App_Func_CreateCard(QWidget* parent, QVBoxLayout** pp_Layout)
|
||||
{
|
||||
APP_GlassCard* card = new APP_GlassCard(parent);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(card);
|
||||
layout->setContentsMargins(20, 20, 20, 20);
|
||||
layout->setSpacing(14);
|
||||
*pp_Layout = layout;
|
||||
return card;
|
||||
}
|
||||
|
||||
void App_Func_SetGridStretch(QGridLayout* grid, int columnCount, int rowCount)
|
||||
{
|
||||
for (int column = 0; column < columnCount; ++column)
|
||||
{
|
||||
grid->setColumnStretch(column, 1);
|
||||
}
|
||||
for (int row = 0; row < rowCount; ++row)
|
||||
{
|
||||
grid->setRowStretch(row, 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
App_UIWindow::App_UIWindow(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
App_Func_InitWindow();
|
||||
App_Func_InitUi();
|
||||
App_Func_InitConnect();
|
||||
App_Func_InitLogic();
|
||||
App_Func_RefreshUi();
|
||||
}
|
||||
|
||||
App_UIWindow::~App_UIWindow()
|
||||
{
|
||||
Lgc_Core_Func_Close(&appLgcState);
|
||||
}
|
||||
|
||||
void App_UIWindow::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
QPainter Painter(this);
|
||||
Painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
Painter.fillRect(rect(), palette().color(QPalette::Window));
|
||||
}
|
||||
|
||||
bool App_UIWindow::nativeEvent(const QByteArray& EventType, void* p_Message, long* p_Result)
|
||||
{
|
||||
/*
|
||||
* Windows 原生消息不在 APP 层解析。
|
||||
* APP 只做一件事:把消息往下转给 LGC / DRI。
|
||||
*/
|
||||
Lgc_Core_Func_HandleNativeMessage(&appLgcState, p_Message);
|
||||
return QWidget::nativeEvent(EventType, p_Message, p_Result);
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_InitWindow()
|
||||
{
|
||||
setWindowTitle(QStringLiteral("数字键盘上位机"));
|
||||
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
setMinimumSize(640, 960);
|
||||
resize(700, 1020);
|
||||
#else
|
||||
setMinimumSize(620, 760);
|
||||
resize(680, 820);
|
||||
#endif
|
||||
|
||||
setAttribute(Qt::WA_StyledBackground, true);
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_InitUi()
|
||||
{
|
||||
QVBoxLayout* p_RootLayout = new QVBoxLayout(this);
|
||||
p_RootLayout->setContentsMargins(26, 22, 26, 24);
|
||||
p_RootLayout->setSpacing(14);
|
||||
|
||||
/*
|
||||
* 页面切换直接用 QTabWidget。
|
||||
* 这比自己维护一套切页按钮更短,也更适合教学。
|
||||
*/
|
||||
App_PageTabWidget* p_PageTab = new App_PageTabWidget(this);
|
||||
|
||||
p_PageTab->addTab(App_Func_CreatePadCard(), QStringLiteral("小键盘"));
|
||||
p_PageTab->addTab(App_Func_CreateFunctionRegisterCard(), QStringLiteral("功能注册"));
|
||||
p_PageTab->addTab(App_Func_CreateFunctionConfigCard(), QStringLiteral("功能配置"));
|
||||
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
p_PageTab->addTab(App_Func_CreateDebugCard(), QStringLiteral("调试"));
|
||||
#endif
|
||||
|
||||
p_RootLayout->addWidget(p_PageTab, 1);
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_InitConnect()
|
||||
{
|
||||
/*
|
||||
* 这份教学版刻意把所有 connect 放在同一个函数里,
|
||||
* 让学生顺着“谁发信号 -> 谁收信号”一眼就能看完。
|
||||
*/
|
||||
connect(&appTimerPoll, &QTimer::timeout, this, &App_UIWindow::App_Func_OnPollTimer);
|
||||
|
||||
/*
|
||||
* 这些控件都在 InitUi 阶段固定创建完成,
|
||||
* 所以这里直接 connect,不再加“防御性空指针判断”干扰阅读。
|
||||
*/
|
||||
const auto ConnectConfigSignal = [this](auto Sender, auto Signal)
|
||||
{
|
||||
connect(Sender, Signal, this, [this]()
|
||||
{
|
||||
App_Func_UpdateFunctionConfigFromUi();
|
||||
});
|
||||
};
|
||||
|
||||
ConnectConfigSignal(appFunctionEditMacroText, &QLineEdit::textChanged);
|
||||
ConnectConfigSignal(appFunctionEditWebsite, &QLineEdit::textChanged);
|
||||
ConnectConfigSignal(appFunctionComboSwapLeft, qOverload<int>(&QComboBox::currentIndexChanged));
|
||||
ConnectConfigSignal(appFunctionComboSwapRight, qOverload<int>(&QComboBox::currentIndexChanged));
|
||||
|
||||
/*
|
||||
* 功能键按钮统一交给 QButtonGroup 管,
|
||||
* 这样既能减少每颗按钮各写一段 lambda,
|
||||
* 也正好把 Qt 里“按钮分组 + id 分发”的知识点展示出来。
|
||||
*/
|
||||
connect(appFunctionButtonGroup, qOverload<int>(&QButtonGroup::buttonClicked), this, [this](int ButtonId)
|
||||
{
|
||||
App_Func_OnFunctionKeyClicked(static_cast<quint16>(ButtonId));
|
||||
});
|
||||
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
connect(appDebugPanel->Debug_Func_GetRefreshButton(), &QPushButton::clicked,
|
||||
this, &App_UIWindow::App_Func_OnRefreshDeviceClicked);
|
||||
|
||||
connect(appDebugPanel->Debug_Func_GetClearButton(), &QPushButton::clicked,
|
||||
this, &App_UIWindow::App_Func_OnClearLogClicked);
|
||||
|
||||
connect(appDebugPanel->Debug_Func_GetApplyConfigButton(), &QPushButton::clicked,
|
||||
this, &App_UIWindow::App_Func_OnApplyDeviceConfigClicked);
|
||||
#endif
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_InitLogic()
|
||||
{
|
||||
Lgc_Core_Func_Init(&appLgcState);
|
||||
Lgc_Core_Func_SetWindowHandle(&appLgcState, reinterpret_cast<void*>(winId()));
|
||||
|
||||
App_Func_UpdateFunctionConfigFromUi();
|
||||
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
App_Func_RefreshDeviceConfigFromState();
|
||||
#endif
|
||||
|
||||
Lgc_Core_Func_Start(&appLgcState);
|
||||
|
||||
/*
|
||||
* 轮询不仅服务调试窗口,
|
||||
* 小键盘状态页和功能键页本身也要靠它持续拿最新状态。
|
||||
* 所以这里始终启动,不跟调试开关绑定。
|
||||
*/
|
||||
appTimerPoll.setInterval(30);
|
||||
appTimerPoll.start();
|
||||
|
||||
App_Func_RefreshAfterLogicChange();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshUi()
|
||||
{
|
||||
App_Func_RefreshKeypadButtons();
|
||||
App_Func_RefreshFunctionButtons();
|
||||
App_Func_RefreshFunctionStatus();
|
||||
update();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshKeypadState()
|
||||
{
|
||||
appKeypadModel.App_Func_SetNumLockOn(appLgcState.IsSystemNumLockOn);
|
||||
appKeypadModel.App_Func_SetSwapUsagePair(
|
||||
appLgcState.SwapUsageLeft,
|
||||
appLgcState.SwapUsageRight,
|
||||
appLgcState.IsSwapModeOn);
|
||||
|
||||
const QVector<quint16>* p_UsageList = nullptr;
|
||||
if (appLgcState.IsPhysicalKeyStateValid)
|
||||
{
|
||||
p_UsageList = &appLgcState.PhysicalUsageList;
|
||||
}
|
||||
else if (appLgcState.IsVisibleKeyStateValid)
|
||||
{
|
||||
p_UsageList = &appLgcState.VisibleUsageList;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
APP_KeyButton* p_Button = It.value();
|
||||
p_Button->App_Func_SetLatched(appKeypadModel.App_Func_IsLatched(It.key()));
|
||||
p_Button->App_Func_SetPressed(appKeypadModel.App_Func_IsPressed(It.key()));
|
||||
}
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshFunctionButtons()
|
||||
{
|
||||
for (auto It = appFunctionButtonMap.begin(); It != appFunctionButtonMap.end(); ++It)
|
||||
{
|
||||
const QString KeyId = It.key();
|
||||
APP_KeyButton* p_Button = It.value();
|
||||
const quint16 Usage = appKeypadModel.App_Func_GetUsageFromKeyId(KeyId);
|
||||
const bool IsFunctionMode = Lgc_Core_Func_IsUsageFunctionMode(&appLgcState, Usage);
|
||||
|
||||
p_Button->App_Func_SetLatched(IsFunctionMode);
|
||||
p_Button->App_Func_SetPressed(appKeypadModel.App_Func_IsPressed(KeyId));
|
||||
}
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshFunctionStatus()
|
||||
{
|
||||
appFunctionLabelStatus->setText(appLgcState.TextFunctionStatus.isEmpty()
|
||||
? QStringLiteral("等待功能键动作。")
|
||||
: appLgcState.TextFunctionStatus);
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshDebugView()
|
||||
{
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
appDebugPanel->Debug_Func_SetConnectionText(appLgcState.TextConnection, appLgcState.IsConnected);
|
||||
appDebugPanel->Debug_Func_SetLogText(appLgcState.TextLog);
|
||||
#endif
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_RefreshAfterLogicChange()
|
||||
{
|
||||
/*
|
||||
* 逻辑层状态一旦变化,界面层真正需要做的事情其实只有这三步:
|
||||
* 1. 先把 LGC 状态同步到 APP 自己的显示模型
|
||||
* 2. 再把调试文本同步到调试页
|
||||
* 3. 最后统一刷新界面控件
|
||||
*/
|
||||
App_Func_RefreshKeypadState();
|
||||
App_Func_RefreshDebugView();
|
||||
App_Func_RefreshUi();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_UpdateFunctionConfigFromUi()
|
||||
{
|
||||
const quint16 OldSwapUsageLeft = appLgcState.FunctionButtonConfig.SwapUsageLeft;
|
||||
const quint16 OldSwapUsageRight = appLgcState.FunctionButtonConfig.SwapUsageRight;
|
||||
|
||||
appLgcState.FunctionButtonConfig.MacroText = appFunctionEditMacroText->text();
|
||||
appLgcState.FunctionButtonConfig.WebsiteUrl = appFunctionEditWebsite->text();
|
||||
appLgcState.FunctionButtonConfig.SwapUsageLeft =
|
||||
static_cast<quint16>(appFunctionComboSwapLeft->currentData().toUInt());
|
||||
appLgcState.FunctionButtonConfig.SwapUsageRight =
|
||||
static_cast<quint16>(appFunctionComboSwapRight->currentData().toUInt());
|
||||
|
||||
if (appLgcState.IsSwapModeOn &&
|
||||
((OldSwapUsageLeft != appLgcState.FunctionButtonConfig.SwapUsageLeft) ||
|
||||
(OldSwapUsageRight != appLgcState.FunctionButtonConfig.SwapUsageRight)))
|
||||
{
|
||||
Lgc_Core_Func_SetSwapMode(
|
||||
&appLgcState,
|
||||
appLgcState.FunctionButtonConfig.SwapUsageLeft,
|
||||
appLgcState.FunctionButtonConfig.SwapUsageRight,
|
||||
true);
|
||||
App_Func_RefreshAfterLogicChange();
|
||||
}
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_OnFunctionKeyClicked(quint16 Usage)
|
||||
{
|
||||
const bool IsFunctionMode = Lgc_Core_Func_IsUsageFunctionMode(&appLgcState, Usage);
|
||||
Lgc_Core_Func_SetUsageFunctionMode(&appLgcState, Usage, !IsFunctionMode);
|
||||
App_Func_RefreshAfterLogicChange();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_OnPollTimer()
|
||||
{
|
||||
if (Lgc_Core_Func_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(
|
||||
QStringLiteral("当前目标 VID:PID = 0x%1:0x%2")
|
||||
.arg(appLgcState.DeviceConfig.VendorId, 4, 16, QLatin1Char('0'))
|
||||
.arg(appLgcState.DeviceConfig.ProductId, 4, 16, QLatin1Char('0'))
|
||||
.toUpper(),
|
||||
true);
|
||||
}
|
||||
|
||||
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 输入无效,请输入十六进制,例如 1209 和 0001。"),
|
||||
false);
|
||||
return;
|
||||
}
|
||||
|
||||
appLgcState.DeviceConfig.VendorId = VendorId;
|
||||
appLgcState.DeviceConfig.ProductId = ProductId;
|
||||
App_Func_OnRefreshDeviceClicked();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_OnRefreshDeviceClicked()
|
||||
{
|
||||
Lgc_Core_Func_RefreshDevice(&appLgcState);
|
||||
App_Func_RefreshDeviceConfigFromState();
|
||||
App_Func_RefreshAfterLogicChange();
|
||||
}
|
||||
|
||||
void App_UIWindow::App_Func_OnClearLogClicked()
|
||||
{
|
||||
Lgc_Core_Func_ClearLog(&appLgcState);
|
||||
App_Func_RefreshDebugView();
|
||||
}
|
||||
#endif
|
||||
|
||||
QWidget* App_UIWindow::App_Func_CreatePadCard()
|
||||
{
|
||||
QVBoxLayout* p_Layout = nullptr;
|
||||
APP_GlassCard* p_Card = App_Func_CreateCard(this, &p_Layout);
|
||||
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("小键盘状态页"),
|
||||
APP_Theme::App_Func_GetMetricFont()));
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("这一页直接显示实体小键盘当前的按下状态,NumLock 也会同步点亮。"),
|
||||
APP_Theme::App_Func_GetBodyFont(), true));
|
||||
|
||||
QGridLayout* p_Grid = new QGridLayout();
|
||||
p_Grid->setSpacing(14);
|
||||
|
||||
const QVector<APP_KeyInfo>& KeyList = appKeypadModel.App_Func_GetKeyList();
|
||||
|
||||
for (const APP_KeyInfo& Key : KeyList)
|
||||
{
|
||||
APP_KeyButton* p_Button = new APP_KeyButton(Key, p_Card);
|
||||
appKeypadButtonMap.insert(Key.id, p_Button);
|
||||
p_Grid->addWidget(p_Button, Key.row, Key.column, Key.rowSpan, Key.columnSpan);
|
||||
}
|
||||
|
||||
App_Func_SetGridStretch(p_Grid, 4, 5);
|
||||
|
||||
p_Layout->addLayout(p_Grid, 1);
|
||||
return p_Card;
|
||||
}
|
||||
|
||||
QWidget* App_UIWindow::App_Func_CreateFunctionRegisterCard()
|
||||
{
|
||||
QVBoxLayout* p_Layout = nullptr;
|
||||
APP_GlassCard* p_Card = App_Func_CreateCard(this, &p_Layout);
|
||||
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("功能注册"),
|
||||
APP_Theme::App_Func_GetMetricFont()));
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("这一页只负责决定哪些小键盘键切到功能键模式。按钮点亮表示该键已经注册为功能键;再次点击即可取消。"),
|
||||
APP_Theme::App_Func_GetBodyFont(), true));
|
||||
|
||||
QGridLayout* p_Grid = new QGridLayout();
|
||||
p_Grid->setSpacing(14);
|
||||
|
||||
const QVector<APP_KeyInfo>& KeyList = appKeypadModel.App_Func_GetFunctionKeyList();
|
||||
appFunctionButtonGroup = new QButtonGroup(this);
|
||||
|
||||
for (const APP_KeyInfo& Key : KeyList)
|
||||
{
|
||||
APP_KeyButton* p_Button = new APP_KeyButton(Key, p_Card);
|
||||
appFunctionButtonMap.insert(Key.id, p_Button);
|
||||
appFunctionButtonGroup->addButton(p_Button, static_cast<int>(Key.usage));
|
||||
p_Grid->addWidget(p_Button, Key.row, Key.column, Key.rowSpan, Key.columnSpan);
|
||||
}
|
||||
|
||||
App_Func_SetGridStretch(p_Grid, 4, 4);
|
||||
p_Layout->addLayout(p_Grid, 1);
|
||||
return p_Card;
|
||||
}
|
||||
|
||||
QWidget* App_UIWindow::App_Func_CreateFunctionConfigCard()
|
||||
{
|
||||
QVBoxLayout* p_Layout = nullptr;
|
||||
APP_GlassCard* p_Card = App_Func_CreateCard(this, &p_Layout);
|
||||
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("功能配置"),
|
||||
APP_Theme::App_Func_GetMetricFont()));
|
||||
p_Layout->addWidget(App_Func_CreateLabel(p_Card, QStringLiteral("这一页只放功能案例参数。当前教学版保留 0=文本输入、1=按键交换、2=打开网址,学生能更清楚看到“注册”和“配置”是两件事。"),
|
||||
APP_Theme::App_Func_GetBodyFont(), true));
|
||||
|
||||
QFormLayout* p_ConfigLayout = new QFormLayout();
|
||||
p_ConfigLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||
p_ConfigLayout->setLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
p_ConfigLayout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
p_ConfigLayout->setHorizontalSpacing(10);
|
||||
p_ConfigLayout->setVerticalSpacing(10);
|
||||
const auto AddConfigRow = [p_Card, p_ConfigLayout](const QString& text, QWidget* field)
|
||||
{
|
||||
p_ConfigLayout->addRow(
|
||||
App_Func_CreateLabel(p_Card, text, APP_Theme::App_Func_GetBodyFont()),
|
||||
field);
|
||||
};
|
||||
|
||||
appFunctionEditMacroText = new QLineEdit(p_Card);
|
||||
appFunctionEditMacroText->setText(QStringLiteral("HELLO WORLD!"));
|
||||
appFunctionEditMacroText->setPlaceholderText(QStringLiteral("例如:HELLO WORLD!"));
|
||||
AddConfigRow(QStringLiteral("功能键 0 文本"), appFunctionEditMacroText);
|
||||
|
||||
appFunctionComboSwapLeft = new QComboBox(p_Card);
|
||||
appFunctionComboSwapRight = new QComboBox(p_Card);
|
||||
|
||||
const QVector<APP_KeyInfo>& FunctionKeyList = appKeypadModel.App_Func_GetFunctionKeyList();
|
||||
for (const APP_KeyInfo& Key : FunctionKeyList)
|
||||
{
|
||||
appFunctionComboSwapLeft->addItem(Key.label, static_cast<uint>(Key.usage));
|
||||
appFunctionComboSwapRight->addItem(Key.label, static_cast<uint>(Key.usage));
|
||||
}
|
||||
|
||||
const auto SetComboIndex = [](QComboBox* Combo, quint16 Usage)
|
||||
{
|
||||
const int Index = Combo->findData(static_cast<uint>(Usage));
|
||||
if (Index >= 0)
|
||||
{
|
||||
Combo->setCurrentIndex(Index);
|
||||
}
|
||||
};
|
||||
|
||||
SetComboIndex(appFunctionComboSwapLeft, 0x005C);
|
||||
SetComboIndex(appFunctionComboSwapRight, 0x005D);
|
||||
|
||||
QWidget* p_SwapEditor = new QWidget(p_Card);
|
||||
QHBoxLayout* p_SwapLayout = new QHBoxLayout(p_SwapEditor);
|
||||
p_SwapLayout->setContentsMargins(0, 0, 0, 0);
|
||||
p_SwapLayout->setSpacing(8);
|
||||
p_SwapLayout->addWidget(appFunctionComboSwapLeft);
|
||||
p_SwapLayout->addWidget(App_Func_CreateLabel(p_SwapEditor, QStringLiteral("<->"),
|
||||
APP_Theme::App_Func_GetBodyFont()));
|
||||
p_SwapLayout->addWidget(appFunctionComboSwapRight);
|
||||
p_SwapLayout->addStretch(1);
|
||||
AddConfigRow(QStringLiteral("功能键 1 交换"), p_SwapEditor);
|
||||
|
||||
appFunctionEditWebsite = new QLineEdit(p_Card);
|
||||
appFunctionEditWebsite->setText(QStringLiteral("https://www.deepseek.com/"));
|
||||
appFunctionEditWebsite->setPlaceholderText(QStringLiteral("例如:https://www.deepseek.com/"));
|
||||
AddConfigRow(QStringLiteral("功能键 2 网址"), appFunctionEditWebsite);
|
||||
|
||||
appFunctionLabelStatus = App_Func_CreateLabel(
|
||||
p_Card, QStringLiteral("等待功能键动作。"),
|
||||
APP_Theme::App_Func_GetBodyFont(), true);
|
||||
AddConfigRow(QStringLiteral("最近一次动作"), appFunctionLabelStatus);
|
||||
|
||||
p_Layout->addLayout(p_ConfigLayout);
|
||||
p_Layout->addStretch(1);
|
||||
return p_Card;
|
||||
}
|
||||
|
||||
#if APP_ENABLE_DEBUG_WINDOW
|
||||
QWidget* App_UIWindow::App_Func_CreateDebugCard()
|
||||
{
|
||||
appDebugPanel = new DEBUG::Debug_Panel(this);
|
||||
appDebugPanel->Debug_Func_SetConnectionText(QStringLiteral("未连接,等待枚举设备。"), false);
|
||||
appDebugPanel->Debug_Func_SetLogText(QStringLiteral("等待收到输入包。"));
|
||||
return appDebugPanel;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace APP
|
||||
Reference in New Issue
Block a user