File indexing completed on 2024-12-01 12:40:42
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2000 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 KXMLGUICLIENT_H 0010 #define KXMLGUICLIENT_H 0011 0012 #include <kxmlgui_export.h> 0013 0014 #include <QStringList> 0015 #include <memory> 0016 0017 class QDomDocument; 0018 class QDomElement; 0019 class QWidget; 0020 0021 class QAction; 0022 class KActionCollection; 0023 class KXMLGUIClientPrivate; 0024 class KXMLGUIFactory; 0025 class KXMLGUIBuilder; 0026 0027 namespace KDEPrivate 0028 { 0029 class KEditToolBarWidget; 0030 } 0031 0032 /** 0033 * @class KXMLGUIClient kxmlguiclient.h KXMLGUIClient 0034 * 0035 * A KXMLGUIClient can be used with KXMLGUIFactory to create a 0036 * GUI from actions and an XML document, and can be dynamically merged 0037 * with other KXMLGUIClients. 0038 */ 0039 class KXMLGUI_EXPORT KXMLGUIClient 0040 { 0041 friend class KDEPrivate::KEditToolBarWidget; // for setXMLFile(3 args) 0042 public: 0043 /** 0044 * Constructs a KXMLGUIClient which can be used with a 0045 * KXMLGUIFactory to create a GUI from actions and an XML document, and 0046 * which can be dynamically merged with other KXMLGUIClients. 0047 */ 0048 KXMLGUIClient(); 0049 0050 /** 0051 * Constructs a KXMLGUIClient which can be used with a KXMLGUIFactory 0052 * to create a GUI from actions and an XML document, 0053 * and which can be dynamically merged with other KXMLGUIClients. 0054 * 0055 * This constructor takes an additional @p parent argument, which makes 0056 * the client a child client of the parent. 0057 * 0058 * Child clients are automatically added to the GUI if the parent is added. 0059 * 0060 */ 0061 explicit KXMLGUIClient(KXMLGUIClient *parent); 0062 0063 /** 0064 * Destructs the KXMLGUIClient. 0065 * 0066 * If the client was in a factory, the factory is NOT informed about the client 0067 * being removed. This is a feature, it makes window destruction fast (the xmlgui 0068 * is not updated for every client being deleted), but if you want to simply remove 0069 * one client and to keep using the window, make sure to call factory->removeClient(client) 0070 * before deleting the client. 0071 */ 0072 virtual ~KXMLGUIClient(); 0073 0074 /** 0075 * Retrieves an action of the client by name. If not found, it looks in its child clients. 0076 * This method is provided for convenience, as it uses actionCollection() 0077 * to get the action object. 0078 */ 0079 QAction *action(const char *name) const; 0080 0081 /** 0082 * Retrieves an action for a given QDomElement. The default 0083 * implementation uses the "name" attribute to query the action 0084 * object via the other action() method. 0085 */ 0086 virtual QAction *action(const QDomElement &element) const; 0087 0088 /** 0089 * Retrieves the entire action collection for the GUI client. 0090 */ 0091 virtual KActionCollection *actionCollection() const; 0092 0093 /** 0094 * @return The component name for this GUI client. 0095 */ 0096 virtual QString componentName() const; 0097 0098 /** 0099 * @return The parsed XML in a QDomDocument, set by 0100 * setXMLFile() or setXML(). 0101 * This document describes the layout of the GUI. 0102 */ 0103 virtual QDomDocument domDocument() const; 0104 0105 /** 0106 * This will return the name of the XML file as set by setXMLFile(). 0107 * If setXML() is used directly, then this will return an empty string. 0108 * 0109 * The filename that this returns is obvious for components as each 0110 * component has exactly one XML file. In non-components, however, 0111 * there are usually two: the global file and the local file. This 0112 * function doesn't really care about that, though. It will always 0113 * return the last XML file set. This, in almost all cases, will 0114 * be the local XML file. 0115 * 0116 * @return The name of the XML file or QString() 0117 */ 0118 virtual QString xmlFile() const; 0119 0120 virtual QString localXMLFile() const; 0121 0122 /** 0123 * @internal 0124 */ 0125 void setXMLGUIBuildDocument(const QDomDocument &doc); 0126 /** 0127 * @internal 0128 */ 0129 QDomDocument xmlguiBuildDocument() const; 0130 0131 /** 0132 * This method is called by the KXMLGUIFactory as soon as the client 0133 * is added to the KXMLGUIFactory's GUI. 0134 */ 0135 void setFactory(KXMLGUIFactory *factory); 0136 /** 0137 * Retrieves a pointer to the KXMLGUIFactory this client is 0138 * associated with (will return nullptr if the client's GUI has not been built 0139 * by a KXMLGUIFactory. 0140 */ 0141 KXMLGUIFactory *factory() const; 0142 0143 /** 0144 * KXMLGUIClients can form a simple child/parent object tree. This 0145 * method returns a pointer to the parent client or nullptr if it has no 0146 * parent client assigned. 0147 */ 0148 KXMLGUIClient *parentClient() const; 0149 0150 /** 0151 * Use this method to make a client a child client of another client. 0152 * Usually you don't need to call this method, as it is called 0153 * automatically when using the second constructor, which takes a 0154 * parent argument. 0155 */ 0156 void insertChildClient(KXMLGUIClient *child); 0157 0158 /** 0159 * Removes the given @p child from the client's children list. 0160 */ 0161 void removeChildClient(KXMLGUIClient *child); 0162 0163 /** 0164 * Retrieves a list of all child clients. 0165 */ 0166 QList<KXMLGUIClient *> childClients(); 0167 0168 /** 0169 * A client can have an own KXMLGUIBuilder. 0170 * Use this method to assign your builder instance to the client (so that the 0171 * KXMLGUIFactory can use it when building the client's GUI) 0172 * 0173 * Client specific guibuilders are useful if you want to create 0174 * custom container widgets for your GUI. 0175 */ 0176 void setClientBuilder(KXMLGUIBuilder *builder); 0177 0178 /** 0179 * Retrieves the client's GUI builder or nullptr if no client specific 0180 * builder has been assigned via setClientBuilder() 0181 */ 0182 KXMLGUIBuilder *clientBuilder() const; 0183 0184 /** 0185 * Forces this client to re-read its XML resource file. This is 0186 * intended to be used when you know that the resource file has 0187 * changed and you will soon be rebuilding the GUI. This will only have 0188 * an effect if the client is then removed and re-added to the factory. 0189 * 0190 * This method is only for child clients, do not call it for a mainwindow! 0191 * For a mainwindow, use loadStandardsXmlFile + setXmlFile(xmlFile()) instead. 0192 */ 0193 void reloadXML(); 0194 0195 /** 0196 * ActionLists are a way for XMLGUI to support dynamic lists of 0197 * actions. E.g. if you are writing a file manager, and there is a 0198 * menu file whose contents depend on the mimetype of the file that 0199 * is selected, then you can achieve this using ActionLists. It 0200 * works as follows: 0201 * In your xxxui.rc file ( the one that you set in setXMLFile() / pass to setupGUI() 0202 * ), you put a tag <tt>\<ActionList name="xxx"\></tt>. 0203 * 0204 * Example: 0205 * \code 0206 * <gui name="xxx_part" version="1"> 0207 * <MenuBar> 0208 * <Menu name="file"> 0209 * ... <!-- some useful actions--> 0210 * <ActionList name="xxx_file_actionlist" /> 0211 * ... <!-- even more useful actions--> 0212 * </Menu> 0213 * ... 0214 * </MenuBar> 0215 * </gui> 0216 * \endcode 0217 * 0218 * This tag will get expanded to a list of actions. In the example 0219 * above ( a file manager with a dynamic file menu ), you would call 0220 * \code 0221 * QList<QAction*> file_actions; 0222 * for( ... ) 0223 * if( ... ) 0224 * file_actions.append( cool_action ); 0225 * unplugActionList( "xxx_file_actionlist" ); 0226 * plugActionList( "xxx_file_actionlist", file_actions ); 0227 * \endcode 0228 * every time a file is selected, unselected or ... 0229 * 0230 * \note You should not call KXmlGuiWindow::createGUI() after calling this 0231 * function. In fact, that would remove the newly added 0232 * actionlists again... 0233 * \note Forgetting to call unplugActionList() before 0234 * plugActionList() would leave the previous actions in the 0235 * menu too.. 0236 * \see unplugActionList() 0237 */ 0238 void plugActionList(const QString &name, const QList<QAction *> &actionList); 0239 0240 /** 0241 * Unplugs the action list \p name from the XMLGUI. 0242 * Calling this removes the specified action list, i.e. this is the 0243 * complement to plugActionList(). See plugActionList() for a more 0244 * detailed example. 0245 * \see plugActionList() 0246 */ 0247 void unplugActionList(const QString &name); 0248 0249 static QString findMostRecentXMLFile(const QStringList &files, QString &doc); 0250 0251 void addStateActionEnabled(const QString &state, const QString &action); 0252 0253 void addStateActionDisabled(const QString &state, const QString &action); 0254 0255 enum ReverseStateChange { StateNoReverse, StateReverse }; 0256 struct StateChange { 0257 QStringList actionsToEnable; 0258 QStringList actionsToDisable; 0259 }; 0260 0261 StateChange getActionsToChangeForState(const QString &state); 0262 0263 void beginXMLPlug(QWidget *); 0264 void endXMLPlug(); 0265 void prepareXMLUnplug(QWidget *); 0266 0267 /** 0268 * Sets a new xmlFile() and localXMLFile(). The purpose of this public 0269 * method is to allow non-inherited objects to replace the ui definition 0270 * of an embedded client with a customized version. It corresponds to the 0271 * usual calls to setXMLFile() and setLocalXMLFile(). 0272 * 0273 * @param xmlfile The xml file to use. Contrary to setXMLFile(), this 0274 * must be an absolute file path. 0275 * @param localxmlfile The local xml file to set. This should be the full path 0276 * to a writeable file, usually using QStandardPaths::writableLocation. 0277 * You can set this to QString(), but no user changes to shortcuts / toolbars 0278 * will be possible in this case. 0279 * @param merge Whether to merge with the global document 0280 * 0281 * @note If in any doubt whether you need this or not, use setXMLFile() 0282 * and setLocalXMLFile(), instead of this function. 0283 * @note Just like setXMLFile(), this function has to be called before 0284 * the client is added to a KXMLGUIFactory in order to have an 0285 * effect. 0286 * 0287 * @see setLocalXMLFile() 0288 * @since 4.4 0289 */ 0290 void replaceXMLFile(const QString &xmlfile, const QString &localxmlfile, bool merge = false); 0291 0292 /** 0293 * Returns the version number of the given xml data (belonging to an xml rc file) 0294 * 0295 * @since 5.73 0296 */ 0297 static QString findVersionNumber(const QString &xml); 0298 0299 protected: 0300 /** 0301 * Sets the component name for this part. 0302 * 0303 * Call this first in the inherited class constructor. 0304 * (At least before setXMLFile().) 0305 * @param componentName the name of the directory where the XMLGUI files will be found 0306 * @param componentDisplayName a user-visible name (e.g. for the toolbar editor) 0307 */ 0308 virtual void setComponentName(const QString &componentName, const QString &componentDisplayName); 0309 0310 /** 0311 * Sets the name of the rc file containing the XML for the part. 0312 * 0313 * Call this in the inherited class constructor, for parts and plugins. 0314 * @note For mainwindows, don't call this, pass the name of the xml file 0315 * to KXmlGuiWindow::setupGUI() or KXmlGuiWindow::createGUI(). 0316 * 0317 * @param file Either an absolute path for the file, or simply the 0318 * filename. See below for details. 0319 * If you pass an absolute path here, make sure to also call 0320 * setLocalXMLFile, otherwise toolbar editing won't work. 0321 * @param merge Whether to merge with the global document. 0322 * @param setXMLDoc Specify whether to call setXML. Default is true. 0323 * 0324 * The preferred way to call this method is with a simple filename for the @p file argument. 0325 * 0326 * Since KF 5.1, the file will then be assumed to be installed in DATADIR/kxmlgui5/, under a directory 0327 * named after the component name. 0328 * You should use ${KDE_INSTALL_KXMLGUI5DIR}/componentname in your CMakeLists.txt file, to install 0329 * the .rc file(s). 0330 * 0331 * Since KF 5.4, the file will then be assumed to be installed in a Qt resource in :/kxmlgui5/, 0332 * under a directory named after the component name. 0333 * 0334 * Compatibility notes: 0335 * Fallback lookups exist to older locations: DATADIR/componentname/file and DATADIR/file. 0336 * The latter was there so that setXMLFile("componentname/filename") worked (but this was 0337 * undocumented). Do not do this anymore after porting to KDE_INSTALL_KXMLGUI5DIR, use 0338 * setComponentName("componentname") and setXMLFile("filename"). 0339 **/ 0340 virtual void setXMLFile(const QString &file, bool merge = false, bool setXMLDoc = true); 0341 0342 /** 0343 * Return the full path to the ui_standards.rc, might return a resource path. 0344 * @return full path to ui_standards.rc, always non-empty. 0345 * @since 5.16 0346 */ 0347 static QString standardsXmlFileLocation(); 0348 0349 /** 0350 * Load the ui_standards.rc file. Usually followed by setXMLFile(xmlFile, true), for merging. 0351 * @since 4.6 0352 */ 0353 void loadStandardsXmlFile(); 0354 0355 /** 0356 * Set the full path to the "local" xml file, the one used for saving 0357 * toolbar and shortcut changes. You normally don't need to call this, 0358 * if you pass a simple filename to setXMLFile. 0359 */ 0360 virtual void setLocalXMLFile(const QString &file); 0361 0362 /** 0363 * Sets the XML for the part. 0364 * 0365 * Call this in the Part-inherited class constructor if you 0366 * don't call setXMLFile(). 0367 **/ 0368 virtual void setXML(const QString &document, bool merge = false); 0369 0370 /** 0371 * Sets the Document for the part, describing the layout of the GUI. 0372 * 0373 * Call this in the Part-inherited class constructor if you don't call 0374 * setXMLFile() or setXML(). 0375 * 0376 * @warning Using this method is not recommended. Many code paths 0377 * lead to reloading from the XML file on disk. And editing toolbars requires 0378 * that the result is written to disk anyway, and loaded from there the next time. 0379 * 0380 * For application-specific changes to a client's XML, it is a better idea to 0381 * save the modified dom document to an app/default-client.xml and define a local-xml-file 0382 * to something specific like app/local-client.xml, using replaceXMLFile(). 0383 * See kdepimlibs/kontactinterface/plugin.cpp for an example. 0384 */ 0385 virtual void setDOMDocument(const QDomDocument &document, bool merge = false); 0386 0387 /** 0388 * Actions can collectively be assigned a "State". To accomplish this 0389 * the respective actions are tagged as \<enable\> or \<disable\> in 0390 * a \<State\> \</State\> group of the XMLfile. During program execution the 0391 * programmer can call stateChanged() to set actions to a defined state. 0392 * 0393 * @param newstate Name of a State in the XMLfile. 0394 * @param reverse If the flag reverse is set to StateReverse, the State is reversed. 0395 * (actions to be enabled will be disabled and action to be disabled will be enabled) 0396 * Default is reverse=false. 0397 */ 0398 virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse); 0399 0400 // KDE5 TODO: virtual void loadActionLists() {}, called when the guiclient is added to the xmlgui factory 0401 0402 protected: 0403 virtual void virtual_hook(int id, void *data); 0404 0405 private: 0406 // TODO Post KF 5.79 make std::unique_ptr, when there is a Konsole released with bug:432421 fixed 0407 // std::unique_ptr<KXMLGUIClientPrivate> const d; 0408 KXMLGUIClientPrivate *const d; 0409 }; 0410 0411 #endif