25static void _readOldLegendGroup( 
const QDomElement &groupElem, 
QgsLayerTreeGroup *parent );
 
   26static void _readOldLegendLayer( 
const QDomElement &layerElem, 
QgsLayerTreeGroup *parent );
 
   30  if ( legendElem.isNull() )
 
   33  const QDomNodeList legendChildren = legendElem.childNodes();
 
   35  for ( 
int i = 0; i < legendChildren.size(); ++i )
 
   37    const QDomElement currentChildElem = legendChildren.at( i ).toElement();
 
   38    if ( currentChildElem.tagName() == QLatin1String( 
"legendlayer" ) )
 
   40      _readOldLegendLayer( currentChildElem, root );
 
   42    else if ( currentChildElem.tagName() == QLatin1String( 
"legendgroup" ) )
 
   44      _readOldLegendGroup( currentChildElem, root );
 
 
   53static bool _readOldLegendLayerOrderGroup( 
const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
 
   55  const QDomNodeList legendChildren = groupElem.childNodes();
 
   57  for ( 
int i = 0; i < legendChildren.size(); ++i )
 
   59    const QDomElement currentChildElem = legendChildren.at( i ).toElement();
 
   60    if ( currentChildElem.tagName() == QLatin1String( 
"legendlayer" ) )
 
   62      const QDomElement layerFileElem = currentChildElem.firstChildElement( QStringLiteral( 
"filegroup" ) ).firstChildElement( QStringLiteral( 
"legendlayerfile" ) );
 
   64      const int layerIndex = currentChildElem.attribute( QStringLiteral( 
"drawingOrder" ) ).toInt();
 
   65      if ( layerIndex == -1 )
 
   67      layerIndexes.insert( layerIndex, layerFileElem.attribute( QStringLiteral( 
"layerid" ) ) );
 
   69    else if ( currentChildElem.tagName() == QLatin1String( 
"legendgroup" ) )
 
   71      if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
 
   82  if ( legendElem.isNull() )
 
   85  hasCustomOrder = legendElem.attribute( QStringLiteral( 
"updateDrawingOrder" ) ) == QLatin1String( 
"false" );
 
   88  QMap<int, QString> layerIndexes;
 
   91  const bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
 
   93  if ( !res && hasCustomOrder )
 
   96  const auto constLayerIndexes = layerIndexes;
 
   97  for ( 
const QString &layerId : constLayerIndexes )
 
  100    order.append( layerId );
 
 
  107static QDomElement _writeOldLegendLayer( QDomDocument &doc, 
QgsLayerTreeLayer *nodeLayer, 
bool hasCustomOrder, 
const QList<QgsMapLayer *> &order )
 
  109  int drawingOrder = -1;
 
  110  if ( hasCustomOrder )
 
  111    drawingOrder = order.indexOf( nodeLayer->
layer() );
 
  113  QDomElement layerElem = doc.createElement( QStringLiteral( 
"legendlayer" ) );
 
  114  layerElem.setAttribute( QStringLiteral( 
"drawingOrder" ), drawingOrder );
 
  115  layerElem.setAttribute( QStringLiteral( 
"open" ), nodeLayer->
isExpanded() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" ) );
 
  117  layerElem.setAttribute( QStringLiteral( 
"name" ), nodeLayer->
name() );
 
  118  layerElem.setAttribute( QStringLiteral( 
"showFeatureCount" ), nodeLayer->
customProperty( QStringLiteral( 
"showFeatureCount" ) ).toInt() );
 
  120  QDomElement fileGroupElem = doc.createElement( QStringLiteral( 
"filegroup" ) );
 
  121  fileGroupElem.setAttribute( QStringLiteral( 
"open" ), nodeLayer->
isExpanded() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" ) );
 
  122  fileGroupElem.setAttribute( QStringLiteral( 
"hidden" ), QStringLiteral( 
"false" ) );
 
  124  QDomElement layerFileElem = doc.createElement( QStringLiteral( 
"legendlayerfile" ) );
 
  125  layerFileElem.setAttribute( QStringLiteral( 
"isInOverview" ), nodeLayer->
customProperty( QStringLiteral( 
"overview" ) ).toInt() );
 
  126  layerFileElem.setAttribute( QStringLiteral( 
"layerid" ), nodeLayer->
layerId() );
 
  127  layerFileElem.setAttribute( QStringLiteral( 
"visible" ), nodeLayer->
isVisible() ? 1 : 0 );
 
  129  layerElem.appendChild( fileGroupElem );
 
  130  fileGroupElem.appendChild( layerFileElem );
 
  135static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, 
QgsLayerTreeGroup *nodeGroup, 
bool hasCustomOrder, 
const QList<QgsMapLayer *> &order );
 
  137static QDomElement _writeOldLegendGroup( QDomDocument &doc, 
QgsLayerTreeGroup *nodeGroup, 
bool hasCustomOrder, 
const QList<QgsMapLayer *> &order )
 
  139  QDomElement groupElem = doc.createElement( QStringLiteral( 
"legendgroup" ) );
 
  140  groupElem.setAttribute( QStringLiteral( 
"open" ), nodeGroup->
isExpanded() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" ) );
 
  141  groupElem.setAttribute( QStringLiteral( 
"name" ), nodeGroup->
name() );
 
  144  if ( nodeGroup->
customProperty( QStringLiteral( 
"embedded" ) ).toInt() )
 
  146    groupElem.setAttribute( QStringLiteral( 
"embedded" ), 1 );
 
  147    groupElem.setAttribute( QStringLiteral( 
"project" ), nodeGroup->
customProperty( QStringLiteral( 
"embedded_project" ) ).toString() );
 
  150  _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
 
  155static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, 
QgsLayerTreeGroup *nodeGroup, 
bool hasCustomOrder, 
const QList<QgsMapLayer *> &order )
 
  157  const auto constChildren = nodeGroup->
children();
 
  162      groupElem.appendChild( _writeOldLegendGroup( doc, 
QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
 
  166      groupElem.appendChild( _writeOldLegendLayer( doc, 
QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
 
  174  QDomElement legendElem = doc.createElement( QStringLiteral( 
"legend" ) );
 
  175  legendElem.setAttribute( QStringLiteral( 
"updateDrawingOrder" ), hasCustomOrder ? QStringLiteral( 
"false" ) : QStringLiteral( 
"true" ) );
 
  177  _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
 
 
  188      return QStringLiteral( 
"Qt::Unchecked" );
 
  189    case Qt::PartiallyChecked:
 
  190      return QStringLiteral( 
"Qt::PartiallyChecked" );
 
  192      return QStringLiteral( 
"Qt::Checked" );
 
 
  199  if ( txt == QLatin1String( 
"Qt::Unchecked" ) )
 
  200    return Qt::Unchecked;
 
  201  else if ( txt == QLatin1String( 
"Qt::PartiallyChecked" ) )
 
  202    return Qt::PartiallyChecked;
 
 
  209static void _readOldLegendGroup( 
const QDomElement &groupElem, 
QgsLayerTreeGroup *parent )
 
  211  const QDomNodeList groupChildren = groupElem.childNodes();
 
  216  groupNode->
setExpanded( groupElem.attribute( QStringLiteral( 
"open" ) ) == QLatin1String( 
"true" ) );
 
  218  if ( groupElem.attribute( QStringLiteral( 
"embedded" ) ) == QLatin1String( 
"1" ) )
 
  221    groupNode->
setCustomProperty( QStringLiteral( 
"embedded_project" ), groupElem.attribute( QStringLiteral( 
"project" ) ) );
 
  224  for ( 
int i = 0; i < groupChildren.size(); ++i )
 
  226    const QDomElement currentChildElem = groupChildren.at( i ).toElement();
 
  227    if ( currentChildElem.tagName() == QLatin1String( 
"legendlayer" ) )
 
  229      _readOldLegendLayer( currentChildElem, groupNode );
 
  231    else if ( currentChildElem.tagName() == QLatin1String( 
"legendgroup" ) )
 
  233      _readOldLegendGroup( currentChildElem, groupNode );
 
  240static void _readOldLegendLayer( 
const QDomElement &layerElem, 
QgsLayerTreeGroup *parent )
 
  242  const QDomElement layerFileElem = layerElem.firstChildElement( QStringLiteral( 
"filegroup" ) ).firstChildElement( QStringLiteral( 
"legendlayerfile" ) );
 
  243  const QString layerId = layerFileElem.attribute( QStringLiteral( 
"layerid" ) );
 
  247  layerNode->
setExpanded( layerElem.attribute( QStringLiteral( 
"open" ) ) == QLatin1String( 
"true" ) );
 
  249  if ( layerFileElem.attribute( QStringLiteral( 
"isInOverview" ) ) == QLatin1String( 
"1" ) )
 
  252  if ( layerElem.attribute( QStringLiteral( 
"embedded" ) ) == QLatin1String( 
"1" ) )
 
  255  if ( layerElem.attribute( QStringLiteral( 
"showFeatureCount" ) ) == QLatin1String( 
"1" ) )
 
  265  const auto constLayerNodes = layerNodes;
 
 
  280  const auto constLayerNodes = layerNodes;
 
 
  295  QList<QgsLayerTreeNode *> nodesToRemove;
 
  296  const auto constChildren = group->
children();
 
  304        nodesToRemove << node;
 
  308  const auto constNodesToRemove = nodesToRemove;
 
 
  315  const QDomElement projectLayersElement { doc->documentElement().firstChildElement( QStringLiteral( 
"projectlayers" ) ) };
 
  327        QDomElement layerElement { projectLayersElement.firstChildElement( QStringLiteral( 
"maplayer" ) ) };
 
  328        while ( ! layerElement.isNull() )
 
  330          const QString id( layerElement.firstChildElement( QStringLiteral( 
"id" ) ).firstChild().nodeValue() );
 
  334            QTextStream stream( &str );
 
  335            layerElement.save( stream, 4  );
 
  336            l->setOriginalXmlProperties( QStringLiteral( 
"<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1" ).arg( str ) );
 
  339          layerElement = layerElement.nextSiblingElement( );
 
  345      const QList<QgsLayerTreeNode *> constChildren( node->children( ) );
 
  346      for ( 
const auto &childNode : constChildren )
 
  353  const QList<QgsLayerTreeNode *> children = group->
children();
 
 
  369      if ( child->itemVisibilityChecked() == Qt::Unchecked )
 
 
  388  const auto constChildren = group->
children();
 
  393      if ( child->customProperty( QStringLiteral( 
"embedded" ) ).toInt() )
 
  395        child->setCustomProperty( QStringLiteral( 
"embedded-invisible-layers" ), 
invisibleLayerList( child ) );
 
 
  409  const auto constChildren = group->
children();
 
  412    if ( !node->customProperty( QStringLiteral( 
"embedded_project" ) ).toString().isEmpty() )
 
  415      const QString newPath = project->
writePath( node->customProperty( QStringLiteral( 
"embedded_project" ) ).toString() );
 
  416      node->setCustomProperty( QStringLiteral( 
"embedded_project" ), newPath );
 
 
  429  layer.
setCustomProperty( QStringLiteral( 
"legend/expressionFilterEnabled" ), enabled && !expr.isEmpty() );
 
 
  434  const QString expression = layer.
customProperty( QStringLiteral( 
"legend/expressionFilter" ), QString() ).toString();
 
  436    *enabled = !expression.isEmpty() && layer.
customProperty( QStringLiteral( 
"legend/expressionFilterEnabled" ), QString() ).toBool();
 
 
  442  const auto constFindLayers = group.
findLayers();
 
  447    if ( exprEnabled && !expr.isEmpty() )
 
 
  474  return parent->
insertLayer( idx + 1, layerToInsert );
 
 
  477static void _collectMapLayers( 
const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
 
  484      if ( nodeLayer->
layer() )
 
  485        layersSet << nodeLayer->
layer();
 
  496  QSet<QgsMapLayer *> layersSet;
 
  497  _collectMapLayers( nodes, layersSet );
 
 
  511  const QList<QgsLayerTreeNode *> children = tree->
children();
 
 
  535  int vectorLineIndex = 0;
 
  536  int vectorPolygonIndex = 0;
 
  537  int pointCloudIndex = 0;
 
  540  int basemapIndex = 0;
 
  542  const QList<QgsLayerTreeNode *> children = group->
children();
 
  549      const QgsMapLayer *childLayer = qobject_cast<const QgsLayerTreeLayer *>( child )->layer();
 
  553      switch ( childLayer->
type() )
 
  560            if ( vectorLineIndex < nodeIdx )
 
  561              vectorLineIndex = nodeIdx;
 
  562            if ( vectorPolygonIndex < nodeIdx )
 
  563              vectorPolygonIndex = nodeIdx;
 
  564            if ( pointCloudIndex < nodeIdx )
 
  565              pointCloudIndex = nodeIdx;
 
  566            if ( meshIndex < nodeIdx )
 
  568            if ( rasterIndex < nodeIdx )
 
  569              rasterIndex = nodeIdx;
 
  570            if ( basemapIndex < nodeIdx )
 
  571              basemapIndex = 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 ( pointCloudIndex < nodeIdx )
 
  589              pointCloudIndex = nodeIdx;
 
  590            if ( meshIndex < nodeIdx )
 
  592            if ( rasterIndex < nodeIdx )
 
  593              rasterIndex = nodeIdx;
 
  594            if ( basemapIndex < nodeIdx )
 
  595              basemapIndex = nodeIdx;
 
  602          if ( meshIndex < nodeIdx )
 
  604          if ( rasterIndex < nodeIdx )
 
  605            rasterIndex = nodeIdx;
 
  606          if ( basemapIndex < nodeIdx )
 
  607            basemapIndex = nodeIdx;
 
  613          if ( rasterIndex < nodeIdx )
 
  614            rasterIndex = nodeIdx;
 
  615          if ( basemapIndex < nodeIdx )
 
  616            basemapIndex = nodeIdx;
 
  626            if ( basemapIndex < nodeIdx )
 
  627              basemapIndex = nodeIdx;
 
  643  switch ( layer->
type() )
 
  654        index = vectorLineIndex;
 
  658        index = vectorPolygonIndex;
 
  665      index = pointCloudIndex;
 
  683        index = basemapIndex;
 
  690      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)