29using namespace Qt::StringLiterals;
31static void _readOldLegendGroup(
const QDomElement &groupElem,
QgsLayerTreeGroup *parent );
32static void _readOldLegendLayer(
const QDomElement &layerElem,
QgsLayerTreeGroup *parent );
36 if ( legendElem.isNull() )
39 const QDomNodeList legendChildren = legendElem.childNodes();
41 for (
int i = 0; i < legendChildren.size(); ++i )
43 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
44 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
46 _readOldLegendLayer( currentChildElem, root );
48 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
50 _readOldLegendGroup( currentChildElem, root );
58static bool _readOldLegendLayerOrderGroup(
const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
60 const QDomNodeList legendChildren = groupElem.childNodes();
62 for (
int i = 0; i < legendChildren.size(); ++i )
64 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
65 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
67 const QDomElement layerFileElem = currentChildElem.firstChildElement( u
"filegroup"_s ).firstChildElement( u
"legendlayerfile"_s );
69 const int layerIndex = currentChildElem.attribute( u
"drawingOrder"_s ).toInt();
70 if ( layerIndex == -1 )
72 layerIndexes.insert( layerIndex, layerFileElem.attribute( u
"layerid"_s ) );
74 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
76 if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
87 if ( legendElem.isNull() )
90 hasCustomOrder = legendElem.attribute( u
"updateDrawingOrder"_s ) ==
"false"_L1;
93 QMap<int, QString> layerIndexes;
96 const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
98 if ( !res && hasCustomOrder )
101 const auto constLayerIndexes = layerIndexes;
102 for (
const QString &layerId : constLayerIndexes )
105 order.append( layerId );
112static QDomElement _writeOldLegendLayer( QDomDocument &doc,
QgsLayerTreeLayer *nodeLayer,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
114 int drawingOrder = -1;
115 if ( hasCustomOrder )
116 drawingOrder = order.indexOf( nodeLayer->
layer() );
118 QDomElement layerElem = doc.createElement( u
"legendlayer"_s );
119 layerElem.setAttribute( u
"drawingOrder"_s, drawingOrder );
120 layerElem.setAttribute( u
"open"_s, nodeLayer->
isExpanded() ? u
"true"_s : u
"false"_s );
122 layerElem.setAttribute( u
"name"_s, nodeLayer->
name() );
123 layerElem.setAttribute( u
"showFeatureCount"_s, nodeLayer->
customProperty( u
"showFeatureCount"_s ).toInt() );
125 QDomElement fileGroupElem = doc.createElement( u
"filegroup"_s );
126 fileGroupElem.setAttribute( u
"open"_s, nodeLayer->
isExpanded() ? u
"true"_s : u
"false"_s );
127 fileGroupElem.setAttribute( u
"hidden"_s, u
"false"_s );
129 QDomElement layerFileElem = doc.createElement( u
"legendlayerfile"_s );
130 layerFileElem.setAttribute( u
"isInOverview"_s, nodeLayer->
customProperty( u
"overview"_s ).toInt() );
131 layerFileElem.setAttribute( u
"layerid"_s, nodeLayer->
layerId() );
132 layerFileElem.setAttribute( u
"visible"_s, nodeLayer->
isVisible() ? 1 : 0 );
134 layerElem.appendChild( fileGroupElem );
135 fileGroupElem.appendChild( layerFileElem );
140static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order );
142static QDomElement _writeOldLegendGroup( QDomDocument &doc,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
144 QDomElement groupElem = doc.createElement( u
"legendgroup"_s );
145 groupElem.setAttribute( u
"open"_s, nodeGroup->
isExpanded() ? u
"true"_s : u
"false"_s );
146 groupElem.setAttribute( u
"name"_s, nodeGroup->
name() );
151 groupElem.setAttribute( u
"embedded"_s, 1 );
152 groupElem.setAttribute( u
"project"_s, nodeGroup->
customProperty( u
"embedded_project"_s ).toString() );
155 _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
160static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
162 const auto constChildren = nodeGroup->
children();
167 groupElem.appendChild( _writeOldLegendGroup( doc,
QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
171 groupElem.appendChild( _writeOldLegendLayer( doc,
QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
179 QDomElement legendElem = doc.createElement( u
"legend"_s );
180 legendElem.setAttribute( u
"updateDrawingOrder"_s, hasCustomOrder ? u
"false"_s : u
"true"_s );
182 _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
193 return u
"Qt::Unchecked"_s;
194 case Qt::PartiallyChecked:
195 return u
"Qt::PartiallyChecked"_s;
197 return u
"Qt::Checked"_s;
204 if ( txt ==
"Qt::Unchecked"_L1 )
205 return Qt::Unchecked;
206 else if ( txt ==
"Qt::PartiallyChecked"_L1 )
207 return Qt::PartiallyChecked;
213static void _readOldLegendGroup(
const QDomElement &groupElem,
QgsLayerTreeGroup *parent )
215 const QDomNodeList groupChildren = groupElem.childNodes();
220 groupNode->
setExpanded( groupElem.attribute( u
"open"_s ) ==
"true"_L1 );
222 if ( groupElem.attribute( u
"embedded"_s ) ==
"1"_L1 )
225 groupNode->
setCustomProperty( u
"embedded_project"_s, groupElem.attribute( u
"project"_s ) );
228 for (
int i = 0; i < groupChildren.size(); ++i )
230 const QDomElement currentChildElem = groupChildren.at( i ).toElement();
231 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
233 _readOldLegendLayer( currentChildElem, groupNode );
235 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
237 _readOldLegendGroup( currentChildElem, groupNode );
244static void _readOldLegendLayer(
const QDomElement &layerElem,
QgsLayerTreeGroup *parent )
246 const QDomElement layerFileElem = layerElem.firstChildElement( u
"filegroup"_s ).firstChildElement( u
"legendlayerfile"_s );
247 const QString layerId = layerFileElem.attribute( u
"layerid"_s );
251 layerNode->
setExpanded( layerElem.attribute( u
"open"_s ) ==
"true"_L1 );
253 if ( layerFileElem.attribute( u
"isInOverview"_s ) ==
"1"_L1 )
256 if ( layerElem.attribute( u
"embedded"_s ) ==
"1"_L1 )
259 if ( layerElem.attribute( u
"showFeatureCount"_s ) ==
"1"_L1 )
269 const auto constLayerNodes = layerNodes;
284 const auto constLayerNodes = layerNodes;
299 QList<QgsLayerTreeNode *> nodesToRemove;
300 const auto constChildren = group->
children();
308 nodesToRemove << node;
312 const auto constNodesToRemove = nodesToRemove;
322 const QList<QgsLayerTreeNode *> children = node->
children();
329 const QDomElement projectLayersElement { doc->documentElement().firstChildElement( u
"projectlayers"_s ) };
340 QDomElement layerElement { projectLayersElement.firstChildElement( u
"maplayer"_s ) };
341 while ( !layerElement.isNull() )
343 const QString id( layerElement.firstChildElement( u
"id"_s ).firstChild().nodeValue() );
347 QTextStream stream( &str );
348 layerElement.save( stream, 4 );
349 l->setOriginalXmlProperties( u
"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1"_s.arg( str ) );
352 layerElement = layerElement.nextSiblingElement();
358 const QList<QgsLayerTreeNode *> constChildren( node->children() );
359 for (
const auto &childNode : constChildren )
366 const QList<QgsLayerTreeNode *> children = group->
children();
382 if ( child->itemVisibilityChecked() == Qt::Unchecked )
401 const auto constChildren = group->
children();
406 if ( child->customProperty( u
"embedded"_s ).toInt() )
408 child->setCustomProperty( u
"embedded-invisible-layers"_s,
invisibleLayerList( child ) );
422 const auto constChildren = group->
children();
425 if ( !node->customProperty( u
"embedded_project"_s ).toString().isEmpty() )
428 const QString newPath = project->
writePath( node->customProperty( u
"embedded_project"_s ).toString() );
429 node->setCustomProperty( u
"embedded_project"_s, newPath );
442 layer.
setCustomProperty( u
"legend/expressionFilterEnabled"_s, enabled && !expr.isEmpty() );
447 const QString expression = layer.
customProperty( u
"legend/expressionFilter"_s, QString() ).toString();
449 *enabled = !expression.isEmpty() && layer.
customProperty( u
"legend/expressionFilterEnabled"_s, QString() ).toBool();
455 const auto constFindLayers = group.
findLayers();
460 if ( exprEnabled && !expr.isEmpty() )
487 return parent->
insertLayer( idx + 1, layerToInsert );
490static void _collectMapLayers(
const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
497 if ( nodeLayer->
layer() )
498 layersSet << nodeLayer->
layer();
509 QSet<QgsMapLayer *> layersSet;
510 _collectMapLayers( nodes, layersSet );
524 const QList<QgsLayerTreeNode *> children = tree->
children();
548 int vectorLineIndex = 0;
549 int vectorPolygonIndex = 0;
550 int pointCloudIndex = 0;
553 int basemapIndex = 0;
555 const QList<QgsLayerTreeNode *> children = group->
children();
562 const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
566 switch ( childLayer->
type() )
573 if ( vectorLineIndex < nodeIdx )
574 vectorLineIndex = nodeIdx;
575 if ( vectorPolygonIndex < nodeIdx )
576 vectorPolygonIndex = nodeIdx;
577 if ( pointCloudIndex < nodeIdx )
578 pointCloudIndex = nodeIdx;
579 if ( meshIndex < nodeIdx )
581 if ( rasterIndex < nodeIdx )
582 rasterIndex = nodeIdx;
583 if ( basemapIndex < nodeIdx )
584 basemapIndex = nodeIdx;
588 if ( vectorPolygonIndex < nodeIdx )
589 vectorPolygonIndex = nodeIdx;
590 if ( pointCloudIndex < nodeIdx )
591 pointCloudIndex = nodeIdx;
592 if ( meshIndex < nodeIdx )
594 if ( rasterIndex < nodeIdx )
595 rasterIndex = nodeIdx;
596 if ( basemapIndex < nodeIdx )
597 basemapIndex = nodeIdx;
601 if ( pointCloudIndex < nodeIdx )
602 pointCloudIndex = nodeIdx;
603 if ( meshIndex < nodeIdx )
605 if ( rasterIndex < nodeIdx )
606 rasterIndex = nodeIdx;
607 if ( basemapIndex < nodeIdx )
608 basemapIndex = nodeIdx;
615 if ( meshIndex < nodeIdx )
617 if ( rasterIndex < nodeIdx )
618 rasterIndex = nodeIdx;
619 if ( basemapIndex < nodeIdx )
620 basemapIndex = nodeIdx;
626 if ( rasterIndex < nodeIdx )
627 rasterIndex = nodeIdx;
628 if ( basemapIndex < nodeIdx )
629 basemapIndex = nodeIdx;
639 if ( basemapIndex < nodeIdx )
640 basemapIndex = nodeIdx;
656 switch ( layer->
type() )
667 index = vectorLineIndex;
671 index = vectorPolygonIndex;
678 index = pointCloudIndex;
696 index = basemapIndex;
703 index = basemapIndex;
@ UsersCannotToggleEditing
Indicates that users are not allowed to toggle editing for this layer. Note that this does not imply ...
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
virtual QString name() const =0
Returns a provider name.
Layer tree group node serves as a container for layers and further groups.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString name() const override
Returns the group's name.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
void removeAllChildren()
Remove all child nodes.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
QgsLayerTreeLayer * insertLayer(int index, QgsMapLayer *layer)
Insert a new layer node for given map layer at specified position.
Layer tree node points to a map layer.
QString layerId() const
Returns the ID for the map layer associated with this node.
QString name() const override
Returns the layer's name.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
Base class for nodes in a layer tree.
@ NodeLayer
Leaf node pointing to a layer.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well).
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
void setExpanded(bool expanded)
Sets whether the node should be shown as expanded or collapsed in GUI.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
bool isExpanded() const
Returns whether the node should be shown as expanded or collapsed in GUI.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children).
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children).
static bool layersEditable(const QList< QgsLayerTreeLayer * > &layerNodes, bool ignoreLayersWhichCannotBeToggled=false)
Returns true if any of the specified layers is editable.
static QString checkStateToXml(Qt::CheckState state)
Convert Qt::CheckState to QString.
static void replaceChildrenOfEmbeddedGroups(QgsLayerTreeGroup *group)
Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers.
static QgsLayerTreeLayer * insertLayerBelow(QgsLayerTreeGroup *group, const QgsMapLayer *refLayer, QgsMapLayer *layerToInsert)
Insert a QgsMapLayer just below another one.
static void setLegendFilterByExpression(QgsLayerTreeLayer &layer, const QString &expr, bool enabled=true)
Sets the expression filter of a legend layer.
static QString legendFilterByExpression(const QgsLayerTreeLayer &layer, bool *enabled=nullptr)
Returns the expression filter of a legend layer.
static void storeOriginalLayersProperties(QgsLayerTreeGroup *group, const QDomDocument *doc)
Stores in a layer's originalXmlProperties the layer properties information.
static QSet< QgsMapLayer * > collectMapLayersRecursive(const QList< QgsLayerTreeNode * > &nodes)
Returns map layers from the given list of layer tree nodes.
static bool hasLegendFilterExpression(const QgsLayerTreeGroup &group)
Test if one of the layers in a group has an expression filter.
static int countMapLayerInTree(QgsLayerTreeNode *tree, QgsMapLayer *layer)
Returns how many occurrences of a map layer are there in a layer tree.
static QDomElement writeOldLegend(QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList< QgsMapLayer * > &order)
Returns.
static bool readOldLegendLayerOrder(const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order)
Try to load custom layer order from.
static QgsLayerTreeLayer * insertLayerAtOptimalPlacement(QgsLayerTreeGroup *group, QgsMapLayer *layer)
Inserts a layer within a given group at an optimal index position by insuring a given layer type will...
static void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group, const QgsProject *project)
Updates an embedded group from a project.
static bool readOldLegend(QgsLayerTreeGroup *root, const QDomElement &legendElem)
Try to load layer tree from.
static QgsLayerTreeGroup * firstGroupWithoutCustomProperty(QgsLayerTreeGroup *group, const QString &property)
Returns the first parent which doesn't have the given custom property or the group itself if it doesn...
static void removeInvalidLayers(QgsLayerTreeGroup *group)
Removes layer nodes that refer to invalid layers.
static void regenerateGroupIds(QgsLayerTreeNode *node)
Assigns a new unique id to every group in the sub-tree rooted at node.
static Qt::CheckState checkStateFromXml(const QString &txt)
Convert QString to Qt::CheckState.
static QStringList invisibleLayerList(QgsLayerTreeNode *node)
Gets invisible layers.
static bool layersModified(const QList< QgsLayerTreeLayer * > &layerNodes)
Returns true if any of the layers is modified.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Base class for all map layer types.
virtual Qgis::MapLayerProperties properties() const
Returns the map layer properties of this layer.
virtual bool isEditable() const
Returns true if the layer can be edited.
virtual bool isModified() const
Returns true if the layer has been modified since last commit/save.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
static QString createUniqueId(const QString &base=QString())
Generates a unique identifier by appending a random UUID to base.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
#define QgsDebugMsgLevel(str, level)