QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 "qgsmaplayerregistry.h"
19 
20 #include "qgslayertree.h"
21 
22 #include "qgsproject.h"
23 #include "qgslogger.h"
24 
26  : QObject( parent )
27  , mRoot( root )
28  , mRegistryRemovingLayers( false )
29  , mEnabled( true )
30  , mNewLayersVisible( true )
31  , mInsertionPointGroup( root )
32  , mInsertionPointIndex( 0 )
33 {
34  connect( QgsMapLayerRegistry::instance(), SIGNAL( legendLayersAdded( QList<QgsMapLayer*> ) ), this, SLOT( layersAdded( QList<QgsMapLayer*> ) ) );
36 
37  connect( mRoot, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( groupWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
38  connect( mRoot, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( groupRemovedChildren() ) );
39 }
40 
42 {
43  mInsertionPointGroup = parentGroup;
45 }
46 
48 {
49  if ( !mEnabled )
50  return;
51 
53  Q_FOREACH ( QgsMapLayer* layer, layers )
54  {
55  QgsLayerTreeLayer* nodeLayer = new QgsLayerTreeLayer( layer );
56  nodeLayer->setVisible( mNewLayersVisible ? Qt::Checked : Qt::Unchecked );
57 
58  nodes << nodeLayer;
59 
60  // check whether the layer is marked as embedded
61  QString projectFile = QgsProject::instance()->layerIsEmbedded( nodeLayer->layerId() );
62  if ( !projectFile.isEmpty() )
63  {
64  nodeLayer->setCustomProperty( "embedded", 1 );
65  nodeLayer->setCustomProperty( "embedded_project", projectFile );
66  }
67  }
68 
69  // add new layers to the right place
71 
72  // tell other components that layers have been added - this signal is used in QGIS to auto-select the first layer
73  emit addedLayersToLayerTree( layers );
74 }
75 
77 {
78  QgsDebugMsg( QString( "%1 layers will be removed, enabled:%2" ).arg( layerIds.count() ).arg( mEnabled ) );
79 
80  if ( !mEnabled )
81  return;
82 
83  // when we start removing child nodes, the bridge would try to remove those layers from
84  // the registry _again_ in groupRemovedChildren() - this prevents it
86 
87  Q_FOREACH ( const QString& layerId, layerIds )
88  {
89  QgsLayerTreeLayer* nodeLayer = mRoot->findLayer( layerId );
90  if ( nodeLayer )
91  qobject_cast<QgsLayerTreeGroup*>( nodeLayer->parent() )->removeChildNode( nodeLayer );
92  }
93 
95 }
96 
97 
98 static void _collectLayerIdsInGroup( QgsLayerTreeGroup* group, int indexFrom, int indexTo, QStringList& lst )
99 {
100  for ( int i = indexFrom; i <= indexTo; ++i )
101  {
102  QgsLayerTreeNode* child = group->children().at( i );
103  if ( QgsLayerTree::isLayer( child ) )
104  {
105  lst << QgsLayerTree::toLayer( child )->layerId();
106  }
107  else if ( QgsLayerTree::isGroup( child ) )
108  {
109  _collectLayerIdsInGroup( QgsLayerTree::toGroup( child ), 0, child->children().count() - 1, lst );
110  }
111  }
112 }
113 
115 {
117  return; // do not try to remove those layers again
118 
119  Q_ASSERT( mLayerIdsForRemoval.isEmpty() );
120 
121  Q_ASSERT( QgsLayerTree::isGroup( node ) );
122  QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
123 
124  _collectLayerIdsInGroup( group, indexFrom, indexTo, mLayerIdsForRemoval );
125 }
126 
128 {
130  return; // do not try to remove those layers again
131 
132  // remove only those that really do not exist in the tree
133  // (ignores layers that were dragged'n'dropped: 1. drop new 2. remove old)
134  QStringList toRemove;
135  Q_FOREACH ( const QString& layerId, mLayerIdsForRemoval )
136  if ( !mRoot->findLayer( layerId ) )
137  toRemove << layerId;
139 
140  QgsDebugMsg( QString( "%1 layers will be removed" ).arg( toRemove.count() ) );
141 
142  // delay the removal of layers from the registry. There may be other slots connected to map layer registry's signals
143  // that might disrupt the execution flow - e.g. a processEvents() call may force update of layer tree view with
144  // semi-broken tree model
145  QMetaObject::invokeMethod( this, "removeLayersFromRegistry", Qt::QueuedConnection, Q_ARG( QStringList, toRemove ) );
146 }
147 
149 {
151 }
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
Layer tree group node serves as a container for layers and further groups.
QgsLayerTreeRegistryBridge(QgsLayerTreeGroup *root, QObject *parent=nullptr)
void clear()
static unsigned index
Base class for all map layer types.
Definition: qgsmaplayer.h:49
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
const T & at(int i) const
void removeMapLayers(const QStringList &theLayerIds)
Remove a set of layers from the registry by layer ID.
void layersWillBeRemoved(const QStringList &layerIds)
QString layerId() const
void groupWillRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is ...
Definition: qgslayertree.h:46
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...
int count(const T &value) const
void layersAdded(const QList< QgsMapLayer *> &layers)
static void _collectLayerIdsInGroup(QgsLayerTreeGroup *group, int indexFrom, int indexTo, QStringList &lst)
QString layerIsEmbedded(const QString &id) const
Returns project file path if layer is embedded from other project file.
bool isEmpty() const
QgsLayerTreeNode * parent()
Get pointer to the parent. If parent is a null pointer, the node is a root node.
bool isEmpty() const
This class is a base class for nodes in a layer tree.
void setVisible(Qt::CheckState visible)
void insertChildNodes(int index, const QList< QgsLayerTreeNode *> &nodes)
Insert existing nodes at specified position. The nodes must not have a parent yet. The nodes will be owned by this group.
QList< QgsLayerTreeNode * > children()
Get list of children of the node. Children are owned by the parent.
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QgsLayerTreeLayer * findLayer(const QString &layerId) const
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is ...
Definition: qgslayertree.h:52
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
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.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
Layer tree node points to a map layer.