File indexing completed on 2024-06-16 04:15:41

0001 /* This file is part of the KDE libraries
0002    SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
0003    SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #ifndef kxmlguifactory_h
0009 #define kxmlguifactory_h
0010 
0011 #include <kritawidgetutils_export.h>
0012 
0013 #include <QObject>
0014 
0015 class QAction;
0016 class KisKXMLGUIFactoryPrivate;
0017 class KisKXMLGUIClient;
0018 class KisKXMLGUIBuilder;
0019 
0020 class QDomAttr;
0021 class QDomDocument;
0022 class QDomElement;
0023 class QDomNode;
0024 class QDomNamedNodeMap;
0025 
0026 namespace KisKXMLGUI
0027 {
0028 struct MergingIndex;
0029 struct ContainerNode;
0030 struct ContainerClient;
0031 class BuildHelper;
0032 }
0033 
0034 /**
0035  * KisKXMLGUIFactory, together with KisKXMLGUIClient objects, can be used to create
0036  * a GUI of container widgets (like menus, toolbars, etc.) and container items
0037  * (menu items, toolbar buttons, etc.) from an XML document and action objects.
0038  *
0039  * Each KisKXMLGUIClient represents a part of the GUI, composed from containers and
0040  * actions. KisKXMLGUIFactory takes care of building (with the help of a KisKXMLGUIBuilder)
0041  * and merging the GUI from an unlimited number of clients.
0042  *
0043  * Each client provides XML through a QDomDocument and actions through a
0044  * KisKActionCollection . The XML document contains the rules for how to merge the
0045  * GUI.
0046  *
0047  * KisKXMLGUIFactory processes the DOM tree provided by a client and plugs in the client's actions,
0048  * according to the XML and the merging rules of previously inserted clients. Container widgets
0049  * are built via a KisKXMLGUIBuilder , which has to be provided with the KisKXMLGUIFactory constructor.
0050  */
0051 class KRITAWIDGETUTILS_EXPORT KisKXMLGUIFactory : public QObject
0052 {
0053     friend class KisKXMLGUI::BuildHelper;
0054     Q_OBJECT
0055 public:
0056     /**
0057      * Constructs a KisKXMLGUIFactory. The provided @p builder KisKXMLGUIBuilder will be called
0058      * for creating and removing container widgets, when clients are added/removed from the GUI.
0059      *
0060      * Note that the ownership of the given KisKXMLGUIBuilder object won't be transferred to this
0061      * KisKXMLGUIFactory, so you have to take care of deleting it properly.
0062      */
0063     explicit KisKXMLGUIFactory(KisKXMLGUIBuilder *builder, QObject *parent = 0);
0064 
0065     /**
0066      * Destructor
0067      */
0068     ~KisKXMLGUIFactory() override;
0069 
0070     // XXX move to somewhere else? (Simon)
0071     /// @internal
0072     static QString readConfigFile(const QString &filename,
0073                                   const QString &componentName = QString());
0074     /// @internal
0075     static bool saveConfigFile(const QDomDocument &doc, const QString &filename,
0076                                const QString &componentName = QString());
0077 
0078     /**
0079      * @internal
0080      * Find or create the ActionProperties element, used when saving custom action properties
0081      */
0082     static QDomElement actionPropertiesElement(QDomDocument &doc);
0083 
0084     /**
0085      * @internal
0086      * Find or create the element for a given action, by name.
0087      * Used when saving custom action properties
0088      */
0089     static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create);
0090 
0091     /**
0092      * Creates the GUI described by the QDomDocument of the client,
0093      * using the client's actions, and merges it with the previously
0094      * created GUI.
0095      * This also means that the order in which clients are added to the factory
0096      * is relevant; assuming that your application supports plugins, you should
0097      * first add your application to the factory and then the plugin, so that the
0098      * plugin's UI is merged into the UI of your application, and not the other
0099      * way round.
0100      */
0101     void addClient(KisKXMLGUIClient *client);
0102 
0103     /**
0104      * Removes the GUI described by the client, by unplugging all
0105      * provided actions and removing all owned containers (and storing
0106      * container state information in the given client)
0107      */
0108     void removeClient(KisKXMLGUIClient *client);
0109 
0110     void plugActionList(KisKXMLGUIClient *client, const QString &name, const QList<QAction *> &actionList);
0111     void unplugActionList(KisKXMLGUIClient *client, const QString &name);
0112 
0113     /**
0114      * Returns a list of all clients currently added to this factory
0115      */
0116     QList<KisKXMLGUIClient *> clients() const;
0117 
0118     /**
0119      * Use this method to get access to a container widget with the name specified with @p containerName
0120      * and which is owned by the @p client. The container name is specified with a "name" attribute in the
0121      * XML document.
0122      *
0123      * This function is particularly useful for getting hold of a popupmenu defined in an XMLUI file.
0124      * For instance:
0125      * \code
0126      * QMenu *popup = static_cast<QMenu*>(guiFactory()->container("my_popup",this));
0127      * \endcode
0128      * where @p "my_popup" is the name of the menu in the XMLUI file, and
0129      * @p "this" is XMLGUIClient which owns the popupmenu (e.g. the mainwindow, or the part, or the plugin...)
0130      *
0131      * @param containerName Name of the container widget
0132      * @param client Owner of the container widget
0133      * @param useTagName Specifies whether to compare the specified name with the name attribute or
0134      *        the tag name.
0135      *
0136      * This method may return 0 if no container with the given name exists or is not owned by the client.
0137      */
0138     QWidget *container(const QString &containerName, KisKXMLGUIClient *client, bool useTagName = false);
0139 
0140     QList<QWidget *> containers(const QString &tagName);
0141 
0142     /**
0143      * Use this method to free all memory allocated by the KisKXMLGUIFactory. This deletes the internal node
0144      * tree and therefore resets the internal state of the class. Please note that the actual GUI is
0145      * NOT touched at all, meaning no containers are deleted nor any actions unplugged. That is
0146      * something you have to do on your own. So use this method only if you know what you are doing :-)
0147      *
0148      * (also note that this will call KisKXMLGUIClient::setFactory( 0 ) for all inserted clients)
0149      */
0150     void reset();
0151 
0152     /**
0153      * Use this method to free all memory allocated by the KisKXMLGUIFactory for a specific container,
0154      * including all child containers and actions. This deletes the internal node subtree for the
0155      * specified container. The actual GUI is not touched, no containers are deleted or any actions
0156      * unplugged. Use this method only if you know what you are doing :-)
0157      *
0158      * (also note that this will call KisKXMLGUIClient::setFactory( 0 ) for all clients of the
0159      * container)
0160      */
0161     void resetContainer(const QString &containerName, bool useTagName = false);
0162 
0163 Q_SIGNALS:
0164     void clientAdded(KisKXMLGUIClient *client);
0165     void clientRemoved(KisKXMLGUIClient *client);
0166 
0167     /**
0168      * Emitted when the factory is currently making changes to the GUI,
0169      * i.e. adding or removing clients.
0170      * makingChanges(true) is emitted before any change happens, and
0171      * makingChanges(false) is emitted after the change is done.
0172      * This allows e.g. KisKMainWindow to know that the GUI is
0173      * being changed programmatically and not by the user (so there is no reason to
0174      * save toolbar settings afterwards).
0175      * @since 4.1.3
0176      */
0177     void makingChanges(bool);
0178 
0179 private:
0180     friend class KisKXMLGUIClient;
0181     /// Internal, called by KisKXMLGUIClient destructor
0182     void forgetClient(KisKXMLGUIClient *client);
0183 
0184     KisKXMLGUIFactoryPrivate *const d;
0185 };
0186 
0187 #endif
0188