QGIS API Documentation 4.3.0-Master (6402a64e93b)
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#include "qgsstringutils.h"
23
24#include <QDomElement>
25#include <QString>
26#include <QStringList>
27
28#include "moc_qgslayertreegroup.cpp"
29
30using namespace Qt::StringLiterals;
31
32QgsLayerTreeGroup::QgsLayerTreeGroup( const QString &name, bool checked )
33 : QgsLayerTreeNode( NodeGroup, checked )
34 , mName( name )
35 , mId( QgsStringUtils::createUniqueId( u"group"_s ) )
36 , mServerProperties( std::make_unique<QgsMapLayerServerProperties>() )
37{
38 init();
39}
40
42 : QgsLayerTreeNode( other )
43 , mName( other.mName )
44 , mId( other.mId )
49 , mGroupLayer( other.mGroupLayer )
50 , mServerProperties( std::make_unique<QgsMapLayerServerProperties>() )
51 , mWmsGroupRequestMode( other.mWmsGroupRequestMode )
52{
53 other.serverProperties()->copyTo( mServerProperties.get() );
54
55 init();
56}
57
58void QgsLayerTreeGroup::init()
59{
61 connect( this, &QgsLayerTreeNode::addedChildren, this, &QgsLayerTreeGroup::updateGroupLayers );
62 connect( this, &QgsLayerTreeNode::removedChildren, this, &QgsLayerTreeGroup::updateGroupLayers );
63 connect( this, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeGroup::updateGroupLayers );
64}
65
67{
68 return mName;
69}
70
71void QgsLayerTreeGroup::setName( const QString &n )
72{
73 if ( mName == n )
74 return;
75
76 mName = n;
77 emit nameChanged( this, n );
78}
79
80void QgsLayerTreeGroup::setId( const QString &id )
81{
82 mId = id;
83}
84
85
87{
89 insertChildNode( index, grp );
90 return grp;
91}
92
94{
96 addChildNode( grp );
97 return grp;
98}
99
101{
102 if ( !layer )
103 return nullptr;
104
105 QgsLayerTreeLayer *ll = new QgsLayerTreeLayer( layer );
106 insertChildNode( index, ll );
107
108 updateGroupLayers();
109 return ll;
110}
111
113{
114 if ( !layer )
115 return nullptr;
116
117 QgsLayerTreeLayer *ll = new QgsLayerTreeLayer( layer );
118 addChildNode( ll );
119
120 updateGroupLayers();
121 return ll;
122}
123
124QgsLayerTreeCustomNode *QgsLayerTreeGroup::insertCustomNode( int index, const QString &id, const QString &name )
125{
126 if ( id.trimmed().isEmpty() )
127 return nullptr;
128
129 // Avoid registering two custom nodes with the same id
130 const QStringList customNodeIds = findCustomNodeIds();
131 if ( customNodeIds.contains( id ) )
132 return nullptr;
133
134 QgsLayerTreeCustomNode *customNode = new QgsLayerTreeCustomNode( id, name );
135 insertChildNode( index, customNode );
136 return customNode;
137}
138
140{
141 if ( node->id().trimmed().isEmpty() )
142 return nullptr;
143
144 // Avoid registering two custom nodes with the same id
145 const QStringList customNodeIds = findCustomNodeIds();
146 if ( customNodeIds.contains( node->id() ) )
147 return nullptr;
148
149 insertChildNode( index, node );
150 return node;
151}
152
154{
155 if ( id.trimmed().isEmpty() )
156 return nullptr;
157
158 // Avoid registering two custom nodes with the same id
159 const QStringList customNodeIds = findCustomNodeIds();
160 if ( customNodeIds.contains( id ) )
161 return nullptr;
162
163 QgsLayerTreeCustomNode *customNode = new QgsLayerTreeCustomNode( id, name );
164 addChildNode( customNode );
165 return customNode;
166}
167
169{
170 QList<QgsLayerTreeNode *> nodes;
171 nodes << node;
172 insertChildNodes( index, nodes );
173}
174
175void QgsLayerTreeGroup::insertChildNodes( int index, const QList<QgsLayerTreeNode *> &nodes )
176{
177 QgsLayerTreeNode *meChild = nullptr;
180
181 // low-level insert
182 insertChildrenPrivate( index, nodes );
183
184 if ( mMutuallyExclusive )
185 {
186 if ( meChild )
187 {
188 // the child could have change its index - or the new children may have been also set as visible
189 mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
190 }
191 else if ( mChecked )
192 {
193 // we have not picked a child index yet, but we should pick one now
194 // ... so pick the first one from the newly added
195 if ( index == -1 )
196 index = mChildren.count() - nodes.count(); // get real insertion index
198 }
200 }
201
202 updateGroupLayers();
203}
204
206{
207 insertChildNode( -1, node );
208
209 updateGroupLayers();
210}
211
213{
214 int i = mChildren.indexOf( node );
215 if ( i >= 0 )
216 removeChildren( i, 1 );
217
218 updateGroupLayers();
219}
220
222{
223 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
224 {
225 if ( QgsLayerTree::isLayer( child ) )
226 {
227 QgsLayerTreeLayer *childLayer = QgsLayerTree::toLayer( child );
228 if ( childLayer->layer() == layer )
229 {
230 removeChildren( mChildren.indexOf( child ), 1 );
231 break;
232 }
233 }
234 }
235
236 updateGroupLayers();
237}
238
240{
241 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
242 {
243 if ( QgsLayerTree::isCustomNode( child ) )
244 {
246 if ( childCustom->id() == customNode->id() )
247 {
248 removeChildren( mChildren.indexOf( child ), 1 );
249 break;
250 }
251 }
252 }
253
254 updateGroupLayers();
255}
256
257void QgsLayerTreeGroup::removeChildren( int from, int count )
258{
259 QgsLayerTreeNode *meChild = nullptr;
262
263 removeChildrenPrivate( from, count );
264
265 if ( meChild )
266 {
267 // the child could have change its index - or may have been removed completely
268 mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
269 // we need to uncheck this group
270 //if ( mMutuallyExclusiveChildIndex == -1 )
271 // setItemVisibilityChecked( false );
272 }
273
274 updateGroupLayers();
275}
276
278{
279 // clean the layer tree by removing empty group
280 const auto childNodes = children();
281 for ( QgsLayerTreeNode *treeNode : childNodes )
282 {
283 if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
284 {
285 QgsLayerTreeGroup *treeGroup = qobject_cast<QgsLayerTreeGroup *>( treeNode );
286 if ( treeGroup->findLayerIds().isEmpty() )
287 removeChildNode( treeNode );
288 else
290 }
291 }
292
293 updateGroupLayers();
294}
295
300
302{
303 if ( !layer )
304 return nullptr;
305
306 return findLayer( layer->id() );
307}
308
309QgsLayerTreeLayer *QgsLayerTreeGroup::findLayer( const QString &layerId ) const
310{
311 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
312 {
313 if ( QgsLayerTree::isLayer( child ) )
314 {
315 QgsLayerTreeLayer *childLayer = QgsLayerTree::toLayer( child );
316 if ( childLayer->layerId() == layerId )
317 return childLayer;
318 }
319 else if ( QgsLayerTree::isGroup( child ) )
320 {
321 QgsLayerTreeLayer *res = QgsLayerTree::toGroup( child )->findLayer( layerId );
322 if ( res )
323 return res;
324 }
325 }
326 return nullptr;
327}
328
329QList<QgsLayerTreeLayer *> QgsLayerTreeGroup::findLayers() const
330{
331 QList<QgsLayerTreeLayer *> list;
332 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
333 {
334 if ( QgsLayerTree::isLayer( child ) )
335 list << QgsLayerTree::toLayer( child );
336 else if ( QgsLayerTree::isGroup( child ) )
337 list << QgsLayerTree::toGroup( child )->findLayers();
338 }
339 return list;
340}
341
343{
344 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
345 {
346 if ( QgsLayerTree::isCustomNode( child ) )
347 {
349 if ( childCustom->id() == id )
350 return childCustom;
351 }
352 else if ( QgsLayerTree::isGroup( child ) )
353 {
355 if ( res )
356 return res;
357 }
358 }
359 return nullptr;
360}
361
362QList<QgsLayerTreeNode *> QgsLayerTreeGroup::findLayersAndCustomNodes() const
363{
364 QList<QgsLayerTreeNode *> list;
365 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
366 {
367 if ( QgsLayerTree::isLayer( child ) || QgsLayerTree::isCustomNode( child ) )
368 list << child;
369 else if ( QgsLayerTree::isGroup( child ) )
371 }
372 return list;
373}
374
375void QgsLayerTreeGroup::reorderGroupLayers( const QList<QgsMapLayer *> &order )
376{
377 const QList< QgsLayerTreeLayer * > childLayers = findLayers();
378 int targetIndex = 0;
379 for ( QgsMapLayer *targetLayer : order )
380 {
381 for ( QgsLayerTreeLayer *layerNode : childLayers )
382 {
383 if ( layerNode->layer() == targetLayer )
384 {
385 QgsLayerTreeLayer *cloned = layerNode->clone();
386 insertChildNode( targetIndex, cloned );
387 removeChildNode( layerNode );
388 targetIndex++;
389 break;
390 }
391 }
392 }
393}
394
395void QgsLayerTreeGroup::reorderGroupLayersAndCustomNodes( const QList<QgsLayerTreeNode *> &order )
396{
397 const QList< QgsLayerTreeNode * > childNodes = findLayersAndCustomNodes();
398 int targetIndex = 0;
399 for ( QgsLayerTreeNode *targetNode : order )
400 {
401 for ( QgsLayerTreeNode *childNode : childNodes )
402 {
403 if ( childNode == targetNode )
404 {
405 QgsLayerTreeNode *cloned = childNode->clone();
406 insertChildNode( targetIndex, cloned );
407 removeChildNode( childNode );
408 targetIndex++;
409 break;
410 }
411 }
412 }
413}
414
416{
417 QList<QgsMapLayer *> list;
418 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
419 {
420 if ( QgsLayerTree::isLayer( child ) )
421 {
422 QgsMapLayer *layer = QgsLayerTree::toLayer( child )->layer();
423 if ( !layer || !layer->isSpatial() )
424 continue;
425 list << layer;
426 }
427 else if ( QgsLayerTree::isGroup( child ) )
428 {
430 if ( group->groupLayer() )
431 {
432 list << group->groupLayer();
433 }
434 else
435 {
436 list << group->layerOrderRespectingGroupLayers();
437 }
438 }
439 }
440 return list;
441}
442
444{
445 QList<QgsLayerTreeNode *> list;
446 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
447 {
448 if ( QgsLayerTree::isLayer( child ) )
449 {
450 QgsMapLayer *layer = QgsLayerTree::toLayer( child )->layer();
451 if ( !layer || !layer->isSpatial() )
452 continue;
453 list << child;
454 }
455 else if ( QgsLayerTree::isCustomNode( child ) )
456 {
457 list << child;
458 }
459 else if ( QgsLayerTree::isGroup( child ) )
460 {
462 if ( group->groupLayer() )
463 {
464 list << group;
465 }
466 else
467 {
469 }
470 }
471 }
472 return list;
473}
474
476{
477 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
478 {
479 if ( QgsLayerTree::isGroup( child ) )
480 {
481 QgsLayerTreeGroup *childGroup = QgsLayerTree::toGroup( child );
482 if ( childGroup->name() == name )
483 return childGroup;
484 else
485 {
486 QgsLayerTreeGroup *grp = childGroup->findGroup( name );
487 if ( grp )
488 return grp;
489 }
490 }
491 }
492 return nullptr;
493}
494
495QList<QgsLayerTreeGroup *> QgsLayerTreeGroup::findGroups( bool recursive ) const
496{
497 QList<QgsLayerTreeGroup *> list;
498
499 for ( QgsLayerTreeNode *child : mChildren )
500 {
501 if ( QgsLayerTree::isGroup( child ) )
502 {
503 QgsLayerTreeGroup *childGroup = QgsLayerTree::toGroup( child );
504 list << childGroup;
505 if ( recursive )
506 list << childGroup->findGroups( recursive );
507 }
508 }
509 return list;
510}
511
512QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( const QDomElement &element, const QgsReadWriteContext &context ) // cppcheck-suppress duplInheritedMember
513{
514 if ( element.tagName() != "layer-tree-group"_L1 )
515 return nullptr;
516
517 QString name = context.projectTranslator()->translate( u"project:layergroups"_s, element.attribute( u"name"_s ) );
518 bool isExpanded = ( element.attribute( u"expanded"_s, u"1"_s ) == "1"_L1 );
519 bool checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( u"checked"_s ) ) != Qt::Unchecked;
520 bool isMutuallyExclusive = element.attribute( u"mutually-exclusive"_s, u"0"_s ) == "1"_L1;
521 int mutuallyExclusiveChildIndex = element.attribute( u"mutually-exclusive-child"_s, u"-1"_s ).toInt();
522
523 QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( name, checked );
524 // maintains backwards compatibility
525 const QString id = element.attribute( u"id"_s );
526 if ( !id.isEmpty() )
527 groupNode->mId = id;
528 groupNode->setExpanded( isExpanded );
529
530 groupNode->readCommonXml( element );
531
532 groupNode->readChildrenFromXml( element, context );
533
534 groupNode->setIsMutuallyExclusive( isMutuallyExclusive, mutuallyExclusiveChildIndex );
535
536 groupNode->mWmsHasTimeDimension = element.attribute( u"wms-has-time-dimension"_s, u"0"_s ) == "1"_L1;
537
538 groupNode->mWmsGroupRequestMode = { qgsEnumKeyToValue( element.attribute( u"wms-group-request-mode"_s ), Qgis::WmsGroupRequestMode::Normal ) };
539
540 groupNode->mGroupLayer = QgsMapLayerRef( element.attribute( u"groupLayer"_s ) );
541
542 readLegacyServerProperties( groupNode );
543
544 groupNode->serverProperties()->readXml( element );
545
546 return groupNode;
547}
548
549void QgsLayerTreeGroup::readLegacyServerProperties( QgsLayerTreeGroup *groupNode )
550{
551 const QVariant wmsShortName = groupNode->customProperty( u"wmsShortName"_s );
552 if ( wmsShortName.isValid() )
553 {
554 groupNode->serverProperties()->setShortName( wmsShortName.toString() );
555 groupNode->removeCustomProperty( u"wmsShortName"_s );
556 }
557
558 const QVariant wmsTitle = groupNode->customProperty( u"wmsTitle"_s );
559 if ( wmsTitle.isValid() )
560 {
561 groupNode->serverProperties()->setTitle( wmsTitle.toString() );
562 groupNode->removeCustomProperty( u"wmsTitle"_s );
563 }
564
565 const QVariant wmsAbstract = groupNode->customProperty( u"wmsAbstract"_s );
566 if ( wmsAbstract.isValid() )
567 {
568 groupNode->serverProperties()->setAbstract( wmsAbstract.toString() );
569 groupNode->removeCustomProperty( u"wmsAbstract"_s );
570 }
571}
572
573QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( const QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context )
574{
575 QgsLayerTreeGroup *node = readXml( element, context );
576 if ( !node )
577 return nullptr;
578
579 node->resolveReferences( project );
580
581 return node;
582}
583
584void QgsLayerTreeGroup::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context )
585{
586 QDomDocument doc = parentElement.ownerDocument();
587 QDomElement elem = doc.createElement( u"layer-tree-group"_s );
588 elem.setAttribute( u"name"_s, mName );
589 elem.setAttribute( u"id"_s, mId );
590 elem.setAttribute( u"expanded"_s, mExpanded ? u"1"_s : u"0"_s );
591 elem.setAttribute( u"checked"_s, mChecked ? u"Qt::Checked"_s : u"Qt::Unchecked"_s );
592 if ( mMutuallyExclusive )
593 {
594 elem.setAttribute( u"mutually-exclusive"_s, u"1"_s );
595 elem.setAttribute( u"mutually-exclusive-child"_s, mMutuallyExclusiveChildIndex );
596 }
597
599 {
600 elem.setAttribute( u"wms-has-time-dimension"_s, u"1"_s );
601 }
602
603 elem.setAttribute( u"wms-group-request-mode"_s, qgsEnumValueToKey( mWmsGroupRequestMode ) );
604
605 elem.setAttribute( u"groupLayer"_s, mGroupLayer.layerId );
606
607 writeCommonXml( elem );
608
609 serverProperties()->writeXml( elem, doc );
610
611 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
612 node->writeXml( elem, context );
613
614 parentElement.appendChild( elem );
615}
616
617void QgsLayerTreeGroup::readChildrenFromXml( const QDomElement &element, const QgsReadWriteContext &context )
618{
619 QList<QgsLayerTreeNode *> nodes;
620 QDomElement childElem = element.firstChildElement();
621 while ( !childElem.isNull() )
622 {
623 QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem, context );
624 if ( newNode )
625 nodes << newNode;
626
627 childElem = childElem.nextSiblingElement();
628 }
629
630 insertChildNodes( -1, nodes );
631}
632
634{
635 QString header = u"GROUP: %1 checked=%2 expanded=%3\n"_s.arg( name() ).arg( mChecked ).arg( mExpanded );
636 QStringList childrenDump;
637 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
638 childrenDump << node->dump().split( '\n' );
639 for ( int i = 0; i < childrenDump.count(); ++i )
640 childrenDump[i].prepend( " " );
641 return header + childrenDump.join( QLatin1Char( '\n' ) );
642}
643
645{
646 return new QgsLayerTreeGroup( *this );
647}
648
649void QgsLayerTreeGroup::resolveReferences( const QgsProject *project, bool looseMatching )
650{
651 for ( QgsLayerTreeNode *node : std::as_const( mChildren ) )
652 node->resolveReferences( project, looseMatching );
653
654 mGroupLayer.resolve( project );
655}
656
657static bool _nodeIsChecked( QgsLayerTreeNode *node )
658{
659 return node->itemVisibilityChecked();
660}
661
662
667
668void QgsLayerTreeGroup::setIsMutuallyExclusive( bool enabled, int initialChildIndex )
669{
670 mMutuallyExclusive = enabled;
671 mMutuallyExclusiveChildIndex = initialChildIndex;
672
673 if ( !enabled )
674 {
675 return;
676 }
677
679 {
680 // try to use first checked index
681 int index = 0;
682 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
683 {
684 if ( _nodeIsChecked( child ) )
685 {
687 break;
688 }
689 index++;
690 }
691 }
692
694}
695
697{
698 return qobject_cast< QgsGroupLayer * >( mGroupLayer.layer );
699}
700
702{
703 if ( QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( mGroupLayer.get() ) )
704 {
705 if ( !layer )
706 {
707 groupLayer->prepareLayersForRemovalFromGroup();
708 }
709 }
710 mGroupLayer.setLayer( layer );
711 refreshParentGroupLayerMembers();
712}
713
715{
716 if ( !mGroupLayer.layerId.isEmpty() )
717 return nullptr;
718
719 auto res = std::make_unique< QgsGroupLayer >( name(), options );
720
721 mGroupLayer.setLayer( res.get() );
722 updateGroupLayers();
723
724 return res.release();
725}
726
727void QgsLayerTreeGroup::refreshParentGroupLayerMembers()
728{
729 QgsLayerTreeGroup *parentGroup = qobject_cast< QgsLayerTreeGroup * >( parent() );
730 while ( parentGroup )
731 {
732 if ( QgsLayerTree *layerTree = qobject_cast< QgsLayerTree * >( parentGroup ) )
733 layerTree->emit layerOrderChanged();
734
735 parentGroup->updateGroupLayers();
736 parentGroup = qobject_cast< QgsLayerTreeGroup * >( parentGroup->parent() );
737 }
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 )->findLayerIds();
747 else if ( QgsLayerTree::isLayer( child ) )
748 lst << QgsLayerTree::toLayer( child )->layerId();
749 }
750 return lst;
751}
752
754{
755 QStringList lst;
756 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
757 {
758 if ( QgsLayerTree::isGroup( child ) )
759 lst << QgsLayerTree::toGroup( child )->findCustomNodeIds();
760 else if ( QgsLayerTree::isCustomNode( child ) )
761 lst << QgsLayerTree::toCustomNode( child )->id();
762 }
763 return lst;
764}
765
767{
768 int childIndex = mChildren.indexOf( node );
769 if ( childIndex == -1 )
770 {
771 updateGroupLayers();
772 return; // not a direct child - ignore
773 }
774
775 if ( mMutuallyExclusive )
776 {
777 if ( _nodeIsChecked( node ) )
778 mMutuallyExclusiveChildIndex = childIndex;
779 else if ( mMutuallyExclusiveChildIndex == childIndex )
781
782 // we need to make sure there is only one child node checked
784 }
785
786 updateGroupLayers();
787}
788
790{
791 if ( mChildren.isEmpty() )
792 return;
793
794 mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
795
796 int index = 0;
797 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
798 {
799 child->setItemVisibilityChecked( index == mMutuallyExclusiveChildIndex );
800 ++index;
801 }
802
804
805 updateGroupLayers();
806}
807
809{
811 // Reconnect internal signals
813}
814
815void QgsLayerTreeGroup::updateGroupLayers()
816{
817 QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( mGroupLayer.get() );
818 if ( !groupLayer )
819 return;
820
821 QList< QgsMapLayer * > layers;
822
823 std::function< void( QgsLayerTreeGroup * ) > findGroupLayerChildren;
824 findGroupLayerChildren = [&layers, &findGroupLayerChildren]( QgsLayerTreeGroup *group ) {
825 for ( auto it = group->mChildren.crbegin(); it != group->mChildren.crend(); ++it )
826 {
827 if ( QgsLayerTreeLayer *layerTreeLayer = qobject_cast< QgsLayerTreeLayer * >( *it ) )
828 {
829 if ( layerTreeLayer->layer() && layerTreeLayer->isVisible() )
830 layers << layerTreeLayer->layer();
831 }
832 else if ( QgsLayerTreeGroup *childGroup = qobject_cast< QgsLayerTreeGroup * >( *it ) )
833 {
834 if ( childGroup->isVisible() )
835 {
836 if ( QgsGroupLayer *groupLayer = childGroup->groupLayer() )
837 layers << groupLayer;
838 else
839 findGroupLayerChildren( childGroup );
840 }
841 }
842 }
843 };
844 findGroupLayerChildren( this );
845
846 groupLayer->setChildLayers( layers );
847 refreshParentGroupLayerMembers();
848}
849
851{
853
854 mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
855
856 int index = 0;
857 for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
858 {
859 child->setItemVisibilityCheckedRecursive( checked && ( mMutuallyExclusiveChildIndex < 0 || index == mMutuallyExclusiveChildIndex ) );
860 ++index;
861 }
862
864
865 updateGroupLayers();
866}
867
869{
870 return mServerProperties.get();
871}
872
874{
875 return mServerProperties.get();
876}
877
882
887
889{
890 return mWmsGroupRequestMode;
891}
892
894{
895 mWmsGroupRequestMode = groupRequestMode;
896}
WmsGroupRequestMode
Request mode of groups in a WMS context.
Definition qgis.h:6942
@ Normal
Group and children can be requested.
Definition qgis.h:6943
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 id() const override
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).
QString id() const override
Returns the node's unique identifier.
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.
Utility functions for working with strings.
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:7743
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7724
#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.