QGIS API Documentation  2.99.0-Master (19b062c)
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  Q_FOREACH ( QgsLayerTreeNode *child, other.mChildren )
41  clonedChildren << child->clone();
42  insertChildrenPrivate( -1, clonedChildren );
43 }
44 
46 {
47  qDeleteAll( mChildren );
48 }
49 
50 QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsReadWriteContext &context )
51 {
52  QgsLayerTreeNode *node = nullptr;
53  if ( element.tagName() == QLatin1String( "layer-tree-group" ) )
54  node = QgsLayerTreeGroup::readXml( element, context );
55  else if ( element.tagName() == QLatin1String( "layer-tree-layer" ) )
56  node = QgsLayerTreeLayer::readXml( element, context );
57 
58  return node;
59 }
60 
61 QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsProject *project )
62 {
63  QgsReadWriteContext context;
64  QgsPathResolver resolver;
65  if ( project )
66  resolver = project->pathResolver();
67  context.setPathResolver( resolver );
68 
69  QgsLayerTreeNode *node = readXml( element, context );
70  if ( node )
71  node->resolveReferences( project );
72  return node;
73 }
74 
75 
77 {
78  if ( mChecked == checked )
79  return;
80  mChecked = checked;
81  emit visibilityChanged( this );
82 }
83 
85 {
86  setItemVisibilityChecked( checked );
87 }
88 
90 {
91  setItemVisibilityChecked( checked );
92  if ( mParent )
94 }
95 
97 {
98  return mChecked && ( !mParent || mParent->isVisible() );
99 }
100 
101 
103 {
104  return mExpanded;
105 }
106 
108 {
109  if ( !mChecked )
110  return false;
111  Q_FOREACH ( QgsLayerTreeNode *child, mChildren )
112  {
113  if ( !child->isItemVisibilityCheckedRecursive() )
114  return false;
115  }
116 
117  return true;
118 }
119 
121 {
122  if ( mChecked )
123  return false;
124  Q_FOREACH ( QgsLayerTreeNode *child, mChildren )
125  {
126  if ( !child->isItemVisibilityUncheckedRecursive() )
127  return false;
128  }
129 
130  return true;
131 }
132 
133 void fetchCheckedLayers( const QgsLayerTreeNode *node, QList<QgsMapLayer *> &layers )
134 {
135  if ( QgsLayerTree::isLayer( node ) )
136  {
137  const QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
138  if ( nodeLayer->isVisible() )
139  layers << nodeLayer->layer();
140  }
141 
142  Q_FOREACH ( QgsLayerTreeNode *child, node->children() )
143  fetchCheckedLayers( child, layers );
144 }
145 
146 QList<QgsMapLayer *> QgsLayerTreeNode::checkedLayers() const
147 {
148  QList<QgsMapLayer *> layers;
149  fetchCheckedLayers( this, layers );
150  return layers;
151 }
152 
153 void QgsLayerTreeNode::setExpanded( bool expanded )
154 {
155  if ( mExpanded == expanded )
156  return;
157 
158  mExpanded = expanded;
159  emit expandedChanged( this, expanded );
160 }
161 
162 
163 void QgsLayerTreeNode::setCustomProperty( const QString &key, const QVariant &value )
164 {
165  mProperties.setValue( key, value );
166  emit customPropertyChanged( this, key );
167 }
168 
169 QVariant QgsLayerTreeNode::customProperty( const QString &key, const QVariant &defaultValue ) const
170 {
171  return mProperties.value( key, defaultValue );
172 }
173 
174 void QgsLayerTreeNode::removeCustomProperty( const QString &key )
175 {
176  mProperties.remove( key );
177  emit customPropertyChanged( this, key );
178 }
179 
181 {
182  return mProperties.keys();
183 }
184 
185 void QgsLayerTreeNode::readCommonXml( QDomElement &element )
186 {
187  mProperties.readXml( element );
188 }
189 
190 void QgsLayerTreeNode::writeCommonXml( QDomElement &element )
191 {
192  QDomDocument doc( element.ownerDocument() );
193  mProperties.writeXml( element, doc );
194 }
195 
196 void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode *> nodes )
197 {
198  if ( nodes.isEmpty() )
199  return;
200 
201  Q_FOREACH ( QgsLayerTreeNode *node, nodes )
202  {
203  Q_ASSERT( !node->mParent );
204  node->mParent = this;
205  }
206 
207  if ( index < 0 || index >= mChildren.count() )
208  index = mChildren.count();
209 
210  int indexTo = index + nodes.count() - 1;
211  emit willAddChildren( this, index, indexTo );
212  for ( int i = 0; i < nodes.count(); ++i )
213  {
214  QgsLayerTreeNode *node = nodes.at( i );
215  mChildren.insert( index + i, node );
216 
217  // forward the signal towards the root
226  }
227  emit addedChildren( this, index, indexTo );
228 }
229 
230 void QgsLayerTreeNode::removeChildrenPrivate( int from, int count, bool destroy )
231 {
232  if ( from < 0 || count <= 0 )
233  return;
234 
235  int to = from + count - 1;
236  if ( to >= mChildren.count() )
237  return;
238  emit willRemoveChildren( this, from, to );
239  while ( --count >= 0 )
240  {
241  QgsLayerTreeNode *node = mChildren.takeAt( from );
242  node->mParent = nullptr;
243  if ( destroy )
244  delete node;
245  }
246  emit removedChildren( this, from, to );
247 }
248 
250 {
251  int index = mChildren.indexOf( node );
252  if ( index < 0 )
253  return false;
254 
255  int n = mChildren.size();
256 
257  removeChildrenPrivate( index, 1, false );
258 
259  return mChildren.size() < n;
260 }
The class is used as a container of context for various read/write operations on other objects...
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
bool isItemVisibilityUncheckedRecursive() const
Return whether this node is unchecked and all its children.
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from XML.
void insertChildrenPrivate(int index, QList< QgsLayerTreeNode *> nodes)
Low-level insertion of children to the node. The children must not have any parent yet! ...
bool takeChild(QgsLayerTreeNode *node)
Remove a child from a node.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
bool mExpanded
whether the node should be shown in GUI as expanded
void willRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes will be removed from a node within the tree.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well) ...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Return value for the given key. If the key is not stored, default value will be used.
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Write store contents to XML.
static QgsLayerTreeNode * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read layer tree from XML.
bool isExpanded() const
Return whether the node should be shown as expanded or collapsed in GUI.
NodeType
Enumeration of possible tree node types.
QStringList customProperties() const
Return list of keys stored in custom properties.
void remove(const QString &key)
Remove a key (entry) from the store.
void willAddChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes will be added to a node within the tree.
QList< QgsMapLayer *> checkedLayers() const
Returns a list of any checked layers which belong to this node or its children.
void removedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes has been removed from a node within the tree.
NodeType mNodeType
type of the node - determines which subclass is used
virtual void setItemVisibilityCheckedRecursive(bool checked)
Check or uncheck a node and all its children (taking into account exclusion rules) ...
void setValue(const QString &key, const QVariant &value)
Add an entry to the store. If the entry with the keys exists already, it will be overwritten.
QList< QgsLayerTreeNode * > children()
Get list of children of the node. Children are owned by the parent.
void expandedChanged(QgsLayerTreeNode *node, bool expanded)
Emitted when the collapsed/expanded state of a node within the tree has been changed.
QgsPathResolver pathResolver() const
Return path resolver object with considering whether the project uses absolute or relative paths and ...
void addedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes have been added to a node within the tree.
void writeCommonXml(QDomElement &element)
Write common XML elements.
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...
QgsLayerTreeNode * mParent
pointer to the parent node - null in case of root node
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
This class is a base class for nodes in a layer tree.
static QgsLayerTreeGroup * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read group (tree) from XML element <layer-tree-group> and return the newly created group (or null on ...
Reads and writes project states.
Definition: qgsproject.h:81
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file...
QStringList keys() const
Return list of stored keys.
void setExpanded(bool expanded)
Set whether the node should be shown as expanded or collapsed in GUI.
void setItemVisibilityCheckedParentRecursive(bool checked)
Check or uncheck a node and all its parents.
void removeChildrenPrivate(int from, int count, bool destroy=true)
Low-level removal of children from the node.
bool isItemVisibilityCheckedRecursive() const
Return whether this node is checked and all its children.
QgsMapLayer * layer() const
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
void readCommonXml(QDomElement &element)
Read common XML elements.
virtual void resolveReferences(const QgsProject *project, bool looseMatching=false)=0
Turn textual references to layers into map layer object from project.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
void fetchCheckedLayers(const QgsLayerTreeNode *node, QList< QgsMapLayer *> &layers)
QList< QgsLayerTreeNode * > mChildren
list of children - node is responsible for their deletion
void customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
Resolves relative paths into absolute paths and vice versa.
void nameChanged(QgsLayerTreeNode *node, QString name)
Emitted when the name of the node is changed.
static QgsLayerTreeLayer * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read layer node from XML.
QgsLayerTreeNode(NodeType t, bool checked=true)
Constructor.
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node. Properties are stored in a map and saved in project file...
Layer tree node points to a map layer.
QgsObjectCustomProperties mProperties
custom properties attached to the node