QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
26static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent );
27static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent );
28
29bool 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
54static 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
81bool 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
108static 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
136static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
137
138static 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
156static 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
173QDomElement 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
184QString 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
198Qt::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
210static 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
241static 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
264bool 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
279bool 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 {
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
427void 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 + 1, layerToInsert );
476}
477
478static 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
495QSet<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.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
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.
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 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
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:104
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