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) <faure@kde.org>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
bb10
Kevin Ottens 2013-02-27 17:11:41 +01:00 committed by The Qt Project
parent bad1918cb4
commit 03e2ea2ac0
6 changed files with 115 additions and 2 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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()
*/

View File

@ -697,6 +697,7 @@ public:
SH_ToolButtonStyle,
SH_RequestSoftwareInputPanel,
SH_ScrollBar_Transient,
SH_Menu_SupportsSections,
// Add new style hint values here
SH_CustomBase = 0xf0000000

View File

@ -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

View File

@ -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();