KXmlGui

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

KDE's Doxygen guidelines are available online.