1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qplatformtheme.h"
41 
42 #include "qplatformtheme_p.h"
43 
44 #include <QtCore/QVariant>
45 #include <QtCore/QStringList>
46 #include <QtCore/qfileinfo.h>
47 #include <qicon.h>
48 #include <qpalette.h>
49 #include <qtextformat.h>
50 #include <private/qiconloader_p.h>
51 #include <private/qguiapplication_p.h>
52 #include <qpa/qplatformintegration.h>
53 #include <qpa/qplatformdialoghelper.h>
54 
55 #include <algorithm>
56 
57 QT_BEGIN_NAMESPACE
58 
59 /*!
60     \class QPlatformTheme
61     \since 5.0
62     \internal
63     \preliminary
64     \ingroup qpa
65     \brief The QPlatformTheme class allows customizing the UI based on themes.
66 
67 */
68 
69 /*!
70     \enum QPlatformTheme::ThemeHint
71 
72     This enum describes the available theme hints.
73 
74     \value CursorFlashTime (int) Cursor flash time in ms, overriding
75                                  QPlatformIntegration::styleHint.
76 
77     \value KeyboardInputInterval (int) Keyboard input interval in ms, overriding
78                                  QPlatformIntegration::styleHint.
79 
80     \value MouseDoubleClickInterval (int) Mouse double click interval in ms,
81                                     overriding QPlatformIntegration::styleHint.
82 
83     \value MouseDoubleClickDistance (int) The maximum distance in logical pixels which the mouse can travel
84                         between clicks in order for the click sequence to be handled as a double click.
85                         The default value is 5 logical pixels.
86 
87     \value MousePressAndHoldInterval (int) Mouse press and hold interval in ms,
88                                     overriding QPlatformIntegration::styleHint.
89 
90     \value StartDragDistance (int) Start drag distance,
91                              overriding QPlatformIntegration::styleHint.
92 
93     \value StartDragTime (int) Start drag time in ms,
94                                overriding QPlatformIntegration::styleHint.
95 
96     \value WheelScrollLines (int) The number of lines to scroll a widget, when the mouse wheel is rotated.
97                         The default value is 3.  \sa QApplication::wheelScrollLines()
98 
99     \value KeyboardAutoRepeatRate (int) Keyboard auto repeat rate,
100                                   overriding QPlatformIntegration::styleHint.
101 
102     \value PasswordMaskDelay (int) Pass word mask delay in ms,
103                                    overriding QPlatformIntegration::styleHint.
104 
105     \value StartDragVelocity (int) Velocity of a drag,
106                                    overriding QPlatformIntegration::styleHint.
107 
108     \value TextCursorWidth  (int) Determines the width of the text cursor.
109 
110     \value DropShadow       (bool) Determines whether the drop shadow effect for
111                             tooltips or whatsthis is enabled.
112 
113     \value MaximumScrollBarDragDistance (int) Determines the value returned by
114                             QStyle::pixelMetric(PM_MaximumDragDistance)
115 
116     \value ToolButtonStyle (int) A value representing a Qt::ToolButtonStyle.
117 
118     \value ToolBarIconSize Icon size for tool bars.
119 
120     \value SystemIconThemeName (QString) Name of the icon theme.
121 
122     \value SystemIconFallbackThemeName (QString) Name of the fallback icon theme.
123 
124     \value IconThemeSearchPaths (QStringList) Search paths for icons.
125 
126     \value ItemViewActivateItemOnSingleClick (bool) Activate items by single click.
127 
128     \value StyleNames (QStringList) A list of preferred style names.
129 
130     \value WindowAutoPlacement (bool) A boolean value indicating whether Windows
131                                (particularly dialogs) are placed by the system
132                                (see _NET_WM_FULL_PLACEMENT in X11).
133 
134     \value DialogButtonBoxLayout (int) An integer representing a
135                                  QDialogButtonBox::ButtonLayout value.
136 
137     \value DialogButtonBoxButtonsHaveIcons (bool) A boolean value indicating whether
138                                             the buttons of a QDialogButtonBox should have icons.
139 
140     \value UseFullScreenForPopupMenu (bool) Pop menus can cover the full screen including task bar.
141 
142     \value KeyboardScheme (int) An integer value (enum KeyboardSchemes) specifying the
143                            keyboard scheme.
144 
145     \value UiEffects (int) A flag value consisting of UiEffect values specifying the enabled UI animations.
146 
147     \value SpellCheckUnderlineStyle (int) A QTextCharFormat::UnderlineStyle specifying
148                                     the underline style used misspelled words when spell checking.
149 
150     \value TabFocusBehavior (int) A Qt::TabFocusBehavior specifying
151                          the behavior of focus change when tab key was pressed.
152                          This enum value was added in Qt 5.5.
153 
154     \value DialogSnapToDefaultButton (bool) Whether the mouse should snap to the default button when a dialog
155                                      becomes visible.
156 
157     \value ContextMenuOnMouseRelease (bool) Whether the context menu should be shown on mouse release.
158 
159     \value TouchDoubleTapDistance (int) The maximum distance in logical pixels which a touchpoint can travel
160                         between taps in order for the tap sequence to be handled as a double tap.
161                         The default value is double the MouseDoubleClickDistance, or 10 logical pixels
162                         if that is not specified.
163 
164     \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.
165 
166     \sa themeHint(), QStyle::pixelMetric()
167 */
168 
169 
170 #ifndef QT_NO_SHORTCUT
171 // Table of key bindings. It must be sorted on key sequence:
172 // The integer value of VK_KEY | Modifier Keys (e.g., VK_META, and etc.)
173 // A priority of 1 indicates that this is the primary key binding when multiple are defined.
174 
175 enum KeyPlatform {
176     KB_Win = (1 << QPlatformTheme::WindowsKeyboardScheme),
177     KB_Mac = (1 << QPlatformTheme::MacKeyboardScheme),
178     KB_X11 = (1 << QPlatformTheme::X11KeyboardScheme),
179     KB_KDE = (1 << QPlatformTheme::KdeKeyboardScheme),
180     KB_Gnome = (1 << QPlatformTheme::GnomeKeyboardScheme),
181     KB_CDE = (1 << QPlatformTheme::CdeKeyboardScheme),
182     KB_All = 0xffff
183 };
184 
185 const QKeyBinding QPlatformThemePrivate::keyBindings[] = {
186     //   StandardKey                            Priority    Key Sequence                            Platforms
187     {QKeySequence::HelpContents,            1,          Qt::CTRL | Qt::Key_Question,            KB_Mac},
188     {QKeySequence::HelpContents,            0,          Qt::Key_F1,                             KB_Win | KB_X11},
189     {QKeySequence::WhatsThis,               1,          Qt::SHIFT | Qt::Key_F1,                 KB_All},
190     {QKeySequence::Open,                    1,          Qt::CTRL | Qt::Key_O,                   KB_All},
191     {QKeySequence::Close,                   0,          Qt::CTRL | Qt::Key_F4,                  KB_Mac},
192     {QKeySequence::Close,                   1,          Qt::CTRL | Qt::Key_F4,                  KB_Win},
193     {QKeySequence::Close,                   1,          Qt::CTRL | Qt::Key_W,                   KB_Mac},
194     {QKeySequence::Close,                   0,          Qt::CTRL | Qt::Key_W,                   KB_Win | KB_X11},
195     {QKeySequence::Save,                    1,          Qt::CTRL | Qt::Key_S,                   KB_All},
196     {QKeySequence::New,                     1,          Qt::CTRL | Qt::Key_N,                   KB_All},
197     {QKeySequence::Delete,                  0,          Qt::CTRL | Qt::Key_D,                   KB_X11}, //emacs (line edit only)
198     {QKeySequence::Delete,                  1,          Qt::Key_Delete,                         KB_All},
199     {QKeySequence::Delete,                  0,          Qt::META | Qt::Key_D,                   KB_Mac},
200     {QKeySequence::Cut,                     1,          Qt::CTRL | Qt::Key_X,                   KB_All},
201     {QKeySequence::Cut,                     0,          Qt::SHIFT | Qt::Key_Delete,             KB_Win | KB_X11}, //## Check if this should work on mac
202     {QKeySequence::Cut,                     0,          Qt::Key_F20,                            KB_X11}, //Cut on sun keyboards
203     {QKeySequence::Cut,                     0,          Qt::META | Qt::Key_K,                   KB_Mac},
204     {QKeySequence::Copy,                    0,          Qt::CTRL | Qt::Key_Insert,              KB_X11 | KB_Win},
205     {QKeySequence::Copy,                    1,          Qt::CTRL | Qt::Key_C,                   KB_All},
206     {QKeySequence::Copy,                    0,          Qt::Key_F16,                            KB_X11}, //Copy on sun keyboards
207     {QKeySequence::Paste,                   0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Insert,  KB_X11},
208     {QKeySequence::Paste,                   1,          Qt::CTRL | Qt::Key_V,                   KB_All},
209     {QKeySequence::Paste,                   0,          Qt::SHIFT | Qt::Key_Insert,             KB_Win | KB_X11},
210     {QKeySequence::Paste,                   0,          Qt::Key_F18,                            KB_X11}, //Paste on sun keyboards
211     {QKeySequence::Paste,                   0,          Qt::META | Qt::Key_Y,                   KB_Mac},
212     {QKeySequence::Undo,                    0,          Qt::ALT  | Qt::Key_Backspace,           KB_Win},
213     {QKeySequence::Undo,                    1,          Qt::CTRL | Qt::Key_Z,                   KB_All},
214     {QKeySequence::Undo,                    0,          Qt::Key_F14,                            KB_X11}, //Undo on sun keyboards
215     {QKeySequence::Redo,                    0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Backspace,KB_Win},
216     {QKeySequence::Redo,                    0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Z,       KB_Mac},
217     {QKeySequence::Redo,                    0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Z,       KB_Win | KB_X11},
218     {QKeySequence::Redo,                    1,          Qt::CTRL | Qt::Key_Y,                   KB_Win},
219     {QKeySequence::Back,                    1,          Qt::ALT  | Qt::Key_Left,                KB_Win | KB_X11},
220     {QKeySequence::Back,                    0,          Qt::CTRL | Qt::Key_Left,                KB_Mac},
221     {QKeySequence::Back,                    1,          Qt::CTRL | Qt::Key_BracketLeft,         KB_Mac},
222     {QKeySequence::Back,                    0,          Qt::Key_Backspace,                      KB_Win},
223     {QKeySequence::Forward,                 1,          Qt::ALT  | Qt::Key_Right,               KB_Win | KB_X11},
224     {QKeySequence::Forward,                 0,          Qt::CTRL | Qt::Key_Right,               KB_Mac},
225     {QKeySequence::Forward,                 1,          Qt::CTRL | Qt::Key_BracketRight,        KB_Mac},
226     {QKeySequence::Forward,                 0,          Qt::SHIFT | Qt::Key_Backspace,          KB_Win},
227     {QKeySequence::Refresh,                 1,          Qt::CTRL | Qt::Key_R,                   KB_Gnome | KB_Mac},
228     {QKeySequence::Refresh,                 0,          Qt::Key_F5,                             KB_Win | KB_X11},
229     {QKeySequence::ZoomIn,                  1,          Qt::CTRL | Qt::Key_Plus,                KB_All},
230     {QKeySequence::ZoomOut,                 1,          Qt::CTRL | Qt::Key_Minus,               KB_All},
231     {QKeySequence::Print,                   1,          Qt::CTRL | Qt::Key_P,                   KB_All},
232     {QKeySequence::AddTab,                  1,          Qt::CTRL | Qt::SHIFT | Qt::Key_N,       KB_KDE},
233     {QKeySequence::AddTab,                  0,          Qt::CTRL | Qt::Key_T,                   KB_All},
234     {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_F6,                  KB_Win},
235     {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_Tab,                 KB_Mac}, //different priority from above
236     {QKeySequence::NextChild,               1,          Qt::CTRL | Qt::Key_Tab,                 KB_Win | KB_X11},
237     {QKeySequence::NextChild,               1,          Qt::CTRL | Qt::Key_BraceRight,          KB_Mac},
238     {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_Comma,               KB_KDE},
239     {QKeySequence::NextChild,               0,          Qt::Key_Forward,                        KB_All},
240     {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::SHIFT | Qt::Key_F6,      KB_Win},
241     {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, KB_Mac },//different priority from above
242     {QKeySequence::PreviousChild,           1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, KB_Win | KB_X11},
243     {QKeySequence::PreviousChild,           1,          Qt::CTRL | Qt::Key_BraceLeft,           KB_Mac},
244     {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::Key_Period,              KB_KDE},
245     {QKeySequence::PreviousChild,           0,          Qt::Key_Back,                           KB_All},
246     {QKeySequence::Find,                    0,          Qt::CTRL | Qt::Key_F,                   KB_All},
247     {QKeySequence::FindNext,                0,          Qt::CTRL | Qt::Key_G,                   KB_Win},
248     {QKeySequence::FindNext,                1,          Qt::CTRL | Qt::Key_G,                   KB_Gnome | KB_Mac},
249     {QKeySequence::FindNext,                1,          Qt::Key_F3,                             KB_Win},
250     {QKeySequence::FindNext,                0,          Qt::Key_F3,                             KB_X11},
251     {QKeySequence::FindPrevious,            0,          Qt::CTRL | Qt::SHIFT | Qt::Key_G,       KB_Win},
252     {QKeySequence::FindPrevious,            1,          Qt::CTRL | Qt::SHIFT | Qt::Key_G,       KB_Gnome | KB_Mac},
253     {QKeySequence::FindPrevious,            1,          Qt::SHIFT | Qt::Key_F3,                 KB_Win},
254     {QKeySequence::FindPrevious,            0,          Qt::SHIFT | Qt::Key_F3,                 KB_X11},
255     {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_R,                   KB_KDE},
256     {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_H,                   KB_Gnome},
257     {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_H,                   KB_Win},
258     {QKeySequence::SelectAll,               1,          Qt::CTRL | Qt::Key_A,                   KB_All},
259     {QKeySequence::Bold,                    1,          Qt::CTRL | Qt::Key_B,                   KB_All},
260     {QKeySequence::Italic,                  0,          Qt::CTRL | Qt::Key_I,                   KB_All},
261     {QKeySequence::Underline,               1,          Qt::CTRL | Qt::Key_U,                   KB_All},
262     {QKeySequence::MoveToNextChar,          1,          Qt::Key_Right,                          KB_All},
263     {QKeySequence::MoveToNextChar,          0,          Qt::META | Qt::Key_F,                   KB_Mac},
264     {QKeySequence::MoveToPreviousChar,      1,          Qt::Key_Left,                           KB_All},
265     {QKeySequence::MoveToPreviousChar,      0,          Qt::META | Qt::Key_B,                   KB_Mac},
266     {QKeySequence::MoveToNextWord,          0,          Qt::ALT  | Qt::Key_Right,               KB_Mac},
267     {QKeySequence::MoveToNextWord,          0,          Qt::CTRL | Qt::Key_Right,               KB_Win | KB_X11},
268     {QKeySequence::MoveToPreviousWord,      0,          Qt::ALT  | Qt::Key_Left,                KB_Mac},
269     {QKeySequence::MoveToPreviousWord,      0,          Qt::CTRL | Qt::Key_Left,                KB_Win | KB_X11},
270     {QKeySequence::MoveToNextLine,          1,          Qt::Key_Down,                           KB_All},
271     {QKeySequence::MoveToNextLine,          0,          Qt::META | Qt::Key_N,                   KB_Mac},
272     {QKeySequence::MoveToPreviousLine,      1,          Qt::Key_Up,                             KB_All},
273     {QKeySequence::MoveToPreviousLine,      0,          Qt::META | Qt::Key_P,                   KB_Mac},
274     {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_PageDown,            KB_Mac},
275     {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_Down,                KB_Mac},
276     {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_V,                   KB_Mac},
277     {QKeySequence::MoveToNextPage,          0,          Qt::ALT  | Qt::Key_PageDown,            KB_Mac },
278     {QKeySequence::MoveToNextPage,          1,          Qt::Key_PageDown,                       KB_All},
279     {QKeySequence::MoveToPreviousPage,      0,          Qt::META | Qt::Key_PageUp,              KB_Mac},
280     {QKeySequence::MoveToPreviousPage,      0,          Qt::META | Qt::Key_Up,                  KB_Mac},
281     {QKeySequence::MoveToPreviousPage,      0,          Qt::ALT  | Qt::Key_PageUp,              KB_Mac },
282     {QKeySequence::MoveToPreviousPage,      1,          Qt::Key_PageUp,                         KB_All},
283     {QKeySequence::MoveToStartOfLine,       0,          Qt::META | Qt::Key_Left,                KB_Mac},
284     {QKeySequence::MoveToStartOfLine,       0,          Qt::CTRL | Qt::Key_Left,                KB_Mac },
285     {QKeySequence::MoveToStartOfLine,       0,          Qt::Key_Home,                           KB_Win | KB_X11},
286     {QKeySequence::MoveToEndOfLine,         0,          Qt::META | Qt::Key_Right,               KB_Mac},
287     {QKeySequence::MoveToEndOfLine,         0,          Qt::CTRL | Qt::Key_Right,               KB_Mac },
288     {QKeySequence::MoveToEndOfLine,         0,          Qt::Key_End,                            KB_Win | KB_X11},
289     {QKeySequence::MoveToEndOfLine,         0,          Qt::CTRL + Qt::Key_E,                   KB_X11},
290     {QKeySequence::MoveToStartOfBlock,      0,          Qt::META | Qt::Key_A,                   KB_Mac},
291     {QKeySequence::MoveToStartOfBlock,      1,          Qt::ALT  | Qt::Key_Up,                  KB_Mac}, //mac only
292     {QKeySequence::MoveToEndOfBlock,        0,          Qt::META | Qt::Key_E,                   KB_Mac},
293     {QKeySequence::MoveToEndOfBlock,        1,          Qt::ALT  | Qt::Key_Down,                KB_Mac}, //mac only
294     {QKeySequence::MoveToStartOfDocument,   1,          Qt::CTRL | Qt::Key_Up,                  KB_Mac},
295     {QKeySequence::MoveToStartOfDocument,   0,          Qt::CTRL | Qt::Key_Home,                KB_Win | KB_X11},
296     {QKeySequence::MoveToStartOfDocument,   0,          Qt::Key_Home,                           KB_Mac},
297     {QKeySequence::MoveToEndOfDocument,     1,          Qt::CTRL | Qt::Key_Down,                KB_Mac},
298     {QKeySequence::MoveToEndOfDocument,     0,          Qt::CTRL | Qt::Key_End,                 KB_Win | KB_X11},
299     {QKeySequence::MoveToEndOfDocument,     0,          Qt::Key_End,                            KB_Mac},
300     {QKeySequence::SelectNextChar,          0,          Qt::SHIFT | Qt::Key_Right,              KB_All},
301     {QKeySequence::SelectPreviousChar,      0,          Qt::SHIFT | Qt::Key_Left,               KB_All},
302     {QKeySequence::SelectNextWord,          0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Right,   KB_Mac},
303     {QKeySequence::SelectNextWord,          0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Right,   KB_Win | KB_X11},
304     {QKeySequence::SelectPreviousWord,      0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Left,    KB_Mac},
305     {QKeySequence::SelectPreviousWord,      0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Left,    KB_Win | KB_X11},
306     {QKeySequence::SelectNextLine,          0,          Qt::SHIFT | Qt::Key_Down,               KB_All},
307     {QKeySequence::SelectPreviousLine,      0,          Qt::SHIFT | Qt::Key_Up,                 KB_All},
308     {QKeySequence::SelectNextPage,          0,          Qt::SHIFT | Qt::Key_PageDown,           KB_All},
309     {QKeySequence::SelectPreviousPage,      0,          Qt::SHIFT | Qt::Key_PageUp,             KB_All},
310     {QKeySequence::SelectStartOfLine,       0,          Qt::META | Qt::SHIFT | Qt::Key_Left,    KB_Mac},
311     {QKeySequence::SelectStartOfLine,       1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Left,    KB_Mac },
312     {QKeySequence::SelectStartOfLine,       0,          Qt::SHIFT | Qt::Key_Home,               KB_Win | KB_X11},
313     {QKeySequence::SelectEndOfLine,         0,          Qt::META | Qt::SHIFT | Qt::Key_Right,   KB_Mac},
314     {QKeySequence::SelectEndOfLine,         1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Right,   KB_Mac },
315     {QKeySequence::SelectEndOfLine,         0,          Qt::SHIFT | Qt::Key_End,                KB_Win | KB_X11},
316     {QKeySequence::SelectStartOfBlock,      1,          Qt::ALT  | Qt::SHIFT | Qt::Key_Up,      KB_Mac}, //mac only
317     {QKeySequence::SelectStartOfBlock,      0,          Qt::META | Qt::SHIFT | Qt::Key_A,       KB_Mac},
318     {QKeySequence::SelectEndOfBlock,        1,          Qt::ALT  | Qt::SHIFT | Qt::Key_Down,    KB_Mac}, //mac only
319     {QKeySequence::SelectEndOfBlock,        0,          Qt::META | Qt::SHIFT | Qt::Key_E,       KB_Mac},
320     {QKeySequence::SelectStartOfDocument,   1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Up,      KB_Mac},
321     {QKeySequence::SelectStartOfDocument,   0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Home,    KB_Win | KB_X11},
322     {QKeySequence::SelectStartOfDocument,   0,          Qt::SHIFT | Qt::Key_Home,               KB_Mac},
323     {QKeySequence::SelectEndOfDocument,     1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Down,    KB_Mac},
324     {QKeySequence::SelectEndOfDocument,     0,          Qt::CTRL | Qt::SHIFT | Qt::Key_End,     KB_Win | KB_X11},
325     {QKeySequence::SelectEndOfDocument,     0,          Qt::SHIFT | Qt::Key_End,                KB_Mac},
326     {QKeySequence::DeleteStartOfWord,       0,          Qt::ALT  | Qt::Key_Backspace,           KB_Mac},
327     {QKeySequence::DeleteStartOfWord,       0,          Qt::CTRL | Qt::Key_Backspace,           KB_X11 | KB_Win},
328     {QKeySequence::DeleteEndOfWord,         0,          Qt::ALT  | Qt::Key_Delete,              KB_Mac},
329     {QKeySequence::DeleteEndOfWord,         0,          Qt::CTRL | Qt::Key_Delete,              KB_X11 | KB_Win},
330     {QKeySequence::DeleteEndOfLine,         0,          Qt::CTRL | Qt::Key_K,                   KB_X11}, //emacs (line edit only)
331     {QKeySequence::InsertParagraphSeparator,0,          Qt::Key_Enter,                          KB_All},
332     {QKeySequence::InsertParagraphSeparator,0,          Qt::Key_Return,                         KB_All},
333     {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_Enter,               KB_Mac},
334     {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_Return,              KB_Mac},
335     {QKeySequence::InsertLineSeparator,     0,          Qt::SHIFT | Qt::Key_Enter,              KB_All},
336     {QKeySequence::InsertLineSeparator,     0,          Qt::SHIFT | Qt::Key_Return,             KB_All},
337     {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_O,                   KB_Mac},
338     {QKeySequence::SaveAs,                  0,          Qt::CTRL | Qt::SHIFT | Qt::Key_S,       KB_Gnome | KB_Mac},
339     {QKeySequence::Preferences,             0,          Qt::CTRL | Qt::Key_Comma,               KB_Mac},
340     {QKeySequence::Quit,                    0,          Qt::CTRL | Qt::Key_Q,                   KB_X11 | KB_Gnome | KB_KDE | KB_Mac},
341     {QKeySequence::FullScreen,              1,          Qt::META | Qt::CTRL | Qt::Key_F,        KB_Mac},
342     {QKeySequence::FullScreen,              0,          Qt::ALT  | Qt::Key_Enter,               KB_Win},
343     {QKeySequence::FullScreen,              0,          Qt::CTRL | Qt::SHIFT | Qt::Key_F,       KB_KDE},
344     {QKeySequence::FullScreen,              1,          Qt::CTRL | Qt::Key_F11,                 KB_Gnome},
345     {QKeySequence::FullScreen,              1,          Qt::Key_F11,                            KB_Win | KB_KDE},
346     {QKeySequence::Deselect,                0,          Qt::CTRL | Qt::SHIFT | Qt::Key_A,       KB_X11},
347     {QKeySequence::DeleteCompleteLine,      0,          Qt::CTRL | Qt::Key_U,                   KB_X11},
348     {QKeySequence::Backspace,               0,          Qt::META | Qt::Key_H,                   KB_Mac},
349     {QKeySequence::Cancel,                  0,          Qt::Key_Escape,                         KB_All},
350     {QKeySequence::Cancel,                  0,          Qt::CTRL | Qt::Key_Period,              KB_Mac}
351 };
352 
353 const uint QPlatformThemePrivate::numberOfKeyBindings = sizeof(QPlatformThemePrivate::keyBindings)/(sizeof(QKeyBinding));
354 #endif
355 
QPlatformThemePrivate()356 QPlatformThemePrivate::QPlatformThemePrivate()
357         : systemPalette(nullptr)
358 { }
359 
~QPlatformThemePrivate()360 QPlatformThemePrivate::~QPlatformThemePrivate()
361 {
362     delete systemPalette;
363 }
364 
365 Q_GUI_EXPORT QPalette qt_fusionPalette();
366 
initializeSystemPalette()367 void QPlatformThemePrivate::initializeSystemPalette()
368 {
369     Q_ASSERT(!systemPalette);
370     systemPalette = new QPalette(qt_fusionPalette());
371 }
372 
QPlatformTheme()373 QPlatformTheme::QPlatformTheme()
374     : d_ptr(new QPlatformThemePrivate)
375 {
376 
377 }
378 
QPlatformTheme(QPlatformThemePrivate * priv)379 QPlatformTheme::QPlatformTheme(QPlatformThemePrivate *priv)
380     : d_ptr(priv)
381 { }
382 
~QPlatformTheme()383 QPlatformTheme::~QPlatformTheme()
384 {
385 
386 }
387 
usePlatformNativeDialog(DialogType type) const388 bool QPlatformTheme::usePlatformNativeDialog(DialogType type) const
389 {
390     Q_UNUSED(type);
391     return false;
392 }
393 
createPlatformDialogHelper(DialogType type) const394 QPlatformDialogHelper *QPlatformTheme::createPlatformDialogHelper(DialogType type) const
395 {
396     Q_UNUSED(type);
397     return nullptr;
398 }
399 
palette(Palette type) const400 const QPalette *QPlatformTheme::palette(Palette type) const
401 {
402     Q_D(const QPlatformTheme);
403     if (type == QPlatformTheme::SystemPalette) {
404         if (!d->systemPalette)
405             const_cast<QPlatformTheme *>(this)->d_ptr->initializeSystemPalette();
406         return d->systemPalette;
407     }
408     return nullptr;
409 }
410 
font(Font type) const411 const QFont *QPlatformTheme::font(Font type) const
412 {
413     Q_UNUSED(type)
414     return nullptr;
415 }
416 
standardPixmap(StandardPixmap sp,const QSizeF & size) const417 QPixmap QPlatformTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
418 {
419     Q_UNUSED(sp);
420     Q_UNUSED(size);
421     // TODO Should return QCommonStyle pixmaps?
422     return QPixmap();
423 }
424 
425 /*!
426     \brief Return an icon for \a fileInfo, observing \a iconOptions.
427 
428     This function is queried by QFileIconProvider and similar classes to obtain
429     an icon for a file. If it does not return a non-null icon, fileIconPixmap()
430     is queried for a specific size.
431 
432     \since 5.8
433 */
434 
fileIcon(const QFileInfo & fileInfo,QPlatformTheme::IconOptions iconOptions) const435 QIcon QPlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const
436 {
437     Q_UNUSED(fileInfo);
438     Q_UNUSED(iconOptions);
439     // TODO Should return QCommonStyle pixmaps?
440     return QIcon();
441 }
442 
themeHint(ThemeHint hint) const443 QVariant QPlatformTheme::themeHint(ThemeHint hint) const
444 {
445     // For theme hints which mirror platform integration style hints, query
446     // the platform integration. The base QPlatformIntegration::styleHint()
447     // function will in turn query QPlatformTheme::defaultThemeHint() if there
448     // is no custom value.
449     switch (hint) {
450     case QPlatformTheme::CursorFlashTime:
451         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::CursorFlashTime);
452     case QPlatformTheme::KeyboardInputInterval:
453         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardInputInterval);
454     case QPlatformTheme::KeyboardAutoRepeatRate:
455         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardAutoRepeatRate);
456     case QPlatformTheme::MouseDoubleClickInterval:
457         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MouseDoubleClickInterval);
458     case QPlatformTheme::StartDragDistance:
459         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragDistance);
460     case QPlatformTheme::StartDragTime:
461         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragTime);
462     case QPlatformTheme::StartDragVelocity:
463         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragVelocity);
464     case QPlatformTheme::PasswordMaskDelay:
465         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskDelay);
466     case QPlatformTheme::PasswordMaskCharacter:
467         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskCharacter);
468     case QPlatformTheme::MousePressAndHoldInterval:
469         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MousePressAndHoldInterval);
470     case QPlatformTheme::ItemViewActivateItemOnSingleClick:
471         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ItemViewActivateItemOnSingleClick);
472     case QPlatformTheme::UiEffects:
473         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::UiEffects);
474     case QPlatformTheme::ShowShortcutsInContextMenus:
475         return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ShowShortcutsInContextMenus);
476     default:
477         return QPlatformTheme::defaultThemeHint(hint);
478     }
479 }
480 
defaultThemeHint(ThemeHint hint)481 QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
482 {
483     switch (hint) {
484     case QPlatformTheme::CursorFlashTime:
485         return QVariant(1000);
486     case QPlatformTheme::KeyboardInputInterval:
487         return QVariant(400);
488     case QPlatformTheme::KeyboardAutoRepeatRate:
489         return QVariant(30);
490     case QPlatformTheme::MouseDoubleClickInterval:
491         return QVariant(400);
492     case QPlatformTheme::StartDragDistance:
493         return QVariant(10);
494     case QPlatformTheme::StartDragTime:
495         return QVariant(500);
496     case QPlatformTheme::PasswordMaskDelay:
497         return QVariant(int(0));
498     case QPlatformTheme::PasswordMaskCharacter:
499         return QVariant(QChar(0x25CF));
500     case QPlatformTheme::StartDragVelocity:
501         return QVariant(int(0)); // no limit
502     case QPlatformTheme::UseFullScreenForPopupMenu:
503         return QVariant(false);
504     case QPlatformTheme::WindowAutoPlacement:
505         return QVariant(false);
506     case QPlatformTheme::DialogButtonBoxLayout:
507         return QVariant(int(0));
508     case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
509         return QVariant(false);
510     case QPlatformTheme::ItemViewActivateItemOnSingleClick:
511         return QVariant(false);
512     case QPlatformTheme::ToolButtonStyle:
513         return QVariant(int(Qt::ToolButtonIconOnly));
514     case QPlatformTheme::ToolBarIconSize:
515         return QVariant(int(0));
516     case QPlatformTheme::SystemIconThemeName:
517     case QPlatformTheme::SystemIconFallbackThemeName:
518         return QVariant(QString());
519     case QPlatformTheme::IconThemeSearchPaths:
520         return QVariant(QStringList());
521     case QPlatformTheme::IconFallbackSearchPaths:
522         return QVariant(QStringList());
523     case QPlatformTheme::StyleNames:
524         return QVariant(QStringList());
525     case QPlatformTheme::ShowShortcutsInContextMenus:
526         return QVariant(true);
527     case TextCursorWidth:
528         return QVariant(1);
529     case DropShadow:
530         return QVariant(false);
531     case MaximumScrollBarDragDistance:
532         return QVariant(-1);
533     case KeyboardScheme:
534         return QVariant(int(WindowsKeyboardScheme));
535     case UiEffects:
536         return QVariant(int(0));
537     case SpellCheckUnderlineStyle:
538         return QVariant(int(QTextCharFormat::WaveUnderline));
539     case TabFocusBehavior:
540         return QVariant(int(Qt::TabFocusAllControls));
541     case IconPixmapSizes:
542         return QVariant::fromValue(QList<int>());
543     case DialogSnapToDefaultButton:
544     case ContextMenuOnMouseRelease:
545         return QVariant(false);
546     case MousePressAndHoldInterval:
547         return QVariant(800);
548     case MouseDoubleClickDistance:
549         {
550             bool ok = false;
551             const int dist = qEnvironmentVariableIntValue("QT_DBL_CLICK_DIST", &ok);
552             return QVariant(ok ? dist : 5);
553         }
554     case WheelScrollLines:
555         return QVariant(3);
556     case TouchDoubleTapDistance:
557         {
558             bool ok = false;
559             int dist = qEnvironmentVariableIntValue("QT_DBL_TAP_DIST", &ok);
560             if (!ok)
561                 dist = defaultThemeHint(MouseDoubleClickDistance).toInt(&ok) * 2;
562             return QVariant(ok ? dist : 10);
563         }
564     case MouseQuickSelectionThreshold:
565         return QVariant(10);
566     }
567     return QVariant();
568 }
569 
createPlatformMenuItem() const570 QPlatformMenuItem *QPlatformTheme::createPlatformMenuItem() const
571 {
572     return nullptr;
573 }
574 
createPlatformMenu() const575 QPlatformMenu *QPlatformTheme::createPlatformMenu() const
576 {
577     return nullptr;
578 }
579 
createPlatformMenuBar() const580 QPlatformMenuBar *QPlatformTheme::createPlatformMenuBar() const
581 {
582     return nullptr;
583 }
584 
585 #ifndef QT_NO_SYSTEMTRAYICON
586 /*!
587    Factory function for QSystemTrayIcon. This function will return 0 if the platform
588    integration does not support creating any system tray icon.
589 */
createPlatformSystemTrayIcon() const590 QPlatformSystemTrayIcon *QPlatformTheme::createPlatformSystemTrayIcon() const
591 {
592     return nullptr;
593 }
594 #endif
595 
596 /*!
597    Factory function for the QIconEngine used by QIcon::fromTheme(). By default this
598    function returns a QIconLoaderEngine, but subclasses can reimplement it to
599    provide their own.
600 
601    It is especially useful to benefit from some platform specific facilities or
602    optimizations like an inter-process cache in systems mostly built with Qt.
603 
604    \since 5.1
605 */
createIconEngine(const QString & iconName) const606 QIconEngine *QPlatformTheme::createIconEngine(const QString &iconName) const
607 {
608     return new QIconLoaderEngine(iconName);
609 }
610 
611 #if defined(Q_OS_MACX)
maybeSwapShortcut(int shortcut)612 static inline int maybeSwapShortcut(int shortcut)
613 {
614     if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
615         uint oldshortcut = shortcut;
616         shortcut &= ~(Qt::CTRL | Qt::META);
617         if (oldshortcut & Qt::CTRL)
618             shortcut |= Qt::META;
619         if (oldshortcut & Qt::META)
620             shortcut |= Qt::CTRL;
621     }
622     return shortcut;
623 }
624 #endif
625 
626 #ifndef QT_NO_SHORTCUT
627 // mixed-mode predicate: all of these overloads are actually needed (but not all for every compiler)
628 struct ByStandardKey {
629     typedef bool result_type;
630 
operator ()ByStandardKey631     bool operator()(QKeySequence::StandardKey lhs, QKeySequence::StandardKey rhs) const
632     { return lhs < rhs; }
633 
operator ()ByStandardKey634     bool operator()(const QKeyBinding& lhs, const QKeyBinding& rhs) const
635     { return operator()(lhs.standardKey, rhs.standardKey); }
636 
operator ()ByStandardKey637     bool operator()(QKeySequence::StandardKey lhs, const QKeyBinding& rhs) const
638     { return operator()(lhs, rhs.standardKey); }
639 
operator ()ByStandardKey640     bool operator()(const QKeyBinding& lhs, QKeySequence::StandardKey rhs) const
641     { return operator()(lhs.standardKey, rhs); }
642 };
643 
644 /*!
645    Returns the key sequence that should be used for a standard action.
646 
647   \since 5.2
648  */
keyBindings(QKeySequence::StandardKey key) const649 QList<QKeySequence> QPlatformTheme::keyBindings(QKeySequence::StandardKey key) const
650 {
651     const uint platform = QPlatformThemePrivate::currentKeyPlatforms();
652     QList <QKeySequence> list;
653 
654     std::pair<const QKeyBinding *, const QKeyBinding *> range =
655         std::equal_range(QPlatformThemePrivate::keyBindings,
656                          QPlatformThemePrivate::keyBindings + QPlatformThemePrivate::numberOfKeyBindings,
657                          key, ByStandardKey());
658 
659     for (const QKeyBinding *it = range.first; it < range.second; ++it) {
660         if (!(it->platform & platform))
661             continue;
662 
663         uint shortcut =
664 #if defined(Q_OS_MACX)
665             maybeSwapShortcut(it->shortcut);
666 #else
667             it->shortcut;
668 #endif
669         if (it->priority > 0)
670             list.prepend(QKeySequence(shortcut));
671         else
672             list.append(QKeySequence(shortcut));
673     }
674 
675     return list;
676 }
677 #endif
678 
679 /*!
680    Returns the text of a standard \a button.
681 
682   \since 5.3
683   \sa QPlatformDialogHelper::StandardButton
684  */
685 
standardButtonText(int button) const686 QString QPlatformTheme::standardButtonText(int button) const
687 {
688     return QPlatformTheme::defaultStandardButtonText(button);
689 }
690 
691 /*!
692    Returns the mnemonic that should be used for a standard \a button.
693 
694   \since 5.9
695   \sa QPlatformDialogHelper::StandardButton
696  */
697 
standardButtonShortcut(int button) const698 QKeySequence QPlatformTheme::standardButtonShortcut(int button) const
699 {
700     Q_UNUSED(button)
701     return QKeySequence();
702 }
703 
defaultStandardButtonText(int button)704 QString QPlatformTheme::defaultStandardButtonText(int button)
705 {
706     switch (button) {
707     case QPlatformDialogHelper::Ok:
708         return QCoreApplication::translate("QPlatformTheme", "OK");
709     case QPlatformDialogHelper::Save:
710         return QCoreApplication::translate("QPlatformTheme", "Save");
711     case QPlatformDialogHelper::SaveAll:
712         return QCoreApplication::translate("QPlatformTheme", "Save All");
713     case QPlatformDialogHelper::Open:
714         return QCoreApplication::translate("QPlatformTheme", "Open");
715     case QPlatformDialogHelper::Yes:
716         return QCoreApplication::translate("QPlatformTheme", "&Yes");
717     case QPlatformDialogHelper::YesToAll:
718         return QCoreApplication::translate("QPlatformTheme", "Yes to &All");
719     case QPlatformDialogHelper::No:
720         return QCoreApplication::translate("QPlatformTheme", "&No");
721     case QPlatformDialogHelper::NoToAll:
722         return QCoreApplication::translate("QPlatformTheme", "N&o to All");
723     case QPlatformDialogHelper::Abort:
724         return QCoreApplication::translate("QPlatformTheme", "Abort");
725     case QPlatformDialogHelper::Retry:
726         return QCoreApplication::translate("QPlatformTheme", "Retry");
727     case QPlatformDialogHelper::Ignore:
728         return QCoreApplication::translate("QPlatformTheme", "Ignore");
729     case QPlatformDialogHelper::Close:
730         return QCoreApplication::translate("QPlatformTheme", "Close");
731     case QPlatformDialogHelper::Cancel:
732         return QCoreApplication::translate("QPlatformTheme", "Cancel");
733     case QPlatformDialogHelper::Discard:
734         return QCoreApplication::translate("QPlatformTheme", "Discard");
735     case QPlatformDialogHelper::Help:
736         return QCoreApplication::translate("QPlatformTheme", "Help");
737     case QPlatformDialogHelper::Apply:
738         return QCoreApplication::translate("QPlatformTheme", "Apply");
739     case QPlatformDialogHelper::Reset:
740         return QCoreApplication::translate("QPlatformTheme", "Reset");
741     case QPlatformDialogHelper::RestoreDefaults:
742         return QCoreApplication::translate("QPlatformTheme", "Restore Defaults");
743     default:
744         break;
745     }
746     return QString();
747 }
748 
removeMnemonics(const QString & original)749 QString QPlatformTheme::removeMnemonics(const QString &original)
750 {
751     QString returnText(original.size(), 0);
752     int finalDest = 0;
753     int currPos = 0;
754     int l = original.length();
755     while (l) {
756         if (original.at(currPos) == QLatin1Char('&')) {
757             ++currPos;
758             --l;
759             if (l == 0)
760                 break;
761         } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 &&
762                    original.at(currPos + 1) == QLatin1Char('&') &&
763                    original.at(currPos + 2) != QLatin1Char('&') &&
764                    original.at(currPos + 3) == QLatin1Char(')')) {
765             /* remove mnemonics its format is "\s*(&X)" */
766             int n = 0;
767             while (finalDest > n && returnText.at(finalDest - n - 1).isSpace())
768                 ++n;
769             finalDest -= n;
770             currPos += 4;
771             l -= 4;
772             continue;
773         }
774         returnText[finalDest] = original.at(currPos);
775         ++currPos;
776         ++finalDest;
777         --l;
778     }
779     returnText.truncate(finalDest);
780     return returnText;
781 }
782 
currentKeyPlatforms()783 unsigned QPlatformThemePrivate::currentKeyPlatforms()
784 {
785     const uint keyboardScheme = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::KeyboardScheme).toInt();
786     unsigned result = 1u << keyboardScheme;
787 #ifndef QT_NO_SHORTCUT
788     if (keyboardScheme == QPlatformTheme::KdeKeyboardScheme
789         || keyboardScheme == QPlatformTheme::GnomeKeyboardScheme
790         || keyboardScheme == QPlatformTheme::CdeKeyboardScheme)
791         result |= KB_X11;
792 #endif
793     return result;
794 }
795 
796 QT_END_NAMESPACE
797