QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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
56static bool _readOldLegendLayerOrderGroup( const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
57{
58 const QDomNodeList legendChildren = groupElem.childNodes();
59
60 for ( int i = 0; i < legendChildren.size(); ++i )
61 {
62 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
63 if ( currentChildElem.tagName() == "legendlayer"_L1 )
64 {
65 const QDomElement layerFileElem = currentChildElem.firstChildElement( u"filegroup"_s ).firstChildElement( u"legendlayerfile"_s );
66
67 const int layerIndex = currentChildElem.attribute( u"drawingOrder"_s ).toInt();
68 if ( layerIndex == -1 )
69 return false; // order undefined
70 layerIndexes.insert( layerIndex, layerFileElem.attribute( u"layerid"_s ) );
71 }
72 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
73 {
74 if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
75 return false;
76 }
77 }
78
79 return true;
80}
81
82
83bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order )
84{
85 if ( legendElem.isNull() )
86 return false;
87
88 hasCustomOrder = legendElem.attribute( u"updateDrawingOrder"_s ) == "false"_L1;
89 order.clear();
90
91 QMap<int, QString> layerIndexes;
92
93 // try to read the order. may be undefined (order = -1) for some or all items
94 const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
95
96 if ( !res && hasCustomOrder )
97 return false; // invalid state
98
99 const auto constLayerIndexes = layerIndexes;
100 for ( const QString &layerId : constLayerIndexes )
101 {
102 QgsDebugMsgLevel( layerId, 2 );
103 order.append( layerId );
104 }
105
106 return true;
107}
108
109
110static QDomElement _writeOldLegendLayer( QDomDocument &doc, QgsLayerTreeLayer *nodeLayer, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
111{
112 int drawingOrder = -1;
113 if ( hasCustomOrder )
114 drawingOrder = order.indexOf( nodeLayer->layer() );
115
116 QDomElement layerElem = doc.createElement( u"legendlayer"_s );
117 layerElem.setAttribute( u"drawingOrder"_s, drawingOrder );
118 layerElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
119 layerElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
120 layerElem.setAttribute( u"name"_s, nodeLayer->name() );
121 layerElem.setAttribute( u"showFeatureCount"_s, nodeLayer->customProperty( u"showFeatureCount"_s ).toInt() );
122
123 QDomElement fileGroupElem = doc.createElement( u"filegroup"_s );
124 fileGroupElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
125 fileGroupElem.setAttribute( u"hidden"_s, u"false"_s );
126
127 QDomElement layerFileElem = doc.createElement( u"legendlayerfile"_s );
128 layerFileElem.setAttribute( u"isInOverview"_s, nodeLayer->customProperty( u"overview"_s ).toInt() );
129 layerFileElem.setAttribute( u"layerid"_s, nodeLayer->layerId() );
130 layerFileElem.setAttribute( u"visible"_s, nodeLayer->isVisible() ? 1 : 0 );
131
132 layerElem.appendChild( fileGroupElem );
133 fileGroupElem.appendChild( layerFileElem );
134 return layerElem;
135}
136
137// need forward declaration as write[..]Group and write[..]GroupChildren call each other
138static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
139
140static QDomElement _writeOldLegendGroup( QDomDocument &doc, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
141{
142 QDomElement groupElem = doc.createElement( u"legendgroup"_s );
143 groupElem.setAttribute( u"open"_s, nodeGroup->isExpanded() ? u"true"_s : u"false"_s );
144 groupElem.setAttribute( u"name"_s, nodeGroup->name() );
145 groupElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
146
147 if ( nodeGroup->customProperty( u"embedded"_s ).toInt() )
148 {
149 groupElem.setAttribute( u"embedded"_s, 1 );
150 groupElem.setAttribute( u"project"_s, nodeGroup->customProperty( u"embedded_project"_s ).toString() );
151 }
152
153 _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
154 return groupElem;
155}
156
157
158static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
159{
160 const auto constChildren = nodeGroup->children();
161 for ( QgsLayerTreeNode *node : constChildren )
162 {
163 if ( QgsLayerTree::isGroup( node ) )
164 {
165 groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
166 }
167 else if ( QgsLayerTree::isLayer( node ) )
168 {
169 groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
170 }
171 }
172}
173
174
175QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
176{
177 QDomElement legendElem = doc.createElement( u"legend"_s );
178 legendElem.setAttribute( u"updateDrawingOrder"_s, hasCustomOrder ? u"false"_s : u"true"_s );
179
180 _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
181
182 return legendElem;
183}
184
185
186QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
187{
188 switch ( state )
189 {
190 case Qt::Unchecked:
191 return u"Qt::Unchecked"_s;
192 case Qt::PartiallyChecked:
193 return u"Qt::PartiallyChecked"_s;
194 case Qt::Checked:
195 return u"Qt::Checked"_s;
196 }
197 return QString();
198}
199
200Qt::CheckState QgsLayerTreeUtils::checkStateFromXml( const QString &txt )
201{
202 if ( txt == "Qt::Unchecked"_L1 )
203 return Qt::Unchecked;
204 else if ( txt == "Qt::PartiallyChecked"_L1 )
205 return Qt::PartiallyChecked;
206 else // "Qt::Checked"
207 return Qt::Checked;
208}
209
210
211static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent )
212{
213 const QDomNodeList groupChildren = groupElem.childNodes();
214
215 QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( groupElem.attribute( u"name"_s ) );
216
217 groupNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( u"checked"_s ) ) != Qt::Unchecked );
218 groupNode->setExpanded( groupElem.attribute( u"open"_s ) == "true"_L1 );
219
220 if ( groupElem.attribute( u"embedded"_s ) == "1"_L1 )
221 {
222 groupNode->setCustomProperty( u"embedded"_s, 1 );
223 groupNode->setCustomProperty( u"embedded_project"_s, groupElem.attribute( u"project"_s ) );
224 }
225
226 for ( int i = 0; i < groupChildren.size(); ++i )
227 {
228 const QDomElement currentChildElem = groupChildren.at( i ).toElement();
229 if ( currentChildElem.tagName() == "legendlayer"_L1 )
230 {
231 _readOldLegendLayer( currentChildElem, groupNode );
232 }
233 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
234 {
235 _readOldLegendGroup( currentChildElem, groupNode );
236 }
237 }
238
239 parent->addChildNode( groupNode );
240}
241
242static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent )
243{
244 const QDomElement layerFileElem = layerElem.firstChildElement( u"filegroup"_s ).firstChildElement( u"legendlayerfile"_s );
245 const QString layerId = layerFileElem.attribute( u"layerid"_s );
246 QgsLayerTreeLayer *layerNode = new QgsLayerTreeLayer( layerId, layerElem.attribute( u"name"_s ) );
247
248 layerNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( u"checked"_s ) ) != Qt::Unchecked );
249 layerNode->setExpanded( layerElem.attribute( u"open"_s ) == "true"_L1 );
250
251 if ( layerFileElem.attribute( u"isInOverview"_s ) == "1"_L1 )
252 layerNode->setCustomProperty( u"overview"_s, 1 );
253
254 if ( layerElem.attribute( u"embedded"_s ) == "1"_L1 )
255 layerNode->setCustomProperty( u"embedded"_s, 1 );
256
257 if ( layerElem.attribute( u"showFeatureCount"_s ) == "1"_L1 )
258 layerNode->setCustomProperty( u"showFeatureCount"_s, 1 );
259
260 // drawing order is handled by readOldLegendLayerOrder()
261
262 parent->addChildNode( layerNode );
263}
264
265bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled )
266{
267 const auto constLayerNodes = layerNodes;
268 for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
269 {
270 QgsMapLayer *layer = layerNode->layer();
271 if ( !layer )
272 continue;
273
274 if ( layer->isEditable() && ( !ignoreLayersWhichCannotBeToggled || !( layer->properties() & Qgis::MapLayerProperty::UsersCannotToggleEditing ) ) )
275 return true;
276 }
277 return false;
278}
279
280bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer *> &layerNodes )
281{
282 const auto constLayerNodes = layerNodes;
283 for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
284 {
285 QgsMapLayer *layer = layerNode->layer();
286 if ( !layer )
287 continue;
288
289 if ( layer->isEditable() && layer->isModified() )
290 return true;
291 }
292 return false;
293}
294
296{
297 QList<QgsLayerTreeNode *> nodesToRemove;
298 const auto constChildren = group->children();
299 for ( QgsLayerTreeNode *node : constChildren )
300 {
301 if ( QgsLayerTree::isGroup( node ) )
303 else if ( QgsLayerTree::isLayer( node ) )
304 {
305 if ( !QgsLayerTree::toLayer( node )->layer() )
306 nodesToRemove << node;
307 }
308 }
309
310 const auto constNodesToRemove = nodesToRemove;
311 for ( QgsLayerTreeNode *node : constNodesToRemove )
312 group->removeChildNode( node );
313}
314
316{
317 const QDomElement projectLayersElement { doc->documentElement().firstChildElement( u"projectlayers"_s ) };
318
319 std::function<void( QgsLayerTreeNode * )> _store = [&]( QgsLayerTreeNode *node ) {
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() == Qgis::LayerType::Annotation )
326 return;
327
328 QDomElement layerElement { projectLayersElement.firstChildElement( u"maplayer"_s ) };
329 while ( !layerElement.isNull() )
330 {
331 const QString id( layerElement.firstChildElement( u"id"_s ).firstChild().nodeValue() );
332 if ( id == l->id() )
333 {
334 QString str;
335 QTextStream stream( &str );
336 layerElement.save( stream, 4 /*indent*/ );
337 l->setOriginalXmlProperties( u"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1"_s.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( u"embedded"_s ).toInt() )
395 {
396 child->setCustomProperty( u"embedded-invisible-layers"_s, 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( u"embedded_project"_s ).toString().isEmpty() )
414 {
415 // may change from absolute path to relative path
416 const QString newPath = project->writePath( node->customProperty( u"embedded_project"_s ).toString() );
417 node->setCustomProperty( u"embedded_project"_s, 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( u"legend/expressionFilter"_s, expr );
430 layer.setCustomProperty( u"legend/expressionFilterEnabled"_s, enabled && !expr.isEmpty() );
431}
432
434{
435 const QString expression = layer.customProperty( u"legend/expressionFilter"_s, QString() ).toString();
436 if ( enabled )
437 *enabled = !expression.isEmpty() && layer.customProperty( u"legend/expressionFilterEnabled"_s, 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}
533
535{
536 int vectorLineIndex = 0;
537 int vectorPolygonIndex = 0;
538 int pointCloudIndex = 0;
539 int meshIndex = 0;
540 int rasterIndex = 0;
541 int basemapIndex = 0;
542
543 const QList<QgsLayerTreeNode *> children = group->children();
544 int nodeIdx = 0;
545 for ( const QgsLayerTreeNode *child : children )
546 {
547 if ( QgsLayerTree::isLayer( child ) )
548 {
549 nodeIdx++;
550 const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
551 if ( !childLayer )
552 continue;
553
554 switch ( childLayer->type() )
555 {
557 {
558 const QgsVectorLayer *vlayer = static_cast<const QgsVectorLayer *>( childLayer );
559 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
560 {
561 if ( vectorLineIndex < nodeIdx )
562 vectorLineIndex = nodeIdx;
563 if ( vectorPolygonIndex < nodeIdx )
564 vectorPolygonIndex = nodeIdx;
565 if ( pointCloudIndex < nodeIdx )
566 pointCloudIndex = nodeIdx;
567 if ( meshIndex < nodeIdx )
568 meshIndex = nodeIdx;
569 if ( rasterIndex < nodeIdx )
570 rasterIndex = nodeIdx;
571 if ( basemapIndex < nodeIdx )
572 basemapIndex = nodeIdx;
573 }
574 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
575 {
576 if ( vectorPolygonIndex < nodeIdx )
577 vectorPolygonIndex = nodeIdx;
578 if ( pointCloudIndex < nodeIdx )
579 pointCloudIndex = nodeIdx;
580 if ( meshIndex < nodeIdx )
581 meshIndex = nodeIdx;
582 if ( rasterIndex < nodeIdx )
583 rasterIndex = nodeIdx;
584 if ( basemapIndex < nodeIdx )
585 basemapIndex = nodeIdx;
586 }
587 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
588 {
589 if ( pointCloudIndex < nodeIdx )
590 pointCloudIndex = nodeIdx;
591 if ( meshIndex < nodeIdx )
592 meshIndex = nodeIdx;
593 if ( rasterIndex < nodeIdx )
594 rasterIndex = nodeIdx;
595 if ( basemapIndex < nodeIdx )
596 basemapIndex = nodeIdx;
597 }
598 break;
599 }
600
602 {
603 if ( meshIndex < nodeIdx )
604 meshIndex = nodeIdx;
605 if ( rasterIndex < nodeIdx )
606 rasterIndex = nodeIdx;
607 if ( basemapIndex < nodeIdx )
608 basemapIndex = nodeIdx;
609 break;
610 }
611
613 {
614 if ( rasterIndex < nodeIdx )
615 rasterIndex = nodeIdx;
616 if ( basemapIndex < nodeIdx )
617 basemapIndex = nodeIdx;
618 break;
619 }
620
622 {
623 if ( childLayer->dataProvider() && childLayer->dataProvider()->name() == "gdal"_L1 )
624 {
625 // Assume non-gdal raster layers are most likely to be base maps (e.g. XYZ raster)
626 // Admittedly a gross assumption, but better than nothing
627 if ( basemapIndex < nodeIdx )
628 basemapIndex = nodeIdx;
629 }
630 break;
631 }
632
637 default:
638 break;
639 }
640 }
641 }
642
643 int index = 0;
644 switch ( layer->type() )
645 {
647 {
648 QgsVectorLayer *vlayer = static_cast<QgsVectorLayer *>( layer );
649 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
650 {
651 index = 0;
652 }
653 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
654 {
655 index = vectorLineIndex;
656 }
657 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
658 {
659 index = vectorPolygonIndex;
660 }
661 break;
662 }
663
665 {
666 index = pointCloudIndex;
667 break;
668 }
669
671 {
672 index = meshIndex;
673 break;
674 }
675
677 {
678 if ( layer->dataProvider() && layer->dataProvider()->name() == "gdal"_L1 )
679 {
680 index = rasterIndex;
681 }
682 else
683 {
684 index = basemapIndex;
685 }
686 break;
687 }
688
690 {
691 index = basemapIndex;
692 break;
693 }
694
698 default:
699 break;
700 }
701 return group->insertLayer( index, layer );
702}
@ UsersCannotToggleEditing
Indicates that users are not allowed to toggle editing for this layer. Note that this does not imply ...
Definition qgis.h:2361
@ Point
Points.
Definition qgis.h:380
@ Line
Lines.
Definition qgis.h:381
@ Polygon
Polygons.
Definition qgis.h:382
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
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:113
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