/* This file is part of the KDE libraries SPDX-FileCopyrightText: 2001 Simon Hausmann SPDX-License-Identifier: LGPL-2.0-or-later */ #ifndef kxmlguifactory_p_h #define kxmlguifactory_p_h #include #include #include #include #include #include class QWidget; class KXMLGUIClient; class KXMLGUIBuilder; namespace KXMLGUI { struct BuildState; class ActionList : public QList { public: ActionList() { } ActionList(const QList &rhs) : QList(rhs) { } ActionList &operator=(const QList &rhs) { QList::operator=(rhs); return *this; } void plug(QWidget *container, int index) const; }; typedef QMap ActionListMap; /* * This structure is used to know to which client certain actions and custom elements * (i.e. menu separators) belong. * We do not only use a ContainerClient per GUIClient but also per merging group. * * groupName : Used for grouped merging. Specifies the group name to which these actions/elements * belong to. * actionLists : maps from action list name to action list. * mergingName : The (named) merging point. * * A ContainerClient always belongs to a ContainerNode. */ struct ContainerClient { KXMLGUIClient *client; ActionList actions; QList customElements; QString groupName; // is empty if no group client ActionListMap actionLists; QString mergingName; }; typedef QList ContainerClientList; struct ContainerNode; struct MergingIndex { int value; // the actual index value, used as index for plug() or createContainer() calls QString mergingName; // the name of the merging index (i.e. the name attribute of the // Merge or DefineGroup tag) QString clientName; // the name of the client that defined this index }; typedef QList MergingIndexList; /* * Here we store detailed information about a container, its clients (client=a guiclient having actions * plugged into the container), child nodes, naming information (tagname and name attribute) and * merging index information, to plug/insert new actions/items a the correct position. * * The builder variable is needed for using the proper GUIBuilder for destruction ( to use the same for * con- and destruction ). The builderCustomTags and builderContainerTags variables are cached values * of what the corresponding methods of the GUIBuilder which built the container return. The stringlists * is shared all over the place, so there's no need to worry about memory consumption for these * variables :-) * * The mergingIndices list contains the merging indices ;-) , as defined by , * or by tags. The order of these index structures within the mergingIndices list * is (and has to be) identical with the order in the DOM tree. * * Beside the merging indices we have the "real" index of the container. It points to the next free * position. * (used when no merging index is used for a certain action, custom element or sub-container) */ struct ContainerNode { ContainerNode(QWidget *_container, const QString &_tagName, const QString &_name, ContainerNode *_parent = nullptr, KXMLGUIClient *_client = nullptr, KXMLGUIBuilder *_builder = nullptr, QAction *containerAction = nullptr, const QString &_mergingName = QString(), const QString &groupName = QString(), const QStringList &customTags = QStringList(), const QStringList &containerTags = QStringList()); ~ContainerNode(); ContainerNode(const ContainerNode &) = delete; ContainerNode &operator=(const ContainerNode &) = delete; ContainerNode *parent; KXMLGUIClient *client; KXMLGUIBuilder *builder; QStringList builderCustomTags; QStringList builderContainerTags; QWidget *container; QAction *containerAction; QString tagName; QString name; QString groupName; // is empty if the container is in no group ContainerClientList clients; QList children; int index; MergingIndexList mergingIndices; QString mergingName; void clearChildren() { qDeleteAll(children); children.clear(); } void removeChild(ContainerNode *child); void deleteChild(ContainerNode *child); void removeActions(const QList &actions); MergingIndexList::iterator findIndex(const QString &name); ContainerNode *findContainer(const QString &_name, bool tag); ContainerNode *findContainer(const QString &name, const QString &tagName, const QList *excludeList, KXMLGUIClient *currClient); ContainerClient *findChildContainerClient(KXMLGUIClient *currentGUIClient, const QString &groupName, const MergingIndexList::iterator &mergingIdx); void plugActionList(BuildState &state); void plugActionList(BuildState &state, const MergingIndexList::iterator &mergingIdxIt); void unplugActionList(BuildState &state); void unplugActionList(BuildState &state, const MergingIndexList::iterator &mergingIdxIt); void adjustMergingIndices(int offset, const MergingIndexList::iterator &it, const QString ¤tClientName); bool destruct(QDomElement element, BuildState &state); void destructChildren(const QDomElement &element, BuildState &state); static QDomElement findElementForChild(const QDomElement &baseElement, ContainerNode *childNode); void unplugActions(BuildState &state); void unplugClient(ContainerClient *client); void reset(); int calcMergingIndex(const QString &mergingName, MergingIndexList::iterator &it, BuildState &state, bool ignoreDefaultMergingIndex); void dump(int offset = 0); }; typedef QList ContainerNodeList; class BuildHelper { public: BuildHelper(BuildState &state, ContainerNode *node); void build(const QDomElement &element); private: void processElement(const QDomElement &element); void processActionOrCustomElement(const QDomElement &e, bool isActionTag); bool processActionElement(const QDomElement &e, int idx); bool processCustomElement(const QDomElement &e, int idx); void processStateElement(const QDomElement &element); void processMergeElement(const QString &tag, const QString &name, const QDomElement &e); void processContainerElement(const QDomElement &e, const QString &tag, const QString &name); QWidget *createContainer(QWidget *parent, int index, const QDomElement &element, QAction *&containerAction, KXMLGUIBuilder **builder); int calcMergingIndex(const QDomElement &element, MergingIndexList::iterator &it, QString &group); QStringList customTags; QStringList containerTags; QList containerList; ContainerClient *containerClient; bool ignoreDefaultMergingIndex; BuildState &m_state; ContainerNode *parentNode; }; struct BuildState { BuildState() : guiClient(nullptr) , builder(nullptr) , clientBuilder(nullptr) { } void reset(); QString clientName; QString actionListName; ActionList actionList; KXMLGUIClient *guiClient; MergingIndexList::iterator currentDefaultMergingIt; MergingIndexList::iterator currentClientMergingIt; KXMLGUIBuilder *builder; QStringList builderCustomTags; QStringList builderContainerTags; KXMLGUIBuilder *clientBuilder; QStringList clientBuilderCustomTags; QStringList clientBuilderContainerTags; }; typedef QStack BuildStateStack; } QDebug operator<<(QDebug stream, const KXMLGUI::MergingIndex &mi); #endif