QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgslayertreegroup.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayertreegroup.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 "qgslayertreegroup.h"
17
18#include "qgsgrouplayer.h"
19#include "qgslayertree.h"
20#include "qgslayertreeutils.h"
21#include "qgsmaplayer.h"
22
23#include <QDomElement>
24#include <QString>
25#include <QStringList>
26
27#include "moc_qgslayertreegroup.cpp"
28
29using namespace Qt::StringLiterals;
30
31QgsLayerTreeGroup::QgsLayerTreeGroup( const QString &name, bool checked )
32 : QgsLayerTreeNode( NodeGroup, checked )
33 , mName( name )
34 , mServerProperties( std::make_unique<QgsMapLayerServerProperties>() )
35{
36 init();
37}
38
40 : QgsLayerTreeNode( other )
41 , mName( other.mName )
46 , mGroupLayer( other.mGroupLayer )
47 , mServerProperties( std::make_unique<QgsMapLayerServerProperties>() )
48 , mWmsGroupRequestMode( other.mWmsGroupRequestMode )
49{
50 other.serverProperties()->copyTo( mServerProperties.get() );
51
52 init();
53}
54
55void QgsLayerTreeGroup::init()
56{
58 connect( this, &QgsLayerTreeNode::addedChildren, this, &QgsLayerTreeGroup::updateGroupLayers );
59 connect( this, &QgsLayerTreeNode::removedChildren, this, &QgsLayerTreeGroup::updateGroupLayers );
60 connect( this, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeGroup::updateGroupLayers );
61}
62
64{
65 return mName;
66}
67
68void QgsLayerTreeGroup::setName( const QString &n )
69{
70 if ( mName == n )
71 return;
72
73 mName = n;
74 emit nameChanged( this, n );
75}
76
77
79{
81 insertChildNode( index, grp );
82 return grp;
83}
84
86{
88 addChildNode( grp );
89 return grp;
90}
91
93{
94 if ( !layer )
95 return nullptr;
96
97 QgsLayerTreeLayer *ll = new QgsLayerTreeLayer( layer );
98 insertChildNode( index, ll );
99
100 updateGroupLayers();
101 return ll;
102}
103
105{
106 if ( !layer )
107 return nullptr;
108
109 QgsLayerTreeLayer *ll = new QgsLayerTreeLayer( layer );
110 addChildNode( ll );
111
112 updateGroupLayers();
113 return ll;
114}
115
116QgsLayerTreeCustomNode *QgsLayerTreeGroup::insertCustomNode( int index, const QString &id, const QString &name )
117{
118 if ( id.trimmed().isEmpty() )
119 return nullptr;
120
121 // Avoid registering two custom nodes with the same id
122 const QStringList customNodeIds = findCustomNodeIds();
123 if ( customNodeIds.contains( id ) )
124 return nullptr;
125
126 QgsLayerTreeCustomNode *customNode = new QgsLayerTreeCustomNode( id, name );
127 insertChildNode( index, customNode );
128 return customNode;
129}
130
132{
133 if ( node->nodeId().trimmed().isEmpty() )
134 return nullptr;
135
136 // Avoid registering two custom nodes with the same id
137 const QStringList customNodeIds = findCustomNodeIds();
138 if ( customNodeIds.contains( node->nodeId() ) )
139 return nullptr;
140
141 insertChildNode( index, node );
142 return node;
143}
144
146{
147 if ( id.trimmed().isEmpty() )
148 return nullptr;
149
150 // Avoid registering two custom nodes with the same id
151 const QStringList customNodeIds = findCustomNodeIds();
152 if ( customNodeIds.contains( id ) )
153 return nullptr;
154
155 QgsLayerTreeCustomNode *customNode = new QgsLayerTreeCustomNode( id, name );
156 addChildNode( customNode );
157 return customNode;
158}
159
161{
162 QList<QgsLayerTreeNode *> nodes;
163 nodes << node;
164 insertChildNodes( index, nodes );
165}
166
167void QgsLayerTreeGroup::insertChildNodes( int index, const QList<QgsLayerTreeNode *> &nodes )
168{
169 QgsLayerTreeNode *meChild = nullptr;
172
173 // low-level insert
174 insertChildrenPrivate( index, nodes );
175
176 if ( mMutuallyExclusive )
177 {
178 if ( meChild )
179 {
180 // the child could have change its index - or the new children may have been also set as visible
181 mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
182 }
183 else if ( mChecked )
184 {
185 // we have not picked a child index yet, but we should pick one now
186 // ... so pick the first one from the newly added
187 if ( index == -1 )
188 index = mChildren.count() - nodes.count(); // get real insertion index
190 }
192 }
193
194 updateGroupLayers();
195}
196
198{
199 insertChildNode( -1, node );
200
201 updateGroupLayers();
202}
203
205{
206 int i = mChildren.indexOf( node );
207 if ( i >= 0 )
208 removeChildren( i, 1 );
209
210 updateGroupLayers();
211}
212
214{
215 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
216 {
217 if ( QgsLayerTree::isLayer( child ) )
218 {
219 QgsLayerTreeLayer *childLayer = QgsLayerTree::toLayer( child );
220 if ( childLayer->layer() == layer )
221 {
222 removeChildren( mChildren.indexOf( child ), 1 );
223 break;
224 }
225 }
226 }
227
228 updateGroupLayers();
229}
230
232{
233 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
234 {
235 if ( QgsLayerTree::isCustomNode( child ) )
236 {
238 if ( childCustom->nodeId() == customNode->nodeId() )
239 {
240 removeChildren( mChildren.indexOf( child ), 1 );
241 break;
242 }
243 }
244 }
245
246 updateGroupLayers();
247}
248
249void QgsLayerTreeGroup::removeChildren( int from, int count )
250{
251 QgsLayerTreeNode *meChild = nullptr;
254
255 removeChildrenPrivate( from, count );
256
257 if ( meChild )
258 {
259 // the child could have change its index - or may have been removed completely
260 mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
261 // we need to uncheck this group
262 //if ( mMutuallyExclusiveChildIndex == -1 )
263 // setItemVisibilityChecked( false );
264 }
265
266 updateGroupLayers();
267}
268
270{
271 // clean the layer tree by removing empty group
272 const auto childNodes = children();
273 for ( QgsLayerTreeNode *treeNode : childNodes )
274 {
275 if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
276 {
277 QgsLayerTreeGroup *treeGroup = qobject_cast<QgsLayerTreeGroup *>( treeNode );
278 if ( treeGroup->findLayerIds().isEmpty() )
279 removeChildNode( treeNode );
280 else
282 }
283 }
284
285 updateGroupLayers();
286}
287
292
294{
295 if ( !layer )
296 return nullptr;
297
298 return findLayer( layer->id() );
299}
300
301QgsLayerTreeLayer *QgsLayerTreeGroup::findLayer( const QString &layerId ) const
302{
303 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
304 {
305 if ( QgsLayerTree::isLayer( child ) )
306 {
307 QgsLayerTreeLayer *childLayer = QgsLayerTree::toLayer( child );
308 if ( childLayer->layerId() == layerId )
309 return childLayer;
310 }
311 else if ( QgsLayerTree::isGroup( child ) )
312 {
313 QgsLayerTreeLayer *res = QgsLayerTree::toGroup( child )->findLayer( layerId );
314 if ( res )
315 return res;
316 }
317 }
318 return nullptr;
319}
320
321QList<QgsLayerTreeLayer *> QgsLayerTreeGroup::findLayers() const
322{
323 QList<QgsLayerTreeLayer *> list;
324 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
325 {
326 if ( QgsLayerTree::isLayer( child ) )
327 list << QgsLayerTree::toLayer( child );
328 else if ( QgsLayerTree::isGroup( child ) )
329 list << QgsLayerTree::toGroup( child )->findLayers();
330 }
331 return list;
332}
333
335{
336 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
337 {
338 if ( QgsLayerTree::isCustomNode( child ) )
339 {
341 if ( childCustom->nodeId() == id )
342 return childCustom;
343 }
344 else if ( QgsLayerTree::isGroup( child ) )
345 {
347 if ( res )
348 return res;
349 }
350 }
351 return nullptr;
352}
353
354QList<QgsLayerTreeNode *> QgsLayerTreeGroup::findLayersAndCustomNodes() const
355{
356 QList<QgsLayerTreeNode *> list;
357 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
358 {
359 if ( QgsLayerTree::isLayer( child ) || QgsLayerTree::isCustomNode( child ) )
360 list << child;
361 else if ( QgsLayerTree::isGroup( child ) )
363 }
364 return list;
365}
366
367void QgsLayerTreeGroup::reorderGroupLayers( const QList<QgsMapLayer *> &order )
368{
369 const QList< QgsLayerTreeLayer * > childLayers = findLayers();
370 int targetIndex = 0;
371 for ( QgsMapLayer *targetLayer : order )
372 {
373 for ( QgsLayerTreeLayer *layerNode : childLayers )
374 {
375 if ( layerNode->layer() == targetLayer )
376 {
377 QgsLayerTreeLayer *cloned = layerNode->clone();
378 insertChildNode( targetIndex, cloned );
379 removeChildNode( layerNode );
380 targetIndex++;
381 break;
382 }
383 }
384 }
385}
386
387void QgsLayerTreeGroup::reorderGroupLayersAndCustomNodes( const QList<QgsLayerTreeNode *> &order )
388{
389 const QList< QgsLayerTreeNode * > childNodes = findLayersAndCustomNodes();
390 int targetIndex = 0;
391 for ( QgsLayerTreeNode *targetNode : order )
392 {
393 for ( QgsLayerTreeNode *childNode : childNodes )
394 {
395 if ( childNode == targetNode )
396 {
397 QgsLayerTreeNode *cloned = childNode->clone();
398 insertChildNode( targetIndex, cloned );
399 removeChildNode( childNode );
400 targetIndex++;
401 break;
402 }
403 }
404 }
405}
406
408{
409 QList<QgsMapLayer *> list;
410 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
411 {
412 if ( QgsLayerTree::isLayer( child ) )
413 {
414 QgsMapLayer *layer = QgsLayerTree::toLayer( child )->layer();
415 if ( !layer || !layer->isSpatial() )
416 continue;
417 list << layer;
418 }
419 else if ( QgsLayerTree::isGroup( child ) )
420 {
422 if ( group->groupLayer() )
423 {
424 list << group->groupLayer();
425 }
426 else
427 {
428 list << group->layerOrderRespectingGroupLayers();
429 }
430 }
431 }
432 return list;
433}
434
436{
437 QList<QgsLayerTreeNode *> list;
438 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
439 {
440 if ( QgsLayerTree::isLayer( child ) )
441 {
442 QgsMapLayer *layer = QgsLayerTree::toLayer( child )->layer();
443 if ( !layer || !layer->isSpatial() )
444 continue;
445 list << child;
446 }
447 else if ( QgsLayerTree::isCustomNode( child ) )
448 {
449 list << child;
450 }
451 else if ( QgsLayerTree::isGroup( child ) )
452 {
454 if ( group->groupLayer() )
455 {
456 list << group;
457 }
458 else
459 {
461 }
462 }
463 }
464 return list;
465}
466
468{
469 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
470 {
471 if ( QgsLayerTree::isGroup( child ) )
472 {
473 QgsLayerTreeGroup *childGroup = QgsLayerTree::toGroup( child );
474 if ( childGroup->name() == name )
475 return childGroup;
476 else
477 {
478 QgsLayerTreeGroup *grp = childGroup->findGroup( name );
479 if ( grp )
480 return grp;
481 }
482 }
483 }
484 return nullptr;
485}
486
487QList<QgsLayerTreeGroup *> QgsLayerTreeGroup::findGroups( bool recursive ) const
488{
489 QList<QgsLayerTreeGroup *> list;
490
491 for ( QgsLayerTreeNode *child : mChildren )
492 {
493 if ( QgsLayerTree::isGroup( child ) )
494 {
495 QgsLayerTreeGroup *childGroup = QgsLayerTree::toGroup( child );
496 list << childGroup;
497 if ( recursive )
498 list << childGroup->findGroups( recursive );
499 }
500 }
501 return list;
502}
503
504QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( const QDomElement &element, const QgsReadWriteContext &context ) // cppcheck-suppress duplInheritedMember
505{
506 if ( element.tagName() != "layer-tree-group"_L1 )
507 return nullptr;
508
509 QString name = context.projectTranslator()->translate( u"project:layergroups"_s, element.attribute( u"name"_s ) );
510 bool isExpanded = ( element.attribute( u"expanded"_s, u"1"_s ) == "1"_L1 );
511 bool checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( u"checked"_s ) ) != Qt::Unchecked;
512 bool isMutuallyExclusive = element.attribute( u"mutually-exclusive"_s, u"0"_s ) == "1"_L1;
513 int mutuallyExclusiveChildIndex = element.attribute( u"mutually-exclusive-child"_s, u"-1"_s ).toInt();
514
515 QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( name, checked );
516 groupNode->setExpanded( isExpanded );
517
518 groupNode->readCommonXml( element );
519
520 groupNode->readChildrenFromXml( element, context );
521
522 groupNode->setIsMutuallyExclusive( isMutuallyExclusive, mutuallyExclusiveChildIndex );
523
524 groupNode->mWmsHasTimeDimension = element.attribute( u"wms-has-time-dimension"_s, u"0"_s ) == "1"_L1;
525
526 groupNode->mWmsGroupRequestMode = { qgsEnumKeyToValue( element.attribute( u"wms-group-request-mode"_s ), Qgis::WmsGroupRequestMode::Normal ) };
527
528 groupNode->mGroupLayer = QgsMapLayerRef( element.attribute( u"groupLayer"_s ) );
529
530 readLegacyServerProperties( groupNode );
531
532 groupNode->serverProperties()->readXml( element );
533
534 return groupNode;
535}
536
537void QgsLayerTreeGroup::readLegacyServerProperties( QgsLayerTreeGroup *groupNode )
538{
539 const QVariant wmsShortName = groupNode->customProperty( u"wmsShortName"_s );
540 if ( wmsShortName.isValid() )
541 {
542 groupNode->serverProperties()->setShortName( wmsShortName.toString() );
543 groupNode->removeCustomProperty( u"wmsShortName"_s );
544 }
545
546 const QVariant wmsTitle = groupNode->customProperty( u"wmsTitle"_s );
547 if ( wmsTitle.isValid() )
548 {
549 groupNode->serverProperties()->setTitle( wmsTitle.toString() );
550 groupNode->removeCustomProperty( u"wmsTitle"_s );
551 }
552
553 const QVariant wmsAbstract = groupNode->customProperty( u"wmsAbstract"_s );
554 if ( wmsAbstract.isValid() )
555 {
556 groupNode->serverProperties()->setAbstract( wmsAbstract.toString() );
557 groupNode->removeCustomProperty( u"wmsAbstract"_s );
558 }
559}
560
561QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( const QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context )
562{
563 QgsLayerTreeGroup *node = readXml( element, context );
564 if ( !node )
565 return nullptr;
566
567 node->resolveReferences( project );
568
569 return node;
570}
571
572void QgsLayerTreeGroup::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context )
573{
574 QDomDocument doc = parentElement.ownerDocument();
575 QDomElement elem = doc.createElement( u"layer-tree-group"_s );
576 elem.setAttribute( u"name"_s, mName );
577 elem.setAttribute( u"expanded"_s, mExpanded ? u"1"_s : u"0"_s );
578 elem.setAttribute( u"checked"_s, mChecked ? u"Qt::Checked"_s : u"Qt::Unchecked"_s );
579 if ( mMutuallyExclusive )
580 {
581 elem.setAttribute( u"mutually-exclusive"_s, u"1"_s );
582 elem.setAttribute( u"mutually-exclusive-child"_s, mMutuallyExclusiveChildIndex );
583 }
584
586 {
587 elem.setAttribute( u"wms-has-time-dimension"_s, u"1"_s );
588 }
589
590 elem.setAttribute( u"wms-group-request-mode"_s, qgsEnumValueToKey( mWmsGroupRequestMode ) );
591
592 elem.setAttribute( u"groupLayer"_s, mGroupLayer.layerId );
593
594 writeCommonXml( elem );
595
596 serverProperties()->writeXml( elem, doc );
597
598 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
599 node->writeXml( elem, context );
600
601 parentElement.appendChild( elem );
602}
603
604void QgsLayerTreeGroup::readChildrenFromXml( const QDomElement &element, const QgsReadWriteContext &context )
605{
606 QList<QgsLayerTreeNode *> nodes;
607 QDomElement childElem = element.firstChildElement();
608 while ( !childElem.isNull() )
609 {
610 QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem, context );
611 if ( newNode )
612 nodes << newNode;
613
614 childElem = childElem.nextSiblingElement();
615 }
616
617 insertChildNodes( -1, nodes );
618}
619
621{
622 QString header = u"GROUP: %1 checked=%2 expanded=%3\n"_s.arg( name() ).arg( mChecked ).arg( mExpanded );
623 QStringList childrenDump;
624 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
625 childrenDump << node->dump().split( '\n' );
626 for ( int i = 0; i < childrenDump.count(); ++i )
627 childrenDump[i].prepend( " " );
628 return header + childrenDump.join( QLatin1Char( '\n' ) );
629}
630
632{
633 return new QgsLayerTreeGroup( *this );
634}
635
636void QgsLayerTreeGroup::resolveReferences( const QgsProject *project, bool looseMatching )
637{
638 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
639 node->resolveReferences( project, looseMatching );
640
641 mGroupLayer.resolve( project );
642}
643
644static bool _nodeIsChecked( QgsLayerTreeNode *node )
645{
646 return node->itemVisibilityChecked();
647}
648
649
654
655void QgsLayerTreeGroup::setIsMutuallyExclusive( bool enabled, int initialChildIndex )
656{
657 mMutuallyExclusive = enabled;
658 mMutuallyExclusiveChildIndex = initialChildIndex;
659
660 if ( !enabled )
661 {
662 return;
663 }
664
666 {
667 // try to use first checked index
668 int index = 0;
669 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
670 {
671 if ( _nodeIsChecked( child ) )
672 {
674 break;
675 }
676 index++;
677 }
678 }
679
681}
682
684{
685 return qobject_cast< QgsGroupLayer * >( mGroupLayer.layer );
686}
687
689{
690 if ( QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( mGroupLayer.get() ) )
691 {
692 if ( !layer )
693 {
694 groupLayer->prepareLayersForRemovalFromGroup();
695 }
696 }
697 mGroupLayer.setLayer( layer );
698 refreshParentGroupLayerMembers();
699}
700
702{
703 if ( !mGroupLayer.layerId.isEmpty() )
704 return nullptr;
705
706 auto res = std::make_unique< QgsGroupLayer >( name(), options );
707
708 mGroupLayer.setLayer( res.get() );
709 updateGroupLayers();
710
711 return res.release();
712}
713
714void QgsLayerTreeGroup::refreshParentGroupLayerMembers()
715{
716 QgsLayerTreeGroup *parentGroup = qobject_cast< QgsLayerTreeGroup * >( parent() );
717 while ( parentGroup )
718 {
719 if ( QgsLayerTree *layerTree = qobject_cast< QgsLayerTree * >( parentGroup ) )
720 layerTree->emit layerOrderChanged();
721
722 parentGroup->updateGroupLayers();
723 parentGroup = qobject_cast< QgsLayerTreeGroup * >( parentGroup->parent() );
724 }
725}
726
728{
729 QStringList lst;
730 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
731 {
732 if ( QgsLayerTree::isGroup( child ) )
733 lst << QgsLayerTree::toGroup( child )->findLayerIds();
734 else if ( QgsLayerTree::isLayer( child ) )
735 lst << QgsLayerTree::toLayer( child )->layerId();
736 }
737 return lst;
738}
739
741{
742 QStringList lst;
743 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
744 {
745 if ( QgsLayerTree::isGroup( child ) )
746 lst << QgsLayerTree::toGroup( child )->findCustomNodeIds();
747 else if ( QgsLayerTree::isCustomNode( child ) )
748 lst << QgsLayerTree::toCustomNode( child )->nodeId();
749 }
750 return lst;
751}
752
754{
755 int childIndex = mChildren.indexOf( node );
756 if ( childIndex == -1 )
757 {
758 updateGroupLayers();
759 return; // not a direct child - ignore
760 }
761
762 if ( mMutuallyExclusive )
763 {
764 if ( _nodeIsChecked( node ) )
765 mMutuallyExclusiveChildIndex = childIndex;
766 else if ( mMutuallyExclusiveChildIndex == childIndex )
768
769 // we need to make sure there is only one child node checked
771 }
772
773 updateGroupLayers();
774}
775
777{
778 if ( mChildren.isEmpty() )
779 return;
780
781 mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
782
783 int index = 0;
784 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
785 {
786 child->setItemVisibilityChecked( index == mMutuallyExclusiveChildIndex );
787 ++index;
788 }
789
791
792 updateGroupLayers();
793}
794
796{
798 // Reconnect internal signals
800}
801
802void QgsLayerTreeGroup::updateGroupLayers()
803{
804 QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( mGroupLayer.get() );
805 if ( !groupLayer )
806 return;
807
808 QList< QgsMapLayer * > layers;
809
810 std::function< void( QgsLayerTreeGroup * ) > findGroupLayerChildren;
811 findGroupLayerChildren = [&layers, &findGroupLayerChildren]( QgsLayerTreeGroup *group ) {
812 for ( auto it = group->mChildren.crbegin(); it != group->mChildren.crend(); ++it )
813 {
814 if ( QgsLayerTreeLayer *layerTreeLayer = qobject_cast< QgsLayerTreeLayer * >( *it ) )
815 {
816 if ( layerTreeLayer->layer() && layerTreeLayer->isVisible() )
817 layers << layerTreeLayer->layer();
818 }
819 else if ( QgsLayerTreeGroup *childGroup = qobject_cast< QgsLayerTreeGroup * >( *it ) )
820 {
821 if ( childGroup->isVisible() )
822 {
823 if ( QgsGroupLayer *groupLayer = childGroup->groupLayer() )
824 layers << groupLayer;
825 else
826 findGroupLayerChildren( childGroup );
827 }
828 }
829 }
830 };
831 findGroupLayerChildren( this );
832
833 groupLayer->setChildLayers( layers );
834 refreshParentGroupLayerMembers();
835}
836
838{
840
841 mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
842
843 int index = 0;
844 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
845 {
846 child->setItemVisibilityCheckedRecursive( checked && ( mMutuallyExclusiveChildIndex < 0 || index == mMutuallyExclusiveChildIndex ) );
847 ++index;
848 }
849
851
852 updateGroupLayers();
853}
854
856{
857 return mServerProperties.get();
858}
859
861{
862 return mServerProperties.get();
863}
864
869
874
876{
877 return mWmsGroupRequestMode;
878}
879
881{
882 mWmsGroupRequestMode = groupRequestMode;
883}
WmsGroupRequestMode
Request mode of groups in a WMS context.
Definition qgis.h:6764
@ Normal
Group and children can be requested.
Definition qgis.h:6765
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
Layer tree custom node serves as a node for objects that are not layers nor groups.
QString nodeId() const
Returns the node's unique identifier.
Layer tree group node serves as a container for layers and further groups.
QStringList findCustomNodeIds() const
Find custom node IDs.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
QgsLayerTreeCustomNode * insertCustomNode(int index, const QString &id, const QString &name=QString())
Insert a new custom node with the given id and name at specified index.
QgsLayerTreeCustomNode * findCustomNode(const QString &id) const
Find custom node representing an object specified by its ID.
void setName(const QString &n) override
Sets the group's name.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QgsGroupLayer * convertToGroupLayer(const QgsGroupLayer::LayerOptions &options)
Converts the group to a QgsGroupLayer.
void setHasWmsTimeDimension(const bool hasWmsTimeDimension)
Sets whether the WMS time dimension should be computed for this group or not.
QgsLayerTreeGroup * insertGroup(int index, const QString &name)
Insert a new group node with given name at specified position.
void readChildrenFromXml(const QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QList< QgsLayerTreeNode * > findLayersAndCustomNodes() const
Find all layer and custom nodes.
QList< QgsLayerTreeGroup * > findGroups(bool recursive=false) const
Find group layer nodes.
void writeXml(QDomElement &parentElement, const QgsReadWriteContext &context) override
Write group (tree) as XML element <layer-tree-group> and add it to the given parent element.
QString name() const override
Returns the group's name.
QgsLayerTreeGroup(const QString &name=QString(), bool checked=true)
Constructor.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
QList< QgsMapLayer * > layerOrderRespectingGroupLayers() const
Returns an ordered list of map layers in the group, ignoring any layers which are child layers of Qgs...
void removeCustomNode(QgsLayerTreeCustomNode *customNode)
Remove a custom node from this group.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the layer tree group.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
QList< QgsLayerTreeNode * > layerAndCustomNodeOrderRespectingGroupLayers() const
Returns an ordered list of map layers and custom nodes in the group, ignoring any layers which are ch...
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
void removeAllChildren()
Remove all child nodes.
bool mMutuallyExclusive
Whether the group is mutually exclusive (i.e. only one child can be checked at a time).
void setIsMutuallyExclusive(bool enabled, int initialChildIndex=-1)
Set whether the group is mutually exclusive (only one child can be checked at a time).
void setItemVisibilityCheckedRecursive(bool checked) override
Check or uncheck a node and all its children (taking into account exclusion rules).
QgsLayerTreeGroup * clone() const override
Returns a clone of the group.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
bool isMutuallyExclusive() const
Returns whether the group is mutually exclusive (only one child can be checked at a time).
QgsLayerTreeCustomNode * addCustomNode(const QString &id, const QString &name=QString())
Append a new custom node with the given id and name.
void updateChildVisibilityMutuallyExclusive()
Set check state of children - if mutually exclusive.
bool hasWmsTimeDimension() const
Returns whether the WMS time dimension should be computed for this group or not.
static QgsLayerTreeGroup * readXml(const QDomElement &element, const QgsReadWriteContext &context)
Read group (tree) from XML element <layer-tree-group> and return the newly created group (or nullptr ...
void setGroupLayer(QgsGroupLayer *layer)
Sets the associated group layer, if the layer tree group will be treated as group layer during map re...
QgsLayerTreeGroup * addGroup(const QString &name)
Append a new group node with given name.
Qgis::WmsGroupRequestMode wmsGroupRequestMode() const
Returns the request mode of the group.
void removeChildren(int from, int count)
Remove child nodes from index "from".
void removeChildrenGroupWithoutLayers()
Remove all child group nodes without layers.
QgsLayerTreeLayer * addLayer(QgsMapLayer *layer)
Append a new layer node for given map layer.
void makeOrphan() override
Sets parent to nullptr and disconnects all external and forwarded signals.
void removeLayer(QgsMapLayer *layer)
Remove map layer's node from this group.
void setWmsGroupRequestMode(Qgis::WmsGroupRequestMode groupRequestMode)
Sets the request mode of the group.
QgsLayerTreeLayer * insertLayer(int index, QgsMapLayer *layer)
Insert a new layer node for given map layer at specified position.
QString dump() const override
Returns text representation of the tree.
void nodeVisibilityChanged(QgsLayerTreeNode *node)
void reorderGroupLayers(const QList< QgsMapLayer * > &order)
Reorders layers in the group to match the order specified by order.
int mMutuallyExclusiveChildIndex
Keeps track which child has been most recently selected (so if the whole group is unchecked and check...
void reorderGroupLayersAndCustomNodes(const QList< QgsLayerTreeNode * > &order)
Reorders layers and custom nodes in the group to match the order specified by order.
QgsGroupLayer * groupLayer()
Returns a reference to the associated group layer, if the layer tree group will be treated as group l...
Layer tree node points to a map layer.
QString layerId() const
Returns the ID for the map layer associated with this node.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
Base class for nodes in a layer tree.
virtual void makeOrphan()
Sets parent to nullptr and disconnects all external and forwarded signals.
@ NodeGroup
Container of other groups and layers.
void removedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes has been removed from a node within the tree.
void nameChanged(QgsLayerTreeNode *node, QString name)
Emitted when the name of the node is changed.
static QgsLayerTreeNode * readXml(QDomElement &element, const QgsReadWriteContext &context)
Read layer tree from XML.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
void setExpanded(bool expanded)
Sets whether the node should be shown as expanded or collapsed in GUI.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
QgsLayerTreeNode(NodeType t, bool checked=true)
Constructor.
void writeCommonXml(QDomElement &element)
Write common XML elements.
void insertChildrenPrivate(int index, const QList< QgsLayerTreeNode * > &nodes)
Low-level insertion of children to the node. The children must not have any parent yet!
void addedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes have been added to a node within the tree.
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
QList< QgsLayerTreeNode * > mChildren
list of children - node is responsible for their deletion
bool mExpanded
whether the node should be shown in GUI as expanded
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).
void readCommonXml(const QDomElement &element)
Read common XML elements.
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children).
void removeChildrenPrivate(int from, int count, bool destroy=true)
Low-level removal of children from the node.
static Qt::CheckState checkStateFromXml(const QString &txt)
Convert QString to Qt::CheckState.
Namespace with helper functions for layer tree operations.
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.
static bool isCustomNode(const QgsLayerTreeNode *node)
Check whether the node is a valid custom node.
static QgsLayerTreeCustomNode * toCustomNode(QgsLayerTreeNode *node)
Cast node to a custom node.
Manages QGIS Server properties for a map layer.
void readXml(const QDomNode &layer_node)
Reads server properties from project file.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
void setShortName(const QString &name)
Sets the short name of the layer used by QGIS Server to identify the layer.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves server properties to xml under the layer node.
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
Definition qgsmaplayer.h:83
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
QString id
Definition qgsmaplayer.h:86
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
Translates a string using the Qt QTranslator mechanism.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:114
A container for the context for various read/write operations on objects.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7423
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7404
#define SIP_TRANSFER
Definition qgis_sip.h:35
_LayerRef< QgsMapLayer > QgsMapLayerRef
Setting options for loading group layers.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer.