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