File indexing completed on 2024-04-28 15:32:13

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org>
0004     SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
0005     SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
0006     SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
0007     SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org>
0008     SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org>
0009     SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org>
0010     SPDX-FileCopyrightText: 2003 Andras Mantia <amantia@kde.org>
0011     SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org>
0012     SPDX-FileCopyrightText: 2006 Albert Astals Cid <aacid@kde.org>
0013     SPDX-FileCopyrightText: 2006 Clarence Dang <dang@kde.org>
0014     SPDX-FileCopyrightText: 2006 Michel Hermier <michel.hermier@gmail.com>
0015     SPDX-FileCopyrightText: 2007 Nick Shaforostoff <shafff@ukr.net>
0016 
0017     SPDX-License-Identifier: LGPL-2.0-only
0018 */
0019 
0020 #ifndef KSELECTACTION_H
0021 #define KSELECTACTION_H
0022 
0023 #include <QToolButton>
0024 #include <QWidgetAction>
0025 #include <memory>
0026 
0027 #include <kwidgetsaddons_export.h>
0028 
0029 class KSelectActionPrivate;
0030 
0031 /**
0032  *  @class KSelectAction kselectaction.h KSelectAction
0033  *
0034  *  @short Action for selecting one of several items
0035  *
0036  *  Action for selecting one of several items.
0037  *
0038  *  This action shows up a submenu with a list of items.
0039  *  One of them can be checked. If the user clicks on an item
0040  *  this item will automatically be checked,
0041  *  the formerly checked item becomes unchecked.
0042  *  There can be only one item checked at a time.
0043  */
0044 class KWIDGETSADDONS_EXPORT KSelectAction : public QWidgetAction
0045 {
0046     Q_OBJECT
0047     Q_PROPERTY(QAction *currentAction READ currentAction WRITE setCurrentAction)
0048     Q_PROPERTY(bool editable READ isEditable WRITE setEditable)
0049     Q_PROPERTY(int comboWidth READ comboWidth WRITE setComboWidth)
0050     Q_PROPERTY(QString currentText READ currentText)
0051     Q_PROPERTY(ToolBarMode toolBarMode READ toolBarMode WRITE setToolBarMode)
0052     Q_PROPERTY(QToolButton::ToolButtonPopupMode toolButtonPopupMode READ toolButtonPopupMode WRITE setToolButtonPopupMode)
0053     Q_PROPERTY(int currentItem READ currentItem WRITE setCurrentItem)
0054     Q_PROPERTY(QStringList items READ items WRITE setItems)
0055 
0056 public:
0057     /**
0058      * Constructs a selection action with the specified parent.
0059      *
0060      * @param parent The action's parent object.
0061      */
0062     explicit KSelectAction(QObject *parent);
0063 
0064     /**
0065      * Constructs a selection action with text; a shortcut may be specified by
0066      * the ampersand character (e.g.\ "&Option" creates a shortcut with key \e O )
0067      *
0068      * This is the most common KSelectAction used when you do not have a
0069      * corresponding icon (note that it won't appear in the current version
0070      * of the "Edit ToolBar" dialog, because an action needs an icon to be
0071      * plugged in a toolbar...).
0072      *
0073      * @param text The text that will be displayed.
0074      * @param parent The action's parent object.
0075      */
0076     KSelectAction(const QString &text, QObject *parent);
0077 
0078     /**
0079      * Constructs a selection action with text and an icon; a shortcut may be specified by
0080      * the ampersand character (e.g.\ "&Option" creates a shortcut with key \e O )
0081      *
0082      * This is the other common KSelectAction used.  Use it when you
0083      * \e do have a corresponding icon.
0084      *
0085      * @param icon The icon to display.
0086      * @param text The text that will be displayed.
0087      * @param parent The action's parent object.
0088      */
0089     KSelectAction(const QIcon &icon, const QString &text, QObject *parent);
0090 
0091     /**
0092      * Destructor
0093      */
0094     ~KSelectAction() override;
0095 
0096     enum ToolBarMode {
0097         /// Creates a button which pops up a menu when interacted with, as defined by toolButtonPopupMode().
0098         MenuMode,
0099         /// Creates a combo box which contains the actions.
0100         /// This is the default.
0101         ComboBoxMode,
0102     };
0103     Q_ENUM(ToolBarMode)
0104 
0105     /**
0106      * Returns which type of widget (combo box or button with drop-down menu) will be inserted
0107      * in a toolbar.
0108      */
0109     ToolBarMode toolBarMode() const;
0110 
0111     /**
0112      * Set the type of widget to be inserted in a toolbar to \a mode.
0113      */
0114     void setToolBarMode(ToolBarMode mode);
0115 
0116     /**
0117      * Returns the style for the list of actions, when this action is plugged
0118      * into a KToolBar. The default value is QToolButton::InstantPopup
0119      *
0120      * \sa QToolButton::setPopupMode()
0121      */
0122     QToolButton::ToolButtonPopupMode toolButtonPopupMode() const;
0123 
0124     /**
0125      * Set how this list of actions should behave when in popup mode and plugged into a toolbar.
0126      */
0127     void setToolButtonPopupMode(QToolButton::ToolButtonPopupMode mode);
0128 
0129     /**
0130      * The action group used to create exclusivity between the actions associated with this action.
0131      */
0132     QActionGroup *selectableActionGroup() const;
0133 
0134     /**
0135      * Returns the current QAction.
0136      * @see setCurrentAction
0137      */
0138     QAction *currentAction() const;
0139 
0140     /**
0141      * Returns the index of the current item.
0142      *
0143      * @sa currentText(), currentAction()
0144      */
0145     int currentItem() const;
0146 
0147     /**
0148      * Returns the text of the currently selected item.
0149      *
0150      * @sa currentItem(), currentAction()
0151      */
0152     QString currentText() const;
0153 
0154     /**
0155      * Returns the list of selectable actions
0156      */
0157     QList<QAction *> actions() const;
0158 
0159     /**
0160      * Returns the action at \a index, if one exists.
0161      */
0162     QAction *action(int index) const;
0163 
0164     /**
0165      * Searches for an action with the specified \a text, using a search whose
0166      * case sensitivity is defined by \a cs.
0167      */
0168     QAction *action(const QString &text, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0169 
0170     /**
0171      * Sets the currently checked item.
0172      *
0173      * @param action the QAction to become the currently checked item.
0174      *
0175      * \return \e true if a corresponding action was found and successfully checked.
0176      */
0177     bool setCurrentAction(QAction *action);
0178 
0179     /**
0180      * Convenience function to set the currently checked action to be the action
0181      * at index \p index.
0182      *
0183      * If there is no action at that index, the currently checked action (if any) will
0184      * be deselected.
0185      *
0186      * \return \e true if a corresponding action was found and thus set to the current action, otherwise \e false
0187      */
0188     bool setCurrentItem(int index);
0189 
0190     /**
0191      * Overloaded member function, provided for convenience, to set the currently
0192      * checked action to be the action which has \p text as its text().
0193      *
0194      * If there is no action at that index, the currently checked action (if any) will
0195      * be deselected.
0196      *
0197      * \return \e true if a corresponding action was found, otherwise \e false
0198      */
0199     bool setCurrentAction(const QString &text, Qt::CaseSensitivity cs = Qt::CaseSensitive);
0200 
0201     /**
0202      * Add \a action to the list of selectable actions.
0203      */
0204     void addAction(QAction *action);
0205 
0206     /**
0207      * Overloaded member function, provided for convenience, which creates an action
0208      * from \p text and inserts it into the list of selectable actions.
0209      *
0210      * The newly created action is checkable and not user configurable.
0211      */
0212     QAction *addAction(const QString &text);
0213 
0214     /**
0215      * Overloaded member function, provided for convenience, which creates an action
0216      * from \p text and \p icon and inserts it into the list of selectable actions.
0217      *
0218      * The newly created action is checkable and not user configurable.
0219      */
0220     QAction *addAction(const QIcon &icon, const QString &text);
0221 
0222     /**
0223      * Remove the specified \a action from this action selector.
0224      *
0225      * You take ownership here, so save or delete it in order to not leak the action.
0226      */
0227     virtual QAction *removeAction(QAction *action);
0228 
0229     /**
0230      * Inserts the action action to this widget's list of actions, before the action before.
0231      * It appends the action if before is a null pointer or before is not a valid action for this widget.
0232      *
0233      * @since 5.0
0234      */
0235     virtual void insertAction(QAction *before, QAction *action);
0236 
0237     /**
0238      * Convenience function to create the list of selectable items.
0239      * Any previously existing items will be cleared.
0240      */
0241     void setItems(const QStringList &lst);
0242 
0243     /**
0244      * Convenience function which returns the items that can be selected with this action.
0245      * It is the same as iterating selectableActionGroup()->actions() and looking at each
0246      * action's text().
0247      */
0248     QStringList items() const;
0249 
0250     /**
0251      * When this action is plugged into a toolbar, it creates a combobox.
0252      * @return true if the combo editable.
0253      */
0254     bool isEditable() const;
0255 
0256     /**
0257      * When this action is plugged into a toolbar, it creates a combobox.
0258      * This makes the combo editable or read-only.
0259      */
0260     void setEditable(bool);
0261 
0262     /**
0263      * When this action is plugged into a toolbar, it creates a combobox.
0264      * This returns the maximum width set by setComboWidth
0265      */
0266     int comboWidth() const;
0267 
0268     /**
0269      * When this action is plugged into a toolbar, it creates a combobox.
0270      * This gives a _maximum_ size to the combobox.
0271      * The minimum size is automatically given by the contents (the items).
0272      */
0273     void setComboWidth(int width);
0274 
0275     /**
0276      * Sets the maximum items that are visible at once if the action
0277      * is a combobox, that is the number of items in the combobox's viewport
0278      */
0279     void setMaxComboViewCount(int n);
0280 
0281     /**
0282      * Remove and delete all the items in this action.
0283      *
0284      * @see removeAllActions()
0285      */
0286     void clear();
0287 
0288     /**
0289      * Remove all the items in this action.
0290      *
0291      * Unlike clear(), this will not delete the actions.
0292      *
0293      * @see clear()
0294      */
0295     void removeAllActions();
0296 
0297     /**
0298      * Sets whether any occurrence of the ampersand character ( & ) in items
0299      * should be interpreted as keyboard accelerator for items displayed in a
0300      * menu or not.  Only applies to (overloaded) methods dealing with QStrings,
0301      * not those dealing with QActions.
0302      *
0303      * Defaults to true.
0304      *
0305      * \param b true if ampersands indicate a keyboard accelerator, otherwise false.
0306      */
0307     void setMenuAccelsEnabled(bool b);
0308 
0309     /**
0310      * Returns whether ampersands passed to methods using QStrings are interpreted
0311      * as keyboard accelerator indicators or as literal ampersands.
0312      */
0313     bool menuAccelsEnabled() const;
0314 
0315     /**
0316      * You should delete KSelectAction::menu() before calling setMenu(). KSelectAction
0317      * will take the @param menu ownership and it will be deleted when KSelectAction is
0318      * destroyed.
0319      */
0320     using QWidgetAction::setMenu;
0321 
0322     /**
0323      * Changes the text of item @param index to @param text .
0324      */
0325     void changeItem(int index, const QString &text);
0326 
0327 Q_SIGNALS:
0328     /**
0329      * This signal is emitted when an item is selected.
0330      * @param action indicates the item selected
0331      */
0332     void triggered(QAction *action); // clazy:exclude=overloaded-signal
0333     // TODO KF6:: rename to actionTriggered(QAction *action)
0334     // We cannot do this in KF5, due to existing slot method with same signature, see below
0335 
0336 #if KWIDGETSADDONS_ENABLE_DEPRECATED_SINCE(5, 78)
0337     /**
0338      * This signal is emitted when an item is selected.
0339      * @param index indicates the item selected
0340      * @deprecated Since 5.78, use indexTriggered(int)
0341      */
0342     KWIDGETSADDONS_DEPRECATED_VERSION(5, 78, "Use KSelectAction::indexTriggered(int)")
0343     void triggered(int index); // clazy:exclude=overloaded-signal
0344 #endif
0345     /**
0346      * This signal is emitted when an item is selected.
0347      * @param index indicates the item selected
0348      *
0349      * In your KSelectAction subclass to be backward-compatible to KF < 5.78, emit instead
0350      * just the deprecated signal triggered(int). That will also
0351      * automatically emit indexTriggered(int) because this signal
0352      * is connected to the deprecated one in the KSelectAction constructor.
0353      * Only if you compile against a variant of KWidgetsAddons built without all API
0354      * deprecated up to version 5.78, then emit this signal directly.
0355      * Your code would be like this:
0356      * @code
0357      *     const int index = selectableActionGroup()->actions().indexOf(action);
0358      * #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 78)
0359      *     // will also indirectly emit indexTriggered since 5.78
0360      *     Q_EMIT triggered(index);
0361      * #else
0362      *     Q_EMIT indexTriggered(index);
0363      * #endif
0364      * @endcode
0365      *
0366      * @since 5.78
0367      */
0368     void indexTriggered(int index);
0369 
0370 #if KWIDGETSADDONS_ENABLE_DEPRECATED_SINCE(5, 78)
0371     /**
0372      * This signal is emitted when an item is selected.
0373      * @param text indicates the item selected
0374      * @deprecated Since 5.78, use textTriggered(const QString &)
0375      */
0376     KWIDGETSADDONS_DEPRECATED_VERSION(5, 78, "Use KSelectAction::textTriggered(const QString &)")
0377     void triggered(const QString &text); // clazy:exclude=overloaded-signal
0378 #endif
0379 
0380     /**
0381      * This signal is emitted when an item is selected.
0382      * @param text indicates the item selected
0383      *
0384      * In your KSelectAction subclass to be backward-compatible to KF < 5.78, emit instead
0385      * just the deprecated signal triggered(const QString &). That will also
0386      * automatically emit textTriggered(const QString &) because this signal
0387      * is connected to the deprecated one in the KSelectAction constructor.
0388      * Only if you compile against a variant of KWidgetsAddons built without all API
0389      * deprecated up to version 5.78, then emit this signal directly.
0390      * Your code would be like this:
0391      * @code
0392      * #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 78)
0393      *     // will also indirectly emit textTriggered since 5.78
0394      *     Q_EMIT triggered(action->text());
0395      * #else
0396      *     Q_EMIT textTriggered(action->text());
0397      * #endif
0398      * @endcode
0399      *
0400      * @since 5.78
0401      */
0402     void textTriggered(const QString &text);
0403 
0404 protected Q_SLOTS:
0405     /**
0406      * This function is called whenever an action from the selections is triggered.
0407      * The default implementation calls trigger() if isCheckable() is @c true, then emits
0408      * the signals triggered(QAction *), triggered(int) and triggered(const QString &)
0409      * as well as since 5.78 the signals indexTriggered(int) and textTriggered(const QString &).
0410      */
0411     virtual void actionTriggered(QAction *action);
0412     // TODO KF6:: rename to handleActionTriggered, to release name to signal
0413 
0414     /**
0415      * For structured menu building. Deselects all items if the action was unchecked by the top menu
0416      */
0417     void slotToggled(bool);
0418 
0419 protected:
0420     /**
0421      * Reimplemented from QWidgetAction.
0422      */
0423     QWidget *createWidget(QWidget *parent) override;
0424 
0425     /**
0426      * Reimplemented from QWidgetAction.
0427      */
0428     void deleteWidget(QWidget *widget) override;
0429 
0430     bool event(QEvent *event) override;
0431 
0432     bool eventFilter(QObject *watched, QEvent *event) override;
0433 
0434     /**
0435      * @internal
0436      * Creates a new KSelectAction object.
0437      *
0438      * @param dd the private d member
0439      * @param parent The action's parent object.
0440      */
0441     KWIDGETSADDONS_NO_EXPORT KSelectAction(KSelectActionPrivate &dd, QObject *parent);
0442 
0443     std::unique_ptr<class KSelectActionPrivate> const d_ptr;
0444 
0445 private:
0446     Q_DECLARE_PRIVATE(KSelectAction)
0447 };
0448 
0449 #endif