1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#ifndef KACTIONCATEGORY_H
9#define KACTIONCATEGORY_H
10
11#include <kxmlgui_export.h>
12
13#include <QList>
14#include <QObject>
15#include <QString>
16#include <memory>
17
18#include <KStandardActions>
19#if KXMLGUI_ENABLE_DEPRECATED_SINCE(6, 15)
20#include <KStandardAction>
21#endif
22
23#include "kactioncollection.h"
24
25struct KActionCategoryPrivate;
26
27class QAction;
28
29/*!
30 * \class KActionCategory
31 * \inmodule KXmlGui
32 *
33 * \brief Categorize actions for KShortcutsEditor.
34 *
35 * KActionCategory provides a second level to organize the actions in
36 * KShortcutsEditor.
37 *
38 * The first possibility is using more than one action collection. Each
39 * actions collection becomes a top level node.
40 *
41 * \list
42 * \li action collection 1
43 * \list
44 * \li first action
45 * \li second action
46 * \li third action
47 * \endlist
48 * \endlist
49 * \list
50 * \li action collection 2
51 * \list
52 * \li first action
53 * \li second action
54 * \li third action
55 * \endlist
56 * \endlist
57 *
58 * Using KActionCategory it's possible to group the actions of one collection.
59 * \list
60 * \li action collection 1
61 * \list
62 * \li first action
63 * \li first category
64 * \list
65 * \li action 1 in category
66 * \li action 2 in category
67 * \endlist
68 * \li second action
69 * \endlist
70 * \endlist
71 *
72 * The usage is analogous to action collections. Just create a category and use
73 * it instead of the collection to create the actions.
74 *
75 * The synchronization between KActionCollection and KActionCategory is done
76 * internally. There is for example no need to remove actions from a category.
77 * It is done implicitly if the action is removed from the associated
78 * collection.
79 *
80 * \code
81 * KActionCategory *file = new KActionCategory(i18n("File"), actionCollection());
82 * file->addAction(
83 * KStandardActions::New, //< see KStandardAction
84 * this, //< Receiver
85 * &MyApp::fileNew); //< Slot
86 *
87 * // ... more actions added to file ...
88 *
89 * KActionCategory *edit = new KActionCategory(i18n("Edit"), actionCollection());
90 * edit->addAction(
91 * KStandardActions::Copy, //< see KStandardAction
92 * this, //< Receiver
93 * &MyApp::fileNew); //< Slot
94 *
95 * // ...
96 * \endcode
97 */
98class KXMLGUI_EXPORT KActionCategory : public QObject
99{
100 Q_OBJECT
101
102 /*!
103 * \property KActionCategory::text
104 */
105 Q_PROPERTY(QString text READ text WRITE setText)
106
107public:
108 /*!
109 * \brief Constructs a new KActionCategory object named \a text
110 * as a child of \a parent.
111 */
112 explicit KActionCategory(const QString &text, KActionCollection *parent = nullptr);
113
114 /*!
115 * \brief Destructor.
116 */
117 ~KActionCategory() override;
118
119 /*!
120 * \brief Adds an action to the category.
121 *
122 * These methods are provided for your convenience. They call the
123 * corresponding method of KActionCollection.
124 */
125 QAction *addAction(const QString &name, QAction *action);
126
127#if KXMLGUI_ENABLE_DEPRECATED_SINCE(6, 9)
128 /*!
129 * \overload addAction(const QString &name, QAction *action)
130 */
131 KXMLGUI_DEPRECATED_VERSION(6, 9, "Use KStandardActions overload")
132 QAction *addAction(KStandardAction::StandardAction actionType, const QObject *receiver = nullptr, const char *member = nullptr);
133#endif
134
135#if KXMLGUI_ENABLE_DEPRECATED_SINCE(6, 9)
136 /*!
137 * \overload addAction(const QString &name, QAction *action)
138 */
139 KXMLGUI_DEPRECATED_VERSION(6, 9, "Use KStandardActions overload")
140 QAction *addAction(KStandardAction::StandardAction actionType, const QString &name, const QObject *receiver = nullptr, const char *member = nullptr);
141#endif
142
143#if KXMLGUI_ENABLE_DEPRECATED_SINCE(6, 9)
144 // not marked with KXMLGUI_DEPRECATED_VERSION, otherwise addAction("bla") generates a warning, but we don't want that
145 /*!
146 * \deprecated[6.9]
147 * Use PMF overload
148 * \overload addAction(const QString &name, QAction *action)
149 */
150 QAction *addAction(const QString &name, const QObject *receiver = nullptr, const char *member = nullptr);
151#else
152 // this is only enabled when
153 // addAction(KStandardAction::StandardAction actionType, const QObject *receiver = nullptr, const char *member = nullptr
154 // is not built, otherwise there is ambiguity
155 inline QAction *addAction(const QString &name)
156 {
157 QAction *action = collection()->addAction(name);
158 addAction(action);
159 return action;
160 }
161#endif
162
163#if KXMLGUI_ENABLE_DEPRECATED_SINCE(6, 9)
164 template<class ActionType>
165 KXMLGUI_DEPRECATED_VERSION(6, 9, "Use PMF-based overload")
166 ActionType *add(const QString &name, const QObject *receiver, const char *member)
167 {
168 ActionType *action = collection()->add<ActionType>(name, receiver, member);
169 addAction(action);
170 return action;
171 }
172#endif
173
174 /*!
175 * Creates a new standard action, adds it to the collection and connects the
176 * action's triggered(bool) signal to the specified receiver/member. The
177 * newly created action is also returned.
178 *
179 * The KActionCollection takes ownership of the action object.
180 *
181 * \a actionType The standard action type of the action to create.
182 *
183 * \a receiver The QObject to connect the triggered(bool) signal to. Leave nullptr if no
184 * connection is desired.
185 *
186 * \a slot The slot or lambda to connect the triggered(bool) signal to.
187 *
188 * Returns the created action.
189 *
190 * \since 6.9
191 */
192#ifdef Q_QDOC
193 inline QAction *addAction(KStandardActions::StandardAction actionType, const Receiver *receiver, Func slot)
194#else
195 template<class Receiver, class Func>
196 inline typename std::enable_if<!std::is_convertible<Func, const char *>::value, QAction>::type *
197 addAction(KStandardActions::StandardAction actionType, const Receiver *receiver, Func slot)
198#endif
199 {
200 QAction *action = collection()->addAction(actionType, receiver, slot);
201 addAction(action);
202 return action;
203 }
204
205 /*!
206 * Creates a new standard action and adds it to the collection.
207 * The newly created action is also returned.
208 *
209 * The KActionCollection takes ownership of the action object.
210 *
211 * \a actionType The standard action type of the action to create.
212 *
213 * Returns the created action.
214 *
215 * \since 6.9
216 */
217 QAction *addAction(KStandardActions::StandardAction actionType);
218
219 /*!
220 * Creates a new standard action and adds it to the collection.
221 *
222 * The newly created action is also returned.
223 *
224 * The KActionCollection takes ownership of the action object.
225 *
226 * \a actionType The standard action type of the action to create.
227 *
228 * \a name The name by which the action be retrieved again from the collection.
229 *
230 * Returns the created action.
231 *
232 * \since 6.15
233 */
234 QAction *addAction(KStandardActions::StandardAction actionType, const QString &name);
235
236 /*!
237 * Creates a new standard action, adds it to the collection and connects the
238 * action's triggered(bool) signal to the specified receiver/member. The
239 * newly created action is also returned.
240 *
241 * The KActionCollection takes ownership of the action object.
242 *
243 * \a actionType The standard action type of the action to create.
244 *
245 * \a name The name by which the action be retrieved again from the collection.
246 *
247 * \a receiver The QObject to connect the triggered(bool) signal to. Leave nullptr if no
248 * connection is desired.
249 *
250 * \a slot The slot or lambda to connect the triggered(bool) signal to.
251 *
252 * Returns the created action.
253 *
254 * \since 6.9
255 */
256#ifdef Q_QDOC
257 inline QAction *addAction(KStandardActions::StandardAction actionType, const Receiver *receiver, Func slot)
258#else
259 template<class Receiver, class Func>
260 inline typename std::enable_if<!std::is_convertible<Func, const char *>::value, QAction>::type *
261 addAction(KStandardActions::StandardAction actionType, const QString &name, const Receiver *receiver, Func slot)
262#endif
263 {
264 QAction *action = collection()->addAction(actionType, name, receiver, slot);
265 addAction(action);
266 return action;
267 }
268
269 /*!
270 * Creates a new action, adds it to the collection and connects the
271 * action's triggered(bool) signal to the specified receiver/member. The
272 * newly created action is also returned.
273 *
274 * The KActionCollection takes ownership of the action object.
275 *
276 * \a name The name by which the action be retrieved again from the collection.
277 *
278 * \a receiver The QObject to connect the triggered(bool) signal to. Leave nullptr if no
279 * connection is desired.
280 *
281 * \a slot The slot or lambda to connect the triggered(bool) signal to.
282 *
283 * Returns the created action.
284 *
285 * \since 6.9
286 */
287#ifdef Q_QDOC
288 inline QAction *addAction(const Receiver *receiver, Func slot)
289#else
290 template<class Receiver, class Func>
291 inline typename std::enable_if<!std::is_convertible<Func, const char *>::value, QAction>::type *
292 addAction(const QString &name, const Receiver *receiver, Func slot)
293#endif
294 {
295 QAction *action = collection()->addAction(name, receiver, slot);
296 addAction(action);
297 return action;
298 }
299
300 /*!
301 * Creates a new action, adds it to the collection and connects the
302 * action's triggered(bool) signal to the specified receiver/member. The
303 * newly created action is also returned.
304 *
305 * The KActionCollection takes ownership of the action object.
306 *
307 * \a name The name by which the action be retrieved again from the collection.
308 *
309 * \a receiver The QObject to connect the triggered(bool) signal to. Leave nullptr if no
310 * connection is desired.
311 *
312 * \a slot The slot or lambda to connect the triggered(bool) signal to.
313 *
314 * Returns the created action.
315 *
316 * \since 6.9
317 */
318#ifdef Q_QDOC
319 inline QAction *add(const Receiver *receiver, Func slot)
320#else
321 template<class ActionType, class Receiver, class Func>
322 inline typename std::enable_if<!std::is_convertible<Func, const char *>::value, QAction>::type *
323 add(const QString &name, const Receiver *receiver, Func slot)
324#endif
325 {
326 QAction *action = collection()->add<ActionType>(name, receiver, slot);
327 addAction(action);
328 return action;
329 }
330
331 /*!
332 * Creates a new action and adds it to the collection.
333 * The newly created action is also returned.
334 *
335 * The KActionCollection takes ownership of the action object.
336 *
337 * \a name The name by which the action be retrieved again from the collection.
338 *
339 * Returns the created action.
340 *
341 * \since 6.9
342 */
343 template<class ActionType>
344 ActionType *add(const QString &name)
345 {
346 ActionType *action = collection()->add<ActionType>(name);
347 addAction(action);
348 return action;
349 }
350
351 /*!
352 * \brief Returns the actions belonging to this category.
353 */
354 const QList<QAction *> actions() const;
355
356 /*!
357 * \brief Returns the action collection this category is associated with.
358 */
359 KActionCollection *collection() const;
360
361 /*!
362 * \brief Returns the action category's descriptive text.
363 */
364 QString text() const;
365
366 /*!
367 * \brief Sets the action category's descriptive \a text.
368 */
369 void setText(const QString &text);
370
371private:
372 /*!
373 * \brief Removes \a action from this category if found.
374 */
375 KXMLGUI_NO_EXPORT void unlistAction(QAction *action);
376
377 /*!
378 * \brief Adds \a action to this category.
379 */
380 void addAction(QAction *action); // exported because called from template method ActionType *add<ActionType>(...)
381
382private:
383 friend class KActionCollectionPrivate;
384
385 std::unique_ptr<KActionCategoryPrivate> const d;
386};
387
388#endif /* #ifndef KACTIONCATEGORY_H */
389

source code of kxmlgui/src/kactioncategory.h