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

source code of kxmlgui/src/kxmlguifactory.h