Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayertreenode.h 3 : : -------------------------------------- 4 : : Date : May 2014 5 : : Copyright : (C) 2014 by Martin Dobias 6 : : Email : wonder dot sk at gmail dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSLAYERTREENODE_H 17 : : #define QGSLAYERTREENODE_H 18 : : 19 : : #include "qgis_core.h" 20 : : #include <QObject> 21 : : 22 : : #include "qgsobjectcustomproperties.h" 23 : : #include "qgsreadwritecontext.h" 24 : : #include "qgis_sip.h" 25 : : 26 : : class QDomElement; 27 : : 28 : : class QgsProject; 29 : : class QgsMapLayer; 30 : : 31 : : /** 32 : : * \ingroup core 33 : : * \brief This class is a base class for nodes in a layer tree. 34 : : * 35 : : * Layer tree is a hierarchical structure consisting of group and layer nodes: 36 : : * 37 : : * - group nodes are containers and may contain children (layer and group nodes) 38 : : * - layer nodes point to map layers, they do not contain further children 39 : : * 40 : : * Layer trees may be used for organization of layers, typically a layer tree 41 : : * is exposed to the user using QgsLayerTreeView widget which shows the tree 42 : : * and allows manipulation with the tree. 43 : : * 44 : : * Ownership of nodes: every node is owned by its parent. Therefore once node 45 : : * is added to a layer tree, it is the responsibility of the parent to delete it 46 : : * when the node is not needed anymore. Deletion of root node of a tree will 47 : : * delete all nodes of the tree. 48 : : * 49 : : * Signals: signals are propagated from children to parent. That means it is 50 : : * sufficient to connect to root node in order to get signals about updates 51 : : * in the whole layer tree. When adding or removing a node that contains further 52 : : * children (i.e. a whole subtree), the addition/removal signals are emitted 53 : : * only for the root node of the subtree that is being added or removed. 54 : : * 55 : : * Custom properties: Every node may have some custom properties assigned to it. 56 : : * This mechanism allows third parties store additional data with the nodes. 57 : : * The properties are used within QGIS code (whether to show layer in overview, 58 : : * whether the node is embedded from another project etc), but may be also 59 : : * used by third party plugins. Custom properties are stored also in the project 60 : : * file. The storage is not efficient for large amount of data. 61 : : * 62 : : * Custom properties that have already been used within QGIS: 63 : : * 64 : : * - "loading" - whether the project is being currently loaded (root node only) 65 : : * - "overview" - whether to show a layer in overview 66 : : * - "showFeatureCount" - whether to show feature counts in layer tree (vector only) 67 : : * - "embedded" - whether the node comes from an external project 68 : : * - "embedded_project" - path to the external project (embedded root node only) 69 : : * - "legend/..." - properties for legend appearance customization 70 : : * - "expandedLegendNodes" - list of layer's legend nodes' rules in expanded state 71 : : * 72 : : * \see also QgsLayerTree, QgsLayerTreeLayer, QgsLayerTreeGroup 73 : : * \since QGIS 2.4 74 : : */ 75 : : class CORE_EXPORT QgsLayerTreeNode : public QObject 76 : : { 77 : : Q_OBJECT 78 : : 79 : : #ifdef SIP_RUN 80 : : SIP_CONVERT_TO_SUBCLASS_CODE 81 : : if ( sipCpp->inherits( "QgsLayerTreeNode" ) ) 82 : : { 83 : : sipType = sipType_QgsLayerTreeNode; 84 : : QgsLayerTreeNode *node = qobject_cast<QgsLayerTreeNode *>( sipCpp ); 85 : : if ( QgsLayerTree::isLayer( node ) ) 86 : : sipType = sipType_QgsLayerTreeLayer; 87 : : else if ( qobject_cast<QgsLayerTree *>( sipCpp ) ) 88 : : sipType = sipType_QgsLayerTree; 89 : : else if ( QgsLayerTree::isGroup( node ) ) 90 : : sipType = sipType_QgsLayerTreeGroup; 91 : : } 92 : : else 93 : : sipType = 0; 94 : : SIP_END 95 : : #endif 96 : : 97 : : public: 98 : : 99 : : //! Enumeration of possible tree node types 100 : : enum NodeType 101 : : { 102 : : NodeGroup, //!< Container of other groups and layers 103 : : NodeLayer //!< Leaf node pointing to a layer 104 : : }; 105 : : 106 : : ~QgsLayerTreeNode() override; 107 : : 108 : : //! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that 109 : 2 : NodeType nodeType() const { return mNodeType; } 110 : : //! Gets pointer to the parent. If parent is NULLPTR, the node is a root node 111 : 0 : QgsLayerTreeNode *parent() { return mParent; } 112 : : //! Gets list of children of the node. Children are owned by the parent 113 : 3 : QList<QgsLayerTreeNode *> children() { return mChildren; } 114 : : //! Gets list of children of the node. Children are owned by the parent 115 : 0 : QList<QgsLayerTreeNode *> children() const { return mChildren; } SIP_SKIP 116 : : 117 : : /** 118 : : * Removes the childrens, disconnect all the forwarded and external signals and sets their parent to NULLPTR 119 : : * \return the removed children 120 : : * \since QGIS 3.16 121 : : */ 122 : : QList<QgsLayerTreeNode *> abandonChildren() SIP_SKIP; 123 : : 124 : : /** 125 : : * Returns name of the node 126 : : * \since QGIS 3.0 127 : : */ 128 : : virtual QString name() const = 0; 129 : : 130 : : /** 131 : : * Set name of the node. Emits nameChanged signal. 132 : : * \since QGIS 3.0 133 : : */ 134 : : virtual void setName( const QString &name ) = 0; 135 : : 136 : : /** 137 : : * Read layer tree from XML. Returns new instance. 138 : : * Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. 139 : : */ 140 : : static QgsLayerTreeNode *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY; 141 : : 142 : : /** 143 : : * Read layer tree from XML. Returns new instance. 144 : : * Also resolves textual references to layers from the project (calls resolveReferences() internally). 145 : : * \since QGIS 3.0 146 : : */ 147 : : static QgsLayerTreeNode *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY; 148 : : 149 : : //! Write layer tree to XML 150 : : virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) = 0; 151 : : 152 : : //! Returns string with layer tree structure. For debug purposes only 153 : : virtual QString dump() const = 0; 154 : : 155 : : //! Create a copy of the node. Returns new instance 156 : : virtual QgsLayerTreeNode *clone() const = 0 SIP_FACTORY; 157 : : 158 : : /** 159 : : * Turn textual references to layers into map layer object from project. 160 : : * This method should be called after readXml() 161 : : * If \a looseMatching is TRUE then a looser match will be used, where a layer 162 : : * will match if the name, public source, and data provider match. This can be 163 : : * used to match legend customization from different projects where layers 164 : : * will have different layer IDs. 165 : : * \since QGIS 3.0 166 : : */ 167 : : virtual void resolveReferences( const QgsProject *project, bool looseMatching = false ) = 0; 168 : : 169 : : /** 170 : : * Returns whether a node is really visible (ie checked and all its ancestors checked as well) 171 : : * \since QGIS 3.0 172 : : */ 173 : : bool isVisible() const; 174 : : 175 : : /** 176 : : * Returns whether a node is checked (independently of its ancestors or children) 177 : : * \since QGIS 3.0 178 : : */ 179 : 0 : bool itemVisibilityChecked() const { return mChecked; } 180 : : 181 : : /** 182 : : * Check or uncheck a node (independently of its ancestors or children) 183 : : * 184 : : * \see QgsLayerTreeView::setLayerVisible() 185 : : * 186 : : * \since QGIS 3.0 187 : : */ 188 : : void setItemVisibilityChecked( bool checked ); 189 : : 190 : : /** 191 : : * Check or uncheck a node and all its children (taking into account exclusion rules) 192 : : * \since QGIS 3.0 193 : : */ 194 : : virtual void setItemVisibilityCheckedRecursive( bool checked ); 195 : : 196 : : /** 197 : : * Check or uncheck a node and all its parents 198 : : * \since QGIS 3.0 199 : : */ 200 : : void setItemVisibilityCheckedParentRecursive( bool checked ); 201 : : 202 : : /** 203 : : * Returns whether this node is checked and all its children. 204 : : * \since QGIS 3.0 205 : : */ 206 : : bool isItemVisibilityCheckedRecursive() const; 207 : : 208 : : /** 209 : : * Returns whether this node is unchecked and all its children. 210 : : * \since QGIS 3.0 211 : : */ 212 : : bool isItemVisibilityUncheckedRecursive() const; 213 : : 214 : : /** 215 : : * Returns a list of any checked layers which belong to this node or its 216 : : * children. 217 : : * \since QGIS 3.0 218 : : */ 219 : : QList< QgsMapLayer * > checkedLayers() const; 220 : : 221 : : /** 222 : : * Returns the depth of this node, i.e. the number of its ancestors 223 : : * \since QGIS 3.14 224 : : */ 225 : : int depth() const; 226 : : 227 : : //! Returns whether the node should be shown as expanded or collapsed in GUI 228 : : bool isExpanded() const; 229 : : //! Sets whether the node should be shown as expanded or collapsed in GUI 230 : : void setExpanded( bool expanded ); 231 : : 232 : : //! Sets a custom property for the node. Properties are stored in a map and saved in project file. 233 : : void setCustomProperty( const QString &key, const QVariant &value ); 234 : : //! Read a custom property from layer. Properties are stored in a map and saved in project file. 235 : : QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const; 236 : : //! Remove a custom property from layer. Properties are stored in a map and saved in project file. 237 : : void removeCustomProperty( const QString &key ); 238 : : //! Returns list of keys stored in custom properties 239 : : QStringList customProperties() const; 240 : : //! Remove a child from a node 241 : : bool takeChild( QgsLayerTreeNode *node ); 242 : : 243 : : signals: 244 : : 245 : : //! Emitted when one or more nodes will be added to a node within the tree 246 : : void willAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); 247 : : //! Emitted when one or more nodes have been added to a node within the tree 248 : : void addedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); 249 : : //! Emitted when one or more nodes will be removed from a node within the tree 250 : : void willRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); 251 : : //! Emitted when one or more nodes has been removed from a node within the tree 252 : : void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); 253 : : //! Emitted when check state of a node within the tree has been changed 254 : : void visibilityChanged( QgsLayerTreeNode *node ); 255 : : //! Emitted when a custom property of a node within the tree has been changed or removed 256 : : void customPropertyChanged( QgsLayerTreeNode *node, const QString &key ); 257 : : //! Emitted when the collapsed/expanded state of a node within the tree has been changed 258 : : void expandedChanged( QgsLayerTreeNode *node, bool expanded ); 259 : : 260 : : /** 261 : : * Emitted when the name of the node is changed 262 : : * \since QGIS 3.0 263 : : */ 264 : : void nameChanged( QgsLayerTreeNode *node, QString name ); 265 : : 266 : : protected: 267 : : 268 : : //! Constructor 269 : : QgsLayerTreeNode( NodeType t, bool checked = true ); 270 : : QgsLayerTreeNode( const QgsLayerTreeNode &other ); 271 : : 272 : : // low-level utility functions 273 : : 274 : : //! Read common XML elements. 275 : : void readCommonXml( QDomElement &element ); 276 : : //! Write common XML elements. 277 : : void writeCommonXml( QDomElement &element ); 278 : : 279 : : //! Low-level insertion of children to the node. The children must not have any parent yet! 280 : : void insertChildrenPrivate( int index, QList<QgsLayerTreeNode *> nodes ); 281 : : //! Low-level removal of children from the node. 282 : : void removeChildrenPrivate( int from, int count, bool destroy = true ); 283 : : 284 : : protected: 285 : : //! type of the node - determines which subclass is used 286 : : NodeType mNodeType; 287 : : bool mChecked; 288 : : //! pointer to the parent node - NULLPTR in case of root node 289 : : QgsLayerTreeNode *mParent = nullptr; 290 : : //! list of children - node is responsible for their deletion 291 : : QList<QgsLayerTreeNode *> mChildren; 292 : : //! whether the node should be shown in GUI as expanded 293 : : bool mExpanded; 294 : : //! custom properties attached to the node 295 : : QgsObjectCustomProperties mProperties; 296 : : 297 : : //! Sets parent to NULLPTR and disconnects all external and forwarded signals 298 : : virtual void makeOrphan() SIP_SKIP; 299 : : 300 : : private: 301 : : QgsLayerTreeNode &operator=( const QgsLayerTreeNode & ) = delete; 302 : : 303 : : }; 304 : : 305 : : 306 : : 307 : : 308 : : #endif // QGSLAYERTREENODE_H