Skip to content

Commit afbfb8f

Browse files
committed
App: add virtual keyboard
1 parent ff9466a commit afbfb8f

18 files changed

Lines changed: 485 additions & 33 deletions

.github/workflows/macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
SOURCE_DIR: ${{github.workspace}}/.cache/source
5252
TOOLS_DIR: ${{github.workspace}}/.cache/tools
5353
INSTALL_DIR: ${{github.workspace}}/.cache/install_${{matrix.os}}
54-
qt_modules: "qtscxml qtmultimedia qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine"
54+
qt_modules: "qtscxml qtmultimedia qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine qtspeech qtvirtualkeyboard"
5555
VCPKGGITCOMMITID: 7213cf8135c329c37c7e2778e40774489a0583a8
5656
VCPKG_TARGET_TRIPLET: ${{matrix.VCPKG_TARGET_TRIPLET}}
5757
VCPKG_DEFAULT_TRIPLET: ${{matrix.VCPKG_TARGET_TRIPLET}}

.github/workflows/msvc.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
BUILD_TYPE: Release
2222
qt_version: 6.10.2
2323
qt_arch: win64_msvc2022_64
24-
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine
24+
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine qtspeech qtvirtualkeyboard
2525
os: windows-2022
2626

2727
- CMAKE_GENERATOR_PLATFORM: arm64
@@ -30,7 +30,7 @@ jobs:
3030
BUILD_TYPE: Release
3131
qt_version: 6.10.2
3232
qt_arch: win64_msvc2022_arm64
33-
qt_modules: qt5compat qtimageformats qtmultimedia qtpositioning qtscxml qtserialport qtwebchannel qtwebsockets
33+
qt_modules: qt5compat qtimageformats qtmultimedia qtpositioning qtscxml qtserialport qtwebchannel qtwebsockets qtspeech qtvirtualkeyboard
3434
os: windows-11-arm
3535

3636
- CMAKE_GENERATOR_PLATFORM: x64
@@ -39,7 +39,7 @@ jobs:
3939
BUILD_TYPE: Release
4040
qt_version: 6.9.3
4141
qt_arch: win64_msvc2022_64
42-
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine
42+
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qt5compat qtwebsockets qtpositioning qtwebchannel qtwebengine qtspeech qtvirtualkeyboard
4343
os: windows-2022
4444

4545
- CMAKE_GENERATOR_PLATFORM: arm64
@@ -48,7 +48,7 @@ jobs:
4848
BUILD_TYPE: Release
4949
qt_version: 6.9.3
5050
qt_arch: win64_msvc2022_arm64
51-
qt_modules: qt5compat qtimageformats qtmultimedia qtpositioning qtscxml qtserialport qtwebchannel qtwebsockets
51+
qt_modules: qt5compat qtimageformats qtmultimedia qtpositioning qtscxml qtserialport qtwebchannel qtwebsockets qtspeech qtvirtualkeyboard
5252
os: windows-11-arm
5353

5454
- CMAKE_GENERATOR_PLATFORM: Win32

App/Client/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ list(APPEND APP_INCLUDE_DIRS
7575
# endif()
7676
#endif()
7777

78-
set(APP_QT_COMPONENTS Core Gui Widgets Network Svg Xml Multimedia MultimediaWidgets Sql)
78+
set(APP_QT_COMPONENTS Core Gui Widgets Network Svg Xml
79+
Multimedia MultimediaWidgets Sql)
7980
if(QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
8081
list(APPEND APP_QT_COMPONENTS StateMachine)
8182
endif()
@@ -87,6 +88,13 @@ if(Qt${QT_VERSION_MAJOR}_FOUND)
8788
else()
8889
message(FATAL_ERROR "Qt${QT_VERSION_MAJOR} don't found")
8990
endif()
91+
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS VirtualKeyboard)
92+
if(Qt${QT_VERSION_MAJOR}_FOUND)
93+
list(APPEND QT_LIBRARIES Qt${QT_VERSION_MAJOR}::VirtualKeyboard)
94+
list(APPEND APP_PRIVATE_DEFINITIONS HAVE_VirtualKeyboard)
95+
list(APPEND SOURCE_FILES VirtualKeyboardSettingsDialog.cpp)
96+
list(APPEND HEADER_FILES VirtualKeyboardSettingsDialog.h)
97+
endif()
9098

9199
option(WITH_MACOSX_BUNDLE "Create BUNDLE directory" OFF)
92100
if(WITH_MACOSX_BUNDLE)
@@ -101,6 +109,7 @@ ADD_TARGET(NAME ${PROJECT_NAME}
101109
INCLUDE_DIRS ${APP_INCLUDE_DIRS}
102110
PRIVATE_DEFINITIONS RabbitRemoteControl_VERSION="${RabbitRemoteControl_VERSION}"
103111
RabbitRemoteControl_REVISION="${RabbitRemoteControl_REVISION}"
112+
${APP_PRIVATE_DEFINITIONS}
104113
SOURCE_FILES ${SOURCE_FILES} ${HEADER_FILES} ${SOURCE_UI_FILES} ${RCC_FILES} ${AppImage}
105114
PRIVATE_LIBS Plugin ${QT_LIBRARIES}
106115
)
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
#include "VirtualKeyboardSettingsDialog.h"
2+
#include <QDebug>
3+
#include <QLocale>
4+
#include <QMessageBox>
5+
#include <QApplication>
6+
#include <QScreen>
7+
#include <QStyleFactory>
8+
9+
CVirtualKeyboardSettingsDialog::CVirtualKeyboardSettingsDialog(QWidget *parent)
10+
: QDialog(parent)
11+
, m_settings(new QSettings("YourCompany", "YourApp", this))
12+
{
13+
setWindowTitle(tr("虚拟键盘设置"));
14+
setModal(true);
15+
setMinimumWidth(400);
16+
17+
setupUi();
18+
loadSettings();
19+
20+
// 连接信号槽
21+
connect(m_applyButton, &QPushButton::clicked, this, &CVirtualKeyboardSettingsDialog::applySettings);
22+
connect(m_defaultsButton, &QPushButton::clicked, this, &CVirtualKeyboardSettingsDialog::restoreDefaults);
23+
connect(m_okButton, &QPushButton::clicked, this, &QDialog::accept);
24+
connect(m_cancelButton, &QPushButton::clicked, this, &QDialog::reject);
25+
26+
connect(m_languageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
27+
this, &CVirtualKeyboardSettingsDialog::onLanguageChanged);
28+
connect(m_themeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
29+
this, &CVirtualKeyboardSettingsDialog::onThemeChanged);
30+
}
31+
32+
CVirtualKeyboardSettingsDialog::~CVirtualKeyboardSettingsDialog()
33+
{
34+
}
35+
36+
void CVirtualKeyboardSettingsDialog::setupUi()
37+
{
38+
QVBoxLayout *mainLayout = new QVBoxLayout(this);
39+
40+
// ===== 语言设置组 =====
41+
QGroupBox *languageGroup = new QGroupBox(tr("输入语言"), this);
42+
QVBoxLayout *languageLayout = new QVBoxLayout(languageGroup);
43+
44+
m_languageCombo = new QComboBox(this);
45+
m_localeList = getAvailableLocales();
46+
47+
// 填充语言下拉框
48+
for (const QString &locale : m_localeList) {
49+
QLocale loc(locale);
50+
QString displayName = QString("%1 (%2)")
51+
.arg(loc.nativeLanguageName())
52+
.arg(loc.nativeCountryName());
53+
m_languageCombo->addItem(displayName, locale);
54+
}
55+
56+
languageLayout->addWidget(new QLabel(tr("选择输入语言:"), this));
57+
languageLayout->addWidget(m_languageCombo);
58+
languageLayout->addStretch();
59+
60+
// ===== 外观设置组 =====
61+
QGroupBox *appearanceGroup = new QGroupBox(tr("外观设置"), this);
62+
QVBoxLayout *appearanceLayout = new QVBoxLayout(appearanceGroup);
63+
64+
// 主题选择
65+
QHBoxLayout *themeLayout = new QHBoxLayout();
66+
themeLayout->addWidget(new QLabel(tr("键盘主题:"), this));
67+
m_themeCombo = new QComboBox(this);
68+
QStringList themes = getAvailableStyles();
69+
themes.prepend("默认"); // 添加默认主题选项
70+
m_themeCombo->addItems(themes);
71+
themeLayout->addWidget(m_themeCombo);
72+
themeLayout->addStretch();
73+
appearanceLayout->addLayout(themeLayout);
74+
75+
// 按键大小调节
76+
QHBoxLayout *keySizeLayout = new QHBoxLayout();
77+
keySizeLayout->addWidget(new QLabel(tr("按键大小:"), this));
78+
m_keySizeSlider = new QSlider(Qt::Horizontal, this);
79+
m_keySizeSlider->setRange(50, 150);
80+
m_keySizeSlider->setValue(100);
81+
m_keySizeSlider->setTickPosition(QSlider::TicksBelow);
82+
m_keySizeSlider->setTickInterval(10);
83+
keySizeLayout->addWidget(m_keySizeSlider, 1);
84+
85+
m_keySizeLabel = new QLabel("100%", this);
86+
keySizeLayout->addWidget(m_keySizeLabel);
87+
appearanceLayout->addLayout(keySizeLayout);
88+
89+
// 连接滑块信号更新百分比显示
90+
connect(m_keySizeSlider, &QSlider::valueChanged, [this](int value) {
91+
m_keySizeLabel->setText(QString("%1%").arg(value));
92+
});
93+
94+
// 辅助选项
95+
m_smallTextCheck = new QCheckBox(tr("显示按键辅助小文本"), this);
96+
m_autoCapsCheck = new QCheckBox(tr("自动大写"), this);
97+
appearanceLayout->addWidget(m_smallTextCheck);
98+
appearanceLayout->addWidget(m_autoCapsCheck);
99+
100+
// ===== 反馈设置组 =====
101+
QGroupBox *feedbackGroup = new QGroupBox(tr("按键反馈"), this);
102+
QVBoxLayout *feedbackLayout = new QVBoxLayout(feedbackGroup);
103+
104+
m_keySoundCheck = new QCheckBox(tr("启用按键音"), this);
105+
m_hapticCheck = new QCheckBox(tr("启用震动反馈"), this);
106+
107+
feedbackLayout->addWidget(m_keySoundCheck);
108+
feedbackLayout->addWidget(m_hapticCheck);
109+
110+
// ===== 按钮区域 =====
111+
QHBoxLayout *buttonLayout = new QHBoxLayout();
112+
m_defaultsButton = new QPushButton(tr("恢复默认"), this);
113+
m_applyButton = new QPushButton(tr("应用"), this);
114+
m_okButton = new QPushButton(tr("确定"), this);
115+
m_cancelButton = new QPushButton(tr("取消"), this);
116+
117+
buttonLayout->addWidget(m_defaultsButton);
118+
buttonLayout->addStretch();
119+
buttonLayout->addWidget(m_applyButton);
120+
buttonLayout->addWidget(m_okButton);
121+
buttonLayout->addWidget(m_cancelButton);
122+
123+
// 将所有组件添加到主布局
124+
mainLayout->addWidget(languageGroup);
125+
mainLayout->addWidget(appearanceGroup);
126+
mainLayout->addWidget(feedbackGroup);
127+
mainLayout->addStretch();
128+
mainLayout->addLayout(buttonLayout);
129+
}
130+
131+
void CVirtualKeyboardSettingsDialog::loadSettings()
132+
{
133+
// 加载语言设置
134+
QString savedLocale = m_settings->value("virtualkeyboard/locale", "en_US").toString();
135+
int localeIndex = m_localeList.indexOf(savedLocale);
136+
if (localeIndex >= 0) {
137+
m_languageCombo->setCurrentIndex(localeIndex);
138+
}
139+
140+
// 加载主题设置
141+
QString savedTheme = m_settings->value("virtualkeyboard/theme", "默认").toString();
142+
int themeIndex = m_themeCombo->findText(savedTheme);
143+
if (themeIndex >= 0) {
144+
m_themeCombo->setCurrentIndex(themeIndex);
145+
}
146+
147+
// 加载其他设置
148+
m_keySoundCheck->setChecked(m_settings->value("virtualkeyboard/keySound", true).toBool());
149+
m_hapticCheck->setChecked(m_settings->value("virtualkeyboard/haptic", false).toBool());
150+
m_keySizeSlider->setValue(m_settings->value("virtualkeyboard/keySize", 100).toInt());
151+
m_smallTextCheck->setChecked(m_settings->value("virtualkeyboard/smallText", true).toBool());
152+
m_autoCapsCheck->setChecked(m_settings->value("virtualkeyboard/autoCaps", true).toBool());
153+
}
154+
155+
void CVirtualKeyboardSettingsDialog::saveSettings()
156+
{
157+
m_settings->setValue("virtualkeyboard/locale",
158+
m_languageCombo->currentData().toString());
159+
m_settings->setValue("virtualkeyboard/theme", m_themeCombo->currentText());
160+
m_settings->setValue("virtualkeyboard/keySound", m_keySoundCheck->isChecked());
161+
m_settings->setValue("virtualkeyboard/haptic", m_hapticCheck->isChecked());
162+
m_settings->setValue("virtualkeyboard/keySize", m_keySizeSlider->value());
163+
m_settings->setValue("virtualkeyboard/smallText", m_smallTextCheck->isChecked());
164+
m_settings->setValue("virtualkeyboard/autoCaps", m_autoCapsCheck->isChecked());
165+
166+
m_settings->sync();
167+
}
168+
169+
void CVirtualKeyboardSettingsDialog::applySettings()
170+
{
171+
// 应用语言设置
172+
QString selectedLocale = m_languageCombo->currentData().toString();
173+
applyLanguage(selectedLocale);
174+
175+
// 应用主题设置
176+
applyTheme(m_themeCombo->currentText());
177+
178+
// 应用其他设置
179+
applyKeySound(m_keySoundCheck->isChecked());
180+
applyHapticFeedback(m_hapticCheck->isChecked());
181+
applyKeySize(m_keySizeSlider->value());
182+
183+
// 辅助选项
184+
// QVirtualKeyboardSettings *vkSettings = QVirtualKeyboardSettings::instance();
185+
// if (vkSettings) {
186+
// vkSettings->setSmallTextVisible(m_smallTextCheck->isChecked());
187+
// // 自动大写可能需要通过其他方式设置
188+
// }
189+
190+
// 保存到QSettings
191+
saveSettings();
192+
193+
qDebug() << "Virtual keyboard settings applied";
194+
}
195+
196+
void CVirtualKeyboardSettingsDialog::restoreDefaults()
197+
{
198+
m_languageCombo->setCurrentIndex(m_localeList.indexOf("en_US"));
199+
m_themeCombo->setCurrentIndex(0); // "默认"
200+
m_keySoundCheck->setChecked(true);
201+
m_hapticCheck->setChecked(false);
202+
m_keySizeSlider->setValue(100);
203+
m_smallTextCheck->setChecked(true);
204+
m_autoCapsCheck->setChecked(true);
205+
}
206+
207+
void CVirtualKeyboardSettingsDialog::onLanguageChanged(int index)
208+
{
209+
if (index >= 0 && index < m_localeList.size()) {
210+
// 可以在这里实时预览语言切换效果
211+
QString locale = m_localeList[index];
212+
qDebug() << "Language preview:" << locale;
213+
}
214+
}
215+
216+
void CVirtualKeyboardSettingsDialog::onThemeChanged(int index)
217+
{
218+
Q_UNUSED(index);
219+
// 主题预览逻辑
220+
}
221+
222+
QStringList CVirtualKeyboardSettingsDialog::getAvailableLocales()
223+
{
224+
// 返回支持的locale列表
225+
// 这取决于你的Qt构建包含的语言包
226+
return QStringList()
227+
<< "en_US" // 英语
228+
<< "zh_CN" // 简体中文
229+
<< "zh_TW" // 繁体中文
230+
<< "ja_JP" // 日语
231+
<< "ko_KR" // 韩语
232+
<< "fr_FR" // 法语
233+
<< "de_DE" // 德语
234+
<< "ru_RU" // 俄语
235+
<< "es_ES" // 西班牙语
236+
<< "ar_SA" // 阿拉伯语
237+
<< "hi_IN"; // 印地语
238+
}
239+
240+
QStringList CVirtualKeyboardSettingsDialog::getAvailableStyles()
241+
{
242+
// 返回可用的键盘样式
243+
return QStyleFactory::keys();
244+
}
245+
246+
void CVirtualKeyboardSettingsDialog::applyLanguage(const QString &locale)
247+
{
248+
// QVirtualKeyboardSettings *settings = QVirtualKeyboardSettings::instance();
249+
// if (settings) {
250+
// settings->setLocale(locale);
251+
// }
252+
}
253+
254+
void CVirtualKeyboardSettingsDialog::applyTheme(const QString &theme)
255+
{
256+
if (theme != "默认") {
257+
// 应用Qt样式表
258+
qApp->setStyle(theme);
259+
} else {
260+
// 恢复默认样式
261+
qApp->setStyle(QStyleFactory::create("Fusion"));
262+
}
263+
}
264+
265+
void CVirtualKeyboardSettingsDialog::applyKeySound(bool enabled)
266+
{
267+
// 按键音的实现通常需要与平台相关
268+
// 这里可以通过QSettings保存设置,在键盘事件中检查
269+
qDebug() << "Key sound:" << enabled;
270+
271+
// 实际使用时,你需要在按键处理代码中检查这个设置
272+
}
273+
274+
void CVirtualKeyboardSettingsDialog::applyHapticFeedback(bool enabled)
275+
{
276+
// 震动反馈的实现通常需要平台特定API
277+
qDebug() << "Haptic feedback:" << enabled;
278+
}
279+
280+
void CVirtualKeyboardSettingsDialog::applyKeySize(int size)
281+
{
282+
// 按键大小的实现通常需要通过QML或样式表调整
283+
// 这里保存设置,然后在键盘初始化时使用
284+
qDebug() << "Key size:" << size << "%";
285+
286+
// 可以设置一个环境变量或全局属性,供QML使用
287+
qputenv("QT_VIRTUALKEYBOARD_KEY_SIZE", QByteArray::number(size));
288+
}

0 commit comments

Comments
 (0)