1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
3 (C) 1999 Simon Hausmann <hausmann@kde.org>
4 (C) 2000 Nicolas Hadacek <haadcek@kde.org>
5 (C) 2000 Kurt Granroth <granroth@kde.org>
6 (C) 2000 Michael Koch <koch@kde.org>
7 (C) 2001 Holger Freyther <freyther@kde.org>
8 (C) 2002 Ellis Whitehead <ellis@kde.org>
9 (C) 2005-2006 Hamish Rodda <rodda@kde.org>
10
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License version 2 as published by the Free Software Foundation.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA.
24*/
25
26#ifndef KACTION_H
27#define KACTION_H
28
29#include <kdeui_export.h>
30#include <kguiitem.h>
31#include <kshortcut.h>
32
33#include <QtGui/QWidgetAction>
34
35class KIcon;
36class KShapeGesture;
37class KRockerGesture;
38
39namespace KAuth {
40 class Action;
41}
42
43//TODO Reduce the word count. This is not very focused and takes too long to read.
44//Keep in mind that QAction also has documentation that we don't need to repeat here.
45/**
46 * @short Class to encapsulate user-driven action or event
47 * @extends QAction
48 *
49 * The KAction class (and derived and super classes) extends QAction,
50 * which provides a way to easily encapsulate a "real" user-selected
51 * action or event in your program.
52 *
53 * For instance, a user may want to @p paste the contents of
54 * the clipboard, @p scroll @p down a document, or @p quit the
55 * application. These are all \b actions -- events that the
56 * user causes to happen. The KAction class allows the developer to
57 * deal with these actions in an easy and intuitive manner, and conforms
58 * to KDE's extended functionality requirements - including supporting
59 * multiple user-configurable shortcuts, and KDE named icons. Actions
60 * also improve accessibility.
61 *
62 * Specifically, QAction (and thus KAction) encapsulates the various attributes
63 * of an event/action. For instance, an action might have an icon()
64 * that provides a visual representation (a clipboard for a "paste" action or
65 * scissors for a "cut" action). The action should also be described by some text().
66 * It will certainly be connected to a method that actually @p executes the action!
67 * All these attributes are contained within the action object.
68 *
69 * The advantage of dealing with actions is that you can manipulate
70 * the Action without regard to the GUI representation of it. For
71 * instance, in the "normal" way of dealing with actions like "cut",
72 * you would manually insert a item for Cut into a menu and a button
73 * into a toolbar. If you want to disable the cut action for a moment
74 * (maybe nothing is selected), you would have to hunt down the pointer
75 * to the menu item and the toolbar button and disable both
76 * individually. Setting the menu item and toolbar item up uses very
77 * similar code - but has to be done twice!
78 *
79 * With the action concept, you simply add the action to whatever
80 * GUI element you want. The KAction class will then take care of
81 * correctly defining the menu item (with icons, accelerators, text,
82 * etc), toolbar button, or other. From then on, if you
83 * manipulate the action at all, the effect will propagate through all
84 * GUI representations of it. Back to the "cut" example: if you want
85 * to disable the Cut Action, you would simply call
86 * 'cutAction->setEnabled(false)' and both the menuitem and button would
87 * instantly be disabled!
88 *
89 * This is the biggest advantage to the action concept -- there is a
90 * one-to-one relationship between the "real" action and @p all
91 * GUI representations of it.
92 *
93 * KAction emits the hovered() signal on mouseover, and the triggered(bool checked)
94 * signal on activation of a corresponding GUI element ( menu item, toolbar button, etc. )
95 *
96 * If you are in the situation of wanting to map the triggered()
97 * signal of multiple action objects to one slot, with a special
98 * argument bound to each action, you have several options:
99 *
100 * Using QActionGroup:
101 * \li Create a QActionGroup and assign it to each of the actions with setActionGroup(), then
102 * \li Connect the QActionGroup::triggered(QAction*) signal to your slot.
103 *
104 * Using QSignalMapper:
105 * \code
106 * QSignalMapper *desktopNumberMapper = new QSignalMapper( this );
107 * connect( desktopNumberMapper, SIGNAL( mapped( int ) ),
108 * this, SLOT( moveWindowToDesktop( int ) ) );
109 *
110 * for ( uint i = 0; i < numberOfDesktops; ++i ) {
111 * KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... );
112 * connect( desktopAction, SIGNAL( triggered(bool) ), desktopNumberMapper, SLOT( map() ) );
113 * desktopNumberMapper->setMapping( desktopAction, i );
114 * }
115 * \endcode
116 *
117 * \section kaction_general General Usage
118 *
119 * The steps to using actions are roughly as follows:
120 *
121 * @li Decide which attributes you want to associate with a given
122 * action (icons, text, keyboard shortcut, etc)
123 * @li Create the action using KAction (or derived or super class).
124 * @li Add the action into whatever GUI element you want. Typically,
125 * this will be a menu or toolbar.
126 *
127 * \section kaction_general The kinds of shortcuts
128 *
129 * Local shortcuts are active if their context has the focus, global shortcus
130 * are active even if the program does not have the focus. If a global
131 * shortcut and a local shortcut are ambiguous the global shortcut wins.
132 *
133 * @li Active shortcuts trigger a KAction if activated.
134 * @li Default shortcuts are what the active shortcuts revert to if the user chooses
135 * to reset shortcuts to default.
136 *
137 * \section kaction_example Detailed Example
138 *
139 * Here is an example of enabling a "New [document]" action
140 * \code
141 * KAction *newAct = actionCollection()->addAction(
142 * KStandardAction::New, //< see KStandardAction
143 * this, //< Receiver
144 * SLOT(fileNew()) ); //< SLOT
145 * \endcode
146 *
147 * This section creates our action. Text, Icon and Shortcut will be set from
148 * KStandardAction. KStandardAction ensures your application complies to the
149 * platform standards. When triggered the \c fileNew() slot will be called.
150 *
151 * @see KStandardAction for more information.
152 *
153 * If you want to create your own actions use
154 * \code
155 * KAction *newAct = actionCollection()->addAction("quick-connect");
156 * newAct->setText(i18n("Quick Connect"))
157 * newAct->setIcon(KIcon("quick-connect"));
158 * newAct->setShortcut(Qt::Key_F6);
159 * connect(newAct, SIGNAL(triggered()), this, SLOT(quickConnect()));
160 * \endcode
161 *
162 * This section creates our action. It displays the text "Quick Connect",
163 * uses the Icon "quick-connect" and pressing \c F6 will trigger it. When
164 * invoked, the slot quickConnect() is called.
165 *
166 * \code
167 * QMenu *file = new QMenu;
168 * file->addAction(newAct);
169 * \endcode
170 * That just inserted the action into the File menu. The point is, it's not
171 * important in which menu it is: all manipulation of the item is
172 * done through the newAct object.
173 *
174 * \code
175 * toolBar()->addAction(newAct);
176 * \endcode
177 * And this added the action into the main toolbar as a button.
178 *
179 * That's it!
180 *
181 * If you want to disable that action sometime later, you can do so
182 * with
183 * \code
184 * newAct->setEnabled(false)
185 * \endcode
186 * and both the menuitem in File and the toolbar button will instantly
187 * be disabled.
188 *
189 * Unlike with previous versions of KDE, the action can simply be deleted
190 * when you have finished with it - the destructor takes care of all
191 * of the cleanup.
192 *
193 * \warning calling QAction::setShortcut() on a KAction may lead to unexpected
194 * behavior. There is nothing we can do about it because QAction::setShortcut()
195 * is not virtual.
196 *
197 * \note if you are using a "standard" action like "new", "paste",
198 * "quit", or any other action described in the KDE UI Standards,
199 * please use the methods in the KStandardAction class rather than
200 * defining your own.
201 *
202 * \section Using QActions
203 *
204 * Mixing QActions and KActions in an application is not a
205 * good idea. KShortcutsEditor doesn't handle QActions at all.
206 *
207 * \section kaction_xmlgui Usage Within the XML Framework
208 *
209 * If you are using KAction within the context of the XML menu and
210 * toolbar building framework, you do not ever
211 * have to add your actions to containers manually. The framework
212 * does that for you.
213 *
214 * @see KStandardAction
215 */
216class KDEUI_EXPORT KAction : public QWidgetAction
217{
218 Q_OBJECT
219
220 Q_PROPERTY( KShortcut shortcut READ shortcut WRITE setShortcut )
221 Q_PROPERTY( bool shortcutConfigurable READ isShortcutConfigurable WRITE setShortcutConfigurable )
222 Q_PROPERTY( KShortcut globalShortcut READ globalShortcut WRITE setGlobalShortcut )
223#ifndef KDE_NO_DEPRECATED
224 Q_PROPERTY( bool globalShortcutAllowed READ globalShortcutAllowed WRITE setGlobalShortcutAllowed )
225#endif
226 Q_PROPERTY( bool globalShortcutEnabled READ isGlobalShortcutEnabled )
227 Q_FLAGS( ShortcutType )
228
229public:
230 /**
231 * An enumeration about the two types of shortcuts in a KAction
232 */
233 enum ShortcutType {
234 /// The shortcut will immediately become active but may be reset to "default".
235 ActiveShortcut = 0x1,
236 /// The shortcut is a default shortcut - it becomes active when somebody decides to
237 /// reset shortcuts to default.
238 DefaultShortcut = 0x2
239 };
240 Q_DECLARE_FLAGS(ShortcutTypes, ShortcutType)
241
242 /**
243 * An enum about global shortcut setter semantics
244 */
245 //This enum will be ORed with ShortcutType in calls to KGlobalAccel, so it must not contain
246 //any value equal to a value in ShortcutType.
247 enum GlobalShortcutLoading {
248 /// Look up the action in global settings (using its main component's name and text())
249 /// and set the shortcut as saved there.
250 /// @see setGlobalShortcut()
251 Autoloading = 0x0,
252 /// Prevent autoloading of saved global shortcut for action
253 NoAutoloading = 0x4
254 };
255 /**
256 * Constructs an action.
257 */
258 explicit KAction(QObject *parent);
259
260 /**
261 * Constructs an action with the specified parent and visible text.
262 *
263 * @param text The visible text for this action.
264 * @param parent The parent for this action.
265 */
266 KAction(const QString& text, QObject *parent);
267
268 /**
269 * Constructs an action with text and icon; a shortcut may be specified by
270 * the ampersand character (e.g. \"&amp;Option\" creates a shortcut with key \e O )
271 *
272 * This is the other common KAction constructor used. Use it when you
273 * \e do have a corresponding icon.
274 *
275 * @param icon The icon to display.
276 * @param text The text that will be displayed.
277 * @param parent The parent for this action.
278 */
279 KAction(const KIcon& icon, const QString& text, QObject *parent);
280
281 /**
282 * Standard destructor
283 */
284 virtual ~KAction();
285
286 /**
287 * Sets the help text for the action.
288 * This help text will be set for all help mechanisms:
289 * - the status-bar help text
290 * - the tooltip (for toolbar buttons)
291 * - the "WhatsThis" help text (unless one was already set)
292 *
293 * This is more convenient than calling all three methods with the
294 * same text, and this level of abstraction can allow to change
295 * the default implementation of help one day more easily.
296 * Of course you can also call setStatusTip, setToolTip and setWhatsThis
297 * separately for more flexibility.
298 *
299 * This method is also the easiest way to port from KDE3's KAction::setToolTip.
300 *
301 * @since 4.3
302 */
303 void setHelpText(const QString& text);
304
305 /**
306 * Get the shortcut for this action.
307 *
308 * This is preferred over QAction::shortcut(), as it allows for multiple shortcuts
309 * per action. The first and second shortcut as reported by shortcuts() will be the
310 * primary and alternate shortcut of the shortcut returned.
311 *
312 * \param types the type of shortcut to return. Should both be specified, only the
313 * active shortcut will be returned. Defaults to the active shortcut, if one exists.
314 * \sa shortcuts()
315 */
316 KShortcut shortcut(ShortcutTypes types = ActiveShortcut) const;
317
318 /**
319 * Set the shortcut for this action.
320 *
321 * This is preferred over QAction::setShortcut(), as it allows for multiple shortcuts
322 * per action.
323 *
324 * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
325 * \param type type of shortcut to be set: active shortcut,
326 * default shortcut, or both (the default).
327 */
328 void setShortcut(const KShortcut& shortcut, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
329
330 /**
331 * \overload void setShortcut(const KShortcut& shortcut)
332 *
333 * Set the primary shortcut only for this action.
334 *
335 * This function is there to explicitly override QAction::setShortcut(const QKeySequence&).
336 * QAction::setShortcut() will bypass everything in KAction and may lead to unexpected behavior.
337 *
338 * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
339 * \param type type of shortcut to be set: active shortcut,
340 * default shortcut, or both (default argument value).
341 */
342 void setShortcut(const QKeySequence& shortcut, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
343
344 /**
345 * \overload void setShortcuts(const QList\<QKeySequence\>& shortcuts).
346 *
347 * Set the shortcuts for this action.
348 *
349 * This function is there to explicitly override QAction::setShortcut(const QList\<QKeySequence\>&).
350 * QAction::setShortcuts() will bypass everything in KAction and may lead to unexpected behavior.
351 *
352 * \param shortcut shortcut(s) to use for this action in its specified shortcutContext()
353 * \param type type of shortcut to be set: active shortcut,
354 * default shortcut, or both (default argument value).
355 */
356 void setShortcuts(const QList<QKeySequence>& shortcuts, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
357
358 /**
359 * Returns true if this action's shortcut is configurable.
360 */
361 bool isShortcutConfigurable() const;
362
363 /**
364 * Indicate whether the user may configure the action's shortcut.
365 *
366 * \param configurable set to \e true if this shortcut may be configured by the user, otherwise \e false.
367 */
368 void setShortcutConfigurable(bool configurable);
369
370 /**
371 * Get the global shortcut for this action, if one exists. Global shortcuts
372 * allow your actions to respond to accellerators independently of the focused window.
373 * Unlike regular shortcuts, the application's window does not need focus
374 * for them to be activated.
375 *
376 * \param type the type of shortcut to be returned. Should both be specified, only the
377 * active shortcut will be returned. Defaults to the active shortcut,
378 * if one exists.
379 *
380 * \sa KGlobalAccel
381 * \sa setGlobalShortcut()
382 */
383 const KShortcut& globalShortcut(ShortcutTypes type = ActiveShortcut) const;
384
385 /**
386 * Assign a global shortcut for this action. Global shortcuts
387 * allow an action to respond to key shortcuts independently of the focused window,
388 * i.e. the action will trigger if the keys were pressed no matter where in the X session.
389 *
390 * The action must have a per main component unique
391 * objectName() to enable cross-application bookeeping. If the objectName() is empty this method will
392 * do nothing, otherwise the isGlobalShortcutEnabled() property will be set to true and the
393 * shortcut will be enabled.
394 * It is mandatory that the objectName() doesn't change once isGlobalshortcutEnabled()
395 * has become true.
396 *
397 * \note KActionCollection::insert(name, action) will set action's objectName to name so you often
398 * don't have to set an objectName explicitly.
399 *
400 * When an action, identified by main component name and objectName(), is assigned
401 * a global shortcut for the first time on a KDE installation the assignment will
402 * be saved. The shortcut will then be restored every time setGlobalShortcut() is
403 * called with @p loading == Autoloading.
404 *
405 * If you actually want to change the global shortcut you have to set
406 * @p loading to NoAutoloading. The new shortcut will be automatically saved again.
407 *
408 * \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).
409 * \param type the type of shortcut to be set, whether the active shortcut, the default shortcut,
410 * or both (the default).
411 * \param loading if Autoloading, assign the global shortcut this action has previously had if any.
412 * That way user preferences and changes made to avoid clashes will be conserved.
413 * if NoAutoloading the given shortcut will be assigned without looking up old values.
414 * You should only do this if the user wants to change the shortcut or if you have
415 * another very good reason. Key combinations that clash with other shortcuts will be
416 * dropped.
417 *
418 * \note the default shortcut will never be influenced by autoloading - it will be set as given.
419 * \sa globalShortcut()
420 */
421 void setGlobalShortcut(const KShortcut& shortcut, ShortcutTypes type =
422 ShortcutTypes(ActiveShortcut | DefaultShortcut),
423 GlobalShortcutLoading loading = Autoloading);
424
425 /**
426 * Returns true if this action is permitted to have a global shortcut.
427 * Defaults to false.
428 * Use isGlobalShortcutEnabled() instead.
429 */
430#ifndef KDE_NO_DEPRECATED
431 KDE_DEPRECATED bool globalShortcutAllowed() const;
432#endif
433
434 /**
435 * Indicate whether the programmer and/or user may define a global shortcut for this action.
436 * Defaults to false. Note that calling setGlobalShortcut() turns this on automatically.
437 *
438 * \param allowed set to \e true if this action may have a global shortcut, otherwise \e false.
439 * \param loading if Autoloading, assign to this action the global shortcut it has previously had
440 * if any.
441 */
442#ifndef KDE_NO_DEPRECATED
443 KDE_DEPRECATED void setGlobalShortcutAllowed(bool allowed, GlobalShortcutLoading loading = Autoloading);
444#endif
445
446 /**
447 * Returns true if this action is enabled to have a global shortcut.
448 * This will be respected by \class KGlobalShortcutsEditor.
449 * Defaults to false.
450 */
451 bool isGlobalShortcutEnabled() const;
452
453 /**
454 * Sets the globalShortcutEnabled property to false and sets the global shortcut to an
455 * empty shortcut.
456 * This will also wipe out knowlegde about the existence of this action's global shortcut
457 * so it will not be considered anymore for shortcut conflict resolution. It will also not be
458 * visible anymore in the shortcuts KControl module.
459 * This method should not be used unless these effects are explicitly desired.
460 * @since 4.1
461 */
462 void forgetGlobalShortcut();
463
464 KShapeGesture shapeGesture(ShortcutTypes type = ActiveShortcut) const;
465 KRockerGesture rockerGesture(ShortcutTypes type = ActiveShortcut) const;
466
467 void setShapeGesture(const KShapeGesture& gest, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
468 void setRockerGesture(const KRockerGesture& gest, ShortcutTypes type = ShortcutTypes(ActiveShortcut | DefaultShortcut));
469
470 /**
471 * Returns the action object associated with this action, or 0 if it does not have one
472 *
473 * @returns the KAuth::Action associated with this action.
474 */
475 KAuth::Action *authAction() const;
476
477 /**
478 * Sets the action object associated with this action
479 *
480 * By setting a KAuth::Action, this action will become associated with it, and
481 * whenever it gets clicked, it will trigger the authorization and execution process
482 * for the action. The signal activated will also be emitted whenever the action gets
483 * clicked and the action gets authorized. Pass 0 to this function to disassociate the action
484 *
485 * @param action the KAuth::Action to associate with this action.
486 */
487 void setAuthAction(KAuth::Action *action);
488
489 /**
490 * Sets the action object associated with this action
491 *
492 * Overloaded member to allow creating the action by name
493 *
494 * @param actionName the name of the action to associate
495 */
496 void setAuthAction(const QString &actionName);
497
498 /**
499 * @reimp
500 */
501 bool event(QEvent*);
502
503
504Q_SIGNALS:
505#ifdef KDE3_SUPPORT
506 /**
507 * Emitted when this action is activated
508 *
509 * \deprecated use triggered(bool checked) instead.
510 */
511 QT_MOC_COMPAT void activated();
512#endif
513
514 /**
515 * Emitted when the action is triggered. Also provides the state of the
516 * keyboard modifiers and mouse buttons at the time.
517 */
518 void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
519
520 /**
521 * Signal emitted when the action is triggered and authorized
522 *
523 * If the action needs authorization, when the user triggers the action,
524 * the authorization process automatically begins.
525 * If it succeeds, this signal is emitted. The KAuth::Action object is provided for convenience
526 * if you have multiple KAuthorizedAction objects, but of course it's always the same set with
527 * setAuthAction().
528 *
529 * WARNING: If your action needs authorization you should connect eventual slots processing
530 * stuff to this signal, and NOT triggered. Triggered will be emitted even if the user has not
531 * been authorized
532 *
533 * @param action The object set with setAuthAction()
534 */
535 void authorized(KAuth::Action *action);
536
537 /**
538 * Emitted when the global shortcut is changed. A global shortcut is
539 * subject to be changed by the global shortcuts kcm.
540 */
541 void globalShortcutChanged(const QKeySequence&);
542
543private:
544 friend class KGlobalAccelPrivate; // Needs access to the component
545 friend class KActionCollectionPrivate; // Needs access to the component
546 friend class KShortcutsEditorDelegate; // Needs access to the component
547 Q_PRIVATE_SLOT(d, void slotTriggered())
548 Q_PRIVATE_SLOT(d, void authStatusChanged(int))
549 class KActionPrivate* const d;
550 friend class KActionPrivate;
551 friend class KGlobalShortcutTest;
552};
553
554Q_DECLARE_OPERATORS_FOR_FLAGS(KAction::ShortcutTypes)
555
556#endif
557