VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/softkeyboard/UISoftKeyboard.cpp@ 82781

Last change on this file since 82781 was 82605, checked in by vboxsync, 4 years ago

FE/Qt: Dealing with todo's mentioned r135326. Part 1.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 148.0 KB
Line 
1/* $Id: UISoftKeyboard.cpp 82605 2019-12-17 12:32:26Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UISoftKeyboard class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QApplication>
20#include <QCheckBox>
21#include <QColorDialog>
22#include <QComboBox>
23#include <QDir>
24#include <QFile>
25#include <QGroupBox>
26#include <QInputDialog>
27#include <QHeaderView>
28#include <QLabel>
29#include <QLineEdit>
30#include <QListWidget>
31#include <QPainter>
32#include <QPicture>
33#include <QPushButton>
34#include <QSplitter>
35#include <QStatusBar>
36#include <QStyle>
37#include <QStackedWidget>
38#include <QTableWidget>
39#include <QToolButton>
40#include <QXmlStreamReader>
41#include <QVBoxLayout>
42
43/* GUI includes: */
44#include "UIDesktopWidgetWatchdog.h"
45#include "UIExtraDataManager.h"
46#include "UIIconPool.h"
47#include "UIMessageCenter.h"
48#include "UIModalWindowManager.h"
49#include "UISession.h"
50#include "UISoftKeyboard.h"
51#include "UICommon.h"
52#ifdef VBOX_WS_MAC
53# include "VBoxUtils-darwin.h"
54#endif
55
56/* External includes: */
57# include <math.h>
58
59/* Forward declarations: */
60class UISoftKeyboardColorButton;
61class UISoftKeyboardLayout;
62class UISoftKeyboardRow;
63class UISoftKeyboardWidget;
64
65const int iMessageTimeout = 3000;
66/** Key position are used to identify respective keys. */
67const int iCapsLockPosition = 30;
68const int iNumLockPosition = 90;
69const int iScrollLockPosition = 125;
70
71/** Set a generous file size limit. */
72const qint64 iFileSizeLimit = _256K;
73const QString strSubDirectorName("keyboardLayouts");
74
75/** Name, background color, normal font color, hover color, edited button background color, pressed button font color. */
76const char* predefinedColorThemes[][6] = {{"Clear Night","#000000", "#ffffff", "#859900", "#9b6767", "#000000"},
77 {"Gobi Dark","#002b36", "#fdf6e3", "#859900", "#cb4b16", "#002b36"},
78 {"Gobi Light","#fdf6e3", "#002b36", "#2aa198", "#cb4b16", "#bf4040"},
79 {0, 0, 0, 0, 0, 0}};
80
81typedef QPair<QLabel*, UISoftKeyboardColorButton*> ColorSelectLabelButton;
82
83enum KeyState
84{
85 KeyState_NotPressed,
86 KeyState_Pressed,
87 KeyState_Locked,
88 KeyState_Max
89};
90
91enum KeyType
92{
93 /** Can be in KeyState_NotPressed and KeyState_Pressed states. */
94 KeyType_Ordinary,
95 /** e.g. CapsLock, NumLock. Can be only in KeyState_NotPressed, KeyState_Locked */
96 KeyType_Lock,
97 /** e.g. Shift Can be in all 3 states*/
98 KeyType_Modifier,
99 KeyType_Max
100};
101
102enum KeyboardColorType
103{
104 KeyboardColorType_Background = 0,
105 KeyboardColorType_Font,
106 KeyboardColorType_Hover,
107 KeyboardColorType_Edit,
108 KeyboardColorType_Pressed,
109 KeyboardColorType_Max
110};
111
112enum KeyboardRegion
113{
114 KeyboardRegion_Main = 0,
115 KeyboardRegion_NumPad,
116 KeyboardRegion_MultimediaKeys,
117 KeyboardRegion_Max
118};
119
120struct UIKeyCaptions
121{
122 UIKeyCaptions(const QString &strBase, const QString &strShift,
123 const QString &strAltGr, const QString &strShiftAltGr)
124 : m_strBase(strBase)
125 , m_strShift(strShift)
126 , m_strAltGr(strAltGr)
127 , m_strShiftAltGr(strShiftAltGr)
128 {
129 m_strBase.replace("\\n", "\n");
130 m_strShift.replace("\\n", "\n");
131 m_strAltGr.replace("\\n", "\n");
132 m_strShiftAltGr.replace("\\n", "\n");
133 }
134 UIKeyCaptions(){}
135 bool operator==(const UIKeyCaptions &other) const
136 {
137 return (m_strBase == other.m_strBase &&
138 m_strShift == other.m_strShift &&
139 m_strAltGr == other.m_strAltGr &&
140 m_strShiftAltGr == other.m_strShiftAltGr);
141 }
142 QString m_strBase;
143 QString m_strShift;
144 QString m_strAltGr;
145 QString m_strShiftAltGr;
146};
147
148/** Returns a QPointF which lies on the line [p0, p1] and with a distance @p fDistance to p0. */
149QPointF pointInBetween(qreal fDistance, const QPointF &p0, const QPointF &p1)
150{
151 QPointF vectorP0P1 = p1 - p0;
152 qreal length = sqrt(vectorP0P1.x() * vectorP0P1.x() + vectorP0P1.y() * vectorP0P1.y());
153 if (length == 0)
154 return QPointF();
155 /* Normalize the vector and add it to starting point: */
156 vectorP0P1 = (fDistance / length) * vectorP0P1 + p0;
157 return vectorP0P1;
158}
159
160
161/*********************************************************************************************************************************
162* UISoftKeyboardColorButton definition. *
163*********************************************************************************************************************************/
164
165class UISoftKeyboardColorButton : public QPushButton
166{
167 Q_OBJECT;
168
169public:
170
171 UISoftKeyboardColorButton(KeyboardColorType enmColorType, QWidget *pParent = 0);
172 KeyboardColorType colorType() const;
173
174public:
175
176 KeyboardColorType m_enmColorType;
177};
178
179
180/*********************************************************************************************************************************
181* UISoftKeyboardPhysicalLayout definition. *
182*********************************************************************************************************************************/
183
184/** This class is used to represent the physical layout of a keyboard (in contrast to UISoftKeyboardLayout).
185 * Physical layouts are read from an xml file where keys are placed in rows. Each UISoftKeyboardLayout must refer to a
186 * refer to a UISoftKeyboardPhysicalLayout instance. An example of an UISoftKeyboardPhysicalLayout instance is 103 key ISO layout.*/
187class UISoftKeyboardPhysicalLayout
188{
189
190public:
191 UISoftKeyboardPhysicalLayout();
192
193 void setName(const QString &strName);
194 const QString &name() const;
195
196 void setFileName(const QString &strName);
197 const QString &fileName() const;
198
199 void setUid(const QUuid &uid);
200 const QUuid &uid() const;
201
202 const QVector<UISoftKeyboardRow> &rows() const;
203 QVector<UISoftKeyboardRow> &rows();
204
205 void setLockKey(int iKeyPosition, UISoftKeyboardKey *pKey);
206 void updateLockKeyStates(bool fCapsLockState, bool fNumLockState, bool fScrollLockState);
207 void reset();
208
209 void setDefaultKeyWidth(int iDefaultKeyWidth);
210 int defaultKeyWidth() const;
211
212 /** Returns the sum totalHeight() of all rows(). */
213 int totalHeight() const;
214
215private:
216
217 void updateLockKeyState(bool fLockState, UISoftKeyboardKey *pKey);
218 QString m_strFileName;
219 QUuid m_uId;
220 QString m_strName;
221 QVector<UISoftKeyboardRow> m_rows;
222 int m_iDefaultKeyWidth;
223 /** Scroll, Num, and Caps Lock keys' states are updated thru some API events. Thus we keep their pointers in a containter. */
224 QMap<int, UISoftKeyboardKey*> m_lockKeys;
225};
226
227/*********************************************************************************************************************************
228* UIKeyboardLayoutEditor definition. *
229*********************************************************************************************************************************/
230
231/** A QWidget extension thru which we can edit key captions, the physical layout of the keyboard, name of the layout etc. */
232class UIKeyboardLayoutEditor : public QIWithRetranslateUI<QWidget>
233{
234 Q_OBJECT;
235
236signals:
237
238 void sigLayoutEdited();
239 void sigUIKeyCaptionsEdited(UISoftKeyboardKey* pKey);
240 void sigGoBackButton();
241
242public:
243
244 UIKeyboardLayoutEditor(QWidget *pParent = 0);
245 void setKey(UISoftKeyboardKey *pKey);
246 void setLayoutToEdit(UISoftKeyboardLayout *pLayout);
247 void setPhysicalLayoutList(const QVector<UISoftKeyboardPhysicalLayout> &physicalLayouts);
248 void reset();
249
250protected:
251
252 virtual void retranslateUi() /* override */;
253
254private slots:
255
256 void sltCaptionsUpdate();
257 void sltPhysicalLayoutChanged();
258 void sltLayoutNameChanged(const QString &strCaption);
259 void sltLayoutNativeNameChanged(const QString &strCaption);
260
261private:
262
263 void prepareObjects();
264 void prepareConnections();
265 QWidget *prepareKeyCaptionEditWidgets();
266 void resetKeyWidgets();
267 QGridLayout *m_pEditorLayout;
268 QToolButton *m_pGoBackButton;
269 QGroupBox *m_pSelectedKeyGroupBox;
270 QGroupBox *m_pCaptionEditGroupBox;
271 QComboBox *m_pPhysicalLayoutCombo;
272 QLabel *m_pTitleLabel;
273 QLabel *m_pPhysicalLayoutLabel;
274 QLabel *m_pLayoutNameLabel;
275 QLabel *m_pLayoutNativeNameLabel;
276 QLabel *m_pScanCodeLabel;
277 QLabel *m_pPositionLabel;
278 QLabel *m_pBaseCaptionLabel;
279 QLabel *m_pShiftCaptionLabel;
280 QLabel *m_pAltGrCaptionLabel;
281 QLabel *m_pShiftAltGrCaptionLabel;
282 QLineEdit *m_pLayoutNameEdit;
283 QLineEdit *m_pLayoutNativeNameEdit;
284 QLineEdit *m_pScanCodeEdit;
285 QLineEdit *m_pPositionEdit;
286 QLineEdit *m_pBaseCaptionEdit;
287 QLineEdit *m_pShiftCaptionEdit;
288 QLineEdit *m_pAltGrCaptionEdit;
289 QLineEdit *m_pShiftAltGrCaptionEdit;
290
291 /** The key which is being currently edited. Might be Null. */
292 UISoftKeyboardKey *m_pKey;
293 /** The layout which is being currently edited. */
294 UISoftKeyboardLayout *m_pLayout;
295};
296
297/*********************************************************************************************************************************
298* UILayoutSelector definition. *
299*********************************************************************************************************************************/
300
301class UILayoutSelector : public QIWithRetranslateUI<QWidget>
302{
303
304 Q_OBJECT;
305
306signals:
307
308 void sigSaveLayout();
309 void sigCopyLayout();
310 void sigDeleteLayout();
311 void sigLayoutSelectionChanged(const QUuid &strSelectedLayoutUid);
312 void sigShowLayoutEditor();
313 void sigCloseLayoutList();
314
315public:
316
317 UILayoutSelector(QWidget *pParent = 0);
318 void setLayoutList(const QStringList &layoutNames, QList<QUuid> layoutIdList);
319 void setCurrentLayout(const QUuid &layoutUid);
320 void setCurrentLayoutIsEditable(bool fEditable);
321
322protected:
323
324 virtual void retranslateUi() /* override */;
325
326private slots:
327
328 void sltCurrentItemChanged(QListWidgetItem *pCurrent, QListWidgetItem *pPrevious);
329
330private:
331
332 void prepareObjects();
333
334 QListWidget *m_pLayoutListWidget;
335 QToolButton *m_pApplyLayoutButton;
336 QToolButton *m_pEditLayoutButton;
337 QToolButton *m_pCopyLayoutButton;
338 QToolButton *m_pSaveLayoutButton;
339 QToolButton *m_pDeleteLayoutButton;
340 QLabel *m_pTitleLabel;
341 QToolButton *m_pCloseButton;
342};
343
344/*********************************************************************************************************************************
345* UISoftKeyboardRow definition. *
346*********************************************************************************************************************************/
347
348/** UISoftKeyboardRow represents a row in the physical keyboard. The rows are read from a physical layout file and contained
349 * keys are added to rows in the order they appear in that file.*/
350class UISoftKeyboardRow
351{
352
353public:
354
355 UISoftKeyboardRow();
356
357 void setDefaultWidth(int iWidth);
358 int defaultWidth() const;
359
360 void setDefaultHeight(int iHeight);
361 int defaultHeight() const;
362
363 /* Return the sum of the maximum key height and m_iSpaceHeightAfter */
364 int totalHeight() const;
365
366 QVector<UISoftKeyboardKey> &keys();
367 const QVector<UISoftKeyboardKey> &keys() const;
368
369 void setSpaceHeightAfter(int iSpace);
370 int spaceHeightAfter() const;
371
372 int leftMargin() const;
373 void setLeftMargin(int iMargin);
374
375private:
376
377 /** Default width and height might be inherited from the layout and overwritten in row settings. */
378 int m_iDefaultWidth;
379 int m_iDefaultHeight;
380
381 QVector<UISoftKeyboardKey> m_keys;
382 int m_iSpaceHeightAfter;
383 /* The width of the empty space before the 1st key. */
384 int m_iLeftMargin;
385};
386
387/*********************************************************************************************************************************
388* UISoftKeyboardKey definition. *
389*********************************************************************************************************************************/
390
391/** UISoftKeyboardKey is a place holder for a keyboard key. Graphical key represantations are drawn according to this class.
392 * The position of a key within the physical layout is read from the layout file. Note that UISoftKeyboardKey usually does not have
393 * caption field(s). Captions are kept by UISoftKeyboardLayout since same keys may (and usually do) have different captions in
394 * different layouts. So called static captions are exections. They are defined in physical layout files and kept as member of
395 * UISoftKeyboardKey. When a static caption exits captions (if any) from the keyboard layout files are ignored. */
396class UISoftKeyboardKey
397{
398public:
399
400 UISoftKeyboardKey();
401
402 const QRect keyGeometry() const;
403 void setKeyGeometry(const QRect &rect);
404
405 void setWidth(int iWidth);
406 int width() const;
407
408 void setHeight(int iHeight);
409 int height() const;
410
411 void setScanCode(LONG scanCode);
412 LONG scanCode() const;
413
414 void addScanCodePrefix(LONG scanCode);
415
416 void setUsageId(LONG usageId);
417 void setUsagePage(LONG usagePage);
418 QPair<LONG, LONG> usagePageIdPair() const;
419
420 void setSpaceWidthAfter(int iSpace);
421 int spaceWidthAfter() const;
422
423 void setPosition(int iPosition);
424 int position() const;
425
426 void setType(KeyType enmType);
427 KeyType type() const;
428
429 KeyboardRegion keyboardRegion() const;
430 void setKeyboardRegion(KeyboardRegion enmRegion);
431
432 void setCutout(int iCorner, int iWidth, int iHeight);
433
434 KeyState state() const;
435 void setState(KeyState state);
436
437 void setStaticCaption(const QString &strCaption);
438 const QString &staticCaption() const;
439
440 void setParentWidget(UISoftKeyboardWidget* pParent);
441 QVector<LONG> scanCodeWithPrefix() const;
442
443 void setIsOSMenuKey(bool fFlag);
444 bool isOSMenuKey() const;
445
446 void release();
447 void press();
448
449 void setPoints(const QVector<QPointF> &points);
450 const QVector<QPointF> &points() const;
451 const QPainterPath &painterPath() const;
452
453
454 void setCornerRadius(float fCornerRadius);
455
456 QPolygonF polygonInGlobal() const;
457
458 int cutoutCorner() const;
459 int cutoutWidth() const;
460 int cutoutHeight() const;
461
462 void updateLockState(bool fLocked);
463 void reset();
464
465private:
466
467 void updateState(bool fPressed);
468 /** Creates a path out of points m_points with rounded corners. */
469 void computePainterPath();
470
471 QRect m_keyGeometry;
472 /** Stores the key points (vertices) in local coordinates. */
473 QVector<QPointF> m_points;
474 /** We cache the path since re-computing that at each draw is meaningless. */
475 QPainterPath m_painterPath;
476 KeyType m_enmType;
477 KeyState m_enmState;
478 /** Key width as it is read from the xml file. */
479 int m_iWidth;
480 /** Key height as it is read from the xml file. */
481 int m_iHeight;
482 int m_iSpaceWidthAfter;
483 LONG m_scanCode;
484 QVector<LONG> m_scanCodePrefix;
485
486 /** @name Cutouts are used to create non-rectangle keys polygons.
487 * @{ */
488 int m_iCutoutWidth;
489 int m_iCutoutHeight;
490 /** -1 is for no cutout. 0 is the topleft, 2 is the top right and so on. */
491 int m_iCutoutCorner;
492 /** @} */
493
494 /** Key's position in the layout. */
495 int m_iPosition;
496 UISoftKeyboardWidget *m_pParentWidget;
497 LONG m_iUsageId;
498 LONG m_iUsagePage;
499 KeyboardRegion m_enmKeyboardRegion;
500 /** This is used for multimedia keys, OS key etc where we want to have a non-modifiable
501 * caption (usually a single char). This caption is defined in the physical layout file
502 * and has precedence over the captions defined in keyboard layout files. */
503 QString m_strStaticCaption;
504 bool m_fIsOSMenuKey;
505 double m_fCornerRadius;
506};
507
508
509/*********************************************************************************************************************************
510* UISoftKeyboardLayout definition. *
511*********************************************************************************************************************************/
512/** UISoftKeyboardLayout represents mainly a set of captions for the keys. It refers to a phsical layout which defines the
513 * positioning and number of keys (alongside with scan codes etc.). UISoftKeyboardLayout instances are read from xml files. An
514 * example for UISoftKeyboardLayout instance is 'US International' keyboard layout. */
515class UISoftKeyboardLayout
516{
517
518public:
519
520 UISoftKeyboardLayout();
521
522 void setName(const QString &strName);
523 const QString &name() const;
524
525 void setNativeName(const QString &strLocaName);
526 const QString &nativeName() const;
527
528 /** Combines name and native name and returns the string. */
529 QString nameString() const;
530
531 void setSourceFilePath(const QString& strSourceFilePath);
532 const QString& sourceFilePath() const;
533
534 void setIsFromResources(bool fIsFromResources);
535 bool isFromResources() const;
536
537 void setEditable(bool fEditable);
538 bool editable() const;
539
540 void setPhysicalLayoutUuid(const QUuid &uuid);
541 const QUuid &physicalLayoutUuid() const;
542
543 void addOrUpdateUIKeyCaptions(int iKeyPosition, const UIKeyCaptions &keyCaptions);
544 UIKeyCaptions keyCaptions(int iKeyPosition) const;
545
546 bool operator==(const UISoftKeyboardLayout &otherLayout) const;
547
548 QString baseCaption(int iKeyPosition) const;
549 QString shiftCaption(int iKeyPosition) const;
550
551 QString altGrCaption(int iKeyPosition) const;
552 QString shiftAltGrCaption(int iKeyPosition) const;
553
554 void setEditedBuNotSaved(bool fEditedButNotsaved);
555 bool editedButNotSaved() const;
556
557 void setUid(const QUuid &uid);
558 QUuid uid() const;
559
560 void drawTextInRect(const UISoftKeyboardKey &key, QPainter &painter);
561
562private:
563
564 QMap<int, UIKeyCaptions> m_keyCaptionsMap;
565 /** Caching the font sizes we used for font rendering since it is not a very cheap process to compute these. */
566 QMap<int, int> m_keyCaptionsFontSizeMap;
567 /** The UUID of the physical layout used by this layout. */
568 QUuid m_physicalLayoutUuid;
569 /** This is the English name of the layout. */
570 QString m_strName;
571 QString m_strNativeName;
572 QString m_strSourceFilePath;
573 bool m_fEditable;
574 bool m_fIsFromResources;
575 bool m_fEditedButNotSaved;
576 QUuid m_uid;
577};
578
579/*********************************************************************************************************************************
580* UISoftKeyboardColorTheme definition. *
581*********************************************************************************************************************************/
582
583class UISoftKeyboardColorTheme
584{
585
586public:
587
588 UISoftKeyboardColorTheme();
589 UISoftKeyboardColorTheme(const QString &strName,
590 const QString &strBackgroundColor,
591 const QString &strNormalFontColor,
592 const QString &strHoverColor,
593 const QString &strEditedButtonBackgroundColor,
594 const QString &strPressedButtonFontColor);
595
596 void setColor(KeyboardColorType enmColorType, const QColor &color);
597 QColor color(KeyboardColorType enmColorType) const;
598 QStringList colorsToStringList() const;
599 void colorsFromStringList(const QStringList &colorStringList);
600
601 const QString &name() const;
602 void setName(const QString &strName);
603
604 bool isEditable() const;
605 void setIsEditable(bool fIsEditable);
606
607private:
608
609 QVector<QColor> m_colors;
610 QString m_strName;
611 bool m_fIsEditable;
612};
613
614/*********************************************************************************************************************************
615* UISoftKeyboardWidget definition. *
616*********************************************************************************************************************************/
617
618/** The container widget for keyboard keys. It also handles all the keyboard related events. paintEvent of this class
619 * handles drawing of the soft keyboard. */
620class UISoftKeyboardWidget : public QIWithRetranslateUI<QWidget>
621{
622 Q_OBJECT;
623
624 enum Mode
625 {
626 Mode_LayoutEdit,
627 Mode_Keyboard,
628 Mode_Max
629 };
630
631signals:
632
633 void sigStatusBarMessage(const QString &strMessage);
634 void sigPutKeyboardSequence(QVector<LONG> sequence);
635 void sigPutUsageCodesPress(QVector<QPair<LONG, LONG> > sequence);
636 void sigPutUsageCodesRelease(QVector<QPair<LONG, LONG> > sequence);
637 void sigCurrentLayoutChange();
638 void sigKeyToEdit(UISoftKeyboardKey* pKey);
639 void sigCurrentColorThemeChanged();
640
641public:
642
643 UISoftKeyboardWidget(QWidget *pParent = 0);
644
645 virtual QSize minimumSizeHint() const /* override */;
646 virtual QSize sizeHint() const /* override */;
647 void keyStateChange(UISoftKeyboardKey* pKey);
648 void loadLayouts();
649
650 void setCurrentLayout(const QUuid &layoutUid);
651 UISoftKeyboardLayout *currentLayout();
652
653 QStringList layoutNameList() const;
654 QList<QUuid> layoutUidList() const;
655 const QVector<UISoftKeyboardPhysicalLayout> &physicalLayouts() const;
656 void deleteCurrentLayout();
657 void toggleEditMode(bool fIsEditMode);
658
659 void saveCurentLayoutToFile();
660 void copyCurentLayout();
661 float layoutAspectRatio();
662
663 bool hideOSMenuKeys() const;
664 void setHideOSMenuKeys(bool fHide);
665
666 bool hideNumPad() const;
667 void setHideNumPad(bool fHide);
668
669 bool hideMultimediaKeys() const;
670 void setHideMultimediaKeys(bool fHide);
671
672 QColor color(KeyboardColorType enmColorType) const;
673 void setColor(KeyboardColorType ennmColorType, const QColor &color);
674
675 QStringList colorsToStringList(const QString &strColorThemeName);
676 void colorsFromStringList(const QString &strColorThemeName, const QStringList &colorStringList);
677
678 /** Unlike modifier and ordinary keys we update the state of the Lock keys thru event singals we receieve
679 * from the guest OS. Parameter f???State is true if the corresponding key is locked. */
680 void updateLockKeyStates(bool fCapsLockState, bool fNumLockState, bool fScrollLockState);
681 void reset();
682
683 QStringList colorThemeNames() const;
684 QString currentColorThemeName() const;
685 void setColorThemeByName(const QString &strColorThemeName);
686 void parentDialogDeactivated();
687 bool isColorThemeEditable() const;
688 /** Returns a list of layout names that have been edited but not yet saved to a file. */
689 QStringList unsavedLayoutsNameList() const;
690
691protected:
692
693 virtual void paintEvent(QPaintEvent *pEvent) /* override */;
694 virtual void mousePressEvent(QMouseEvent *pEvent) /* override */;
695 virtual void mouseReleaseEvent(QMouseEvent *pEvent) /* override */;
696 virtual void mouseMoveEvent(QMouseEvent *pEvent) /* override */;
697 virtual void retranslateUi() /* override */;
698
699private:
700
701 void addLayout(const UISoftKeyboardLayout &newLayout);
702 void setNewMinimumSize(const QSize &size);
703 void setInitialSize(int iWidth, int iHeight);
704 /** Searches for the key which contains the position of the @p pEvent and returns it if found. */
705 UISoftKeyboardKey *keyUnderMouse(QMouseEvent *pEvent);
706 UISoftKeyboardKey *keyUnderMouse(const QPoint &point);
707 void handleKeyPress(UISoftKeyboardKey *pKey);
708 void handleKeyRelease(UISoftKeyboardKey *pKey);
709 /** Sends usage id/page to API when a modifier key is right clicked. useful for testing and things like
710 * Window key press for start menu opening. This works orthogonal to left clicks.*/
711 void modifierKeyPressRelease(UISoftKeyboardKey *pKey, bool fRelease);
712 bool loadPhysicalLayout(const QString &strLayoutFileName, KeyboardRegion keyboardRegion = KeyboardRegion_Main);
713 bool loadKeyboardLayout(const QString &strLayoutName);
714 void prepareObjects();
715 void prepareColorThemes();
716 UISoftKeyboardPhysicalLayout *findPhysicalLayout(const QUuid &uuid);
717 /** Sets m_pKeyBeingEdited. */
718 void setKeyBeingEdited(UISoftKeyboardKey *pKey);
719 bool layoutByNameExists(const QString &strName) const;
720
721 /** Looks under the default keyboard layout folder and add the file names to the fileList. */
722 void lookAtDefaultLayoutFolder(QStringList &fileList);
723 UISoftKeyboardColorTheme *colorTheme(const QString &strColorThemeName);
724 void showKeyTooltip(UISoftKeyboardKey *pKey);
725
726 UISoftKeyboardKey *m_pKeyUnderMouse;
727 UISoftKeyboardKey *m_pKeyBeingEdited;
728
729 UISoftKeyboardKey *m_pKeyPressed;
730 UISoftKeyboardColorTheme *m_currentColorTheme;
731 QVector<UISoftKeyboardColorTheme> m_colorThemes;
732 QVector<UISoftKeyboardKey*> m_pressedModifiers;
733 QVector<UISoftKeyboardPhysicalLayout> m_physicalLayouts;
734 UISoftKeyboardPhysicalLayout m_numPadLayout;
735 UISoftKeyboardPhysicalLayout m_multiMediaKeysLayout;
736 QMap<QUuid, UISoftKeyboardLayout> m_layouts;
737 QUuid m_uCurrentLayoutId;
738 /** Key is the key position as read from the layout and value is the message we show as mouse hovers over the key. */
739 QMap<int, QString> m_keyTooltips;
740
741 QSize m_minimumSize;
742 float m_fScaleFactorX;
743 float m_fScaleFactorY;
744 int m_iInitialHeight;
745 int m_iInitialWidth;
746 int m_iInitialWidthNoNumPad;
747 int m_iXSpacing;
748 int m_iYSpacing;
749 int m_iLeftMargin;
750 int m_iTopMargin;
751 int m_iRightMargin;
752 int m_iBottomMargin;
753 Mode m_enmMode;
754 bool m_fHideOSMenuKeys;
755 bool m_fHideNumPad;
756 bool m_fHideMultimediaKeys;
757};
758
759/*********************************************************************************************************************************
760* UIPhysicalLayoutReader definition. *
761*********************************************************************************************************************************/
762
763class UIPhysicalLayoutReader
764{
765
766public:
767
768 bool parseXMLFile(const QString &strFileName, UISoftKeyboardPhysicalLayout &physicalLayout);
769 static QVector<QPointF> computeKeyVertices(const UISoftKeyboardKey &key);
770
771private:
772
773 void parseKey(UISoftKeyboardRow &row);
774 void parseRow(int iDefaultWidth, int iDefaultHeight, QVector<UISoftKeyboardRow> &rows);
775 /** Parses the horizontal space between keys. */
776 void parseKeySpace(UISoftKeyboardRow &row);
777 void parseCutout(UISoftKeyboardKey &key);
778
779 QXmlStreamReader m_xmlReader;
780};
781
782/*********************************************************************************************************************************
783* UIKeyboardLayoutReader definition. *
784*********************************************************************************************************************************/
785
786class UIKeyboardLayoutReader
787{
788
789public:
790
791 bool parseFile(const QString &strFileName, UISoftKeyboardLayout &layout);
792
793private:
794
795 void parseKey(UISoftKeyboardLayout &layout);
796 QXmlStreamReader m_xmlReader;
797 /** Map key is the key position and the value is the captions of the key. */
798};
799
800
801/*********************************************************************************************************************************
802* UISoftKeyboardStatusBarWidget definition. *
803*********************************************************************************************************************************/
804
805class UISoftKeyboardStatusBarWidget : public QIWithRetranslateUI<QWidget>
806{
807 Q_OBJECT;
808
809signals:
810
811 void sigShowHideSidePanel();
812 void sigShowSettingWidget();
813 void sigResetKeyboard();
814
815public:
816
817 UISoftKeyboardStatusBarWidget(QWidget *pParent = 0);
818 void updateLayoutNameInStatusBar(const QString &strMessage);
819
820protected:
821
822 virtual void retranslateUi() /* override */;
823
824private:
825
826 void prepareObjects();
827 QToolButton *m_pLayoutListButton;
828 QToolButton *m_pSettingsButton;
829 QToolButton *m_pResetButton;
830 QLabel *m_pMessageLabel;
831};
832
833
834/*********************************************************************************************************************************
835* UISoftKeyboardSettingsWidget definition. *
836*********************************************************************************************************************************/
837
838class UISoftKeyboardSettingsWidget : public QIWithRetranslateUI<QWidget>
839{
840 Q_OBJECT;
841
842signals:
843
844 void sigHideNumPad(bool fHide);
845 void sigHideOSMenuKeys(bool fHide);
846 void sigHideMultimediaKeys(bool fHide);
847 void sigColorCellClicked(int iColorRow);
848 void sigCloseSettingsWidget();
849 void sigColorThemeSelectionChanged(const QString &strColorThemeName);
850
851public:
852
853 UISoftKeyboardSettingsWidget(QWidget *pParent = 0);
854 void setHideOSMenuKeys(bool fHide);
855 void setHideNumPad(bool fHide);
856 void setHideMultimediaKeys(bool fHide);
857 void setColorSelectionButtonBackgroundAndTooltip(KeyboardColorType enmColorType, const QColor &color, bool fIsColorEditable);
858 void setColorThemeNames(const QStringList &colorThemeNames);
859 void setCurrentColorThemeName(const QString &strColorThemeName);
860
861protected:
862
863 virtual void retranslateUi() /* override */;
864
865private slots:
866
867 void sltColorSelectionButtonClicked();
868
869private:
870
871 void prepareObjects();
872
873 QCheckBox *m_pHideNumPadCheckBox;
874 QCheckBox *m_pShowOsMenuButtonsCheckBox;
875 QCheckBox *m_pHideMultimediaKeysCheckBox;
876 QGroupBox *m_pColorThemeGroupBox;
877 QComboBox *m_pColorThemeComboBox;
878 QLabel *m_pTitleLabel;
879 QToolButton *m_pCloseButton;
880 QVector<ColorSelectLabelButton> m_colorSelectLabelsButtons;
881};
882
883
884/*********************************************************************************************************************************
885* UISoftKeyboardColorButton implementation. *
886*********************************************************************************************************************************/
887
888
889UISoftKeyboardColorButton::UISoftKeyboardColorButton(KeyboardColorType enmColorType, QWidget *pParent /*= 0 */)
890 :QPushButton(pParent)
891 , m_enmColorType(enmColorType){}
892
893KeyboardColorType UISoftKeyboardColorButton::colorType() const
894{
895 return m_enmColorType;
896}
897
898
899/*********************************************************************************************************************************
900* UISoftKeyboardPhysicalLayout implementation. *
901*********************************************************************************************************************************/
902
903UISoftKeyboardPhysicalLayout::UISoftKeyboardPhysicalLayout()
904 :m_iDefaultKeyWidth(50)
905{
906}
907
908void UISoftKeyboardPhysicalLayout::setName(const QString &strName)
909{
910 m_strName = strName;
911}
912
913const QString &UISoftKeyboardPhysicalLayout::name() const
914{
915 return m_strName;
916}
917
918void UISoftKeyboardPhysicalLayout::setFileName(const QString &strName)
919{
920 m_strFileName = strName;
921}
922
923const QString &UISoftKeyboardPhysicalLayout::fileName() const
924{
925 return m_strFileName;
926}
927
928void UISoftKeyboardPhysicalLayout::setUid(const QUuid &uid)
929{
930 m_uId = uid;
931}
932
933const QUuid &UISoftKeyboardPhysicalLayout::uid() const
934{
935 return m_uId;
936}
937
938const QVector<UISoftKeyboardRow> &UISoftKeyboardPhysicalLayout::rows() const
939{
940 return m_rows;
941}
942
943QVector<UISoftKeyboardRow> &UISoftKeyboardPhysicalLayout::rows()
944{
945 return m_rows;
946}
947
948void UISoftKeyboardPhysicalLayout::setLockKey(int iKeyPosition, UISoftKeyboardKey *pKey)
949{
950 m_lockKeys[iKeyPosition] = pKey;
951}
952
953void UISoftKeyboardPhysicalLayout::updateLockKeyStates(bool fCapsLockState, bool fNumLockState, bool fScrollLockState)
954{
955 updateLockKeyState(fCapsLockState, m_lockKeys.value(iCapsLockPosition, 0));
956 updateLockKeyState(fNumLockState, m_lockKeys.value(iNumLockPosition, 0));
957 updateLockKeyState(fScrollLockState, m_lockKeys.value(iScrollLockPosition, 0));
958}
959
960void UISoftKeyboardPhysicalLayout::setDefaultKeyWidth(int iDefaultKeyWidth)
961{
962 m_iDefaultKeyWidth = iDefaultKeyWidth;
963}
964
965int UISoftKeyboardPhysicalLayout::defaultKeyWidth() const
966{
967 return m_iDefaultKeyWidth;
968}
969
970void UISoftKeyboardPhysicalLayout::reset()
971{
972 for (int i = 0; i < m_rows.size(); ++i)
973 {
974 for (int j = 0; j < m_rows[i].keys().size(); ++j)
975 {
976 m_rows[i].keys()[j].reset();
977 }
978 }
979}
980
981int UISoftKeyboardPhysicalLayout::totalHeight() const
982{
983 int iHeight = 0;
984 for (int i = 0; i < m_rows.size(); ++i)
985 iHeight += m_rows[i].totalHeight();
986 return iHeight;
987}
988
989void UISoftKeyboardPhysicalLayout::updateLockKeyState(bool fLockState, UISoftKeyboardKey *pKey)
990{
991 if (!pKey)
992 return;
993 pKey->updateLockState(fLockState);
994}
995
996/*********************************************************************************************************************************
997* UIKeyboardLayoutEditor implementation. *
998*********************************************************************************************************************************/
999
1000UIKeyboardLayoutEditor::UIKeyboardLayoutEditor(QWidget *pParent /* = 0 */)
1001 :QIWithRetranslateUI<QWidget>(pParent)
1002 , m_pEditorLayout(0)
1003 , m_pGoBackButton(0)
1004 , m_pSelectedKeyGroupBox(0)
1005 , m_pCaptionEditGroupBox(0)
1006 , m_pPhysicalLayoutCombo(0)
1007 , m_pTitleLabel(0)
1008 , m_pPhysicalLayoutLabel(0)
1009 , m_pLayoutNameLabel(0)
1010 , m_pLayoutNativeNameLabel(0)
1011 , m_pScanCodeLabel(0)
1012 , m_pPositionLabel(0)
1013 , m_pBaseCaptionLabel(0)
1014 , m_pShiftCaptionLabel(0)
1015 , m_pAltGrCaptionLabel(0)
1016 , m_pShiftAltGrCaptionLabel(0)
1017 , m_pLayoutNameEdit(0)
1018 , m_pLayoutNativeNameEdit(0)
1019 , m_pScanCodeEdit(0)
1020 , m_pPositionEdit(0)
1021 , m_pBaseCaptionEdit(0)
1022 , m_pShiftCaptionEdit(0)
1023 , m_pAltGrCaptionEdit(0)
1024 , m_pShiftAltGrCaptionEdit(0)
1025 , m_pKey(0)
1026 , m_pLayout(0)
1027{
1028 setAutoFillBackground(true);
1029 prepareObjects();
1030}
1031
1032void UIKeyboardLayoutEditor::setKey(UISoftKeyboardKey *pKey)
1033{
1034 if (m_pKey == pKey || !m_pLayout)
1035 return;
1036 /* First apply the pending changes to the key that has been edited: */
1037 if (m_pKey)
1038 {
1039 UIKeyCaptions captions = m_pLayout->keyCaptions(m_pKey->position());
1040 if (captions.m_strBase != m_pBaseCaptionEdit->text() ||
1041 captions.m_strShift != m_pShiftCaptionEdit->text() ||
1042 captions.m_strAltGr != m_pAltGrCaptionEdit->text() ||
1043 captions.m_strShiftAltGr != m_pShiftAltGrCaptionEdit->text())
1044 m_pLayout->addOrUpdateUIKeyCaptions(m_pKey->position(),
1045 UIKeyCaptions(m_pBaseCaptionEdit->text(),
1046 m_pShiftCaptionEdit->text(),
1047 m_pAltGrCaptionEdit->text(),
1048 m_pShiftAltGrCaptionEdit->text()));
1049 }
1050 m_pKey = pKey;
1051 if (m_pSelectedKeyGroupBox)
1052 m_pSelectedKeyGroupBox->setEnabled(m_pKey);
1053 if (!m_pKey)
1054 {
1055 resetKeyWidgets();
1056 return;
1057 }
1058 if (m_pScanCodeEdit)
1059 m_pScanCodeEdit->setText(QString::number(m_pKey->scanCode(), 16));
1060 if (m_pPositionEdit)
1061 m_pPositionEdit->setText(QString::number(m_pKey->position()));
1062 UIKeyCaptions captions = m_pLayout->keyCaptions(m_pKey->position());
1063 if (m_pBaseCaptionEdit)
1064 m_pBaseCaptionEdit->setText(captions.m_strBase);
1065 if (m_pShiftCaptionEdit)
1066 m_pShiftCaptionEdit->setText(captions.m_strShift);
1067 if (m_pAltGrCaptionEdit)
1068 m_pAltGrCaptionEdit->setText(captions.m_strAltGr);
1069 if (m_pShiftAltGrCaptionEdit)
1070 m_pShiftAltGrCaptionEdit->setText(captions.m_strShiftAltGr);
1071 m_pBaseCaptionEdit->setFocus();
1072}
1073
1074void UIKeyboardLayoutEditor::setLayoutToEdit(UISoftKeyboardLayout *pLayout)
1075{
1076 if (m_pLayout == pLayout)
1077 return;
1078
1079 m_pLayout = pLayout;
1080 if (!m_pLayout)
1081 reset();
1082
1083 if (m_pLayoutNameEdit)
1084 m_pLayoutNameEdit->setText(m_pLayout ? m_pLayout->name() : QString());
1085
1086 if (m_pLayoutNativeNameEdit)
1087 m_pLayoutNativeNameEdit->setText(m_pLayout ? m_pLayout->nativeName() : QString());
1088
1089 if (m_pPhysicalLayoutCombo && m_pLayout)
1090 {
1091 int iIndex = m_pPhysicalLayoutCombo->findData(m_pLayout->physicalLayoutUuid());
1092 if (iIndex != -1)
1093 m_pPhysicalLayoutCombo->setCurrentIndex(iIndex);
1094 }
1095 update();
1096}
1097
1098void UIKeyboardLayoutEditor::setPhysicalLayoutList(const QVector<UISoftKeyboardPhysicalLayout> &physicalLayouts)
1099{
1100 if (!m_pPhysicalLayoutCombo)
1101 return;
1102 m_pPhysicalLayoutCombo->clear();
1103 foreach (const UISoftKeyboardPhysicalLayout &physicalLayout, physicalLayouts)
1104 m_pPhysicalLayoutCombo->addItem(physicalLayout.name(), physicalLayout.uid());
1105}
1106
1107void UIKeyboardLayoutEditor::retranslateUi()
1108{
1109 if (m_pTitleLabel)
1110 m_pTitleLabel->setText(UISoftKeyboard::tr("Layout Editor"));
1111 if (m_pGoBackButton)
1112 {
1113 m_pGoBackButton->setToolTip(UISoftKeyboard::tr("Return Back to Layout List"));
1114 m_pGoBackButton->setText(UISoftKeyboard::tr("Back to Layout List"));
1115 }
1116 if (m_pPhysicalLayoutLabel)
1117 m_pPhysicalLayoutLabel->setText(UISoftKeyboard::tr("Physical Layout"));
1118 if (m_pLayoutNameLabel)
1119 m_pLayoutNameLabel->setText(UISoftKeyboard::tr("English Name"));
1120 if (m_pLayoutNameEdit)
1121 m_pLayoutNameEdit->setToolTip(UISoftKeyboard::tr("Name of the Layout in English"));
1122 if (m_pLayoutNativeNameLabel)
1123 m_pLayoutNativeNameLabel->setText(UISoftKeyboard::tr("Native Language Name"));
1124 if (m_pLayoutNativeNameEdit)
1125 m_pLayoutNativeNameEdit->setToolTip(UISoftKeyboard::tr("Name of the Layout in the native Language"));
1126 if (m_pScanCodeLabel)
1127 m_pScanCodeLabel->setText(UISoftKeyboard::tr("Scan Code"));
1128 if (m_pScanCodeEdit)
1129 m_pScanCodeEdit->setToolTip(UISoftKeyboard::tr("The scan code the key produces. Not editable"));
1130 if (m_pPositionLabel)
1131 m_pPositionLabel->setText(UISoftKeyboard::tr("Position"));
1132 if (m_pPositionEdit)
1133 m_pPositionEdit->setToolTip(UISoftKeyboard::tr("The physical position of the key. Not editable"));
1134 if (m_pBaseCaptionLabel)
1135 m_pBaseCaptionLabel->setText(UISoftKeyboard::tr("Base"));
1136 if (m_pShiftCaptionLabel)
1137 m_pShiftCaptionLabel->setText(UISoftKeyboard::tr("Shift"));
1138 if (m_pAltGrCaptionLabel)
1139 m_pAltGrCaptionLabel->setText(UISoftKeyboard::tr("AltGr"));
1140 if (m_pShiftAltGrCaptionLabel)
1141 m_pShiftAltGrCaptionLabel->setText(UISoftKeyboard::tr("ShiftAltGr"));
1142 if (m_pCaptionEditGroupBox)
1143 m_pCaptionEditGroupBox->setTitle(UISoftKeyboard::tr("Captions"));
1144 if (m_pSelectedKeyGroupBox)
1145 m_pSelectedKeyGroupBox->setTitle(UISoftKeyboard::tr("Selected Key"));
1146}
1147
1148void UIKeyboardLayoutEditor::sltCaptionsUpdate()
1149{
1150 if (!m_pKey || !m_pLayout)
1151 return;
1152 m_pLayout->addOrUpdateUIKeyCaptions(m_pKey->position(),
1153 UIKeyCaptions(m_pBaseCaptionEdit->text(),
1154 m_pShiftCaptionEdit->text(),
1155 m_pAltGrCaptionEdit->text(),
1156 m_pShiftAltGrCaptionEdit->text()));
1157 emit sigUIKeyCaptionsEdited(m_pKey);
1158}
1159
1160void UIKeyboardLayoutEditor::sltPhysicalLayoutChanged()
1161{
1162 if (!m_pPhysicalLayoutCombo || !m_pLayout)
1163 return;
1164 QUuid currentData = m_pPhysicalLayoutCombo->currentData().toUuid();
1165 if (!currentData.isNull())
1166 m_pLayout->setPhysicalLayoutUuid(currentData);
1167 emit sigLayoutEdited();
1168}
1169
1170void UIKeyboardLayoutEditor::sltLayoutNameChanged(const QString &strName)
1171{
1172 if (!m_pLayout || m_pLayout->name() == strName)
1173 return;
1174 m_pLayout->setName(strName);
1175 emit sigLayoutEdited();
1176}
1177
1178void UIKeyboardLayoutEditor::sltLayoutNativeNameChanged(const QString &strNativeName)
1179{
1180 if (!m_pLayout || m_pLayout->nativeName() == strNativeName)
1181 return;
1182 m_pLayout->setNativeName(strNativeName);
1183 emit sigLayoutEdited();
1184}
1185
1186void UIKeyboardLayoutEditor::prepareObjects()
1187{
1188 m_pEditorLayout = new QGridLayout;
1189 if (!m_pEditorLayout)
1190 return;
1191 setLayout(m_pEditorLayout);
1192
1193 QHBoxLayout *pTitleLayout = new QHBoxLayout;
1194 m_pGoBackButton = new QToolButton;
1195 m_pGoBackButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
1196 m_pGoBackButton->setIcon(UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_ArrowBack));
1197 m_pGoBackButton->setAutoRaise(true);
1198 m_pEditorLayout->addWidget(m_pGoBackButton, 0, 0, 1, 1);
1199 connect(m_pGoBackButton, &QToolButton::clicked, this, &UIKeyboardLayoutEditor::sigGoBackButton);
1200 m_pTitleLabel = new QLabel;
1201 pTitleLayout->addWidget(m_pTitleLabel);
1202 pTitleLayout->addStretch(2);
1203 pTitleLayout->addWidget(m_pGoBackButton);
1204 m_pEditorLayout->addLayout(pTitleLayout, 0, 0, 1, 2);
1205
1206 m_pLayoutNativeNameLabel = new QLabel;
1207 m_pLayoutNativeNameEdit = new QLineEdit;
1208 m_pLayoutNativeNameLabel->setBuddy(m_pLayoutNativeNameEdit);
1209 m_pEditorLayout->addWidget(m_pLayoutNativeNameLabel, 2, 0, 1, 1);
1210 m_pEditorLayout->addWidget(m_pLayoutNativeNameEdit, 2, 1, 1, 1);
1211 connect(m_pLayoutNativeNameEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltLayoutNativeNameChanged);
1212
1213 m_pLayoutNameLabel = new QLabel;
1214 m_pLayoutNameEdit = new QLineEdit;
1215 m_pLayoutNameLabel->setBuddy(m_pLayoutNameEdit);
1216 m_pEditorLayout->addWidget(m_pLayoutNameLabel, 3, 0, 1, 1);
1217 m_pEditorLayout->addWidget(m_pLayoutNameEdit, 3, 1, 1, 1);
1218 connect(m_pLayoutNameEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltLayoutNameChanged);
1219
1220
1221 m_pPhysicalLayoutLabel = new QLabel;
1222 m_pPhysicalLayoutCombo = new QComboBox;
1223 m_pPhysicalLayoutLabel->setBuddy(m_pPhysicalLayoutCombo);
1224 m_pEditorLayout->addWidget(m_pPhysicalLayoutLabel, 4, 0, 1, 1);
1225 m_pEditorLayout->addWidget(m_pPhysicalLayoutCombo, 4, 1, 1, 1);
1226 connect(m_pPhysicalLayoutCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
1227 this, &UIKeyboardLayoutEditor::sltPhysicalLayoutChanged);
1228
1229 m_pSelectedKeyGroupBox = new QGroupBox;
1230 m_pSelectedKeyGroupBox->setEnabled(false);
1231
1232 m_pEditorLayout->addWidget(m_pSelectedKeyGroupBox, 5, 0, 1, 2);
1233 QGridLayout *pSelectedKeyLayout = new QGridLayout(m_pSelectedKeyGroupBox);
1234 pSelectedKeyLayout->setSpacing(0);
1235 pSelectedKeyLayout->setContentsMargins(0, 0, 0, 0);
1236
1237 m_pScanCodeLabel = new QLabel;
1238 m_pScanCodeEdit = new QLineEdit;
1239 m_pScanCodeLabel->setBuddy(m_pScanCodeEdit);
1240 m_pScanCodeEdit->setEnabled(false);
1241 pSelectedKeyLayout->addWidget(m_pScanCodeLabel, 0, 0);
1242 pSelectedKeyLayout->addWidget(m_pScanCodeEdit, 0, 1);
1243
1244 m_pPositionLabel= new QLabel;
1245 m_pPositionEdit = new QLineEdit;
1246 m_pPositionEdit->setEnabled(false);
1247 m_pPositionLabel->setBuddy(m_pPositionEdit);
1248 pSelectedKeyLayout->addWidget(m_pPositionLabel, 1, 0);
1249 pSelectedKeyLayout->addWidget(m_pPositionEdit, 1, 1);
1250
1251 QWidget *pCaptionEditor = prepareKeyCaptionEditWidgets();
1252 if (pCaptionEditor)
1253 pSelectedKeyLayout->addWidget(pCaptionEditor, 2, 0, 2, 2);
1254
1255 QSpacerItem *pSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
1256 if (pSpacer)
1257 pSelectedKeyLayout->addItem(pSpacer, 4, 1);
1258
1259 retranslateUi();
1260}
1261
1262QWidget *UIKeyboardLayoutEditor::prepareKeyCaptionEditWidgets()
1263{
1264 m_pCaptionEditGroupBox = new QGroupBox;
1265 if (!m_pCaptionEditGroupBox)
1266 return 0;
1267 m_pCaptionEditGroupBox->setFlat(false);
1268 QGridLayout *pCaptionEditorLayout = new QGridLayout(m_pCaptionEditGroupBox);
1269 pCaptionEditorLayout->setSpacing(0);
1270 pCaptionEditorLayout->setContentsMargins(0, 0, 0, 0);
1271
1272 if (!pCaptionEditorLayout)
1273 return 0;
1274
1275 m_pBaseCaptionLabel = new QLabel;
1276 m_pBaseCaptionEdit = new QLineEdit;
1277 m_pBaseCaptionLabel->setBuddy(m_pBaseCaptionEdit);
1278 pCaptionEditorLayout->addWidget(m_pBaseCaptionLabel, 0, 0);
1279 pCaptionEditorLayout->addWidget(m_pBaseCaptionEdit, 0, 1);
1280 connect(m_pBaseCaptionEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltCaptionsUpdate);
1281
1282 m_pShiftCaptionLabel = new QLabel;
1283 m_pShiftCaptionEdit = new QLineEdit;
1284 m_pShiftCaptionLabel->setBuddy(m_pShiftCaptionEdit);
1285 pCaptionEditorLayout->addWidget(m_pShiftCaptionLabel, 1, 0);
1286 pCaptionEditorLayout->addWidget(m_pShiftCaptionEdit, 1, 1);
1287 connect(m_pShiftCaptionEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltCaptionsUpdate);
1288
1289 m_pAltGrCaptionLabel = new QLabel;
1290 m_pAltGrCaptionEdit = new QLineEdit;
1291 m_pAltGrCaptionLabel->setBuddy(m_pAltGrCaptionEdit);
1292 pCaptionEditorLayout->addWidget(m_pAltGrCaptionLabel, 2, 0);
1293 pCaptionEditorLayout->addWidget(m_pAltGrCaptionEdit, 2, 1);
1294 connect(m_pAltGrCaptionEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltCaptionsUpdate);
1295
1296 m_pShiftAltGrCaptionLabel = new QLabel;
1297 m_pShiftAltGrCaptionEdit = new QLineEdit;
1298 m_pShiftAltGrCaptionLabel->setBuddy(m_pShiftAltGrCaptionEdit);
1299 pCaptionEditorLayout->addWidget(m_pShiftAltGrCaptionLabel, 3, 0);
1300 pCaptionEditorLayout->addWidget(m_pShiftAltGrCaptionEdit, 3, 1);
1301 connect(m_pShiftAltGrCaptionEdit, &QLineEdit::textChanged, this, &UIKeyboardLayoutEditor::sltCaptionsUpdate);
1302
1303 QSpacerItem *pSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
1304 if (pSpacer)
1305 pCaptionEditorLayout->addItem(pSpacer, 4, 1);
1306 return m_pCaptionEditGroupBox;
1307}
1308
1309void UIKeyboardLayoutEditor::reset()
1310{
1311 if (m_pLayoutNameEdit)
1312 m_pLayoutNameEdit->clear();
1313 resetKeyWidgets();
1314}
1315
1316void UIKeyboardLayoutEditor::resetKeyWidgets()
1317{
1318 if (m_pScanCodeEdit)
1319 m_pScanCodeEdit->clear();
1320 if (m_pPositionEdit)
1321 m_pPositionEdit->clear();
1322 if (m_pBaseCaptionEdit)
1323 m_pBaseCaptionEdit->clear();
1324 if (m_pShiftCaptionEdit)
1325 m_pShiftCaptionEdit->clear();
1326 if (m_pAltGrCaptionEdit)
1327 m_pAltGrCaptionEdit->clear();
1328 if (m_pShiftAltGrCaptionEdit)
1329 m_pShiftAltGrCaptionEdit->clear();
1330}
1331
1332/*********************************************************************************************************************************
1333* UILayoutSelector implementation. *
1334*********************************************************************************************************************************/
1335
1336UILayoutSelector::UILayoutSelector(QWidget *pParent /* = 0 */)
1337 :QIWithRetranslateUI<QWidget>(pParent)
1338 , m_pLayoutListWidget(0)
1339 , m_pApplyLayoutButton(0)
1340 , m_pEditLayoutButton(0)
1341 , m_pCopyLayoutButton(0)
1342 , m_pSaveLayoutButton(0)
1343 , m_pDeleteLayoutButton(0)
1344 , m_pTitleLabel(0)
1345 , m_pCloseButton(0)
1346{
1347 prepareObjects();
1348}
1349
1350void UILayoutSelector::setCurrentLayout(const QUuid &layoutUid)
1351{
1352 if (!m_pLayoutListWidget)
1353 return;
1354 if (layoutUid.isNull())
1355 {
1356 m_pLayoutListWidget->selectionModel()->clear();
1357 return;
1358 }
1359 QListWidgetItem *pFoundItem = 0;
1360 for (int i = 0; i < m_pLayoutListWidget->count() && !pFoundItem; ++i)
1361 {
1362 QListWidgetItem *pItem = m_pLayoutListWidget->item(i);
1363 if (!pItem)
1364 continue;
1365 if (pItem->data(Qt::UserRole).toUuid() == layoutUid)
1366 pFoundItem = pItem;
1367 }
1368 if (!pFoundItem)
1369 return;
1370 if (pFoundItem == m_pLayoutListWidget->currentItem())
1371 return;
1372 m_pLayoutListWidget->blockSignals(true);
1373 m_pLayoutListWidget->setCurrentItem(pFoundItem);
1374 m_pLayoutListWidget->blockSignals(false);
1375}
1376
1377void UILayoutSelector::setCurrentLayoutIsEditable(bool fEditable)
1378{
1379 if (m_pEditLayoutButton)
1380 m_pEditLayoutButton->setEnabled(fEditable);
1381 if (m_pSaveLayoutButton)
1382 m_pSaveLayoutButton->setEnabled(fEditable);
1383 if (m_pDeleteLayoutButton)
1384 m_pDeleteLayoutButton->setEnabled(fEditable);
1385}
1386
1387void UILayoutSelector::setLayoutList(const QStringList &layoutNames, QList<QUuid> layoutUidList)
1388{
1389 if (!m_pLayoutListWidget || layoutNames.size() != layoutUidList.size())
1390 return;
1391 QUuid currentItemUid;
1392 if (m_pLayoutListWidget->currentItem())
1393 currentItemUid = m_pLayoutListWidget->currentItem()->data(Qt::UserRole).toUuid();
1394 m_pLayoutListWidget->blockSignals(true);
1395 m_pLayoutListWidget->clear();
1396 for (int i = 0; i < layoutNames.size(); ++i)
1397 {
1398 QListWidgetItem *pItem = new QListWidgetItem(layoutNames[i], m_pLayoutListWidget);
1399 pItem->setData(Qt::UserRole, layoutUidList[i]);
1400 m_pLayoutListWidget->addItem(pItem);
1401 if (layoutUidList[i] == currentItemUid)
1402 m_pLayoutListWidget->setCurrentItem(pItem);
1403 }
1404 m_pLayoutListWidget->sortItems();
1405 m_pLayoutListWidget->blockSignals(false);
1406}
1407
1408void UILayoutSelector::retranslateUi()
1409{
1410 if (m_pApplyLayoutButton)
1411 m_pApplyLayoutButton->setToolTip(UISoftKeyboard::tr("Use the selected layout"));
1412 if (m_pEditLayoutButton)
1413 m_pEditLayoutButton->setToolTip(UISoftKeyboard::tr("Edit the selected layout"));
1414 if (m_pDeleteLayoutButton)
1415 m_pDeleteLayoutButton->setToolTip(UISoftKeyboard::tr("Delete the selected layout"));
1416 if (m_pCopyLayoutButton)
1417 m_pCopyLayoutButton->setToolTip(UISoftKeyboard::tr("Copy the selected layout"));
1418 if (m_pSaveLayoutButton)
1419 m_pSaveLayoutButton->setToolTip(UISoftKeyboard::tr("Save the selected layout into File"));
1420 if (m_pTitleLabel)
1421 m_pTitleLabel->setText(UISoftKeyboard::tr("Layout List"));
1422 if (m_pCloseButton)
1423 {
1424 m_pCloseButton->setToolTip(UISoftKeyboard::tr("Close the layout list"));
1425 m_pCloseButton->setText("Close");
1426 }
1427}
1428
1429void UILayoutSelector::prepareObjects()
1430{
1431 QVBoxLayout *pLayout = new QVBoxLayout;
1432 if (!pLayout)
1433 return;
1434 pLayout->setSpacing(0);
1435 setLayout(pLayout);
1436
1437 QHBoxLayout *pTitleLayout = new QHBoxLayout;
1438 m_pCloseButton = new QToolButton;
1439 m_pCloseButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
1440 m_pCloseButton->setIcon(UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_DialogCancel));
1441 m_pCloseButton->setAutoRaise(true);
1442 connect(m_pCloseButton, &QToolButton::clicked, this, &UILayoutSelector::sigCloseLayoutList);
1443 m_pTitleLabel = new QLabel;
1444 pTitleLayout->addWidget(m_pTitleLabel);
1445 pTitleLayout->addStretch(2);
1446 pTitleLayout->addWidget(m_pCloseButton);
1447 pLayout->addLayout(pTitleLayout);
1448
1449 m_pLayoutListWidget = new QListWidget;
1450 pLayout->addWidget(m_pLayoutListWidget);
1451 m_pLayoutListWidget->setSortingEnabled(true);
1452 connect(m_pLayoutListWidget, &QListWidget::currentItemChanged, this, &UILayoutSelector::sltCurrentItemChanged);
1453
1454 m_pLayoutListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
1455 QHBoxLayout *pButtonsLayout = new QHBoxLayout;
1456 pLayout->addLayout(pButtonsLayout);
1457
1458 m_pEditLayoutButton = new QToolButton;
1459 m_pEditLayoutButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_layout_edit_16px.png", ":/soft_keyboard_layout_edit_disabled_16px.png"));
1460 pButtonsLayout->addWidget(m_pEditLayoutButton);
1461 connect(m_pEditLayoutButton, &QToolButton::clicked, this, &UILayoutSelector::sigShowLayoutEditor);
1462
1463 m_pCopyLayoutButton = new QToolButton;
1464 m_pCopyLayoutButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_layout_copy_16px.png", ":/soft_keyboard_layout_copy_disabled_16px.png"));
1465 pButtonsLayout->addWidget(m_pCopyLayoutButton);
1466 connect(m_pCopyLayoutButton, &QToolButton::clicked, this, &UILayoutSelector::sigCopyLayout);
1467
1468 m_pSaveLayoutButton = new QToolButton;
1469 m_pSaveLayoutButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_layout_save_16px.png", ":/soft_keyboard_layout_save_disabled_16px.png"));
1470 pButtonsLayout->addWidget(m_pSaveLayoutButton);
1471 connect(m_pSaveLayoutButton, &QToolButton::clicked, this, &UILayoutSelector::sigSaveLayout);
1472
1473 m_pDeleteLayoutButton = new QToolButton;
1474 m_pDeleteLayoutButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_layout_remove_16px.png", ":/soft_keyboard_layout_remove_disabled_16px.png"));
1475 pButtonsLayout->addWidget(m_pDeleteLayoutButton);
1476 connect(m_pDeleteLayoutButton, &QToolButton::clicked, this, &UILayoutSelector::sigDeleteLayout);
1477
1478 pButtonsLayout->addStretch(2);
1479
1480 retranslateUi();
1481}
1482
1483void UILayoutSelector::sltCurrentItemChanged(QListWidgetItem *pCurrent, QListWidgetItem *pPrevious)
1484{
1485 Q_UNUSED(pPrevious);
1486 if (!pCurrent)
1487 return;
1488 emit sigLayoutSelectionChanged(pCurrent->data(Qt::UserRole).toUuid());
1489}
1490
1491/*********************************************************************************************************************************
1492* UISoftKeyboardRow implementation. *
1493*********************************************************************************************************************************/
1494
1495UISoftKeyboardRow::UISoftKeyboardRow()
1496 : m_iDefaultWidth(0)
1497 , m_iDefaultHeight(0)
1498 , m_iSpaceHeightAfter(0)
1499 , m_iLeftMargin(0)
1500{
1501}
1502
1503void UISoftKeyboardRow::setDefaultWidth(int iWidth)
1504{
1505 m_iDefaultWidth = iWidth;
1506}
1507
1508int UISoftKeyboardRow::defaultWidth() const
1509{
1510 return m_iDefaultWidth;
1511}
1512
1513int UISoftKeyboardRow::totalHeight() const
1514{
1515 int iMaxHeight = 0;
1516 for (int i = 0; i < m_keys.size(); ++i)
1517 iMaxHeight = qMax(iMaxHeight, m_keys[i].height());
1518 return iMaxHeight + m_iSpaceHeightAfter;
1519}
1520
1521void UISoftKeyboardRow::setDefaultHeight(int iHeight)
1522{
1523 m_iDefaultHeight = iHeight;
1524}
1525
1526int UISoftKeyboardRow::defaultHeight() const
1527{
1528 return m_iDefaultHeight;
1529}
1530
1531QVector<UISoftKeyboardKey> &UISoftKeyboardRow::keys()
1532{
1533 return m_keys;
1534}
1535
1536const QVector<UISoftKeyboardKey> &UISoftKeyboardRow::keys() const
1537{
1538 return m_keys;
1539}
1540
1541void UISoftKeyboardRow::setSpaceHeightAfter(int iSpace)
1542{
1543 m_iSpaceHeightAfter = iSpace;
1544}
1545
1546int UISoftKeyboardRow::spaceHeightAfter() const
1547{
1548 return m_iSpaceHeightAfter;
1549}
1550
1551int UISoftKeyboardRow::leftMargin() const
1552{
1553 return m_iLeftMargin;
1554}
1555
1556void UISoftKeyboardRow::setLeftMargin(int iMargin)
1557{
1558 m_iLeftMargin = iMargin;
1559}
1560
1561/*********************************************************************************************************************************
1562* UISoftKeyboardKey implementation. *
1563*********************************************************************************************************************************/
1564
1565UISoftKeyboardKey::UISoftKeyboardKey()
1566 : m_enmType(KeyType_Ordinary)
1567 , m_enmState(KeyState_NotPressed)
1568 , m_iWidth(0)
1569 , m_iHeight(0)
1570 , m_iSpaceWidthAfter(0)
1571 , m_scanCode(0)
1572 , m_iCutoutWidth(0)
1573 , m_iCutoutHeight(0)
1574 , m_iCutoutCorner(-1)
1575 , m_iPosition(0)
1576 , m_pParentWidget(0)
1577 , m_enmKeyboardRegion(KeyboardRegion_Main)
1578 , m_fIsOSMenuKey(false)
1579 , m_fCornerRadius(5.)
1580{
1581}
1582
1583const QRect UISoftKeyboardKey::keyGeometry() const
1584{
1585 return m_keyGeometry;
1586}
1587
1588void UISoftKeyboardKey::setKeyGeometry(const QRect &rect)
1589{
1590 m_keyGeometry = rect;
1591}
1592
1593
1594void UISoftKeyboardKey::setWidth(int iWidth)
1595{
1596 m_iWidth = iWidth;
1597}
1598
1599int UISoftKeyboardKey::width() const
1600{
1601 return m_iWidth;
1602}
1603
1604void UISoftKeyboardKey::setHeight(int iHeight)
1605{
1606 m_iHeight = iHeight;
1607}
1608
1609int UISoftKeyboardKey::height() const
1610{
1611 return m_iHeight;
1612}
1613
1614void UISoftKeyboardKey::setScanCode(LONG scanCode)
1615{
1616 m_scanCode = scanCode;
1617}
1618
1619LONG UISoftKeyboardKey::scanCode() const
1620{
1621 return m_scanCode;
1622}
1623
1624void UISoftKeyboardKey::addScanCodePrefix(LONG scanCodePrefix)
1625{
1626 m_scanCodePrefix << scanCodePrefix;
1627}
1628
1629void UISoftKeyboardKey::setSpaceWidthAfter(int iSpace)
1630{
1631 m_iSpaceWidthAfter = iSpace;
1632}
1633
1634int UISoftKeyboardKey::spaceWidthAfter() const
1635{
1636 return m_iSpaceWidthAfter;
1637}
1638
1639void UISoftKeyboardKey::setUsageId(LONG usageId)
1640{
1641 m_iUsageId = usageId;
1642}
1643
1644void UISoftKeyboardKey::setUsagePage(LONG usagePage)
1645{
1646 m_iUsagePage = usagePage;
1647}
1648
1649QPair<LONG, LONG> UISoftKeyboardKey::usagePageIdPair() const
1650{
1651 return QPair<LONG, LONG>(m_iUsageId, m_iUsagePage);
1652}
1653
1654void UISoftKeyboardKey::setPosition(int iPosition)
1655{
1656 m_iPosition = iPosition;
1657}
1658
1659int UISoftKeyboardKey::position() const
1660{
1661 return m_iPosition;
1662}
1663
1664void UISoftKeyboardKey::setType(KeyType enmType)
1665{
1666 m_enmType = enmType;
1667}
1668
1669KeyType UISoftKeyboardKey::type() const
1670{
1671 return m_enmType;
1672}
1673
1674KeyboardRegion UISoftKeyboardKey::keyboardRegion() const
1675{
1676 return m_enmKeyboardRegion;
1677}
1678
1679void UISoftKeyboardKey::setKeyboardRegion(KeyboardRegion enmRegion)
1680{
1681 m_enmKeyboardRegion = enmRegion;
1682}
1683
1684void UISoftKeyboardKey::setCutout(int iCorner, int iWidth, int iHeight)
1685{
1686 m_iCutoutCorner = iCorner;
1687 m_iCutoutWidth = iWidth;
1688 m_iCutoutHeight = iHeight;
1689}
1690
1691KeyState UISoftKeyboardKey::state() const
1692{
1693 return m_enmState;
1694}
1695
1696void UISoftKeyboardKey::setState(KeyState state)
1697{
1698 m_enmState = state;
1699}
1700
1701void UISoftKeyboardKey::setStaticCaption(const QString &strCaption)
1702{
1703 m_strStaticCaption = strCaption;
1704}
1705
1706const QString &UISoftKeyboardKey::staticCaption() const
1707{
1708 return m_strStaticCaption;
1709}
1710
1711void UISoftKeyboardKey::setParentWidget(UISoftKeyboardWidget* pParent)
1712{
1713 m_pParentWidget = pParent;
1714}
1715
1716void UISoftKeyboardKey::setIsOSMenuKey(bool fFlag)
1717{
1718 m_fIsOSMenuKey = fFlag;
1719}
1720
1721bool UISoftKeyboardKey::isOSMenuKey() const
1722{
1723 return m_fIsOSMenuKey;
1724}
1725
1726void UISoftKeyboardKey::release()
1727{
1728 /* Lock key states are controlled by the event signals we get from the guest OS. See updateLockKeyState function: */
1729 if (m_enmType != KeyType_Lock)
1730 updateState(false);
1731}
1732
1733void UISoftKeyboardKey::press()
1734{
1735 /* Lock key states are controlled by the event signals we get from the guest OS. See updateLockKeyState function: */
1736 if (m_enmType != KeyType_Lock)
1737 updateState(true);
1738}
1739
1740void UISoftKeyboardKey::setPoints(const QVector<QPointF> &points)
1741{
1742 m_points = points;
1743 computePainterPath();
1744}
1745
1746const QVector<QPointF> &UISoftKeyboardKey::points() const
1747{
1748 return m_points;
1749}
1750
1751const QPainterPath &UISoftKeyboardKey::painterPath() const
1752{
1753 return m_painterPath;
1754}
1755
1756void UISoftKeyboardKey::computePainterPath()
1757{
1758 if (m_points.size() < 3)
1759 return;
1760
1761 m_painterPath = QPainterPath(pointInBetween(m_fCornerRadius, m_points[0], m_points[1]));
1762 for (int i = 0; i < m_points.size(); ++i)
1763 {
1764 QPointF p0 = pointInBetween(m_fCornerRadius, m_points[(i+1)%m_points.size()], m_points[i]);
1765 QPointF p1 = pointInBetween(m_fCornerRadius, m_points[(i+1)%m_points.size()], m_points[(i+2)%m_points.size()]);
1766 m_painterPath.lineTo(p0);
1767 m_painterPath.quadTo(m_points[(i+1)%m_points.size()], p1);
1768 }
1769}
1770
1771void UISoftKeyboardKey::setCornerRadius(float fCornerRadius)
1772{
1773 m_fCornerRadius = fCornerRadius;
1774}
1775
1776QPolygonF UISoftKeyboardKey::polygonInGlobal() const
1777{
1778 QPolygonF globalPolygon(m_points);
1779 globalPolygon.translate(m_keyGeometry.x(), m_keyGeometry.y());
1780 return globalPolygon;
1781}
1782
1783int UISoftKeyboardKey::cutoutCorner() const
1784{
1785 return m_iCutoutCorner;
1786}
1787
1788int UISoftKeyboardKey::cutoutWidth() const
1789{
1790 return m_iCutoutWidth;
1791}
1792
1793int UISoftKeyboardKey::cutoutHeight() const
1794{
1795 return m_iCutoutHeight;
1796}
1797
1798void UISoftKeyboardKey::updateState(bool fPressed)
1799{
1800 KeyState enmPreviousState = state();
1801 if (m_enmType == KeyType_Modifier)
1802 {
1803 if (fPressed)
1804 {
1805 if (m_enmState == KeyState_NotPressed)
1806 m_enmState = KeyState_Pressed;
1807 else if(m_enmState == KeyState_Pressed)
1808 m_enmState = KeyState_Locked;
1809 else
1810 m_enmState = KeyState_NotPressed;
1811 }
1812 else
1813 {
1814 if(m_enmState == KeyState_Pressed)
1815 m_enmState = KeyState_NotPressed;
1816 }
1817 }
1818 else if (m_enmType == KeyType_Lock)
1819 {
1820 m_enmState = fPressed ? KeyState_Locked : KeyState_NotPressed;
1821 }
1822 else if (m_enmType == KeyType_Ordinary)
1823 {
1824 if (m_enmState == KeyState_NotPressed)
1825 m_enmState = KeyState_Pressed;
1826 else
1827 m_enmState = KeyState_NotPressed;
1828 }
1829 if (enmPreviousState != state() && m_pParentWidget)
1830 m_pParentWidget->keyStateChange(this);
1831}
1832
1833void UISoftKeyboardKey::updateLockState(bool fLocked)
1834{
1835 if (m_enmType != KeyType_Lock)
1836 return;
1837 if (fLocked && m_enmState == KeyState_Locked)
1838 return;
1839 if (!fLocked && m_enmState == KeyState_NotPressed)
1840 return;
1841 updateState(fLocked);
1842}
1843
1844void UISoftKeyboardKey::reset()
1845{
1846 m_enmState = KeyState_NotPressed;
1847}
1848
1849
1850/*********************************************************************************************************************************
1851* UISoftKeyboardLayout implementation. *
1852*********************************************************************************************************************************/
1853
1854UISoftKeyboardLayout::UISoftKeyboardLayout()
1855 : m_fEditable(true)
1856 , m_fIsFromResources(false)
1857 , m_fEditedButNotSaved(false)
1858 , m_uid(QUuid::createUuid())
1859{
1860}
1861
1862QString UISoftKeyboardLayout::nameString() const
1863{
1864 QString strCombinedName;
1865 if (nativeName().isEmpty() && !name().isEmpty())
1866 strCombinedName = name();
1867 else if (!nativeName().isEmpty() && name().isEmpty())
1868 strCombinedName = nativeName();
1869 else
1870 strCombinedName = QString("%1 (%2)").arg(nativeName()).arg(name());
1871 return strCombinedName;
1872}
1873
1874void UISoftKeyboardLayout::setSourceFilePath(const QString& strSourceFilePath)
1875{
1876 m_strSourceFilePath = strSourceFilePath;
1877 setEditedBuNotSaved(true);
1878}
1879
1880const QString& UISoftKeyboardLayout::sourceFilePath() const
1881{
1882 return m_strSourceFilePath;
1883}
1884
1885void UISoftKeyboardLayout::setIsFromResources(bool fIsFromResources)
1886{
1887 m_fIsFromResources = fIsFromResources;
1888 setEditedBuNotSaved(true);
1889}
1890
1891bool UISoftKeyboardLayout::isFromResources() const
1892{
1893 return m_fIsFromResources;
1894}
1895
1896void UISoftKeyboardLayout::setName(const QString &strName)
1897{
1898 m_strName = strName;
1899 setEditedBuNotSaved(true);
1900}
1901
1902const QString &UISoftKeyboardLayout::name() const
1903{
1904 return m_strName;
1905}
1906
1907void UISoftKeyboardLayout::setNativeName(const QString &strNativeName)
1908{
1909 m_strNativeName = strNativeName;
1910 setEditedBuNotSaved(true);
1911}
1912
1913const QString &UISoftKeyboardLayout::nativeName() const
1914{
1915 return m_strNativeName;
1916}
1917
1918void UISoftKeyboardLayout::setEditable(bool fEditable)
1919{
1920 m_fEditable = fEditable;
1921 setEditedBuNotSaved(true);
1922}
1923
1924bool UISoftKeyboardLayout::editable() const
1925{
1926 return m_fEditable;
1927}
1928
1929void UISoftKeyboardLayout::setPhysicalLayoutUuid(const QUuid &uuid)
1930{
1931 m_physicalLayoutUuid = uuid;
1932 setEditedBuNotSaved(true);
1933}
1934
1935const QUuid &UISoftKeyboardLayout::physicalLayoutUuid() const
1936{
1937 return m_physicalLayoutUuid;
1938}
1939
1940void UISoftKeyboardLayout::addOrUpdateUIKeyCaptions(int iKeyPosition, const UIKeyCaptions &keyCaptions)
1941{
1942 if (m_keyCaptionsMap[iKeyPosition] == keyCaptions)
1943 return;
1944 m_keyCaptionsMap[iKeyPosition] = keyCaptions;
1945 /* Updating the captions invalidates the cached font size. We set it to 0, thereby forcing its recomputaion: */
1946 m_keyCaptionsFontSizeMap[iKeyPosition] = 0;
1947 setEditedBuNotSaved(true);
1948}
1949
1950UIKeyCaptions UISoftKeyboardLayout::keyCaptions(int iKeyPosition) const
1951{
1952 return m_keyCaptionsMap[iKeyPosition];
1953}
1954
1955bool UISoftKeyboardLayout::operator==(const UISoftKeyboardLayout &otherLayout) const
1956{
1957 if (m_strName != otherLayout.m_strName)
1958 return false;
1959 if (m_strNativeName != otherLayout.m_strNativeName)
1960 return false;
1961 if (m_physicalLayoutUuid != otherLayout.m_physicalLayoutUuid)
1962 return false;
1963 if (m_fEditable != otherLayout.m_fEditable)
1964 return false;
1965 if (m_strSourceFilePath != otherLayout.m_strSourceFilePath)
1966 return false;
1967 if (m_fIsFromResources != otherLayout.m_fIsFromResources)
1968 return false;
1969 return true;
1970}
1971
1972QString UISoftKeyboardLayout::baseCaption(int iKeyPosition) const
1973{
1974 return m_keyCaptionsMap.value(iKeyPosition, UIKeyCaptions()).m_strBase;
1975}
1976
1977QString UISoftKeyboardLayout::shiftCaption(int iKeyPosition) const
1978{
1979 if (!m_keyCaptionsMap.contains(iKeyPosition))
1980 return QString();
1981 return m_keyCaptionsMap[iKeyPosition].m_strShift;
1982}
1983
1984QString UISoftKeyboardLayout::altGrCaption(int iKeyPosition) const
1985{
1986 if (!m_keyCaptionsMap.contains(iKeyPosition))
1987 return QString();
1988 return m_keyCaptionsMap[iKeyPosition].m_strAltGr;
1989}
1990
1991QString UISoftKeyboardLayout::shiftAltGrCaption(int iKeyPosition) const
1992{
1993 if (!m_keyCaptionsMap.contains(iKeyPosition))
1994 return QString();
1995 return m_keyCaptionsMap[iKeyPosition].m_strShiftAltGr;
1996}
1997
1998void UISoftKeyboardLayout::setEditedBuNotSaved(bool fEditedButNotsaved)
1999{
2000 m_fEditedButNotSaved = fEditedButNotsaved;
2001}
2002
2003bool UISoftKeyboardLayout::editedButNotSaved() const
2004{
2005 return m_fEditedButNotSaved;
2006}
2007
2008void UISoftKeyboardLayout::setUid(const QUuid &uid)
2009{
2010 m_uid = uid;
2011 setEditedBuNotSaved(true);
2012}
2013
2014QUuid UISoftKeyboardLayout::uid() const
2015{
2016 return m_uid;
2017}
2018
2019void UISoftKeyboardLayout::drawTextInRect(const UISoftKeyboardKey &key, QPainter &painter)
2020{
2021 int iKeyPosition = key.position();
2022 const QRect &keyGeometry = key.keyGeometry();
2023 QFont painterFont(painter.font());
2024
2025 QString strBaseCaption;
2026 QString strShiftCaption;
2027 QString strShiftAltGrCaption;
2028 QString strAltGrCaption;
2029
2030 /* Static captions which are defined in the physical layout files have precedence over
2031 the one define in the keyboard layouts. In effect they stay the same for all the
2032 keyboard layouts sharing the same physical layout: */
2033
2034 if (key.staticCaption().isEmpty())
2035 {
2036 strBaseCaption = baseCaption(iKeyPosition);
2037 strShiftCaption = shiftCaption(iKeyPosition);
2038 strShiftAltGrCaption = shiftAltGrCaption(iKeyPosition);
2039 strAltGrCaption = altGrCaption(iKeyPosition);
2040 }
2041 else
2042 strBaseCaption = key.staticCaption();
2043
2044 const QString &strTopleftString = !strShiftCaption.isEmpty() ? strShiftCaption : strBaseCaption;
2045 const QString &strBottomleftString = !strShiftCaption.isEmpty() ? strBaseCaption : QString();
2046
2047 int iFontSize = 30;
2048 if (!m_keyCaptionsFontSizeMap.contains(iKeyPosition) || m_keyCaptionsFontSizeMap.value(iKeyPosition) == 0)
2049 {
2050 do
2051 {
2052 painterFont.setPixelSize(iFontSize);
2053 painterFont.setBold(true);
2054 painter.setFont(painterFont);
2055 QFontMetrics fontMetrics = painter.fontMetrics();
2056 int iMargin = 0.25 * fontMetrics.width('X');
2057
2058 int iTopWidth = 0;
2059 /* Some captions are multi line using \n as separator: */
2060 QStringList strList;
2061 strList << strTopleftString.split("\n", QString::SkipEmptyParts)
2062 << strShiftAltGrCaption.split("\n", QString::SkipEmptyParts);
2063 foreach (const QString &strPart, strList)
2064 iTopWidth = qMax(iTopWidth, fontMetrics.width(strPart));
2065 strList.clear();
2066 strList << strBottomleftString.split("\n", QString::SkipEmptyParts)
2067 << strAltGrCaption.split("\n", QString::SkipEmptyParts);
2068
2069 int iBottomWidth = 0;
2070 foreach (const QString &strPart, strList)
2071 iBottomWidth = qMax(iBottomWidth, fontMetrics.width(strPart));
2072 int iTextWidth = 2 * iMargin + qMax(iTopWidth, iBottomWidth);
2073 int iTextHeight = 0;
2074
2075 if (key.keyboardRegion() == KeyboardRegion_MultimediaKeys)
2076 iTextHeight = 2 * iMargin + fontMetrics.height();
2077 else
2078 iTextHeight = 2 * iMargin + 2 * fontMetrics.height();
2079
2080 if (iTextWidth >= keyGeometry.width() || iTextHeight >= keyGeometry.height())
2081 --iFontSize;
2082 else
2083 break;
2084
2085 }while(iFontSize > 1);
2086 m_keyCaptionsFontSizeMap[iKeyPosition] = iFontSize;
2087 }
2088 else
2089 {
2090 iFontSize = m_keyCaptionsFontSizeMap[iKeyPosition];
2091 painterFont.setPixelSize(iFontSize);
2092 painterFont.setBold(true);
2093 painter.setFont(painterFont);
2094 }
2095
2096 QFontMetrics fontMetrics = painter.fontMetrics();
2097 int iMargin = 0.25 * fontMetrics.width('X');
2098 QRect textRect;
2099 if (key.keyboardRegion() == KeyboardRegion_MultimediaKeys)
2100 textRect = QRect(2 * iMargin, iMargin,
2101 keyGeometry.width() - 2 * iMargin,
2102 keyGeometry.height() - 2 * iMargin);
2103 else
2104 textRect = QRect(iMargin, iMargin,
2105 keyGeometry.width() - 2 * iMargin,
2106 keyGeometry.height() - 2 * iMargin);
2107
2108 if (key.keyboardRegion() == KeyboardRegion_MultimediaKeys)
2109 {
2110 painter.drawText(QRect(0, 0, keyGeometry.width(), keyGeometry.height()),
2111 Qt::AlignHCenter | Qt::AlignVCenter, strTopleftString);
2112
2113 }
2114 else
2115 {
2116 painter.drawText(textRect, Qt::AlignLeft | Qt::AlignTop, strTopleftString);
2117 painter.drawText(textRect, Qt::AlignLeft | Qt::AlignBottom, strBottomleftString);
2118 painter.drawText(textRect, Qt::AlignRight | Qt::AlignTop, strShiftAltGrCaption);
2119 painter.drawText(textRect, Qt::AlignRight | Qt::AlignBottom, strAltGrCaption);
2120 }
2121}
2122
2123
2124/*********************************************************************************************************************************
2125* UISoftKeyboardColorTheme implementation. *
2126*********************************************************************************************************************************/
2127
2128UISoftKeyboardColorTheme::UISoftKeyboardColorTheme()
2129 : m_colors(QVector<QColor>(KeyboardColorType_Max))
2130 , m_fIsEditable(false)
2131{
2132 m_colors[KeyboardColorType_Background].setNamedColor("#ff878787");
2133 m_colors[KeyboardColorType_Font].setNamedColor("#ff000000");
2134 m_colors[KeyboardColorType_Hover].setNamedColor("#ff676767");
2135 m_colors[KeyboardColorType_Edit].setNamedColor("#ff9b6767");
2136 m_colors[KeyboardColorType_Pressed].setNamedColor("#fffafafa");
2137}
2138
2139UISoftKeyboardColorTheme::UISoftKeyboardColorTheme(const QString &strName,
2140 const QString &strBackgroundColor,
2141 const QString &strNormalFontColor,
2142 const QString &strHoverColor,
2143 const QString &strEditedButtonBackgroundColor,
2144 const QString &strPressedButtonFontColor)
2145 :m_colors(QVector<QColor>(KeyboardColorType_Max))
2146 ,m_strName(strName)
2147 , m_fIsEditable(false)
2148{
2149 m_colors[KeyboardColorType_Background].setNamedColor(strBackgroundColor);
2150 m_colors[KeyboardColorType_Font].setNamedColor(strNormalFontColor);
2151 m_colors[KeyboardColorType_Hover].setNamedColor(strHoverColor);
2152 m_colors[KeyboardColorType_Edit].setNamedColor(strEditedButtonBackgroundColor);
2153 m_colors[KeyboardColorType_Pressed].setNamedColor(strPressedButtonFontColor);
2154}
2155
2156
2157void UISoftKeyboardColorTheme::setColor(KeyboardColorType enmColorType, const QColor &color)
2158{
2159 if ((int) enmColorType >= m_colors.size())
2160 return;
2161 m_colors[(int)enmColorType] = color;
2162}
2163
2164QColor UISoftKeyboardColorTheme::color(KeyboardColorType enmColorType) const
2165{
2166 if ((int) enmColorType >= m_colors.size())
2167 return QColor();
2168 return m_colors[(int)enmColorType];
2169}
2170
2171QStringList UISoftKeyboardColorTheme::colorsToStringList() const
2172{
2173 QStringList colorStringList;
2174 foreach (const QColor &color, m_colors)
2175 colorStringList << color.name(QColor::HexArgb);
2176 return colorStringList;
2177}
2178
2179void UISoftKeyboardColorTheme::colorsFromStringList(const QStringList &colorStringList)
2180{
2181 for (int i = 0; i < colorStringList.size() && i < m_colors.size(); ++i)
2182 {
2183 if (!QColor::isValidColor(colorStringList[i]))
2184 continue;
2185 m_colors[i].setNamedColor(colorStringList[i]);
2186 }
2187}
2188
2189const QString &UISoftKeyboardColorTheme::name() const
2190{
2191 return m_strName;
2192}
2193
2194void UISoftKeyboardColorTheme::setName(const QString &strName)
2195{
2196 m_strName = strName;
2197}
2198
2199bool UISoftKeyboardColorTheme::isEditable() const
2200{
2201 return m_fIsEditable;
2202}
2203
2204void UISoftKeyboardColorTheme::setIsEditable(bool fIsEditable)
2205{
2206 m_fIsEditable = fIsEditable;
2207}
2208
2209/*********************************************************************************************************************************
2210* UISoftKeyboardWidget implementation. *
2211*********************************************************************************************************************************/
2212
2213UISoftKeyboardWidget::UISoftKeyboardWidget(QWidget *pParent /* = 0 */)
2214 :QIWithRetranslateUI<QWidget>(pParent)
2215 , m_pKeyUnderMouse(0)
2216 , m_pKeyBeingEdited(0)
2217 , m_pKeyPressed(0)
2218 , m_currentColorTheme(0)
2219 , m_iInitialHeight(0)
2220 , m_iInitialWidth(0)
2221 , m_iInitialWidthNoNumPad(0)
2222 , m_iXSpacing(5)
2223 , m_iYSpacing(5)
2224 , m_iLeftMargin(10)
2225 , m_iTopMargin(10)
2226 , m_iRightMargin(10)
2227 , m_iBottomMargin(10)
2228 , m_enmMode(Mode_Keyboard)
2229 , m_fHideOSMenuKeys(false)
2230 , m_fHideNumPad(false)
2231 , m_fHideMultimediaKeys(false)
2232{
2233 prepareObjects();
2234 prepareColorThemes();
2235 retranslateUi();
2236}
2237
2238QSize UISoftKeyboardWidget::minimumSizeHint() const
2239{
2240 float fScale = 0.5f;
2241 return QSize(fScale * m_minimumSize.width(), fScale * m_minimumSize.height());
2242}
2243
2244QSize UISoftKeyboardWidget::sizeHint() const
2245{
2246 float fScale = 0.5f;
2247 return QSize(fScale * m_minimumSize.width(), fScale * m_minimumSize.height());
2248}
2249
2250void UISoftKeyboardWidget::paintEvent(QPaintEvent *pEvent) /* override */
2251{
2252 Q_UNUSED(pEvent);
2253 if (!m_layouts.contains(m_uCurrentLayoutId))
2254 return;
2255
2256 UISoftKeyboardLayout &currentLayout = m_layouts[m_uCurrentLayoutId];
2257
2258 if (m_iInitialWidth == 0 || m_iInitialWidthNoNumPad == 0 || m_iInitialHeight == 0)
2259 return;
2260
2261 if (!m_fHideNumPad)
2262 m_fScaleFactorX = width() / (float) m_iInitialWidth;
2263 else
2264 m_fScaleFactorX = width() / (float) m_iInitialWidthNoNumPad;
2265
2266 if (!m_fHideMultimediaKeys)
2267 m_fScaleFactorY = height() / (float) m_iInitialHeight;
2268 else
2269 m_fScaleFactorY = height() / (float)(m_iInitialHeight - m_multiMediaKeysLayout.totalHeight());
2270
2271 QPainter painter(this);
2272 QFont painterFont(font());
2273 painterFont.setPixelSize(15);
2274 painterFont.setBold(true);
2275 painter.setFont(painterFont);
2276 painter.setRenderHint(QPainter::Antialiasing);
2277 painter.scale(m_fScaleFactorX, m_fScaleFactorY);
2278 int unitSize = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
2279 float fLedRadius = 0.8 * unitSize;
2280 float fLedMargin = 5;//0.6 * unitSize;
2281
2282 UISoftKeyboardPhysicalLayout *pPhysicalLayout = findPhysicalLayout(currentLayout.physicalLayoutUuid());
2283 if (!pPhysicalLayout)
2284 return;
2285
2286 QVector<UISoftKeyboardRow> &rows = pPhysicalLayout->rows();
2287 for (int i = 0; i < rows.size(); ++i)
2288 {
2289 QVector<UISoftKeyboardKey> &keys = rows[i].keys();
2290 for (int j = 0; j < keys.size(); ++j)
2291 {
2292 UISoftKeyboardKey &key = keys[j];
2293
2294 if (m_fHideOSMenuKeys && key.isOSMenuKey())
2295 continue;
2296
2297 if (m_fHideNumPad && key.keyboardRegion() == KeyboardRegion_NumPad)
2298 continue;
2299
2300 if (m_fHideMultimediaKeys && key.keyboardRegion() == KeyboardRegion_MultimediaKeys)
2301 continue;
2302
2303 if (m_fHideMultimediaKeys)
2304 painter.translate(key.keyGeometry().x(), key.keyGeometry().y() - m_multiMediaKeysLayout.totalHeight());
2305 else
2306 painter.translate(key.keyGeometry().x(), key.keyGeometry().y());
2307
2308 if(&key == m_pKeyBeingEdited)
2309 painter.setBrush(QBrush(color(KeyboardColorType_Edit)));
2310 else if (&key == m_pKeyUnderMouse)
2311 painter.setBrush(QBrush(color(KeyboardColorType_Hover)));
2312 else
2313 painter.setBrush(QBrush(color(KeyboardColorType_Background)));
2314
2315 if (&key == m_pKeyPressed)
2316 painter.setPen(QPen(color(KeyboardColorType_Pressed), 2));
2317 else
2318 painter.setPen(QPen(color(KeyboardColorType_Font), 2));
2319
2320 /* Draw the key shape: */
2321 painter.drawPath(key.painterPath());
2322
2323 currentLayout.drawTextInRect(key, painter);
2324 /* Draw small LED like circles on the modifier/lock keys: */
2325 if (key.type() != KeyType_Ordinary)
2326 {
2327 QColor ledColor;
2328 if (key.state() == KeyState_NotPressed)
2329 ledColor = color(KeyboardColorType_Font);
2330 else if (key.state() == KeyState_Pressed)
2331 ledColor = QColor(0, 191, 204);
2332 else
2333 ledColor = QColor(255, 50, 50);
2334 if (m_enmMode == Mode_LayoutEdit)
2335 ledColor = color(KeyboardColorType_Font);
2336 painter.setBrush(ledColor);
2337 painter.setPen(ledColor);
2338 QRectF rectangle(key.keyGeometry().width() - 2 * fLedMargin, key.keyGeometry().height() - 2 * fLedMargin,
2339 fLedRadius, fLedRadius);
2340 painter.drawEllipse(rectangle);
2341 }
2342 if (m_fHideMultimediaKeys)
2343 painter.translate(-key.keyGeometry().x(), -key.keyGeometry().y() + m_multiMediaKeysLayout.totalHeight());
2344 else
2345 painter.translate(-key.keyGeometry().x(), -key.keyGeometry().y());
2346
2347 }
2348 }
2349}
2350
2351void UISoftKeyboardWidget::mousePressEvent(QMouseEvent *pEvent)
2352{
2353 QWidget::mousePressEvent(pEvent);
2354 if (pEvent->button() != Qt::RightButton && pEvent->button() != Qt::LeftButton)
2355 return;
2356
2357 m_pKeyPressed = keyUnderMouse(pEvent);
2358 if (!m_pKeyPressed)
2359 return;
2360
2361 /* Handling the right button press: */
2362 if (pEvent->button() == Qt::RightButton)
2363 modifierKeyPressRelease(m_pKeyPressed, false);
2364 else
2365 {
2366 /* Handling the left button press: */
2367 if (m_enmMode == Mode_Keyboard)
2368 handleKeyPress(m_pKeyPressed);
2369 else if (m_enmMode == Mode_LayoutEdit)
2370 setKeyBeingEdited(m_pKeyUnderMouse);
2371 }
2372 update();
2373}
2374
2375void UISoftKeyboardWidget::mouseReleaseEvent(QMouseEvent *pEvent)
2376{
2377 QWidget::mouseReleaseEvent(pEvent);
2378
2379 if (pEvent->button() != Qt::RightButton && pEvent->button() != Qt::LeftButton)
2380 return;
2381
2382 if (!m_pKeyPressed)
2383 return;
2384 if (pEvent->button() == Qt::RightButton)
2385 modifierKeyPressRelease(m_pKeyPressed, true);
2386 else
2387 {
2388 if (m_enmMode == Mode_Keyboard)
2389 handleKeyRelease(m_pKeyPressed);
2390 }
2391 m_pKeyPressed = 0;
2392 update();
2393}
2394
2395void UISoftKeyboardWidget::mouseMoveEvent(QMouseEvent *pEvent)
2396{
2397 QWidget::mouseMoveEvent(pEvent);
2398 UISoftKeyboardKey *pPreviousKeyUnderMouse = m_pKeyUnderMouse;
2399 keyUnderMouse(pEvent);
2400 if (pPreviousKeyUnderMouse != m_pKeyUnderMouse)
2401 showKeyTooltip(m_pKeyUnderMouse);
2402}
2403
2404void UISoftKeyboardWidget::retranslateUi()
2405{
2406 m_keyTooltips[300] = UISoftKeyboard::tr("Web browser go back");
2407 m_keyTooltips[301] = UISoftKeyboard::tr("Web browser go the home page");
2408 m_keyTooltips[302] = UISoftKeyboard::tr("Web browser go forward");
2409 m_keyTooltips[315] = UISoftKeyboard::tr("Web browser reload the current page");
2410 m_keyTooltips[314] = UISoftKeyboard::tr("Web browser stop loading the page");
2411 m_keyTooltips[313] = UISoftKeyboard::tr("Web browser search");
2412
2413 m_keyTooltips[307] = UISoftKeyboard::tr("Jump back to previous media track");
2414 m_keyTooltips[308] = UISoftKeyboard::tr("Jump to next media track");
2415 m_keyTooltips[309] = UISoftKeyboard::tr("Stop playing");
2416 m_keyTooltips[310] = UISoftKeyboard::tr("Play or pause playing");
2417
2418 m_keyTooltips[303] = UISoftKeyboard::tr("Start email application");
2419 m_keyTooltips[311] = UISoftKeyboard::tr("Start calculator");
2420 m_keyTooltips[312] = UISoftKeyboard::tr("Show 'My Computer'");
2421 m_keyTooltips[316] = UISoftKeyboard::tr("Show Media folder");
2422
2423 m_keyTooltips[304] = UISoftKeyboard::tr("Mute");
2424 m_keyTooltips[305] = UISoftKeyboard::tr("Volume up");
2425 m_keyTooltips[306] = UISoftKeyboard::tr("Volume down");
2426}
2427
2428void UISoftKeyboardWidget::saveCurentLayoutToFile()
2429{
2430 if (!m_layouts.contains(m_uCurrentLayoutId))
2431 return;
2432 UISoftKeyboardLayout &currentLayout = m_layouts[m_uCurrentLayoutId];
2433 QString strHomeFolder = uiCommon().homeFolder();
2434 QDir dir(strHomeFolder);
2435 if (!dir.exists(strSubDirectorName))
2436 {
2437 if (!dir.mkdir(strSubDirectorName))
2438 {
2439 sigStatusBarMessage(QString("%1 %2").arg(UISoftKeyboard::tr("Error! Could not create folder under").arg(strHomeFolder)));
2440 return;
2441 }
2442 }
2443
2444 strHomeFolder += QString(QDir::separator()) + strSubDirectorName;
2445 QInputDialog dialog(this);
2446 dialog.setInputMode(QInputDialog::TextInput);
2447 dialog.setWindowModality(Qt::WindowModal);
2448 dialog.setWindowTitle(UISoftKeyboard::tr("Provide a file name"));
2449 dialog.setTextValue(currentLayout.name());
2450 dialog.setLabelText(QString("%1 %2").arg(UISoftKeyboard::tr("The file will be saved under:<br>")).arg(strHomeFolder));
2451 if (dialog.exec() == QDialog::Rejected)
2452 return;
2453 QString strFileName(dialog.textValue());
2454 if (strFileName.isEmpty() || strFileName.contains("..") || strFileName.contains(QDir::separator()))
2455 {
2456 sigStatusBarMessage(QString("%1 %2").arg(strFileName).arg(UISoftKeyboard::tr(" is an invalid file name")));
2457 return;
2458 }
2459
2460 UISoftKeyboardPhysicalLayout *pPhysicalLayout = findPhysicalLayout(currentLayout.physicalLayoutUuid());
2461 if (!pPhysicalLayout)
2462 {
2463 sigStatusBarMessage("The layout file could not be saved");
2464 return;
2465 }
2466
2467 QFileInfo fileInfo(strFileName);
2468 if (fileInfo.suffix().compare("xml", Qt::CaseInsensitive) != 0)
2469 strFileName += ".xml";
2470 strFileName = strHomeFolder + QString(QDir::separator()) + strFileName;
2471 QFile xmlFile(strFileName);
2472 if (!xmlFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
2473 {
2474 sigStatusBarMessage("The layout file could not be saved");
2475 return;
2476 }
2477
2478 QXmlStreamWriter xmlWriter;
2479 xmlWriter.setDevice(&xmlFile);
2480
2481 xmlWriter.setAutoFormatting(true);
2482 xmlWriter.writeStartDocument("1.0");
2483 xmlWriter.writeStartElement("layout");
2484 xmlWriter.writeTextElement("name", currentLayout.name());
2485 xmlWriter.writeTextElement("nativename", currentLayout.nativeName());
2486 xmlWriter.writeTextElement("physicallayoutid", pPhysicalLayout->uid().toString());
2487 xmlWriter.writeTextElement("id", currentLayout.uid().toString());
2488
2489 QVector<UISoftKeyboardRow> &rows = pPhysicalLayout->rows();
2490 for (int i = 0; i < rows.size(); ++i)
2491 {
2492 QVector<UISoftKeyboardKey> &keys = rows[i].keys();
2493
2494 for (int j = 0; j < keys.size(); ++j)
2495 {
2496 xmlWriter.writeStartElement("key");
2497
2498 UISoftKeyboardKey &key = keys[j];
2499 xmlWriter.writeTextElement("position", QString::number(key.position()));
2500 xmlWriter.writeTextElement("basecaption", currentLayout.baseCaption(key.position()));
2501 xmlWriter.writeTextElement("shiftcaption", currentLayout.shiftCaption(key.position()));
2502 xmlWriter.writeTextElement("altgrcaption", currentLayout.altGrCaption(key.position()));
2503 xmlWriter.writeTextElement("shiftaltgrcaption", currentLayout.shiftAltGrCaption(key.position()));
2504 xmlWriter.writeEndElement();
2505 }
2506 }
2507 xmlWriter.writeEndElement();
2508 xmlWriter.writeEndDocument();
2509
2510 xmlFile.close();
2511 currentLayout.setSourceFilePath(strFileName);
2512 currentLayout.setEditedBuNotSaved(false);
2513 sigStatusBarMessage(QString("%1 %2").arg(strFileName).arg(UISoftKeyboard::tr(" is saved")));
2514}
2515
2516void UISoftKeyboardWidget::copyCurentLayout()
2517{
2518 UISoftKeyboardLayout newLayout(m_layouts[m_uCurrentLayoutId]);
2519
2520 QString strNewName = QString("%1-%2").arg(newLayout.name()).arg(UISoftKeyboard::tr("Copy"));
2521 int iCount = 1;
2522 while (layoutByNameExists(strNewName))
2523 {
2524 strNewName = QString("%1-%2-%3").arg(newLayout.name()).arg(UISoftKeyboard::tr("Copy")).arg(QString::number(iCount));
2525 ++iCount;
2526 }
2527
2528 newLayout.setName(strNewName);
2529 newLayout.setEditedBuNotSaved(true);
2530 newLayout.setEditable(true);
2531 newLayout.setIsFromResources(false);
2532 newLayout.setSourceFilePath(QString());
2533 newLayout.setUid(QUuid::createUuid());
2534 addLayout(newLayout);
2535}
2536
2537float UISoftKeyboardWidget::layoutAspectRatio()
2538{
2539 if (m_iInitialWidth == 0)
2540 return 1.f;
2541 return m_iInitialHeight / (float) m_iInitialWidth;
2542}
2543
2544bool UISoftKeyboardWidget::hideOSMenuKeys() const
2545{
2546 return m_fHideOSMenuKeys;
2547}
2548
2549void UISoftKeyboardWidget::setHideOSMenuKeys(bool fHide)
2550{
2551 if (m_fHideOSMenuKeys == fHide)
2552 return;
2553 m_fHideOSMenuKeys = fHide;
2554 update();
2555}
2556
2557bool UISoftKeyboardWidget::hideNumPad() const
2558{
2559 return m_fHideNumPad;
2560}
2561
2562void UISoftKeyboardWidget::setHideNumPad(bool fHide)
2563{
2564 if (m_fHideNumPad == fHide)
2565 return;
2566 m_fHideNumPad = fHide;
2567 update();
2568}
2569
2570bool UISoftKeyboardWidget::hideMultimediaKeys() const
2571{
2572 return m_fHideMultimediaKeys;
2573}
2574
2575void UISoftKeyboardWidget::setHideMultimediaKeys(bool fHide)
2576{
2577 if (m_fHideMultimediaKeys == fHide)
2578 return;
2579 m_fHideMultimediaKeys = fHide;
2580 update();
2581}
2582
2583QColor UISoftKeyboardWidget::color(KeyboardColorType enmColorType) const
2584{
2585 if (!m_currentColorTheme)
2586 return QColor();
2587 return m_currentColorTheme->color(enmColorType);
2588}
2589
2590void UISoftKeyboardWidget::setColor(KeyboardColorType enmColorType, const QColor &color)
2591{
2592 if (m_currentColorTheme)
2593 m_currentColorTheme->setColor(enmColorType, color);
2594 update();
2595}
2596
2597QStringList UISoftKeyboardWidget::colorsToStringList(const QString &strColorThemeName)
2598{
2599 UISoftKeyboardColorTheme *pTheme = colorTheme(strColorThemeName);
2600 if (!pTheme)
2601 return QStringList();
2602 return pTheme->colorsToStringList();
2603}
2604
2605void UISoftKeyboardWidget::colorsFromStringList(const QString &strColorThemeName, const QStringList &colorStringList)
2606{
2607 UISoftKeyboardColorTheme *pTheme = colorTheme(strColorThemeName);
2608 if (!pTheme)
2609 return;
2610 pTheme->colorsFromStringList(colorStringList);
2611}
2612
2613void UISoftKeyboardWidget::updateLockKeyStates(bool fCapsLockState, bool fNumLockState, bool fScrollLockState)
2614{
2615 for (int i = 0; i < m_physicalLayouts.size(); ++i)
2616 m_physicalLayouts[i].updateLockKeyStates(fCapsLockState, fNumLockState, fScrollLockState);
2617 update();
2618}
2619
2620QStringList UISoftKeyboardWidget::colorThemeNames() const
2621{
2622 QStringList nameList;
2623 foreach (const UISoftKeyboardColorTheme &theme, m_colorThemes)
2624 {
2625 nameList << theme.name();
2626 }
2627 return nameList;
2628}
2629
2630QString UISoftKeyboardWidget::currentColorThemeName() const
2631{
2632 if (!m_currentColorTheme)
2633 return QString();
2634 return m_currentColorTheme->name();
2635}
2636
2637void UISoftKeyboardWidget::setColorThemeByName(const QString &strColorThemeName)
2638{
2639 if (strColorThemeName.isEmpty())
2640 return;
2641 if (m_currentColorTheme && m_currentColorTheme->name() == strColorThemeName)
2642 return;
2643 for (int i = 0; i < m_colorThemes.size(); ++i)
2644 {
2645 if (m_colorThemes[i].name() == strColorThemeName)
2646 {
2647 m_currentColorTheme = &(m_colorThemes[i]);
2648 break;
2649 }
2650 }
2651 update();
2652 emit sigCurrentColorThemeChanged();
2653}
2654
2655void UISoftKeyboardWidget::parentDialogDeactivated()
2656{
2657 if (!underMouse())
2658 m_pKeyUnderMouse = 0;
2659 update();
2660}
2661
2662bool UISoftKeyboardWidget::isColorThemeEditable() const
2663{
2664 if (!m_currentColorTheme)
2665 return false;
2666 return m_currentColorTheme->isEditable();
2667}
2668
2669QStringList UISoftKeyboardWidget::unsavedLayoutsNameList() const
2670{
2671 QStringList nameList;
2672 foreach (const UISoftKeyboardLayout &layout, m_layouts)
2673 {
2674 if (layout.editedButNotSaved())
2675 nameList << layout.nameString();
2676 }
2677 return nameList;
2678}
2679
2680void UISoftKeyboardWidget::deleteCurrentLayout()
2681{
2682 if (!m_layouts.contains(m_uCurrentLayoutId))
2683 return;
2684
2685 /* Make sure we will have at least one layout remaining. */
2686 if (m_layouts.size() <= 1)
2687 return;
2688
2689 const UISoftKeyboardLayout &layout = m_layouts.value(m_uCurrentLayoutId);
2690 if (!layout.editable() || layout.isFromResources())
2691 return;
2692
2693 QDir fileToDelete;
2694 QString strFilePath(layout.sourceFilePath());
2695
2696 bool fFileExists = false;
2697 if (!strFilePath.isEmpty())
2698 fFileExists = fileToDelete.exists(strFilePath);
2699 /* It might be that the layout copied but not yet saved into a file: */
2700 if (fFileExists)
2701 {
2702 if (!msgCenter().questionBinary(this, MessageType_Question,
2703 QString(UISoftKeyboard::tr("This will delete the keyboard layout file as well. Proceed?")),
2704 0 /* auto-confirm id */,
2705 QString("Delete") /* ok button text */,
2706 QString() /* cancel button text */,
2707 false /* ok button by default? */))
2708 return;
2709
2710 if (fileToDelete.remove(strFilePath))
2711 sigStatusBarMessage(QString("%1 %2 %3").arg(UISoftKeyboard::tr("The file ")).arg(strFilePath).arg(UISoftKeyboard::tr(" has been deleted")));
2712 else
2713 sigStatusBarMessage(QString("%1 %2 %3").arg(UISoftKeyboard::tr("Deleting the file ")).arg(strFilePath).arg(UISoftKeyboard::tr(" has failed")));
2714 }
2715
2716 m_layouts.remove(m_uCurrentLayoutId);
2717 setCurrentLayout(m_layouts.firstKey());
2718}
2719
2720void UISoftKeyboardWidget::toggleEditMode(bool fIsEditMode)
2721{
2722 if (fIsEditMode)
2723 m_enmMode = Mode_LayoutEdit;
2724 else
2725 {
2726 m_enmMode = Mode_Keyboard;
2727 m_pKeyBeingEdited = 0;
2728 }
2729 update();
2730}
2731
2732void UISoftKeyboardWidget::addLayout(const UISoftKeyboardLayout &newLayout)
2733{
2734 if (m_layouts.contains(newLayout.uid()))
2735 return;
2736 m_layouts[newLayout.uid()] = newLayout;
2737}
2738
2739void UISoftKeyboardWidget::setNewMinimumSize(const QSize &size)
2740{
2741 m_minimumSize = size;
2742 updateGeometry();
2743}
2744
2745void UISoftKeyboardWidget::setInitialSize(int iWidth, int iHeight)
2746{
2747 m_iInitialWidth = iWidth;
2748 m_iInitialHeight = iHeight;
2749}
2750
2751UISoftKeyboardKey *UISoftKeyboardWidget::keyUnderMouse(QMouseEvent *pEvent)
2752{
2753 QPoint eventPosition(pEvent->pos().x() / m_fScaleFactorX, pEvent->pos().y() / m_fScaleFactorY);
2754 return keyUnderMouse(eventPosition);
2755}
2756
2757UISoftKeyboardKey *UISoftKeyboardWidget::keyUnderMouse(const QPoint &eventPosition)
2758{
2759 const UISoftKeyboardLayout &currentLayout = m_layouts.value(m_uCurrentLayoutId);
2760
2761 UISoftKeyboardPhysicalLayout *pPhysicalLayout = findPhysicalLayout(currentLayout.physicalLayoutUuid());
2762 if (!pPhysicalLayout)
2763 return 0;
2764
2765 UISoftKeyboardKey *pKey = 0;
2766 QVector<UISoftKeyboardRow> &rows = pPhysicalLayout->rows();
2767 for (int i = 0; i < rows.size(); ++i)
2768 {
2769 QVector<UISoftKeyboardKey> &keys = rows[i].keys();
2770 for (int j = 0; j < keys.size(); ++j)
2771 {
2772 UISoftKeyboardKey &key = keys[j];
2773 if (key.polygonInGlobal().containsPoint(eventPosition, Qt::OddEvenFill))
2774 {
2775 pKey = &key;
2776 break;
2777 }
2778 }
2779 }
2780 if (m_pKeyUnderMouse != pKey)
2781 {
2782 m_pKeyUnderMouse = pKey;
2783 update();
2784 }
2785 return pKey;
2786}
2787
2788void UISoftKeyboardWidget::handleKeyRelease(UISoftKeyboardKey *pKey)
2789{
2790 if (!pKey)
2791 return;
2792 if (pKey->type() == KeyType_Ordinary)
2793 pKey->release();
2794 /* We only send the scan codes of Ordinary keys: */
2795 if (pKey->type() == KeyType_Modifier)
2796 return;
2797
2798#if 0
2799
2800 QVector<LONG> sequence;
2801 if (!pKey->scanCodePrefix().isEmpty())
2802 sequence << pKey->scanCodePrefix();
2803 sequence << (pKey->scanCode() | 0x80);
2804
2805 /* Add the pressed modifiers in the reverse order: */
2806 for (int i = m_pressedModifiers.size() - 1; i >= 0; --i)
2807 {
2808 UISoftKeyboardKey *pModifier = m_pressedModifiers[i];
2809 if (!pModifier->scanCodePrefix().isEmpty())
2810 sequence << pModifier->scanCodePrefix();
2811 sequence << (pModifier->scanCode() | 0x80);
2812 /* Release the pressed modifiers (if there are not locked): */
2813 pModifier->release();
2814 }
2815 emit sigPutKeyboardSequence(sequence);
2816
2817#else
2818
2819 QVector<QPair<LONG, LONG> > sequence;
2820 sequence << QPair<LONG, LONG>(pKey->usagePageIdPair());
2821 /* Add the pressed modifiers in the reverse order: */
2822 for (int i = m_pressedModifiers.size() - 1; i >= 0; --i)
2823 {
2824 UISoftKeyboardKey *pModifier = m_pressedModifiers[i];
2825 sequence << pModifier->usagePageIdPair();
2826 /* Release the pressed modifiers (if there are not locked): */
2827 pModifier->release();
2828 }
2829 emit sigPutUsageCodesRelease(sequence);
2830
2831#endif
2832}
2833
2834void UISoftKeyboardWidget::handleKeyPress(UISoftKeyboardKey *pKey)
2835{
2836 if (!pKey)
2837 return;
2838 pKey->press();
2839
2840 if (pKey->type() == KeyType_Modifier)
2841 return;
2842
2843#if 0
2844 QVector<LONG> sequence;
2845 /* Add the pressed modifiers first: */
2846 for (int i = 0; i < m_pressedModifiers.size(); ++i)
2847 {
2848 UISoftKeyboardKey *pModifier = m_pressedModifiers[i];
2849 if (!pModifier->scanCodePrefix().isEmpty())
2850 sequence << pModifier->scanCodePrefix();
2851 sequence << pModifier->scanCode();
2852 }
2853
2854 if (!pKey->scanCodePrefix().isEmpty())
2855 sequence << pKey->scanCodePrefix();
2856 sequence << pKey->scanCode();
2857 emit sigPutKeyboardSequence(sequence);
2858
2859#else
2860
2861 QVector<QPair<LONG, LONG> > sequence;
2862
2863 /* Add the pressed modifiers first: */
2864 for (int i = 0; i < m_pressedModifiers.size(); ++i)
2865 {
2866 UISoftKeyboardKey *pModifier = m_pressedModifiers[i];
2867 sequence << pModifier->usagePageIdPair();
2868 }
2869
2870 sequence << pKey->usagePageIdPair();
2871 emit sigPutUsageCodesPress(sequence);
2872
2873#endif
2874}
2875
2876void UISoftKeyboardWidget::modifierKeyPressRelease(UISoftKeyboardKey *pKey, bool fRelease)
2877{
2878 if (!pKey || pKey->type() != KeyType_Modifier)
2879 return;
2880
2881 pKey->setState(KeyState_NotPressed);
2882
2883 QVector<QPair<LONG, LONG> > sequence;
2884 sequence << pKey->usagePageIdPair();
2885 if (fRelease)
2886 emit sigPutUsageCodesRelease(sequence);
2887 else
2888 emit sigPutUsageCodesPress(sequence);
2889}
2890
2891void UISoftKeyboardWidget::keyStateChange(UISoftKeyboardKey* pKey)
2892{
2893 if (!pKey)
2894 return;
2895 if (pKey->type() == KeyType_Modifier)
2896 {
2897 if (pKey->state() == KeyState_NotPressed)
2898 m_pressedModifiers.removeOne(pKey);
2899 else
2900 if (!m_pressedModifiers.contains(pKey))
2901 m_pressedModifiers.append(pKey);
2902 }
2903}
2904
2905void UISoftKeyboardWidget::setCurrentLayout(const QUuid &layoutUid)
2906{
2907 if (m_uCurrentLayoutId == layoutUid || !m_layouts.contains(layoutUid))
2908 return;
2909
2910 UISoftKeyboardPhysicalLayout *pPhysicalLayout = findPhysicalLayout(m_layouts[layoutUid].physicalLayoutUuid());
2911 if (!pPhysicalLayout)
2912 return;
2913
2914 m_uCurrentLayoutId = layoutUid;
2915 emit sigCurrentLayoutChange();
2916 update();
2917}
2918
2919UISoftKeyboardLayout *UISoftKeyboardWidget::currentLayout()
2920{
2921 if (!m_layouts.contains(m_uCurrentLayoutId))
2922 return 0;
2923 return &(m_layouts[m_uCurrentLayoutId]);
2924}
2925
2926bool UISoftKeyboardWidget::loadPhysicalLayout(const QString &strLayoutFileName, KeyboardRegion keyboardRegion /* = KeyboardRegion_Main */)
2927{
2928 if (strLayoutFileName.isEmpty())
2929 return false;
2930 UIPhysicalLayoutReader reader;
2931 UISoftKeyboardPhysicalLayout *newPhysicalLayout = 0;
2932 if (keyboardRegion == KeyboardRegion_Main)
2933 {
2934 m_physicalLayouts.append(UISoftKeyboardPhysicalLayout());
2935 newPhysicalLayout = &(m_physicalLayouts.back());
2936 }
2937 else if (keyboardRegion == KeyboardRegion_NumPad)
2938 newPhysicalLayout = &(m_numPadLayout);
2939 else if (keyboardRegion == KeyboardRegion_MultimediaKeys)
2940 newPhysicalLayout = &(m_multiMediaKeysLayout);
2941 else
2942 return false;
2943
2944 if (!reader.parseXMLFile(strLayoutFileName, *newPhysicalLayout))
2945 {
2946 m_physicalLayouts.removeLast();
2947 return false;
2948 }
2949
2950 for (int i = 0; i < newPhysicalLayout->rows().size(); ++i)
2951 {
2952 UISoftKeyboardRow &row = newPhysicalLayout->rows()[i];
2953 for (int j = 0; j < row.keys().size(); ++j)
2954 row.keys()[j].setKeyboardRegion(keyboardRegion);
2955 }
2956
2957 if (keyboardRegion == KeyboardRegion_NumPad || keyboardRegion == KeyboardRegion_MultimediaKeys)
2958 return true;
2959
2960 /* Go thru all the keys row by row and construct their geometries: */
2961 int iY = m_iTopMargin;
2962 int iMaxWidth = 0;
2963 int iMaxWidthNoNumPad = 0;
2964 const QVector<UISoftKeyboardRow> &numPadRows = m_numPadLayout.rows();
2965 QVector<UISoftKeyboardRow> &rows = newPhysicalLayout->rows();
2966
2967 /* Prepend the multimedia rows to the layout */
2968 const QVector<UISoftKeyboardRow> &multimediaRows = m_multiMediaKeysLayout.rows();
2969 for (int i = multimediaRows.size() - 1; i >= 0; --i)
2970 rows.prepend(multimediaRows[i]);
2971
2972 for (int i = 0; i < rows.size(); ++i)
2973 {
2974 UISoftKeyboardRow &row = rows[i];
2975 /* Insert the numpad rows at the end of keyboard rows starting with appending 0th numpad row to the
2976 end of (1 + multimediaRows.size())th layout row: */
2977 if (i > multimediaRows.size())
2978 {
2979 int iNumPadRowIndex = i - (1 + multimediaRows.size());
2980 if (iNumPadRowIndex >= 0 && iNumPadRowIndex < numPadRows.size())
2981 {
2982 for (int m = 0; m < numPadRows[iNumPadRowIndex].keys().size(); ++m)
2983 row.keys().append(numPadRows[iNumPadRowIndex].keys()[m]);
2984 }
2985 }
2986
2987 int iX = m_iLeftMargin + row.leftMargin();
2988 int iXNoNumPad = m_iLeftMargin;
2989 int iRowHeight = row.defaultHeight();
2990 for (int j = 0; j < row.keys().size(); ++j)
2991 {
2992 UISoftKeyboardKey &key = (row.keys())[j];
2993 if (key.position() == iScrollLockPosition ||
2994 key.position() == iNumLockPosition ||
2995 key.position() == iCapsLockPosition)
2996 newPhysicalLayout->setLockKey(key.position(), &key);
2997
2998 key.setKeyGeometry(QRect(iX, iY, key.width(), key.height()));
2999 key.setCornerRadius(0.1 * newPhysicalLayout->defaultKeyWidth());
3000 key.setPoints(UIPhysicalLayoutReader::computeKeyVertices(key));
3001 key.setParentWidget(this);
3002 iX += key.width();
3003 if (j < row.keys().size() - 1)
3004 iX += m_iXSpacing;
3005 if (key.spaceWidthAfter() != 0)
3006 iX += (m_iXSpacing + key.spaceWidthAfter());
3007
3008 if (key.keyboardRegion() != KeyboardRegion_NumPad)
3009 {
3010 iXNoNumPad += key.width();
3011 if (j < row.keys().size() - 1)
3012 iXNoNumPad += m_iXSpacing;
3013 if (key.spaceWidthAfter() != 0)
3014 iXNoNumPad += (m_iXSpacing + key.spaceWidthAfter());
3015 }
3016 }
3017 if (row.spaceHeightAfter() != 0)
3018 iY += row.spaceHeightAfter() + m_iYSpacing;
3019 iMaxWidth = qMax(iMaxWidth, iX);
3020 iMaxWidthNoNumPad = qMax(iMaxWidthNoNumPad, iXNoNumPad);
3021 iY += iRowHeight;
3022 if (i < rows.size() - 1)
3023 iY += m_iYSpacing;
3024 }
3025 int iInitialWidth = iMaxWidth + m_iRightMargin;
3026 int iInitialWidthNoNumPad = iMaxWidthNoNumPad + m_iRightMargin;
3027 int iInitialHeight = iY + m_iBottomMargin;
3028 m_iInitialWidth = qMax(m_iInitialWidth, iInitialWidth);
3029 m_iInitialWidthNoNumPad = qMax(m_iInitialWidthNoNumPad, iInitialWidthNoNumPad);
3030 m_iInitialHeight = qMax(m_iInitialHeight, iInitialHeight);
3031
3032 return true;
3033}
3034
3035bool UISoftKeyboardWidget::loadKeyboardLayout(const QString &strLayoutFileName)
3036{
3037 if (strLayoutFileName.isEmpty())
3038 return false;
3039
3040 UIKeyboardLayoutReader keyboardLayoutReader;
3041
3042 UISoftKeyboardLayout newLayout;
3043 if (!keyboardLayoutReader.parseFile(strLayoutFileName, newLayout))
3044 return false;
3045
3046 UISoftKeyboardPhysicalLayout *pPhysicalLayout = findPhysicalLayout(newLayout.physicalLayoutUuid());
3047 /* If no pyhsical layout with the UUID the keyboard layout refers is found then cancel loading the keyboard layout: */
3048 if (!pPhysicalLayout)
3049 return false;
3050
3051 /* Make sure we have unique lay1out UUIDs: */
3052 int iCount = 0;
3053 foreach (const UISoftKeyboardLayout &layout, m_layouts)
3054 {
3055 if (layout.uid() == newLayout.uid())
3056 ++iCount;
3057 }
3058 if (iCount > 1)
3059 return false;
3060
3061 newLayout.setSourceFilePath(strLayoutFileName);
3062 addLayout(newLayout);
3063 return true;
3064}
3065
3066UISoftKeyboardPhysicalLayout *UISoftKeyboardWidget::findPhysicalLayout(const QUuid &uuid)
3067{
3068 for (int i = 0; i < m_physicalLayouts.size(); ++i)
3069 {
3070 if (m_physicalLayouts[i].uid() == uuid)
3071 return &(m_physicalLayouts[i]);
3072 }
3073 return 0;
3074}
3075
3076void UISoftKeyboardWidget::reset()
3077{
3078 m_pressedModifiers.clear();
3079 m_pKeyUnderMouse = 0;
3080 m_pKeyBeingEdited = 0;
3081 m_pKeyPressed = 0;
3082 m_enmMode = Mode_Keyboard;
3083
3084 for (int i = 0; i < m_physicalLayouts.size(); ++i)
3085 m_physicalLayouts[i].reset();
3086}
3087
3088void UISoftKeyboardWidget::loadLayouts()
3089{
3090 /* Load physical layouts from resources: Numpad and multimedia layout files should be read first
3091 since we insert these to other layouts: */
3092 loadPhysicalLayout(":/numpad.xml", KeyboardRegion_NumPad);
3093 loadPhysicalLayout(":/multimedia_keys.xml", KeyboardRegion_MultimediaKeys);
3094 QStringList physicalLayoutNames;
3095 physicalLayoutNames << ":/101_ansi.xml"
3096 << ":/102_iso.xml"
3097 << ":/106_japanese.xml"
3098 << ":/103_iso.xml"
3099 << ":/103_ansi.xml";
3100 foreach (const QString &strName, physicalLayoutNames)
3101 loadPhysicalLayout(strName);
3102
3103 setNewMinimumSize(QSize(m_iInitialWidth, m_iInitialHeight));
3104 setInitialSize(m_iInitialWidth, m_iInitialHeight);
3105
3106 /* Add keyboard layouts from resources: */
3107 QStringList keyboardLayoutNames;
3108 keyboardLayoutNames << ":/us_international.xml"
3109 << ":/german.xml"
3110 << ":/us.xml"
3111 << ":/greek.xml"
3112 << ":/japanese.xml"
3113 << ":/brazilian.xml"
3114 << ":/korean.xml";
3115
3116 foreach (const QString &strName, keyboardLayoutNames)
3117 loadKeyboardLayout(strName);
3118 /* Mark the layouts we load from the resources as non-editable: */
3119 for (QMap<QUuid, UISoftKeyboardLayout>::iterator iterator = m_layouts.begin(); iterator != m_layouts.end(); ++iterator)
3120 {
3121 iterator.value().setEditable(false);
3122 iterator.value().setIsFromResources(true);
3123 }
3124 keyboardLayoutNames.clear();
3125 /* Add keyboard layouts from the defalt keyboard layout folder: */
3126 lookAtDefaultLayoutFolder(keyboardLayoutNames);
3127 foreach (const QString &strName, keyboardLayoutNames)
3128 loadKeyboardLayout(strName);
3129
3130 if (m_layouts.isEmpty())
3131 return;
3132 for (QMap<QUuid, UISoftKeyboardLayout>::iterator iterator = m_layouts.begin(); iterator != m_layouts.end(); ++iterator)
3133 iterator.value().setEditedBuNotSaved(false);
3134 setCurrentLayout(m_layouts.firstKey());
3135}
3136
3137void UISoftKeyboardWidget::prepareObjects()
3138{
3139 setMouseTracking(true);
3140}
3141
3142void UISoftKeyboardWidget::prepareColorThemes()
3143{
3144 int iIndex = 0;
3145 while (predefinedColorThemes[iIndex][0])
3146 {
3147 m_colorThemes << UISoftKeyboardColorTheme(predefinedColorThemes[iIndex][0],
3148 predefinedColorThemes[iIndex][1],
3149 predefinedColorThemes[iIndex][2],
3150 predefinedColorThemes[iIndex][3],
3151 predefinedColorThemes[iIndex][4],
3152 predefinedColorThemes[iIndex][5]);
3153 ++iIndex;
3154 }
3155
3156 UISoftKeyboardColorTheme customTheme;
3157 customTheme.setName("Custom");
3158 customTheme.setIsEditable(true);
3159 m_colorThemes.append(customTheme);
3160 m_currentColorTheme = &(m_colorThemes.back());
3161}
3162
3163void UISoftKeyboardWidget::setKeyBeingEdited(UISoftKeyboardKey* pKey)
3164{
3165 if (m_pKeyBeingEdited == pKey)
3166 return;
3167 m_pKeyBeingEdited = pKey;
3168 emit sigKeyToEdit(pKey);
3169}
3170
3171bool UISoftKeyboardWidget::layoutByNameExists(const QString &strName) const
3172{
3173 foreach (const UISoftKeyboardLayout &layout, m_layouts)
3174 {
3175 if (layout.name() == strName)
3176 return true;
3177 }
3178 return false;
3179}
3180
3181void UISoftKeyboardWidget::lookAtDefaultLayoutFolder(QStringList &fileList)
3182{
3183 QString strFolder = QString("%1%2%3").arg(uiCommon().homeFolder()).arg(QDir::separator()).arg(strSubDirectorName);
3184 QDir dir(strFolder);
3185 if (!dir.exists())
3186 return;
3187 QStringList filters;
3188 filters << "*.xml";
3189 dir.setNameFilters(filters);
3190 QFileInfoList fileInfoList = dir.entryInfoList();
3191 foreach (const QFileInfo &fileInfo, fileInfoList)
3192 fileList << fileInfo.absoluteFilePath();
3193}
3194
3195UISoftKeyboardColorTheme *UISoftKeyboardWidget::colorTheme(const QString &strColorThemeName)
3196{
3197 for (int i = 0; i < m_colorThemes.size(); ++i)
3198 {
3199 if (m_colorThemes[i].name() == strColorThemeName)
3200 return &(m_colorThemes[i]);
3201 }
3202 return 0;
3203}
3204
3205void UISoftKeyboardWidget::showKeyTooltip(UISoftKeyboardKey *pKey)
3206{
3207 if (pKey && m_keyTooltips.contains(pKey->position()))
3208 sigStatusBarMessage(m_keyTooltips[pKey->position()]);
3209 else
3210 sigStatusBarMessage(QString());
3211
3212}
3213
3214QStringList UISoftKeyboardWidget::layoutNameList() const
3215{
3216 QStringList layoutNames;
3217 foreach (const UISoftKeyboardLayout &layout, m_layouts)
3218 layoutNames << layout.nameString();
3219 return layoutNames;
3220}
3221
3222QList<QUuid> UISoftKeyboardWidget::layoutUidList() const
3223{
3224 QList<QUuid> layoutUids;
3225 foreach (const UISoftKeyboardLayout &layout, m_layouts)
3226 layoutUids << layout.uid();
3227 return layoutUids;
3228}
3229
3230const QVector<UISoftKeyboardPhysicalLayout> &UISoftKeyboardWidget::physicalLayouts() const
3231{
3232 return m_physicalLayouts;
3233}
3234
3235/*********************************************************************************************************************************
3236* UIPhysicalLayoutReader implementation. *
3237*********************************************************************************************************************************/
3238
3239bool UIPhysicalLayoutReader::parseXMLFile(const QString &strFileName, UISoftKeyboardPhysicalLayout &physicalLayout)
3240{
3241 QFile xmlFile(strFileName);
3242 if (!xmlFile.exists())
3243 return false;
3244
3245 if (xmlFile.size() >= iFileSizeLimit)
3246 return false;
3247
3248 if (!xmlFile.open(QIODevice::ReadOnly))
3249 return false;
3250
3251 m_xmlReader.setDevice(&xmlFile);
3252
3253 if (!m_xmlReader.readNextStartElement() || m_xmlReader.name() != "physicallayout")
3254 return false;
3255 physicalLayout.setFileName(strFileName);
3256
3257 QXmlStreamAttributes attributes = m_xmlReader.attributes();
3258 int iDefaultWidth = attributes.value("defaultWidth").toInt();
3259 int iDefaultHeight = attributes.value("defaultHeight").toInt();
3260 QVector<UISoftKeyboardRow> &rows = physicalLayout.rows();
3261 physicalLayout.setDefaultKeyWidth(iDefaultWidth);
3262
3263 while (m_xmlReader.readNextStartElement())
3264 {
3265 if (m_xmlReader.name() == "row")
3266 parseRow(iDefaultWidth, iDefaultHeight, rows);
3267 else if (m_xmlReader.name() == "name")
3268 physicalLayout.setName(m_xmlReader.readElementText());
3269 else if (m_xmlReader.name() == "id")
3270 physicalLayout.setUid(m_xmlReader.readElementText());
3271 else
3272 m_xmlReader.skipCurrentElement();
3273 }
3274
3275 return true;
3276}
3277
3278void UIPhysicalLayoutReader::parseRow(int iDefaultWidth, int iDefaultHeight, QVector<UISoftKeyboardRow> &rows)
3279{
3280 rows.append(UISoftKeyboardRow());
3281 UISoftKeyboardRow &row = rows.back();
3282
3283 row.setDefaultWidth(iDefaultWidth);
3284 row.setDefaultHeight(iDefaultHeight);
3285 row.setSpaceHeightAfter(0);
3286
3287 /* Override the layout attributes if the row also has them: */
3288 QXmlStreamAttributes attributes = m_xmlReader.attributes();
3289 if (attributes.hasAttribute("defaultWidth"))
3290 row.setDefaultWidth(attributes.value("defaultWidth").toInt());
3291 if (attributes.hasAttribute("defaultHeight"))
3292 row.setDefaultHeight(attributes.value("defaultHeight").toInt());
3293 while (m_xmlReader.readNextStartElement())
3294 {
3295 if (m_xmlReader.name() == "key")
3296 parseKey(row);
3297 else if (m_xmlReader.name() == "space")
3298 parseKeySpace(row);
3299 else
3300 m_xmlReader.skipCurrentElement();
3301 }
3302}
3303
3304void UIPhysicalLayoutReader::parseKey(UISoftKeyboardRow &row)
3305{
3306 row.keys().append(UISoftKeyboardKey());
3307 UISoftKeyboardKey &key = row.keys().back();
3308 key.setWidth(row.defaultWidth());
3309 key.setHeight(row.defaultHeight());
3310 QString strKeyCap;
3311 while (m_xmlReader.readNextStartElement())
3312 {
3313 if (m_xmlReader.name() == "width")
3314 key.setWidth(m_xmlReader.readElementText().toInt());
3315 else if (m_xmlReader.name() == "height")
3316 key.setHeight(m_xmlReader.readElementText().toInt());
3317 else if (m_xmlReader.name() == "scancode")
3318 {
3319 QString strCode = m_xmlReader.readElementText();
3320 bool fOk = false;
3321 key.setScanCode(strCode.toInt(&fOk, 16));
3322 }
3323 else if (m_xmlReader.name() == "scancodeprefix")
3324 {
3325 QString strCode = m_xmlReader.readElementText();
3326 QStringList strList;
3327 strList << strCode.split('-', QString::SkipEmptyParts);
3328 foreach (const QString &strPrefix, strList)
3329 {
3330 bool fOk = false;
3331 LONG iCode = strPrefix.toInt(&fOk, 16);
3332 if (fOk)
3333 key.addScanCodePrefix(iCode);
3334 }
3335 }
3336 else if (m_xmlReader.name() == "usageid")
3337 {
3338 QString strCode = m_xmlReader.readElementText();
3339 bool fOk = false;
3340 key.setUsageId(strCode.toInt(&fOk, 16));
3341 }
3342 else if (m_xmlReader.name() == "usagepage")
3343 {
3344 QString strCode = m_xmlReader.readElementText();
3345 bool fOk = false;
3346 key.setUsagePage(strCode.toInt(&fOk, 16));
3347 }
3348 else if (m_xmlReader.name() == "cutout")
3349 parseCutout(key);
3350 else if (m_xmlReader.name() == "position")
3351 key.setPosition(m_xmlReader.readElementText().toInt());
3352 else if (m_xmlReader.name() == "type")
3353 {
3354 QString strType = m_xmlReader.readElementText();
3355 if (strType == "modifier")
3356 key.setType(KeyType_Modifier);
3357 else if (strType == "lock")
3358 key.setType(KeyType_Lock);
3359 }
3360 else if (m_xmlReader.name() == "osmenukey")
3361 {
3362 if (m_xmlReader.readElementText() == "true")
3363 key.setIsOSMenuKey(true);
3364 }
3365 else if (m_xmlReader.name() == "staticcaption")
3366 key.setStaticCaption(m_xmlReader.readElementText());
3367 else
3368 m_xmlReader.skipCurrentElement();
3369 }
3370}
3371
3372void UIPhysicalLayoutReader::parseKeySpace(UISoftKeyboardRow &row)
3373{
3374 int iWidth = row.defaultWidth();
3375 int iHeight = 0;
3376 while (m_xmlReader.readNextStartElement())
3377 {
3378 if (m_xmlReader.name() == "width")
3379 iWidth = m_xmlReader.readElementText().toInt();
3380 else if (m_xmlReader.name() == "height")
3381 iHeight = m_xmlReader.readElementText().toInt();
3382 else
3383 m_xmlReader.skipCurrentElement();
3384 }
3385 row.setSpaceHeightAfter(iHeight);
3386 /* If we have keys add the parsed space to the last key as the 'space after': */
3387 if (!row.keys().empty())
3388 row.keys().back().setSpaceWidthAfter(iWidth);
3389 /* If we have no keys than this is the initial space left to first key: */
3390 else
3391 row.setLeftMargin(iWidth);
3392}
3393
3394void UIPhysicalLayoutReader::parseCutout(UISoftKeyboardKey &key)
3395{
3396 int iWidth = 0;
3397 int iHeight = 0;
3398 int iCorner = 0;
3399 while (m_xmlReader.readNextStartElement())
3400 {
3401 if (m_xmlReader.name() == "width")
3402 iWidth = m_xmlReader.readElementText().toInt();
3403 else if (m_xmlReader.name() == "height")
3404 iHeight = m_xmlReader.readElementText().toInt();
3405 else if (m_xmlReader.name() == "corner")
3406 {
3407 QString strCorner = m_xmlReader.readElementText();
3408 if (strCorner == "topLeft")
3409 iCorner = 0;
3410 else if(strCorner == "topRight")
3411 iCorner = 1;
3412 else if(strCorner == "bottomRight")
3413 iCorner = 2;
3414 else if(strCorner == "bottomLeft")
3415 iCorner = 3;
3416 }
3417 else
3418 m_xmlReader.skipCurrentElement();
3419 }
3420 key.setCutout(iCorner, iWidth, iHeight);
3421}
3422
3423QVector<QPointF> UIPhysicalLayoutReader::computeKeyVertices(const UISoftKeyboardKey &key)
3424{
3425 QVector<QPointF> vertices;
3426
3427 if (key.cutoutCorner() == -1 || key.width() <= key.cutoutWidth() || key.height() <= key.cutoutHeight())
3428 {
3429 vertices.append(QPoint(0, 0));
3430 vertices.append(QPoint(key.width(), 0));
3431 vertices.append(QPoint(key.width(), key.height()));
3432 vertices.append(QPoint(0, key.height()));
3433 return vertices;
3434 }
3435 if (key.cutoutCorner() == 0)
3436 {
3437 vertices.append(QPoint(key.cutoutWidth(), 0));
3438 vertices.append(QPoint(key.width(), 0));
3439 vertices.append(QPoint(key.width(), key.height()));
3440 vertices.append(QPoint(0, key.height()));
3441 vertices.append(QPoint(0, key.cutoutHeight()));
3442 vertices.append(QPoint(key.cutoutWidth(), key.cutoutHeight()));
3443 }
3444 else if (key.cutoutCorner() == 1)
3445 {
3446 vertices.append(QPoint(0, 0));
3447 vertices.append(QPoint(key.width() - key.cutoutWidth(), 0));
3448 vertices.append(QPoint(key.width() - key.cutoutWidth(), key.cutoutHeight()));
3449 vertices.append(QPoint(key.width(), key.cutoutHeight()));
3450 vertices.append(QPoint(key.width(), key.height()));
3451 vertices.append(QPoint(0, key.height()));
3452 }
3453 else if (key.cutoutCorner() == 2)
3454 {
3455 vertices.append(QPoint(0, 0));
3456 vertices.append(QPoint(key.width(), 0));
3457 vertices.append(QPoint(key.width(), key.cutoutHeight()));
3458 vertices.append(QPoint(key.width() - key.cutoutWidth(), key.cutoutHeight()));
3459 vertices.append(QPoint(key.width() - key.cutoutWidth(), key.height()));
3460 vertices.append(QPoint(0, key.height()));
3461 }
3462 else if (key.cutoutCorner() == 3)
3463 {
3464 vertices.append(QPoint(0, 0));
3465 vertices.append(QPoint(key.width(), 0));
3466 vertices.append(QPoint(key.width(), key.height()));
3467 vertices.append(QPoint(key.cutoutWidth(), key.height()));
3468 vertices.append(QPoint(key.cutoutWidth(), key.height() - key.cutoutHeight()));
3469 vertices.append(QPoint(0, key.height() - key.cutoutHeight()));
3470 }
3471 return vertices;
3472}
3473
3474/*********************************************************************************************************************************
3475* UIKeyboardLayoutReader implementation. *
3476*********************************************************************************************************************************/
3477
3478bool UIKeyboardLayoutReader::parseFile(const QString &strFileName, UISoftKeyboardLayout &layout)
3479{
3480 QFile xmlFile(strFileName);
3481 if (!xmlFile.exists())
3482 return false;
3483
3484 if (xmlFile.size() >= iFileSizeLimit)
3485 return false;
3486
3487 if (!xmlFile.open(QIODevice::ReadOnly))
3488 return false;
3489
3490 m_xmlReader.setDevice(&xmlFile);
3491
3492 if (!m_xmlReader.readNextStartElement() || m_xmlReader.name() != "layout")
3493 return false;
3494
3495 while (m_xmlReader.readNextStartElement())
3496 {
3497 if (m_xmlReader.name() == "key")
3498 parseKey(layout);
3499 else if (m_xmlReader.name() == "name")
3500 layout.setName(m_xmlReader.readElementText());
3501 else if (m_xmlReader.name() == "nativename")
3502 layout.setNativeName(m_xmlReader.readElementText());
3503 else if (m_xmlReader.name() == "physicallayoutid")
3504 layout.setPhysicalLayoutUuid(QUuid(m_xmlReader.readElementText()));
3505 else if (m_xmlReader.name() == "id")
3506 layout.setUid(QUuid(m_xmlReader.readElementText()));
3507 else
3508 m_xmlReader.skipCurrentElement();
3509 }
3510 return true;
3511}
3512
3513void UIKeyboardLayoutReader::parseKey(UISoftKeyboardLayout &layout)
3514{
3515 UIKeyCaptions keyCaptions;
3516 int iKeyPosition = 0;
3517 while (m_xmlReader.readNextStartElement())
3518 {
3519 if (m_xmlReader.name() == "basecaption")
3520 {
3521 keyCaptions.m_strBase = m_xmlReader.readElementText();
3522 keyCaptions.m_strBase.replace("\\n", "\n");
3523 }
3524 else if (m_xmlReader.name() == "shiftcaption")
3525 {
3526 keyCaptions.m_strShift = m_xmlReader.readElementText();
3527 keyCaptions.m_strShift.replace("\\n", "\n");
3528 }
3529 else if (m_xmlReader.name() == "altgrcaption")
3530 {
3531 keyCaptions.m_strAltGr = m_xmlReader.readElementText();
3532 keyCaptions.m_strAltGr.replace("\\n", "\n");
3533 }
3534 else if (m_xmlReader.name() == "shiftaltgrcaption")
3535 {
3536 keyCaptions.m_strShiftAltGr = m_xmlReader.readElementText();
3537 keyCaptions.m_strShiftAltGr.replace("\\n", "\n");
3538 }
3539 else if (m_xmlReader.name() == "position")
3540 iKeyPosition = m_xmlReader.readElementText().toInt();
3541 else
3542 m_xmlReader.skipCurrentElement();
3543 }
3544 layout.addOrUpdateUIKeyCaptions(iKeyPosition, keyCaptions);
3545}
3546
3547
3548/*********************************************************************************************************************************
3549* UISoftKeyboardStatusBarWidget implementation. *
3550*********************************************************************************************************************************/
3551
3552UISoftKeyboardStatusBarWidget::UISoftKeyboardStatusBarWidget(QWidget *pParent /* = 0*/ )
3553 : QIWithRetranslateUI<QWidget>(pParent)
3554 , m_pLayoutListButton(0)
3555 , m_pSettingsButton(0)
3556 , m_pResetButton(0)
3557 , m_pMessageLabel(0)
3558{
3559 prepareObjects();
3560}
3561
3562void UISoftKeyboardStatusBarWidget::retranslateUi()
3563{
3564 if (m_pLayoutListButton)
3565 m_pLayoutListButton->setToolTip(UISoftKeyboard::tr("Layout List"));
3566 if (m_pSettingsButton)
3567 m_pSettingsButton->setToolTip(UISoftKeyboard::tr("Settings"));
3568 if (m_pResetButton)
3569 m_pResetButton->setToolTip(UISoftKeyboard::tr("Reset the keyboard and release all keys"));
3570}
3571
3572void UISoftKeyboardStatusBarWidget::prepareObjects()
3573{
3574 QHBoxLayout *pLayout = new QHBoxLayout;
3575 if (!pLayout)
3576 return;
3577 pLayout->setContentsMargins(0, 0, 0, 0);
3578 setLayout(pLayout);
3579
3580 m_pMessageLabel = new QLabel;
3581 pLayout->addWidget(m_pMessageLabel);
3582
3583 m_pLayoutListButton = new QToolButton;
3584 if (m_pLayoutListButton)
3585 {
3586 m_pLayoutListButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_layout_list_16px.png", ":/soft_keyboard_layout_list_disabled_16px.png"));
3587 m_pLayoutListButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
3588 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
3589 m_pLayoutListButton->resize(QSize(iIconMetric, iIconMetric));
3590 m_pLayoutListButton->setStyleSheet("QToolButton { border: 0px none black; margin: 0px 0px 0px 0px; } QToolButton::menu-indicator {image: none;}");
3591 connect(m_pLayoutListButton, &QToolButton::clicked, this, &UISoftKeyboardStatusBarWidget::sigShowHideSidePanel);
3592 pLayout->addWidget(m_pLayoutListButton);
3593 }
3594
3595 m_pSettingsButton = new QToolButton;
3596 if (m_pSettingsButton)
3597 {
3598 m_pSettingsButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_settings_16px.png", ":/soft_keyboard_settings_disabled_16px.png"));
3599 m_pSettingsButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
3600 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
3601 m_pSettingsButton->resize(QSize(iIconMetric, iIconMetric));
3602 m_pSettingsButton->setStyleSheet("QToolButton { border: 0px none black; margin: 0px 0px 0px 0px; } QToolButton::menu-indicator {image: none;}");
3603 connect(m_pSettingsButton, &QToolButton::clicked, this, &UISoftKeyboardStatusBarWidget::sigShowSettingWidget);
3604 pLayout->addWidget(m_pSettingsButton);
3605 }
3606
3607 m_pResetButton = new QToolButton;
3608 if (m_pResetButton)
3609 {
3610 m_pResetButton->setIcon(UIIconPool::iconSet(":/soft_keyboard_reset_16px.png"));
3611 m_pResetButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
3612 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
3613 m_pResetButton->resize(QSize(iIconMetric, iIconMetric));
3614 m_pResetButton->setStyleSheet("QToolButton { border: 0px none black; margin: 0px 0px 0px 0px; } QToolButton::menu-indicator {image: none;}");
3615 connect(m_pResetButton, &QToolButton::clicked, this, &UISoftKeyboardStatusBarWidget::sigResetKeyboard);
3616 pLayout->addWidget(m_pResetButton);
3617 }
3618
3619 retranslateUi();
3620}
3621
3622void UISoftKeyboardStatusBarWidget::updateLayoutNameInStatusBar(const QString &strMessage)
3623{
3624 if (!m_pMessageLabel)
3625 return;
3626 m_pMessageLabel->setText(strMessage);
3627}
3628
3629
3630/*********************************************************************************************************************************
3631* UISoftKeyboardSettingsWidget implementation. *
3632*********************************************************************************************************************************/
3633
3634UISoftKeyboardSettingsWidget::UISoftKeyboardSettingsWidget(QWidget *pParent /* = 0 */)
3635 : QIWithRetranslateUI<QWidget>(pParent)
3636 , m_pHideNumPadCheckBox(0)
3637 , m_pShowOsMenuButtonsCheckBox(0)
3638 , m_pHideMultimediaKeysCheckBox(0)
3639 , m_pColorThemeGroupBox(0)
3640 , m_pColorThemeComboBox(0)
3641 , m_pTitleLabel(0)
3642 , m_pCloseButton(0)
3643
3644{
3645 prepareObjects();
3646}
3647
3648void UISoftKeyboardSettingsWidget::setHideOSMenuKeys(bool fHide)
3649{
3650 if (m_pShowOsMenuButtonsCheckBox)
3651 m_pShowOsMenuButtonsCheckBox->setChecked(fHide);
3652}
3653
3654void UISoftKeyboardSettingsWidget::setHideNumPad(bool fHide)
3655{
3656 if (m_pHideNumPadCheckBox)
3657 m_pHideNumPadCheckBox->setChecked(fHide);
3658}
3659
3660void UISoftKeyboardSettingsWidget::setHideMultimediaKeys(bool fHide)
3661{
3662 if (m_pHideMultimediaKeysCheckBox)
3663 m_pHideMultimediaKeysCheckBox->setChecked(fHide);
3664}
3665
3666void UISoftKeyboardSettingsWidget::setColorSelectionButtonBackgroundAndTooltip(KeyboardColorType enmColorType,
3667 const QColor &color, bool fIsColorEditable)
3668{
3669 if (m_colorSelectLabelsButtons.size() > enmColorType && m_colorSelectLabelsButtons[enmColorType].second)
3670 {
3671 UISoftKeyboardColorButton *pButton = m_colorSelectLabelsButtons[enmColorType].second;
3672 QPalette pal = pButton->palette();
3673 pal.setColor(QPalette::Button, color);
3674 pButton->setAutoFillBackground(true);
3675 pButton->setPalette(pal);
3676 pButton->setToolTip(fIsColorEditable ? UISoftKeyboard::tr("Click to change the color.") : UISoftKeyboard::tr("This color theme is not editable."));
3677 pButton->update();
3678 }
3679}
3680
3681void UISoftKeyboardSettingsWidget::setColorThemeNames(const QStringList &colorThemeNames)
3682{
3683 if (!m_pColorThemeComboBox)
3684 return;
3685 m_pColorThemeComboBox->blockSignals(true);
3686 m_pColorThemeComboBox->clear();
3687 foreach (const QString &strName, colorThemeNames)
3688 m_pColorThemeComboBox->addItem(strName);
3689 m_pColorThemeComboBox->blockSignals(false);
3690}
3691
3692void UISoftKeyboardSettingsWidget::setCurrentColorThemeName(const QString &strColorThemeName)
3693{
3694 if (!m_pColorThemeComboBox)
3695 return;
3696 int iItemIndex = m_pColorThemeComboBox->findText(strColorThemeName, Qt::MatchFixedString);
3697 if (iItemIndex == -1)
3698 return;
3699 m_pColorThemeComboBox->blockSignals(true);
3700 m_pColorThemeComboBox->setCurrentIndex(iItemIndex);
3701 m_pColorThemeComboBox->blockSignals(false);
3702}
3703
3704void UISoftKeyboardSettingsWidget::retranslateUi()
3705{
3706 if (m_pTitleLabel)
3707 m_pTitleLabel->setText(UISoftKeyboard::tr("Keyboard Settings"));
3708 if (m_pCloseButton)
3709 {
3710 m_pCloseButton->setToolTip(UISoftKeyboard::tr("Close the layout list"));
3711 m_pCloseButton->setText("Close");
3712 }
3713 if (m_pHideNumPadCheckBox)
3714 m_pHideNumPadCheckBox->setText(UISoftKeyboard::tr("Hide NumPad"));
3715 if (m_pShowOsMenuButtonsCheckBox)
3716 m_pShowOsMenuButtonsCheckBox->setText(UISoftKeyboard::tr("Hide OS/Menu Keys"));
3717 if (m_pHideMultimediaKeysCheckBox)
3718 m_pHideMultimediaKeysCheckBox->setText(UISoftKeyboard::tr("Hide Multimedia Keys"));
3719 if (m_pColorThemeGroupBox)
3720 m_pColorThemeGroupBox->setTitle(UISoftKeyboard::tr("Color Themes"));
3721
3722 if (m_colorSelectLabelsButtons.size() == KeyboardColorType_Max)
3723 {
3724 if (m_colorSelectLabelsButtons[KeyboardColorType_Background].first)
3725 m_colorSelectLabelsButtons[KeyboardColorType_Background].first->setText(UISoftKeyboard::tr("Button Background Color"));
3726 if (m_colorSelectLabelsButtons[KeyboardColorType_Font].first)
3727 m_colorSelectLabelsButtons[KeyboardColorType_Font].first->setText(UISoftKeyboard::tr("Button Font Color"));
3728 if (m_colorSelectLabelsButtons[KeyboardColorType_Hover].first)
3729 m_colorSelectLabelsButtons[KeyboardColorType_Hover].first->setText(UISoftKeyboard::tr("Button Hover Color"));
3730 if (m_colorSelectLabelsButtons[KeyboardColorType_Edit].first)
3731 m_colorSelectLabelsButtons[KeyboardColorType_Edit].first->setText(UISoftKeyboard::tr("Button Edit Color"));
3732 if (m_colorSelectLabelsButtons[KeyboardColorType_Pressed].first)
3733 m_colorSelectLabelsButtons[KeyboardColorType_Pressed].first->setText(UISoftKeyboard::tr("Pressed Button Font Color"));
3734 }
3735}
3736
3737void UISoftKeyboardSettingsWidget::prepareObjects()
3738{
3739 QGridLayout *pSettingsLayout = new QGridLayout;
3740 if (!pSettingsLayout)
3741 return;
3742
3743 QHBoxLayout *pTitleLayout = new QHBoxLayout;
3744 m_pCloseButton = new QToolButton;
3745 m_pCloseButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
3746 m_pCloseButton->setIcon(UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_DialogCancel));
3747 m_pCloseButton->setAutoRaise(true);
3748 connect(m_pCloseButton, &QToolButton::clicked, this, &UISoftKeyboardSettingsWidget::sigCloseSettingsWidget);
3749 m_pTitleLabel = new QLabel;
3750 pTitleLayout->addWidget(m_pTitleLabel);
3751 pTitleLayout->addStretch(2);
3752 pTitleLayout->addWidget(m_pCloseButton);
3753 pSettingsLayout->addLayout(pTitleLayout, 0, 0, 1, 2);
3754
3755 m_pHideNumPadCheckBox = new QCheckBox;
3756 m_pShowOsMenuButtonsCheckBox = new QCheckBox;
3757 m_pHideMultimediaKeysCheckBox = new QCheckBox;
3758 pSettingsLayout->addWidget(m_pHideNumPadCheckBox, 1, 0, 1, 1);
3759 pSettingsLayout->addWidget(m_pShowOsMenuButtonsCheckBox, 2, 0, 1, 1);
3760 pSettingsLayout->addWidget(m_pHideMultimediaKeysCheckBox, 3, 0, 1, 1);
3761 connect(m_pHideNumPadCheckBox, &QCheckBox::toggled, this, &UISoftKeyboardSettingsWidget::sigHideNumPad);
3762 connect(m_pShowOsMenuButtonsCheckBox, &QCheckBox::toggled, this, &UISoftKeyboardSettingsWidget::sigHideOSMenuKeys);
3763 connect(m_pHideMultimediaKeysCheckBox, &QCheckBox::toggled, this, &UISoftKeyboardSettingsWidget::sigHideMultimediaKeys);
3764
3765 /* A groupbox to host the color selection widgets: */
3766 m_pColorThemeGroupBox = new QGroupBox;
3767 QVBoxLayout *pGroupBoxLayout = new QVBoxLayout(m_pColorThemeGroupBox);
3768 pSettingsLayout->addWidget(m_pColorThemeGroupBox, 4, 0, 1, 1);
3769
3770 m_pColorThemeComboBox = new QComboBox;
3771 pGroupBoxLayout->addWidget(m_pColorThemeComboBox);
3772 connect(m_pColorThemeComboBox, &QComboBox::currentTextChanged, this, &UISoftKeyboardSettingsWidget::sigColorThemeSelectionChanged);
3773
3774 /* Creating and configuring the color selection buttons: */
3775 QGridLayout *pColorSelectionLayout = new QGridLayout;
3776 pColorSelectionLayout->setSpacing(1);
3777 pGroupBoxLayout->addLayout(pColorSelectionLayout);
3778 for (int i = KeyboardColorType_Background; i < KeyboardColorType_Max; ++i)
3779 {
3780 QLabel *pLabel = new QLabel;
3781 UISoftKeyboardColorButton *pButton = new UISoftKeyboardColorButton((KeyboardColorType)i);
3782 pButton->setFlat(true);
3783 pButton->setMaximumWidth(3 * qApp->style()->pixelMetric(QStyle::PM_LargeIconSize));
3784 pColorSelectionLayout->addWidget(pLabel, i, 0, 1, 1);
3785 pColorSelectionLayout->addWidget(pButton, i, 1, 1, 1);
3786 m_colorSelectLabelsButtons.append(ColorSelectLabelButton(pLabel, pButton));
3787 connect(pButton, &UISoftKeyboardColorButton::clicked, this, &UISoftKeyboardSettingsWidget::sltColorSelectionButtonClicked);
3788 }
3789
3790 QSpacerItem *pSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
3791 if (pSpacer)
3792 pSettingsLayout->addItem(pSpacer, 6, 0);
3793
3794 setLayout(pSettingsLayout);
3795 retranslateUi();
3796}
3797
3798void UISoftKeyboardSettingsWidget::sltColorSelectionButtonClicked()
3799{
3800 UISoftKeyboardColorButton *pButton = qobject_cast<UISoftKeyboardColorButton*>(sender());
3801 if (!pButton)
3802 return;
3803 emit sigColorCellClicked((int)pButton->colorType());
3804}
3805
3806
3807/*********************************************************************************************************************************
3808* UISoftKeyboard implementation. *
3809*********************************************************************************************************************************/
3810
3811UISoftKeyboard::UISoftKeyboard(QWidget *pParent,
3812 UISession *pSession, QWidget *pCenterWidget, QString strMachineName /* = QString()*/)
3813 : QMainWindowWithRestorableGeometryAndRetranslateUi(pParent)
3814 , m_pSession(pSession)
3815 , m_pCenterWidget(pCenterWidget)
3816 , m_pMainLayout(0)
3817 , m_strMachineName(strMachineName)
3818 , m_pSplitter(0)
3819 , m_pSidePanelWidget(0)
3820 , m_pKeyboardWidget(0)
3821 , m_pLayoutEditor(0)
3822 , m_pLayoutSelector(0)
3823 , m_pSettingsWidget(0)
3824 , m_pStatusBarWidget(0)
3825{
3826 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Soft Keyboard")));
3827 setAttribute(Qt::WA_DeleteOnClose);
3828 prepareObjects();
3829 prepareConnections();
3830
3831 if (m_pKeyboardWidget)
3832 {
3833 m_pKeyboardWidget->loadLayouts();
3834 if (m_pLayoutEditor)
3835 m_pLayoutEditor->setPhysicalLayoutList(m_pKeyboardWidget->physicalLayouts());
3836 }
3837
3838 loadSettings();
3839 configure();
3840 retranslateUi();
3841}
3842
3843UISoftKeyboard::~UISoftKeyboard()
3844{
3845 saveSettings();
3846 keyboard().ReleaseKeys();
3847}
3848
3849void UISoftKeyboard::retranslateUi()
3850{
3851}
3852
3853bool UISoftKeyboard::shouldBeMaximized() const
3854{
3855 return gEDataManager->softKeyboardDialogShouldBeMaximized();
3856}
3857
3858void UISoftKeyboard::closeEvent(QCloseEvent *event)
3859{
3860 QStringList strNameList = m_pKeyboardWidget->unsavedLayoutsNameList();
3861 /* Show a warning dialog when there are not saved layouts: */
3862 if (m_pKeyboardWidget && !strNameList.empty())
3863 {
3864 QString strJoinedString = strNameList.join("<br/>");
3865 if (msgCenter().questionBinary(this, MessageType_Warning,
3866 tr("<p>Following layouts are edited/copied but not saved:</p>%1"
3867 "<p>Closing this dialog will cause loosing the changes. Proceed?</p>").arg(strJoinedString),
3868 0 /* auto-confirm id */,
3869 "Ok", "Cancel"))
3870 QMainWindowWithRestorableGeometryAndRetranslateUi::closeEvent(event);
3871 else
3872 event->ignore();
3873 return;
3874 }
3875 QMainWindowWithRestorableGeometryAndRetranslateUi::closeEvent(event);
3876}
3877
3878bool UISoftKeyboard::event(QEvent *pEvent)
3879{
3880 if (pEvent->type() == QEvent::WindowDeactivate)
3881 {
3882 if (m_pKeyboardWidget)
3883 m_pKeyboardWidget->parentDialogDeactivated();
3884 }
3885 return QMainWindowWithRestorableGeometryAndRetranslateUi::event(pEvent);
3886}
3887
3888void UISoftKeyboard::sltKeyboardLedsChange()
3889{
3890 bool fNumLockLed = m_pSession->isNumLock();
3891 bool fCapsLockLed = m_pSession->isCapsLock();
3892 bool fScrollLockLed = m_pSession->isScrollLock();
3893 if (m_pKeyboardWidget)
3894 m_pKeyboardWidget->updateLockKeyStates(fCapsLockLed, fNumLockLed, fScrollLockLed);
3895}
3896
3897void UISoftKeyboard::sltPutKeyboardSequence(QVector<LONG> sequence)
3898{
3899 keyboard().PutScancodes(sequence);
3900}
3901
3902void UISoftKeyboard::sltPutUsageCodesPress(QVector<QPair<LONG, LONG> > sequence)
3903{
3904 for (int i = 0; i < sequence.size(); ++i)
3905 keyboard().PutUsageCode(sequence[i].first, sequence[i].second, false);
3906}
3907
3908void UISoftKeyboard::sltPutUsageCodesRelease(QVector<QPair<LONG, LONG> > sequence)
3909{
3910 for (int i = 0; i < sequence.size(); ++i)
3911 keyboard().PutUsageCode(sequence[i].first, sequence[i].second, true);
3912}
3913
3914void UISoftKeyboard::sltLayoutSelectionChanged(const QUuid &layoutUid)
3915{
3916 if (!m_pKeyboardWidget)
3917 return;
3918 m_pKeyboardWidget->setCurrentLayout(layoutUid);
3919 if (m_pLayoutSelector && m_pKeyboardWidget->currentLayout())
3920 m_pLayoutSelector->setCurrentLayoutIsEditable(m_pKeyboardWidget->currentLayout()->editable());
3921}
3922
3923void UISoftKeyboard::sltCurentLayoutChanged()
3924{
3925 if (!m_pKeyboardWidget)
3926 return;
3927 UISoftKeyboardLayout *pCurrentLayout = m_pKeyboardWidget->currentLayout();
3928
3929 /* Update the status bar string: */
3930 if (!pCurrentLayout)
3931 return;
3932 updateStatusBarMessage(pCurrentLayout->nameString());
3933}
3934
3935void UISoftKeyboard::sltShowLayoutSelector()
3936{
3937 if (m_pSidePanelWidget && m_pLayoutSelector)
3938 m_pSidePanelWidget->setCurrentWidget(m_pLayoutSelector);
3939 if (m_pKeyboardWidget)
3940 m_pKeyboardWidget->toggleEditMode(false);
3941 if (m_pLayoutEditor)
3942 m_pLayoutEditor->setKey(0);
3943}
3944
3945void UISoftKeyboard::sltShowLayoutEditor()
3946{
3947 if (m_pSidePanelWidget && m_pLayoutEditor)
3948 {
3949 m_pLayoutEditor->setLayoutToEdit(m_pKeyboardWidget->currentLayout());
3950 m_pSidePanelWidget->setCurrentWidget(m_pLayoutEditor);
3951 }
3952 if (m_pKeyboardWidget)
3953 m_pKeyboardWidget->toggleEditMode(true);
3954}
3955
3956void UISoftKeyboard::sltKeyToEditChanged(UISoftKeyboardKey* pKey)
3957{
3958 if (m_pLayoutEditor)
3959 m_pLayoutEditor->setKey(pKey);
3960}
3961
3962void UISoftKeyboard::sltLayoutEdited()
3963{
3964 if (!m_pKeyboardWidget)
3965 return;
3966 m_pKeyboardWidget->update();
3967 updateLayoutSelectorList();
3968 UISoftKeyboardLayout *pCurrentLayout = m_pKeyboardWidget->currentLayout();
3969
3970 /* Update the status bar string: */
3971 QString strLayoutName = pCurrentLayout ? pCurrentLayout->name() : QString();
3972 updateStatusBarMessage(strLayoutName);
3973}
3974
3975void UISoftKeyboard::sltKeyCaptionsEdited(UISoftKeyboardKey* pKey)
3976{
3977 Q_UNUSED(pKey);
3978 if (m_pKeyboardWidget)
3979 m_pKeyboardWidget->update();
3980}
3981
3982void UISoftKeyboard::sltShowHideSidePanel()
3983{
3984 if (!m_pSidePanelWidget)
3985 return;
3986 m_pSidePanelWidget->setVisible(!m_pSidePanelWidget->isVisible());
3987
3988 if (m_pSidePanelWidget->isVisible() && m_pSettingsWidget->isVisible())
3989 m_pSettingsWidget->setVisible(false);
3990}
3991
3992void UISoftKeyboard::sltShowHideSettingsWidget()
3993{
3994 if (!m_pSettingsWidget)
3995 return;
3996 m_pSettingsWidget->setVisible(!m_pSettingsWidget->isVisible());
3997 if (m_pSidePanelWidget->isVisible() && m_pSettingsWidget->isVisible())
3998 m_pSidePanelWidget->setVisible(false);
3999}
4000
4001void UISoftKeyboard::sltHandleColorThemeListSelection(const QString &strColorThemeName)
4002{
4003 if (m_pKeyboardWidget)
4004 m_pKeyboardWidget->setColorThemeByName(strColorThemeName);
4005}
4006
4007void UISoftKeyboard::sltHandleKeyboardWidgetColorThemeChange()
4008{
4009 for (int i = (int)KeyboardColorType_Background;
4010 i < (int)KeyboardColorType_Max; ++i)
4011 {
4012 KeyboardColorType enmType = (KeyboardColorType)i;
4013 m_pSettingsWidget->setColorSelectionButtonBackgroundAndTooltip(enmType,
4014 m_pKeyboardWidget->color(enmType),
4015 m_pKeyboardWidget->isColorThemeEditable());
4016 }
4017}
4018
4019void UISoftKeyboard::sltCopyLayout()
4020{
4021 if (!m_pKeyboardWidget)
4022 return;
4023 m_pKeyboardWidget->copyCurentLayout();
4024 updateLayoutSelectorList();
4025}
4026
4027void UISoftKeyboard::sltSaveLayout()
4028{
4029 if (m_pKeyboardWidget)
4030 m_pKeyboardWidget->saveCurentLayoutToFile();
4031}
4032
4033void UISoftKeyboard::sltDeleteLayout()
4034{
4035 if (m_pKeyboardWidget)
4036 m_pKeyboardWidget->deleteCurrentLayout();
4037 updateLayoutSelectorList();
4038 if (m_pKeyboardWidget && m_pKeyboardWidget->currentLayout() && m_pLayoutSelector)
4039 {
4040 m_pLayoutSelector->setCurrentLayout(m_pKeyboardWidget->currentLayout()->uid());
4041 m_pLayoutSelector->setCurrentLayoutIsEditable(m_pKeyboardWidget->currentLayout()->editable());
4042 }
4043}
4044
4045void UISoftKeyboard::sltStatusBarMessage(const QString &strMessage)
4046{
4047 statusBar()->showMessage(strMessage, iMessageTimeout);
4048}
4049
4050void UISoftKeyboard::sltShowHideOSMenuKeys(bool fHide)
4051{
4052 if (m_pKeyboardWidget)
4053 m_pKeyboardWidget->setHideOSMenuKeys(fHide);
4054}
4055
4056void UISoftKeyboard::sltShowHideNumPad(bool fHide)
4057{
4058 if (m_pKeyboardWidget)
4059 m_pKeyboardWidget->setHideNumPad(fHide);
4060}
4061
4062void UISoftKeyboard::sltShowHideMultimediaKeys(bool fHide)
4063{
4064 if (m_pKeyboardWidget)
4065 m_pKeyboardWidget->setHideMultimediaKeys(fHide);
4066}
4067
4068void UISoftKeyboard::sltHandleColorCellClick(int iColorRow)
4069{
4070 if (!m_pKeyboardWidget || iColorRow >= static_cast<int>(KeyboardColorType_Max))
4071 return;
4072
4073 if (!m_pKeyboardWidget->isColorThemeEditable())
4074 return;
4075 const QColor &currentColor = m_pKeyboardWidget->color(static_cast<KeyboardColorType>(iColorRow));
4076 QColorDialog colorDialog(currentColor, this);
4077
4078 if (colorDialog.exec() == QDialog::Rejected)
4079 return;
4080 QColor newColor = colorDialog.selectedColor();
4081 if (currentColor == newColor)
4082 return;
4083 m_pKeyboardWidget->setColor(static_cast<KeyboardColorType>(iColorRow), newColor);
4084 m_pSettingsWidget->setColorSelectionButtonBackgroundAndTooltip(static_cast<KeyboardColorType>(iColorRow),
4085 newColor, m_pKeyboardWidget->isColorThemeEditable());
4086}
4087
4088void UISoftKeyboard::sltResetKeyboard()
4089{
4090 if (m_pKeyboardWidget)
4091 m_pKeyboardWidget->reset();
4092 if (m_pLayoutEditor)
4093 m_pLayoutEditor->reset();
4094 keyboard().ReleaseKeys();
4095 update();
4096}
4097
4098void UISoftKeyboard::prepareObjects()
4099{
4100 m_pSplitter = new QSplitter;
4101 if (!m_pSplitter)
4102 return;
4103 setCentralWidget(m_pSplitter);
4104 m_pSidePanelWidget = new QStackedWidget;
4105 if (!m_pSidePanelWidget)
4106 return;
4107
4108 m_pSidePanelWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
4109 m_pSidePanelWidget->hide();
4110
4111 m_pLayoutSelector = new UILayoutSelector;
4112 if (m_pLayoutSelector)
4113 m_pSidePanelWidget->addWidget(m_pLayoutSelector);
4114
4115 m_pLayoutEditor = new UIKeyboardLayoutEditor;
4116 if (m_pLayoutEditor)
4117 m_pSidePanelWidget->addWidget(m_pLayoutEditor);
4118
4119 m_pSettingsWidget = new UISoftKeyboardSettingsWidget;
4120 if (m_pSettingsWidget)
4121 {
4122 m_pSettingsWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
4123 m_pSettingsWidget->hide();
4124 }
4125 m_pKeyboardWidget = new UISoftKeyboardWidget;
4126 if (!m_pKeyboardWidget)
4127 return;
4128 m_pKeyboardWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
4129 m_pKeyboardWidget->updateGeometry();
4130 m_pSplitter->addWidget(m_pKeyboardWidget);
4131 m_pSplitter->addWidget(m_pSidePanelWidget);
4132 m_pSplitter->addWidget(m_pSettingsWidget);
4133
4134 m_pSplitter->setCollapsible(0, false);
4135 m_pSplitter->setCollapsible(1, false);
4136 m_pSplitter->setCollapsible(2, false);
4137
4138 statusBar()->setStyleSheet( "QStatusBar::item { border: 0px}" );
4139 m_pStatusBarWidget = new UISoftKeyboardStatusBarWidget;
4140 statusBar()->addPermanentWidget(m_pStatusBarWidget);
4141
4142 retranslateUi();
4143}
4144
4145void UISoftKeyboard::prepareConnections()
4146{
4147 connect(m_pSession, &UISession::sigKeyboardLedsChange, this, &UISoftKeyboard::sltKeyboardLedsChange);
4148 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigPutKeyboardSequence, this, &UISoftKeyboard::sltPutKeyboardSequence);
4149 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigPutUsageCodesPress, this, &UISoftKeyboard::sltPutUsageCodesPress);
4150 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigPutUsageCodesRelease, this, &UISoftKeyboard::sltPutUsageCodesRelease);
4151
4152 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigCurrentLayoutChange, this, &UISoftKeyboard::sltCurentLayoutChanged);
4153 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigKeyToEdit, this, &UISoftKeyboard::sltKeyToEditChanged);
4154 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigStatusBarMessage, this, &UISoftKeyboard::sltStatusBarMessage);
4155 connect(m_pKeyboardWidget, &UISoftKeyboardWidget::sigCurrentColorThemeChanged, this, &UISoftKeyboard::sltHandleKeyboardWidgetColorThemeChange);
4156
4157 connect(m_pLayoutSelector, &UILayoutSelector::sigLayoutSelectionChanged, this, &UISoftKeyboard::sltLayoutSelectionChanged);
4158 connect(m_pLayoutSelector, &UILayoutSelector::sigShowLayoutEditor, this, &UISoftKeyboard::sltShowLayoutEditor);
4159 connect(m_pLayoutSelector, &UILayoutSelector::sigCloseLayoutList, this, &UISoftKeyboard::sltShowHideSidePanel);
4160 connect(m_pLayoutSelector, &UILayoutSelector::sigSaveLayout, this, &UISoftKeyboard::sltSaveLayout);
4161 connect(m_pLayoutSelector, &UILayoutSelector::sigDeleteLayout, this, &UISoftKeyboard::sltDeleteLayout);
4162 connect(m_pLayoutSelector, &UILayoutSelector::sigCopyLayout, this, &UISoftKeyboard::sltCopyLayout);
4163 connect(m_pLayoutEditor, &UIKeyboardLayoutEditor::sigGoBackButton, this, &UISoftKeyboard::sltShowLayoutSelector);
4164 connect(m_pLayoutEditor, &UIKeyboardLayoutEditor::sigLayoutEdited, this, &UISoftKeyboard::sltLayoutEdited);
4165 connect(m_pLayoutEditor, &UIKeyboardLayoutEditor::sigUIKeyCaptionsEdited, this, &UISoftKeyboard::sltKeyCaptionsEdited);
4166
4167 connect(m_pStatusBarWidget, &UISoftKeyboardStatusBarWidget::sigShowHideSidePanel, this, &UISoftKeyboard::sltShowHideSidePanel);
4168 connect(m_pStatusBarWidget, &UISoftKeyboardStatusBarWidget::sigShowSettingWidget, this, &UISoftKeyboard::sltShowHideSettingsWidget);
4169 connect(m_pStatusBarWidget, &UISoftKeyboardStatusBarWidget::sigResetKeyboard, this, &UISoftKeyboard::sltResetKeyboard);
4170
4171 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigHideOSMenuKeys, this, &UISoftKeyboard::sltShowHideOSMenuKeys);
4172 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigHideNumPad, this, &UISoftKeyboard::sltShowHideNumPad);
4173 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigHideMultimediaKeys, this, &UISoftKeyboard::sltShowHideMultimediaKeys);
4174 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigColorCellClicked, this, &UISoftKeyboard::sltHandleColorCellClick);
4175 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigCloseSettingsWidget, this, &UISoftKeyboard::sltShowHideSettingsWidget);
4176 connect(m_pSettingsWidget, &UISoftKeyboardSettingsWidget::sigColorThemeSelectionChanged, this, &UISoftKeyboard::sltHandleColorThemeListSelection);
4177}
4178
4179void UISoftKeyboard::saveSettings()
4180{
4181 /* Save geometry to extradata: */
4182 const QRect geo = currentGeometry();
4183 LogRel2(("GUI: UISoftKeyboard: Saving geometry as: Origin=%dx%d, Size=%dx%d\n",
4184 geo.x(), geo.y(), geo.width(), geo.height()));
4185 gEDataManager->setSoftKeyboardDialogGeometry(geo, isCurrentlyMaximized());
4186
4187 /* Save other settings: */
4188 if (m_pKeyboardWidget)
4189 {
4190 /* Save the changes to the 'Custom' color theme to extra data: */
4191 QStringList colors = m_pKeyboardWidget->colorsToStringList("Custom");
4192 colors.prepend("Custom");
4193 gEDataManager->setSoftKeyboardColorTheme(colors);
4194 gEDataManager->setSoftKeyboardSelectedColorTheme(m_pKeyboardWidget->currentColorThemeName());
4195 gEDataManager->setSoftKeyboardOptions(m_pKeyboardWidget->hideNumPad(),
4196 m_pKeyboardWidget->hideOSMenuKeys(),
4197 m_pKeyboardWidget->hideMultimediaKeys());
4198 if (m_pKeyboardWidget->currentLayout())
4199 gEDataManager->setSoftKeyboardSelectedLayout(m_pKeyboardWidget->currentLayout()->uid());
4200 }
4201}
4202
4203void UISoftKeyboard::loadSettings()
4204{
4205 /* Invent default window geometry: */
4206 float fKeyboardAspectRatio = 1.0f;
4207 if (m_pKeyboardWidget)
4208 fKeyboardAspectRatio = m_pKeyboardWidget->layoutAspectRatio();
4209 const QRect availableGeo = gpDesktop->availableGeometry(this);
4210 const int iDefaultWidth = availableGeo.width() / 2;
4211 const int iDefaultHeight = iDefaultWidth * fKeyboardAspectRatio;
4212 QRect defaultGeo(0, 0, iDefaultWidth, iDefaultHeight);
4213
4214 /* Load geometry from extradata: */
4215 const QRect geo = gEDataManager->softKeyboardDialogGeometry(this, m_pCenterWidget, defaultGeo);
4216 LogRel2(("GUI: UISoftKeyboard: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
4217 geo.x(), geo.y(), geo.width(), geo.height()));
4218 restoreGeometry(geo);
4219
4220 /* Load other settings: */
4221 if (m_pKeyboardWidget)
4222 {
4223 QStringList colorTheme = gEDataManager->softKeyboardColorTheme();
4224 if (!colorTheme.empty())
4225 {
4226 /* The fist item is the theme name and the rest are color codes: */
4227 QString strThemeName = colorTheme[0];
4228 colorTheme.removeFirst();
4229 m_pKeyboardWidget->colorsFromStringList(strThemeName, colorTheme);
4230 }
4231 m_pKeyboardWidget->setColorThemeByName(gEDataManager->softKeyboardSelectedColorTheme());
4232 m_pKeyboardWidget->setCurrentLayout(gEDataManager->softKeyboardSelectedLayout());
4233
4234 /* Load other options from exra data: */
4235 bool fHideNumPad = false;
4236 bool fHideOSMenuKeys = false;
4237 bool fHideMultimediaKeys = false;
4238 gEDataManager->softKeyboardOptions(fHideNumPad, fHideOSMenuKeys, fHideMultimediaKeys);
4239 m_pKeyboardWidget->setHideNumPad(fHideNumPad);
4240 m_pKeyboardWidget->setHideOSMenuKeys(fHideOSMenuKeys);
4241 m_pKeyboardWidget->setHideMultimediaKeys(fHideMultimediaKeys);
4242 }
4243}
4244
4245void UISoftKeyboard::configure()
4246{
4247 setWindowIcon(UIIconPool::iconSet(":/soft_keyboard_16px.png"));
4248 if (m_pKeyboardWidget && m_pSettingsWidget)
4249 {
4250 m_pSettingsWidget->setHideOSMenuKeys(m_pKeyboardWidget->hideOSMenuKeys());
4251 m_pSettingsWidget->setHideNumPad(m_pKeyboardWidget->hideNumPad());
4252 m_pSettingsWidget->setHideMultimediaKeys(m_pKeyboardWidget->hideMultimediaKeys());
4253
4254 m_pSettingsWidget->setColorThemeNames(m_pKeyboardWidget->colorThemeNames());
4255 m_pSettingsWidget->setCurrentColorThemeName(m_pKeyboardWidget->currentColorThemeName());
4256
4257 for (int i = (int)KeyboardColorType_Background;
4258 i < (int)KeyboardColorType_Max; ++i)
4259 {
4260 KeyboardColorType enmType = (KeyboardColorType)i;
4261 m_pSettingsWidget->setColorSelectionButtonBackgroundAndTooltip(enmType,
4262 m_pKeyboardWidget->color(enmType),
4263 m_pKeyboardWidget->isColorThemeEditable());
4264 }
4265 }
4266 updateLayoutSelectorList();
4267 if (m_pKeyboardWidget && m_pKeyboardWidget->currentLayout() && m_pLayoutSelector)
4268 {
4269 m_pLayoutSelector->setCurrentLayout(m_pKeyboardWidget->currentLayout()->uid());
4270 m_pLayoutSelector->setCurrentLayoutIsEditable(m_pKeyboardWidget->currentLayout()->editable());
4271 }
4272}
4273
4274void UISoftKeyboard::updateStatusBarMessage(const QString &strName)
4275{
4276 if (!m_pStatusBarWidget)
4277 return;
4278 QString strMessage;
4279 if (!strName.isEmpty())
4280 {
4281 strMessage += QString("%1: %2").arg(tr("Layout")).arg(strName);
4282 m_pStatusBarWidget->updateLayoutNameInStatusBar(strMessage);
4283 }
4284 else
4285 m_pStatusBarWidget->updateLayoutNameInStatusBar(QString());
4286}
4287
4288void UISoftKeyboard::updateLayoutSelectorList()
4289{
4290 if (!m_pKeyboardWidget || !m_pLayoutSelector)
4291 return;
4292 m_pLayoutSelector->setLayoutList(m_pKeyboardWidget->layoutNameList(), m_pKeyboardWidget->layoutUidList());
4293}
4294
4295CKeyboard& UISoftKeyboard::keyboard() const
4296{
4297 return m_pSession->keyboard();
4298}
4299
4300#include "UISoftKeyboard.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use