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