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