QGIS API Documentation  3.23.0-Master (dd0cd13a00)
qgslayertreeutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreeutils.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 "qgslayertreeutils.h"
17 #include "qgslayertree.h"
18 #include "qgsvectorlayer.h"
19 #include "qgsmeshlayer.h"
20 #include "qgsproject.h"
21 #include "qgslogger.h"
22 
23 #include <QDomElement>
24 #include <QTextStream>
25 
26 static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent );
27 static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent );
28 
29 bool QgsLayerTreeUtils::readOldLegend( QgsLayerTreeGroup *root, const QDomElement &legendElem )
30 {
31  if ( legendElem.isNull() )
32  return false;
33 
34  const QDomNodeList legendChildren = legendElem.childNodes();
35 
36  for ( int i = 0; i < legendChildren.size(); ++i )
37  {
38  const QDomElement currentChildElem = legendChildren.at( i ).toElement();
39  if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
40  {
41  _readOldLegendLayer( currentChildElem, root );
42  }
43  else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
44  {
45  _readOldLegendGroup( currentChildElem, root );
46  }
47  }
48 
49  return true;
50 }
51 
52 
53 
54 static bool _readOldLegendLayerOrderGroup( const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
55 {
56  const QDomNodeList legendChildren = groupElem.childNodes();
57 
58  for ( int i = 0; i < legendChildren.size(); ++i )
59  {
60  const QDomElement currentChildElem = legendChildren.at( i ).toElement();
61  if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
62  {
63  const QDomElement layerFileElem = currentChildElem.firstChildElement( QStringLiteral( "filegroup" ) ).firstChildElement( QStringLiteral( "legendlayerfile" ) );
64 
65  const int layerIndex = currentChildElem.attribute( QStringLiteral( "drawingOrder" ) ).toInt();
66  if ( layerIndex == -1 )
67  return false; // order undefined
68  layerIndexes.insert( layerIndex, layerFileElem.attribute( QStringLiteral( "layerid" ) ) );
69  }
70  else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
71  {
72  if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
73  return false;
74  }
75  }
76 
77  return true;
78 }
79 
80 
81 bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order )
82 {
83  if ( legendElem.isNull() )
84  return false;
85 
86  hasCustomOrder = legendElem.attribute( QStringLiteral( "updateDrawingOrder" ) ) == QLatin1String( "false" );
87  order.clear();
88 
89  QMap<int, QString> layerIndexes;
90 
91  // try to read the order. may be undefined (order = -1) for some or all items
92  const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
93 
94  if ( !res && hasCustomOrder )
95  return false; // invalid state
96 
97  const auto constLayerIndexes = layerIndexes;
98  for ( const QString &layerId : constLayerIndexes )
99  {
100  QgsDebugMsg( layerId );
101  order.append( layerId );
102  }
103 
104  return true;
105 }
106 
107 
108 static QDomElement _writeOldLegendLayer( QDomDocument &doc, QgsLayerTreeLayer *nodeLayer, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
109 {
110  int drawingOrder = -1;
111  if ( hasCustomOrder )
112  drawingOrder = order.indexOf( nodeLayer->layer() );
113 
114  QDomElement layerElem = doc.createElement( QStringLiteral( "legendlayer" ) );
115  layerElem.setAttribute( QStringLiteral( "drawingOrder" ), drawingOrder );
116  layerElem.setAttribute( QStringLiteral( "open" ), nodeLayer->isExpanded() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
117  layerElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
118  layerElem.setAttribute( QStringLiteral( "name" ), nodeLayer->name() );
119  layerElem.setAttribute( QStringLiteral( "showFeatureCount" ), nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ) ).toInt() );
120 
121  QDomElement fileGroupElem = doc.createElement( QStringLiteral( "filegroup" ) );
122  fileGroupElem.setAttribute( QStringLiteral( "open" ), nodeLayer->isExpanded() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
123  fileGroupElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "false" ) );
124 
125  QDomElement layerFileElem = doc.createElement( QStringLiteral( "legendlayerfile" ) );
126  layerFileElem.setAttribute( QStringLiteral( "isInOverview" ), nodeLayer->customProperty( QStringLiteral( "overview" ) ).toInt() );
127  layerFileElem.setAttribute( QStringLiteral( "layerid" ), nodeLayer->layerId() );
128  layerFileElem.setAttribute( QStringLiteral( "visible" ), nodeLayer->isVisible() ? 1 : 0 );
129 
130  layerElem.appendChild( fileGroupElem );
131  fileGroupElem.appendChild( layerFileElem );
132  return layerElem;
133 }
134 
135 // need forward declaration as write[..]Group and write[..]GroupChildren call each other
136 static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
137 
138 static QDomElement _writeOldLegendGroup( QDomDocument &doc, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
139 {
140  QDomElement groupElem = doc.createElement( QStringLiteral( "legendgroup" ) );
141  groupElem.setAttribute( QStringLiteral( "open" ), nodeGroup->isExpanded() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
142  groupElem.setAttribute( QStringLiteral( "name" ), nodeGroup->name() );
143  groupElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
144 
145  if ( nodeGroup->customProperty( QStringLiteral( "embedded" ) ).toInt() )
146  {
147  groupElem.setAttribute( QStringLiteral( "embedded" ), 1 );
148  groupElem.setAttribute( QStringLiteral( "project" ), nodeGroup->customProperty( QStringLiteral( "embedded_project" ) ).toString() );
149  }
150 
151  _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
152  return groupElem;
153 }
154 
155 
156 static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
157 {
158  const auto constChildren = nodeGroup->children();
159  for ( QgsLayerTreeNode *node : constChildren )
160  {
161  if ( QgsLayerTree::isGroup( node ) )
162  {
163  groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
164  }
165  else if ( QgsLayerTree::isLayer( node ) )
166  {
167  groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
168  }
169  }
170 }
171 
172 
173 QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
174 {
175  QDomElement legendElem = doc.createElement( QStringLiteral( "legend" ) );
176  legendElem.setAttribute( QStringLiteral( "updateDrawingOrder" ), hasCustomOrder ? QStringLiteral( "false" ) : QStringLiteral( "true" ) );
177 
178  _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
179 
180  return legendElem;
181 }
182 
183 
184 QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
185 {
186  switch ( state )
187  {
188  case Qt::Unchecked:
189  return QStringLiteral( "Qt::Unchecked" );
190  case Qt::PartiallyChecked:
191  return QStringLiteral( "Qt::PartiallyChecked" );
192  case Qt::Checked:
193  return QStringLiteral( "Qt::Checked" );
194  }
195  return QString();
196 }
197 
198 Qt::CheckState QgsLayerTreeUtils::checkStateFromXml( const QString &txt )
199 {
200  if ( txt == QLatin1String( "Qt::Unchecked" ) )
201  return Qt::Unchecked;
202  else if ( txt == QLatin1String( "Qt::PartiallyChecked" ) )
203  return Qt::PartiallyChecked;
204  else // "Qt::Checked"
205  return Qt::Checked;
206 }
207 
208 
209 
210 static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent )
211 {
212  const QDomNodeList groupChildren = groupElem.childNodes();
213 
214  QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( groupElem.attribute( QStringLiteral( "name" ) ) );
215 
216  groupNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
217  groupNode->setExpanded( groupElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
218 
219  if ( groupElem.attribute( QStringLiteral( "embedded" ) ) == QLatin1String( "1" ) )
220  {
221  groupNode->setCustomProperty( QStringLiteral( "embedded" ), 1 );
222  groupNode->setCustomProperty( QStringLiteral( "embedded_project" ), groupElem.attribute( QStringLiteral( "project" ) ) );
223  }
224 
225  for ( int i = 0; i < groupChildren.size(); ++i )
226  {
227  const QDomElement currentChildElem = groupChildren.at( i ).toElement();
228  if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
229  {
230  _readOldLegendLayer( currentChildElem, groupNode );
231  }
232  else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
233  {
234  _readOldLegendGroup( currentChildElem, groupNode );
235  }
236  }
237 
238  parent->addChildNode( groupNode );
239 }
240 
241 static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent )
242 {
243  const QDomElement layerFileElem = layerElem.firstChildElement( QStringLiteral( "filegroup" ) ).firstChildElement( QStringLiteral( "legendlayerfile" ) );
244  const QString layerId = layerFileElem.attribute( QStringLiteral( "layerid" ) );
245  QgsLayerTreeLayer *layerNode = new QgsLayerTreeLayer( layerId, layerElem.attribute( QStringLiteral( "name" ) ) );
246 
247  layerNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
248  layerNode->setExpanded( layerElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
249 
250  if ( layerFileElem.attribute( QStringLiteral( "isInOverview" ) ) == QLatin1String( "1" ) )
251  layerNode->setCustomProperty( QStringLiteral( "overview" ), 1 );
252 
253  if ( layerElem.attribute( QStringLiteral( "embedded" ) ) == QLatin1String( "1" ) )
254  layerNode->setCustomProperty( QStringLiteral( "embedded" ), 1 );
255 
256  if ( layerElem.attribute( QStringLiteral( "showFeatureCount" ) ) == QLatin1String( "1" ) )
257  layerNode->setCustomProperty( QStringLiteral( "showFeatureCount" ), 1 );
258 
259  // drawing order is handled by readOldLegendLayerOrder()
260 
261  parent->addChildNode( layerNode );
262 }
263 
264 bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled )
265 {
266  const auto constLayerNodes = layerNodes;
267  for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
268  {
269  QgsMapLayer *layer = layerNode->layer();
270  if ( !layer )
271  continue;
272 
273  if ( layer->isEditable() && ( !ignoreLayersWhichCannotBeToggled || !( layer->properties() & Qgis::MapLayerProperty::UsersCannotToggleEditing ) ) )
274  return true;
275  }
276  return false;
277 }
278 
279 bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer *> &layerNodes )
280 {
281  const auto constLayerNodes = layerNodes;
282  for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
283  {
284  QgsMapLayer *layer = layerNode->layer();
285  if ( !layer )
286  continue;
287 
288  if ( layer->isEditable() && layer->isModified() )
289  return true;
290  }
291  return false;
292 }
293 
295 {
296  QList<QgsLayerTreeNode *> nodesToRemove;
297  const auto constChildren = group->children();
298  for ( QgsLayerTreeNode *node : constChildren )
299  {
300  if ( QgsLayerTree::isGroup( node ) )
302  else if ( QgsLayerTree::isLayer( node ) )
303  {
304  if ( !QgsLayerTree::toLayer( node )->layer() )
305  nodesToRemove << node;
306  }
307  }
308 
309  const auto constNodesToRemove = nodesToRemove;
310  for ( QgsLayerTreeNode *node : constNodesToRemove )
311  group->removeChildNode( node );
312 }
313 
315 {
316  const QDomElement projectLayersElement { doc->documentElement().firstChildElement( QStringLiteral( "projectlayers" ) ) };
317 
318  std::function<void ( QgsLayerTreeNode * )> _store = [ & ]( QgsLayerTreeNode * node )
319  {
320  if ( QgsLayerTree::isLayer( node ) )
321  {
322  if ( QgsMapLayer *l = QgsLayerTree::toLayer( node )->layer() )
323  {
324  // no need to store for annotation layers, they can never break!
325  if ( l->type() == QgsMapLayerType::AnnotationLayer )
326  return;
327 
328  QDomElement layerElement { projectLayersElement.firstChildElement( QStringLiteral( "maplayer" ) ) };
329  while ( ! layerElement.isNull() )
330  {
331  const QString id( layerElement.firstChildElement( QStringLiteral( "id" ) ).firstChild().nodeValue() );
332  if ( id == l->id() )
333  {
334  QString str;
335  QTextStream stream( &str );
336  layerElement.save( stream, 4 /*indent*/ );
337  l->setOriginalXmlProperties( QStringLiteral( "<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1" ).arg( str ) );
338  break;
339  }
340  layerElement = layerElement.nextSiblingElement( );
341  }
342  }
343  }
344  else if ( QgsLayerTree::isGroup( node ) )
345  {
346  const QList<QgsLayerTreeNode *> constChildren( node->children( ) );
347  for ( const auto &childNode : constChildren )
348  {
349  _store( childNode );
350  }
351  }
352  };
353 
354  const QList<QgsLayerTreeNode *> children = group->children();
355  for ( QgsLayerTreeNode *node : children )
356  {
357  _store( node );
358  }
359 }
360 
362 {
363  QStringList list;
364 
365  if ( QgsLayerTree::isGroup( node ) )
366  {
367  const auto constChildren = QgsLayerTree::toGroup( node )->children();
368  for ( QgsLayerTreeNode *child : constChildren )
369  {
370  if ( child->itemVisibilityChecked() == Qt::Unchecked )
371  {
372  list << invisibleLayerList( child );
373  }
374  }
375  }
376  else if ( QgsLayerTree::isLayer( node ) )
377  {
378  QgsLayerTreeLayer *layer = QgsLayerTree::toLayer( node );
379 
380  if ( !layer->isVisible() )
381  list << layer->layerId();
382  }
383 
384  return list;
385 }
386 
388 {
389  const auto constChildren = group->children();
390  for ( QgsLayerTreeNode *child : constChildren )
391  {
392  if ( QgsLayerTree::isGroup( child ) )
393  {
394  if ( child->customProperty( QStringLiteral( "embedded" ) ).toInt() )
395  {
396  child->setCustomProperty( QStringLiteral( "embedded-invisible-layers" ), invisibleLayerList( child ) );
398  }
399  else
400  {
402  }
403  }
404  }
405 }
406 
407 
409 {
410  const auto constChildren = group->children();
411  for ( QgsLayerTreeNode *node : constChildren )
412  {
413  if ( !node->customProperty( QStringLiteral( "embedded_project" ) ).toString().isEmpty() )
414  {
415  // may change from absolute path to relative path
416  const QString newPath = project->writePath( node->customProperty( QStringLiteral( "embedded_project" ) ).toString() );
417  node->setCustomProperty( QStringLiteral( "embedded_project" ), newPath );
418  }
419 
420  if ( QgsLayerTree::isGroup( node ) )
421  {
423  }
424  }
425 }
426 
427 void QgsLayerTreeUtils::setLegendFilterByExpression( QgsLayerTreeLayer &layer, const QString &expr, bool enabled )
428 {
429  layer.setCustomProperty( QStringLiteral( "legend/expressionFilter" ), expr );
430  layer.setCustomProperty( QStringLiteral( "legend/expressionFilterEnabled" ), enabled && !expr.isEmpty() );
431 }
432 
434 {
435  const QString expression = layer.customProperty( QStringLiteral( "legend/expressionFilter" ), QString() ).toString();
436  if ( enabled )
437  *enabled = !expression.isEmpty() && layer.customProperty( QStringLiteral( "legend/expressionFilterEnabled" ), QString() ).toBool();
438  return expression;
439 }
440 
442 {
443  const auto constFindLayers = group.findLayers();
444  for ( QgsLayerTreeLayer *l : constFindLayers )
445  {
446  bool exprEnabled;
447  const QString expr = legendFilterByExpression( *l, &exprEnabled );
448  if ( exprEnabled && !expr.isEmpty() )
449  {
450  return true;
451  }
452  }
453  return false;
454 }
455 
457 {
458  // get the index of the reflayer
459  QgsLayerTreeLayer *inTree = group->findLayer( refLayer->id() );
460  if ( !inTree )
461  return nullptr;
462 
463  int idx = 0;
464  const auto constChildren = inTree->parent()->children();
465  for ( QgsLayerTreeNode *vl : constChildren )
466  {
467  if ( vl->nodeType() == QgsLayerTreeNode::NodeLayer && static_cast<QgsLayerTreeLayer *>( vl )->layer() == refLayer )
468  {
469  break;
470  }
471  idx++;
472  }
473  // insert the new layer
474  QgsLayerTreeGroup *parent = static_cast<QgsLayerTreeGroup *>( inTree->parent() ) ? static_cast<QgsLayerTreeGroup *>( inTree->parent() ) : group;
475  return parent->insertLayer( idx, layerToInsert );
476 }
477 
478 static void _collectMapLayers( const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
479 {
480  for ( QgsLayerTreeNode *node : nodes )
481  {
482  if ( QgsLayerTree::isLayer( node ) )
483  {
484  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
485  if ( nodeLayer->layer() )
486  layersSet << nodeLayer->layer();
487  }
488  else if ( QgsLayerTree::isGroup( node ) )
489  {
490  _collectMapLayers( QgsLayerTree::toGroup( node )->children(), layersSet );
491  }
492  }
493 }
494 
495 QSet<QgsMapLayer *> QgsLayerTreeUtils::collectMapLayersRecursive( const QList<QgsLayerTreeNode *> &nodes )
496 {
497  QSet<QgsMapLayer *> layersSet;
498  _collectMapLayers( nodes, layersSet );
499  return layersSet;
500 }
501 
503 {
504  if ( QgsLayerTree::isLayer( tree ) )
505  {
506  if ( QgsLayerTree::toLayer( tree )->layer() == layer )
507  return 1;
508  return 0;
509  }
510 
511  int cnt = 0;
512  const QList<QgsLayerTreeNode *> children = tree->children();
513  for ( QgsLayerTreeNode *child : children )
514  cnt += countMapLayerInTree( child, layer );
515  return cnt;
516 }
517 
519 {
520  // if the group is embedded go to the first non-embedded group, at worst the top level item
521  while ( group->customProperty( property ).toInt() )
522  {
523  if ( !group->parent() )
524  break;
525 
526  if ( QgsLayerTree::isGroup( group->parent() ) )
527  group = QgsLayerTree::toGroup( group->parent() );
528  else
529  Q_ASSERT( false );
530  }
531  return group;
532 }
@ UsersCannotToggleEditing
Indicates that users are not allowed to toggle editing for this layer. Note that this does not imply ...
Layer tree group node serves as a container for layers and further groups.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString name() const override
Returns the group's name.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
void removeAllChildren()
Remove all child nodes.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
QgsLayerTreeLayer * insertLayer(int index, QgsMapLayer *layer)
Insert a new layer node for given map layer at specified position.
Layer tree node points to a map layer.
QString layerId() const
Returns the ID for the map layer associated with this node.
QString name() const override
Returns the layer's name.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
This class is a base class for nodes in a layer tree.
@ NodeLayer
Leaf node pointing to a layer.
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.
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.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
bool isExpanded() const
Returns whether the node should be shown as expanded or collapsed in GUI.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children)
static bool layersEditable(const QList< QgsLayerTreeLayer * > &layerNodes, bool ignoreLayersWhichCannotBeToggled=false)
Returns true if any of the specified layers is editable.
static QString checkStateToXml(Qt::CheckState state)
Convert Qt::CheckState to QString.
static void replaceChildrenOfEmbeddedGroups(QgsLayerTreeGroup *group)
Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers.
static QgsLayerTreeLayer * insertLayerBelow(QgsLayerTreeGroup *group, const QgsMapLayer *refLayer, QgsMapLayer *layerToInsert)
Insert a QgsMapLayer just below another one.
static void setLegendFilterByExpression(QgsLayerTreeLayer &layer, const QString &expr, bool enabled=true)
Sets the expression filter of a legend layer.
static QString legendFilterByExpression(const QgsLayerTreeLayer &layer, bool *enabled=nullptr)
Returns the expression filter of a legend layer.
static void storeOriginalLayersProperties(QgsLayerTreeGroup *group, const QDomDocument *doc)
Stores in a layer's originalXmlProperties the layer properties information.
static QSet< QgsMapLayer * > collectMapLayersRecursive(const QList< QgsLayerTreeNode * > &nodes)
Returns map layers from the given list of layer tree nodes.
static bool hasLegendFilterExpression(const QgsLayerTreeGroup &group)
Test if one of the layers in a group has an expression filter.
static int countMapLayerInTree(QgsLayerTreeNode *tree, QgsMapLayer *layer)
Returns how many occurrences of a map layer are there in a layer tree.
static QDomElement writeOldLegend(QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList< QgsMapLayer * > &order)
Returns.
static bool readOldLegendLayerOrder(const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order)
Try to load custom layer order from.
static void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group, const QgsProject *project)
Updates an embedded group from a project.
static bool readOldLegend(QgsLayerTreeGroup *root, const QDomElement &legendElem)
Try to load layer tree from.
static QgsLayerTreeGroup * firstGroupWithoutCustomProperty(QgsLayerTreeGroup *group, const QString &property)
Returns the first parent which doesn't have the given custom property or the group itself if it doesn...
static void removeInvalidLayers(QgsLayerTreeGroup *group)
Removes layer nodes that refer to invalid layers.
static Qt::CheckState checkStateFromXml(const QString &txt)
Convert QString to Qt::CheckState.
static QStringList invisibleLayerList(QgsLayerTreeNode *node)
Gets invisible layers.
static bool layersModified(const QList< QgsLayerTreeLayer * > &layerNodes)
Returns true if any of the layers is modified.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:43
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Definition: qgslayertree.h:64
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
virtual Qgis::MapLayerProperties properties() const
Returns the map layer properties of this layer.
virtual bool isEditable() const
Returns true if the layer can be edited.
virtual bool isModified() const
Returns true if the layer has been modified since last commit/save.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
#define str(x)
Definition: qgis.cpp:37
#define QgsDebugMsg(str)
Definition: qgslogger.h:38