File indexing completed on 2024-03-24 15:27:36

0001 /* This file is part of the KDE libraries
0002     Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
0003               (C) 1999 Simon Hausmann <hausmann@kde.org>
0004               (C) 2000 Nicolas Hadacek <haadcek@kde.org>
0005               (C) 2000 Kurt Granroth <granroth@kde.org>
0006               (C) 2000 Michael Koch <koch@kde.org>
0007               (C) 2001 Holger Freyther <freyther@kde.org>
0008               (C) 2002 Ellis Whitehead <ellis@kde.org>
0009               (C) 2005-2006 Hamish Rodda <rodda@kde.org>
0010 
0011     This library is free software; you can redistribute it and/or
0012     modify it under the terms of the GNU Library General Public
0013     License version 2 as published by the Free Software Foundation.
0014 
0015     This library is distributed in the hope that it will be useful,
0016     but WITHOUT ANY WARRANTY; without even the implied warranty of
0017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018     Library General Public License for more details.
0019 
0020     You should have received a copy of the GNU Library General Public License
0021     along with this library; see the file COPYING.LIB.  If not, write to
0022     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023     Boston, MA 02110-1301, USA.
0024 */
0025 
0026 #ifndef KACTION_H
0027 #define KACTION_H
0028 
0029 #include <kdelibs4support_export.h>
0030 #include <kauth/action.h>
0031 
0032 #include <QWidgetAction>
0033 
0034 class KShapeGesture;
0035 class KRockerGesture;
0036 class KShortcut;
0037 
0038 //TODO Reduce the word count. This is not very focused and takes too long to read.
0039 //Keep in mind that QAction also has documentation that we don't need to repeat here.
0040 /**
0041  * @short Class to encapsulate user-driven action or event
0042  * @extends QAction
0043  *
0044  * The KAction class (and derived and super classes) extends QAction,
0045  * which provides a way to easily encapsulate a "real" user-selected
0046  * action or event in your program.
0047  *
0048  * For instance, a user may want to @p paste the contents of
0049  * the clipboard, @p scroll @p down a document, or @p quit the
0050  * application.  These are all \b actions -- events that the
0051  * user causes to happen.  The KAction class allows the developer to
0052  * deal with these actions in an easy and intuitive manner, and conforms
0053  * to KDE's extended functionality requirements - including supporting
0054  * multiple user-configurable shortcuts, and KDE named icons.  Actions
0055  * also improve accessibility.
0056  *
0057  * Specifically, QAction (and thus KAction) encapsulates the various attributes
0058  * of an event/action.  For instance, an action might have an icon()
0059  * that provides a visual representation (a clipboard for a "paste" action or
0060  * scissors for a "cut" action).  The action should also be described by some text().
0061  * It will certainly be connected to a method that actually @p executes the action!
0062  * All these attributes are contained within the action object.
0063  *
0064  * The advantage of dealing with actions is that you can manipulate
0065  * the Action without regard to the GUI representation of it.  For
0066  * instance, in the "normal" way of dealing with actions like "cut",
0067  * you would manually insert a item for Cut into a menu and a button
0068  * into a toolbar.  If you want to disable the cut action for a moment
0069  * (maybe nothing is selected), you would have to hunt down the pointer
0070  * to the menu item and the toolbar button and disable both
0071  * individually.  Setting the menu item and toolbar item up uses very
0072  * similar code - but has to be done twice!
0073  *
0074  * With the action concept, you simply add the action to whatever
0075  * GUI element you want.  The KAction class will then take care of
0076  * correctly defining the menu item (with icons, accelerators, text,
0077  * etc), toolbar button, or other.  From then on, if you
0078  * manipulate the action at all, the effect will propagate through all
0079  * GUI representations of it.  Back to the "cut" example: if you want
0080  * to disable the Cut Action, you would simply call
0081  * 'cutAction->setEnabled(false)' and both the menuitem and button would
0082  * instantly be disabled!
0083  *
0084  * This is the biggest advantage to the action concept -- there is a
0085  * one-to-one relationship between the "real" action and @p all
0086  * GUI representations of it.
0087  *
0088  * KAction emits the hovered() signal on mouseover, and the triggered(bool checked)
0089  * signal on activation of a corresponding GUI element ( menu item, toolbar button, etc. )
0090  *
0091  * If you are in the situation of wanting to map the triggered()
0092  * signal of multiple action objects to one slot, with a special
0093  * argument bound to each action, you have several options:
0094  *
0095  * Using QActionGroup:
0096  * \li Create a QActionGroup and assign it to each of the actions with setActionGroup(), then
0097  * \li Connect the QActionGroup::triggered(QAction*) signal to your slot.
0098  *
0099  * Using QSignalMapper:
0100  * \code
0101  * QSignalMapper *desktopNumberMapper = new QSignalMapper( this );
0102  * connect( desktopNumberMapper, SIGNAL( mapped( int ) ),
0103  *          this, SLOT( moveWindowToDesktop( int ) ) );
0104  *
0105  * for ( uint i = 0; i < numberOfDesktops; ++i ) {
0106  *     KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... );
0107  *     connect( desktopAction, SIGNAL( triggered(bool) ), desktopNumberMapper, SLOT( map() ) );
0108  *     desktopNumberMapper->setMapping( desktopAction, i );
0109  * }
0110  * \endcode
0111  *
0112  * \section kaction_general General Usage
0113  *
0114  * The steps to using actions are roughly as follows:
0115  *
0116  * @li Decide which attributes you want to associate with a given
0117  *     action (icons, text, keyboard shortcut, etc)
0118  * @li Create the action using KAction (or derived or super class).
0119  * @li Add the action into whatever GUI element you want.  Typically,
0120  *      this will be a menu or toolbar.
0121  *
0122  * \section kaction_general The kinds of shortcuts
0123  *
0124  * Local shortcuts are active if their context has the focus, global shortcus
0125  * are active even if the program does not have the focus. If a global
0126  * shortcut and a local shortcut are ambiguous the global shortcut wins.
0127  *
0128  * @li Active shortcuts trigger a KAction if activated.
0129  * @li Default shortcuts are what the active shortcuts revert to if the user chooses
0130  * to reset shortcuts to default.
0131  *
0132  * \section kaction_example Detailed Example
0133  *
0134  * Here is an example of enabling a "New [document]" action
0135  * \code
0136  * KAction *newAct = actionCollection()->addAction(
0137  *              KStandardAction::New,   //< see KStandardAction
0138  *              this,                   //< Receiver
0139  *              SLOT(fileNew())  );     //< SLOT
0140  * \endcode
0141  *
0142  * This section creates our action. Text, Icon and Shortcut will be set from
0143  * KStandardAction. KStandardAction ensures your application complies to the
0144  * platform standards. When triggered the \c fileNew() slot will be called.
0145  *
0146  * @see KStandardAction for more information.
0147  *
0148  * If you want to create your own actions use
0149  * \code
0150  * KAction *newAct = actionCollection()->addAction("quick-connect");
0151  * newAct->setText(i18n("Quick Connect"))
0152  * newAct->setIcon(QIcon::fromTheme("quick-connect"));
0153  * newAct->setShortcut(Qt::Key_F6);
0154  * connect(newAct, SIGNAL(triggered()), this, SLOT(quickConnect()));
0155  * \endcode
0156  *
0157  * This section creates our action. It displays the text "Quick Connect",
0158  * uses the Icon "quick-connect" and pressing \c F6 will trigger it. When
0159  * invoked, the slot quickConnect() is called.
0160  *
0161  * \code
0162  * QMenu *file = new QMenu;
0163  * file->addAction(newAct);
0164  * \endcode
0165  * That just inserted the action into the File menu.  The point is, it's not
0166  * important in which menu it is: all manipulation of the item is
0167  * done through the newAct object.
0168  *
0169  * \code
0170  * toolBar()->addAction(newAct);
0171  * \endcode
0172  * And this added the action into the main toolbar as a button.
0173  *
0174  * That's it!
0175  *
0176  * If you want to disable that action sometime later, you can do so
0177  * with
0178  * \code
0179  * newAct->setEnabled(false)
0180  * \endcode
0181  * and both the menuitem in File and the toolbar button will instantly
0182  * be disabled.
0183  *
0184  * Unlike with previous versions of KDE, the action can simply be deleted
0185  * when you have finished with it - the destructor takes care of all
0186  * of the cleanup.
0187  *
0188  * \warning calling QAction::setShortcut() on a KAction may lead to unexpected
0189  * behavior. There is nothing we can do about it because QAction::setShortcut()
0190  * is not virtual.
0191  *
0192  * \note if you are using a "standard" action like "new", "paste",
0193  * "quit", or any other action described in the KDE UI Standards,
0194  * please use the methods in the KStandardAction class rather than
0195  * defining your own.
0196  *
0197  * \section Using QActions
0198  *
0199  * Mixing QActions and KActions in an application is not a
0200  * good idea. KShortcutsEditor doesn't handle QActions at all.
0201  *
0202  * \section kaction_xmlgui Usage Within the XML Framework
0203  *
0204  * If you are using KAction within the context of the XML menu and
0205  * toolbar building framework, you do not ever
0206  * have to add your actions to containers manually.  The framework
0207  * does that for you.
0208  *
0209  * @see KStandardAction
0210  */
0211 class KDELIBS4SUPPORT_DEPRECATED_EXPORT KAction : public QWidgetAction
0212 {
0213     Q_OBJECT
0214 
0215     Q_PROPERTY(KShortcut shortcut READ shortcut WRITE setShortcut)
0216     Q_PROPERTY(bool shortcutConfigurable READ isShortcutConfigurable WRITE setShortcutConfigurable)
0217     Q_PROPERTY(KShortcut globalShortcut READ globalShortcut WRITE setGlobalShortcut)
0218 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
0219     Q_PROPERTY(bool globalShortcutAllowed READ globalShortcutAllowed WRITE setGlobalShortcutAllowed)
0220 #endif
0221     Q_PROPERTY(bool globalShortcutEnabled READ isGlobalShortcutEnabled)
0222     Q_FLAGS(ShortcutType)
0223 
0224 public:
0225     /**
0226      * An enumeration about the two types of shortcuts in a KAction
0227      */
0228     enum ShortcutType {
0229         /// The shortcut will immediately become active but may be reset to "default".
0230         ActiveShortcut = 0x1,
0231         /// The shortcut is a default shortcut - it becomes active when somebody decides to
0232         /// reset shortcuts to default.
0233         DefaultShortcut = 0x2
0234     };
0235     Q_DECLARE_FLAGS(ShortcutTypes, ShortcutType)
0236 
0237     /**
0238      * An enum about global shortcut setter semantics
0239      */
0240     //This enum will be ORed with ShortcutType in calls to KGlobalAccel, so it must not contain
0241     //any value equal to a value in ShortcutType.
0242     enum GlobalShortcutLoading {
0243         /// Look up the action in global settings (using its main component's name and text())
0244         /// and set the shortcut as saved there.
0245         /// @see setGlobalShortcut()
0246         Autoloading = 0x0,
0247         /// Prevent autoloading of saved global shortcut for action
0248         NoAutoloading = 0x4
0249     };
0250     /**
0251      * Constructs an action.
0252      */
0253     KDELIBS4SUPPORT_DEPRECATED explicit KAction(QObject *parent);
0254 
0255     /**
0256      * Constructs an action with the specified parent and visible text.
0257      *
0258      * @param text The visible text for this action.
0259      * @param parent The parent for this action.
0260      */
0261     KAction(const QString &text, QObject *parent);
0262 
0263     /**
0264      * Constructs an action with text and icon; a shortcut may be specified by
0265      * the ampersand character (e.g. \"&amp;Option\" creates a shortcut with key \e O )
0266      *
0267      * This is the other common KAction constructor used.  Use it when you
0268      * \e do have a corresponding icon.
0269      *
0270      * @param icon The icon to display.
0271      * @param text The text that will be displayed.
0272      * @param parent The parent for this action.
0273      */
0274     KAction(const QIcon &icon, const QString &text, QObject *parent);
0275 
0276     /**
0277      * Standard destructor
0278      */
0279     ~KAction() override;
0280 
0281     /**
0282      * Sets the help text for the action.
0283      * This help text will be set for all help mechanisms:
0284      *  - the status-bar help text
0285      *  - the tooltip (for toolbar buttons)
0286      *  - the "WhatsThis" help text (unless one was already set)
0287      *
0288      * This is more convenient than calling all three methods with the
0289      * same text, and this level of abstraction can allow to change
0290      * the default implementation of help one day more easily.
0291      * Of course you can also call setStatusTip, setToolTip and setWhatsThis
0292      * separately for more flexibility.
0293      *
0294      * This method is also the easiest way to port from KDE3's KAction::setToolTip.
0295      *
0296      * @since 4.3
0297      */
0298     void setHelpText(const QString &text);
0299 
0300     /**
0301      * Get the shortcut for this action.
0302      *
0303      * This is preferred over QAction::shortcut(), as it allows for multiple shortcuts
0304      * per action. The first and second shortcut as reported by shortcuts() will be the
0305      * primary and alternate shortcut of the shortcut returned.
0306      *
0307      * \param types the type of shortcut to return. Should both be specified, only the
0308      *             active shortcut will be returned. Defaults to the active shortcut, if one exists.
0309      * \sa shortcuts()
0310      */
0311     KShortcut shortcut(ShortcutTypes types = ActiveShortcut) const;
0312 
0313     /**
0314      * Set the shortcut for this action.
0315      *
0316      * This is preferred over QAction::setShortcut(), as it allows for multiple shortcuts
0317      * per action.
0318      *
0319      * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
0320      * \param type type of shortcut to be set: active shortcut,
0321      *  default shortcut, or both (the default).
0322      */
0323     void setShortcut(const KShortcut &shortcut, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
0324 
0325     /**
0326      * \overload void setShortcut(const KShortcut& shortcut)
0327      *
0328      * Set the primary shortcut only for this action.
0329      *
0330      * This function is there to explicitly override QAction::setShortcut(const QKeySequence&).
0331      * QAction::setShortcut() will bypass everything in KAction and may lead to unexpected behavior.
0332      *
0333      * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
0334      * \param type type of shortcut to be set: active shortcut,
0335      *  default shortcut, or both (default argument value).
0336      */
0337     void setShortcut(const QKeySequence &shortcut, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
0338 
0339     /**
0340      * \overload void setShortcuts(const QList\<QKeySequence\>& shortcuts).
0341      *
0342      * Set the shortcuts for this action.
0343      *
0344      * This function is there to explicitly override QAction::setShortcut(const QList\<QKeySequence\>&).
0345      * QAction::setShortcuts() will bypass everything in KAction and may lead to unexpected behavior.
0346      *
0347      * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
0348      * \param type type of shortcut to be set: active shortcut,
0349      *  default shortcut, or both (default argument value).
0350      */
0351     void setShortcuts(const QList<QKeySequence> &shortcuts, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
0352 
0353     /**
0354      * Returns true if this action's shortcut is configurable.
0355      */
0356     bool isShortcutConfigurable() const;
0357 
0358     /**
0359      * Indicate whether the user may configure the action's shortcut.
0360      *
0361      * \param configurable set to \e true if this shortcut may be configured by the user, otherwise \e false.
0362      */
0363     void setShortcutConfigurable(bool configurable);
0364 
0365     /**
0366      * Get the global shortcut for this action, if one exists. Global shortcuts
0367      * allow your actions to respond to accellerators independently of the focused window.
0368      * Unlike regular shortcuts, the application's window does not need focus
0369      * for them to be activated.
0370      *
0371      * \param type the type of shortcut to be returned. Should both be specified, only the
0372      *             active shortcut will be returned.  Defaults to the active shortcut,
0373      *             if one exists.
0374      *
0375      * \sa KGlobalAccel
0376      * \sa setGlobalShortcut()
0377      */
0378     KShortcut globalShortcut(ShortcutTypes type = ActiveShortcut) const;
0379 
0380     /**
0381      * Assign a global shortcut for this action. Global shortcuts
0382      * allow an action to respond to key shortcuts independently of the focused window,
0383      * i.e. the action will trigger if the keys were pressed no matter where in the X session.
0384      *
0385      * The action must have a per main component unique
0386      * objectName() to enable cross-application bookeeping. If the objectName() is empty this method will
0387      * do nothing, otherwise the isGlobalShortcutEnabled() property will be set to true and the
0388      * shortcut will be enabled.
0389      * It is mandatory that the objectName() doesn't change once isGlobalshortcutEnabled()
0390      * has become true.
0391      *
0392      * \note KActionCollection::insert(name, action) will set action's objectName to name so you often
0393      * don't have to set an objectName explicitly.
0394      *
0395      * When an action, identified by main component name and objectName(), is assigned
0396      * a global shortcut for the first time on a KDE installation the assignment will
0397      * be saved. The shortcut will then be restored every time setGlobalShortcut() is
0398      * called with @p loading == Autoloading.
0399      *
0400      * If you actually want to change the global shortcut you have to set
0401      * @p loading to NoAutoloading. The new shortcut will be automatically saved again.
0402      *
0403      * \param shortcut global shortcut(s) to assign. Will be ignored unless \p loading is set to NoAutoloading or this is the first time ever you call this method (see above).
0404      * \param type the type of shortcut to be set, whether the active shortcut, the default shortcut,
0405      *             or both (the default).
0406      * \param loading if Autoloading, assign the global shortcut this action has previously had if any.
0407      *                   That way user preferences and changes made to avoid clashes will be conserved.
0408      *                if NoAutoloading the given shortcut will be assigned without looking up old values.
0409      *                   You should only do this if the user wants to change the shortcut or if you have
0410      *                   another very good reason. Key combinations that clash with other shortcuts will be
0411      *                   dropped.
0412      *
0413      * \note the default shortcut will never be influenced by autoloading - it will be set as given.
0414      * \sa globalShortcut()
0415      */
0416     void setGlobalShortcut(const KShortcut &shortcut, ShortcutTypes type =
0417                                ShortcutTypes(ActiveShortcut | DefaultShortcut),
0418                            GlobalShortcutLoading loading = Autoloading);
0419 
0420     /**
0421      * Returns true if this action is permitted to have a global shortcut.
0422      * Defaults to false.
0423      * Use isGlobalShortcutEnabled() instead.
0424      */
0425 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
0426     KDELIBS4SUPPORT_DEPRECATED bool globalShortcutAllowed() const;
0427 #endif
0428 
0429     /**
0430      * Indicate whether the programmer and/or user may define a global shortcut for this action.
0431      * Defaults to false. Note that calling setGlobalShortcut() turns this on automatically.
0432      *
0433      * \param allowed set to \e true if this action may have a global shortcut, otherwise \e false.
0434      * \param loading if Autoloading, assign to this action the global shortcut it has previously had
0435      *                if any.
0436      */
0437 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
0438     KDELIBS4SUPPORT_DEPRECATED void setGlobalShortcutAllowed(bool allowed, GlobalShortcutLoading loading = Autoloading);
0439 #endif
0440 
0441     /**
0442      * Returns true if this action is enabled to have a global shortcut.
0443      * This will be respected by \class KGlobalShortcutsEditor.
0444      * Defaults to false.
0445      */
0446     bool isGlobalShortcutEnabled() const;
0447 
0448     /**
0449      * Sets the globalShortcutEnabled property to false and sets the global shortcut to an
0450      * empty shortcut.
0451      * This will also wipe out knowlegde about the existence of this action's global shortcut
0452      * so it will not be considered anymore for shortcut conflict resolution. It will also not be
0453      * visible anymore in the shortcuts KControl module.
0454      * This method should not be used unless these effects are explicitly desired.
0455      * @since 4.1
0456      */
0457     void forgetGlobalShortcut();
0458 
0459     KShapeGesture shapeGesture(ShortcutTypes type = ActiveShortcut) const;
0460     KRockerGesture rockerGesture(ShortcutTypes type = ActiveShortcut) const;
0461 
0462     void setShapeGesture(const KShapeGesture &gest, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
0463     void setRockerGesture(const KRockerGesture &gest, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
0464 
0465     /**
0466      * Returns the action object associated with this action, or 0 if it does not have one
0467      *
0468      * @returns the KAuth::Action associated with this action.
0469      */
0470     KAuth::Action authAction() const;
0471 
0472     /**
0473      * Sets the action object associated with this action
0474      *
0475      * By setting a KAuth::Action, this action will become associated with it, and
0476      * whenever it gets clicked, it will trigger the authorization and execution process
0477      * for the action. The signal activated will also be emitted whenever the action gets
0478      * clicked and the action gets authorized. Pass 0 to this function to disassociate the action
0479      *
0480      * @param action the KAuth::Action to associate with this action.
0481      */
0482     void setAuthAction(const KAuth::Action &action);
0483 
0484     /**
0485     * Sets the action object associated with this action
0486     *
0487     * Overloaded member to allow creating the action by name
0488     *
0489     * @param actionName the name of the action to associate
0490     */
0491     void setAuthAction(const QString &actionName);
0492 
0493 Q_SIGNALS:
0494 #ifdef KDE3_SUPPORT
0495     /**
0496      * Emitted when this action is activated
0497      *
0498      * \deprecated use triggered(bool checked) instead.
0499      */
0500     QT_MOC_COMPAT void activated();
0501 #endif
0502 
0503     /**
0504      * Emitted when the action is triggered. Also provides the state of the
0505      * keyboard modifiers and mouse buttons at the time.
0506      * @deprecated since 5.0, use triggered() signal from QAction and check for
0507      * QApplication::mouseButtons() and QApplication::keyboardModifiers() in the slot.
0508      */
0509     void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
0510 
0511     /**
0512      * Signal emitted when the action is triggered and authorized
0513      *
0514      * If the action needs authorization, when the user triggers the action,
0515      * the authorization process automatically begins.
0516      * If it succeeds, this signal is emitted. The KAuth::Action object is provided for convenience
0517      * if you have multiple KAuthorizedAction objects, but of course it's always the same set with
0518      * setAuthAction().
0519      *
0520      * WARNING: If your action needs authorization you should connect eventual slots processing
0521      * stuff to this signal, and NOT triggered. Triggered will be emitted even if the user has not
0522      * been authorized
0523      *
0524      * @param action The object set with setAuthAction()
0525      */
0526     void authorized(const KAuth::Action &action);
0527 
0528     /**
0529      * Emitted when the global shortcut is changed. A global shortcut is
0530      * subject to be changed by the global shortcuts kcm.
0531      * @deprecated use KGlobalAccel::globalShortcutChanged instead
0532      */
0533     void globalShortcutChanged(const QKeySequence &);
0534 
0535 private:
0536     friend class KGlobalAccelPrivate; // Needs access to the component
0537     friend class KActionCollectionPrivate; // Needs access to the component
0538     friend class KShortcutsEditorDelegate; // Needs access to the component
0539     Q_PRIVATE_SLOT(d, void slotTriggered())
0540     Q_PRIVATE_SLOT(d, void _k_emitActionGlobalShortcutChanged(QAction *, const QKeySequence &))
0541     class KActionPrivate *const d;
0542     friend class KActionPrivate;
0543     friend class KGlobalShortcutTest;
0544 };
0545 
0546 Q_DECLARE_OPERATORS_FOR_FLAGS(KAction::ShortcutTypes)
0547 
0548 #endif