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 | |
25 | struct KActionCategoryPrivate; |
26 | |
27 | class 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 | */ |
98 | class 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 | |
107 | public: |
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 | |
371 | private: |
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 | |
382 | private: |
383 | friend class KActionCollectionPrivate; |
384 | |
385 | std::unique_ptr<KActionCategoryPrivate> const d; |
386 | }; |
387 | |
388 | #endif /* #ifndef KACTIONCATEGORY_H */ |
389 | |