1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999 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 kxmlguifactory_h
10#define kxmlguifactory_h
11
12#include <kxmlgui_export.h>
13
14#include <QObject>
15#include <memory>
16
17class QAction;
18class KXMLGUIFactoryPrivate;
19class KXMLGUIClient;
20class KXMLGUIBuilder;
21
22class QDomAttr;
23class QDomDocument;
24class QDomElement;
25class QDomNode;
26class QDomNamedNodeMap;
27
28namespace KXMLGUI
29{
30struct MergingIndex;
31struct ContainerNode;
32struct ContainerClient;
33class BuildHelper;
34}
35
36/**
37 * @class KXMLGUIFactory kxmlguifactory.h KXMLGUIFactory
38 *
39 * KXMLGUIFactory, together with KXMLGUIClient objects, can be used to create
40 * a GUI of container widgets (like menus, toolbars, etc.) and container items
41 * (menu items, toolbar buttons, etc.) from an XML document and action objects.
42 *
43 * Each KXMLGUIClient represents a part of the GUI, composed from containers and
44 * actions. KXMLGUIFactory takes care of building (with the help of a KXMLGUIBuilder)
45 * and merging the GUI from an unlimited number of clients.
46 *
47 * Each client provides XML through a QDomDocument and actions through a
48 * KActionCollection . The XML document contains the rules for how to merge the
49 * GUI.
50 *
51 * KXMLGUIFactory processes the DOM tree provided by a client and plugs in the client's actions,
52 * according to the XML and the merging rules of previously inserted clients. Container widgets
53 * are built via a KXMLGUIBuilder , which has to be provided with the KXMLGUIFactory constructor.
54 */
55class KXMLGUI_EXPORT KXMLGUIFactory : public QObject
56{
57 friend class KXMLGUI::BuildHelper;
58 Q_OBJECT
59public:
60 /**
61 * Constructs a KXMLGUIFactory. The provided @p builder KXMLGUIBuilder will be called
62 * for creating and removing container widgets, when clients are added/removed from the GUI.
63 *
64 * Note that the ownership of the given KXMLGUIBuilder object won't be transferred to this
65 * KXMLGUIFactory, so you have to take care of deleting it properly.
66 */
67 explicit KXMLGUIFactory(KXMLGUIBuilder *builder, QObject *parent = nullptr);
68
69 /**
70 * Destructor
71 */
72 ~KXMLGUIFactory() override;
73
74 // XXX move to somewhere else? (Simon)
75 /// @internal
76 static QString readConfigFile(const QString &filename, const QString &componentName = QString());
77 /// @internal
78 static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName = QString());
79
80 /**
81 * @internal
82 * Find or create the ActionProperties element, used when saving custom action properties
83 */
84 static QDomElement actionPropertiesElement(QDomDocument &doc);
85
86 /**
87 * @internal
88 * Find or create the element for a given action, by name.
89 * Used when saving custom action properties
90 */
91 static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create);
92
93 /**
94 * Creates the GUI described by the QDomDocument of the client,
95 * using the client's actions, and merges it with the previously
96 * created GUI.
97 * This also means that the order in which clients are added to the factory
98 * is relevant; assuming that your application supports plugins, you should
99 * first add your application to the factory and then the plugin, so that the
100 * plugin's UI is merged into the UI of your application, and not the other
101 * way round.
102 */
103 void addClient(KXMLGUIClient *client);
104
105 /**
106 * Removes the GUI described by the client, by unplugging all
107 * provided actions and removing all owned containers (and storing
108 * container state information in the given client)
109 */
110 void removeClient(KXMLGUIClient *client);
111
112 void plugActionList(KXMLGUIClient *client, const QString &name, const QList<QAction *> &actionList);
113 void unplugActionList(KXMLGUIClient *client, const QString &name);
114
115 /**
116 * Returns a list of all clients currently added to this factory
117 */
118 QList<KXMLGUIClient *> clients() const;
119
120 /**
121 * Use this method to get access to a container widget with the name specified with @p containerName
122 * and which is owned by the @p client. The container name is specified with a "name" attribute in the
123 * XML document.
124 *
125 * This function is particularly useful for getting hold of a popupmenu defined in an XMLUI file.
126 * For instance:
127 * \code
128 * QMenu *popup = static_cast<QMenu*>(guiFactory()->container("my_popup",this));
129 * \endcode
130 * where @p "my_popup" is the name of the menu in the XMLUI file, and
131 * @p "this" is XMLGUIClient which owns the popupmenu (e.g. the mainwindow, or the part, or the plugin...)
132 *
133 * @param containerName Name of the container widget
134 * @param client Owner of the container widget
135 * @param useTagName Specifies whether to compare the specified name with the name attribute or
136 * the tag name.
137 *
138 * This method may return nullptr if no container with the given name exists or is not owned by the client.
139 */
140 QWidget *container(const QString &containerName, KXMLGUIClient *client, bool useTagName = false);
141
142 QList<QWidget *> containers(const QString &tagName);
143
144 /**
145 * Use this method to free all memory allocated by the KXMLGUIFactory. This deletes the internal node
146 * tree and therefore resets the internal state of the class. Please note that the actual GUI is
147 * NOT touched at all, meaning no containers are deleted nor any actions unplugged. That is
148 * something you have to do on your own. So use this method only if you know what you are doing :-)
149 *
150 * (also note that this will call KXMLGUIClient::setFactory(nullptr) for all inserted clients)
151 */
152 void reset();
153
154 /**
155 * Use this method to free all memory allocated by the KXMLGUIFactory for a specific container,
156 * including all child containers and actions. This deletes the internal node subtree for the
157 * specified container. The actual GUI is not touched, no containers are deleted or any actions
158 * unplugged. Use this method only if you know what you are doing :-)
159 *
160 * (also note that this will call KXMLGUIClient::setFactory(nullptr) for all clients of the
161 * container)
162 */
163 void resetContainer(const QString &containerName, bool useTagName = false);
164
165 /**
166 * Use this method to reset and reread action properties (shortcuts, etc.) for all actions.
167 * This is needed, for example, when you change shortcuts scheme at runtime.
168 */
169 void refreshActionProperties();
170
171public Q_SLOTS:
172 /**
173 * Shows a dialog (KShortcutsDialog) that lists every action in this factory,
174 * and which can be used to change the shortcuts associated with each action.
175 *
176 * This slot can be connected directly to the configure shortcuts action,
177 * for example:
178 * @code
179 * KStandardAction::keyBindings(guiFactory(), &KXMLGUIFactory::showConfigureShortcutsDialog, actionCollection());
180 * @endcode
181 *
182 * This method constructs a KShortcutsDialog with the default arguments
183 * (KShortcutsEditor::AllActions and KShortcutsEditor::LetterShortcutsAllowed).
184 *
185 * @see KShortcutsDialog, KShortcutsEditor::ActionTypes, KShortcutsEditor::LetterShortcuts
186 *
187 * By default the changes will be saved back to the @c *ui.rc file
188 * which they were initially read from.
189 *
190 * If you need to run some extra code if the dialog is accepted and the settings
191 * are saved, you can simply connect to the @ref KXMLGUIFactory::shortcutsSaved()
192 * signal before calling this method, for example:
193 * @code
194 * connect(guiFactory(), &KXMLGUIFactory::shortcutsSaved, this, &MyClass::slotShortcutSaved);
195 * guiFactory()->showConfigureShortcutsDialog();
196 * @endcode
197 *
198 * @since 5.84
199 */
200 void showConfigureShortcutsDialog();
201
202 void changeShortcutScheme(const QString &scheme);
203
204Q_SIGNALS:
205 void clientAdded(KXMLGUIClient *client);
206 void clientRemoved(KXMLGUIClient *client);
207
208 /**
209 * Emitted when the factory is currently making changes to the GUI,
210 * i.e. adding or removing clients.
211 * makingChanges(true) is emitted before any change happens, and
212 * makingChanges(false) is emitted after the change is done.
213 * This allows e.g. KMainWindow to know that the GUI is
214 * being changed programmatically and not by the user (so there is no reason to
215 * save toolbar settings afterwards).
216 * @since 4.1.3
217 */
218 void makingChanges(bool);
219
220 /**
221 * Emitted when the shortcuts have been saved (i.e. the user accepted the dialog).
222 *
223 * If you're using multiple instances of the same KXMLGUIClient, you probably want to
224 * connect to this signal and call @c KXMLGUIClient::reloadXML() for each of your
225 * KXMLGUIClients, so that the other instances update their shortcuts settings.
226 *
227 * @since 5.79
228 */
229 void shortcutsSaved();
230
231private:
232 /// Internal, called by KXMLGUIClient destructor
233 KXMLGUI_NO_EXPORT void forgetClient(KXMLGUIClient *client);
234
235private:
236 friend class KXMLGUIClient;
237 std::unique_ptr<KXMLGUIFactoryPrivate> const d;
238};
239
240#endif
241

source code of kxmlgui/src/kxmlguifactory.h