QGIS API Documentation 4.3.0-Master (6402a64e93b)
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 "qgsmaplayer.h"
21#include "qgsproject.h"
22#include "qgsstringutils.h"
23#include "qgsvectorlayer.h"
24
25#include <QDomElement>
26#include <QString>
27#include <QTextStream>
28
29using namespace Qt::StringLiterals;
30
31static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent );
32static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent );
33
34bool QgsLayerTreeUtils::readOldLegend( QgsLayerTreeGroup *root, const QDomElement &legendElem )
35{
36 if ( legendElem.isNull() )
37 return false;
38
39 const QDomNodeList legendChildren = legendElem.childNodes();
40
41 for ( int i = 0; i < legendChildren.size(); ++i )
42 {
43 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
44 if ( currentChildElem.tagName() == "legendlayer"_L1 )
45 {
46 _readOldLegendLayer( currentChildElem, root );
47 }
48 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
49 {
50 _readOldLegendGroup( currentChildElem, root );
51 }
52 }
53
54 return true;
55}
56
57
58static bool _readOldLegendLayerOrderGroup( const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
59{
60 const QDomNodeList legendChildren = groupElem.childNodes();
61
62 for ( int i = 0; i < legendChildren.size(); ++i )
63 {
64 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
65 if ( currentChildElem.tagName() == "legendlayer"_L1 )
66 {
67 const QDomElement layerFileElem = currentChildElem.firstChildElement( u"filegroup"_s ).firstChildElement( u"legendlayerfile"_s );
68
69 const int layerIndex = currentChildElem.attribute( u"drawingOrder"_s ).toInt();
70 if ( layerIndex == -1 )
71 return false; // order undefined
72 layerIndexes.insert( layerIndex, layerFileElem.attribute( u"layerid"_s ) );
73 }
74 else if ( currentChildElem.tagName() == "legendgroup"_L1 )
75 {
76 if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
77 return false;
78 }
79 }
80
81 return true;
82}
83
84
85bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order )
86{
87 if ( legendElem.isNull() )
88 return false;
89
90 hasCustomOrder = legendElem.attribute( u"updateDrawingOrder"_s ) == "false"_L1;
91 order.clear();
92
93 QMap<int, QString> layerIndexes;
94
95 // try to read the order. may be undefined (order = -1) for some or all items
96 const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
97
98 if ( !res && hasCustomOrder )
99 return false; // invalid state
100
101 const auto constLayerIndexes = layerIndexes;
102 for ( const QString &layerId : constLayerIndexes )
103 {
104 QgsDebugMsgLevel( layerId, 2 );
105 order.append( layerId );
106 }
107
108 return true;
109}
110
111
112static QDomElement _writeOldLegendLayer( QDomDocument &doc, QgsLayerTreeLayer *nodeLayer, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
113{
114 int drawingOrder = -1;
115 if ( hasCustomOrder )
116 drawingOrder = order.indexOf( nodeLayer->layer() );
117
118 QDomElement layerElem = doc.createElement( u"legendlayer"_s );
119 layerElem.setAttribute( u"drawingOrder"_s, drawingOrder );
120 layerElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
121 layerElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
122 layerElem.setAttribute( u"name"_s, nodeLayer->name() );
123 layerElem.setAttribute( u"showFeatureCount"_s, nodeLayer->customProperty( u"showFeatureCount"_s ).toInt() );
124
125 QDomElement fileGroupElem = doc.createElement( u"filegroup"_s );
126 fileGroupElem.setAttribute( u"open"_s, nodeLayer->isExpanded() ? u"true"_s : u"false"_s );
127 fileGroupElem.setAttribute( u"hidden"_s, u"false"_s );
128
129 QDomElement layerFileElem = doc.createElement( u"legendlayerfile"_s );
130 layerFileElem.setAttribute( u"isInOverview"_s, nodeLayer->customProperty( u"overview"_s ).toInt() );
131 layerFileElem.setAttribute( u"layerid"_s, nodeLayer->layerId() );
132 layerFileElem.setAttribute( u"visible"_s, nodeLayer->isVisible() ? 1 : 0 );
133
134 layerElem.appendChild( fileGroupElem );
135 fileGroupElem.appendChild( layerFileElem );
136 return layerElem;
137}
138
139// need forward declaration as write[..]Group and write[..]GroupChildren call each other
140static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
141
142static QDomElement _writeOldLegendGroup( QDomDocument &doc, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
143{
144 QDomElement groupElem = doc.createElement( u"legendgroup"_s );
145 groupElem.setAttribute( u"open"_s, nodeGroup->isExpanded() ? u"true"_s : u"false"_s );
146 groupElem.setAttribute( u"name"_s, nodeGroup->name() );
147 groupElem.setAttribute( u"checked"_s, QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
148
149 if ( nodeGroup->customProperty( u"embedded"_s ).toInt() )
150 {
151 groupElem.setAttribute( u"embedded"_s, 1 );
152 groupElem.setAttribute( u"project"_s, nodeGroup->customProperty( u"embedded_project"_s ).toString() );
153 }
154
155 _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
156 return groupElem;
157}
158
159
160static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
161{
162 const auto constChildren = nodeGroup->children();
163 for ( QgsLayerTreeNode *node : constChildren )
164 {
165 if ( QgsLayerTree::isGroup( node ) )
166 {
167 groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
168 }
169 else if ( QgsLayerTree::isLayer( node ) )
170 {
171 groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
172 }
173 }
174}
175
176
177QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
178{
179 QDomElement legendElem = doc.createElement( u"legend"_s );
180 legendElem.setAttribute( u"updateDrawingOrder"_s, hasCustomOrder ? u"false"_s : u"true"_s );
181
182 _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
183
184 return legendElem;
185}
186
187
188QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
189{
190 switch ( state )
191 {
192 case Qt::Unchecked:
193 return u"Qt::Unchecked"_s;
194 case Qt::PartiallyChecked:
195 return u"Qt::PartiallyChecked"_s;
196 case Qt::Checked:
197 return u"Qt::Checked"_s;
198 }
199 return QString();
200}
201
202Qt::CheckState QgsLayerTreeUtils::checkStateFromXml( const QString &txt )
203{
204 if ( txt == "Qt::Unchecked"_L1 )
205 return Qt::Unchecked;
206 else if ( txt == "Qt::PartiallyChecked"_L1 )
207 return Qt::PartiallyChecked;
208 else // "Qt::Checked"
209 return Qt::Checked;
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 if ( QgsLayerTree::isGroup( node ) )
320 QgsLayerTree::toGroup( node )->setId( QgsStringUtils::createUniqueId( u"group"_s ) );
321
322 const QList<QgsLayerTreeNode *> children = node->children();
323 for ( QgsLayerTreeNode *child : children )
324 regenerateGroupIds( child );
325}
326
328{
329 const QDomElement projectLayersElement { doc->documentElement().firstChildElement( u"projectlayers"_s ) };
330
331 std::function<void( QgsLayerTreeNode * )> _store = [&]( QgsLayerTreeNode *node ) {
332 if ( QgsLayerTree::isLayer( node ) )
333 {
334 if ( QgsMapLayer *l = QgsLayerTree::toLayer( node )->layer() )
335 {
336 // no need to store for annotation layers, they can never break!
337 if ( l->type() == Qgis::LayerType::Annotation )
338 return;
339
340 QDomElement layerElement { projectLayersElement.firstChildElement( u"maplayer"_s ) };
341 while ( !layerElement.isNull() )
342 {
343 const QString id( layerElement.firstChildElement( u"id"_s ).firstChild().nodeValue() );
344 if ( id == l->id() )
345 {
346 QString str;
347 QTextStream stream( &str );
348 layerElement.save( stream, 4 /*indent*/ );
349 l->setOriginalXmlProperties( u"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1"_s.arg( str ) );
350 break;
351 }
352 layerElement = layerElement.nextSiblingElement();
353 }
354 }
355 }
356 else if ( QgsLayerTree::isGroup( node ) )
357 {
358 const QList<QgsLayerTreeNode *> constChildren( node->children() );
359 for ( const auto &childNode : constChildren )
360 {
361 _store( childNode );
362 }
363 }
364 };
365
366 const QList<QgsLayerTreeNode *> children = group->children();
367 for ( QgsLayerTreeNode *node : children )
368 {
369 _store( node );
370 }
371}
372
374{
375 QStringList list;
376
377 if ( QgsLayerTree::isGroup( node ) )
378 {
379 const auto constChildren = QgsLayerTree::toGroup( node )->children();
380 for ( QgsLayerTreeNode *child : constChildren )
381 {
382 if ( child->itemVisibilityChecked() == Qt::Unchecked )
383 {
384 list << invisibleLayerList( child );
385 }
386 }
387 }
388 else if ( QgsLayerTree::isLayer( node ) )
389 {
391
392 if ( !layer->isVisible() )
393 list << layer->layerId();
394 }
395
396 return list;
397}
398
400{
401 const auto constChildren = group->children();
402 for ( QgsLayerTreeNode *child : constChildren )
403 {
404 if ( QgsLayerTree::isGroup( child ) )
405 {
406 if ( child->customProperty( u"embedded"_s ).toInt() )
407 {
408 child->setCustomProperty( u"embedded-invisible-layers"_s, invisibleLayerList( child ) );
410 }
411 else
412 {
414 }
415 }
416 }
417}
418
419
421{
422 const auto constChildren = group->children();
423 for ( QgsLayerTreeNode *node : constChildren )
424 {
425 if ( !node->customProperty( u"embedded_project"_s ).toString().isEmpty() )
426 {
427 // may change from absolute path to relative path
428 const QString newPath = project->writePath( node->customProperty( u"embedded_project"_s ).toString() );
429 node->setCustomProperty( u"embedded_project"_s, newPath );
430 }
431
432 if ( QgsLayerTree::isGroup( node ) )
433 {
435 }
436 }
437}
438
439void QgsLayerTreeUtils::setLegendFilterByExpression( QgsLayerTreeLayer &layer, const QString &expr, bool enabled )
440{
441 layer.setCustomProperty( u"legend/expressionFilter"_s, expr );
442 layer.setCustomProperty( u"legend/expressionFilterEnabled"_s, enabled && !expr.isEmpty() );
443}
444
446{
447 const QString expression = layer.customProperty( u"legend/expressionFilter"_s, QString() ).toString();
448 if ( enabled )
449 *enabled = !expression.isEmpty() && layer.customProperty( u"legend/expressionFilterEnabled"_s, QString() ).toBool();
450 return expression;
451}
452
454{
455 const auto constFindLayers = group.findLayers();
456 for ( QgsLayerTreeLayer *l : constFindLayers )
457 {
458 bool exprEnabled;
459 const QString expr = legendFilterByExpression( *l, &exprEnabled );
460 if ( exprEnabled && !expr.isEmpty() )
461 {
462 return true;
463 }
464 }
465 return false;
466}
467
469{
470 // get the index of the reflayer
471 QgsLayerTreeLayer *inTree = group->findLayer( refLayer->id() );
472 if ( !inTree )
473 return nullptr;
474
475 int idx = 0;
476 const auto constChildren = inTree->parent()->children();
477 for ( QgsLayerTreeNode *vl : constChildren )
478 {
479 if ( vl->nodeType() == QgsLayerTreeNode::NodeLayer && static_cast<QgsLayerTreeLayer *>( vl )->layer() == refLayer )
480 {
481 break;
482 }
483 idx++;
484 }
485 // insert the new layer
486 QgsLayerTreeGroup *parent = static_cast<QgsLayerTreeGroup *>( inTree->parent() ) ? static_cast<QgsLayerTreeGroup *>( inTree->parent() ) : group;
487 return parent->insertLayer( idx + 1, layerToInsert );
488}
489
490static void _collectMapLayers( const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
491{
492 for ( QgsLayerTreeNode *node : nodes )
493 {
494 if ( QgsLayerTree::isLayer( node ) )
495 {
496 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
497 if ( nodeLayer->layer() )
498 layersSet << nodeLayer->layer();
499 }
500 else if ( QgsLayerTree::isGroup( node ) )
501 {
502 _collectMapLayers( QgsLayerTree::toGroup( node )->children(), layersSet );
503 }
504 }
505}
506
507QSet<QgsMapLayer *> QgsLayerTreeUtils::collectMapLayersRecursive( const QList<QgsLayerTreeNode *> &nodes )
508{
509 QSet<QgsMapLayer *> layersSet;
510 _collectMapLayers( nodes, layersSet );
511 return layersSet;
512}
513
515{
516 if ( QgsLayerTree::isLayer( tree ) )
517 {
518 if ( QgsLayerTree::toLayer( tree )->layer() == layer )
519 return 1;
520 return 0;
521 }
522
523 int cnt = 0;
524 const QList<QgsLayerTreeNode *> children = tree->children();
525 for ( QgsLayerTreeNode *child : children )
526 cnt += countMapLayerInTree( child, layer );
527 return cnt;
528}
529
531{
532 // if the group is embedded go to the first non-embedded group, at worst the top level item
533 while ( group->customProperty( property ).toInt() )
534 {
535 if ( !group->parent() )
536 break;
537
538 if ( QgsLayerTree::isGroup( group->parent() ) )
539 group = QgsLayerTree::toGroup( group->parent() );
540 else
541 Q_ASSERT( false );
542 }
543 return group;
544}
545
547{
548 int vectorLineIndex = 0;
549 int vectorPolygonIndex = 0;
550 int pointCloudIndex = 0;
551 int meshIndex = 0;
552 int rasterIndex = 0;
553 int basemapIndex = 0;
554
555 const QList<QgsLayerTreeNode *> children = group->children();
556 int nodeIdx = 0;
557 for ( const QgsLayerTreeNode *child : children )
558 {
559 if ( QgsLayerTree::isLayer( child ) )
560 {
561 nodeIdx++;
562 const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
563 if ( !childLayer )
564 continue;
565
566 switch ( childLayer->type() )
567 {
569 {
570 const QgsVectorLayer *vlayer = static_cast<const QgsVectorLayer *>( childLayer );
571 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
572 {
573 if ( vectorLineIndex < nodeIdx )
574 vectorLineIndex = nodeIdx;
575 if ( vectorPolygonIndex < nodeIdx )
576 vectorPolygonIndex = nodeIdx;
577 if ( pointCloudIndex < nodeIdx )
578 pointCloudIndex = nodeIdx;
579 if ( meshIndex < nodeIdx )
580 meshIndex = nodeIdx;
581 if ( rasterIndex < nodeIdx )
582 rasterIndex = nodeIdx;
583 if ( basemapIndex < nodeIdx )
584 basemapIndex = nodeIdx;
585 }
586 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
587 {
588 if ( vectorPolygonIndex < nodeIdx )
589 vectorPolygonIndex = nodeIdx;
590 if ( pointCloudIndex < nodeIdx )
591 pointCloudIndex = nodeIdx;
592 if ( meshIndex < nodeIdx )
593 meshIndex = nodeIdx;
594 if ( rasterIndex < nodeIdx )
595 rasterIndex = nodeIdx;
596 if ( basemapIndex < nodeIdx )
597 basemapIndex = nodeIdx;
598 }
599 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
600 {
601 if ( pointCloudIndex < nodeIdx )
602 pointCloudIndex = nodeIdx;
603 if ( meshIndex < nodeIdx )
604 meshIndex = nodeIdx;
605 if ( rasterIndex < nodeIdx )
606 rasterIndex = nodeIdx;
607 if ( basemapIndex < nodeIdx )
608 basemapIndex = nodeIdx;
609 }
610 break;
611 }
612
614 {
615 if ( meshIndex < nodeIdx )
616 meshIndex = nodeIdx;
617 if ( rasterIndex < nodeIdx )
618 rasterIndex = nodeIdx;
619 if ( basemapIndex < nodeIdx )
620 basemapIndex = nodeIdx;
621 break;
622 }
623
625 {
626 if ( rasterIndex < nodeIdx )
627 rasterIndex = nodeIdx;
628 if ( basemapIndex < nodeIdx )
629 basemapIndex = nodeIdx;
630 break;
631 }
632
634 {
635 if ( childLayer->dataProvider() && childLayer->dataProvider()->name() == "gdal"_L1 )
636 {
637 // Assume non-gdal raster layers are most likely to be base maps (e.g. XYZ raster)
638 // Admittedly a gross assumption, but better than nothing
639 if ( basemapIndex < nodeIdx )
640 basemapIndex = nodeIdx;
641 }
642 break;
643 }
644
649 default:
650 break;
651 }
652 }
653 }
654
655 int index = 0;
656 switch ( layer->type() )
657 {
659 {
660 QgsVectorLayer *vlayer = static_cast<QgsVectorLayer *>( layer );
661 if ( vlayer->geometryType() == Qgis::GeometryType::Point )
662 {
663 index = 0;
664 }
665 else if ( vlayer->geometryType() == Qgis::GeometryType::Line )
666 {
667 index = vectorLineIndex;
668 }
669 else if ( vlayer->geometryType() == Qgis::GeometryType::Polygon )
670 {
671 index = vectorPolygonIndex;
672 }
673 break;
674 }
675
677 {
678 index = pointCloudIndex;
679 break;
680 }
681
683 {
684 index = meshIndex;
685 break;
686 }
687
689 {
690 if ( layer->dataProvider() && layer->dataProvider()->name() == "gdal"_L1 )
691 {
692 index = rasterIndex;
693 }
694 else
695 {
696 index = basemapIndex;
697 }
698 break;
699 }
700
702 {
703 index = basemapIndex;
704 break;
705 }
706
710 default:
711 break;
712 }
713 return group->insertLayer( index, layer );
714}
@ UsersCannotToggleEditing
Indicates that users are not allowed to toggle editing for this layer. Note that this does not imply ...
Definition qgis.h:2445
@ 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 void regenerateGroupIds(QgsLayerTreeNode *node)
Assigns a new unique id to every group in the sub-tree rooted at node.
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:114
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
static QString createUniqueId(const QString &base=QString())
Generates a unique identifier by appending a random UUID to base.
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:80