QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
18#include "qgslayertree.h"
19#include "qgslogger.h"
20#include "qgsproject.h"
21#include "qgsvectorlayer.h"
22
23#include <QDomElement>
24#include <QString>
25#include <QTextStream>
26
27using namespace Qt::StringLiterals;
28
29static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent );
30static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent );
31
32bool QgsLayerTreeUtils::readOldLegend( QgsLayerTreeGroup *root, const QDomElement &legendElem )
33{
34 if ( legendElem.isNull() )
35 return false;
36
37 const QDomNodeList legendChildren = legendElem.childNodes();
38
39 for ( int i = 0; i < legendChildren.size(); ++i )
40 {
41 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
42 if ( currentChildElem.tagName() == "legendlayer"_L1 )
43 {
44 _readOldLegendLayer( currentChildElem, root );
45 }
46 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
47 {
48 _readOldLegendGroup( currentChildElem, root );
49 }
50 }
51
52 return true;
53}
54
55
56
57static bool _readOldLegendLayerOrderGroup( const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
58{
59 const QDomNodeList legendChildren = groupElem.childNodes();
60
61 for ( int i = 0; i < legendChildren.size(); ++i )
62 {
63 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
64 if ( currentChildElem.tagName() == "legendlayer"_L1 )
65 {
66 const QDomElement layerFileElem = currentChildElem.firstChildElement( u"filegroup"_s ).firstChildElement( u"legendlayerfile"_s );
67
68 const int layerIndex = currentChildElem.attribute( u"drawingOrder"_s ).toInt();
69 if ( layerIndex == -1 )
70 return false; // order undefined
71 layerIndexes.insert( layerIndex, layerFileElem.attribute( u"layerid"_s ) );
72 }
73 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
74 {
75 if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
76 return false;
77 }
78 }
79
80 return true;
81}
82
83
84bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order )
85{
86 if ( legendElem.isNull() )
87 return false;
88
89 hasCustomOrder = legendElem.attribute( u"updateDrawingOrder"_s ) == "false"_L1;
90 order.clear();
91
92 QMap<int, QString> layerIndexes;
93
94 // try to read the order. may be undefined (order = -1) for some or all items
95 const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
96
97 if ( !res && hasCustomOrder )
98 return false; // invalid state
99
100 const auto constLayerIndexes = layerIndexes;
101 for ( const QString &layerId : constLayerIndexes )
102 {
103 QgsDebugMsgLevel( layerId, 2 );
104 order.append( layerId );
105 }
106
107 return true;
108}
109
110
111static QDomElement _writeOldLegendLayer( QDomDocument &doc, QgsLayerTreeLayer *nodeLayer, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
112{
113 int drawingOrder = -1;
114 if ( hasCustomOrder )
115 drawingOrder = order.indexOf( nodeLayer->layer() );
116
117 QDomElement layerElem = doc.createElement( u"legendlayer"_s );
118 layerElem.setAttribute( u"drawingOrder"_s, drawingOrder );
119 layerElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
120 layerElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
121 layerElem.setAttribute( u"name"_s, nodeLayer->name() );
122 layerElem.setAttribute( u"showFeatureCount"_s, nodeLayer->customProperty( u"showFeatureCount"_s ).toInt() );
123
124 QDomElement fileGroupElem = doc.createElement( u"filegroup"_s );
125 fileGroupElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
126 fileGroupElem.setAttribute( u"hidden"_s, u"false"_s );
127
128 QDomElement layerFileElem = doc.createElement( u"legendlayerfile"_s );
129 layerFileElem.setAttribute( u"isInOverview"_s, nodeLayer->customProperty( u"overview"_s ).toInt() );
130 layerFileElem.setAttribute( u"layerid"_s, nodeLayer->layerId() );
131 layerFileElem.setAttribute( u"visible"_s, nodeLayer->isVisible() ? 1 : 0 );
132
133 layerElem.appendChild( fileGroupElem );
134 fileGroupElem.appendChild( layerFileElem );
135 return layerElem;
136}
137
138// need forward declaration as write[..]Group and write[..]GroupChildren call each other
139static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
140
141static QDomElement _writeOldLegendGroup( QDomDocument &doc, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
142{
143 QDomElement groupElem = doc.createElement( u"legendgroup"_s );
144 groupElem.setAttribute( u"open"_s, nodeGroup->isExpanded() ? u"true"_s : u"false"_s );
145 groupElem.setAttribute( u"name"_s, nodeGroup->name() );
146 groupElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
147
148 if ( nodeGroup->customProperty( u"embedded"_s ).toInt() )
149 {
150 groupElem.setAttribute( u"embedded"_s, 1 );
151 groupElem.setAttribute( u"project"_s, nodeGroup->customProperty( u"embedded_project"_s ).toString() );
152 }
153
154 _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
155 return groupElem;
156}
157
158
159static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
160{
161 const auto constChildren = nodeGroup->children();
162 for ( QgsLayerTreeNode *node : constChildren )
163 {
164 if ( QgsLayerTree::isGroup( node ) )
165 {
166 groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
167 }
168 else if ( QgsLayerTree::isLayer( node ) )
169 {
170 groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
171 }
172 }
173}
174
175
176QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
177{
178 QDomElement legendElem = doc.createElement( u"legend"_s );
179 legendElem.setAttribute( u"updateDrawingOrder"_s, hasCustomOrder ? u"false"_s : u"true"_s );
180
181 _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
182
183 return legendElem;
184}
185
186
187QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
188{
189 switch ( state )
190 {
191 case Qt::Unchecked:
192 return u"Qt::Unchecked"_s;
193 case Qt::PartiallyChecked:
194 return u"Qt::PartiallyChecked"_s;
195 case Qt::Checked:
196 return u"Qt::Checked"_s;
197 }
198 return QString();
199}
200
201Qt::CheckState QgsLayerTreeUtils::checkStateFromXml( const QString &txt )
202{
203 if ( txt == "Qt::Unchecked"_L1 )
204 return Qt::Unchecked;
205 else if ( txt == "Qt::PartiallyChecked"_L1 )
206 return Qt::PartiallyChecked;
207 else // "Qt::Checked"
208 return Qt::Checked;
209}
210
211
212
213static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent )
214{
215 const QDomNodeList groupChildren = groupElem.childNodes();
216
217 QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( groupElem.attribute( u"name"_s ) );
218
219 groupNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( u"checked"_s ) ) != Qt::Unchecked );
220 groupNode->setExpanded( groupElem.attribute( u"open"_s ) == "true"_L1 );
221
222 if ( groupElem.attribute( u"embedded"_s ) == "1"_L1 )
223 {
224 groupNode->setCustomProperty( u"embedded"_s, 1 );
225 groupNode->setCustomProperty( u"embedded_project"_s, groupElem.attribute( u"project"_s ) );
226 }
227
228 for ( int i = 0; i < groupChildren.size(); ++i )
229 {
230 const QDomElement currentChildElem = groupChildren.at( i ).toElement();
231 if ( currentChildElem.tagName() == "legendlayer"_L1 )
232 {
233 _readOldLegendLayer( currentChildElem, groupNode );
234 }
235 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
236 {
237 _readOldLegendGroup( currentChildElem, groupNode );
238 }
239 }
240
241 parent->addChildNode( groupNode );
242}
243
244static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent )
245{
246 const QDomElement layerFileElem = layerElem.firstChildElement( u"filegroup"_s ).firstChildElement( u"legendlayerfile"_s );
247 const QString layerId = layerFileElem.attribute( u"layerid"_s );
248 QgsLayerTreeLayer *layerNode = new QgsLayerTreeLayer( layerId, layerElem.attribute( u"name"_s ) );
249
250 layerNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( u"checked"_s ) ) != Qt::Unchecked );
251 layerNode->setExpanded( layerElem.attribute( u"open"_s ) == "true"_L1 );
252
253 if ( layerFileElem.attribute( u"isInOverview"_s ) == "1"_L1 )
254 layerNode->setCustomProperty( u"overview"_s, 1 );
255
256 if ( layerElem.attribute( u"embedded"_s ) == "1"_L1 )
257 layerNode->setCustomProperty( u"embedded"_s, 1 );
258
259 if ( layerElem.attribute( u"showFeatureCount"_s ) == "1"_L1 )
260 layerNode->setCustomProperty( u"showFeatureCount"_s, 1 );
261
262 // drawing order is handled by readOldLegendLayerOrder()
263
264 parent->addChildNode( layerNode );
265}
266
267bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled )
268{
269 const auto constLayerNodes = layerNodes;
270 for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
271 {
272 QgsMapLayer *layer = layerNode->layer();
273 if ( !layer )
274 continue;
275
276 if ( layer->isEditable() && ( !ignoreLayersWhichCannotBeToggled || !( layer->properties() & Qgis::MapLayerProperty::UsersCannotToggleEditing ) ) )
277 return true;
278 }
279 return false;
280}
281
282bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer *> &layerNodes )
283{
284 const auto constLayerNodes = layerNodes;
285 for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
286 {
287 QgsMapLayer *layer = layerNode->layer();
288 if ( !layer )
289 continue;
290
291 if ( layer->isEditable() && layer->isModified() )
292 return true;
293 }
294 return false;
295}
296
298{
299 QList<QgsLayerTreeNode *> nodesToRemove;
300 const auto constChildren = group->children();
301 for ( QgsLayerTreeNode *node : constChildren )
302 {
303 if ( QgsLayerTree::isGroup( node ) )
305 else if ( QgsLayerTree::isLayer( node ) )
306 {
307 if ( !QgsLayerTree::toLayer( node )->layer() )
308 nodesToRemove << node;
309 }
310 }
311
312 const auto constNodesToRemove = nodesToRemove;
313 for ( QgsLayerTreeNode *node : constNodesToRemove )
314 group->removeChildNode( node );
315}
316
318{
319 const QDomElement projectLayersElement { doc->documentElement().firstChildElement( u"projectlayers"_s ) };
320
321 std::function<void ( QgsLayerTreeNode * )> _store = [ & ]( QgsLayerTreeNode * node )
322 {
323 if ( QgsLayerTree::isLayer( node ) )
324 {
325 if ( QgsMapLayer *l = QgsLayerTree::toLayer( node )->layer() )
326 {
327 // no need to store for annotation layers, they can never break!
328 if ( l->type() == Qgis::LayerType::Annotation )
329 return;
330
331 QDomElement layerElement { projectLayersElement.firstChildElement( u"maplayer"_s ) };
332 while ( ! layerElement.isNull() )
333 {
334 const QString id( layerElement.firstChildElement( u"id"_s ).firstChild().nodeValue() );
335 if ( id == l->id() )
336 {
337 QString str;
338 QTextStream stream( &str );
339 layerElement.save( stream, 4 /*indent*/ );
340 l->setOriginalXmlProperties( u"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1"_s.arg( str ) );
341 break;
342 }
343 layerElement = layerElement.nextSiblingElement( );
344 }
345 }
346 }
347 else if ( QgsLayerTree::isGroup( node ) )
348 {
349 const QList<QgsLayerTreeNode *> constChildren( node->children( ) );
350 for ( const auto &childNode : constChildren )
351 {
352 _store( childNode );
353 }
354 }
355 };
356
357 const QList<QgsLayerTreeNode *> children = group->children();
358 for ( QgsLayerTreeNode *node : children )
359 {
360 _store( node );
361 }
362}
363
365{
366 QStringList list;
367
368 if ( QgsLayerTree::isGroup( node ) )
369 {
370 const auto constChildren = QgsLayerTree::toGroup( node )->children();
371 for ( QgsLayerTreeNode *child : constChildren )
372 {
373 if ( child->itemVisibilityChecked() == Qt::Unchecked )
374 {
375 list << invisibleLayerList( child );
376 }
377 }
378 }
379 else if ( QgsLayerTree::isLayer( node ) )
380 {
382
383 if ( !layer->isVisible() )
384 list << layer->layerId();
385 }
386
387 return list;
388}
389
391{
392 const auto constChildren = group->children();
393 for ( QgsLayerTreeNode *child : constChildren )
394 {
395 if ( QgsLayerTree::isGroup( child ) )
396 {
397 if ( child->customProperty( u"embedded"_s ).toInt() )
398 {
399 child->setCustomProperty( u"embedded-invisible-layers"_s, invisibleLayerList( child ) );
401 }
402 else
403 {
405 }
406 }
407 }
408}
409
410
412{
413 const auto constChildren = group->children();
414 for ( QgsLayerTreeNode *node : constChildren )
415 {
416 if ( !node->customProperty( u"embedded_project"_s ).toString().isEmpty() )
417 {
418 // may change from absolute path to relative path
419 const QString newPath = project->writePath( node->customProperty( u"embedded_project"_s ).toString() );
420 node->setCustomProperty( u"embedded_project"_s, newPath );
421 }
422
423 if ( QgsLayerTree::isGroup( node ) )
424 {
426 }
427 }
428}
429
430void QgsLayerTreeUtils::setLegendFilterByExpression( QgsLayerTreeLayer &layer, const QString &expr, bool enabled )
431{
432 layer.setCustomProperty( u"legend/expressionFilter"_s, expr );
433 layer.setCustomProperty( u"legend/expressionFilterEnabled"_s, enabled && !expr.isEmpty() );
434}
435
437{
438 const QString expression = layer.customProperty( u"legend/expressionFilter"_s, QString() ).toString();
439 if ( enabled )
440 *enabled = !expression.isEmpty() && layer.customProperty( u"legend/expressionFilterEnabled"_s, QString() ).toBool();
441 return expression;
442}
443
445{
446 const auto constFindLayers = group.findLayers();
447 for ( QgsLayerTreeLayer *l : constFindLayers )
448 {
449 bool exprEnabled;
450 const QString expr = legendFilterByExpression( *l, &exprEnabled );
451 if ( exprEnabled && !expr.isEmpty() )
452 {
453 return true;
454 }
455 }
456 return false;
457}
458
460{
461 // get the index of the reflayer
462 QgsLayerTreeLayer *inTree = group->findLayer( refLayer->id() );
463 if ( !inTree )
464 return nullptr;
465
466 int idx = 0;
467 const auto constChildren = inTree->parent()->children();
468 for ( QgsLayerTreeNode *vl : constChildren )
469 {
470 if ( vl->nodeType() == QgsLayerTreeNode::NodeLayer && static_cast<QgsLayerTreeLayer *>( vl )->layer() == refLayer )
471 {
472 break;
473 }
474 idx++;
475 }
476 // insert the new layer
477 QgsLayerTreeGroup *parent = static_cast<QgsLayerTreeGroup *>( inTree->parent() ) ? static_cast<QgsLayerTreeGroup *>( inTree->parent() ) : group;
478 return parent->insertLayer( idx + 1, layerToInsert );
479}
480
481static void _collectMapLayers( const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
482{
483 for ( QgsLayerTreeNode *node : nodes )
484 {
485 if ( QgsLayerTree::isLayer( node ) )
486 {
487 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
488 if ( nodeLayer->layer() )
489 layersSet << nodeLayer->layer();
490 }
491 else if ( QgsLayerTree::isGroup( node ) )
492 {
493 _collectMapLayers( QgsLayerTree::toGroup( node )->children(), layersSet );
494 }
495 }
496}
497
498QSet<QgsMapLayer *> QgsLayerTreeUtils::collectMapLayersRecursive( const QList<QgsLayerTreeNode *> &nodes )
499{
500 QSet<QgsMapLayer *> layersSet;
501 _collectMapLayers( nodes, layersSet );
502 return layersSet;
503}
504
506{
507 if ( QgsLayerTree::isLayer( tree ) )
508 {
509 if ( QgsLayerTree::toLayer( tree )->layer() == layer )
510 return 1;
511 return 0;
512 }
513
514 int cnt = 0;
515 const QList<QgsLayerTreeNode *> children = tree->children();
516 for ( QgsLayerTreeNode *child : children )
517 cnt += countMapLayerInTree( child, layer );
518 return cnt;
519}
520
522{
523 // if the group is embedded go to the first non-embedded group, at worst the top level item
524 while ( group->customProperty( property ).toInt() )
525 {
526 if ( !group->parent() )
527 break;
528
529 if ( QgsLayerTree::isGroup( group->parent() ) )
530 group = QgsLayerTree::toGroup( group->parent() );
531 else
532 Q_ASSERT( false );
533 }
534 return group;
535}
536
538{
539 int vectorLineIndex = 0;
540 int vectorPolygonIndex = 0;
541 int pointCloudIndex = 0;
542 int meshIndex = 0;
543 int rasterIndex = 0;
544 int basemapIndex = 0;
545
546 const QList<QgsLayerTreeNode *> children = group->children();
547 int nodeIdx = 0;
548 for ( const QgsLayerTreeNode *child : children )
549 {
550 if ( QgsLayerTree::isLayer( child ) )
551 {
552 nodeIdx++;
553 const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
554 if ( !childLayer )
555 continue;
556
557 switch ( childLayer->type() )
558 {
560 {
561 const QgsVectorLayer *vlayer = static_cast<const QgsVectorLayer *>( childLayer );
562 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
563 {
564 if ( vectorLineIndex < nodeIdx )
565 vectorLineIndex = nodeIdx;
566 if ( vectorPolygonIndex < nodeIdx )
567 vectorPolygonIndex = nodeIdx;
568 if ( pointCloudIndex < nodeIdx )
569 pointCloudIndex = nodeIdx;
570 if ( meshIndex < nodeIdx )
571 meshIndex = nodeIdx;
572 if ( rasterIndex < nodeIdx )
573 rasterIndex = nodeIdx;
574 if ( basemapIndex < nodeIdx )
575 basemapIndex = nodeIdx;
576 }
577 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
578 {
579 if ( vectorPolygonIndex < nodeIdx )
580 vectorPolygonIndex = nodeIdx;
581 if ( pointCloudIndex < nodeIdx )
582 pointCloudIndex = nodeIdx;
583 if ( meshIndex < nodeIdx )
584 meshIndex = nodeIdx;
585 if ( rasterIndex < nodeIdx )
586 rasterIndex = nodeIdx;
587 if ( basemapIndex < nodeIdx )
588 basemapIndex = nodeIdx;
589 }
590 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
591 {
592 if ( pointCloudIndex < nodeIdx )
593 pointCloudIndex = nodeIdx;
594 if ( meshIndex < nodeIdx )
595 meshIndex = nodeIdx;
596 if ( rasterIndex < nodeIdx )
597 rasterIndex = nodeIdx;
598 if ( basemapIndex < nodeIdx )
599 basemapIndex = nodeIdx;
600 }
601 break;
602 }
603
605 {
606 if ( meshIndex < nodeIdx )
607 meshIndex = nodeIdx;
608 if ( rasterIndex < nodeIdx )
609 rasterIndex = nodeIdx;
610 if ( basemapIndex < nodeIdx )
611 basemapIndex = nodeIdx;
612 break;
613 }
614
616 {
617 if ( rasterIndex < nodeIdx )
618 rasterIndex = nodeIdx;
619 if ( basemapIndex < nodeIdx )
620 basemapIndex = nodeIdx;
621 break;
622 }
623
625 {
626 if ( childLayer->dataProvider() && childLayer->dataProvider()->name() == "gdal"_L1 )
627 {
628 // Assume non-gdal raster layers are most likely to be base maps (e.g. XYZ raster)
629 // Admittedly a gross assumption, but better than nothing
630 if ( basemapIndex < nodeIdx )
631 basemapIndex = nodeIdx;
632 }
633 break;
634 }
635
640 default:
641 break;
642 }
643 }
644 }
645
646 int index = 0;
647 switch ( layer->type() )
648 {
650 {
651 QgsVectorLayer *vlayer = static_cast<QgsVectorLayer *>( layer );
652 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
653 {
654 index = 0;
655 }
656 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
657 {
658 index = vectorLineIndex;
659 }
660 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
661 {
662 index = vectorPolygonIndex;
663 }
664 break;
665 }
666
668 {
669 index = pointCloudIndex;
670 break;
671 }
672
674 {
675 index = meshIndex;
676 break;
677 }
678
680 {
681 if ( layer->dataProvider() && layer->dataProvider()->name() == "gdal"_L1 )
682 {
683 index = rasterIndex;
684 }
685 else
686 {
687 index = basemapIndex;
688 }
689 break;
690 }
691
693 {
694 index = basemapIndex;
695 break;
696 }
697
701 default:
702 break;
703 }
704 return group->insertLayer( index, layer );
705}
@ UsersCannotToggleEditing
Indicates that users are not allowed to toggle editing for this layer. Note that this does not imply ...
Definition qgis.h:2338
@ Point
Points.
Definition qgis.h:366
@ Line
Lines.
Definition qgis.h:367
@ Polygon
Polygons.
Definition qgis.h:368
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:201
@ Plugin
Plugin based layer.
Definition qgis.h:196
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:199
@ Vector
Vector layer.
Definition qgis.h:194
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:198
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:197
@ Raster
Raster layer.
Definition qgis.h:195
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:200
virtual QString name() const =0
Returns a provider name.
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.
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 QgsLayerTreeLayer * insertLayerAtOptimalPlacement(QgsLayerTreeGroup *group, QgsMapLayer *layer)
Inserts a layer within a given group at an optimal index position by insuring a given layer type will...
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.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString id
Definition qgsmaplayer.h:86
Qgis::LayerType type
Definition qgsmaplayer.h:93
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.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:112
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63