Coverage Report

Created: 2026-03-12 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/kernel/qactiongroup.cpp
Line
Count
Source
1
// Copyright (C) 2019 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
// Qt-Security score:significant reason:default
4
5
#include "qactiongroup.h"
6
7
#include "qaction.h"
8
#include "qaction_p.h"
9
#include "qactiongroup_p.h"
10
#include "qevent.h"
11
#include "qlist.h"
12
13
QT_BEGIN_NAMESPACE
14
15
QActionGroupPrivate::QActionGroupPrivate() :
16
0
    enabled(1), visible(1)
17
0
{
18
0
}
19
20
0
QActionGroupPrivate::~QActionGroupPrivate() = default;
21
22
void QActionGroup::_q_actionChanged()
23
0
{
24
0
    Q_D(QActionGroup);
25
0
    auto action = qobject_cast<QAction*>(sender());
26
0
    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionChanged", "internal error");
27
0
    if (d->exclusionPolicy != QActionGroup::ExclusionPolicy::None) {
28
0
        if (action->isChecked()) {
29
0
            if (action != d->current) {
30
0
                if (!d->current.isNull())
31
0
                    d->current->setChecked(false);
32
0
                d->current = action;
33
0
            }
34
0
        } else if (action == d->current) {
35
0
            d->current = nullptr;
36
0
        }
37
0
    }
38
0
}
39
40
void QActionGroup::_q_actionTriggered()
41
0
{
42
0
    auto action = qobject_cast<QAction*>(sender());
43
0
    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionTriggered", "internal error");
44
0
    emit triggered(action);
45
0
}
46
47
void QActionGroup::_q_actionHovered()
48
0
{
49
0
    auto action = qobject_cast<QAction*>(sender());
50
0
    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionHovered", "internal error");
51
0
    emit hovered(action);
52
0
}
53
54
/*!
55
    \class QActionGroup
56
    \brief The QActionGroup class groups actions together.
57
    \since 6.0
58
59
    \inmodule QtGui
60
61
    QActionGroup is a base class for classes grouping
62
    classes inhheriting QAction objects together.
63
64
    In some situations it is useful to group QAction objects together.
65
    For example, if you have a \uicontrol{Left Align} action, a \uicontrol{Right
66
    Align} action, a \uicontrol{Justify} action, and a \uicontrol{Center} action,
67
    only one of these actions should be active at any one time. One
68
    simple way of achieving this is to group the actions together in
69
    an action group, inheriting QActionGroup.
70
71
    \sa QAction
72
*/
73
74
/*!
75
    \enum QActionGroup::ExclusionPolicy
76
77
    This enum specifies the different policies that can be used to
78
    control how the group performs exclusive checking on checkable actions.
79
80
    \value None
81
           The actions in the group can be checked independently of each other.
82
83
    \value Exclusive
84
           Exactly one action can be checked at any one time.
85
           This is the default policy.
86
87
    \value ExclusiveOptional
88
           At most one action can be checked at any one time. The actions
89
           can also be all unchecked.
90
91
    \sa exclusionPolicy
92
*/
93
94
/*!
95
    Constructs an action group for the \a parent object.
96
97
    The action group is exclusive by default. Call setExclusive(false)
98
    to make the action group non-exclusive. To make the group exclusive
99
    but allow unchecking the active action call instead
100
    setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional)
101
*/
102
QActionGroup::QActionGroup(QObject* parent) :
103
0
    QActionGroup(*new QActionGroupPrivate, parent)
104
0
{
105
0
}
106
107
QActionGroup::QActionGroup(QActionGroupPrivate &dd, QObject *parent) :
108
0
    QObject(dd, parent)
109
0
{
110
0
}
111
112
/*!
113
    Destroys the action group.
114
*/
115
0
QActionGroup::~QActionGroup() = default;
116
117
/*!
118
    \fn QAction *QActionGroup::addAction(QAction *action)
119
120
    Adds the \a action to this group, and returns it.
121
122
    Normally an action is added to a group by creating it with the
123
    group as its parent, so this function is not usually used.
124
125
    \sa QAction::setActionGroup()
126
*/
127
QAction *QActionGroup::addAction(QAction* a)
128
0
{
129
0
    Q_D(QActionGroup);
130
0
    if (!d->actions.contains(a)) {
131
0
        d->actions.append(a);
132
0
        QObject::connect(a, &QAction::triggered, this, &QActionGroup::_q_actionTriggered);
133
0
        QObject::connect(a, &QAction::changed, this, &QActionGroup::_q_actionChanged);
134
0
        QObject::connect(a, &QAction::hovered, this, &QActionGroup::_q_actionHovered);
135
0
    }
136
0
    a->d_func()->setEnabled(d->enabled, true);
137
0
    if (!a->d_func()->forceInvisible)
138
0
        a->d_func()->setVisible(d->visible);
139
0
    if (a->isChecked())
140
0
        d->current = a;
141
0
    QActionGroup *oldGroup = a->d_func()->group;
142
0
    if (oldGroup != this) {
143
0
        if (oldGroup)
144
0
            oldGroup->removeAction(a);
145
0
        a->d_func()->group = this;
146
0
        a->d_func()->sendDataChanged();
147
0
    }
148
0
    return a;
149
0
}
150
151
/*!
152
    Creates and returns an action with \a text.  The newly created
153
    action is a child of this action group.
154
155
    Normally an action is added to a group by creating it with the
156
    group as parent, so this function is not usually used.
157
158
    \sa QAction::setActionGroup()
159
*/
160
QAction *QActionGroup::addAction(const QString &text)
161
0
{
162
0
    return new QAction(text, this);
163
0
}
164
165
/*!
166
    Creates and returns an action with \a text and an \a icon. The
167
    newly created action is a child of this action group.
168
169
    Normally an action is added to a group by creating it with the
170
    group as its parent, so this function is not usually used.
171
172
    \sa QAction::setActionGroup()
173
*/
174
QAction *QActionGroup::addAction(const QIcon &icon, const QString &text)
175
0
{
176
0
    return new QAction(icon, text, this);
177
0
}
178
179
/*!
180
  Removes the \a action from this group. The action will have no
181
  parent as a result.
182
183
  \sa QAction::setActionGroup()
184
*/
185
void QActionGroup::removeAction(QAction *action)
186
0
{
187
0
    Q_D(QActionGroup);
188
0
    if (d->actions.removeAll(action)) {
189
0
        if (action == d->current)
190
0
            d->current = nullptr;
191
0
        QObject::disconnect(action, &QAction::triggered, this, &QActionGroup::_q_actionTriggered);
192
0
        QObject::disconnect(action, &QAction::changed, this, &QActionGroup::_q_actionChanged);
193
0
        QObject::disconnect(action, &QAction::hovered, this, &QActionGroup::_q_actionHovered);
194
0
        action->d_func()->group = nullptr;
195
0
    }
196
0
}
197
198
/*!
199
    Returns the list of this groups's actions. This may be empty.
200
*/
201
QList<QAction*> QActionGroup::actions() const
202
0
{
203
0
    Q_D(const QActionGroup);
204
0
    return d->actions;
205
0
}
206
207
/*!
208
    \brief Enable or disable the group exclusion checking
209
210
    This is a convenience method that calls
211
    setExclusionPolicy(ExclusionPolicy::Exclusive) when \a b is true,
212
    else setExclusionPolicy(QActionGroup::ExclusionPolicy::None).
213
214
    \sa QActionGroup::exclusionPolicy
215
*/
216
void QActionGroup::setExclusive(bool b)
217
0
{
218
0
    setExclusionPolicy(b ? QActionGroup::ExclusionPolicy::Exclusive
219
0
                         : QActionGroup::ExclusionPolicy::None);
220
0
}
221
222
/*!
223
    \brief Returns true if the group is exclusive
224
225
    The group is exclusive if the ExclusionPolicy is either Exclusive
226
    or ExclusionOptional.
227
228
*/
229
bool QActionGroup::isExclusive() const
230
0
{
231
0
    return exclusionPolicy() != QActionGroup::ExclusionPolicy::None;
232
0
}
233
234
/*!
235
    \property QActionGroup::exclusionPolicy
236
    \brief This property holds the group exclusive checking policy
237
238
    If exclusionPolicy is set to Exclusive, only one checkable
239
    action in the action group can ever be active at any time. If the user
240
    chooses another checkable action in the group, the one they chose becomes
241
    active and the one that was active becomes inactive. If exclusionPolicy is
242
    set to ExclusionOptional the group is exclusive but the active checkable
243
    action in the group can be unchecked leaving the group with no actions
244
    checked.
245
246
    \sa QAction::checkable
247
*/
248
void QActionGroup::setExclusionPolicy(QActionGroup::ExclusionPolicy policy)
249
0
{
250
0
    Q_D(QActionGroup);
251
0
    d->exclusionPolicy = policy;
252
0
}
253
254
QActionGroup::ExclusionPolicy QActionGroup::exclusionPolicy() const
255
0
{
256
0
    Q_D(const QActionGroup);
257
0
    return d->exclusionPolicy;
258
0
}
259
260
/*!
261
    \fn void QActionGroup::setDisabled(bool b)
262
263
    This is a convenience function for the \l enabled property, that
264
    is useful for signals--slots connections. If \a b is true the
265
    action group is disabled; otherwise it is enabled.
266
*/
267
268
/*!
269
    \property QActionGroup::enabled
270
    \brief whether the action group is enabled
271
272
    Each action in the group will be enabled or disabled unless it
273
    has been explicitly disabled.
274
275
    \sa QAction::setEnabled()
276
*/
277
void QActionGroup::setEnabled(bool b)
278
0
{
279
0
    Q_D(QActionGroup);
280
0
    d->enabled = b;
281
0
    for (auto action : std::as_const(d->actions)) {
282
0
        action->d_func()->setEnabled(b, true);
283
0
    }
284
0
}
285
286
bool QActionGroup::isEnabled() const
287
0
{
288
0
    Q_D(const QActionGroup);
289
0
    return d->enabled;
290
0
}
291
292
/*!
293
  Returns the currently checked action in the group, or \nullptr if
294
  none are checked.
295
*/
296
QAction *QActionGroup::checkedAction() const
297
0
{
298
0
    Q_D(const QActionGroup);
299
0
    return d->current.data();
300
0
}
301
302
/*!
303
    \property QActionGroup::visible
304
    \brief whether the action group is visible
305
306
    Each action in the action group will match the visible state of
307
    this group unless it has been explicitly hidden.
308
309
    \sa QAction::setEnabled()
310
*/
311
void QActionGroup::setVisible(bool b)
312
0
{
313
0
    Q_D(QActionGroup);
314
0
    d->visible = b;
315
0
    for (auto action : std::as_const(d->actions)) {
316
0
        if (!action->d_func()->forceInvisible)
317
0
            action->d_func()->setVisible(b);
318
0
    }
319
0
}
320
321
bool QActionGroup::isVisible() const
322
0
{
323
    Q_D(const QActionGroup);
324
0
    return d->visible;
325
0
}
326
327
/*!
328
    \fn void QActionGroup::triggered(QAction *action)
329
330
    This signal is emitted when the given \a action in the action
331
    group is activated by the user; for example, when the user clicks
332
    a menu option or a toolbar button, or presses an action's shortcut
333
    key combination.
334
335
    Connect to this signal for command actions.
336
337
    \sa QAction::activate()
338
*/
339
340
/*!
341
    \fn void QActionGroup::hovered(QAction *action)
342
343
    This signal is emitted when the given \a action in the action
344
    group is highlighted by the user; for example, when the user
345
    pauses with the cursor over a menu option or a toolbar button,
346
    or presses an action's shortcut key combination.
347
348
    \sa QAction::activate()
349
*/
350
351
QT_END_NAMESPACE
352
353
#include "moc_qactiongroup.cpp"