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