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/qaction.cpp
Line
Count
Source
1
// Copyright (C) 2020 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 "qaction.h"
6
#include "qactiongroup.h"
7
8
#include "qaction_p.h"
9
#include "qguiapplication.h"
10
#include "qevent.h"
11
#include "qlist.h"
12
#include "qstylehints.h"
13
#if QT_CONFIG(shortcut)
14
#  include <private/qshortcutmap_p.h>
15
#endif
16
#include <private/qguiapplication_p.h>
17
#include <private/qdebug_p.h>
18
19
#define QAPP_CHECK(functionName) \
20
0
    if (Q_UNLIKELY(!QCoreApplication::instance())) { \
21
0
        qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \
22
0
        return; \
23
0
    }
24
25
QT_BEGIN_NAMESPACE
26
27
using namespace Qt::StringLiterals;
28
29
/*
30
  internal: guesses a descriptive text from a text suited for a menu entry
31
 */
32
static QString qt_strippedText(QString s)
33
0
{
34
0
    for (qsizetype i = 0; i < s.size(); ++i) {
35
0
        const QChar &c = s.at(i);
36
0
        if (c == u'&' || c == u'\x2026')    // Horizontal Ellipsis
37
0
            s.remove(i, 1);
38
0
        else if (i + 2 < s.size() && c == u'.' && s.at(i + 1) == u'.' && s.at(i + 2) == u'.')
39
0
            s.remove(i, 3);
40
0
    }
41
0
    return s.trimmed();
42
0
}
43
44
QActionPrivate *QGuiApplicationPrivate::createActionPrivate() const
45
0
{
46
0
    return new QActionPrivate;
47
0
}
48
49
QActionPrivate::QActionPrivate() :
50
#if QT_CONFIG(shortcut)
51
0
    autorepeat(1),
52
#endif
53
0
    enabled(1), explicitEnabled(0), explicitEnabledValue(1), visible(1), forceInvisible(0), checkable(0),
54
0
    checked(0), separator(0), fontSet(false),
55
0
    iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1)
56
0
{
57
0
}
58
59
#if QT_CONFIG(shortcut)
60
0
static bool dummy(QObject *, Qt::ShortcutContext) { return false; } // only for GUI testing.
61
62
QShortcutMap::ContextMatcher QActionPrivate::contextMatcher() const
63
0
{
64
0
    return dummy;
65
0
};
66
#endif // QT_CONFIG(shortcut)
67
68
0
QActionPrivate::~QActionPrivate() = default;
69
70
void QActionPrivate::destroy()
71
0
{
72
0
}
73
74
void QActionPrivate::sendDataChanged()
75
0
{
76
0
    Q_Q(QAction);
77
0
    QActionEvent e(QEvent::ActionChanged, q);
78
0
    QCoreApplication::sendEvent(q, &e);
79
80
0
    emit q->changed();
81
0
}
82
83
#if QT_CONFIG(shortcut)
84
void QActionPrivate::redoGrab(QShortcutMap &map)
85
0
{
86
0
    Q_Q(QAction);
87
0
    for (int id : std::as_const(shortcutIds)) {
88
0
        if (id)
89
0
            map.removeShortcut(id, q);
90
0
    }
91
92
0
    shortcutIds.clear();
93
0
    for (const QKeySequence &shortcut : std::as_const(shortcuts)) {
94
0
        if (!shortcut.isEmpty())
95
0
            shortcutIds.append(map.addShortcut(q, shortcut, shortcutContext, contextMatcher()));
96
0
        else
97
0
            shortcutIds.append(0);
98
0
    }
99
0
    if (!enabled) {
100
0
        for (int id : std::as_const(shortcutIds)) {
101
0
            if (id)
102
0
                map.setShortcutEnabled(false, id, q);
103
0
        }
104
0
    }
105
0
    if (!autorepeat) {
106
0
        for (int id : std::as_const(shortcutIds)) {
107
0
            if (id)
108
0
                map.setShortcutAutoRepeat(false, id, q);
109
0
        }
110
0
    }
111
0
}
112
113
void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
114
0
{
115
0
    Q_Q(QAction);
116
0
    for (int id : std::as_const(shortcutIds)) {
117
0
        if (id)
118
0
            map.setShortcutEnabled(enable, id, q);
119
0
    }
120
0
}
121
#endif // QT_NO_SHORTCUT
122
123
bool QActionPrivate::showStatusText(QObject *object, const QString &str)
124
0
{
125
0
    if (QObject *receiver = object ? object : parent) {
126
0
        QStatusTipEvent tip(str);
127
0
        QCoreApplication::sendEvent(receiver, &tip);
128
0
        return true;
129
0
    }
130
0
    return false;
131
0
}
132
133
void QActionPrivate::setMenu(QObject *)
134
0
{
135
0
}
136
137
QObject *QActionPrivate::menu() const
138
0
{
139
0
    return nullptr;
140
0
}
141
142
/*!
143
    \class QAction
144
    \brief The QAction class provides an abstraction for user commands
145
    that can be added to different user interface components.
146
    \since 6.0
147
148
    \inmodule QtGui
149
150
    In applications many common commands can be invoked via menus,
151
    toolbar buttons, and keyboard shortcuts. Since the user expects
152
    each command to be performed in the same way, regardless of the
153
    user interface used, it is useful to represent each command as
154
    an \e action.
155
156
    Actions can be added to user interface elements such as menus and toolbars,
157
    and will automatically keep the UI in sync. For example, in a word
158
    processor, if the user presses a Bold toolbar button, the Bold menu item
159
    will automatically be checked.
160
161
    A QAction may contain an icon, descriptive text, icon text, a keyboard
162
    shortcut, status text, "What's This?" text, and a tooltip. All properties
163
    can be set independently with setIcon(), setText(), setIconText(),
164
    setShortcut(), setStatusTip(), setWhatsThis(), and setToolTip(). Icon and
165
    text, as the two most important properties, can also be set in the
166
    constructor. It's possible to set an individual font with setFont(), which
167
    e.g. menus respect when displaying the action as a menu item.
168
169
    We recommend that actions are created as children of the window
170
    they are used in. In most cases actions will be children of
171
    the application's main window.
172
173
    \section1 QAction in widget applications
174
175
    Once a QAction has been created, it should be added to the relevant
176
    menu and toolbar, then connected to the slot which will perform
177
    the action.
178
179
    Actions are added to widgets using QWidget::addAction() or
180
    QGraphicsWidget::addAction(). Note that an action must be added to a
181
    widget before it can be used. This is also true when the shortcut should
182
    be global (i.e., Qt::ApplicationShortcut as Qt::ShortcutContext).
183
184
    Actions can be created as independent objects. But they may
185
    also be created during the construction of menus. The QMenu class
186
    contains convenience functions for creating actions suitable for
187
    use as menu items.
188
189
190
    \sa QMenu, QToolBar
191
*/
192
193
/*!
194
    \fn void QAction::trigger()
195
196
    This is a convenience slot that calls activate(Trigger).
197
*/
198
199
/*!
200
    \fn void QAction::hover()
201
202
    This is a convenience slot that calls activate(Hover).
203
*/
204
205
/*!
206
    \enum QAction::MenuRole
207
208
    This enum describes how an action should be moved into the application menu on \macos.
209
210
    \value NoRole This action should not be put into the application menu
211
    \value TextHeuristicRole This action should be put in the application menu based on the action's text
212
           as described in the QMenuBar documentation.
213
    \value ApplicationSpecificRole This action should be put in the application menu with an application specific role
214
    \value AboutQtRole This action handles the "About Qt" menu item.
215
    \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
216
           the menu item will be set to "About <application name>". The application name is fetched from the
217
           \c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}).
218
    \value PreferencesRole This action should be placed where the  "Preferences..." menu item is in the application menu.
219
    \value QuitRole This action should be placed where the Quit menu item is in the application menu.
220
221
    Setting this value only has effect on items that are in the immediate menus
222
    of the menubar, not the submenus of those menus. For example, if you have
223
    File menu in your menubar and the File menu has a submenu, setting the
224
    MenuRole for the actions in that submenu have no effect. They will never be moved.
225
*/
226
227
/*!
228
    Constructs an action with \a parent. If \a parent is an action
229
    group the action will be automatically inserted into the group.
230
231
    \note The \a parent argument is optional since Qt 5.7.
232
*/
233
QAction::QAction(QObject *parent)
234
0
    : QAction(*QGuiApplicationPrivate::instance()->createActionPrivate(), parent)
235
0
{
236
0
}
237
238
/*!
239
    Constructs an action with some \a text and \a parent. If \a
240
    parent is an action group the action will be automatically
241
    inserted into the group.
242
243
    A stripped version of \a text (for example, "\&Menu Option..." becomes
244
    "Menu Option") will be used for tooltips and icon text unless you specify a
245
    different text using setToolTip() or setIconText(), respectively.
246
247
    \sa text
248
*/
249
QAction::QAction(const QString &text, QObject *parent)
250
0
    : QAction(parent)
251
0
{
252
0
    Q_D(QAction);
253
0
    d->text = text;
254
0
}
255
256
/*!
257
    Constructs an action with an \a icon and some \a text and \a
258
    parent. If \a parent is an action group the action will be
259
    automatically inserted into the group.
260
261
    A stripped version of \a text (for example, "\&Menu Option..." becomes
262
    "Menu Option") will be used for tooltips and icon text unless you specify a
263
    different text using setToolTip() or setIconText(), respectively.
264
265
    \sa text, icon
266
*/
267
QAction::QAction(const QIcon &icon, const QString &text, QObject *parent)
268
0
    : QAction(text, parent)
269
0
{
270
0
    Q_D(QAction);
271
0
    d->icon = icon;
272
0
}
273
274
/*!
275
    \internal
276
*/
277
QAction::QAction(QActionPrivate &dd, QObject *parent)
278
0
    : QObject(dd, parent)
279
0
{
280
0
    Q_D(QAction);
281
0
    d->group = qobject_cast<QActionGroup *>(parent);
282
0
    if (d->group)
283
0
        d->group->addAction(this);
284
0
}
285
286
#if QT_CONFIG(shortcut)
287
/*!
288
    \property QAction::shortcut
289
    \brief the action's primary shortcut key
290
291
    Valid keycodes for this property can be found in \l Qt::Key and
292
    \l Qt::Modifier. There is no default shortcut key.
293
*/
294
295
/*!
296
    Sets \a shortcut as the sole shortcut that triggers the action.
297
298
    \sa shortcut, setShortcuts()
299
*/
300
void QAction::setShortcut(const QKeySequence &shortcut)
301
0
{
302
0
    if (shortcut.isEmpty())
303
0
        setShortcuts({});
304
0
    else
305
0
        setShortcuts({ shortcut });
306
0
}
307
308
/*!
309
    Sets \a shortcuts as the list of shortcuts that trigger the
310
    action. The first element of the list is the primary shortcut.
311
312
    \sa shortcut, setShortcut()
313
*/
314
void QAction::setShortcuts(const QList<QKeySequence> &shortcuts)
315
0
{
316
0
    QAPP_CHECK("setShortcuts");
317
0
    Q_D(QAction);
318
319
0
    if (d->shortcuts == shortcuts)
320
0
        return;
321
322
0
    d->shortcuts = shortcuts;
323
0
    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
324
0
    d->sendDataChanged();
325
0
}
326
327
/*!
328
    Sets a platform dependent list of shortcuts based on the \a key.
329
    The result of calling this function will depend on the currently running platform.
330
    Note that more than one shortcut can assigned by this action.
331
    If only the primary shortcut is required, use setShortcut instead.
332
333
    \sa QKeySequence::keyBindings()
334
*/
335
void QAction::setShortcuts(QKeySequence::StandardKey key)
336
0
{
337
0
    QList <QKeySequence> list = QKeySequence::keyBindings(key);
338
0
    setShortcuts(list);
339
0
}
340
341
/*!
342
    Returns the primary shortcut.
343
344
    \sa setShortcuts()
345
*/
346
QKeySequence QAction::shortcut() const
347
0
{
348
0
    Q_D(const QAction);
349
0
    if (d->shortcuts.isEmpty())
350
0
        return QKeySequence();
351
0
    return d->shortcuts.first();
352
0
}
353
354
/*!
355
    Returns the list of shortcuts, with the primary shortcut as
356
    the first element of the list.
357
358
    \sa setShortcuts()
359
*/
360
QList<QKeySequence> QAction::shortcuts() const
361
0
{
362
0
    Q_D(const QAction);
363
0
    return d->shortcuts;
364
0
}
365
366
/*!
367
    \property QAction::shortcutContext
368
    \brief the context for the action's shortcut
369
370
    Valid values for this property can be found in \l Qt::ShortcutContext.
371
    The default value is Qt::WindowShortcut.
372
*/
373
void QAction::setShortcutContext(Qt::ShortcutContext context)
374
0
{
375
0
    Q_D(QAction);
376
0
    if (d->shortcutContext == context)
377
0
        return;
378
0
    QAPP_CHECK("setShortcutContext");
379
0
    d->shortcutContext = context;
380
0
    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
381
0
    d->sendDataChanged();
382
0
}
383
384
Qt::ShortcutContext QAction::shortcutContext() const
385
0
{
386
0
    Q_D(const QAction);
387
0
    return d->shortcutContext;
388
0
}
389
390
/*!
391
    \property QAction::autoRepeat
392
    \brief whether the action can auto repeat
393
394
    If true, the action will auto repeat when the keyboard shortcut
395
    combination is held down, provided that keyboard auto repeat is
396
    enabled on the system.
397
    The default value is true.
398
*/
399
void QAction::setAutoRepeat(bool on)
400
0
{
401
0
    Q_D(QAction);
402
0
    if (d->autorepeat == on)
403
0
        return;
404
0
    QAPP_CHECK("setAutoRepeat");
405
0
    d->autorepeat = on;
406
0
    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
407
0
    d->sendDataChanged();
408
0
}
409
410
bool QAction::autoRepeat() const
411
0
{
412
0
    Q_D(const QAction);
413
0
    return d->autorepeat;
414
0
}
415
#endif // QT_CONFIG(shortcut)
416
417
/*!
418
    \property QAction::font
419
    \brief the action's font
420
421
    The font property is used to render the text set on the
422
    QAction. The font can be considered a hint as it will not be
423
    consulted in all cases based upon application and style.
424
425
    By default, this property contains the application's default font.
426
427
    \sa setText()
428
*/
429
void QAction::setFont(const QFont &font)
430
0
{
431
0
    Q_D(QAction);
432
0
    if (d->font == font)
433
0
        return;
434
435
0
    d->fontSet = true;
436
0
    d->font = font;
437
0
    d->sendDataChanged();
438
0
}
439
440
QFont QAction::font() const
441
0
{
442
0
    Q_D(const QAction);
443
0
    return d->font;
444
0
}
445
446
447
/*!
448
    Destroys the object and frees allocated resources.
449
*/
450
QAction::~QAction()
451
0
{
452
0
    Q_D(QAction);
453
454
0
    d->destroy();
455
456
0
    if (d->group)
457
0
        d->group->removeAction(this);
458
0
#if QT_CONFIG(shortcut)
459
0
    if (qApp) {
460
0
        for (int id : std::as_const(d->shortcutIds)) {
461
0
            if (id)
462
0
                QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
463
0
        }
464
0
    }
465
0
#endif
466
0
}
467
468
/*!
469
  Sets this action group to \a group. The action will be automatically
470
  added to the group's list of actions.
471
472
  Actions within the group will be mutually exclusive.
473
474
  \sa QActionGroup, actionGroup()
475
*/
476
void QAction::setActionGroup(QActionGroup *group)
477
0
{
478
0
    Q_D(QAction);
479
0
    if (group == d->group)
480
0
        return;
481
482
0
    if (d->group)
483
0
        d->group->removeAction(this);
484
0
    d->group = group;
485
0
    if (group)
486
0
        group->addAction(this);
487
0
    d->sendDataChanged();
488
0
}
489
490
/*!
491
  Returns the action group for this action. If no action group manages
492
  this action, then \nullptr will be returned.
493
494
  \sa QActionGroup, setActionGroup()
495
*/
496
QActionGroup *QAction::actionGroup() const
497
0
{
498
0
    Q_D(const QAction);
499
0
    return d->group;
500
0
}
501
502
/*!
503
  \since 6.0
504
  Returns a list of objects this action has been added to.
505
506
  \sa QWidget::addAction(), QGraphicsWidget::addAction()
507
*/
508
QList<QObject*> QAction::associatedObjects() const
509
0
{
510
0
    Q_D(const QAction);
511
0
    return d->associatedObjects;
512
0
}
513
514
/*!
515
    \fn QWidget *QAction::parentWidget() const
516
    \deprecated [6.0] Use parent() with qobject_cast() instead.
517
518
    Returns the parent widget.
519
*/
520
521
/*!
522
    \fn QList<QWidget*> QAction::associatedWidgets() const
523
    \deprecated [6.0] Use associatedObjects() with qobject_cast() instead.
524
525
    Returns a list of widgets this action has been added to.
526
527
    \sa QWidget::addAction(), associatedObjects(), associatedGraphicsWidgets()
528
*/
529
530
/*!
531
    \fn QList<QWidget*> QAction::associatedGraphicsWidgets() const
532
    \deprecated [6.0] Use associatedObjects() with qobject_cast() instead.
533
534
    Returns a list of graphics widgets this action has been added to.
535
536
    \sa QGraphicsWidget::addAction(), associatedObjects(), associatedWidgets()
537
*/
538
539
/*!
540
    \property QAction::icon
541
    \brief the action's icon
542
543
    In toolbars, the icon is used as the tool button icon; in menus,
544
    it is displayed to the left of the menu text, as long as
545
    QAction::iconVisibleInMenu returns \c true.
546
547
    There is no default icon.
548
549
    If a null icon (QIcon::isNull()) is passed into this function,
550
    the icon of the action is cleared.
551
*/
552
void QAction::setIcon(const QIcon &icon)
553
0
{
554
0
    Q_D(QAction);
555
0
    d->icon = icon;
556
0
    d->sendDataChanged();
557
0
}
558
559
QIcon QAction::icon() const
560
0
{
561
0
    Q_D(const QAction);
562
0
    return d->icon;
563
0
}
564
565
/*!
566
  If \a b is true then this action will be considered a separator.
567
568
  How a separator is represented depends on the widget it is inserted
569
  into. Under most circumstances the text, submenu, and icon will be
570
  ignored for separator actions.
571
572
  \sa isSeparator()
573
*/
574
void QAction::setSeparator(bool b)
575
0
{
576
0
    Q_D(QAction);
577
0
    if (d->separator == b)
578
0
        return;
579
580
0
    d->separator = b;
581
0
    d->sendDataChanged();
582
0
}
583
584
/*!
585
  Returns \c true if this action is a separator action; otherwise it
586
  returns \c false.
587
588
  \sa setSeparator()
589
*/
590
bool QAction::isSeparator() const
591
0
{
592
0
    Q_D(const QAction);
593
0
    return d->separator;
594
0
}
595
596
/*!
597
    \property QAction::text
598
    \brief the action's descriptive text
599
600
    If the action is added to a menu, the menu option will consist of
601
    the icon (if there is one), the text, and the shortcut (if there
602
    is one). If the text is not explicitly set in the constructor, or
603
    by using setText(), the action's description icon text will be
604
    used as text. There is no default text.
605
606
    Certain UI elements, such as menus or buttons, can use '&' in front of a
607
    character to automatically create a mnemonic (a shortcut) for that
608
    character. For example, "&File" for a menu will create the shortcut
609
    \uicontrol Alt+F, which will open the File menu. "E&xit" will create the
610
    shortcut \uicontrol Alt+X for a button, or in a menu allow navigating to
611
    the menu item by pressing "x". (use '&&' to display an actual ampersand).
612
    The widget might consume and perform an action on a given shortcut.
613
614
    \sa iconText
615
*/
616
void QAction::setText(const QString &text)
617
0
{
618
0
    Q_D(QAction);
619
0
    if (d->text == text)
620
0
        return;
621
622
0
    d->text = text;
623
0
    d->sendDataChanged();
624
0
}
625
626
QString QAction::text() const
627
0
{
628
0
    Q_D(const QAction);
629
0
    QString s = d->text;
630
0
    if (s.isEmpty()) {
631
0
        s = d->iconText;
632
0
        s.replace(u'&', "&&"_L1);
633
0
    }
634
0
    return s;
635
0
}
636
637
/*!
638
    \property QAction::iconText
639
    \brief the action's descriptive icon text
640
641
    If QToolBar::toolButtonStyle is set to a value that permits text to
642
    be displayed, the text defined held in this property appears as a
643
    label in the relevant tool button.
644
645
    It also serves as the default text in menus and tooltips if the action
646
    has not been defined with setText() or setToolTip(), and will
647
    also be used in toolbar buttons if no icon has been defined using setIcon().
648
649
    If the icon text is not explicitly set, the action's normal text will be
650
    used for the icon text.
651
652
    By default, this property contains an empty string.
653
654
    \sa setToolTip(), setStatusTip()
655
*/
656
void QAction::setIconText(const QString &text)
657
0
{
658
0
    Q_D(QAction);
659
0
    if (d->iconText == text)
660
0
        return;
661
662
0
    d->iconText = text;
663
0
    d->sendDataChanged();
664
0
}
665
666
QString QAction::iconText() const
667
0
{
668
0
    Q_D(const QAction);
669
0
    if (d->iconText.isEmpty())
670
0
        return qt_strippedText(d->text);
671
0
    return d->iconText;
672
0
}
673
674
/*!
675
    \property QAction::toolTip
676
    \brief the action's tooltip
677
678
    This text is used for the tooltip. If no tooltip is specified,
679
    the action's text is used.
680
681
    By default, this property contains the action's text.
682
683
    \sa setStatusTip(), setShortcut()
684
*/
685
void QAction::setToolTip(const QString &tooltip)
686
0
{
687
0
    Q_D(QAction);
688
0
    if (d->tooltip == tooltip)
689
0
        return;
690
691
0
    d->tooltip = tooltip;
692
0
    d->sendDataChanged();
693
0
}
694
695
QString QAction::toolTip() const
696
0
{
697
0
    Q_D(const QAction);
698
0
    if (d->tooltip.isEmpty()) {
699
0
        if (!d->text.isEmpty())
700
0
            return qt_strippedText(d->text);
701
0
        return qt_strippedText(d->iconText);
702
0
    }
703
0
    return d->tooltip;
704
0
}
705
706
/*!
707
    \property QAction::statusTip
708
    \brief the action's status tip
709
710
    The status tip is displayed on all status bars provided by the
711
    action's top-level parent widget.
712
713
    By default, this property contains an empty string.
714
715
    \sa setToolTip(), showStatusText()
716
*/
717
void QAction::setStatusTip(const QString &statustip)
718
0
{
719
0
    Q_D(QAction);
720
0
    if (d->statustip == statustip)
721
0
        return;
722
723
0
    d->statustip = statustip;
724
0
    d->sendDataChanged();
725
0
}
726
727
QString QAction::statusTip() const
728
0
{
729
0
    Q_D(const QAction);
730
0
    return d->statustip;
731
0
}
732
733
/*!
734
  Updates the relevant status bar for the UI represented by \a object by sending a
735
  QStatusTipEvent. Returns \c true if an event was sent, otherwise returns \c false.
736
737
  If a null widget is specified, the event is sent to the action's parent.
738
739
  \sa statusTip
740
*/
741
bool QAction::showStatusText(QObject *object)
742
0
{
743
0
    Q_D(QAction);
744
0
    return d->showStatusText(object, statusTip());
745
0
}
746
747
/*!
748
    \property QAction::whatsThis
749
    \brief the action's "What's This?" help text
750
751
    The "What's This?" text is used to provide a brief description of
752
    the action. The text may contain rich text. There is no default
753
    "What's This?" text.
754
755
    \sa QWhatsThis
756
*/
757
void QAction::setWhatsThis(const QString &whatsthis)
758
0
{
759
0
    Q_D(QAction);
760
0
    if (d->whatsthis == whatsthis)
761
0
        return;
762
763
0
    d->whatsthis = whatsthis;
764
0
    d->sendDataChanged();
765
0
}
766
767
QString QAction::whatsThis() const
768
0
{
769
0
    Q_D(const QAction);
770
0
    return d->whatsthis;
771
0
}
772
773
/*!
774
    \enum QAction::Priority
775
776
    This enum defines priorities for actions in user interface.
777
778
    \value LowPriority The action should not be prioritized in
779
    the user interface.
780
781
    \value NormalPriority
782
783
    \value HighPriority The action should be prioritized in
784
    the user interface.
785
786
    \sa priority
787
*/
788
789
790
/*!
791
    \property QAction::priority
792
793
    \brief the actions's priority in the user interface.
794
795
    This property can be set to indicate how the action should be prioritized
796
    in the user interface.
797
798
    For instance, when toolbars have the Qt::ToolButtonTextBesideIcon
799
    mode set, then actions with LowPriority will not show the text
800
    labels.
801
*/
802
void QAction::setPriority(Priority priority)
803
0
{
804
0
    Q_D(QAction);
805
0
    if (d->priority == priority)
806
0
        return;
807
808
0
    d->priority = priority;
809
0
    d->sendDataChanged();
810
0
}
811
812
QAction::Priority QAction::priority() const
813
0
{
814
0
    Q_D(const QAction);
815
0
    return d->priority;
816
0
}
817
818
/*!
819
    \property QAction::checkable
820
    \brief whether the action is a checkable action
821
822
    A checkable action is one which has an on/off state. For example,
823
    in a word processor, a Bold toolbar button may be either on or
824
    off. An action which is not a toggle action is a command action;
825
    a command action is simply executed, e.g. file save.
826
    By default, this property is \c false.
827
828
    In some situations, the state of one toggle action should depend
829
    on the state of others. For example, "Left Align", "Center" and
830
    "Right Align" toggle actions are mutually exclusive. To achieve
831
    exclusive toggling, add the relevant toggle actions to a
832
    QActionGroup with the QActionGroup::exclusive property set to
833
    true.
834
835
    \sa setChecked()
836
*/
837
void QAction::setCheckable(bool b)
838
0
{
839
0
    Q_D(QAction);
840
0
    if (d->checkable == b)
841
0
        return;
842
843
0
    d->checkable = b;
844
0
    QPointer<QAction> guard(this);
845
0
    d->sendDataChanged();
846
0
    if (guard)
847
0
        emit checkableChanged(b);
848
0
    if (guard && d->checked)
849
0
        emit toggled(b);
850
0
}
851
852
bool QAction::isCheckable() const
853
0
{
854
0
    Q_D(const QAction);
855
0
    return d->checkable;
856
0
}
857
858
/*!
859
    \fn void QAction::toggle()
860
861
    This is a convenience function for the \l checked property.
862
    Connect to it to change the checked state to its opposite state.
863
*/
864
void QAction::toggle()
865
0
{
866
0
    Q_D(QAction);
867
0
    setChecked(!d->checked);
868
0
}
869
870
/*!
871
    \property QAction::checked
872
    \brief whether the action is checked.
873
874
    Only checkable actions can be checked.  By default, this is false
875
    (the action is unchecked).
876
877
    \note The notifier signal for this property is toggled(). As toggling
878
    a QAction changes its state, it will also emit a changed() signal.
879
880
    \sa checkable, toggled()
881
*/
882
void QAction::setChecked(bool b)
883
0
{
884
0
    Q_D(QAction);
885
0
    if (d->checked == b)
886
0
        return;
887
888
0
    d->checked = b;
889
0
    if (!d->checkable)
890
0
        return;
891
0
    QPointer<QAction> guard(this);
892
0
    d->sendDataChanged();
893
0
    if (guard)
894
0
        emit toggled(b);
895
0
}
896
897
bool QAction::isChecked() const
898
0
{
899
0
    Q_D(const QAction);
900
0
    return d->checked && d->checkable;
901
0
}
902
903
/*!
904
    \fn void QAction::setDisabled(bool b)
905
906
    This is a convenience function for the \l enabled property, that
907
    is useful for signals--slots connections. If \a b is true the
908
    action is disabled; otherwise it is enabled.
909
*/
910
911
/*!
912
    \property QAction::enabled
913
    \brief whether the action is enabled
914
915
    Disabled actions cannot be chosen by the user. They do not
916
    disappear from menus or toolbars, but they are displayed in a way
917
    which indicates that they are unavailable. For example, they might
918
    be displayed using only shades of gray.
919
920
    \uicontrol{What's This?} help on disabled actions is still available, provided
921
    that the QAction::whatsThis property is set.
922
923
    An action will be disabled when all widgets to which it is added
924
    (with QWidget::addAction()) are disabled or not visible. When an
925
    action is disabled, it is not possible to trigger it through its
926
    shortcut.
927
928
    By default, this property is \c true (actions are enabled).
929
930
    \sa text
931
*/
932
void QAction::setEnabled(bool b)
933
0
{
934
0
    Q_D(QAction);
935
0
    if (d->explicitEnabledValue == b && d->explicitEnabled)
936
0
        return;
937
0
    d->explicitEnabledValue = b;
938
0
    d->explicitEnabled = true;
939
0
    QAPP_CHECK("setEnabled");
940
0
    d->setEnabled(b, false);
941
0
}
942
943
bool QActionPrivate::setEnabled(bool b, bool byGroup)
944
0
{
945
0
    Q_Q(QAction);
946
0
    if (b && !visible)
947
0
        b = false;
948
0
    if (b && !byGroup && (group && !group->isEnabled()))
949
0
        b = false;
950
0
    if (b && byGroup && explicitEnabled)
951
0
        b = explicitEnabledValue;
952
953
0
    if (b == enabled)
954
0
        return false;
955
956
0
    enabled = b;
957
0
#if QT_CONFIG(shortcut)
958
0
    setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap);
959
0
#endif
960
0
    QPointer guard(q);
961
0
    sendDataChanged();
962
0
    if (guard)
963
0
        emit q->enabledChanged(b);
964
0
    return true;
965
0
}
966
967
void QAction::resetEnabled()
968
0
{
969
0
    Q_D(QAction);
970
0
    if (!d->explicitEnabled)
971
0
        return;
972
0
    d->explicitEnabled = false;
973
0
    d->setEnabled(true, false);
974
0
}
975
976
bool QAction::isEnabled() const
977
0
{
978
0
    Q_D(const QAction);
979
0
    return d->enabled;
980
0
}
981
982
/*!
983
    \property QAction::visible
984
    \brief whether the action can be seen (e.g. in menus and toolbars)
985
986
    If \e visible is true the action can be seen (e.g. in menus and
987
    toolbars) and chosen by the user; if \e visible is false the
988
    action cannot be seen or chosen by the user.
989
990
    Actions which are not visible are \e not grayed out; they do not
991
    appear at all.
992
993
    By default, this property is \c true (actions are visible).
994
*/
995
void QAction::setVisible(bool b)
996
0
{
997
0
    Q_D(QAction);
998
0
    if (b != d->forceInvisible)
999
0
        return;
1000
0
    d->forceInvisible = !b;
1001
0
    if (b && d->group && !d->group->isVisible())
1002
0
        return;
1003
0
    d->setVisible(b);
1004
0
}
1005
1006
void QActionPrivate::setVisible(bool b)
1007
0
{
1008
0
    Q_Q(QAction);
1009
0
    if (b == visible)
1010
0
        return;
1011
0
    QAPP_CHECK("setVisible");
1012
0
    visible = b;
1013
0
    bool enable = visible;
1014
0
    if (enable && explicitEnabled)
1015
0
        enable = explicitEnabledValue;
1016
0
    QPointer guard(q);
1017
0
    if (!setEnabled(enable, false))
1018
0
        sendDataChanged();
1019
0
    if (guard)
1020
0
        emit q->visibleChanged();
1021
0
}
1022
1023
bool QAction::isVisible() const
1024
0
{
1025
0
    Q_D(const QAction);
1026
0
    return d->visible;
1027
0
}
1028
1029
/*!
1030
  \reimp
1031
*/
1032
bool QAction::event(QEvent *e)
1033
0
{
1034
0
    Q_D(QAction);
1035
0
    if (e->type() == QEvent::ActionChanged) {
1036
0
        for (auto object : std::as_const(d->associatedObjects))
1037
0
            QCoreApplication::sendEvent(object, e);
1038
0
    }
1039
1040
0
#if QT_CONFIG(shortcut)
1041
0
    if (e->type() == QEvent::Shortcut) {
1042
0
        QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
1043
0
        Q_ASSERT_X(d_func()->shortcutIds.contains(se->shortcutId()),
1044
0
                   "QAction::event",
1045
0
                   "Received shortcut event from incorrect shortcut");
1046
0
        if (se->isAmbiguous())
1047
0
            qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
1048
0
        else
1049
0
            activate(Trigger);
1050
0
        return true;
1051
0
    }
1052
0
#endif // QT_CONFIG(shortcut)
1053
0
    return QObject::event(e);
1054
0
}
1055
1056
/*!
1057
  Returns the user data as set in QAction::setData.
1058
1059
  \sa setData()
1060
*/
1061
QVariant QAction::data() const
1062
0
{
1063
0
    Q_D(const QAction);
1064
0
    return d->userData;
1065
0
}
1066
1067
/*!
1068
  Sets the action's internal data to the given \a data.
1069
1070
  \sa data()
1071
*/
1072
void QAction::setData(const QVariant &data)
1073
0
{
1074
0
    Q_D(QAction);
1075
0
    if (d->userData == data)
1076
0
        return;
1077
0
    d->userData = data;
1078
0
    d->sendDataChanged();
1079
0
}
1080
1081
/*!
1082
  Sends the relevant signals for ActionEvent \a event.
1083
1084
  Action-based widgets use this API to cause the QAction
1085
  to emit signals as well as emitting their own.
1086
*/
1087
void QAction::activate(ActionEvent event)
1088
0
{
1089
0
    Q_D(QAction);
1090
0
    if (event == Trigger) {
1091
        // Ignore even explicit triggers when explicitly disabled
1092
0
        if ((d->explicitEnabled && !d->explicitEnabledValue) || (d->group && !d->group->isEnabled()))
1093
0
            return;
1094
0
        QPointer<QObject> guard = this;
1095
0
        if (d->checkable) {
1096
            // the checked action of an exclusive group may not be unchecked
1097
0
            if (d->checked && (d->group
1098
0
                               && d->group->exclusionPolicy() == QActionGroup::ExclusionPolicy::Exclusive
1099
0
                               && d->group->checkedAction() == this)) {
1100
0
                if (!guard.isNull())
1101
0
                    emit triggered(true);
1102
0
                return;
1103
0
            }
1104
0
            setChecked(!d->checked);
1105
0
        }
1106
0
        if (!guard.isNull())
1107
0
            emit triggered(d->checked);
1108
0
    } else if (event == Hover) {
1109
0
        emit hovered();
1110
0
    }
1111
0
}
1112
1113
/*!
1114
    \fn void QAction::triggered(bool checked)
1115
1116
    This signal is emitted when an action is activated by the user;
1117
    for example, when the user clicks a menu option, toolbar button,
1118
    or presses an action's shortcut key combination, or when trigger()
1119
    was called. Notably, it is \e not emitted when setChecked() or
1120
    toggle() is called.
1121
1122
    If the action is checkable, \a checked is true if the action is
1123
    checked, or false if the action is unchecked.
1124
1125
    \sa activate(), toggled(), checked
1126
*/
1127
1128
/*!
1129
    \fn void QAction::toggled(bool checked)
1130
1131
    This signal is emitted whenever a checkable action changes its
1132
    isChecked() status. This can be the result of a user interaction,
1133
    or because setChecked() was called. As setChecked() changes the
1134
    QAction, it emits changed() in addition to toggled().
1135
1136
    \a checked is true if the action is checked, or false if the
1137
    action is unchecked.
1138
1139
    \sa activate(), triggered(), checked
1140
*/
1141
1142
/*!
1143
    \fn void QAction::hovered()
1144
1145
    This signal is emitted when an action is highlighted by the user;
1146
    for example, when the user pauses with the cursor over a menu option,
1147
    toolbar button, or presses an action's shortcut key combination.
1148
1149
    \sa activate()
1150
*/
1151
1152
/*!
1153
    \fn void QAction::changed()
1154
1155
    This signal is emitted when an action has changed. If you
1156
    are only interested in actions in a given widget, you can
1157
    watch for QWidget::actionEvent() sent with an
1158
    QEvent::ActionChanged.
1159
1160
    \sa QWidget::actionEvent()
1161
*/
1162
1163
/*!
1164
    \enum QAction::ActionEvent
1165
1166
    This enum type is used when calling QAction::activate()
1167
1168
    \value Trigger this will cause the QAction::triggered() signal to be emitted.
1169
1170
    \value Hover this will cause the QAction::hovered() signal to be emitted.
1171
*/
1172
1173
/*!
1174
    \property QAction::menuRole
1175
    \brief the action's menu role
1176
1177
    This indicates what role the action serves in the application menu on
1178
    \macos. By default all actions have the TextHeuristicRole, which means that
1179
    the action is added based on its text (see QMenuBar for more information).
1180
1181
    The menu role can only be changed before the actions are put into the menu
1182
    bar in \macos (usually just before the first application window is
1183
    shown).
1184
*/
1185
void QAction::setMenuRole(MenuRole menuRole)
1186
0
{
1187
0
    Q_D(QAction);
1188
0
    if (d->menuRole == menuRole)
1189
0
        return;
1190
1191
0
    d->menuRole = menuRole;
1192
0
    d->sendDataChanged();
1193
0
}
1194
1195
QAction::MenuRole QAction::menuRole() const
1196
0
{
1197
0
    Q_D(const QAction);
1198
0
    return d->menuRole;
1199
0
}
1200
1201
/*!
1202
    \fn QMenu *QAction::menu() const
1203
1204
    Returns the menu contained by this action.
1205
1206
    In widget applications, actions that contain menus can be used to create menu
1207
    items with submenus, or inserted into toolbars to create buttons with popup menus.
1208
1209
    \sa QMenu::addAction(), QMenu::menuInAction()
1210
*/
1211
QObject* QAction::menuObject() const
1212
0
{
1213
0
    Q_D(const QAction);
1214
0
    return d->menu();
1215
0
}
1216
1217
/*!
1218
    \fn void QAction::setMenu(QMenu *menu)
1219
1220
    Sets the menu contained by this action to the specified \a menu.
1221
*/
1222
void QAction::setMenuObject(QObject *object)
1223
0
{
1224
0
    Q_D(QAction);
1225
0
    d->setMenu(object);
1226
0
}
1227
1228
/*!
1229
    \property QAction::iconVisibleInMenu
1230
    \brief Whether or not an action should show an icon in a menu
1231
1232
    In some applications, it may make sense to have actions with icons in the
1233
    toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it
1234
    is false, it is not shown.
1235
1236
    The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
1237
    is set for the application. Explicitly settings this property overrides
1238
    the presence (or absence) of the attribute.
1239
1240
    For example:
1241
    \snippet code/src_gui_kernel_qaction.cpp 0
1242
1243
    \sa icon, QCoreApplication::setAttribute()
1244
*/
1245
void QAction::setIconVisibleInMenu(bool visible)
1246
0
{
1247
0
    Q_D(QAction);
1248
0
    if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
1249
0
        int oldValue = d->iconVisibleInMenu;
1250
0
        d->iconVisibleInMenu = visible;
1251
        // Only send data changed if we really need to.
1252
0
        if (oldValue != -1
1253
0
            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) {
1254
0
            d->sendDataChanged();
1255
0
        }
1256
0
    }
1257
0
}
1258
1259
bool QAction::isIconVisibleInMenu() const
1260
0
{
1261
0
    Q_D(const QAction);
1262
0
    if (d->iconVisibleInMenu == -1) {
1263
0
        return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus);
1264
0
    }
1265
0
    return d->iconVisibleInMenu;
1266
0
}
1267
1268
/*!
1269
    \property QAction::shortcutVisibleInContextMenu
1270
    \brief Whether or not an action should show a shortcut in a context menu
1271
1272
    In some applications, it may make sense to have actions with shortcuts in
1273
    context menus. If true, the shortcut (if valid) is shown when the action is
1274
    shown via a context menu, when it is false, it is not shown.
1275
1276
    The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
1277
    is set for the application. Explicitly setting this property overrides the attribute.
1278
1279
    \sa shortcut, QCoreApplication::setAttribute()
1280
*/
1281
void QAction::setShortcutVisibleInContextMenu(bool visible)
1282
0
{
1283
0
    Q_D(QAction);
1284
0
    if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) {
1285
0
        int oldValue = d->shortcutVisibleInContextMenu;
1286
0
        d->shortcutVisibleInContextMenu = visible;
1287
        // Only send data changed if we really need to.
1288
0
        if (oldValue != -1
1289
0
            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) {
1290
0
            d->sendDataChanged();
1291
0
        }
1292
0
    }
1293
0
}
1294
1295
bool QAction::isShortcutVisibleInContextMenu() const
1296
0
{
1297
0
    Q_D(const QAction);
1298
0
    if (d->shortcutVisibleInContextMenu == -1)
1299
0
        return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus);
1300
0
    return d->shortcutVisibleInContextMenu;
1301
0
}
1302
1303
#ifndef QT_NO_DEBUG_STREAM
1304
Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAction *action)
1305
0
{
1306
0
    QDebugStateSaver saver(d);
1307
0
    d.nospace();
1308
0
    d << "QAction(" << static_cast<const void *>(action);
1309
0
    if (action) {
1310
0
        d << " text=" << action->text();
1311
0
        if (!action->toolTip().isEmpty())
1312
0
            d << " toolTip=" << action->toolTip();
1313
0
        if (action->isCheckable())
1314
0
            d << " checked=" << action->isChecked();
1315
0
#if QT_CONFIG(shortcut)
1316
0
        if (!action->shortcuts().isEmpty())
1317
0
            d << " shortcuts=" << action->shortcuts();
1318
0
#endif
1319
0
        d << " menuRole=";
1320
0
        QtDebugUtils::formatQEnum(d, action->menuRole());
1321
0
        d << " enabled=" << action->isEnabled();
1322
0
        d << " visible=" << action->isVisible();
1323
0
    }
1324
0
    d << ')';
1325
0
    return d;
1326
0
}
1327
#endif // QT_NO_DEBUG_STREAM
1328
1329
QT_END_NAMESPACE
1330
1331
#undef QAPP_CHECK
1332
1333
#include "moc_qaction.cpp"