File indexing completed on 2024-12-08 03:44:01
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2001 Simon Hausmann <hausmann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef kxmlguifactory_p_h 0009 #define kxmlguifactory_p_h 0010 0011 #include <QAction> 0012 #include <QDebug> 0013 #include <QDomElement> 0014 #include <QMap> 0015 #include <QStack> 0016 #include <QStringList> 0017 0018 class QWidget; 0019 class KXMLGUIClient; 0020 class KXMLGUIBuilder; 0021 0022 namespace KXMLGUI 0023 { 0024 struct BuildState; 0025 0026 class ActionList : public QList<QAction *> 0027 { 0028 public: 0029 ActionList() 0030 { 0031 } 0032 ActionList(const QList<QAction *> &rhs) 0033 : QList<QAction *>(rhs) 0034 { 0035 } 0036 ActionList &operator=(const QList<QAction *> &rhs) 0037 { 0038 QList<QAction *>::operator=(rhs); 0039 return *this; 0040 } 0041 0042 void plug(QWidget *container, int index) const; 0043 }; 0044 0045 typedef QMap<QString, ActionList> ActionListMap; 0046 0047 /* 0048 * This structure is used to know to which client certain actions and custom elements 0049 * (i.e. menu separators) belong. 0050 * We do not only use a ContainerClient per GUIClient but also per merging group. 0051 * 0052 * groupName : Used for grouped merging. Specifies the group name to which these actions/elements 0053 * belong to. 0054 * actionLists : maps from action list name to action list. 0055 * mergingName : The (named) merging point. 0056 * 0057 * A ContainerClient always belongs to a ContainerNode. 0058 */ 0059 struct ContainerClient { 0060 KXMLGUIClient *client; 0061 ActionList actions; 0062 QList<QAction *> customElements; 0063 QString groupName; // is empty if no group client 0064 ActionListMap actionLists; 0065 QString mergingName; 0066 }; 0067 typedef QList<ContainerClient *> ContainerClientList; 0068 0069 struct ContainerNode; 0070 0071 struct MergingIndex { 0072 int value; // the actual index value, used as index for plug() or createContainer() calls 0073 QString mergingName; // the name of the merging index (i.e. the name attribute of the 0074 // Merge or DefineGroup tag) 0075 QString clientName; // the name of the client that defined this index 0076 }; 0077 typedef QList<MergingIndex> MergingIndexList; 0078 0079 /* 0080 * Here we store detailed information about a container, its clients (client=a guiclient having actions 0081 * plugged into the container), child nodes, naming information (tagname and name attribute) and 0082 * merging index information, to plug/insert new actions/items a the correct position. 0083 * 0084 * The builder variable is needed for using the proper GUIBuilder for destruction ( to use the same for 0085 * con- and destruction ). The builderCustomTags and builderContainerTags variables are cached values 0086 * of what the corresponding methods of the GUIBuilder which built the container return. The stringlists 0087 * is shared all over the place, so there's no need to worry about memory consumption for these 0088 * variables :-) 0089 * 0090 * The mergingIndices list contains the merging indices ;-) , as defined by <Merge>, <DefineGroup> 0091 * or by <ActionList> tags. The order of these index structures within the mergingIndices list 0092 * is (and has to be) identical with the order in the DOM tree. 0093 * 0094 * Beside the merging indices we have the "real" index of the container. It points to the next free 0095 * position. 0096 * (used when no merging index is used for a certain action, custom element or sub-container) 0097 */ 0098 struct ContainerNode { 0099 ContainerNode(QWidget *_container, 0100 const QString &_tagName, 0101 const QString &_name, 0102 ContainerNode *_parent = nullptr, 0103 KXMLGUIClient *_client = nullptr, 0104 KXMLGUIBuilder *_builder = nullptr, 0105 QAction *containerAction = nullptr, 0106 const QString &_mergingName = QString(), 0107 const QString &groupName = QString(), 0108 const QStringList &customTags = QStringList(), 0109 const QStringList &containerTags = QStringList()); 0110 ~ContainerNode(); 0111 0112 ContainerNode(const ContainerNode &) = delete; 0113 ContainerNode &operator=(const ContainerNode &) = delete; 0114 0115 ContainerNode *parent; 0116 KXMLGUIClient *client; 0117 KXMLGUIBuilder *builder; 0118 QStringList builderCustomTags; 0119 QStringList builderContainerTags; 0120 QWidget *container; 0121 QAction *containerAction; 0122 0123 QString tagName; 0124 QString name; 0125 0126 QString groupName; // is empty if the container is in no group 0127 0128 ContainerClientList clients; 0129 QList<ContainerNode *> children; 0130 0131 int index; 0132 MergingIndexList mergingIndices; 0133 0134 QString mergingName; 0135 0136 void clearChildren() 0137 { 0138 qDeleteAll(children); 0139 children.clear(); 0140 } 0141 void removeChild(ContainerNode *child); 0142 void deleteChild(ContainerNode *child); 0143 void removeActions(const QList<QAction *> &actions); 0144 0145 MergingIndexList::iterator findIndex(const QString &name); 0146 ContainerNode *findContainer(const QString &_name, bool tag); 0147 ContainerNode *findContainer(const QString &name, const QString &tagName, const QList<QWidget *> *excludeList, KXMLGUIClient *currClient); 0148 0149 ContainerClient *findChildContainerClient(KXMLGUIClient *currentGUIClient, const QString &groupName, const MergingIndexList::iterator &mergingIdx); 0150 0151 void plugActionList(BuildState &state); 0152 void plugActionList(BuildState &state, const MergingIndexList::iterator &mergingIdxIt); 0153 0154 void unplugActionList(BuildState &state); 0155 void unplugActionList(BuildState &state, const MergingIndexList::iterator &mergingIdxIt); 0156 0157 void adjustMergingIndices(int offset, const MergingIndexList::iterator &it, const QString ¤tClientName); 0158 0159 bool destruct(QDomElement element, BuildState &state); 0160 void destructChildren(const QDomElement &element, BuildState &state); 0161 static QDomElement findElementForChild(const QDomElement &baseElement, ContainerNode *childNode); 0162 void unplugActions(BuildState &state); 0163 void unplugClient(ContainerClient *client); 0164 0165 void reset(); 0166 0167 int calcMergingIndex(const QString &mergingName, MergingIndexList::iterator &it, BuildState &state, bool ignoreDefaultMergingIndex); 0168 0169 void dump(int offset = 0); 0170 }; 0171 0172 typedef QList<ContainerNode *> ContainerNodeList; 0173 0174 class BuildHelper 0175 { 0176 public: 0177 BuildHelper(BuildState &state, ContainerNode *node); 0178 0179 void build(const QDomElement &element); 0180 0181 private: 0182 void processElement(const QDomElement &element); 0183 0184 void processActionOrCustomElement(const QDomElement &e, bool isActionTag); 0185 bool processActionElement(const QDomElement &e, int idx); 0186 bool processCustomElement(const QDomElement &e, int idx); 0187 0188 void processStateElement(const QDomElement &element); 0189 0190 void processMergeElement(const QString &tag, const QString &name, const QDomElement &e); 0191 0192 void processContainerElement(const QDomElement &e, const QString &tag, const QString &name); 0193 0194 QWidget *createContainer(QWidget *parent, int index, const QDomElement &element, QAction *&containerAction, KXMLGUIBuilder **builder); 0195 0196 int calcMergingIndex(const QDomElement &element, MergingIndexList::iterator &it, QString &group); 0197 0198 QStringList customTags; 0199 QStringList containerTags; 0200 0201 QList<QWidget *> containerList; 0202 0203 ContainerClient *containerClient; 0204 0205 bool ignoreDefaultMergingIndex; 0206 0207 BuildState &m_state; 0208 0209 ContainerNode *parentNode; 0210 }; 0211 0212 struct BuildState { 0213 BuildState() 0214 : guiClient(nullptr) 0215 , builder(nullptr) 0216 , clientBuilder(nullptr) 0217 { 0218 } 0219 0220 void reset(); 0221 0222 QString clientName; 0223 0224 QString actionListName; 0225 ActionList actionList; 0226 0227 KXMLGUIClient *guiClient; 0228 0229 MergingIndexList::iterator currentDefaultMergingIt; 0230 MergingIndexList::iterator currentClientMergingIt; 0231 0232 KXMLGUIBuilder *builder; 0233 QStringList builderCustomTags; 0234 QStringList builderContainerTags; 0235 0236 KXMLGUIBuilder *clientBuilder; 0237 QStringList clientBuilderCustomTags; 0238 QStringList clientBuilderContainerTags; 0239 }; 0240 0241 typedef QStack<BuildState> BuildStateStack; 0242 0243 } 0244 0245 QDebug operator<<(QDebug stream, const KXMLGUI::MergingIndex &mi); 0246 0247 #endif