1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org> |
4 | SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-only |
7 | */ |
8 | |
9 | #ifndef KXMLGUICLIENT_H |
10 | #define KXMLGUICLIENT_H |
11 | |
12 | #include <kxmlgui_export.h> |
13 | |
14 | #include <QStringList> |
15 | #include <memory> |
16 | |
17 | class QDomDocument; |
18 | class QDomElement; |
19 | class QWidget; |
20 | |
21 | class QAction; |
22 | class KActionCollection; |
23 | class KXMLGUIClientPrivate; |
24 | class KXMLGUIFactory; |
25 | class KXMLGUIBuilder; |
26 | |
27 | namespace KDEPrivate |
28 | { |
29 | class KEditToolBarWidget; |
30 | } |
31 | |
32 | /** |
33 | * @class KXMLGUIClient kxmlguiclient.h KXMLGUIClient |
34 | * |
35 | * A KXMLGUIClient can be used with KXMLGUIFactory to create a |
36 | * GUI from actions and an XML document, and can be dynamically merged |
37 | * with other KXMLGUIClients. |
38 | */ |
39 | class KXMLGUI_EXPORT KXMLGUIClient |
40 | { |
41 | friend class KDEPrivate::KEditToolBarWidget; // for setXMLFile(3 args) |
42 | public: |
43 | /** |
44 | * Constructs a KXMLGUIClient which can be used with a |
45 | * KXMLGUIFactory to create a GUI from actions and an XML document, and |
46 | * which can be dynamically merged with other KXMLGUIClients. |
47 | */ |
48 | KXMLGUIClient(); |
49 | |
50 | /** |
51 | * Constructs a KXMLGUIClient which can be used with a KXMLGUIFactory |
52 | * to create a GUI from actions and an XML document, |
53 | * and which can be dynamically merged with other KXMLGUIClients. |
54 | * |
55 | * This constructor takes an additional @p parent argument, which makes |
56 | * the client a child client of the parent. |
57 | * |
58 | * Child clients are automatically added to the GUI if the parent is added. |
59 | * |
60 | */ |
61 | explicit KXMLGUIClient(KXMLGUIClient *parent); |
62 | |
63 | /** |
64 | * Destructs the KXMLGUIClient. |
65 | * |
66 | * If the client was in a factory, the factory is NOT informed about the client |
67 | * being removed. This is a feature, it makes window destruction fast (the xmlgui |
68 | * is not updated for every client being deleted), but if you want to simply remove |
69 | * one client and to keep using the window, make sure to call factory->removeClient(client) |
70 | * before deleting the client. |
71 | */ |
72 | virtual ~KXMLGUIClient(); |
73 | |
74 | /** |
75 | * Retrieves an action of the client by name. If not found, it looks in its child clients. |
76 | * This method is provided for convenience, as it uses actionCollection() |
77 | * to get the action object. |
78 | * |
79 | * @since 6.0 |
80 | */ |
81 | QAction *action(const QString &name) const; |
82 | |
83 | /** |
84 | * Retrieves an action for a given QDomElement. The default |
85 | * implementation uses the "name" attribute to query the action |
86 | * object via the other action() method. |
87 | */ |
88 | virtual QAction *action(const QDomElement &element) const; |
89 | |
90 | /** |
91 | * Retrieves the entire action collection for the GUI client. |
92 | */ |
93 | virtual KActionCollection *actionCollection() const; |
94 | |
95 | /** |
96 | * @return The component name for this GUI client. |
97 | */ |
98 | virtual QString componentName() const; |
99 | |
100 | /** |
101 | * @return The parsed XML in a QDomDocument, set by |
102 | * setXMLFile() or setXML(). |
103 | * This document describes the layout of the GUI. |
104 | */ |
105 | virtual QDomDocument domDocument() const; |
106 | |
107 | /** |
108 | * This will return the name of the XML file as set by setXMLFile(). |
109 | * If setXML() is used directly, then this will return an empty string. |
110 | * |
111 | * The filename that this returns is obvious for components as each |
112 | * component has exactly one XML file. In non-components, however, |
113 | * there are usually two: the global file and the local file. This |
114 | * function doesn't really care about that, though. It will always |
115 | * return the last XML file set. This, in almost all cases, will |
116 | * be the local XML file. |
117 | * |
118 | * @return The name of the XML file or QString() |
119 | */ |
120 | virtual QString xmlFile() const; |
121 | |
122 | virtual QString localXMLFile() const; |
123 | |
124 | /** |
125 | * @internal |
126 | */ |
127 | void setXMLGUIBuildDocument(const QDomDocument &doc); |
128 | /** |
129 | * @internal |
130 | */ |
131 | QDomDocument xmlguiBuildDocument() const; |
132 | |
133 | /** |
134 | * This method is called by the KXMLGUIFactory as soon as the client |
135 | * is added to the KXMLGUIFactory's GUI. |
136 | */ |
137 | void setFactory(KXMLGUIFactory *factory); |
138 | /** |
139 | * Retrieves a pointer to the KXMLGUIFactory this client is |
140 | * associated with (will return nullptr if the client's GUI has not been built |
141 | * by a KXMLGUIFactory. |
142 | */ |
143 | KXMLGUIFactory *factory() const; |
144 | |
145 | /** |
146 | * KXMLGUIClients can form a simple child/parent object tree. This |
147 | * method returns a pointer to the parent client or nullptr if it has no |
148 | * parent client assigned. |
149 | */ |
150 | KXMLGUIClient *parentClient() const; |
151 | |
152 | /** |
153 | * Use this method to make a client a child client of another client. |
154 | * Usually you don't need to call this method, as it is called |
155 | * automatically when using the second constructor, which takes a |
156 | * parent argument. |
157 | */ |
158 | void insertChildClient(KXMLGUIClient *child); |
159 | |
160 | /** |
161 | * Removes the given @p child from the client's children list. |
162 | */ |
163 | void removeChildClient(KXMLGUIClient *child); |
164 | |
165 | /** |
166 | * Retrieves a list of all child clients. |
167 | */ |
168 | QList<KXMLGUIClient *> childClients(); |
169 | |
170 | /** |
171 | * A client can have an own KXMLGUIBuilder. |
172 | * Use this method to assign your builder instance to the client (so that the |
173 | * KXMLGUIFactory can use it when building the client's GUI) |
174 | * |
175 | * Client specific guibuilders are useful if you want to create |
176 | * custom container widgets for your GUI. |
177 | */ |
178 | void setClientBuilder(KXMLGUIBuilder *builder); |
179 | |
180 | /** |
181 | * Retrieves the client's GUI builder or nullptr if no client specific |
182 | * builder has been assigned via setClientBuilder() |
183 | */ |
184 | KXMLGUIBuilder *clientBuilder() const; |
185 | |
186 | /** |
187 | * Forces this client to re-read its XML resource file. This is |
188 | * intended to be used when you know that the resource file has |
189 | * changed and you will soon be rebuilding the GUI. This will only have |
190 | * an effect if the client is then removed and re-added to the factory. |
191 | * |
192 | * This method is only for child clients, do not call it for a mainwindow! |
193 | * For a mainwindow, use loadStandardsXmlFile + setXmlFile(xmlFile()) instead. |
194 | */ |
195 | void reloadXML(); |
196 | |
197 | /** |
198 | * ActionLists are a way for XMLGUI to support dynamic lists of |
199 | * actions. E.g. if you are writing a file manager, and there is a |
200 | * menu file whose contents depend on the mimetype of the file that |
201 | * is selected, then you can achieve this using ActionLists. It |
202 | * works as follows: |
203 | * In your xxxui.rc file ( the one that you set in setXMLFile() / pass to setupGUI() |
204 | * ), you put a tag <tt>\<ActionList name="xxx"\></tt>. |
205 | * |
206 | * Example: |
207 | * \code |
208 | * <gui name="xxx_part" version="1"> |
209 | * <MenuBar> |
210 | * <Menu name="file"> |
211 | * ... <!-- some useful actions--> |
212 | * <ActionList name="xxx_file_actionlist" /> |
213 | * ... <!-- even more useful actions--> |
214 | * </Menu> |
215 | * ... |
216 | * </MenuBar> |
217 | * </gui> |
218 | * \endcode |
219 | * |
220 | * This tag will get expanded to a list of actions. In the example |
221 | * above ( a file manager with a dynamic file menu ), you would call |
222 | * \code |
223 | * QList<QAction*> file_actions; |
224 | * for( ... ) |
225 | * if( ... ) |
226 | * file_actions.append( cool_action ); |
227 | * unplugActionList( "xxx_file_actionlist" ); |
228 | * plugActionList( "xxx_file_actionlist", file_actions ); |
229 | * \endcode |
230 | * every time a file is selected, unselected or ... |
231 | * |
232 | * \note You should not call KXmlGuiWindow::createGUI() after calling this |
233 | * function. In fact, that would remove the newly added |
234 | * actionlists again... |
235 | * \note Forgetting to call unplugActionList() before |
236 | * plugActionList() would leave the previous actions in the |
237 | * menu too.. |
238 | * \see unplugActionList() |
239 | */ |
240 | void plugActionList(const QString &name, const QList<QAction *> &actionList); |
241 | |
242 | /** |
243 | * Unplugs the action list \p name from the XMLGUI. |
244 | * Calling this removes the specified action list, i.e. this is the |
245 | * complement to plugActionList(). See plugActionList() for a more |
246 | * detailed example. |
247 | * \see plugActionList() |
248 | */ |
249 | void unplugActionList(const QString &name); |
250 | |
251 | static QString findMostRecentXMLFile(const QStringList &files, QString &doc); |
252 | |
253 | void addStateActionEnabled(const QString &state, const QString &action); |
254 | |
255 | void addStateActionDisabled(const QString &state, const QString &action); |
256 | |
257 | enum ReverseStateChange { StateNoReverse, StateReverse }; |
258 | struct StateChange { |
259 | QStringList actionsToEnable; |
260 | QStringList actionsToDisable; |
261 | }; |
262 | |
263 | StateChange getActionsToChangeForState(const QString &state); |
264 | |
265 | void beginXMLPlug(QWidget *); |
266 | void endXMLPlug(); |
267 | void prepareXMLUnplug(QWidget *); |
268 | |
269 | /** |
270 | * Sets a new xmlFile() and localXMLFile(). The purpose of this public |
271 | * method is to allow non-inherited objects to replace the ui definition |
272 | * of an embedded client with a customized version. It corresponds to the |
273 | * usual calls to setXMLFile() and setLocalXMLFile(). |
274 | * |
275 | * @param xmlfile The xml file to use. Contrary to setXMLFile(), this |
276 | * must be an absolute file path. |
277 | * @param localxmlfile The local xml file to set. This should be the full path |
278 | * to a writeable file, usually using QStandardPaths::writableLocation. |
279 | * You can set this to QString(), but no user changes to shortcuts / toolbars |
280 | * will be possible in this case. |
281 | * @param merge Whether to merge with the global document |
282 | * |
283 | * @note If in any doubt whether you need this or not, use setXMLFile() |
284 | * and setLocalXMLFile(), instead of this function. |
285 | * @note Just like setXMLFile(), this function has to be called before |
286 | * the client is added to a KXMLGUIFactory in order to have an |
287 | * effect. |
288 | * |
289 | * @see setLocalXMLFile() |
290 | * @since 4.4 |
291 | */ |
292 | void replaceXMLFile(const QString &xmlfile, const QString &localxmlfile, bool merge = false); |
293 | |
294 | /** |
295 | * Returns the version number of the given xml data (belonging to an xml rc file) |
296 | * |
297 | * @since 5.73 |
298 | */ |
299 | static QString findVersionNumber(const QString &xml); |
300 | |
301 | protected: |
302 | /** |
303 | * Sets the component name for this part. |
304 | * |
305 | * Call this first in the inherited class constructor. |
306 | * (At least before setXMLFile().) |
307 | * @param componentName the name of the directory where the XMLGUI files will be found |
308 | * @param componentDisplayName a user-visible name (e.g. for the toolbar editor) |
309 | */ |
310 | virtual void setComponentName(const QString &componentName, const QString &componentDisplayName); |
311 | |
312 | /** |
313 | * Sets the name of the rc file containing the XML for the part. |
314 | * |
315 | * Call this in the inherited class constructor, for parts and plugins. |
316 | * @note For mainwindows, don't call this, pass the name of the xml file |
317 | * to KXmlGuiWindow::setupGUI() or KXmlGuiWindow::createGUI(). |
318 | * |
319 | * @param file Either an absolute path for the file, or simply the |
320 | * filename. See below for details. |
321 | * If you pass an absolute path here, make sure to also call |
322 | * setLocalXMLFile, otherwise toolbar editing won't work. |
323 | * @param merge Whether to merge with the global document. |
324 | * @param setXMLDoc Specify whether to call setXML. Default is true. |
325 | * |
326 | * The preferred way to call this method is with a simple filename for the @p file argument. |
327 | * |
328 | * Since KF 5.1, the file will then be assumed to be installed in DATADIR/kxmlgui5/, under a directory |
329 | * named after the component name. |
330 | * You should use ${KDE_INSTALL_KXMLGUIDIR}/componentname in your CMakeLists.txt file, to install |
331 | * the .rc file(s). |
332 | * |
333 | * Since KF 5.4, the file will then be assumed to be installed in a Qt resource in :/kxmlgui5/, |
334 | * under a directory named after the component name. |
335 | **/ |
336 | virtual void setXMLFile(const QString &file, bool merge = false, bool setXMLDoc = true); |
337 | |
338 | /** |
339 | * Return the full path to the ui_standards.rc, might return a resource path. |
340 | * @return full path to ui_standards.rc, always non-empty. |
341 | * @since 5.16 |
342 | */ |
343 | static QString standardsXmlFileLocation(); |
344 | |
345 | /** |
346 | * Load the ui_standards.rc file. Usually followed by setXMLFile(xmlFile, true), for merging. |
347 | * @since 4.6 |
348 | */ |
349 | void loadStandardsXmlFile(); |
350 | |
351 | /** |
352 | * Set the full path to the "local" xml file, the one used for saving |
353 | * toolbar and shortcut changes. You normally don't need to call this, |
354 | * if you pass a simple filename to setXMLFile. |
355 | */ |
356 | virtual void setLocalXMLFile(const QString &file); |
357 | |
358 | /** |
359 | * Sets the XML for the part. |
360 | * |
361 | * Call this in the Part-inherited class constructor if you |
362 | * don't call setXMLFile(). |
363 | **/ |
364 | virtual void setXML(const QString &document, bool merge = false); |
365 | |
366 | /** |
367 | * Sets the Document for the part, describing the layout of the GUI. |
368 | * |
369 | * Call this in the Part-inherited class constructor if you don't call |
370 | * setXMLFile() or setXML(). |
371 | * |
372 | * @warning Using this method is not recommended. Many code paths |
373 | * lead to reloading from the XML file on disk. And editing toolbars requires |
374 | * that the result is written to disk anyway, and loaded from there the next time. |
375 | * |
376 | * For application-specific changes to a client's XML, it is a better idea to |
377 | * save the modified dom document to an app/default-client.xml and define a local-xml-file |
378 | * to something specific like app/local-client.xml, using replaceXMLFile(). |
379 | * See kdepimlibs/kontactinterface/plugin.cpp for an example. |
380 | */ |
381 | virtual void setDOMDocument(const QDomDocument &document, bool merge = false); |
382 | |
383 | /** |
384 | * Actions can collectively be assigned a "State". To accomplish this |
385 | * the respective actions are tagged as \<enable\> or \<disable\> in |
386 | * a \<State\> \</State\> group of the XMLfile. During program execution the |
387 | * programmer can call stateChanged() to set actions to a defined state. |
388 | * |
389 | * @param newstate Name of a State in the XMLfile. |
390 | * @param reverse If the flag reverse is set to StateReverse, the State is reversed. |
391 | * (actions to be enabled will be disabled and action to be disabled will be enabled) |
392 | * Default is reverse=false. |
393 | */ |
394 | virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse); |
395 | |
396 | // KDE5 TODO: virtual void loadActionLists() {}, called when the guiclient is added to the xmlgui factory |
397 | |
398 | protected: |
399 | virtual void virtual_hook(int id, void *data); |
400 | |
401 | private: |
402 | // TODO Post KF 5.79 make std::unique_ptr, when there is a Konsole released with bug:432421 fixed |
403 | // std::unique_ptr<KXMLGUIClientPrivate> const d; |
404 | KXMLGUIClientPrivate *const d; |
405 | }; |
406 | |
407 | #endif |
408 | |