File indexing completed on 2024-12-01 12:40:42
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org> 0004 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #ifndef kxmlguifactory_h 0010 #define kxmlguifactory_h 0011 0012 #include <kxmlgui_export.h> 0013 0014 #include <QObject> 0015 #include <memory> 0016 0017 class QAction; 0018 class KXMLGUIFactoryPrivate; 0019 class KXMLGUIClient; 0020 class KXMLGUIBuilder; 0021 0022 class QDomAttr; 0023 class QDomDocument; 0024 class QDomElement; 0025 class QDomNode; 0026 class QDomNamedNodeMap; 0027 0028 namespace KXMLGUI 0029 { 0030 struct MergingIndex; 0031 struct ContainerNode; 0032 struct ContainerClient; 0033 class BuildHelper; 0034 } 0035 0036 /** 0037 * @class KXMLGUIFactory kxmlguifactory.h KXMLGUIFactory 0038 * 0039 * KXMLGUIFactory, together with KXMLGUIClient objects, can be used to create 0040 * a GUI of container widgets (like menus, toolbars, etc.) and container items 0041 * (menu items, toolbar buttons, etc.) from an XML document and action objects. 0042 * 0043 * Each KXMLGUIClient represents a part of the GUI, composed from containers and 0044 * actions. KXMLGUIFactory takes care of building (with the help of a KXMLGUIBuilder) 0045 * and merging the GUI from an unlimited number of clients. 0046 * 0047 * Each client provides XML through a QDomDocument and actions through a 0048 * KActionCollection . The XML document contains the rules for how to merge the 0049 * GUI. 0050 * 0051 * KXMLGUIFactory processes the DOM tree provided by a client and plugs in the client's actions, 0052 * according to the XML and the merging rules of previously inserted clients. Container widgets 0053 * are built via a KXMLGUIBuilder , which has to be provided with the KXMLGUIFactory constructor. 0054 */ 0055 class KXMLGUI_EXPORT KXMLGUIFactory : public QObject 0056 { 0057 friend class KXMLGUI::BuildHelper; 0058 Q_OBJECT 0059 public: 0060 /** 0061 * Constructs a KXMLGUIFactory. The provided @p builder KXMLGUIBuilder will be called 0062 * for creating and removing container widgets, when clients are added/removed from the GUI. 0063 * 0064 * Note that the ownership of the given KXMLGUIBuilder object won't be transferred to this 0065 * KXMLGUIFactory, so you have to take care of deleting it properly. 0066 */ 0067 explicit KXMLGUIFactory(KXMLGUIBuilder *builder, QObject *parent = nullptr); 0068 0069 /** 0070 * Destructor 0071 */ 0072 ~KXMLGUIFactory() override; 0073 0074 // XXX move to somewhere else? (Simon) 0075 /// @internal 0076 static QString readConfigFile(const QString &filename, const QString &componentName = QString()); 0077 /// @internal 0078 static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName = QString()); 0079 0080 /** 0081 * @internal 0082 * Find or create the ActionProperties element, used when saving custom action properties 0083 */ 0084 static QDomElement actionPropertiesElement(QDomDocument &doc); 0085 0086 /** 0087 * @internal 0088 * Find or create the element for a given action, by name. 0089 * Used when saving custom action properties 0090 */ 0091 static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create); 0092 0093 /** 0094 * Creates the GUI described by the QDomDocument of the client, 0095 * using the client's actions, and merges it with the previously 0096 * created GUI. 0097 * This also means that the order in which clients are added to the factory 0098 * is relevant; assuming that your application supports plugins, you should 0099 * first add your application to the factory and then the plugin, so that the 0100 * plugin's UI is merged into the UI of your application, and not the other 0101 * way round. 0102 */ 0103 void addClient(KXMLGUIClient *client); 0104 0105 /** 0106 * Removes the GUI described by the client, by unplugging all 0107 * provided actions and removing all owned containers (and storing 0108 * container state information in the given client) 0109 */ 0110 void removeClient(KXMLGUIClient *client); 0111 0112 void plugActionList(KXMLGUIClient *client, const QString &name, const QList<QAction *> &actionList); 0113 void unplugActionList(KXMLGUIClient *client, const QString &name); 0114 0115 /** 0116 * Returns a list of all clients currently added to this factory 0117 */ 0118 QList<KXMLGUIClient *> clients() const; 0119 0120 /** 0121 * Use this method to get access to a container widget with the name specified with @p containerName 0122 * and which is owned by the @p client. The container name is specified with a "name" attribute in the 0123 * XML document. 0124 * 0125 * This function is particularly useful for getting hold of a popupmenu defined in an XMLUI file. 0126 * For instance: 0127 * \code 0128 * QMenu *popup = static_cast<QMenu*>(guiFactory()->container("my_popup",this)); 0129 * \endcode 0130 * where @p "my_popup" is the name of the menu in the XMLUI file, and 0131 * @p "this" is XMLGUIClient which owns the popupmenu (e.g. the mainwindow, or the part, or the plugin...) 0132 * 0133 * @param containerName Name of the container widget 0134 * @param client Owner of the container widget 0135 * @param useTagName Specifies whether to compare the specified name with the name attribute or 0136 * the tag name. 0137 * 0138 * This method may return nullptr if no container with the given name exists or is not owned by the client. 0139 */ 0140 QWidget *container(const QString &containerName, KXMLGUIClient *client, bool useTagName = false); 0141 0142 QList<QWidget *> containers(const QString &tagName); 0143 0144 /** 0145 * Use this method to free all memory allocated by the KXMLGUIFactory. This deletes the internal node 0146 * tree and therefore resets the internal state of the class. Please note that the actual GUI is 0147 * NOT touched at all, meaning no containers are deleted nor any actions unplugged. That is 0148 * something you have to do on your own. So use this method only if you know what you are doing :-) 0149 * 0150 * (also note that this will call KXMLGUIClient::setFactory(nullptr) for all inserted clients) 0151 */ 0152 void reset(); 0153 0154 /** 0155 * Use this method to free all memory allocated by the KXMLGUIFactory for a specific container, 0156 * including all child containers and actions. This deletes the internal node subtree for the 0157 * specified container. The actual GUI is not touched, no containers are deleted or any actions 0158 * unplugged. Use this method only if you know what you are doing :-) 0159 * 0160 * (also note that this will call KXMLGUIClient::setFactory(nullptr) for all clients of the 0161 * container) 0162 */ 0163 void resetContainer(const QString &containerName, bool useTagName = false); 0164 0165 /** 0166 * Use this method to reset and reread action properties (shortcuts, etc.) for all actions. 0167 * This is needed, for example, when you change shortcuts scheme at runtime. 0168 */ 0169 void refreshActionProperties(); 0170 0171 public Q_SLOTS: 0172 #if KXMLGUI_ENABLE_DEPRECATED_SINCE(5, 84) 0173 /** 0174 * Shows a dialog (KShortcutsDialog) that lists every action in this factory, 0175 * and which can be used to change the shortcuts associated with each action. 0176 * 0177 * This slot can be connected directly to the action to configure shortcuts. 0178 * This is very simple to do, for example: 0179 * @code 0180 * KStandardAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection()); 0181 * @endcode 0182 * Or if you want to use the pointer-to-member-function signal/slot syntax 0183 * (which is generally preferred as it has compile-time type checking) you 0184 * can use: 0185 * @code 0186 * auto shortcutsSlot = [this]() { 0187 * guiFactory()->configureShortcuts(); 0188 * }; 0189 * KStandardAction::keyBindings(guiFactory(), shortcutsSlot, actionCollection()); 0190 * 0191 * // Alternatively, since 5.84, you can use: 0192 * KStandardAction::keyBindings(guiFactory(), &KXMLGUIFactory::showConfigureShortcutsDialog, actionCollection()); 0193 * @endcode 0194 * 0195 * @param bAllowLetterShortcuts Set to @c false if unmodified alphanumeric keys 0196 * ('A', '1', etc.) are not permissible shortcuts; defaults to @c true 0197 * @param bSaveSettings if @c true, the settings will also be saved back to 0198 * the @c *ui.rc file which they were initially read from; defaults to @c true 0199 * 0200 * @deprecated since 5.84, use @ref KXMLGUIFactory::showConfigureShortcutsDialog() instead. 0201 * If your code checked the return value of this method (e.g. to run some extra code if the 0202 * dialog was accepted), you can port that code by connecting to the @c shortcutsSaved() 0203 * signal before calling @c showConfigureShortcutsDialog() (see the latter's API docs for 0204 * a code example). 0205 */ 0206 KXMLGUI_DEPRECATED_VERSION(5, 84, "Use KXMLGUIFactory::showConfigureShortcutsDialog() instead.") 0207 int configureShortcuts(bool bAllowLetterShortcuts = true, bool bSaveSettings = true); 0208 #endif 0209 0210 /** 0211 * Shows a dialog (KShortcutsDialog) that lists every action in this factory, 0212 * and which can be used to change the shortcuts associated with each action. 0213 * 0214 * This slot can be connected directly to the configure shortcuts action, 0215 * for example: 0216 * @code 0217 * KStandardAction::keyBindings(guiFactory(), &KXMLGUIFactory::showConfigureShortcutsDialog, actionCollection()); 0218 * @endcode 0219 * 0220 * This method constructs a KShortcutsDialog with the default arguments 0221 * (KShortcutsEditor::AllActions and KShortcutsEditor::LetterShortcutsAllowed). 0222 * 0223 * @see KShortcutsDialog, KShortcutsEditor::ActionTypes, KShortcutsEditor::LetterShortcuts 0224 * 0225 * By default the changes will be saved back to the @c *ui.rc file 0226 * which they were initially read from. 0227 * 0228 * If you need to run some extra code if the dialog is accepted and the settings 0229 * are saved, you can simply connect to the @ref KXMLGUIFactory::shortcutsSaved() 0230 * signal before calling this method, for example: 0231 * @code 0232 * connect(guiFactory(), &KXMLGUIFactory::shortcutsSaved, this, &MyClass::slotShortcutSaved); 0233 * guiFactory()->showConfigureShortcutsDialog(); 0234 * @endcode 0235 * 0236 * @since 5.84 0237 */ 0238 void showConfigureShortcutsDialog(); 0239 0240 void changeShortcutScheme(const QString &scheme); 0241 0242 Q_SIGNALS: 0243 void clientAdded(KXMLGUIClient *client); 0244 void clientRemoved(KXMLGUIClient *client); 0245 0246 /** 0247 * Emitted when the factory is currently making changes to the GUI, 0248 * i.e. adding or removing clients. 0249 * makingChanges(true) is emitted before any change happens, and 0250 * makingChanges(false) is emitted after the change is done. 0251 * This allows e.g. KMainWindow to know that the GUI is 0252 * being changed programmatically and not by the user (so there is no reason to 0253 * save toolbar settings afterwards). 0254 * @since 4.1.3 0255 */ 0256 void makingChanges(bool); 0257 0258 /** 0259 * Emitted when the shortcuts have been saved (i.e. the user accepted the dialog). 0260 * 0261 * If you're using multiple instances of the same KXMLGUIClient, you probably want to 0262 * connect to this signal and call @c KXMLGUIClient::reloadXML() for each of your 0263 * KXMLGUIClients, so that the other instances update their shortcuts settings. 0264 * 0265 * @since 5.79 0266 */ 0267 void shortcutsSaved(); 0268 0269 private: 0270 /// Internal, called by KXMLGUIClient destructor 0271 KXMLGUI_NO_EXPORT void forgetClient(KXMLGUIClient *client); 0272 0273 private: 0274 friend class KXMLGUIClient; 0275 std::unique_ptr<KXMLGUIFactoryPrivate> const d; 0276 }; 0277 0278 #endif