1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquickvirtualkeyboardsettings_p.h"
5#include <QtVirtualKeyboard/private/settings_p.h>
6#include <QtVirtualKeyboard/private/virtualkeyboarddebug_p.h>
7#include <QQmlEngine>
8#include <QQmlContext>
9#include <QFileInfo>
10#include <QDir>
11#include <QRegularExpression>
12#include <QtCore/private/qobject_p.h>
13#include <QtCore/qmutex.h>
14
15QT_BEGIN_NAMESPACE
16namespace QtVirtualKeyboard {
17
18class QQuickVirtualKeyboardSettingsPrivate : public QObjectPrivate
19{
20 Q_DECLARE_PUBLIC(QQuickVirtualKeyboardSettings)
21public:
22 QQuickVirtualKeyboardSettingsPrivate(QQuickVirtualKeyboardSettings *q_ptr, QQmlEngine *engine) :
23 QObjectPrivate(),
24 q_ptr(q_ptr),
25 engine(engine)
26 {}
27
28 QString buildStylePath(const QString &path, const QString &name) const
29 {
30 QString importPath(path + name + QLatin1String("/style.qml"));
31 if (!importPath.startsWith(s: QLatin1String("qrc:"))) {
32 QUrl url = QUrl::fromLocalFile(localfile: importPath);
33 importPath = url.toString();
34 }
35 return importPath;
36 }
37
38 QString buildStyleFilePath(const QString &path, const QString &name) const
39 {
40 QString filePath(path);
41 if (filePath.startsWith(s: QLatin1String("qrc:")))
42 filePath.remove(i: 0, len: 3);
43 return filePath + name + QLatin1String("/style.qml");
44 }
45
46 QStringList qmlImportPathList() const
47 {
48 return engine ? engine->importPathList() : QStringList();
49 }
50
51 QString stylePath(const QString &name) const
52 {
53 if (name.isEmpty())
54 return QString();
55
56 QStringList stylePathList;
57 stylePathList << QLatin1String("qrc:/qt-project.org/imports/QtQuick/VirtualKeyboard/Styles/Builtin/");
58 const QStringList importPathList = qmlImportPathList();
59 // Add QML import path (Note: the QML base dir is usually the last entry in the list)
60 for (int i = importPathList.size() - 1; i >= 0; --i) {
61 const QString stylesPath = importPathList.at(i)
62 + QLatin1String("/QtQuick/VirtualKeyboard/Styles/");
63 stylePathList += stylesPath;
64 }
65
66 // Path for backwards compatibility
67 stylePathList << QLatin1String("qrc:/QtQuick/VirtualKeyboard/content/styles/");
68
69 for (const QString &stylePath : std::as_const(t&: stylePathList)) {
70 QString filePath = buildStyleFilePath(path: stylePath, name);
71 bool pathExist = false;
72 pathExist = QFileInfo::exists(file: filePath);
73 if (pathExist)
74 return buildStylePath(path: stylePath, name);
75 }
76 return QString();
77 }
78
79 QQuickVirtualKeyboardSettings *q_ptr;
80 QQmlEngine *engine;
81 QQuickWordCandidateListSettings wordCandidateListSettings;
82};
83
84/*!
85 \qmlmodule QtQuick.VirtualKeyboard.Settings
86 \title Qt Quick Virtual Keyboard Settings QML Types
87 \ingroup qmlmodules
88
89 \brief Provides settings for Qt Virtual Keyboard.
90
91 The QML types can be imported into your application using the following
92 import statements in your .qml file:
93
94 \qml
95 import QtQuick.VirtualKeyboard.Settings
96 \endqml
97*/
98
99/*!
100 \qmltype VirtualKeyboardSettings
101 \inqmlmodule QtQuick.VirtualKeyboard.Settings
102 \ingroup qtvirtualkeyboard-settings-qml
103 \since QtQuick.VirtualKeyboard 1.2
104 \brief Provides settings for virtual keyboard.
105
106 This type provides a VirtualKeyboardSettings singleton instance,
107 which can be used to configure the virtual keyboard settings.
108
109 Please note that the settings have only effect in the current
110 application's lifetime, that is, configuration changes are not
111 permanent.
112
113 For example, to change the keyboard style in application:
114
115 \code
116 Component.onCompleted: VirtualKeyboardSettings.styleName = "retro"
117 \endcode
118*/
119
120/*!
121 \class QtVirtualKeyboard::VirtualKeyboardSettings
122 \internal
123*/
124
125/*!
126 \internal
127*/
128QQuickVirtualKeyboardSettings::QQuickVirtualKeyboardSettings(QQmlEngine *engine, QObject *parent) :
129 QObject(*new QQuickVirtualKeyboardSettingsPrivate(this, engine), parent)
130{
131 Q_D(QQuickVirtualKeyboardSettings);
132 Settings *settings = Settings::instance();
133 if (settings->styleName().isEmpty())
134 resetStyle();
135 if (settings->layoutPath().isEmpty())
136 resetLayoutPath();
137 connect(asender: settings, SIGNAL(styleChanged()), SIGNAL(styleChanged()));
138 connect(asender: settings, SIGNAL(styleNameChanged()), SIGNAL(styleNameChanged()));
139 connect(asender: settings, SIGNAL(localeChanged()), SIGNAL(localeChanged()));
140 connect(asender: settings, SIGNAL(availableLocalesChanged()), SIGNAL(availableLocalesChanged()));
141 connect(asender: settings, SIGNAL(activeLocalesChanged()), SIGNAL(activeLocalesChanged()));
142 connect(asender: settings, SIGNAL(layoutPathChanged()), SIGNAL(layoutPathChanged()));
143 connect(sender: settings, SIGNAL(wclAutoHideDelayChanged()), receiver: &d->wordCandidateListSettings, SIGNAL(autoHideDelayChanged()));
144 connect(sender: settings, SIGNAL(wclAlwaysVisibleChanged()), receiver: &d->wordCandidateListSettings, SIGNAL(alwaysVisibleChanged()));
145 connect(sender: settings, SIGNAL(wclAutoCommitWordChanged()), receiver: &d->wordCandidateListSettings, SIGNAL(autoCommitWordChanged()));
146 connect(asender: settings, SIGNAL(fullScreenModeChanged()), SIGNAL(fullScreenModeChanged()));
147 connect(asender: settings, SIGNAL(userDataPathChanged()), SIGNAL(userDataPathChanged()));
148 settings->connect(asender: this, SIGNAL(userDataReset()), SIGNAL(userDataReset()));
149 connect(asender: settings, SIGNAL(hwrTimeoutForAlphabeticChanged()), SIGNAL(hwrTimeoutForAlphabeticChanged()));
150 connect(asender: settings, SIGNAL(hwrTimeoutForCjkChanged()), SIGNAL(hwrTimeoutForCjkChanged()));
151 connect(asender: settings, SIGNAL(inputMethodHintsChanged()), SIGNAL(inputMethodHintsChanged()));
152 connect(asender: settings, SIGNAL(handwritingModeDisabledChanged()), SIGNAL(handwritingModeDisabledChanged()));
153 connect(asender: settings, SIGNAL(defaultInputMethodDisabledChanged()), SIGNAL(defaultInputMethodDisabledChanged()));
154 connect(asender: settings, SIGNAL(defaultDictionaryDisabledChanged()), SIGNAL(defaultDictionaryDisabledChanged()));
155 connect(asender: settings, SIGNAL(visibleFunctionKeysChanged()), SIGNAL(visibleFunctionKeysChanged()));
156}
157
158/*!
159 \internal
160 TODO: Remove this method when QML stops creating separate singleton instances for each version.
161 */
162QQuickVirtualKeyboardSettings *QQuickVirtualKeyboardSettings::create(
163 QQmlEngine *qmlEngine, QJSEngine *)
164{
165 static QMutex mutex;
166 static QHash<QQmlEngine *, QQuickVirtualKeyboardSettings *> instances;
167 QMutexLocker locker(&mutex);
168 QQuickVirtualKeyboardSettings *&instance = instances[qmlEngine];
169 if (instance == nullptr)
170 instance = new QQuickVirtualKeyboardSettings(qmlEngine);
171 return instance;
172}
173
174/*!
175 \internal
176*/
177QString QQuickVirtualKeyboardSettings::style() const
178{
179 return Settings::instance()->style();
180}
181
182/*!
183 \internal
184*/
185QString QQuickVirtualKeyboardSettings::styleName() const
186{
187 return Settings::instance()->styleName();
188}
189
190/*!
191 \internal
192*/
193void QQuickVirtualKeyboardSettings::setStyleName(const QString &styleName)
194{
195 Q_D(QQuickVirtualKeyboardSettings);
196 Settings *settings = Settings::instance();
197 QString style = d->stylePath(name: styleName);
198 if (style.isEmpty()) {
199 qWarning() << "WARNING: Cannot find style" << styleName << "- fallback:" << settings->styleName();
200 return;
201 }
202 settings->setStyleName(styleName);
203 settings->setStyle(style);
204}
205
206/*!
207 \internal
208*/
209QUrl QQuickVirtualKeyboardSettings::layoutPath() const
210{
211 return Settings::instance()->layoutPath();
212}
213
214/*!
215 \internal
216*/
217void QQuickVirtualKeyboardSettings::setLayoutPath(const QUrl &layoutPath)
218{
219 Settings *settings = Settings::instance();
220 QDir layoutDirectory(layoutPath.toLocalFile());
221 if (!layoutDirectory.exists()) {
222 qWarning() << "WARNING: Cannot find layout path" << layoutPath;
223 return;
224 }
225 settings->setLayoutPath(layoutPath);
226}
227
228void QQuickVirtualKeyboardSettings::resetLayoutPath()
229{
230 Settings *settings = Settings::instance();
231 QUrl layoutPath(QLatin1String(QT_VIRTUALKEYBOARD_DEFAULT_LAYOUTS_DIR));
232 const QString customLayoutPath(QDir::fromNativeSeparators(pathName: qEnvironmentVariable(varName: "QT_VIRTUALKEYBOARD_LAYOUT_PATH")));
233 if (!customLayoutPath.isEmpty()) {
234 bool found = false;
235 QDir customLayoutDirectory(customLayoutPath);
236 if (customLayoutDirectory.exists()) {
237 found = true;
238 layoutPath = QUrl::fromLocalFile(localfile: customLayoutPath);
239 } else {
240 customLayoutDirectory = QDir(QUrl(customLayoutPath).toLocalFile());
241 if (customLayoutDirectory.exists()) {
242 found = true;
243 layoutPath = QUrl(customLayoutPath);
244 }
245 }
246 if (!found) {
247 qWarning() << "WARNING: Cannot assign custom layout path" << customLayoutPath << "- fallback:" << layoutPath;
248 }
249 }
250 settings->setLayoutPath(layoutPath);
251}
252
253QString QQuickVirtualKeyboardSettings::locale() const
254{
255 return Settings::instance()->locale();
256}
257
258void QQuickVirtualKeyboardSettings::setLocale(const QString &locale)
259{
260 Settings::instance()->setLocale(locale);
261}
262
263QStringList QQuickVirtualKeyboardSettings::availableLocales() const
264{
265 return Settings::instance()->availableLocales();
266}
267
268void QQuickVirtualKeyboardSettings::setActiveLocales(const QStringList &activeLocales)
269{
270 Settings::instance()->setActiveLocales(activeLocales);
271}
272
273QStringList QQuickVirtualKeyboardSettings::activeLocales() const
274{
275 return Settings::instance()->activeLocales();
276}
277
278QQuickWordCandidateListSettings *QQuickVirtualKeyboardSettings::wordCandidateList() const
279{
280 Q_D(const QQuickVirtualKeyboardSettings);
281 return const_cast<QQuickWordCandidateListSettings *>(&d->wordCandidateListSettings);
282}
283
284bool QQuickVirtualKeyboardSettings::fullScreenMode() const
285{
286 return Settings::instance()->fullScreenMode();
287}
288
289void QQuickVirtualKeyboardSettings::setFullScreenMode(bool fullScreenMode)
290{
291 return Settings::instance()->setFullScreenMode(fullScreenMode);
292}
293
294QString QQuickVirtualKeyboardSettings::userDataPath() const
295{
296 return Settings::instance()->userDataPath();
297}
298
299void QQuickVirtualKeyboardSettings::setUserDataPath(const QString &userDataPath)
300{
301 return Settings::instance()->setUserDataPath(userDataPath);
302}
303
304int QQuickVirtualKeyboardSettings::hwrTimeoutForAlphabetic() const
305{
306 return Settings::instance()->hwrTimeoutForAlphabetic();
307}
308
309void QQuickVirtualKeyboardSettings::setHwrTimeoutForAlphabetic(int hwrTimeoutForAlphabetic)
310{
311 return Settings::instance()->setHwrTimeoutForAlphabetic(hwrTimeoutForAlphabetic);
312}
313
314int QQuickVirtualKeyboardSettings::hwrTimeoutForCjk() const
315{
316 return Settings::instance()->hwrTimeoutForCjk();
317}
318
319void QQuickVirtualKeyboardSettings::setHwrTimeoutForCjk(int hwrTimeoutForCjk)
320{
321 return Settings::instance()->setHwrTimeoutForCjk(hwrTimeoutForCjk);
322}
323
324Qt::InputMethodHints QQuickVirtualKeyboardSettings::inputMethodHints() const
325{
326 return Settings::instance()->inputMethodHints();
327}
328
329void QQuickVirtualKeyboardSettings::setInputMethodHints(const Qt::InputMethodHints &inputMethodHints)
330{
331 Settings::instance()->setInputMethodHints(inputMethodHints);
332}
333
334bool QQuickVirtualKeyboardSettings::isHandwritingModeDisabled() const
335{
336 return Settings::instance()->isHandwritingModeDisabled();
337}
338
339void QQuickVirtualKeyboardSettings::setHandwritingModeDisabled(bool handwritingModeDisabled)
340{
341 Settings::instance()->setHandwritingModeDisabled(handwritingModeDisabled);
342}
343
344bool QQuickVirtualKeyboardSettings::isDefaultInputMethodDisabled() const
345{
346 return Settings::instance()->isDefaultInputMethodDisabled();
347}
348
349void QQuickVirtualKeyboardSettings::setDefaultInputMethodDisabled(bool defaultInputMethodDisabled)
350{
351 return Settings::instance()->setDefaultInputMethodDisabled(defaultInputMethodDisabled);
352}
353
354bool QQuickVirtualKeyboardSettings::isDefaultDictionaryDisabled() const
355{
356 return Settings::instance()->isDefaultDictionaryDisabled();
357}
358
359void QQuickVirtualKeyboardSettings::setDefaultDictionaryDisabled(bool defaultDictionaryDisabled)
360{
361 return Settings::instance()->setDefaultDictionaryDisabled(defaultDictionaryDisabled);
362}
363
364QtVirtualKeyboard::KeyboardFunctionKeys QQuickVirtualKeyboardSettings::visibleFunctionKeys() const
365{
366 return Settings::instance()->visibleFunctionKeys();
367}
368
369void QQuickVirtualKeyboardSettings::setVisibleFunctionKeys(QtVirtualKeyboard::KeyboardFunctionKeys newVisibleFunctionKeys)
370{
371 Settings::instance()->setVisibleFunctionKeys(newVisibleFunctionKeys);
372}
373
374void QQuickVirtualKeyboardSettings::resetStyle()
375{
376 Q_D(QQuickVirtualKeyboardSettings);
377 Settings *settings = Settings::instance();
378 QString styleName = QLatin1String(QT_VIRTUALKEYBOARD_DEFAULT_STYLE);
379 QString style = d->stylePath(name: styleName);
380 QString customStyleName = QString::fromLatin1(ba: qgetenv(varName: "QT_VIRTUALKEYBOARD_STYLE"));
381 if (!customStyleName.isEmpty()) {
382 bool found = false;
383 QRegularExpression styleNameValidator(QLatin1String("\\A(?:\\w+)\\z"));
384 QRegularExpressionMatch match = styleNameValidator.match(subject: customStyleName);
385 if (match.hasMatch()) {
386 QString customStyle = d->stylePath(name: customStyleName);
387 if (!customStyle.isEmpty()) {
388 styleName = customStyleName;
389 style = customStyle;
390 found = true;
391 }
392 }
393 if (!found) {
394 qWarning() << "WARNING: Cannot find style" << customStyleName << "- fallback:" << styleName;
395 }
396 }
397 if (!style.isEmpty()) {
398 settings->setStyleName(styleName);
399 settings->setStyle(style);
400 }
401}
402
403/*!
404 \qmlproperty string VirtualKeyboardSettings::style
405 \internal
406*/
407
408/*!
409 \qmlproperty string VirtualKeyboardSettings::styleName
410
411 This property provides the current style. Application can change
412 the keyboard style by setting the styleName to different value.
413
414 The system wide keyboard style can be affected by setting
415 the QT_VIRTUALKEYBOARD_STYLE environment variable.
416*/
417
418/*!
419 \qmlproperty string VirtualKeyboardSettings::locale
420 \since QtQuick.VirtualKeyboard.Settings 2.0
421
422 This property provides the default locale for the keyboard.
423
424 When the locale is not specified, the default system locale is used instead.
425
426 If the keyboard locale is different from the new default locale, keyboard
427 language is changed immediately to reflect the new locale. If the locale setting
428 is incorrect, or it is not in the list of supported locales, it is ignored and
429 the default setting is used instead.
430
431 A locale is supported if it is included in the list of availableLocales.
432*/
433
434/*!
435 \qmlproperty list<string> VirtualKeyboardSettings::availableLocales
436 \since QtQuick.VirtualKeyboard.Settings 2.0
437 \readonly
438
439 This property contains a list of languages supported by the virtual keyboard.
440
441 This list is read-only and depends on the build-time configuration of the
442 virtual keyboard.
443*/
444
445/*!
446 \qmlproperty list<string> VirtualKeyboardSettings::activeLocales
447 \since QtQuick.VirtualKeyboard.Settings 2.0
448
449 This property contains a list of activated languages of the virtual keyboard.
450
451 The list of active languages is a subset of the available languages, and can be
452 used to limit the list of available languages in the application lifetime.
453
454 The list of languages will be shown based on the specified ordering.
455*/
456
457/*!
458 \qmlproperty bool VirtualKeyboardSettings::fullScreenMode
459 \since QtQuick.VirtualKeyboard.Settings 2.2
460
461 This property enables the fullscreen mode for the virtual keyboard.
462
463 In fullscreen mode, the virtual keyboard replicates the contents of the
464 focused input field to the fullscreen input field located at the top of the
465 keyboard.
466
467 For example, to activate the fullscreen mode when the screen aspect ratio
468 is greater than 16:9:
469
470 \code
471 Binding {
472 target: VirtualKeyboardSettings
473 property: "fullScreenMode"
474 value: (Screen.width / Screen.height) > (16.0 / 9.0)
475 }
476 \endcode
477*/
478
479/*!
480 \qmlproperty bool VirtualKeyboardSettings::userDataPath
481 \since QtQuick.VirtualKeyboard.Settings 6.1
482
483 This property sets the user data path for the virtual keyboard and its plugins.
484
485 By default, the user data path is set to \l {QStandardPaths::GenericConfigLocation}{GenericConfigLocation} + "/qtvirtualkeyboard".
486*/
487
488/*!
489 \qmlsignal VirtualKeyboardSettings::userDataReset()
490
491 The application triggers this signal prior to the user's data being reset to
492 indicate to the virtual keyboard that all files must be closed
493 in the user data directory.
494*/
495
496/*!
497 \qmlproperty bool VirtualKeyboardSettings::hwrTimeoutForAlphabetic
498 \since QtQuick.VirtualKeyboard.Settings 6.1
499
500 This property sets the handwriting recognition timeout for alphabetical languages.
501
502 By default, the timeout is 500 millliseconds.
503*/
504
505/*!
506 \qmlproperty bool VirtualKeyboardSettings::hwrTimeoutForCjk
507 \since QtQuick.VirtualKeyboard.Settings 6.1
508
509 This property sets the handwriting recognition timeout for Chinese / Japanese / Korean languages.
510
511 By default, the timeout is 500 millliseconds.
512*/
513
514/*!
515 \qmlproperty int VirtualKeyboardSettings::inputMethodHints
516 \since QtQuick.VirtualKeyboard.Settings 6.1
517
518 This property allows to set persistent input method hints.
519
520 The value of this property is combined with the input method
521 hints from the input control. For example, to disable predictive
522 text input, this property can be set to \c Qt::ImhNoPredictiveText.
523*/
524
525/*!
526 \qmlproperty bool VirtualKeyboardSettings::handwritingModeDisabled
527 \since QtQuick.VirtualKeyboard.Settings 6.1
528
529 This property allows to disable handwriting input mode, if it is
530 otherwise available in the system.
531
532 When this property is set to \c true, the handwriting button is hidden
533 from the keyboard layout and the user cannot switch to handwriting
534 input mode.
535*/
536
537/*!
538 \qmlproperty bool VirtualKeyboardSettings::defaultInputMethodDisabled
539 \since QtQuick.VirtualKeyboard.Settings 6.1
540
541 This property disables the default input method. The purpose of this setting is to be able to
542 override the default input method with the plain input method, disabling its functionality.
543*/
544
545/*!
546 \qmlproperty bool VirtualKeyboardSettings::defaultDictionaryDisabled
547 \since QtQuick.VirtualKeyboard.Settings 6.1
548
549 This property disables the default dictionary. The purpose of this setting is to be able to
550 use a custom dictionary only instead of the standard dictionary.
551*/
552
553/*!
554 \qmlproperty enumeration VirtualKeyboardSettings::visibleFunctionKeys
555 \since QtQuick.VirtualKeyboard.Settings 6.6
556
557 This setting adjusts the visibility of specific function keys in the keyboard layout, allowing
558 them to be either displayed or hidden. When a function key is not visible, its functionality
559 remains accessible through the gear menu.
560
561 The value can be combination of the following flags:
562
563 \list
564 \li \c QtVirtualKeyboard.KeyboardFunctionKeys.None All function keys are hidden
565 \li \c QtVirtualKeyboard.KeyboardFunctionKeys.Hide Hide function key is visible
566 \li \c QtVirtualKeyboard.KeyboardFunctionKeys.Language Language function key is visible
567 \li \c QtVirtualKeyboard.KeyboardFunctionKeys.All All function keys are visible
568 \endlist
569
570 The default is \c QtVirtualKeyboard.KeyboardFunctionKeys.All.
571*/
572
573/*!
574 \since QtQuick.VirtualKeyboard.Settings 2.2
575 \qmlproperty int VirtualKeyboardSettings::wordCandidateList.autoHideDelay
576 \qmlproperty bool VirtualKeyboardSettings::wordCandidateList.alwaysVisible
577
578 \table
579 \header
580 \li Name
581 \li Description
582 \row
583 \li autoHideDelay
584 \li This property defines the delay, in milliseconds, after which the
585 word candidate list is hidden if empty.
586
587 If the value is \c 0, the list is immediately hidden when cleared.
588
589 If the value is \c -1, the list is visible until input focus
590 changes, or the input panel is hidden.
591
592 The default value is \c 5000 milliseconds.
593 \row
594 \li alwaysVisible
595 \li This property defines whether the word candidate list should always
596 remain visible.
597
598 The default value is \c false.
599 \row
600 \li autoCommitWord
601 \li This property enables the automatic commit feature that is activated
602 when the word candidate list is narrowed down to a single candidate.
603
604 The automatic commit feature takes effect when the word candidate
605 list initially contains multiple words and is reduced to single word
606 after additional input. This word will be selected and committed
607 automatically without user interaction.
608
609 This property is set to \c false by default.
610 \endtable
611*/
612
613QQuickWordCandidateListSettings::QQuickWordCandidateListSettings(QObject *parent) :
614 QObject(parent)
615{
616}
617
618int QQuickWordCandidateListSettings::autoHideDelay() const
619{
620 return Settings::instance()->wclAutoHideDelay();
621}
622
623void QQuickWordCandidateListSettings::setAutoHideDelay(int autoHideDelay)
624{
625 Settings::instance()->setWclAutoHideDelay(autoHideDelay);
626}
627
628bool QQuickWordCandidateListSettings::alwaysVisible() const
629{
630 return Settings::instance()->wclAlwaysVisible();
631}
632
633void QQuickWordCandidateListSettings::setAlwaysVisible(bool alwaysVisible)
634{
635 Settings::instance()->setWclAlwaysVisible(alwaysVisible);
636}
637
638bool QQuickWordCandidateListSettings::autoCommitWord() const
639{
640 return Settings::instance()->wclAutoCommitWord();
641}
642
643void QQuickWordCandidateListSettings::setAutoCommitWord(bool autoCommitWord)
644{
645 Settings::instance()->setWclAutoCommitWord(autoCommitWord);
646}
647
648} // namespace QtVirtualKeyboard
649QT_END_NAMESPACE
650

source code of qtvirtualkeyboard/src/settings/qquickvirtualkeyboardsettings.cpp