Remove premature non-DRI layers

This commit is contained in:
2026-04-11 10:04:03 +08:00
parent a8b3eb5797
commit 47a2afa3a0
26 changed files with 9 additions and 1435 deletions

View File

@@ -1,100 +0,0 @@
#include "APP/AppKeyButton.h"
#include "APP/AppTheme.h"
namespace APP
{
App_KeyButton::App_KeyButton(quint16 Usage, const QString& Text, QWidget* p_Parent)
: QPushButton(Text, p_Parent),
appUsage(Usage),
appBaseText(Text)
{
setMinimumSize(88, 72);
setCheckable(false);
App_Func_RefreshText();
App_Func_RefreshStyle();
}
quint16 App_KeyButton::App_Func_GetUsage() const
{
return appUsage;
}
void App_KeyButton::App_Func_SetPressedState(bool IsPressed)
{
if (appIsPressed == IsPressed)
{
return;
}
appIsPressed = IsPressed;
App_Func_RefreshStyle();
}
void App_KeyButton::App_Func_SetLatchedState(bool IsLatched)
{
if (appIsLatched == IsLatched)
{
return;
}
appIsLatched = IsLatched;
App_Func_RefreshStyle();
}
void App_KeyButton::App_Func_SetFeatureText(const QString& Text)
{
if (appFeatureText == Text.trimmed())
{
return;
}
appFeatureText = Text.trimmed();
App_Func_RefreshText();
}
void App_KeyButton::App_Func_RefreshText()
{
if (appFeatureText.isEmpty())
{
setText(appBaseText);
return;
}
setText(QStringLiteral("%1\n%2").arg(appBaseText, appFeatureText));
}
void App_KeyButton::App_Func_RefreshStyle()
{
const App_ThemePalette Palette = App_Theme_DefaultPalette();
const QColor FillColor = appIsPressed
? Palette.Accent
: (appIsLatched ? Palette.AccentSoft : Palette.Surface);
const QColor TextColor = appIsPressed
? QColor(15, 23, 42)
: Palette.TextPrimary;
setStyleSheet(QStringLiteral(
"QPushButton {"
" background:rgb(%1,%2,%3);"
" color:rgb(%4,%5,%6);"
" border:1px solid rgb(%7,%8,%9);"
" border-radius:12px;"
" font-size:16px;"
" font-weight:600;"
" padding:8px;"
"}"
)
.arg(FillColor.red())
.arg(FillColor.green())
.arg(FillColor.blue())
.arg(TextColor.red())
.arg(TextColor.green())
.arg(TextColor.blue())
.arg(Palette.Border.red())
.arg(Palette.Border.green())
.arg(Palette.Border.blue()));
}
} // namespace APP

View File

@@ -1,30 +0,0 @@
#pragma once
#include <QtCore/QtGlobal>
#include <QtWidgets/QPushButton>
namespace APP
{
class App_KeyButton : public QPushButton
{
public:
explicit App_KeyButton(quint16 Usage, const QString& Text, QWidget* p_Parent = nullptr);
quint16 App_Func_GetUsage() const;
void App_Func_SetPressedState(bool IsPressed);
void App_Func_SetLatchedState(bool IsLatched);
void App_Func_SetFeatureText(const QString& Text);
private:
void App_Func_RefreshText();
void App_Func_RefreshStyle();
quint16 appUsage = 0;
bool appIsPressed = false;
bool appIsLatched = false;
QString appBaseText;
QString appFeatureText;
};
} // namespace APP

View File

@@ -1,133 +0,0 @@
#include "APP/AppKeyboardPage.h"
#include "APP/AppKeyButton.h"
#include "APP/AppTheme.h"
#include <QtWidgets/QFrame>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QVBoxLayout>
namespace APP
{
namespace
{
struct App_KeySpec
{
quint16 Usage;
const char* Text;
int Row;
int Column;
int RowSpan;
int ColumnSpan;
};
const App_KeySpec kKeySpecList[] = {
{ 0x0053, "Num", 0, 0, 1, 1 },
{ 0x0054, "/", 0, 1, 1, 1 },
{ 0x0055, "*", 0, 2, 1, 1 },
{ 0x0056, "-", 0, 3, 1, 1 },
{ 0x005F, "7", 1, 0, 1, 1 },
{ 0x0060, "8", 1, 1, 1, 1 },
{ 0x0061, "9", 1, 2, 1, 1 },
{ 0x0057, "+", 1, 3, 2, 1 },
{ 0x005C, "4", 2, 0, 1, 1 },
{ 0x005D, "5", 2, 1, 1, 1 },
{ 0x005E, "6", 2, 2, 1, 1 },
{ 0x0059, "1", 3, 0, 1, 1 },
{ 0x005A, "2", 3, 1, 1, 1 },
{ 0x005B, "3", 3, 2, 1, 1 },
{ 0x0058, "Enter", 3, 3, 2, 1 },
{ 0x0062, "0", 4, 0, 1, 2 },
{ 0x0063, ".", 4, 2, 1, 1 },
};
} // namespace
App_KeyboardPage::App_KeyboardPage(QWidget* p_Parent)
: QWidget(p_Parent)
{
App_Func_CreateLayout();
}
void App_KeyboardPage::App_Func_SetPressedUsages(const QVector<quint16>& UsageList)
{
for (auto It = appButtonMap.begin(); It != appButtonMap.end(); ++It)
{
It.value()->App_Func_SetPressedState(UsageList.contains(It.key()));
}
}
void App_KeyboardPage::App_Func_SetLatchedUsage(quint16 Usage, bool IsLatched)
{
App_KeyButton* const p_Button = appButtonMap.value(Usage, nullptr);
if (p_Button != nullptr)
{
p_Button->App_Func_SetLatchedState(IsLatched);
}
}
void App_KeyboardPage::App_Func_SetFeatureLabel(quint16 Usage, const QString& Text)
{
App_KeyButton* const p_Button = appButtonMap.value(Usage, nullptr);
if (p_Button != nullptr)
{
p_Button->App_Func_SetFeatureText(Text);
}
}
void App_KeyboardPage::App_Func_CreateLayout()
{
const App_ThemePalette Palette = App_Theme_DefaultPalette();
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
p_RootLayout->setContentsMargins(0, 0, 0, 0);
p_RootLayout->setSpacing(12);
QFrame* const p_Card = new QFrame(this);
p_Card->setStyleSheet(App_Theme_BuildCardStyleSheet());
p_RootLayout->addWidget(p_Card);
QVBoxLayout* const p_CardLayout = new QVBoxLayout(p_Card);
p_CardLayout->setContentsMargins(20, 20, 20, 20);
p_CardLayout->setSpacing(14);
QLabel* const p_Title = new QLabel(QStringLiteral("Keyboard"), p_Card);
p_Title->setProperty("role", QStringLiteral("title"));
p_CardLayout->addWidget(p_Title);
QLabel* const p_Body = new QLabel(
QStringLiteral("Start from one button, then grow into the whole keypad layout."),
p_Card);
p_Body->setProperty("role", QStringLiteral("body"));
p_Body->setWordWrap(true);
p_CardLayout->addWidget(p_Body);
QGridLayout* const p_GridLayout = new QGridLayout();
p_GridLayout->setSpacing(12);
p_CardLayout->addLayout(p_GridLayout);
for (const App_KeySpec& KeySpec : kKeySpecList)
{
App_KeyButton* const p_Button =
new App_KeyButton(KeySpec.Usage, QString::fromUtf8(KeySpec.Text), p_Card);
p_GridLayout->addWidget(
p_Button,
KeySpec.Row,
KeySpec.Column,
KeySpec.RowSpan,
KeySpec.ColumnSpan);
appButtonMap.insert(KeySpec.Usage, p_Button);
}
for (int Column = 0; Column < 4; ++Column)
{
p_GridLayout->setColumnStretch(Column, 1);
}
Q_UNUSED(Palette);
}
} // namespace APP

View File

@@ -1,27 +0,0 @@
#pragma once
#include <QtCore/QHash>
#include <QtCore/QVector>
#include <QtWidgets/QWidget>
namespace APP
{
class App_KeyButton;
class App_KeyboardPage : public QWidget
{
public:
explicit App_KeyboardPage(QWidget* p_Parent = nullptr);
void App_Func_SetPressedUsages(const QVector<quint16>& UsageList);
void App_Func_SetLatchedUsage(quint16 Usage, bool IsLatched);
void App_Func_SetFeatureLabel(quint16 Usage, const QString& Text);
private:
void App_Func_CreateLayout();
QHash<quint16, App_KeyButton*> appButtonMap;
};
} // namespace APP

View File

@@ -1,71 +0,0 @@
#include "APP/AppMainWindow.h"
#include "APP/AppKeyboardPage.h"
#include "APP/AppSettingsPage.h"
#include "APP/AppTheme.h"
#include <QtWidgets/QTabWidget>
#include <QtCore/QTimer>
#include <QtWidgets/QVBoxLayout>
namespace APP
{
App_MainWindow::App_MainWindow(QWidget* p_Parent)
: QWidget(p_Parent)
{
setWindowTitle(QStringLiteral("KeyBorad"));
resize(860, 760);
setStyleSheet(App_Theme_BuildWindowStyleSheet());
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
p_RootLayout->setContentsMargins(20, 20, 20, 20);
p_RootLayout->setSpacing(12);
appTabWidget = new QTabWidget(this);
appKeyboardPage = new App_KeyboardPage(appTabWidget);
appSettingsPage = new App_SettingsPage(appTabWidget);
appTabWidget->addTab(appKeyboardPage, QStringLiteral("Keyboard"));
appTabWidget->addTab(appSettingsPage, QStringLiteral("Settings"));
p_RootLayout->addWidget(appTabWidget);
appPollTimer = new QTimer(this);
connect(appPollTimer, &QTimer::timeout, this, [this]()
{
if (Lgc_Core_Poll(&appLogic))
{
App_Func_RefreshFromLogic();
}
});
App_Func_StartLogic();
}
void App_MainWindow::App_Func_StartLogic()
{
Lgc_Core_Init(&appLogic);
Lgc_Core_Start(&appLogic);
App_Func_RefreshFromLogic();
appPollTimer->start(30);
}
void App_MainWindow::App_Func_RefreshFromLogic()
{
const Lgc_State& State = Lgc_Core_GetState(&appLogic);
appSettingsPage->App_Func_SetConnectionText(State.ConnectionText);
appSettingsPage->App_Func_SetLastActionText(State.LastActionText);
}
App_KeyboardPage* App_MainWindow::App_Func_GetKeyboardPage() const
{
return appKeyboardPage;
}
App_SettingsPage* App_MainWindow::App_Func_GetSettingsPage() const
{
return appSettingsPage;
}
} // namespace APP

View File

@@ -1,35 +0,0 @@
#pragma once
#include "LOGIC/Lgc_Core.h"
#include <QtWidgets/QWidget>
class QTabWidget;
class QTimer;
namespace APP
{
class App_KeyboardPage;
class App_SettingsPage;
class App_MainWindow : public QWidget
{
public:
explicit App_MainWindow(QWidget* p_Parent = nullptr);
App_KeyboardPage* App_Func_GetKeyboardPage() const;
App_SettingsPage* App_Func_GetSettingsPage() const;
private:
void App_Func_StartLogic();
void App_Func_RefreshFromLogic();
QTabWidget* appTabWidget = nullptr;
App_KeyboardPage* appKeyboardPage = nullptr;
App_SettingsPage* appSettingsPage = nullptr;
QTimer* appPollTimer = nullptr;
Lgc_Core appLogic;
};
} // namespace APP

View File

@@ -1,61 +0,0 @@
#include "APP/AppSettingsPage.h"
#include "APP/AppTheme.h"
#include <QtWidgets/QFrame>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QVBoxLayout>
namespace APP
{
App_SettingsPage::App_SettingsPage(QWidget* p_Parent)
: QWidget(p_Parent)
{
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
p_RootLayout->setContentsMargins(0, 0, 0, 0);
p_RootLayout->setSpacing(12);
QFrame* const p_Card = new QFrame(this);
p_Card->setStyleSheet(App_Theme_BuildCardStyleSheet());
p_RootLayout->addWidget(p_Card);
QVBoxLayout* const p_CardLayout = new QVBoxLayout(p_Card);
p_CardLayout->setContentsMargins(20, 20, 20, 20);
p_CardLayout->setSpacing(14);
QLabel* const p_Title = new QLabel(QStringLiteral("Settings"), p_Card);
p_Title->setProperty("role", QStringLiteral("title"));
p_CardLayout->addWidget(p_Title);
QLabel* const p_Body = new QLabel(
QStringLiteral("Use this page to present transport status and the latest function result."),
p_Card);
p_Body->setProperty("role", QStringLiteral("body"));
p_Body->setWordWrap(true);
p_CardLayout->addWidget(p_Body);
QFormLayout* const p_FormLayout = new QFormLayout();
p_FormLayout->setHorizontalSpacing(12);
p_FormLayout->setVerticalSpacing(12);
p_CardLayout->addLayout(p_FormLayout);
appConnectionLabel = new QLabel(QStringLiteral("Disconnected"), p_Card);
appLastActionLabel = new QLabel(QStringLiteral("Idle"), p_Card);
p_FormLayout->addRow(QStringLiteral("Transport"), appConnectionLabel);
p_FormLayout->addRow(QStringLiteral("Last Action"), appLastActionLabel);
}
void App_SettingsPage::App_Func_SetConnectionText(const QString& Text)
{
appConnectionLabel->setText(Text.trimmed().isEmpty() ? QStringLiteral("Disconnected") : Text.trimmed());
}
void App_SettingsPage::App_Func_SetLastActionText(const QString& Text)
{
appLastActionLabel->setText(Text.trimmed().isEmpty() ? QStringLiteral("Idle") : Text.trimmed());
}
} // namespace APP

View File

@@ -1,23 +0,0 @@
#pragma once
#include <QtWidgets/QWidget>
class QLabel;
namespace APP
{
class App_SettingsPage : public QWidget
{
public:
explicit App_SettingsPage(QWidget* p_Parent = nullptr);
void App_Func_SetConnectionText(const QString& Text);
void App_Func_SetLastActionText(const QString& Text);
private:
QLabel* appConnectionLabel = nullptr;
QLabel* appLastActionLabel = nullptr;
};
} // namespace APP

View File

@@ -1,86 +0,0 @@
#include "APP/AppTheme.h"
namespace APP
{
namespace
{
QString App_Func_RgbText(const QColor& Color)
{
return QStringLiteral("rgb(%1, %2, %3)")
.arg(Color.red())
.arg(Color.green())
.arg(Color.blue());
}
} // namespace
App_ThemePalette App_Theme_DefaultPalette()
{
return App_ThemePalette();
}
QString App_Theme_BuildWindowStyleSheet()
{
const App_ThemePalette Palette = App_Theme_DefaultPalette();
return QStringLiteral(
"QWidget {"
" background:%1;"
" color:%2;"
"}"
"QTabWidget::pane {"
" border:1px solid %3;"
" border-radius:12px;"
" background:%4;"
"}"
"QTabBar::tab {"
" background:%4;"
" color:%5;"
" padding:10px 16px;"
" margin-right:6px;"
" border:1px solid %3;"
" border-bottom:none;"
" border-top-left-radius:10px;"
" border-top-right-radius:10px;"
"}"
"QTabBar::tab:selected {"
" color:%2;"
" background:%1;"
"}"
)
.arg(App_Func_RgbText(Palette.Window))
.arg(App_Func_RgbText(Palette.TextPrimary))
.arg(App_Func_RgbText(Palette.Border))
.arg(App_Func_RgbText(Palette.Surface))
.arg(App_Func_RgbText(Palette.TextMuted));
}
QString App_Theme_BuildCardStyleSheet()
{
const App_ThemePalette Palette = App_Theme_DefaultPalette();
return QStringLiteral(
"QFrame {"
" background:%1;"
" border:1px solid %2;"
" border-radius:14px;"
"}"
"QLabel[role=\"title\"] {"
" color:%3;"
" font-size:20px;"
" font-weight:600;"
"}"
"QLabel[role=\"body\"] {"
" color:%4;"
" font-size:13px;"
"}"
)
.arg(App_Func_RgbText(Palette.Surface))
.arg(App_Func_RgbText(Palette.Border))
.arg(App_Func_RgbText(Palette.TextPrimary))
.arg(App_Func_RgbText(Palette.TextMuted));
}
} // namespace APP

View File

@@ -1,24 +0,0 @@
#pragma once
#include <QtCore/QString>
#include <QtGui/QColor>
namespace APP
{
struct App_ThemePalette
{
QColor Window = QColor(15, 23, 42);
QColor Surface = QColor(17, 24, 39);
QColor Border = QColor(51, 65, 85);
QColor TextPrimary = QColor(226, 232, 240);
QColor TextMuted = QColor(148, 163, 184);
QColor Accent = QColor(76, 201, 240);
QColor AccentSoft = QColor(34, 197, 94);
};
App_ThemePalette App_Theme_DefaultPalette();
QString App_Theme_BuildWindowStyleSheet();
QString App_Theme_BuildCardStyleSheet();
} // namespace APP

View File

@@ -1,59 +0,0 @@
#include "COM/Com_ProtoCodec.h"
#include "COM/Com_CdcDecode.h"
#include "COM/Com_CdcEncode.h"
namespace
{
quint16 Com_Func_ReadLe16(const QByteArray& ByteArray, int Offset)
{
return static_cast<quint16>(
static_cast<quint8>(ByteArray.at(Offset)) |
(static_cast<quint16>(static_cast<quint8>(ByteArray.at(Offset + 1))) << 8));
}
} // namespace
bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet)
{
return Com_Cdc_Func_ParseFrame(ByteArray, p_Packet);
}
bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet)
{
return Com_Cdc_Func_TryTakeFrame(p_Buffer, p_Packet);
}
QByteArray Com_ProtoCodec_BuildHelloReq()
{
const Packet_HelloReq HelloReq;
return Com_Cdc_Func_BuildHelloReq(HelloReq);
}
bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData)
{
return (PacketData.type == Com_Type_HelloRsp) &&
(PacketData.data.size() == Packet_len::Com_Len_HelloRsp);
}
bool Com_ProtoCodec_ParseHelloRsp(
const Packet& PacketData,
Packet_HelloRsp* p_HelloRsp)
{
if ((p_HelloRsp == nullptr) || !Com_ProtoCodec_IsHelloRsp(PacketData))
{
return false;
}
Packet_HelloRsp HelloRsp;
HelloRsp.ProtocolVersion = static_cast<quint8>(PacketData.data.at(0));
HelloRsp.VendorId = Com_Func_ReadLe16(PacketData.data, 1);
HelloRsp.ProductId = Com_Func_ReadLe16(PacketData.data, 3);
HelloRsp.FirmwareMajor = static_cast<quint8>(PacketData.data.at(5));
HelloRsp.FirmwareMinor = static_cast<quint8>(PacketData.data.at(6));
HelloRsp.CapabilityFlags = Com_Func_ReadLe16(PacketData.data, 7);
*p_HelloRsp = HelloRsp;
return true;
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <QtCore/QByteArray>
#include "COM/Com_Cdc.h"
bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet);
bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet);
QByteArray Com_ProtoCodec_BuildHelloReq();
bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData);
bool Com_ProtoCodec_ParseHelloRsp(
const Packet& PacketData,
Packet_HelloRsp* p_HelloRsp);

View File

@@ -37,12 +37,12 @@
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
<QtInstall>D:\App\Qt\5.13.1\msvc2015_64</QtInstall>
<QtModules>core;serialport;widgets</QtModules>
<QtModules>core;serialport</QtModules>
<QtBuildConfig>debug</QtBuildConfig>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
<QtInstall>D:\App\Qt\5.13.1\msvc2015_64</QtInstall>
<QtModules>core;serialport;widgets</QtModules>
<QtModules>core;serialport</QtModules>
<QtBuildConfig>release</QtBuildConfig>
</PropertyGroup>
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
@@ -94,18 +94,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="APP\AppKeyButton.cpp" />
<ClInclude Include="APP\AppKeyButton.h" />
<ClCompile Include="APP\AppKeyboardPage.cpp" />
<ClInclude Include="APP\AppKeyboardPage.h" />
<ClCompile Include="APP\AppMainWindow.cpp" />
<ClInclude Include="APP\AppMainWindow.h" />
<ClCompile Include="APP\AppSettingsPage.cpp" />
<ClInclude Include="APP\AppSettingsPage.h" />
<ClInclude Include="APP\AppTheme.h" />
<ClInclude Include="COM\Com_Cdc.h" />
<ClCompile Include="COM\Com_ProtoCodec.cpp" />
<ClInclude Include="COM\Com_ProtoCodec.h" />
<ClCompile Include="COM\Com_CdcEncode.cpp" />
<ClInclude Include="COM\Com_CdcEncode.h" />
<ClCompile Include="COM\Com_CdcDecode.cpp" />
@@ -113,14 +102,6 @@
<ClCompile Include="DRI\Dri_Cdc.cpp" />
<ClCompile Include="DRI\GATT\Dri_Gatt.cpp" />
<ClInclude Include="DRI\GATT\Dri_Gatt.h" />
<ClCompile Include="APP\AppTheme.cpp" />
<ClCompile Include="LOGIC\Lgc_Core.cpp" />
<ClInclude Include="LOGIC\Lgc_Core.h" />
<ClCompile Include="LOGIC\Lgc_FunctionExecutor.cpp" />
<ClInclude Include="LOGIC\Lgc_FunctionExecutor.h" />
<ClCompile Include="LOGIC\Lgc_Session.cpp" />
<ClInclude Include="LOGIC\Lgc_Session.h" />
<ClInclude Include="LOGIC\Lgc_State.h" />
<ClCompile Include="main.cpp" />
<ClInclude Include="DRI\Dri_Cdc.h" />
</ItemGroup>

View File

@@ -23,42 +23,9 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="APP\AppKeyButton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="APP\AppKeyButton.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="APP\AppKeyboardPage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="APP\AppKeyboardPage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="APP\AppMainWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="APP\AppMainWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="APP\AppSettingsPage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="APP\AppSettingsPage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="APP\AppTheme.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="COM\Com_Cdc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="COM\Com_ProtoCodec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="COM\Com_ProtoCodec.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="COM\Com_CdcEncode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -80,30 +47,6 @@
<ClInclude Include="DRI\GATT\Dri_Gatt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="APP\AppTheme.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LOGIC\Lgc_Core.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="LOGIC\Lgc_Core.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="LOGIC\Lgc_FunctionExecutor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="LOGIC\Lgc_FunctionExecutor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="LOGIC\Lgc_Session.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="LOGIC\Lgc_Session.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LOGIC\Lgc_State.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -1,129 +0,0 @@
#include "LOGIC/Lgc_Core.h"
#include "COM/Com_ProtoCodec.h"
namespace
{
void Lgc_Func_ApplyHelloRsp(
Lgc_Core* p_Core,
const Packet_HelloRsp& HelloRsp)
{
p_Core->State.IsConnected = true;
p_Core->State.IsHandshakeDone = true;
p_Core->State.ProtocolVersion = HelloRsp.ProtocolVersion;
p_Core->State.VendorId = HelloRsp.VendorId;
p_Core->State.ProductId = HelloRsp.ProductId;
p_Core->State.FirmwareMajor = HelloRsp.FirmwareMajor;
p_Core->State.FirmwareMinor = HelloRsp.FirmwareMinor;
p_Core->State.CapabilityFlags = HelloRsp.CapabilityFlags;
p_Core->State.ActiveTransport = Lgc_TransportType::Cdc;
p_Core->State.ActiveEndpointName = p_Core->Session.CdcPort.PortName;
p_Core->State.ConnectionText = QStringLiteral("CDC connected: %1")
.arg(p_Core->Session.CdcPort.PortName);
p_Core->State.LastActionText = QStringLiteral("Handshake completed.");
}
void Lgc_Func_UpdateActionText(Lgc_Core* p_Core, const Packet& PacketData)
{
switch (PacketData.type)
{
case Com_Type_HelloRsp:
p_Core->State.LastActionText = QStringLiteral("Received HelloRsp.");
break;
case Com_Type_Bitmap:
p_Core->State.LastActionText = QStringLiteral("Received Bitmap.");
break;
case Com_Type_FunctionKeyEvent:
p_Core->State.LastActionText = QStringLiteral("Received FunctionKeyEvent.");
break;
case Com_Type_LedState:
p_Core->State.LastActionText = QStringLiteral("Received LedState.");
break;
case Com_Type_TimeSync:
p_Core->State.LastActionText = QStringLiteral("Received TimeSync.");
break;
case Com_Type_ThemeRgb:
p_Core->State.LastActionText = QStringLiteral("Received ThemeRgb.");
break;
case Com_Type_Ack:
p_Core->State.LastActionText = QStringLiteral("Received Ack.");
break;
case Com_Type_Error:
p_Core->State.LastActionText = QStringLiteral("Received Error.");
break;
default:
p_Core->State.LastActionText = QStringLiteral("Received packet type 0x%1.")
.arg(static_cast<quint8>(PacketData.type), 2, 16, QLatin1Char('0'))
.toUpper();
break;
}
}
} // namespace
void Lgc_Core_Init(Lgc_Core* p_Core)
{
if (p_Core == nullptr)
{
return;
}
p_Core->State = Lgc_State();
Lgc_Session_Init(&p_Core->Session);
}
bool Lgc_Core_Start(Lgc_Core* p_Core)
{
if (p_Core == nullptr)
{
return false;
}
Dri_Cdc_Struct_OpenConfig Config;
Packet_HelloRsp HelloRsp;
if (Lgc_Session_TryStartCdc(&p_Core->Session, Config, &HelloRsp))
{
Lgc_Func_ApplyHelloRsp(p_Core, HelloRsp);
return true;
}
p_Core->State.IsConnected = false;
p_Core->State.IsHandshakeDone = false;
p_Core->State.ConnectionText = QStringLiteral("No device found.");
p_Core->State.LastActionText = QStringLiteral("Handshake failed.");
return false;
}
bool Lgc_Core_Poll(Lgc_Core* p_Core)
{
if (p_Core == nullptr)
{
return false;
}
Packet PacketData;
if (!Lgc_Session_ReadNextPacket(&p_Core->Session, &PacketData))
{
return false;
}
Lgc_Func_UpdateActionText(p_Core, PacketData);
return true;
}
void Lgc_Core_Close(Lgc_Core* p_Core)
{
if (p_Core == nullptr)
{
return;
}
Lgc_Session_Close(&p_Core->Session);
p_Core->State = Lgc_State();
}
const Lgc_State& Lgc_Core_GetState(const Lgc_Core* p_Core)
{
return p_Core->State;
}

View File

@@ -1,16 +0,0 @@
#pragma once
#include "LOGIC/Lgc_Session.h"
#include "LOGIC/Lgc_State.h"
struct Lgc_Core
{
Lgc_State State;
Lgc_Session Session;
};
void Lgc_Core_Init(Lgc_Core* p_Core);
bool Lgc_Core_Start(Lgc_Core* p_Core);
bool Lgc_Core_Poll(Lgc_Core* p_Core);
void Lgc_Core_Close(Lgc_Core* p_Core);
const Lgc_State& Lgc_Core_GetState(const Lgc_Core* p_Core);

View File

@@ -1,68 +0,0 @@
#include "LOGIC/Lgc_FunctionExecutor.h"
#include <QtCore/QUrl>
#include <QtGui/QDesktopServices>
namespace
{
QString Lgc_Func_GetFunctionName(const Lgc_FunctionDefinition& Function)
{
return Function.Name.trimmed().isEmpty()
? QStringLiteral("Unnamed Function")
: Function.Name.trimmed();
}
} // namespace
bool Lgc_FunctionExecutor_Run(
const Lgc_FunctionDefinition& Function,
QString* p_TextStatus)
{
if (p_TextStatus != nullptr)
{
p_TextStatus->clear();
}
switch (Function.Type)
{
case Lgc_FunctionType::None:
if (p_TextStatus != nullptr)
{
*p_TextStatus = QStringLiteral("%1 has no executable action.")
.arg(Lgc_Func_GetFunctionName(Function));
}
return false;
case Lgc_FunctionType::Shortcut:
if (p_TextStatus != nullptr)
{
*p_TextStatus = QStringLiteral("Shortcut execution will be connected after transport is ready.");
}
return false;
case Lgc_FunctionType::ShortcutSequence:
if (p_TextStatus != nullptr)
{
*p_TextStatus = QStringLiteral("Shortcut sequence execution will be connected after transport is ready.");
}
return false;
case Lgc_FunctionType::Website:
{
const QUrl Url = QUrl::fromUserInput(Function.WebsiteUrl.trimmed());
const bool IsOpened = Url.isValid() && !Url.isEmpty() && QDesktopServices::openUrl(Url);
if (p_TextStatus != nullptr)
{
*p_TextStatus = IsOpened
? QStringLiteral("Opened website: %1").arg(Url.toString())
: QStringLiteral("Failed to open website for %1.").arg(Lgc_Func_GetFunctionName(Function));
}
return IsOpened;
}
}
return false;
}

View File

@@ -1,27 +0,0 @@
#pragma once
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QtGlobal>
enum class Lgc_FunctionType : quint8
{
None = 0,
Shortcut,
ShortcutSequence,
Website,
};
struct Lgc_FunctionDefinition
{
int Id = 0;
QString Name;
QString Description;
Lgc_FunctionType Type = Lgc_FunctionType::None;
QStringList ShortcutTokens;
QString WebsiteUrl;
};
bool Lgc_FunctionExecutor_Run(
const Lgc_FunctionDefinition& Function,
QString* p_TextStatus);

View File

@@ -1,152 +0,0 @@
#include "LOGIC/Lgc_Session.h"
#include "COM/Com_ProtoCodec.h"
#include <QtCore/QElapsedTimer>
namespace
{
bool Lgc_Func_TryHandshakeCdcPort(
Dri_Cdc_Struct_Port* p_Port,
QByteArray* p_ReadBuffer,
Packet_HelloRsp* p_HelloRsp)
{
const QByteArray HelloReqFrame = Com_ProtoCodec_BuildHelloReq();
if (!Dri_Cdc_WriteBytes(p_Port, HelloReqFrame, 200))
{
return false;
}
QElapsedTimer Timer;
Timer.start();
while (Timer.elapsed() < 200)
{
QByteArray ReadBytes;
if (Dri_Cdc_ReadBytes(p_Port, &ReadBytes, 20) && !ReadBytes.isEmpty())
{
p_ReadBuffer->append(ReadBytes);
}
Packet PacketData;
while (Com_ProtoCodec_TryTakeFrame(p_ReadBuffer, &PacketData))
{
if (!Com_ProtoCodec_ParseHelloRsp(PacketData, p_HelloRsp))
{
continue;
}
return true;
}
}
return false;
}
} // namespace
void Lgc_Session_Init(Lgc_Session* p_Session)
{
if (p_Session == nullptr)
{
return;
}
*p_Session = Lgc_Session();
}
void Lgc_Session_Close(Lgc_Session* p_Session)
{
if (p_Session == nullptr)
{
return;
}
Dri_Cdc_Close(&p_Session->CdcPort);
Dri_Gatt_Deinit(&p_Session->GattPort);
p_Session->CdcReadBuffer.clear();
p_Session->IsStarted = false;
p_Session->IsHandshakeDone = false;
p_Session->ActiveTransport = Lgc_TransportType::None;
}
bool Lgc_Session_TryStartCdc(
Lgc_Session* p_Session,
const Dri_Cdc_Struct_OpenConfig& Config,
Packet_HelloRsp* p_HelloRsp)
{
if ((p_Session == nullptr) || (p_HelloRsp == nullptr))
{
return false;
}
const QVector<Dri_Cdc_Struct_PortInfo> PortList = Dri_Cdc_Enum();
for (const Dri_Cdc_Struct_PortInfo& PortInfo : PortList)
{
Dri_Cdc_Struct_Port Port;
if (!Dri_Cdc_Open(&Port, PortInfo.PortName, Config))
{
continue;
}
QByteArray ReadBuffer;
Packet_HelloRsp HelloRsp;
if (Lgc_Func_TryHandshakeCdcPort(&Port, &ReadBuffer, &HelloRsp))
{
Dri_Cdc_Close(&p_Session->CdcPort);
p_Session->CdcPort = Port;
p_Session->CdcReadBuffer = ReadBuffer;
p_Session->IsStarted = true;
p_Session->IsHandshakeDone = true;
p_Session->ActiveTransport = Lgc_TransportType::Cdc;
*p_HelloRsp = HelloRsp;
return true;
}
Dri_Cdc_Close(&Port);
}
return false;
}
bool Lgc_Session_TryStartGatt(Lgc_Session* p_Session)
{
if (p_Session == nullptr)
{
return false;
}
if (Dri_Gatt_Init(&p_Session->GattPort))
{
p_Session->IsStarted = true;
p_Session->ActiveTransport = Lgc_TransportType::Gatt;
return true;
}
return false;
}
bool Lgc_Session_ReadNextPacket(
Lgc_Session* p_Session,
Packet* p_Packet)
{
if ((p_Session == nullptr) || (p_Packet == nullptr))
{
return false;
}
*p_Packet = Packet();
if (p_Session->ActiveTransport == Lgc_TransportType::Cdc)
{
QByteArray ReadBytes;
if (Dri_Cdc_ReadBytes(&p_Session->CdcPort, &ReadBytes, 0) && !ReadBytes.isEmpty())
{
p_Session->CdcReadBuffer.append(ReadBytes);
}
return Com_ProtoCodec_TryTakeFrame(&p_Session->CdcReadBuffer, p_Packet);
}
return false;
}

View File

@@ -1,27 +0,0 @@
#pragma once
#include "COM/Com_Cdc.h"
#include "DRI/Dri_Cdc.h"
#include "DRI/GATT/Dri_Gatt.h"
#include "LOGIC/Lgc_State.h"
struct Lgc_Session
{
Dri_Cdc_Struct_Port CdcPort;
Dri_Gatt_Struct_Port GattPort;
QByteArray CdcReadBuffer;
bool IsStarted = false;
bool IsHandshakeDone = false;
Lgc_TransportType ActiveTransport = Lgc_TransportType::None;
};
void Lgc_Session_Init(Lgc_Session* p_Session);
void Lgc_Session_Close(Lgc_Session* p_Session);
bool Lgc_Session_TryStartCdc(
Lgc_Session* p_Session,
const Dri_Cdc_Struct_OpenConfig& Config,
Packet_HelloRsp* p_HelloRsp);
bool Lgc_Session_TryStartGatt(Lgc_Session* p_Session);
bool Lgc_Session_ReadNextPacket(
Lgc_Session* p_Session,
Packet* p_Packet);

View File

@@ -1,27 +0,0 @@
#pragma once
#include <QtCore/QString>
#include <QtCore/QtGlobal>
enum class Lgc_TransportType : quint8
{
None = 0,
Cdc,
Gatt,
};
struct Lgc_State
{
bool IsConnected = false;
bool IsHandshakeDone = false;
Lgc_TransportType ActiveTransport = Lgc_TransportType::None;
QString ActiveEndpointName;
QString ConnectionText = QStringLiteral("Disconnected");
QString LastActionText = QStringLiteral("Idle");
quint32 ProtocolVersion = 0;
quint32 CapabilityFlags = 0;
quint16 VendorId = 0;
quint16 ProductId = 0;
quint8 FirmwareMajor = 0;
quint8 FirmwareMinor = 0;
};

View File

@@ -1,13 +1,14 @@
#include <QtWidgets/QApplication>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include "APP/AppMainWindow.h"
#include "DRI/Dri_Cdc.h"
int main(int argc, char *argv[])
{
QApplication App(argc, argv);
QCoreApplication App(argc, argv);
APP::App_MainWindow Window;
Window.show();
const QVector<Dri_Cdc_Struct_PortInfo> PortList = Dri_Cdc_Enum();
qDebug() << "CDC ports:" << PortList.size();
return App.exec();
return 0;
}

View File

@@ -1,10 +0,0 @@
# Generated Code
This directory is reserved for generated protocol code.
Planned layout:
- `cpp/` for host-side protobuf generated files
- `nanopb/` for firmware-side generated files
Do not place hand-written logic here.

View File

@@ -1,97 +0,0 @@
# Host APP Rebuild
## Goal
Keep the APP layer suitable for teaching from simple to complex.
Teaching order:
1. one button
2. one keyboard page
3. two pages
4. one main window
5. one shared theme
## Completed Nodes
### Node 1: theme helpers
Files:
- `KeyBorad/KeyBorad/APP/AppTheme.h`
- `KeyBorad/KeyBorad/APP/AppTheme.cpp`
Design notes:
- centralize colors and style strings
- keep styling readable
- avoid mixing style text inside every widget
### Node 2: key button
Files:
- `KeyBorad/KeyBorad/APP/AppKeyButton.h`
- `KeyBorad/KeyBorad/APP/AppKeyButton.cpp`
Design notes:
- teach one custom button first
- keep state changes explicit
- let one widget own its own text and style refresh
### Node 3: keyboard page
Files:
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.h`
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.cpp`
Design notes:
- grow from one button to a full keypad
- keep layout data local and explicit
### Node 4: settings page
Files:
- `KeyBorad/KeyBorad/APP/AppSettingsPage.h`
- `KeyBorad/KeyBorad/APP/AppSettingsPage.cpp`
Design notes:
- use a second page early
- give transport status and action feedback one simple home
### Node 5: main window integration
Files updated in this step:
- `KeyBorad/KeyBorad/APP/AppMainWindow.h`
- `KeyBorad/KeyBorad/APP/AppMainWindow.cpp`
- `KeyBorad/KeyBorad/main.cpp`
Implemented behavior:
- create the two-page window
- own one `Lgc_Core`
- start handshake on launch
- poll the logic layer with a timer
- refresh settings page texts from logic state
### Node 6: Qt property typing fix
Files updated in this step:
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.cpp`
- `KeyBorad/KeyBorad/APP/AppSettingsPage.cpp`
Design notes:
- keep widget property values explicit under MSVC + Qt
- avoid relying on implicit conversion from string literal to `QVariant`
Implemented behavior:
- replace raw `"title"` / `"body"` property values with `QStringLiteral(...)`

View File

@@ -1,58 +0,0 @@
# Host COM Rebuild
## Goal
Keep the protocol layer small and explicit.
The COM layer should:
- define packet-facing helpers
- own frame parsing and packet building
- avoid transport concerns
- avoid UI and session concerns
## Completed Nodes
### Node 1: legacy protocol baseline
Files already present before this step:
- `KeyBorad/KeyBorad/COM/Com_Cdc.h`
- `KeyBorad/KeyBorad/COM/Com_CdcEncode.h`
- `KeyBorad/KeyBorad/COM/Com_CdcEncode.cpp`
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.h`
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.cpp`
Design notes:
- these files preserve the old packet format
- they already encode and decode complete CDC frames
- they also contain per-packet payload helpers
### Node 2: unified protocol entry
Files added in this step:
- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.h`
- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp`
Design notes:
- provides a thin and readable entry point for higher layers
- keeps `DRI` from depending on packet parsing
- keeps `LGC` from depending on low-level byte layout details
- starts from the smallest useful handshake path
Implemented behavior:
- build `HelloReq` frame
- validate whether a parsed packet is `HelloRsp`
- decode `HelloRsp`
- forward frame parsing and stream extraction to the existing low-level codec
## Next COM nodes
- bitmap encode/decode helper
- ack/error helper
- time sync and theme helper
- replace direct `Com_Cdc*` calls in higher layers with `Com_ProtoCodec*`

View File

@@ -1,77 +0,0 @@
# Host LGC Rebuild
## Goal
Keep the logic layer small, readable, and teachable.
The logic layer should:
- own connection state
- own handshake state
- call DRI for bytes
- call COM for frame and packet parsing
- expose a small interface to APP
The logic layer should not:
- parse serial bytes by itself
- enumerate devices directly
- own widget code
## Completed Nodes
### Node 1: function executor shell
Files:
- `KeyBorad/KeyBorad/LOGIC/Lgc_FunctionExecutor.h`
- `KeyBorad/KeyBorad/LOGIC/Lgc_FunctionExecutor.cpp`
Design notes:
- keep function execution out of session code
- reserve one place for OS-specific actions
- keep the initial implementation small
### Node 2: state model
Files updated in this step:
- `KeyBorad/KeyBorad/LOGIC/Lgc_State.h`
Design notes:
- state is plain data
- connection text and last action text live here
- handshake result fields live here
### Node 3: session handshake path
Files completed in this step:
- `KeyBorad/KeyBorad/LOGIC/Lgc_Session.h`
- `KeyBorad/KeyBorad/LOGIC/Lgc_Session.cpp`
Implemented behavior:
- try CDC handshake
- send `HelloReq`
- wait for `HelloRsp`
- store the active transport
- keep a stream buffer for CDC bytes
- return the next parsed packet to upper layers
### Node 4: core facade
Files completed in this step:
- `KeyBorad/KeyBorad/LOGIC/Lgc_Core.h`
- `KeyBorad/KeyBorad/LOGIC/Lgc_Core.cpp`
Implemented behavior:
- give APP one small entry point
- start CDC handshake through session
- expose `Start / Poll / Close / GetState`
- refresh state from `HelloRsp`
- update a simple action text when packets arrive