QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
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"
20#include "qgslayertreeutils.h"
21
22#include <QDomElement>
23#include <QString>
24#include <QStringList>
25
26#include "moc_qgslayertreenode.cpp"
27
28using namespace Qt::StringLiterals;
29
31 : mNodeType( t )
32 , mChecked( checked )
33
34{
35}
36
38 : QObject( nullptr )
39 , mNodeType( other.mNodeType )
40 , mChecked( other.mChecked )
41 , mExpanded( other.mExpanded )
42 , mProperties( other.mProperties )
43{
44 QList<QgsLayerTreeNode *> clonedChildren;
45
46 for ( QgsLayerTreeNode *child : std::as_const( other.mChildren ) )
47 clonedChildren << child->clone();
48 insertChildrenPrivate( -1, clonedChildren );
49}
50
55
56QList<QgsLayerTreeNode *> QgsLayerTreeNode::abandonChildren()
57{
58 const QList<QgsLayerTreeNode *> orphans { mChildren };
59 mChildren.clear();
60 for ( auto orphan : std::as_const( orphans ) )
61 {
62 orphan->makeOrphan( );
63 }
64 return orphans;
65}
66
68{
69 disconnect();
70 mParent = nullptr;
71}
72
73QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsReadWriteContext &context )
74{
75 QgsLayerTreeNode *node = nullptr;
76 if ( element.tagName() == "layer-tree-group"_L1 )
77 node = QgsLayerTreeGroup::readXml( element, context );
78 else if ( element.tagName() == "layer-tree-layer"_L1 )
79 node = QgsLayerTreeLayer::readXml( element, context );
80 else if ( element.tagName() == "layer-tree-custom-node"_L1 )
81 node = QgsLayerTreeCustomNode::readXml( element, context );
82
83 return node;
84}
85
86QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsProject *project )
87{
88 QgsReadWriteContext context;
89 QgsPathResolver resolver;
90 if ( project )
91 resolver = project->pathResolver();
92 context.setPathResolver( resolver );
93 context.setProjectTranslator( const_cast<QgsProject *>( project ) );
94
95 QgsLayerTreeNode *node = readXml( element, context );
96 if ( node && node->nodeType() != NodeCustom )
97 node->resolveReferences( project );
98 return node;
99}
100
101
103{
104 if ( mChecked == checked )
105 return;
106 mChecked = checked;
107 emit visibilityChanged( this );
108}
109
114
116{
117 setItemVisibilityChecked( checked );
118 if ( mParent )
119 mParent->setItemVisibilityCheckedParentRecursive( checked );
120}
121
123{
124 return mChecked && ( !mParent || mParent->isVisible() );
125}
126
127
129{
130 return mExpanded;
131}
132
134{
135 if ( !mChecked )
136 return false;
137 const auto constMChildren = mChildren;
138 for ( QgsLayerTreeNode *child : constMChildren )
139 {
140 if ( !child->isItemVisibilityCheckedRecursive() )
141 return false;
142 }
143
144 return true;
145}
146
148{
149 if ( mChecked )
150 return false;
151 const auto constMChildren = mChildren;
152 for ( QgsLayerTreeNode *child : constMChildren )
153 {
154 if ( !child->isItemVisibilityUncheckedRecursive() )
155 return false;
156 }
157
158 return true;
159}
160
161void fetchCheckedLayers( const QgsLayerTreeNode *node, QList<QgsMapLayer *> &layers )
162{
163 if ( QgsLayerTree::isLayer( node ) )
164 {
165 const QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
166 if ( nodeLayer->isVisible() )
167 layers << nodeLayer->layer();
168 }
169
170 const auto constChildren = node->children();
171 for ( QgsLayerTreeNode *child : constChildren )
172 {
173 if ( QgsLayerTreeGroup *group = qobject_cast< QgsLayerTreeGroup * >( child ) )
174 {
175 if ( QgsGroupLayer *groupLayer = group->groupLayer() )
176 {
177 layers << groupLayer;
178 continue;
179 }
180 }
181
182 fetchCheckedLayers( child, layers );
183 }
184}
185
186QList<QgsMapLayer *> QgsLayerTreeNode::checkedLayers() const
187{
188 QList<QgsMapLayer *> layers;
189 fetchCheckedLayers( this, layers );
190 return layers;
191}
192
194{
195 int depth = 0;
197 while ( node )
198 {
199 node = node->parent();
200 ++depth;
201 }
202 return depth;
203}
204
205void QgsLayerTreeNode::setExpanded( bool expanded )
206{
207 if ( mExpanded == expanded )
208 return;
209
210 mExpanded = expanded;
211 emit expandedChanged( this, expanded );
212}
213
214
215void QgsLayerTreeNode::setCustomProperty( const QString &key, const QVariant &value )
216{
217 if ( !mProperties.contains( key ) || mProperties.value( key ) != value )
218 {
219 mProperties.setValue( key, value );
220 emit customPropertyChanged( this, key );
221 }
222}
223
224QVariant QgsLayerTreeNode::customProperty( const QString &key, const QVariant &defaultValue ) const
225{
226 return mProperties.value( key, defaultValue );
227}
228
230{
231 if ( mProperties.contains( key ) )
232 {
233 mProperties.remove( key );
234 emit customPropertyChanged( this, key );
235 }
236}
237
239{
240 return mProperties.keys();
241}
242
243void QgsLayerTreeNode::readCommonXml( const QDomElement &element )
244{
245 mProperties.readXml( element );
246}
247
248void QgsLayerTreeNode::writeCommonXml( QDomElement &element )
249{
250 QDomDocument doc( element.ownerDocument() );
251 mProperties.writeXml( element, doc );
252}
253
254void QgsLayerTreeNode::insertChildrenPrivate( int index, const QList<QgsLayerTreeNode *> &nodes )
255{
256 if ( nodes.isEmpty() )
257 return;
258
259 for ( QgsLayerTreeNode *node : nodes )
260 {
261 Q_ASSERT( !node->mParent );
262 node->mParent = this;
263 }
264
265 if ( index < 0 || index >= mChildren.count() )
266 index = mChildren.count();
267
268 for ( int i = 0; i < nodes.count(); ++i )
269 {
270 QgsLayerTreeNode *node = nodes.at( i );
271
272 const QList<QgsLayerTreeNode *> orphans { node->abandonChildren() };
273
274 emit willAddChildren( this, index + i, index + i );
275 mChildren.insert( index + i, node );
276 emit addedChildren( this, index + i, index + i );
277
278 // forward the signal towards the root
287
288 // Now add children
289 if ( ! orphans.isEmpty() )
290 {
291 node->insertChildrenPrivate( -1, orphans );
292 }
293
294 // ensure initial expanded state for node is respected
295 emit expandedChanged( node, node->isExpanded() );
296 }
297}
298
299void QgsLayerTreeNode::removeChildrenPrivate( int from, int count, bool destroy )
300{
301 if ( from < 0 || count <= 0 )
302 return;
303
304 const int to = from + count - 1;
305 if ( to >= mChildren.count() )
306 return;
307
308 // Remove in reverse order
309 while ( --count >= 0 )
310 {
311 const int last { from + count };
312 Q_ASSERT( last >= 0 && last < mChildren.count( ) );
313 QgsLayerTreeNode *node = mChildren.at( last );
314
315 // Remove children first
316 if ( ! node->children().isEmpty() )
317 {
318 node->removeChildrenPrivate( 0, node->children().count( ), destroy );
319 }
320
321 emit willRemoveChildren( this, last, last );
322 node = mChildren.takeAt( last );
323 if ( destroy )
324 {
325 delete node;
326 }
327 else
328 {
329 node->makeOrphan();
330 }
331 emit removedChildren( this, last, last );
332 }
333}
334
336{
337 int index = mChildren.indexOf( node );
338 if ( index < 0 )
339 return false;
340
341 int n = mChildren.size();
342
343 removeChildrenPrivate( index, 1, false );
344
345 return mChildren.size() < n;
346}
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
static QgsLayerTreeCustomNode * readXml(const QDomElement &element, const QgsReadWriteContext &context)
Read custom node from XML element <layer-tree-custom-node> and return the newly created node (or null...
Layer tree group node serves as a container for layers and further groups.
static QgsLayerTreeGroup * readXml(const 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.
Base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the children, disconnect all the forwarded and external signals and sets their parent to null...
virtual void makeOrphan()
Sets parent to nullptr and disconnects all external and forwarded signals.
NodeType
Enumeration of possible tree node types.
@ NodeCustom
Leaf node pointing to a custom object.
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.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
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.
NodeType mNodeType
type of the node - determines which subclass is used
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.
void readCommonXml(const QDomElement &element)
Read common XML elements.
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.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
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:113
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
A container for the context for various read/write operations on 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)