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 
62 QT_BEGIN_NAMESPACE
63 
64 /*
65   internal: guesses a descriptive text from a text suited for a menu entry
66  */
qt_strippedText(QString s)67 static 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 
QActionPrivate()78 QActionPrivate::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 
88 QActionPrivate::~QActionPrivate() = default;
89 
showStatusText(QWidget * widget,const QString & str)90 bool 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 
sendDataChanged()105 void 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)
redoGrab(QShortcutMap & map)125 void 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 
redoGrabAlternate(QShortcutMap & map)139 void 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 
setShortcutEnabled(bool enable,QShortcutMap & map)170 void 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 */
QAction(QObject * parent)277 QAction::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 */
QAction(const QString & text,QObject * parent)296 QAction::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 */
QAction(const QIcon & icon,const QString & text,QObject * parent)315 QAction::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 */
QAction(QActionPrivate & dd,QObject * parent)325 QAction::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 */
parentWidget() const337 QWidget *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 */
associatedWidgets() const351 QList<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 */
associatedGraphicsWidgets() const364 QList<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 */
setShortcut(const QKeySequence & shortcut)379 void 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 */
setShortcuts(const QList<QKeySequence> & shortcuts)400 void 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 */
setShortcuts(QKeySequence::StandardKey key)432 void 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 */
shortcut() const443 QKeySequence 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 */
shortcuts() const457 QList<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 */
setShortcutContext(Qt::ShortcutContext context)475 void 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 
shortcutContext() const487 Qt::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 */
setAutoRepeat(bool on)503 void 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 
autoRepeat() const515 bool 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 */
setFont(const QFont & font)534 void 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 
font() const545 QFont 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 */
~QAction()555 QAction::~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 */
setActionGroup(QActionGroup * group)589 void 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 */
actionGroup() const609 QActionGroup *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 */
setIcon(const QIcon & icon)627 void QAction::setIcon(const QIcon &icon)
628 {
629     Q_D(QAction);
630     d->icon = icon;
631     d->sendDataChanged();
632 }
633 
icon() const634 QIcon 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 */
menu() const648 QMenu *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 */
setMenu(QMenu * menu)657 void QAction::setMenu(QMenu *menu)
658 {
659     Q_D(QAction);
660     if (d->menu)
661         d->menu->d_func()->setOverrideMenuAction(nullptr); //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 */
setSeparator(bool b)678 void 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 */
isSeparator() const694 bool 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 */
setText(const QString & text)712 void 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 
text() const722 QString 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 */
setIconText(const QString & text)756 void 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 
iconText() const766 QString 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 */
setToolTip(const QString & tooltip)785 void 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 
toolTip() const795 QString 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 */
setStatusTip(const QString & statustip)817 void 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 
statusTip() const827 QString 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 */
setWhatsThis(const QString & whatsthis)843 void 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 
whatsThis() const853 QString 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 */
setPriority(Priority priority)890 void 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 
priority() const900 QAction::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 */
setCheckable(bool b)925 void 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 
isCheckable() const936 bool 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 */
toggle()948 void 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 */
setChecked(bool b)966 void 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 
isChecked() const979 bool 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 */
setEnabled(bool b)1014 void 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 
isEnabled() const1030 bool 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 */
setVisible(bool b)1049 void 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 
isVisible() const1065 bool QAction::isVisible() const
1066 {
1067     Q_D(const QAction);
1068     return d->visible;
1069 }
1070 
1071 /*!
1072   \reimp
1073 */
1074 bool
event(QEvent * e)1075 QAction::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 */
1098 QVariant
data() const1099 QAction::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 */
1112 void
setData(const QVariant & data)1113 QAction::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 */
1132 bool
showStatusText(QWidget * widget)1133 QAction::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 */
activate(ActionEvent event)1144 void 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 */
setMenuRole(MenuRole menuRole)1240 void 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 
menuRole() const1250 QAction::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 */
setIconVisibleInMenu(bool visible)1274 void 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 
isIconVisibleInMenu() const1288 bool 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 */
setShortcutVisibleInContextMenu(bool visible)1312 void 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 
isShortcutVisibleInContextMenu() const1326 bool 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
operator <<(QDebug d,const QAction * action)1337 Q_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 
1363 QT_END_NAMESPACE
1364 
1365 #include "moc_qaction.cpp"
1366 
1367 #endif // QT_NO_ACTION
1368