From 03e2ea2ac057b2b4aa1dc4e5b817ffd552080ce5 Mon Sep 17 00:00:00 2001 From: Kevin Ottens Date: Wed, 27 Feb 2013 17:11:41 +0100 Subject: Add convenience for section actions in QMenu Those actions are just separators having also text and potentially icon. It is very convenient to create titled sections in a menu, or give a title to a context menu. Obviously requires support for them on the style side, but modern styles like fusion or oxygen handle them just fine. For legacy styles it properly falls back to a regular separator aspect. That's why a specific style hint is also introduced. It is used by QMenu to know how the sections will be treated and take care of them correctly when eliminating duplicated separators or separators at the beginning of the menu. Change-Id: Iad00a93422b7983dc90dfc4b4b1c360122e47610 Reviewed-by: David Faure (KDE) Reviewed-by: Lars Knoll --- src/widgets/styles/qcommonstyle.cpp | 3 ++ src/widgets/styles/qfusionstyle.cpp | 1 + src/widgets/styles/qstyle.cpp | 3 ++ src/widgets/styles/qstyle.h | 1 + src/widgets/widgets/qmenu.cpp | 104 +++++++++++++++++++++++++++++++++++- src/widgets/widgets/qmenu.h | 5 ++ 6 files changed, 115 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 64eb76dbb4..269b887909 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -5109,6 +5109,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget case SH_ScrollBar_Transient: ret = false; break; + case SH_Menu_SupportsSections: + ret = false; + break; default: ret = 0; break; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index defdf30b6b..ee237ac71a 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -3473,6 +3473,7 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW case SH_ItemView_ChangeHighlightOnFocus: case SH_MenuBar_MouseTracking: case SH_Menu_MouseTracking: + case SH_Menu_SupportsSections: return 1; case SH_ToolBox_SelectedPageTitleBold: diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 9c4901795d..1d4e4bd570 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1891,6 +1891,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_ScrollBar_Transient Determines if the style supports transient scroll bars. Transient scroll bars appear when the content is scrolled and disappear when they are no longer needed. + \value SH_Menu_SupportsSections Determines if the style displays sections in menus or treat them as + plain separators. Sections are separators with a text and icon hint. + \sa styleHint() */ diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index a9ac1813c5..0d139cb83d 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -697,6 +697,7 @@ public: SH_ToolButtonStyle, SH_RequestSoftwareInputPanel, SH_ScrollBar_Transient, + SH_Menu_SupportsSections, // Add new style hint values here SH_CustomBase = 0xf0000000 diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 117d56ff18..bbfc79d117 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -260,12 +260,15 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const bool previousWasSeparator = true; // this is true to allow removing the leading separators for(int i = 0; i <= lastVisibleAction; i++) { QAction *action = actions.at(i); + const bool isSection = action->isSeparator() && (!action->text().isEmpty() || !action->icon().isNull()); + const bool isPlainSeparator = (isSection && !q->style()->styleHint(QStyle::SH_Menu_SupportsSections)) + || (action->isSeparator() && !isSection); if (!action->isVisible() || - (collapsibleSeparators && previousWasSeparator && action->isSeparator())) + (collapsibleSeparators && previousWasSeparator && isPlainSeparator)) continue; // we continue, this action will get an empty QRect - previousWasSeparator = action->isSeparator(); + previousWasSeparator = isPlainSeparator; //let the style modify the above size.. QStyleOptionMenuItem opt; @@ -1510,6 +1513,54 @@ QAction *QMenu::addSeparator() return action; } +/*! + \since 5.1 + + This convenience function creates a new section action, i.e. an + action with QAction::isSeparator() returning true but also + having \a text hint, and adds the new action to this menu's list + of actions. It returns the newly created action. + + The rendering of the hint is style and platform dependent. Widget + styles can use the text information in the rendering for sections, + or can choose to ignore it and render sections like simple separators. + + QMenu takes ownership of the returned QAction. + + \sa QWidget::addAction() +*/ +QAction *QMenu::addSection(const QString &text) +{ + QAction *action = new QAction(text, this); + action->setSeparator(true); + addAction(action); + return action; +} + +/*! + \since 5.1 + + This convenience function creates a new section action, i.e. an + action with QAction::isSeparator() returning true but also + having \a text and \a icon hints, and adds the new action to this menu's + list of actions. It returns the newly created action. + + The rendering of the hints is style and platform dependent. Widget + styles can use the text and icon information in the rendering for sections, + or can choose to ignore them and render sections like simple separators. + + QMenu takes ownership of the returned QAction. + + \sa QWidget::addAction() +*/ +QAction *QMenu::addSection(const QIcon &icon, const QString &text) +{ + QAction *action = new QAction(icon, text, this); + action->setSeparator(true); + addAction(action); + return action; +} + /*! This convenience function inserts \a menu before action \a before and returns the menus menuAction(). @@ -1541,6 +1592,55 @@ QAction *QMenu::insertSeparator(QAction *before) return action; } +/*! + \since 5.1 + + This convenience function creates a new title action, i.e. an + action with QAction::isSeparator() returning true but also having + \a text hint. The function inserts the newly created action + into this menu's list of actions before action \a before and + returns it. + + The rendering of the hint is style and platform dependent. Widget + styles can use the text information in the rendering for sections, + or can choose to ignore it and render sections like simple separators. + + QMenu takes ownership of the returned QAction. + + \sa QWidget::insertAction(), addSection() +*/ +QAction *QMenu::insertSection(QAction *before, const QString &text) +{ + QAction *action = new QAction(text, this); + action->setSeparator(true); + insertAction(before, action); + return action; +} + +/*! + \since 5.1 + + This convenience function creates a new title action, i.e. an + action with QAction::isSeparator() returning true but also having + \a text and \a icon hints. The function inserts the newly created action + into this menu's list of actions before action \a before and returns it. + + The rendering of the hints is style and platform dependent. Widget + styles can use the text and icon information in the rendering for sections, + or can choose to ignore them and render sections like simple separators. + + QMenu takes ownership of the returned QAction. + + \sa QWidget::insertAction(), addSection() +*/ +QAction *QMenu::insertSection(QAction *before, const QIcon &icon, const QString &text) +{ + QAction *action = new QAction(icon, text, this); + action->setSeparator(true); + insertAction(before, action); + return action; +} + /*! This sets the default action to \a act. The default action may have a visual cue, depending on the current QStyle. A default action diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 7547c69a10..7fa3336769 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -93,8 +93,13 @@ public: QAction *addSeparator(); + QAction *addSection(const QString &text); + QAction *addSection(const QIcon &icon, const QString &text); + QAction *insertMenu(QAction *before, QMenu *menu); QAction *insertSeparator(QAction *before); + QAction *insertSection(QAction *before, const QString &text); + QAction *insertSection(QAction *before, const QIcon &icon, const QString &text); bool isEmpty() const; void clear(); -- cgit v1.2.3