QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgslayertreeregistrybridge.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreeregistrybridge.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 
17 
18 #include "qgslayertree.h"
19 
20 #include "qgsproject.h"
21 #include "qgslogger.h"
22 
24  : QObject( parent )
25  , mRoot( root )
26  , mProject( project )
27  , mRegistryRemovingLayers( false )
28  , mEnabled( true )
29  , mNewLayersVisible( true )
30  , mInsertionPoint( root, 0 )
31 {
33  connect( mProject, static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsLayerTreeRegistryBridge::layersWillBeRemoved );
34 
37 }
38 
40 {
41  mInsertionPoint.group = parentGroup;
42  mInsertionPoint.position = index;
43 }
44 
46 {
47  mInsertionPoint = insertionPoint;
48 }
49 
50 void QgsLayerTreeRegistryBridge::layersAdded( const QList<QgsMapLayer *> &layers )
51 {
52  if ( !mEnabled )
53  return;
54 
55  QList<QgsLayerTreeNode *> nodes;
56  const auto constLayers = layers;
57  for ( QgsMapLayer *layer : constLayers )
58  {
59  QgsLayerTreeLayer *nodeLayer = new QgsLayerTreeLayer( layer );
61 
62  nodes << nodeLayer;
63 
64  // check whether the layer is marked as embedded
65  QString projectFile = mProject->layerIsEmbedded( nodeLayer->layerId() );
66  if ( !projectFile.isEmpty() )
67  {
68  nodeLayer->setCustomProperty( QStringLiteral( "embedded" ), 1 );
69  nodeLayer->setCustomProperty( QStringLiteral( "embedded_project" ), projectFile );
70  }
71  }
72 
73  // add new layers to the right place
75 
76  // tell other components that layers have been added - this signal is used in QGIS to auto-select the first layer
77  emit addedLayersToLayerTree( layers );
78 }
79 
80 void QgsLayerTreeRegistryBridge::layersWillBeRemoved( const QStringList &layerIds )
81 {
82  QgsDebugMsgLevel( QStringLiteral( "%1 layers will be removed, enabled:%2" ).arg( layerIds.count() ).arg( mEnabled ), 4 );
83 
84  if ( !mEnabled )
85  return;
86 
87  // when we start removing child nodes, the bridge would try to remove those layers from
88  // the registry _again_ in groupRemovedChildren() - this prevents it
90 
91  const auto constLayerIds = layerIds;
92  for ( const QString &layerId : constLayerIds )
93  {
94  QgsLayerTreeLayer *nodeLayer = mRoot->findLayer( layerId );
95  if ( nodeLayer )
96  qobject_cast<QgsLayerTreeGroup *>( nodeLayer->parent() )->removeChildNode( nodeLayer );
97  }
98 
100 }
101 
102 
103 static void _collectLayerIdsInGroup( QgsLayerTreeGroup *group, int indexFrom, int indexTo, QStringList &lst )
104 {
105  for ( int i = indexFrom; i <= indexTo; ++i )
106  {
107  QgsLayerTreeNode *child = group->children().at( i );
108  if ( QgsLayerTree::isLayer( child ) )
109  {
110  lst << QgsLayerTree::toLayer( child )->layerId();
111  }
112  else if ( QgsLayerTree::isGroup( child ) )
113  {
114  _collectLayerIdsInGroup( QgsLayerTree::toGroup( child ), 0, child->children().count() - 1, lst );
115  }
116  }
117 }
118 
120 {
122  return; // do not try to remove those layers again
123 
124  Q_ASSERT( mLayerIdsForRemoval.isEmpty() );
125 
126  Q_ASSERT( QgsLayerTree::isGroup( node ) );
127  QgsLayerTreeGroup *group = QgsLayerTree::toGroup( node );
128 
129  _collectLayerIdsInGroup( group, indexFrom, indexTo, mLayerIdsForRemoval );
130 }
131 
133 {
135  return; // do not try to remove those layers again
136 
137  // remove only those that really do not exist in the tree
138  // (ignores layers that were dragged'n'dropped: 1. drop new 2. remove old)
139  QStringList toRemove;
140  const auto constMLayerIdsForRemoval = mLayerIdsForRemoval;
141  for ( const QString &layerId : constMLayerIdsForRemoval )
142  if ( !mRoot->findLayer( layerId ) )
143  toRemove << layerId;
144  mLayerIdsForRemoval.clear();
145 
146  QgsDebugMsgLevel( QStringLiteral( "%1 layers will be removed" ).arg( toRemove.count() ), 4 );
147 
148  // delay the removal of layers from the registry. There may be other slots connected to map layer registry's signals
149  // that might disrupt the execution flow - e.g. a processEvents() call may force update of layer tree view with
150  // semi-broken tree model
151  QMetaObject::invokeMethod( this, "removeLayersFromRegistry", Qt::QueuedConnection, Q_ARG( QStringList, toRemove ) );
152 }
153 
154 void QgsLayerTreeRegistryBridge::removeLayersFromRegistry( const QStringList &layerIds )
155 {
156  mProject->removeMapLayers( layerIds );
157 }
QgsLayerTreeGroup::findLayer
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
Definition: qgslayertreegroup.cpp:195
QgsLayerTreeRegistryBridge::QgsLayerTreeRegistryBridge
QgsLayerTreeRegistryBridge(QgsLayerTreeGroup *root, QgsProject *project, QObject *parent=nullptr)
Create the instance that synchronizes given project with a layer tree root.
Definition: qgslayertreeregistrybridge.cpp:23
QgsLayerTreeRegistryBridge::InsertionPoint
A structure to define the insertion point to the layer tree.
Definition: qgslayertreeregistrybridge.h:55
QgsLayerTreeNode
This class is a base class for nodes in a layer tree.
Definition: qgslayertreenode.h:75
QgsProject::layersWillBeRemoved
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QgsLayerTreeNode::setItemVisibilityChecked
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
Definition: qgslayertreenode.cpp:78
QgsLayerTreeNode::removedChildren
void removedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes has been removed from a node within the tree.
qgslayertreeregistrybridge.h
QgsLayerTreeRegistryBridge::removeLayersFromRegistry
void removeLayersFromRegistry(const QStringList &layerIds)
Definition: qgslayertreeregistrybridge.cpp:154
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsLayerTreeLayer::layerId
QString layerId() const
Returns the ID for the map layer associated with this node.
Definition: qgslayertreelayer.h:63
QgsLayerTreeRegistryBridge::groupWillRemoveChildren
void groupWillRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Definition: qgslayertreeregistrybridge.cpp:119
QgsLayerTree::toLayer
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
QgsLayerTreeRegistryBridge::addedLayersToLayerTree
void addedLayersToLayerTree(const QList< QgsMapLayer * > &layers)
Tell others we have just added layers to the tree (used in QGIS to auto-select first newly added laye...
QgsProject::removeMapLayers
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the registry by layer ID.
Definition: qgsproject.cpp:3385
QgsLayerTree::toGroup
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Definition: qgslayertree.h:64
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:95
QgsLayerTreeRegistryBridge::mLayerIdsForRemoval
QStringList mLayerIdsForRemoval
Definition: qgslayertreeregistrybridge.h:107
QgsLayerTreeRegistryBridge::mProject
QgsProject * mProject
Definition: qgslayertreeregistrybridge.h:106
QgsLayerTreeRegistryBridge::layersWillBeRemoved
void layersWillBeRemoved(const QStringList &layerIds)
Definition: qgslayertreeregistrybridge.cpp:80
QgsLayerTreeRegistryBridge::mRegistryRemovingLayers
bool mRegistryRemovingLayers
Definition: qgslayertreeregistrybridge.h:108
QgsLayerTreeLayer
Layer tree node points to a map layer.
Definition: qgslayertreelayer.h:44
QgsLayerTreeGroup
Layer tree group node serves as a container for layers and further groups.
Definition: qgslayertreegroup.h:35
QgsLayerTreeGroup::insertChildNodes
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
Definition: qgslayertreegroup.cpp:99
QgsLayerTreeRegistryBridge::mRoot
QgsLayerTreeGroup * mRoot
Definition: qgslayertreeregistrybridge.h:105
qgslayertree.h
QgsProject::legendLayersAdded
void legendLayersAdded(const QList< QgsMapLayer * > &layers)
Emitted, when a layer was added to the registry and the legend.
QgsLayerTree::isLayer
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
QgsLayerTreeRegistryBridge::mInsertionPoint
InsertionPoint mInsertionPoint
Definition: qgslayertreeregistrybridge.h:112
QgsProject::layerIsEmbedded
QString layerIsEmbedded(const QString &id) const
Returns the source project file path if the layer with matching id is embedded from other project fil...
Definition: qgsproject.cpp:2726
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsLayerTreeRegistryBridge::mNewLayersVisible
bool mNewLayersVisible
Definition: qgslayertreeregistrybridge.h:110
QgsLayerTreeNode::children
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
Definition: qgslayertreenode.h:112
QgsLayerTreeRegistryBridge::groupRemovedChildren
void groupRemovedChildren()
Definition: qgslayertreeregistrybridge.cpp:132
QgsLayerTreeRegistryBridge::InsertionPoint::group
QgsLayerTreeGroup * group
Definition: qgslayertreeregistrybridge.h:60
QgsLayerTreeRegistryBridge::mEnabled
bool mEnabled
Definition: qgslayertreeregistrybridge.h:109
QgsLayerTreeRegistryBridge::setLayerInsertionPoint
Q_DECL_DEPRECATED void setLayerInsertionPoint(QgsLayerTreeGroup *parentGroup, int index)
Set where the new layers should be inserted - can be used to follow current selection.
Definition: qgslayertreeregistrybridge.cpp:39
QgsLayerTreeNode::parent
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
Definition: qgslayertreenode.h:110
QgsLayerTreeNode::willRemoveChildren
void willRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Emitted when one or more nodes will be removed from a node within the tree.
qgslogger.h
QgsLayerTree::isGroup
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:43
qgsproject.h
QgsLayerTreeRegistryBridge::layersAdded
void layersAdded(const QList< QgsMapLayer * > &layers)
Definition: qgslayertreeregistrybridge.cpp:50
QgsLayerTreeRegistryBridge::InsertionPoint::position
int position
Definition: qgslayertreeregistrybridge.h:61