1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qstylehints.h>
5#include "qstylehints_p.h"
6#include <qpa/qplatformintegration.h>
7#include <qpa/qplatformtheme.h>
8#include <private/qguiapplication_p.h>
9#include <qdebug.h>
10
11QT_BEGIN_NAMESPACE
12
13static inline QVariant hint(QPlatformIntegration::StyleHint h)
14{
15 return QGuiApplicationPrivate::platformIntegration()->styleHint(hint: h);
16}
17
18static inline QVariant themeableHint(QPlatformTheme::ThemeHint th,
19 QPlatformIntegration::StyleHint ih)
20{
21 if (!QCoreApplication::instance()) {
22 qWarning(msg: "Must construct a QGuiApplication before accessing a platform theme hint.");
23 return QVariant();
24 }
25 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
26 const QVariant themeHint = theme->themeHint(hint: th);
27 if (themeHint.isValid())
28 return themeHint;
29 }
30 return QGuiApplicationPrivate::platformIntegration()->styleHint(hint: ih);
31}
32
33static inline QVariant themeableHint(QPlatformTheme::ThemeHint th)
34{
35 if (!QCoreApplication::instance()) {
36 qWarning(msg: "Must construct a QGuiApplication before accessing a platform theme hint.");
37 return QVariant();
38 }
39 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
40 const QVariant themeHint = theme->themeHint(hint: th);
41 if (themeHint.isValid())
42 return themeHint;
43 }
44 return QPlatformTheme::defaultThemeHint(hint: th);
45}
46
47/*!
48 \class QStyleHints
49 \since 5.0
50 \brief The QStyleHints class contains platform specific hints and settings.
51 \inmodule QtGui
52
53 An object of this class, obtained from QGuiApplication, provides access to certain global
54 user interface parameters of the current platform.
55
56 Access to most settings is read only. The platform itself usually provides the user with
57 ways to tune these parameters. Authors of custom user interface components should read
58 relevant settings to allow the components to exhibit the same behavior and feel as other
59 components.
60
61 \sa QGuiApplication::styleHints()
62 */
63QStyleHints::QStyleHints()
64 : QObject(*new QStyleHintsPrivate(), nullptr)
65{
66}
67
68/*!
69 Sets the \a mouseDoubleClickInterval.
70 \internal
71 \sa mouseDoubleClickInterval()
72 \since 5.3
73*/
74void QStyleHints::setMouseDoubleClickInterval(int mouseDoubleClickInterval)
75{
76 Q_D(QStyleHints);
77 if (d->m_mouseDoubleClickInterval == mouseDoubleClickInterval)
78 return;
79 d->m_mouseDoubleClickInterval = mouseDoubleClickInterval;
80 emit mouseDoubleClickIntervalChanged(mouseDoubleClickInterval);
81}
82
83/*!
84 \property QStyleHints::mouseDoubleClickInterval
85 \brief the time limit in milliseconds that distinguishes a double click
86 from two consecutive mouse clicks.
87*/
88int QStyleHints::mouseDoubleClickInterval() const
89{
90 Q_D(const QStyleHints);
91 return d->m_mouseDoubleClickInterval >= 0 ?
92 d->m_mouseDoubleClickInterval :
93 themeableHint(th: QPlatformTheme::MouseDoubleClickInterval, ih: QPlatformIntegration::MouseDoubleClickInterval).toInt();
94}
95
96/*!
97 \property QStyleHints::mouseDoubleClickDistance
98 \brief the maximum distance, in pixels, that the mouse can be moved between
99 two consecutive mouse clicks and still have it detected as a double-click
100 \since 5.14
101*/
102int QStyleHints::mouseDoubleClickDistance() const
103{
104 Q_D(const QStyleHints);
105 return d->m_mouseDoubleClickDistance >= 0 ?
106 d->m_mouseDoubleClickDistance :
107 themeableHint(th: QPlatformTheme::MouseDoubleClickDistance, ih: QPlatformIntegration::MouseDoubleClickDistance).toInt();
108}
109
110/*!
111 \property QStyleHints::touchDoubleTapDistance
112 \brief the maximum distance, in pixels, that a finger can be moved between
113 two consecutive taps and still have it detected as a double-tap
114 \since 5.14
115*/
116int QStyleHints::touchDoubleTapDistance() const
117{
118 Q_D(const QStyleHints);
119 return d->m_touchDoubleTapDistance >= 0 ?
120 d->m_touchDoubleTapDistance :
121 themeableHint(th: QPlatformTheme::TouchDoubleTapDistance).toInt();
122}
123
124/*!
125 \property QStyleHints::colorScheme
126 \brief the color scheme of the platform theme.
127 \sa Qt::ColorScheme
128 \since 6.5
129*/
130Qt::ColorScheme QStyleHints::colorScheme() const
131{
132 Q_D(const QStyleHints);
133 return d->colorScheme();
134}
135
136/*!
137 Sets the \a mousePressAndHoldInterval.
138 \internal
139 \sa mousePressAndHoldInterval()
140 \since 5.7
141*/
142void QStyleHints::setMousePressAndHoldInterval(int mousePressAndHoldInterval)
143{
144 Q_D(QStyleHints);
145 if (d->m_mousePressAndHoldInterval == mousePressAndHoldInterval)
146 return;
147 d->m_mousePressAndHoldInterval = mousePressAndHoldInterval;
148 emit mousePressAndHoldIntervalChanged(mousePressAndHoldInterval);
149}
150
151/*!
152 \property QStyleHints::mousePressAndHoldInterval
153 \brief the time limit in milliseconds that activates
154 a press and hold.
155
156 \since 5.3
157*/
158int QStyleHints::mousePressAndHoldInterval() const
159{
160 Q_D(const QStyleHints);
161 return d->m_mousePressAndHoldInterval >= 0 ?
162 d->m_mousePressAndHoldInterval :
163 themeableHint(th: QPlatformTheme::MousePressAndHoldInterval, ih: QPlatformIntegration::MousePressAndHoldInterval).toInt();
164}
165
166/*!
167 Sets the \a startDragDistance.
168 \internal
169 \sa startDragDistance()
170 \since 5.3
171*/
172void QStyleHints::setStartDragDistance(int startDragDistance)
173{
174 Q_D(QStyleHints);
175 if (d->m_startDragDistance == startDragDistance)
176 return;
177 d->m_startDragDistance = startDragDistance;
178 emit startDragDistanceChanged(startDragDistance);
179}
180
181/*!
182 \property QStyleHints::startDragDistance
183 \brief the distance, in pixels, that the mouse must be moved with a button
184 held down before a drag and drop operation will begin.
185
186 If you support drag and drop in your application, and want to start a drag
187 and drop operation after the user has moved the cursor a certain distance
188 with a button held down, you should use this property's value as the
189 minimum distance required.
190
191 For example, if the mouse position of the click is stored in \c startPos
192 and the current position (e.g. in the mouse move event) is \c currentPos,
193 you can find out if a drag should be started with code like this:
194
195 \snippet code/src_gui_kernel_qapplication.cpp 6
196
197 \sa startDragTime, QPoint::manhattanLength(), {Drag and Drop}
198*/
199int QStyleHints::startDragDistance() const
200{
201 Q_D(const QStyleHints);
202 return d->m_startDragDistance >= 0 ?
203 d->m_startDragDistance :
204 themeableHint(th: QPlatformTheme::StartDragDistance, ih: QPlatformIntegration::StartDragDistance).toInt();
205}
206
207/*!
208 Sets the \a startDragDragTime.
209 \internal
210 \sa startDragTime()
211 \since 5.3
212*/
213void QStyleHints::setStartDragTime(int startDragTime)
214{
215 Q_D(QStyleHints);
216 if (d->m_startDragTime == startDragTime)
217 return;
218 d->m_startDragTime = startDragTime;
219 emit startDragTimeChanged(startDragTime);
220}
221
222/*!
223 \property QStyleHints::startDragTime
224 \brief the time, in milliseconds, that a mouse button must be held down
225 before a drag and drop operation will begin.
226
227 If you support drag and drop in your application, and want to start a drag
228 and drop operation after the user has held down a mouse button for a
229 certain amount of time, you should use this property's value as the delay.
230
231 \sa startDragDistance, {Drag and Drop}
232*/
233int QStyleHints::startDragTime() const
234{
235 Q_D(const QStyleHints);
236 return d->m_startDragTime >= 0 ?
237 d->m_startDragTime :
238 themeableHint(th: QPlatformTheme::StartDragTime, ih: QPlatformIntegration::StartDragTime).toInt();
239}
240
241/*!
242 \property QStyleHints::startDragVelocity
243 \brief the limit for the velocity, in pixels per second, that the mouse may
244 be moved, with a button held down, for a drag and drop operation to begin.
245 A value of 0 means there is no such limit.
246
247 \sa startDragDistance, {Drag and Drop}
248*/
249int QStyleHints::startDragVelocity() const
250{
251 return themeableHint(th: QPlatformTheme::StartDragVelocity, ih: QPlatformIntegration::StartDragVelocity).toInt();
252}
253
254/*!
255 Sets the \a keyboardInputInterval.
256 \internal
257 \sa keyboardInputInterval()
258 \since 5.3
259*/
260void QStyleHints::setKeyboardInputInterval(int keyboardInputInterval)
261{
262 Q_D(QStyleHints);
263 if (d->m_keyboardInputInterval == keyboardInputInterval)
264 return;
265 d->m_keyboardInputInterval = keyboardInputInterval;
266 emit keyboardInputIntervalChanged(keyboardInputInterval);
267}
268
269/*!
270 \property QStyleHints::keyboardInputInterval
271 \brief the time limit, in milliseconds, that distinguishes a key press
272 from two consecutive key presses.
273*/
274int QStyleHints::keyboardInputInterval() const
275{
276 Q_D(const QStyleHints);
277 return d->m_keyboardInputInterval >= 0 ?
278 d->m_keyboardInputInterval :
279 themeableHint(th: QPlatformTheme::KeyboardInputInterval, ih: QPlatformIntegration::KeyboardInputInterval).toInt();
280}
281
282#if QT_DEPRECATED_SINCE(6, 5)
283/*!
284 \property QStyleHints::keyboardAutoRepeatRate
285 \brief the rate, in events per second, in which additional repeated key
286 presses will automatically be generated if a key is being held down.
287 \deprecated [6.5] Use keyboardAutoRepeatRateF() instead
288*/
289int QStyleHints::keyboardAutoRepeatRate() const
290{
291 return themeableHint(th: QPlatformTheme::KeyboardAutoRepeatRate, ih: QPlatformIntegration::KeyboardAutoRepeatRate).toInt();
292}
293#endif
294
295/*!
296 \property QStyleHints::keyboardAutoRepeatRateF
297 \since 6.5
298 \brief the rate, in events per second, in which additional repeated key
299 presses will automatically be generated if a key is being held down.
300*/
301qreal QStyleHints::keyboardAutoRepeatRateF() const
302{
303 return themeableHint(th: QPlatformTheme::KeyboardAutoRepeatRate, ih: QPlatformIntegration::KeyboardAutoRepeatRate).toReal();
304}
305
306/*!
307 Sets the \a cursorFlashTime.
308 \internal
309 \sa cursorFlashTime()
310 \since 5.3
311*/
312void QStyleHints::setCursorFlashTime(int cursorFlashTime)
313{
314 Q_D(QStyleHints);
315 if (d->m_cursorFlashTime == cursorFlashTime)
316 return;
317 d->m_cursorFlashTime = cursorFlashTime;
318 emit cursorFlashTimeChanged(cursorFlashTime);
319}
320
321/*!
322 \property QStyleHints::cursorFlashTime
323 \brief the text cursor's flash (blink) time in milliseconds.
324
325 The flash time is the time used to display, invert and restore the
326 caret display. Usually the text cursor is displayed for half the cursor
327 flash time, then hidden for the same amount of time.
328*/
329int QStyleHints::cursorFlashTime() const
330{
331 Q_D(const QStyleHints);
332 return d->m_cursorFlashTime >= 0 ?
333 d->m_cursorFlashTime :
334 themeableHint(th: QPlatformTheme::CursorFlashTime, ih: QPlatformIntegration::CursorFlashTime).toInt();
335}
336
337/*!
338 \property QStyleHints::showIsFullScreen
339 \brief whether the platform defaults to fullscreen windows.
340
341 This property is \c true if the platform defaults to windows being fullscreen,
342 otherwise \c false.
343
344 \note The platform may still choose to show certain windows non-fullscreen,
345 such as popups or dialogs. This property only reports the default behavior.
346
347 \sa QWindow::show(), showIsMaximized()
348*/
349bool QStyleHints::showIsFullScreen() const
350{
351 return hint(h: QPlatformIntegration::ShowIsFullScreen).toBool();
352}
353
354/*!
355 \property QStyleHints::showIsMaximized
356 \brief whether the platform defaults to maximized windows.
357
358 This property is \c true if the platform defaults to windows being maximized,
359 otherwise \c false.
360
361 \note The platform may still choose to show certain windows non-maximized,
362 such as popups or dialogs. This property only reports the default behavior.
363
364 \sa QWindow::show(), showIsFullScreen()
365 \since 5.6
366*/
367bool QStyleHints::showIsMaximized() const
368{
369 return hint(h: QPlatformIntegration::ShowIsMaximized).toBool();
370}
371
372/*!
373 \property QStyleHints::showShortcutsInContextMenus
374 \since 5.10
375 \brief \c true if the platform normally shows shortcut key sequences in
376 context menus, otherwise \c false.
377
378 Since Qt 5.13, the setShowShortcutsInContextMenus() function can be used to
379 override the platform default.
380
381 \sa Qt::AA_DontShowShortcutsInContextMenus
382*/
383bool QStyleHints::showShortcutsInContextMenus() const
384{
385 Q_D(const QStyleHints);
386 return d->m_showShortcutsInContextMenus >= 0
387 ? d->m_showShortcutsInContextMenus != 0
388 : themeableHint(th: QPlatformTheme::ShowShortcutsInContextMenus, ih: QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
389}
390
391void QStyleHints::setShowShortcutsInContextMenus(bool s)
392{
393 Q_D(QStyleHints);
394 if (s != showShortcutsInContextMenus()) {
395 d->m_showShortcutsInContextMenus = s ? 1 : 0;
396 emit showShortcutsInContextMenusChanged(s);
397 }
398}
399
400/*!
401 \property QStyleHints::passwordMaskDelay
402 \brief the time, in milliseconds, a typed letter is displayed unshrouded
403 in a text input field in password mode.
404*/
405int QStyleHints::passwordMaskDelay() const
406{
407 return themeableHint(th: QPlatformTheme::PasswordMaskDelay, ih: QPlatformIntegration::PasswordMaskDelay).toInt();
408}
409
410/*!
411 \property QStyleHints::passwordMaskCharacter
412 \brief the character used to mask the characters typed into text input
413 fields in password mode.
414*/
415QChar QStyleHints::passwordMaskCharacter() const
416{
417 return themeableHint(th: QPlatformTheme::PasswordMaskCharacter, ih: QPlatformIntegration::PasswordMaskCharacter).toChar();
418}
419
420/*!
421 \property QStyleHints::fontSmoothingGamma
422 \brief the gamma value used in font smoothing.
423*/
424qreal QStyleHints::fontSmoothingGamma() const
425{
426 return hint(h: QPlatformIntegration::FontSmoothingGamma).toReal();
427}
428
429/*!
430 \property QStyleHints::useRtlExtensions
431 \brief the writing direction.
432
433 This property is \c true if right-to-left writing direction is enabled,
434 otherwise \c false.
435*/
436bool QStyleHints::useRtlExtensions() const
437{
438 return hint(h: QPlatformIntegration::UseRtlExtensions).toBool();
439}
440
441/*!
442 \property QStyleHints::setFocusOnTouchRelease
443 \brief the event that should set input focus on focus objects.
444
445 This property is \c true if focus objects (line edits etc) should receive
446 input focus after a touch/mouse release. This is normal behavior on
447 touch platforms. On desktop platforms, the standard is to set
448 focus already on touch/mouse press.
449*/
450bool QStyleHints::setFocusOnTouchRelease() const
451{
452 return themeableHint(th: QPlatformTheme::SetFocusOnTouchRelease, ih: QPlatformIntegration::SetFocusOnTouchRelease).toBool();
453}
454
455/*!
456 \property QStyleHints::tabFocusBehavior
457 \since 5.5
458 \brief The focus behavior on press of the tab key.
459
460 \note Do not bind this value in QML because the change notifier
461 signal is not implemented yet.
462*/
463
464Qt::TabFocusBehavior QStyleHints::tabFocusBehavior() const
465{
466 Q_D(const QStyleHints);
467 return Qt::TabFocusBehavior(d->m_tabFocusBehavior >= 0 ?
468 d->m_tabFocusBehavior :
469 themeableHint(th: QPlatformTheme::TabFocusBehavior, ih: QPlatformIntegration::TabFocusBehavior).toInt());
470}
471
472/*!
473 Sets the \a tabFocusBehavior.
474 \internal
475 \sa tabFocusBehavior()
476 \since 5.7
477*/
478void QStyleHints::setTabFocusBehavior(Qt::TabFocusBehavior tabFocusBehavior)
479{
480 Q_D(QStyleHints);
481 if (d->m_tabFocusBehavior == tabFocusBehavior)
482 return;
483 d->m_tabFocusBehavior = tabFocusBehavior;
484 emit tabFocusBehaviorChanged(tabFocusBehavior);
485}
486
487/*!
488 \property QStyleHints::singleClickActivation
489 \brief whether items are activated by single or double click.
490
491 This property is \c true if items should be activated by single click, \c false
492 if they should be activated by double click instead.
493
494 \since 5.5
495*/
496bool QStyleHints::singleClickActivation() const
497{
498 return themeableHint(th: QPlatformTheme::ItemViewActivateItemOnSingleClick, ih: QPlatformIntegration::ItemViewActivateItemOnSingleClick).toBool();
499}
500
501/*!
502 \property QStyleHints::useHoverEffects
503 \brief whether UI elements use hover effects.
504
505 This property is \c true if UI elements should use hover effects. This is the
506 standard behavior on desktop platforms with a mouse pointer, whereas
507 on touch platforms the overhead of hover event delivery can be avoided.
508
509 \since 5.8
510*/
511bool QStyleHints::useHoverEffects() const
512{
513 Q_D(const QStyleHints);
514 return (d->m_uiEffects >= 0 ?
515 d->m_uiEffects :
516 themeableHint(th: QPlatformTheme::UiEffects, ih: QPlatformIntegration::UiEffects).toInt()) & QPlatformTheme::HoverEffect;
517}
518
519void QStyleHints::setUseHoverEffects(bool useHoverEffects)
520{
521 Q_D(QStyleHints);
522 if (d->m_uiEffects >= 0 && useHoverEffects == bool(d->m_uiEffects & QPlatformTheme::HoverEffect))
523 return;
524 if (d->m_uiEffects == -1)
525 d->m_uiEffects = 0;
526 if (useHoverEffects)
527 d->m_uiEffects |= QPlatformTheme::HoverEffect;
528 else
529 d->m_uiEffects &= ~QPlatformTheme::HoverEffect;
530 emit useHoverEffectsChanged(useHoverEffects);
531}
532
533/*!
534 \property QStyleHints::wheelScrollLines
535 \brief Number of lines to scroll by default for each wheel click.
536
537 \since 5.9
538*/
539int QStyleHints::wheelScrollLines() const
540{
541 Q_D(const QStyleHints);
542 if (d->m_wheelScrollLines > 0)
543 return d->m_wheelScrollLines;
544 return themeableHint(th: QPlatformTheme::WheelScrollLines, ih: QPlatformIntegration::WheelScrollLines).toInt();
545}
546
547/*!
548 Sets the \a wheelScrollLines.
549 \internal
550 \sa wheelScrollLines()
551 \since 5.9
552*/
553void QStyleHints::setWheelScrollLines(int scrollLines)
554{
555 Q_D(QStyleHints);
556 if (d->m_wheelScrollLines == scrollLines)
557 return;
558 d->m_wheelScrollLines = scrollLines;
559 emit wheelScrollLinesChanged(scrollLines);
560}
561
562/*!
563 Sets the mouse quick selection threshold.
564 \internal
565 \sa mouseQuickSelectionThreshold()
566 \since 5.11
567*/
568void QStyleHints::setMouseQuickSelectionThreshold(int threshold)
569{
570 Q_D(QStyleHints);
571 if (d->m_mouseQuickSelectionThreshold == threshold)
572 return;
573 d->m_mouseQuickSelectionThreshold = threshold;
574 emit mouseQuickSelectionThresholdChanged(threshold);
575}
576
577/*!
578 \property QStyleHints::mouseQuickSelectionThreshold
579 \brief Quick selection mouse threshold in QLineEdit.
580
581 This property defines how much the mouse cursor should be moved along the y axis
582 to trigger a quick selection during a normal QLineEdit text selection.
583
584 If the property value is less than or equal to 0, the quick selection feature is disabled.
585
586 \since 5.11
587*/
588int QStyleHints::mouseQuickSelectionThreshold() const
589{
590 Q_D(const QStyleHints);
591 if (d->m_mouseQuickSelectionThreshold >= 0)
592 return d->m_mouseQuickSelectionThreshold;
593 return themeableHint(th: QPlatformTheme::MouseQuickSelectionThreshold, ih: QPlatformIntegration::MouseQuickSelectionThreshold).toInt();
594}
595
596/*!
597 \internal
598 QStyleHintsPrivate::setColorScheme - set a new color scheme.
599 Set \a colorScheme as the new color scheme of the QStyleHints.
600 The colorSchemeChanged signal will be emitted if present and new color scheme differ.
601 */
602void QStyleHintsPrivate::setColorScheme(Qt::ColorScheme colorScheme)
603{
604 if (m_colorScheme == colorScheme)
605 return;
606 m_colorScheme = colorScheme;
607 Q_Q(QStyleHints);
608 emit q->colorSchemeChanged(colorScheme);
609}
610
611QStyleHintsPrivate *QStyleHintsPrivate::get(QStyleHints *q)
612{
613 Q_ASSERT(q);
614 return q->d_func();
615}
616
617QT_END_NAMESPACE
618
619#include "moc_qstylehints.cpp"
620

source code of qtbase/src/gui/kernel/qstylehints.cpp