QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsmaplayerstore.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaplayerstore.cpp
3 --------------------
4 begin : May 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsmaplayerstore.h"
19#include "qgsmaplayer.h"
20#include "qgslogger.h"
21#include "qgsthreadingutils.h"
22#include <QList>
23
25 : QObject( parent )
26{}
27
29{
31}
32
34{
36
37 return mMapLayers.size();
38}
39
41{
43
44 int i = 0;
45 const QList<QgsMapLayer *> cLayers = mMapLayers.values();
46 for ( const auto l : cLayers )
47 {
48 if ( l->isValid() )
49 i++;
50 }
51 return i;
52}
53
54QgsMapLayer *QgsMapLayerStore::mapLayer( const QString &layerId ) const
55{
56 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
58
59 return mMapLayers.value( layerId );
60}
61
62QList<QgsMapLayer *> QgsMapLayerStore::mapLayersByName( const QString &layerName ) const
63{
65
66 QList<QgsMapLayer *> myResultList;
67 const auto constMMapLayers = mMapLayers;
68 for ( QgsMapLayer *layer : constMMapLayers )
69 {
70 if ( layer->name() == layerName )
71 {
72 myResultList << layer;
73 }
74 }
75 return myResultList;
76}
77
78QList<QgsMapLayer *> QgsMapLayerStore::addMapLayers( const QList<QgsMapLayer *> &layers, bool takeOwnership )
79{
81
82 QList<QgsMapLayer *> myResultList;
83 const auto constLayers = layers;
84 for ( QgsMapLayer *myLayer : constLayers )
85 {
86 if ( !myLayer )
87 {
88 QgsDebugError( QStringLiteral( "Cannot add null layers" ) );
89 continue;
90 }
91
93
94 // If the layer is already in the store but its validity has flipped to TRUE reset data source
95 if ( mMapLayers.contains( myLayer->id() ) && ! mMapLayers[myLayer->id()]->isValid() && myLayer->isValid() && myLayer->dataProvider() )
96 {
97 mMapLayers[myLayer->id()]->setDataSource( myLayer->dataProvider()->dataSourceUri(), myLayer->name(), myLayer->providerType(), QgsDataProvider::ProviderOptions() );
98 }
99 //check the layer is not already registered!
100 if ( !mMapLayers.contains( myLayer->id() ) )
101 {
102 mMapLayers[myLayer->id()] = myLayer;
103 myResultList << mMapLayers[myLayer->id()];
104 if ( takeOwnership )
105 {
106 myLayer->setParent( this );
107 }
108 connect( myLayer, &QObject::destroyed, this, &QgsMapLayerStore::onMapLayerDeleted );
109 emit layerWasAdded( myLayer );
110 }
111 }
112 if ( !myResultList.isEmpty() )
113 {
114 emit layersAdded( myResultList );
115 }
116 return myResultList;
117}
118
120QgsMapLayerStore::addMapLayer( QgsMapLayer *layer, bool takeOwnership )
121{
123
124 QList<QgsMapLayer *> addedLayers;
125 addedLayers = addMapLayers( QList<QgsMapLayer *>() << layer, takeOwnership );
126 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
127}
128
129void QgsMapLayerStore::removeMapLayers( const QStringList &layerIds )
130{
132
133 QList<QgsMapLayer *> layers;
134 const auto constLayerIds = layerIds;
135 for ( const QString &myId : constLayerIds )
136 {
137 layers << mMapLayers.value( myId );
138 }
139
141}
142
143void QgsMapLayerStore::removeMapLayers( const QList<QgsMapLayer *> &layers )
144{
146
147 if ( layers.isEmpty() )
148 return;
149
150 QStringList layerIds;
151 QList<QgsMapLayer *> layerList;
152
153 const auto constLayers = layers;
154 for ( QgsMapLayer *layer : constLayers )
155 {
156 // check layer and the store contains it
157 if ( layer && mMapLayers.contains( layer->id() ) )
158 {
159 layerIds << layer->id();
160 layerList << layer;
161 }
162 }
163
164 if ( layerIds.isEmpty() )
165 return;
166
167 emit layersWillBeRemoved( layerIds );
168 emit layersWillBeRemoved( layerList );
169
170 const auto constLayerList = layerList;
171 for ( QgsMapLayer *lyr : constLayerList )
172 {
173 const QString myId( lyr->id() );
174 emit layerWillBeRemoved( myId );
175 emit layerWillBeRemoved( lyr );
176 mMapLayers.remove( myId );
177 if ( lyr->parent() == this )
178 {
179 delete lyr;
180 }
181 emit layerRemoved( myId );
182 }
183
184 emit layersRemoved( layerIds );
185}
186
187void QgsMapLayerStore::removeMapLayer( const QString &layerId )
188{
190
191 removeMapLayers( QList<QgsMapLayer *>() << mMapLayers.value( layerId ) );
192}
193
195{
197
198 if ( layer )
199 removeMapLayers( QList<QgsMapLayer *>() << layer );
200}
201
203{
205
206 if ( !layer )
207 return nullptr;
208
209 if ( mMapLayers.contains( layer->id() ) )
210 {
211 emit layersWillBeRemoved( QStringList() << layer->id() );
212 emit layersWillBeRemoved( QList<QgsMapLayer *>() << layer );
213 emit layerWillBeRemoved( layer->id() );
214 emit layerWillBeRemoved( layer );
215
216 mMapLayers.remove( layer->id() );
217 layer->setParent( nullptr );
218 emit layerRemoved( layer->id() );
219 emit layersRemoved( QStringList() << layer->id() );
220 return layer;
221 }
222 return nullptr; //don't return layer - it wasn't owned and accordingly we aren't transferring ownership
223}
224
226{
228
229 emit allLayersRemoved();
230 // now let all observers know to clear themselves,
231 // and then consequently any of their map legends
232 removeMapLayers( mMapLayers.keys() );
233 mMapLayers.clear();
234}
235
237{
239
240 if ( !other || other == this )
241 return;
242
243 Q_ASSERT_X( other->thread() == thread(), "QgsMapLayerStore::transferLayersFromStore", "Cannot transfer layers from store with different thread affinity" );
244
245 const QMap<QString, QgsMapLayer *> otherLayers = other->mapLayers();
246 QMap<QString, QgsMapLayer *>::const_iterator it = otherLayers.constBegin();
247 for ( ; it != otherLayers.constEnd(); ++it )
248 {
249 QgsMapLayer *layer = other->takeMapLayer( it.value() );
250 if ( layer )
251 addMapLayer( layer );
252 }
253}
254
255void QgsMapLayerStore::onMapLayerDeleted( QObject *obj )
256{
258
259 const QString id = mMapLayers.key( static_cast<QgsMapLayer *>( obj ) );
260
261 if ( !id.isNull() )
262 {
263 QgsDebugError( QStringLiteral( "Map layer deleted without unregistering! %1" ).arg( id ) );
264 mMapLayers.remove( id );
265 }
266}
267
268QMap<QString, QgsMapLayer *> QgsMapLayerStore::mapLayers() const
269{
270 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
272
273 return mMapLayers;
274}
275
276QMap<QString, QgsMapLayer *> QgsMapLayerStore::validMapLayers() const
277{
278 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
280
281 QMap<QString, QgsMapLayer *> validLayers;
282 for ( auto it = mMapLayers.constBegin(); it != mMapLayers.constEnd(); it++ )
283 {
284 if ( it.value()->isValid() )
285 validLayers[it.key()] = it.value();
286 }
287 return validLayers;
288}
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
int count() const
Returns the number of layers contained in the store.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all layers by layer ID.
void removeAllMapLayers()
Removes all registered layers.
~QgsMapLayerStore() override
QgsMapLayerStore(QObject *parent=nullptr)
Constructor for QgsMapLayerStore.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the store.
int validCount() const
Returns the number of valid layers contained in the store.
void removeMapLayer(const QString &id)
Remove a layer from the store by layer id.
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the store.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the store.
void allLayersRemoved()
Emitted when all layers are removed, before layersWillBeRemoved() and layerWillBeRemoved() signals ar...
void layerRemoved(const QString &layerId)
Emitted after a layer was removed from the store.
QgsMapLayer * takeMapLayer(QgsMapLayer *layer)
Takes a layer from the store.
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the store.
QList< QgsMapLayer * > mapLayersByName(const QString &name) const
Retrieve a list of matching layers by layer name.
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the store by layer ID.
QMap< QString, QgsMapLayer * > validMapLayers() const
Returns a map of all valid layers by layer ID.
QgsMapLayer * mapLayer(const QString &id) const
Retrieve a pointer to a layer by layer id.
QgsMapLayer * addMapLayer(QgsMapLayer *layer, bool takeOwnership=true)
Add a layer to the store.
void transferLayersFromStore(QgsMapLayerStore *other)
Transfers all the map layers contained within another map layer store and adds them to this store.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the store.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &layers, bool takeOwnership=true)
Add a list of layers to the store.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
#define QgsDebugError(str)
Definition: qgslogger.h:38
#define QGIS_CHECK_QOBJECT_THREAD_EQUALITY(other)
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.