diff options
author | Jake Petroules <jake.petroules@qt.io> | 2017-03-10 16:55:04 -0800 |
---|---|---|
committer | Jake Petroules <jake.petroules@qt.io> | 2017-03-14 05:29:22 +0000 |
commit | c2c3452ba5b4c32d0c2d5df9193bf89986623ab5 (patch) | |
tree | 66b567681989e166bc429f477ae7f13f9c844f75 | |
parent | b6e3fd8ced2ae3629b73b78bf436d1a3ac4bccda (diff) | |
download | qtbase-c2c3452ba5b4c32d0c2d5df9193bf89986623ab5.tar.gz |
Add new API to control whether shortcuts are shown in context menus
Shortcuts are universally not shown on macOS or mobile platforms, making
applications look very obviously out of place.
Windows and GNOME desktop environments almost never use them.
Only KDE appears to do so commonly; default accordingly.
Task-number: QTBUG-49435
Change-Id: Ieac4cee57b15a02be5258f3d07749af6316af62b
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
-rw-r--r-- | src/corelib/global/qnamespace.h | 1 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 5 | ||||
-rw-r--r-- | src/gui/kernel/qplatformintegration.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qplatformintegration.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qplatformtheme.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qplatformtheme.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qstylehints.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qstylehints.h | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qaction.cpp | 42 | ||||
-rw-r--r-- | src/widgets/kernel/qaction.h | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qaction_p.h | 1 | ||||
-rw-r--r-- | src/widgets/widgets/qlineedit.cpp | 5 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 5 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgettextcontrol.cpp | 5 |
14 files changed, 84 insertions, 5 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index da44c01594..dbc8b368b3 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -508,6 +508,7 @@ public: AA_CompressHighFrequencyEvents = 25, AA_DontCheckOpenGLContextThreadAffinity = 26, AA_DisableShaderDiskCache = 27, + AA_DontShowShortcutsInContextMenus = 28, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index b8588b3f98..c44e95a84b 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -114,6 +114,11 @@ \macos menubar \e{may not} pick up a change in this attribute. Changes in the QAction::iconVisibleInMenu property will always be picked up. + \value AA_DontShowShortcutsInContextMenus Actions with the Shortcut property + won't be shown in any shortcut menus unless specifically set by the + QAction::shortcutVisibleInContextMenu property. This value has + been added in Qt 5.10. + \value AA_NativeWindows Ensures that widgets have native windows. \value AA_DontCreateNativeWidgetSiblings Ensures that siblings of native diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index 0af3295430..9673ad673a 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -392,6 +392,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return false; case ShowIsMaximized: return false; + case ShowShortcutsInContextMenus: + return QPlatformTheme::defaultThemeHint(QPlatformTheme::ShowShortcutsInContextMenus); case PasswordMaskDelay: return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskDelay); case PasswordMaskCharacter: diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 54904ef60d..49d41dd576 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -161,6 +161,7 @@ public: ItemViewActivateItemOnSingleClick, UiEffects, WheelScrollLines, + ShowShortcutsInContextMenus, }; virtual QVariant styleHint(StyleHint hint) const; diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index 878f656f2e..ebf65eda12 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -161,6 +161,8 @@ QT_BEGIN_NAMESPACE The default value is double the MouseDoubleClickDistance, or 10 logical pixels if that is not specified. + \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus. + \sa themeHint(), QStyle::pixelMetric() */ @@ -516,6 +518,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint) return QVariant(QStringList()); case QPlatformTheme::StyleNames: return QVariant(QStringList()); + case QPlatformTheme::ShowShortcutsInContextMenus: + return QVariant(false); case TextCursorWidth: return QVariant(1); case DropShadow: diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 2ba2f8669f..f4ff418db6 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -115,7 +115,8 @@ public: MousePressAndHoldInterval, MouseDoubleClickDistance, WheelScrollLines, - TouchDoubleTapDistance + TouchDoubleTapDistance, + ShowShortcutsInContextMenus }; enum DialogType { diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 85c0768e35..0850228ee5 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -365,6 +365,17 @@ bool QStyleHints::showIsMaximized() const } /*! + \property QStyleHints::showShortcutsInContextMenus + \since 5.10 + \brief \c true if the platform normally shows shortcut key sequences in + context menus, otherwise \c false. +*/ +bool QStyleHints::showShortcutsInContextMenus() const +{ + return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool(); +} + +/*! \property QStyleHints::passwordMaskDelay \brief the time, in milliseconds, a typed letter is displayed unshrouded in a text input field in password mode. diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index b9bf428edd..3230149247 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -90,6 +90,7 @@ public: int cursorFlashTime() const; bool showIsFullScreen() const; bool showIsMaximized() const; + bool showShortcutsInContextMenus() const; int passwordMaskDelay() const; QChar passwordMaskCharacter() const; qreal fontSmoothingGamma() const; diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 4582a55394..ec7dc34d4d 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -45,6 +45,7 @@ #include "qapplication.h" #include "qevent.h" #include "qlist.h" +#include "qstylehints.h" #include <private/qshortcutmap_p.h> #include <private/qapplication_p.h> #include <private/qmenu_p.h> @@ -75,6 +76,7 @@ static QString qt_strippedText(QString s) QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false), iconVisibleInMenu(-1), + shortcutVisibleInContextMenu(-1), menuRole(QAction::TextHeuristicRole), priority(QAction::NormalPriority) { @@ -1292,6 +1294,46 @@ bool QAction::isIconVisibleInMenu() const return d->iconVisibleInMenu; } +/*! + \property QAction::shortcutVisibleInContextMenu + \brief Whether or not an action should show a shortcut in a context menu + \since 5.10 + + In some applications, it may make sense to have actions with shortcuts in + context menus. If true, the shortcut (if valid) is shown when the action is + shown via a context menu, when it is false, it is not shown. + + The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute + is set for the application, falling back to the widget style hint. + Explicitly setting this property overrides the presence (or abscence) of the attribute. + + \sa QAction::shortcut, QCoreApplication::setAttribute() +*/ +void QAction::setShortcutVisibleInContextMenu(bool visible) +{ + Q_D(QAction); + if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) { + int oldValue = d->shortcutVisibleInContextMenu; + d->shortcutVisibleInContextMenu = visible; + // Only send data changed if we really need to. + if (oldValue != -1 + || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) { + d->sendDataChanged(); + } + } +} + +bool QAction::isShortcutVisibleInContextMenu() const +{ + Q_D(const QAction); + if (d->shortcutVisibleInContextMenu == -1) { + if (QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus)) + return false; + return qApp->styleHints()->showShortcutsInContextMenus(); + } + return d->shortcutVisibleInContextMenu; +} + #ifndef QT_NO_DEBUG_STREAM Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QAction *action) { diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h index 97948a2457..d211016931 100644 --- a/src/widgets/kernel/qaction.h +++ b/src/widgets/kernel/qaction.h @@ -80,6 +80,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) + Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed) Q_PROPERTY(Priority priority READ priority WRITE setPriority) public: @@ -168,6 +169,8 @@ public: void setIconVisibleInMenu(bool visible); bool isIconVisibleInMenu() const; + void setShortcutVisibleInContextMenu(bool show); + bool isShortcutVisibleInContextMenu() const; QWidget *parentWidget() const; diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h index 8ee71a5ff0..5f4c9a35a3 100644 --- a/src/widgets/kernel/qaction_p.h +++ b/src/widgets/kernel/qaction_p.h @@ -106,6 +106,7 @@ public: uint fontSet : 1; int iconVisibleInMenu : 3; // Only has values -1, 0, and 1 + int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1 QAction::MenuRole menuRole; QAction::Priority priority; diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index fb0ffd6083..419968db75 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -74,7 +74,10 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include "qkeysequence.h" -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ +#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ + ? false \ + : qApp->styleHints()->showShortcutsInContextMenus()) \ + && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) #else #define ACCEL_KEY(k) QString() diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 2917083415..295fb7d89c 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -332,7 +332,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const tabWidth = qMax(int(tabWidth), qfm.width(s.mid(t+1))); s = s.left(t); #ifndef QT_NO_SHORTCUT - } else { + } else if (action->isShortcutVisibleInContextMenu()) { QKeySequence seq = action->shortcut(); if (!seq.isEmpty()) tabWidth = qMax(int(tabWidth), qfm.width(seq.toString(QKeySequence::NativeText))); @@ -1447,7 +1447,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) option->icon = action->icon(); QString textAndAccel = action->text(); #ifndef QT_NO_SHORTCUT - if (textAndAccel.indexOf(QLatin1Char('\t')) == -1) { + if (action->isShortcutVisibleInContextMenu() + && textAndAccel.indexOf(QLatin1Char('\t')) == -1) { QKeySequence seq = action->shortcut(); if (!seq.isEmpty()) textAndAccel += QLatin1Char('\t') + seq.toString(QKeySequence::NativeText); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index f5672bd87a..9aec94d47f 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -85,7 +85,10 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include <qkeysequence.h> -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ +#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ + ? false \ + : qApp->styleHints()->showShortcutsInContextMenus()) \ + && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) #else |