QAction: add exclusionPolicy property
When set to ExclusiveOptional, the new exclusionPolicy property let the user uncheck the active checkable action in an exclusive group. [ChangeLog][QtWidgets][QActionGroup] Added new exclusionPolicy property. Set it to ExclusiveOptional to allow unchecking the active checkable action in an exclusive group. Change-Id: I61a9885cfd076d631cddf8c08313e4b488e5dc38 Fixes: QTBUG-71160 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
b17e05729e
commit
c826e67765
@ -1153,8 +1153,9 @@ void QAction::activate(ActionEvent event)
|
|||||||
if(event == Trigger) {
|
if(event == Trigger) {
|
||||||
QPointer<QObject> guard = this;
|
QPointer<QObject> guard = this;
|
||||||
if(d->checkable) {
|
if(d->checkable) {
|
||||||
// the checked action of an exclusive group cannot be unchecked
|
// the checked action of an exclusive group may not be unchecked
|
||||||
if (d->checked && (d->group && d->group->isExclusive()
|
if (d->checked && (d->group
|
||||||
|
&& d->group->exclusionPolicy() == QActionGroup::ExclusionPolicy::Exclusive
|
||||||
&& d->group->checkedAction() == this)) {
|
&& d->group->checkedAction() == this)) {
|
||||||
if (!guard.isNull())
|
if (!guard.isNull())
|
||||||
emit triggered(true);
|
emit triggered(true);
|
||||||
|
@ -52,12 +52,16 @@ class QActionGroupPrivate : public QObjectPrivate
|
|||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QActionGroup)
|
Q_DECLARE_PUBLIC(QActionGroup)
|
||||||
public:
|
public:
|
||||||
QActionGroupPrivate() : exclusive(1), enabled(1), visible(1) { }
|
QActionGroupPrivate() : enabled(1),
|
||||||
|
visible(1),
|
||||||
|
exclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive)
|
||||||
|
{
|
||||||
|
}
|
||||||
QList<QAction *> actions;
|
QList<QAction *> actions;
|
||||||
QPointer<QAction> current;
|
QPointer<QAction> current;
|
||||||
uint exclusive : 1;
|
|
||||||
uint enabled : 1;
|
uint enabled : 1;
|
||||||
uint visible : 1;
|
uint visible : 1;
|
||||||
|
QActionGroup::ExclusionPolicy exclusionPolicy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _q_actionTriggered(); //private slot
|
void _q_actionTriggered(); //private slot
|
||||||
@ -70,7 +74,7 @@ void QActionGroupPrivate::_q_actionChanged()
|
|||||||
Q_Q(QActionGroup);
|
Q_Q(QActionGroup);
|
||||||
QAction *action = qobject_cast<QAction*>(q->sender());
|
QAction *action = qobject_cast<QAction*>(q->sender());
|
||||||
Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error");
|
Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error");
|
||||||
if(exclusive) {
|
if (exclusionPolicy != QActionGroup::ExclusionPolicy::None) {
|
||||||
if (action->isChecked()) {
|
if (action->isChecked()) {
|
||||||
if (action != current) {
|
if (action != current) {
|
||||||
if(current)
|
if(current)
|
||||||
@ -127,12 +131,17 @@ void QActionGroupPrivate::_q_actionHovered()
|
|||||||
actions is chosen. Each action in an action group emits its
|
actions is chosen. Each action in an action group emits its
|
||||||
triggered() signal as usual.
|
triggered() signal as usual.
|
||||||
|
|
||||||
As stated above, an action group is \l exclusive by default; it
|
As stated above, an action group is exclusive by default; it
|
||||||
ensures that only one checkable action is active at any one time.
|
ensures that at most only one checkable action is active at any one time.
|
||||||
If you want to group checkable actions without making them
|
If you want to group checkable actions without making them
|
||||||
exclusive, you can turn of exclusiveness by calling
|
exclusive, you can turn off exclusiveness by calling
|
||||||
setExclusive(false).
|
setExclusive(false).
|
||||||
|
|
||||||
|
By default the active action of an exclusive group cannot be unchecked.
|
||||||
|
In some cases it may be useful to allow unchecking all the actions,
|
||||||
|
you can allow this by calling
|
||||||
|
setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional).
|
||||||
|
|
||||||
Actions can be added to an action group using addAction(), but it
|
Actions can be added to an action group using addAction(), but it
|
||||||
is usually more convenient to specify a group when creating
|
is usually more convenient to specify a group when creating
|
||||||
actions; this ensures that actions are automatically created with
|
actions; this ensures that actions are automatically created with
|
||||||
@ -145,11 +154,34 @@ void QActionGroupPrivate::_q_actionHovered()
|
|||||||
\sa QAction
|
\sa QAction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum QActionGroup::ExclusionPolicy
|
||||||
|
|
||||||
|
This enum specifies the different policies that can be used to
|
||||||
|
control how the group performs exclusive checking on checkable actions.
|
||||||
|
|
||||||
|
\value None
|
||||||
|
The actions in the group can be checked independently of each other.
|
||||||
|
|
||||||
|
\value Exclusive
|
||||||
|
Exactly one action can be checked at any one time.
|
||||||
|
This is the default policy.
|
||||||
|
|
||||||
|
\value ExclusiveOptional
|
||||||
|
At most one action can be checked at any one time. The actions
|
||||||
|
can also be all unchecked.
|
||||||
|
|
||||||
|
\sa exclusionPolicy
|
||||||
|
\since 5.14
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs an action group for the \a parent object.
|
Constructs an action group for the \a parent object.
|
||||||
|
|
||||||
The action group is exclusive by default. Call setExclusive(false)
|
The action group is exclusive by default. Call setExclusive(false)
|
||||||
to make the action group non-exclusive.
|
to make the action group non-exclusive. To make the group exclusive
|
||||||
|
but allow unchecking the active action call instead
|
||||||
|
setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional)
|
||||||
*/
|
*/
|
||||||
QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
|
QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
|
||||||
{
|
{
|
||||||
@ -258,26 +290,56 @@ QList<QAction*> QActionGroup::actions() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\property QActionGroup::exclusive
|
\brief Enable or disable the group exclusion checking
|
||||||
\brief whether the action group does exclusive checking
|
|
||||||
|
|
||||||
If exclusive is true, only one checkable action in the action group
|
This is a convenience method that calls
|
||||||
can ever be active at any time. If the user chooses another
|
setExclusionPolicy(ExclusionPolicy::Exclusive).
|
||||||
checkable action in the group, the one they chose becomes active and
|
|
||||||
the one that was active becomes inactive.
|
|
||||||
|
|
||||||
\sa QAction::checkable
|
\sa QActionGroup::exclusionPolicy
|
||||||
*/
|
*/
|
||||||
void QActionGroup::setExclusive(bool b)
|
void QActionGroup::setExclusive(bool b)
|
||||||
{
|
{
|
||||||
Q_D(QActionGroup);
|
setExclusionPolicy(b ? QActionGroup::ExclusionPolicy::Exclusive
|
||||||
d->exclusive = b;
|
: QActionGroup::ExclusionPolicy::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Returs true if the group is exclusive
|
||||||
|
|
||||||
|
The group is exclusive if the ExclusionPolicy is either Exclusive
|
||||||
|
or ExclusionOptional.
|
||||||
|
|
||||||
|
*/
|
||||||
bool QActionGroup::isExclusive() const
|
bool QActionGroup::isExclusive() const
|
||||||
|
{
|
||||||
|
return exclusionPolicy() != QActionGroup::ExclusionPolicy::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QActionGroup::exclusionPolicy
|
||||||
|
\brief This property holds the group exclusive checking policy
|
||||||
|
|
||||||
|
If exclusionPolicy is set to Exclusive, only one checkable
|
||||||
|
action in the action group can ever be active at any time. If the user
|
||||||
|
chooses another checkable action in the group, the one they chose becomes
|
||||||
|
active and the one that was active becomes inactive. If exclusionPolicy is
|
||||||
|
set to ExclusionOptional the group is exclusive but the active checkable
|
||||||
|
action in the group can be unchecked leaving the group with no actions
|
||||||
|
checked.
|
||||||
|
|
||||||
|
\sa QAction::checkable
|
||||||
|
\since 5.14
|
||||||
|
*/
|
||||||
|
void QActionGroup::setExclusionPolicy(QActionGroup::ExclusionPolicy policy)
|
||||||
|
{
|
||||||
|
Q_D(QActionGroup);
|
||||||
|
d->exclusionPolicy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
QActionGroup::ExclusionPolicy QActionGroup::exclusionPolicy() const
|
||||||
{
|
{
|
||||||
Q_D(const QActionGroup);
|
Q_D(const QActionGroup);
|
||||||
return d->exclusive;
|
return d->exclusionPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -55,11 +55,18 @@ class Q_WIDGETS_EXPORT QActionGroup : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DECLARE_PRIVATE(QActionGroup)
|
Q_DECLARE_PRIVATE(QActionGroup)
|
||||||
|
|
||||||
Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
|
Q_PROPERTY(QActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy)
|
||||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||||
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
|
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum class ExclusionPolicy {
|
||||||
|
None,
|
||||||
|
Exclusive,
|
||||||
|
ExclusiveOptional
|
||||||
|
};
|
||||||
|
Q_ENUM(ExclusionPolicy)
|
||||||
|
|
||||||
explicit QActionGroup(QObject* parent);
|
explicit QActionGroup(QObject* parent);
|
||||||
~QActionGroup();
|
~QActionGroup();
|
||||||
|
|
||||||
@ -73,6 +80,7 @@ public:
|
|||||||
bool isExclusive() const;
|
bool isExclusive() const;
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
bool isVisible() const;
|
bool isVisible() const;
|
||||||
|
ExclusionPolicy exclusionPolicy() const;
|
||||||
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
@ -80,6 +88,7 @@ public Q_SLOTS:
|
|||||||
inline void setDisabled(bool b) { setEnabled(!b); }
|
inline void setDisabled(bool b) { setEnabled(!b); }
|
||||||
void setVisible(bool);
|
void setVisible(bool);
|
||||||
void setExclusive(bool);
|
void setExclusive(bool);
|
||||||
|
void setExclusionPolicy(ExclusionPolicy policy);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void triggered(QAction *);
|
void triggered(QAction *);
|
||||||
|
@ -41,6 +41,7 @@ private slots:
|
|||||||
void enabledPropagation();
|
void enabledPropagation();
|
||||||
void visiblePropagation();
|
void visiblePropagation();
|
||||||
void exclusive();
|
void exclusive();
|
||||||
|
void exclusiveOptional();
|
||||||
void separators();
|
void separators();
|
||||||
void testActionInTwoQActionGroup();
|
void testActionInTwoQActionGroup();
|
||||||
void unCheckCurrentAction();
|
void unCheckCurrentAction();
|
||||||
@ -151,6 +152,52 @@ void tst_QActionGroup::exclusive()
|
|||||||
QVERIFY( !actThree->isChecked() );
|
QVERIFY( !actThree->isChecked() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QActionGroup::exclusiveOptional()
|
||||||
|
{
|
||||||
|
QActionGroup group(0);
|
||||||
|
group.setExclusive(true);
|
||||||
|
QVERIFY( group.isExclusive() );
|
||||||
|
|
||||||
|
QAction* actOne = new QAction( &group );
|
||||||
|
actOne->setCheckable( true );
|
||||||
|
QAction* actTwo = new QAction( &group );
|
||||||
|
actTwo->setCheckable( true );
|
||||||
|
QAction* actThree = new QAction( &group );
|
||||||
|
actThree->setCheckable( true );
|
||||||
|
|
||||||
|
QVERIFY( !actOne->isChecked() );
|
||||||
|
QVERIFY( !actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
|
||||||
|
actOne->trigger();
|
||||||
|
QVERIFY( actOne->isChecked() );
|
||||||
|
QVERIFY( !actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
|
||||||
|
actOne->trigger();
|
||||||
|
QVERIFY( actOne->isChecked() );
|
||||||
|
QVERIFY( !actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
|
||||||
|
group.setExclusionPolicy( QActionGroup::ExclusionPolicy::ExclusiveOptional );
|
||||||
|
QVERIFY( group.isExclusive() );
|
||||||
|
|
||||||
|
actOne->trigger();
|
||||||
|
QVERIFY( !actOne->isChecked() );
|
||||||
|
QVERIFY( !actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
|
||||||
|
actTwo->trigger();
|
||||||
|
QVERIFY( !actOne->isChecked() );
|
||||||
|
QVERIFY( actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
|
||||||
|
actTwo->trigger();
|
||||||
|
QVERIFY( !actOne->isChecked() );
|
||||||
|
QVERIFY( !actTwo->isChecked() );
|
||||||
|
QVERIFY( !actThree->isChecked() );
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QActionGroup::separators()
|
void tst_QActionGroup::separators()
|
||||||
{
|
{
|
||||||
QMainWindow mw;
|
QMainWindow mw;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user