Coverage Report

Created: 2026-07-30 07:17

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