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