1 /* 2 This file is part of the KDE libraries 3 SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org> 4 SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org> 5 SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org> 6 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org> 7 SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org> 8 SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org> 9 SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org> 10 SPDX-FileCopyrightText: 2003 Andras Mantia <amantia@kde.org> 11 SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org> 12 SPDX-FileCopyrightText: 2006 Albert Astals Cid <aacid@kde.org> 13 SPDX-FileCopyrightText: 2006 Clarence Dang <dang@kde.org> 14 SPDX-FileCopyrightText: 2006 Michel Hermier <michel.hermier@gmail.com> 15 SPDX-FileCopyrightText: 2007 Nick Shaforostoff <shafff@ukr.net> 16 17 SPDX-License-Identifier: LGPL-2.0-only 18 */ 19 20 #ifndef KSELECTACTION_H 21 #define KSELECTACTION_H 22 23 #include <QToolButton> 24 #include <QWidgetAction> 25 #include <memory> 26 27 #include <kwidgetsaddons_export.h> 28 29 class KSelectActionPrivate; 30 31 /** 32 * @class KSelectAction kselectaction.h KSelectAction 33 * 34 * @short Action for selecting one of several items 35 * 36 * Action for selecting one of several items. 37 * 38 * This action shows up a submenu with a list of items. 39 * One of them can be checked. If the user clicks on an item 40 * this item will automatically be checked, 41 * the formerly checked item becomes unchecked. 42 * There can be only one item checked at a time. 43 */ 44 class KWIDGETSADDONS_EXPORT KSelectAction : public QWidgetAction 45 { 46 Q_OBJECT 47 Q_PROPERTY(QAction *currentAction READ currentAction WRITE setCurrentAction) 48 Q_PROPERTY(bool editable READ isEditable WRITE setEditable) 49 Q_PROPERTY(int comboWidth READ comboWidth WRITE setComboWidth) 50 Q_PROPERTY(QString currentText READ currentText) 51 Q_PROPERTY(ToolBarMode toolBarMode READ toolBarMode WRITE setToolBarMode) 52 Q_PROPERTY(QToolButton::ToolButtonPopupMode toolButtonPopupMode READ toolButtonPopupMode WRITE setToolButtonPopupMode) 53 Q_PROPERTY(int currentItem READ currentItem WRITE setCurrentItem) 54 Q_PROPERTY(QStringList items READ items WRITE setItems) 55 56 public: 57 /** 58 * Constructs a selection action with the specified parent. 59 * 60 * @param parent The action's parent object. 61 */ 62 explicit KSelectAction(QObject *parent); 63 64 /** 65 * Constructs a selection action with text; a shortcut may be specified by 66 * the ampersand character (e.g.\ "&Option" creates a shortcut with key \e O ) 67 * 68 * This is the most common KSelectAction used when you do not have a 69 * corresponding icon (note that it won't appear in the current version 70 * of the "Edit ToolBar" dialog, because an action needs an icon to be 71 * plugged in a toolbar...). 72 * 73 * @param text The text that will be displayed. 74 * @param parent The action's parent object. 75 */ 76 KSelectAction(const QString &text, QObject *parent); 77 78 /** 79 * Constructs a selection action with text and an icon; a shortcut may be specified by 80 * the ampersand character (e.g.\ "&Option" creates a shortcut with key \e O ) 81 * 82 * This is the other common KSelectAction used. Use it when you 83 * \e do have a corresponding icon. 84 * 85 * @param icon The icon to display. 86 * @param text The text that will be displayed. 87 * @param parent The action's parent object. 88 */ 89 KSelectAction(const QIcon &icon, const QString &text, QObject *parent); 90 91 /** 92 * Destructor 93 */ 94 ~KSelectAction() override; 95 96 enum ToolBarMode { 97 /// Creates a button which pops up a menu when interacted with, as defined by toolButtonPopupMode(). 98 MenuMode, 99 /// Creates a combo box which contains the actions. 100 /// This is the default. 101 ComboBoxMode, 102 }; 103 Q_ENUM(ToolBarMode) 104 105 /** 106 * Returns which type of widget (combo box or button with drop-down menu) will be inserted 107 * in a toolbar. 108 */ 109 ToolBarMode toolBarMode() const; 110 111 /** 112 * Set the type of widget to be inserted in a toolbar to \a mode. 113 */ 114 void setToolBarMode(ToolBarMode mode); 115 116 /** 117 * Returns the style for the list of actions, when this action is plugged 118 * into a KToolBar. The default value is QToolButton::InstantPopup 119 * 120 * \sa QToolButton::setPopupMode() 121 */ 122 QToolButton::ToolButtonPopupMode toolButtonPopupMode() const; 123 124 /** 125 * Set how this list of actions should behave when in popup mode and plugged into a toolbar. 126 */ 127 void setToolButtonPopupMode(QToolButton::ToolButtonPopupMode mode); 128 129 /** 130 * The action group used to create exclusivity between the actions associated with this action. 131 */ 132 QActionGroup *selectableActionGroup() const; 133 134 /** 135 * Returns the current QAction. 136 * @see setCurrentAction 137 */ 138 QAction *currentAction() const; 139 140 /** 141 * Returns the index of the current item. 142 * 143 * @sa currentText(), currentAction() 144 */ 145 int currentItem() const; 146 147 /** 148 * Returns the text of the currently selected item. 149 * 150 * @sa currentItem(), currentAction() 151 */ 152 QString currentText() const; 153 154 /** 155 * Returns the list of selectable actions 156 */ 157 QList<QAction *> actions() const; 158 159 /** 160 * Returns the action at \a index, if one exists. 161 */ 162 QAction *action(int index) const; 163 164 /** 165 * Searches for an action with the specified \a text, using a search whose 166 * case sensitivity is defined by \a cs. 167 */ 168 QAction *action(const QString &text, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; 169 170 /** 171 * Sets the currently checked item. 172 * 173 * @param action the QAction to become the currently checked item. 174 * 175 * \return \e true if a corresponding action was found and successfully checked. 176 */ 177 bool setCurrentAction(QAction *action); 178 179 /** 180 * Convenience function to set the currently checked action to be the action 181 * at index \p index. 182 * 183 * If there is no action at that index, the currently checked action (if any) will 184 * be deselected. 185 * 186 * \return \e true if a corresponding action was found and thus set to the current action, otherwise \e false 187 */ 188 bool setCurrentItem(int index); 189 190 /** 191 * Overloaded member function, provided for convenience, to set the currently 192 * checked action to be the action which has \p text as its text(). 193 * 194 * If there is no action at that index, the currently checked action (if any) will 195 * be deselected. 196 * 197 * \return \e true if a corresponding action was found, otherwise \e false 198 */ 199 bool setCurrentAction(const QString &text, Qt::CaseSensitivity cs = Qt::CaseSensitive); 200 201 /** 202 * Add \a action to the list of selectable actions. 203 */ 204 void addAction(QAction *action); 205 206 /** 207 * Overloaded member function, provided for convenience, which creates an action 208 * from \p text and inserts it into the list of selectable actions. 209 * 210 * The newly created action is checkable and not user configurable. 211 */ 212 QAction *addAction(const QString &text); 213 214 /** 215 * Overloaded member function, provided for convenience, which creates an action 216 * from \p text and \p icon and inserts it into the list of selectable actions. 217 * 218 * The newly created action is checkable and not user configurable. 219 */ 220 QAction *addAction(const QIcon &icon, const QString &text); 221 222 /** 223 * Remove the specified \a action from this action selector. 224 * 225 * You take ownership here, so save or delete it in order to not leak the action. 226 */ 227 virtual QAction *removeAction(QAction *action); 228 229 /** 230 * Inserts the action action to this widget's list of actions, before the action before. 231 * It appends the action if before is a null pointer or before is not a valid action for this widget. 232 * 233 * @since 5.0 234 */ 235 virtual void insertAction(QAction *before, QAction *action); 236 237 /** 238 * Convenience function to create the list of selectable items. 239 * Any previously existing items will be cleared. 240 */ 241 void setItems(const QStringList &lst); 242 243 /** 244 * Convenience function which returns the items that can be selected with this action. 245 * It is the same as iterating selectableActionGroup()->actions() and looking at each 246 * action's text(). 247 */ 248 QStringList items() const; 249 250 /** 251 * When this action is plugged into a toolbar, it creates a combobox. 252 * @return true if the combo editable. 253 */ 254 bool isEditable() const; 255 256 /** 257 * When this action is plugged into a toolbar, it creates a combobox. 258 * This makes the combo editable or read-only. 259 */ 260 void setEditable(bool); 261 262 /** 263 * When this action is plugged into a toolbar, it creates a combobox. 264 * This returns the maximum width set by setComboWidth 265 */ 266 int comboWidth() const; 267 268 /** 269 * When this action is plugged into a toolbar, it creates a combobox. 270 * This gives a _maximum_ size to the combobox. 271 * The minimum size is automatically given by the contents (the items). 272 */ 273 void setComboWidth(int width); 274 275 /** 276 * Sets the maximum items that are visible at once if the action 277 * is a combobox, that is the number of items in the combobox's viewport 278 */ 279 void setMaxComboViewCount(int n); 280 281 /** 282 * Remove and delete all the items in this action. 283 * 284 * @see removeAllActions() 285 */ 286 void clear(); 287 288 /** 289 * Remove all the items in this action. 290 * 291 * Unlike clear(), this will not delete the actions. 292 * 293 * @see clear() 294 */ 295 void removeAllActions(); 296 297 /** 298 * Sets whether any occurrence of the ampersand character ( & ) in items 299 * should be interpreted as keyboard accelerator for items displayed in a 300 * menu or not. Only applies to (overloaded) methods dealing with QStrings, 301 * not those dealing with QActions. 302 * 303 * Defaults to true. 304 * 305 * \param b true if ampersands indicate a keyboard accelerator, otherwise false. 306 */ 307 void setMenuAccelsEnabled(bool b); 308 309 /** 310 * Returns whether ampersands passed to methods using QStrings are interpreted 311 * as keyboard accelerator indicators or as literal ampersands. 312 */ 313 bool menuAccelsEnabled() const; 314 315 /** 316 * Changes the text of item @param index to @param text . 317 */ 318 void changeItem(int index, const QString &text); 319 320 Q_SIGNALS: 321 /** 322 * This signal is emitted when an item is selected. 323 * @param action indicates the item selected 324 */ 325 void triggered(QAction *action); // clazy:exclude=overloaded-signal 326 // TODO KF6:: rename to actionTriggered(QAction *action) 327 // We cannot do this in KF5, due to existing slot method with same signature, see below 328 329 #if KWIDGETSADDONS_ENABLE_DEPRECATED_SINCE(5, 78) 330 /** 331 * This signal is emitted when an item is selected. 332 * @param index indicates the item selected 333 * @deprecated Since 5.78, use indexTriggered(int) 334 */ 335 KWIDGETSADDONS_DEPRECATED_VERSION(5, 78, "Use KSelectAction::indexTriggered(int)") 336 void triggered(int index); // clazy:exclude=overloaded-signal 337 #endif 338 /** 339 * This signal is emitted when an item is selected. 340 * @param index indicates the item selected 341 * 342 * In your KSelectAction subclass to be backward-compatible to KF < 5.78, emit instead 343 * just the deprecated signal triggered(int). That will also 344 * automatically emit indexTriggered(int) because this signal 345 * is connected to the deprecated one in the KSelectAction constructor. 346 * Only if you compile against a variant of KWidgetsAddons built without all API 347 * deprecated up to version 5.78, then emit this signal directly. 348 * Your code would be like this: 349 * @code 350 * const int index = selectableActionGroup()->actions().indexOf(action); 351 * #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 78) 352 * // will also indirectly emit indexTriggered since 5.78 353 * Q_EMIT triggered(index); 354 * #else 355 * Q_EMIT indexTriggered(index); 356 * #endif 357 * @endcode 358 * 359 * @since 5.78 360 */ 361 void indexTriggered(int index); 362 363 #if KWIDGETSADDONS_ENABLE_DEPRECATED_SINCE(5, 78) 364 /** 365 * This signal is emitted when an item is selected. 366 * @param text indicates the item selected 367 * @deprecated Since 5.78, use textTriggered(const QString &) 368 */ 369 KWIDGETSADDONS_DEPRECATED_VERSION(5, 78, "Use KSelectAction::textTriggered(const QString &)") 370 void triggered(const QString &text); // clazy:exclude=overloaded-signal 371 #endif 372 373 /** 374 * This signal is emitted when an item is selected. 375 * @param text indicates the item selected 376 * 377 * In your KSelectAction subclass to be backward-compatible to KF < 5.78, emit instead 378 * just the deprecated signal triggered(const QString &). That will also 379 * automatically emit textTriggered(const QString &) because this signal 380 * is connected to the deprecated one in the KSelectAction constructor. 381 * Only if you compile against a variant of KWidgetsAddons built without all API 382 * deprecated up to version 5.78, then emit this signal directly. 383 * Your code would be like this: 384 * @code 385 * #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 78) 386 * // will also indirectly emit textTriggered since 5.78 387 * Q_EMIT triggered(action->text()); 388 * #else 389 * Q_EMIT textTriggered(action->text()); 390 * #endif 391 * @endcode 392 * 393 * @since 5.78 394 */ 395 void textTriggered(const QString &text); 396 397 protected Q_SLOTS: 398 /** 399 * This function is called whenever an action from the selections is triggered. 400 * The default implementation calls trigger() if isCheckable() is @c true, then emits 401 * the signals triggered(QAction *), triggered(int) and triggered(const QString &) 402 * as well as since 5.78 the signals indexTriggered(int) and textTriggered(const QString &). 403 */ 404 virtual void actionTriggered(QAction *action); 405 // TODO KF6:: rename to handleActionTriggered, to release name to signal 406 407 /** 408 * For structured menu building. Deselects all items if the action was unchecked by the top menu 409 */ 410 void slotToggled(bool); 411 412 protected: 413 /** 414 * Reimplemented from QWidgetAction. 415 */ 416 QWidget *createWidget(QWidget *parent) override; 417 418 /** 419 * Reimplemented from QWidgetAction. 420 */ 421 void deleteWidget(QWidget *widget) override; 422 423 bool event(QEvent *event) override; 424 425 bool eventFilter(QObject *watched, QEvent *event) override; 426 427 /** 428 * @internal 429 * Creates a new KSelectAction object. 430 * 431 * @param dd the private d member 432 * @param parent The action's parent object. 433 */ 434 KSelectAction(KSelectActionPrivate &dd, QObject *parent); 435 436 std::unique_ptr<class KSelectActionPrivate> const d_ptr; 437 438 private: 439 Q_DECLARE_PRIVATE(KSelectAction) 440 }; 441 442 #endif 443