Coverage Report

Created: 2025-07-16 07:53

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