QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgslayertreenode.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayertreenode.cpp
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#include "qgslayertreenode.h"
17
18#include "qgslayertree.h"
19#include "qgslayertreeutils.h"
20
21#include <QDomElement>
22#include <QStringList>
23
24
26 : mNodeType( t )
27 , mChecked( checked )
28 , mExpanded( true )
29{
30}
31
33 : QObject( nullptr )
34 , mNodeType( other.mNodeType )
35 , mChecked( other.mChecked )
36 , mExpanded( other.mExpanded )
37 , mProperties( other.mProperties )
38{
39 QList<QgsLayerTreeNode *> clonedChildren;
40
41 for ( QgsLayerTreeNode *child : std::as_const( other.mChildren ) )
42 clonedChildren << child->clone();
43 insertChildrenPrivate( -1, clonedChildren );
44}
45
47{
48 qDeleteAll( mChildren );
49}
50
51QList<QgsLayerTreeNode *> QgsLayerTreeNode::abandonChildren()
52{
53 const QList<QgsLayerTreeNode *> orphans { mChildren };
54 mChildren.clear();
55 for ( auto orphan : std::as_const( orphans ) )
56 {
57 orphan->makeOrphan( );
58 }
59 return orphans;
60}
61
63{
64 disconnect();
65 mParent = nullptr;
66}
67
68QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsReadWriteContext &context )
69{
70 QgsLayerTreeNode *node = nullptr;
71 if ( element.tagName() == QLatin1String( "layer-tree-group" ) )
72 node = QgsLayerTreeGroup::readXml( element, context );
73 else if ( element.tagName() == QLatin1String( "layer-tree-layer" ) )
74 node = QgsLayerTreeLayer::readXml( element, context );
75
76 return node;
77}
78
79QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsProject *project )
80{
81 QgsReadWriteContext context;
82 QgsPathResolver resolver;
83 if ( project )
84 resolver = project->pathResolver();
85 context.setPathResolver( resolver );
86 context.setProjectTranslator( const_cast<QgsProject *>( project ) );
87
88 QgsLayerTreeNode *node = readXml( element, context );
89 if ( node )
90 node->resolveReferences( project );
91 return node;
92}
93
94
96{
97 if ( mChecked == checked )
98 return;
99 mChecked = checked;
100 emit visibilityChanged( this );
101}
102
104{
105 setItemVisibilityChecked( checked );
106}
107
109{
110 setItemVisibilityChecked( checked );
111 if ( mParent )
113}
114
116{
117 return mChecked && ( !mParent || mParent->isVisible() );
118}
119
120
122{
123 return mExpanded;
124}
125
127{
128 if ( !mChecked )
129 return false;
130 const auto constMChildren = mChildren;
131 for ( QgsLayerTreeNode *child : constMChildren )
132 {
133 if ( !child->isItemVisibilityCheckedRecursive() )
134 return false;
135 }
136
137 return true;
138}
139
141{
142 if ( mChecked )
143 return false;
144 const auto constMChildren = mChildren;
145 for ( QgsLayerTreeNode *child : constMChildren )
146 {
147 if ( !child->isItemVisibilityUncheckedRecursive() )
148 return false;
149 }
150
151 return true;
152}
153
154void fetchCheckedLayers( const QgsLayerTreeNode *node, QList<QgsMapLayer *> &layers )
155{
156 if ( QgsLayerTree::isLayer( node ) )
157 {
158 const QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
159 if ( nodeLayer->isVisible() )
160 layers << nodeLayer->layer();
161 }
162
163 const auto constChildren = node->children();
164 for ( QgsLayerTreeNode *child : constChildren )
165 {
166 if ( QgsLayerTreeGroup *group = qobject_cast< QgsLayerTreeGroup * >( child ) )
167 {
168 if ( QgsGroupLayer *groupLayer = group->groupLayer() )
169 {
170 layers << groupLayer;
171 continue;
172 }
173 }
174
175 fetchCheckedLayers( child, layers );
176 }
177}
178
179QList<QgsMapLayer *> QgsLayerTreeNode::checkedLayers() const
180{
181 QList<QgsMapLayer *> layers;
182 fetchCheckedLayers( this, layers );
183 return layers;
184}
185
187{
188 int depth = 0;
190 while ( node )
191 {
192 node = node->parent();
193 ++depth;
194 }
195 return depth;
196}
197
198void QgsLayerTreeNode::setExpanded( bool expanded )
199{
200 if ( mExpanded == expanded )
201 return;
202
203 mExpanded = expanded;
204 emit expandedChanged( this, expanded );
205}
206
207
208void QgsLayerTreeNode::setCustomProperty( const QString &key, const QVariant &value )
209{
210 if ( !mProperties.contains( key ) || mProperties.value( key ) != value )
211 {
212 mProperties.setValue( key, value );
213 emit customPropertyChanged( this, key );
214 }
215}
216
217QVariant QgsLayerTreeNode::customProperty( const QString &key, const QVariant &defaultValue ) const
218{
219 return mProperties.value( key, defaultValue );
220}
221
223{
224 if ( mProperties.contains( key ) )
225 {
226 mProperties.remove( key );
227 emit customPropertyChanged( this, key );
228 }
229}
230
232{
233 return mProperties.keys();
234}
235
236void QgsLayerTreeNode::readCommonXml( QDomElement &element )
237{
238 mProperties.readXml( element );
239}
240
241void QgsLayerTreeNode::writeCommonXml( QDomElement &element )
242{
243 QDomDocument doc( element.ownerDocument() );
244 mProperties.writeXml( element, doc );
245}
246
247void QgsLayerTreeNode::insertChildrenPrivate( int index, const QList<QgsLayerTreeNode *> &nodes )
248{
249 if ( nodes.isEmpty() )
250 return;
251
252 for ( QgsLayerTreeNode *node : nodes )
253 {
254 Q_ASSERT( !node->mParent );
255 node->mParent = this;
256 }
257
258 if ( index < 0 || index >= mChildren.count() )
259 index = mChildren.count();
260
261 for ( int i = 0; i < nodes.count(); ++i )
262 {
263 QgsLayerTreeNode *node = nodes.at( i );
264
265 const QList<QgsLayerTreeNode *> orphans { node->abandonChildren() };
266
267 emit willAddChildren( this, index + i, index + i );
268 mChildren.insert( index + i, node );
269 emit addedChildren( this, index + i, index + i );
270
271 // forward the signal towards the root
280
281 // Now add children
282 if ( ! orphans.isEmpty() )
283 {
284 node->insertChildrenPrivate( -1, orphans );
285 }
286
287 }
288}
289
290void QgsLayerTreeNode::removeChildrenPrivate( int from, int count, bool destroy )
291{
292 if ( from < 0 || count <= 0 )
293 return;
294
295 const int to = from + count - 1;
296 if ( to >= mChildren.count() )
297 return;
298
299 // Remove in reverse order
300 while ( --count >= 0 )
301 {
302 const int last { from + count };
303 Q_ASSERT( last >= 0 && last < mChildren.count( ) );
304 QgsLayerTreeNode *node = mChildren.at( last );
305
306 // Remove children first
307 if ( ! node->children().isEmpty() )
308 {
309 node->removeChildrenPrivate( 0, node->children().count( ), destroy );
310 }
311
312 emit willRemoveChildren( this, last, last );
313 node = mChildren.takeAt( last );
314 if ( destroy )
315 {
316 delete node;
317 }
318 else
319 {
320 node->makeOrphan();
321 }
322 emit removedChildren( this, last, last );
323 }
324}
325
327{
328 int index = mChildren.indexOf( node );
329 if ( index < 0 )
330 return false;
331
332 int n = mChildren.size();
333
334 removeChildrenPrivate( index, 1, false );
335
336 return mChildren.size() < n;
337}
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
Definition: qgsgrouplayer.h:42
Layer tree group node serves as a container for layers and further groups.
static QgsLayerTreeGroup * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read group (tree) from XML element <layer-tree-group> and return the newly created group (or nullptr ...
Layer tree node points to a map layer.
static QgsLayerTreeLayer * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read layer node from XML.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
This class is a base class for nodes in a layer tree.
void readCommonXml(QDomElement &element)
Read common XML elements.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the childrens, disconnect all the forwarded and external signals and sets their parent to nul...
virtual void makeOrphan()
Sets parent to nullptr and disconnects all external and forwarded signals.
NodeType
Enumeration of possible tree node types.
void removedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes has been removed from a node within the tree.
void nameChanged(QgsLayerTreeNode *node, QString name)
Emitted when the name of the node is changed.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well)
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
bool isItemVisibilityUncheckedRecursive() const
Returns whether this node is unchecked and all its children.
static QgsLayerTreeNode * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read layer tree from XML.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
void willRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes will be removed from a node within the tree.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
~QgsLayerTreeNode() override
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
void setExpanded(bool expanded)
Sets whether the node should be shown as expanded or collapsed in GUI.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
QgsLayerTreeNode(NodeType t, bool checked=true)
Constructor.
void writeCommonXml(QDomElement &element)
Write common XML elements.
QgsObjectCustomProperties mProperties
custom properties attached to the node
void customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
void insertChildrenPrivate(int index, const QList< QgsLayerTreeNode * > &nodes)
Low-level insertion of children to the node. The children must not have any parent yet!
int depth() const
Returns the depth of this node, i.e.
void addedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes have been added to a node within the tree.
bool takeChild(QgsLayerTreeNode *node)
Remove a child from a node.
void willAddChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes will be added to a node within the tree.
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
QList< QgsLayerTreeNode * > mChildren
list of children - node is responsible for their deletion
virtual void setItemVisibilityCheckedRecursive(bool checked)
Check or uncheck a node and all its children (taking into account exclusion rules)
bool mExpanded
whether the node should be shown in GUI as expanded
bool isExpanded() const
Returns whether the node should be shown as expanded or collapsed in GUI.
QStringList customProperties() const
Returns list of keys stored in custom properties.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
QList< QgsMapLayer * > checkedLayers() const
Returns a list of any checked layers which belong to this node or its children.
QgsLayerTreeNode * mParent
pointer to the parent node - nullptr in case of root node
bool isItemVisibilityCheckedRecursive() const
Returns whether this node is checked and all its children.
virtual void resolveReferences(const QgsProject *project, bool looseMatching=false)=0
Turn textual references to layers into map layer object from project.
void expandedChanged(QgsLayerTreeNode *node, bool expanded)
Emitted when the collapsed/expanded state of a node within the tree has been changed.
void removeChildrenPrivate(int from, int count, bool destroy=true)
Low-level removal of children from the node.
void setItemVisibilityCheckedParentRecursive(bool checked)
Check or uncheck a node and all its parents.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
void setValue(const QString &key, const QVariant &value)
Add an entry to the store with the specified key.
QStringList keys() const
Returns a list of all stored keys.
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Writes the store contents to an XML node.
void remove(const QString &key)
Removes a key (entry) from the store.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for the given key.
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from an XML node.
bool contains(const QString &key) const
Returns true if the properties contains a key with the specified name.
Resolves relative paths into absolute paths and vice versa.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
The class is used as a container of context for various read/write operations on other objects.
void setProjectTranslator(QgsProjectTranslator *projectTranslator)
Sets the project translator.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
void fetchCheckedLayers(const QgsLayerTreeNode *node, QList< QgsMapLayer * > &layers)