27using namespace Qt::StringLiterals;
29static void _readOldLegendGroup(
const QDomElement &groupElem,
QgsLayerTreeGroup *parent );
30static void _readOldLegendLayer(
const QDomElement &layerElem,
QgsLayerTreeGroup *parent );
34 if ( legendElem.isNull() )
37 const QDomNodeList legendChildren = legendElem.childNodes();
39 for (
int i = 0; i < legendChildren.size(); ++i )
41 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
42 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
44 _readOldLegendLayer( currentChildElem, root );
46 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
48 _readOldLegendGroup( currentChildElem, root );
56static bool _readOldLegendLayerOrderGroup(
const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
58 const QDomNodeList legendChildren = groupElem.childNodes();
60 for (
int i = 0; i < legendChildren.size(); ++i )
62 const QDomElement currentChildElem = legendChildren.at( i ).toElement();
63 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
65 const QDomElement layerFileElem = currentChildElem.firstChildElement( u
"filegroup"_s ).firstChildElement( u
"legendlayerfile"_s );
67 const int layerIndex = currentChildElem.attribute( u
"drawingOrder"_s ).toInt();
68 if ( layerIndex == -1 )
70 layerIndexes.insert( layerIndex, layerFileElem.attribute( u
"layerid"_s ) );
72 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
74 if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
85 if ( legendElem.isNull() )
88 hasCustomOrder = legendElem.attribute( u
"updateDrawingOrder"_s ) ==
"false"_L1;
91 QMap<int, QString> layerIndexes;
94 const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
96 if ( !res && hasCustomOrder )
99 const auto constLayerIndexes = layerIndexes;
100 for (
const QString &layerId : constLayerIndexes )
103 order.append( layerId );
110static QDomElement _writeOldLegendLayer( QDomDocument &doc,
QgsLayerTreeLayer *nodeLayer,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
112 int drawingOrder = -1;
113 if ( hasCustomOrder )
114 drawingOrder = order.indexOf( nodeLayer->
layer() );
116 QDomElement layerElem = doc.createElement( u
"legendlayer"_s );
117 layerElem.setAttribute( u
"drawingOrder"_s, drawingOrder );
118 layerElem.setAttribute( u
"open"_s, nodeLayer->
isExpanded() ? u
"true"_s : u
"false"_s );
120 layerElem.setAttribute( u
"name"_s, nodeLayer->
name() );
121 layerElem.setAttribute( u
"showFeatureCount"_s, nodeLayer->
customProperty( u
"showFeatureCount"_s ).toInt() );
123 QDomElement fileGroupElem = doc.createElement( u
"filegroup"_s );
124 fileGroupElem.setAttribute( u
"open"_s, nodeLayer->
isExpanded() ? u
"true"_s : u
"false"_s );
125 fileGroupElem.setAttribute( u
"hidden"_s, u
"false"_s );
127 QDomElement layerFileElem = doc.createElement( u
"legendlayerfile"_s );
128 layerFileElem.setAttribute( u
"isInOverview"_s, nodeLayer->
customProperty( u
"overview"_s ).toInt() );
129 layerFileElem.setAttribute( u
"layerid"_s, nodeLayer->
layerId() );
130 layerFileElem.setAttribute( u
"visible"_s, nodeLayer->
isVisible() ? 1 : 0 );
132 layerElem.appendChild( fileGroupElem );
133 fileGroupElem.appendChild( layerFileElem );
138static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order );
140static QDomElement _writeOldLegendGroup( QDomDocument &doc,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
142 QDomElement groupElem = doc.createElement( u
"legendgroup"_s );
143 groupElem.setAttribute( u
"open"_s, nodeGroup->
isExpanded() ? u
"true"_s : u
"false"_s );
144 groupElem.setAttribute( u
"name"_s, nodeGroup->
name() );
149 groupElem.setAttribute( u
"embedded"_s, 1 );
150 groupElem.setAttribute( u
"project"_s, nodeGroup->
customProperty( u
"embedded_project"_s ).toString() );
153 _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
158static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem,
QgsLayerTreeGroup *nodeGroup,
bool hasCustomOrder,
const QList<QgsMapLayer *> &order )
160 const auto constChildren = nodeGroup->
children();
165 groupElem.appendChild( _writeOldLegendGroup( doc,
QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
169 groupElem.appendChild( _writeOldLegendLayer( doc,
QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
177 QDomElement legendElem = doc.createElement( u
"legend"_s );
178 legendElem.setAttribute( u
"updateDrawingOrder"_s, hasCustomOrder ? u
"false"_s : u
"true"_s );
180 _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
191 return u
"Qt::Unchecked"_s;
192 case Qt::PartiallyChecked:
193 return u
"Qt::PartiallyChecked"_s;
195 return u
"Qt::Checked"_s;
202 if ( txt ==
"Qt::Unchecked"_L1 )
203 return Qt::Unchecked;
204 else if ( txt ==
"Qt::PartiallyChecked"_L1 )
205 return Qt::PartiallyChecked;
211static void _readOldLegendGroup(
const QDomElement &groupElem,
QgsLayerTreeGroup *parent )
213 const QDomNodeList groupChildren = groupElem.childNodes();
218 groupNode->
setExpanded( groupElem.attribute( u
"open"_s ) ==
"true"_L1 );
220 if ( groupElem.attribute( u
"embedded"_s ) ==
"1"_L1 )
223 groupNode->
setCustomProperty( u
"embedded_project"_s, groupElem.attribute( u
"project"_s ) );
226 for (
int i = 0; i < groupChildren.size(); ++i )
228 const QDomElement currentChildElem = groupChildren.at( i ).toElement();
229 if ( currentChildElem.tagName() ==
"legendlayer"_L1 )
231 _readOldLegendLayer( currentChildElem, groupNode );
233 else if ( currentChildElem.tagName() ==
"legendgroup"_L1 )
235 _readOldLegendGroup( currentChildElem, groupNode );
242static void _readOldLegendLayer(
const QDomElement &layerElem,
QgsLayerTreeGroup *parent )
244 const QDomElement layerFileElem = layerElem.firstChildElement( u
"filegroup"_s ).firstChildElement( u
"legendlayerfile"_s );
245 const QString layerId = layerFileElem.attribute( u
"layerid"_s );
249 layerNode->
setExpanded( layerElem.attribute( u
"open"_s ) ==
"true"_L1 );
251 if ( layerFileElem.attribute( u
"isInOverview"_s ) ==
"1"_L1 )
254 if ( layerElem.attribute( u
"embedded"_s ) ==
"1"_L1 )
257 if ( layerElem.attribute( u
"showFeatureCount"_s ) ==
"1"_L1 )
267 const auto constLayerNodes = layerNodes;
282 const auto constLayerNodes = layerNodes;
297 QList<QgsLayerTreeNode *> nodesToRemove;
298 const auto constChildren = group->
children();
306 nodesToRemove << node;
310 const auto constNodesToRemove = nodesToRemove;
317 const QDomElement projectLayersElement { doc->documentElement().firstChildElement( u
"projectlayers"_s ) };
328 QDomElement layerElement { projectLayersElement.firstChildElement( u
"maplayer"_s ) };
329 while ( !layerElement.isNull() )
331 const QString id( layerElement.firstChildElement( u
"id"_s ).firstChild().nodeValue() );
335 QTextStream stream( &str );
336 layerElement.save( stream, 4 );
337 l->setOriginalXmlProperties( u
"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1"_s.arg( str ) );
340 layerElement = layerElement.nextSiblingElement();
346 const QList<QgsLayerTreeNode *> constChildren( node->children() );
347 for (
const auto &childNode : constChildren )
354 const QList<QgsLayerTreeNode *> children = group->
children();
370 if ( child->itemVisibilityChecked() == Qt::Unchecked )
389 const auto constChildren = group->
children();
394 if ( child->customProperty( u
"embedded"_s ).toInt() )
396 child->setCustomProperty( u
"embedded-invisible-layers"_s,
invisibleLayerList( child ) );
410 const auto constChildren = group->
children();
413 if ( !node->customProperty( u
"embedded_project"_s ).toString().isEmpty() )
416 const QString newPath = project->
writePath( node->customProperty( u
"embedded_project"_s ).toString() );
417 node->setCustomProperty( u
"embedded_project"_s, newPath );
430 layer.
setCustomProperty( u
"legend/expressionFilterEnabled"_s, enabled && !expr.isEmpty() );
435 const QString expression = layer.
customProperty( u
"legend/expressionFilter"_s, QString() ).toString();
437 *enabled = !expression.isEmpty() && layer.
customProperty( u
"legend/expressionFilterEnabled"_s, QString() ).toBool();
443 const auto constFindLayers = group.
findLayers();
448 if ( exprEnabled && !expr.isEmpty() )
475 return parent->
insertLayer( idx + 1, layerToInsert );
478static void _collectMapLayers(
const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
485 if ( nodeLayer->
layer() )
486 layersSet << nodeLayer->
layer();
497 QSet<QgsMapLayer *> layersSet;
498 _collectMapLayers( nodes, layersSet );
512 const QList<QgsLayerTreeNode *> children = tree->
children();
536 int vectorLineIndex = 0;
537 int vectorPolygonIndex = 0;
538 int pointCloudIndex = 0;
541 int basemapIndex = 0;
543 const QList<QgsLayerTreeNode *> children = group->
children();
550 const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
554 switch ( childLayer->
type() )
561 if ( vectorLineIndex < nodeIdx )
562 vectorLineIndex = nodeIdx;
563 if ( vectorPolygonIndex < nodeIdx )
564 vectorPolygonIndex = nodeIdx;
565 if ( pointCloudIndex < nodeIdx )
566 pointCloudIndex = nodeIdx;
567 if ( meshIndex < nodeIdx )
569 if ( rasterIndex < nodeIdx )
570 rasterIndex = nodeIdx;
571 if ( basemapIndex < nodeIdx )
572 basemapIndex = nodeIdx;
576 if ( vectorPolygonIndex < nodeIdx )
577 vectorPolygonIndex = nodeIdx;
578 if ( pointCloudIndex < nodeIdx )
579 pointCloudIndex = nodeIdx;
580 if ( meshIndex < nodeIdx )
582 if ( rasterIndex < nodeIdx )
583 rasterIndex = nodeIdx;
584 if ( basemapIndex < nodeIdx )
585 basemapIndex = nodeIdx;
589 if ( pointCloudIndex < nodeIdx )
590 pointCloudIndex = nodeIdx;
591 if ( meshIndex < nodeIdx )
593 if ( rasterIndex < nodeIdx )
594 rasterIndex = nodeIdx;
595 if ( basemapIndex < nodeIdx )
596 basemapIndex = nodeIdx;
603 if ( meshIndex < nodeIdx )
605 if ( rasterIndex < nodeIdx )
606 rasterIndex = nodeIdx;
607 if ( basemapIndex < nodeIdx )
608 basemapIndex = nodeIdx;
614 if ( rasterIndex < nodeIdx )
615 rasterIndex = nodeIdx;
616 if ( basemapIndex < nodeIdx )
617 basemapIndex = nodeIdx;
627 if ( basemapIndex < nodeIdx )
628 basemapIndex = nodeIdx;
644 switch ( layer->
type() )
655 index = vectorLineIndex;
659 index = vectorPolygonIndex;
666 index = pointCloudIndex;
684 index = basemapIndex;
691 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 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.
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)