QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgslayertreelayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreelayer.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 
16 #include "qgslayertreelayer.h"
17 
18 #include "qgslayertreeutils.h"
19 #include "qgsmaplayer.h"
20 #include "qgsmaplayerregistry.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsrasterlayer.h"
23 #include "qgsvectordataprovider.h"
24 #include "qgsrasterdataprovider.h"
25 
27  : QgsLayerTreeNode( NodeLayer )
28  , mLayerId( layer->id() )
29  , mLayer( nullptr )
30  , mVisible( Qt::Checked )
31 {
32  Q_ASSERT( QgsMapLayerRegistry::instance()->mapLayer( mLayerId ) == layer );
33  attachToLayer();
34 }
35 
38  , mLayerId( layerId )
39  , mLayerName( name )
40  , mLayer( nullptr )
41  , mVisible( Qt::Checked )
42 {
43  attachToLayer();
44 }
45 
47  : QgsLayerTreeNode( other )
48  , mLayerId( other.mLayerId )
49  , mLayerName( other.mLayerName )
50  , mLayer( nullptr )
51  , mVisible( other.mVisible )
52 {
53  attachToLayer();
54 }
55 
57 {
59  l->attachToSource( source );
60  return l;
61 }
62 
64 {
65  // layer is not necessarily already loaded
67  if ( l )
68  {
69  mLayer = l;
70  mLayerName = l->name();
71  connect( l, SIGNAL( nameChanged() ), this, SLOT( layerNameChanged() ) );
72  // make sure we are notified if the layer is removed
73  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
74  }
75  else
76  {
77  if ( mLayerName.isEmpty() )
78  mLayerName = "(?)";
79  // wait for the layer to be eventually loaded
81  }
82 }
83 
84 bool QgsLayerTreeLayer::layerMatchesSource( QgsMapLayer* layer, const QgsLayerTreeLayer::LayerMatchParams &params ) const
85 {
86  if ( layer->publicSource() != params.source ||
87  layer->name() != params.name )
88  return false;
89 
90  switch ( layer->type() )
91  {
93  {
94  QgsVectorLayer* vl = qobject_cast< QgsVectorLayer* >( layer );
95  if ( vl->dataProvider()->name() != params.providerKey )
96  return false;
97  break;
98  }
100  {
101  QgsRasterLayer* rl = qobject_cast< QgsRasterLayer* >( layer );
102  if ( rl->dataProvider()->name() != params.providerKey )
103  return false;
104  break;
105  }
107  break;
108 
109  }
110  return true;
111 }
112 
114 {
115  return layerName();
116 }
117 
119 {
120  setLayerName( n );
121 }
122 
124 {
125  // check if matching source already open
126  bool foundMatch = false;
127  Q_FOREACH ( QgsMapLayer* layer, QgsMapLayerRegistry::instance()->mapLayers() )
128  {
129  if ( layerMatchesSource( layer, source ) )
130  {
131  // found a source! need to disconnect from layersAdded signal as original attachToLayer call
132  // will have set this up
134  mLayerId = layer->id();
135  attachToLayer();
136  emit layerLoaded();
137  foundMatch = true;
138  break;
139  }
140  }
141 
142  if ( !foundMatch )
143  mLooseMatchParams = source; // no need to store source if match already made
144 }
145 
147 {
148  return mLayer ? mLayer->name() : mLayerName;
149 }
150 
152 {
153  if ( mLayer )
154  {
155  if ( mLayer->name() == n )
156  return;
157  mLayer->setName( n );
158  // no need to emit signal: we will be notified from layer's nameChanged() signal
159  }
160  else
161  {
162  if ( mLayerName == n )
163  return;
164  mLayerName = n;
165  emit nameChanged( this, n );
166  }
167 }
168 
169 void QgsLayerTreeLayer::setVisible( Qt::CheckState state )
170 {
171  if ( mVisible == state )
172  return;
173 
174  mVisible = state;
175  emit visibilityChanged( this, state );
176 }
177 
179 {
180  if ( element.tagName() != "layer-tree-layer" )
181  return nullptr;
182 
183  QString layerID = element.attribute( "id" );
184  QString layerName = element.attribute( "name" );
185 
186  QString source = element.attribute( "source" );
187  QString providerKey = element.attribute( "providerKey" );
188 
189  Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( "checked" ) );
190  bool isExpanded = ( element.attribute( "expanded", "1" ) == "1" );
191 
192  QgsLayerTreeLayer* nodeLayer = nullptr;
193 
194  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
195 
196  if ( layer )
197  nodeLayer = new QgsLayerTreeLayer( layer );
198  else if ( looseMatch && !source.isEmpty() )
199  {
200  LayerMatchParams params;
201  params.name = layerName;
202  params.source = source;
203  params.providerKey = providerKey;
204  nodeLayer = QgsLayerTreeLayer::createLayerFromParams( params );
205  }
206  else
207  nodeLayer = new QgsLayerTreeLayer( layerID, layerName );
208 
209  nodeLayer->readCommonXML( element );
210 
211  nodeLayer->setVisible( checked );
212  nodeLayer->setExpanded( isExpanded );
213  return nodeLayer;
214 }
215 
217 {
218  QDomDocument doc = parentElement.ownerDocument();
219  QDomElement elem = doc.createElement( "layer-tree-layer" );
220  elem.setAttribute( "id", mLayerId );
221  if ( mLayer )
222  {
223  elem.setAttribute( "source", mLayer->publicSource() );
224 
225  QString providerKey;
226  switch ( mLayer->type() )
227  {
229  {
230  QgsVectorLayer* vl = qobject_cast< QgsVectorLayer* >( mLayer );
231  providerKey = vl->dataProvider()->name();
232  break;
233  }
235  {
236  QgsRasterLayer* rl = qobject_cast< QgsRasterLayer* >( mLayer );
237  providerKey = rl->dataProvider()->name();
238  break;
239  }
241  break;
242  }
243  elem.setAttribute( "providerKey", providerKey );
244  }
245 
246  elem.setAttribute( "name", layerName() );
248  elem.setAttribute( "expanded", mExpanded ? "1" : "0" );
249 
250  writeCommonXML( elem );
251 
252  parentElement.appendChild( elem );
253 }
254 
256 {
257  return QString( "LAYER: %1 visible=%2 expanded=%3 id=%4\n" ).arg( layerName() ).arg( mVisible ).arg( mExpanded ).arg( layerId() );
258 }
259 
261 {
262  return new QgsLayerTreeLayer( *this );
263 }
264 
266 {
267  Q_FOREACH ( QgsMapLayer* l, layers )
268  {
269  if ( !mLooseMatchParams.source.isEmpty() && layerMatchesSource( l, mLooseMatchParams ) )
270  {
271  // we are loosely matching, and found a layer with a matching source.
272  // Attach to this!
273  mLayerId = l->id();
274  }
275  if ( l->id() == mLayerId )
276  {
278  attachToLayer();
279  emit layerLoaded();
280  break;
281  }
282  }
283 }
284 
286 {
287  if ( layerIds.contains( mLayerId ) )
288  {
289  emit layerWillBeUnloaded();
290 
291  // stop listening to removal signals and start hoping that the layer may be added again
292  disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
294 
295  mLayer = nullptr;
296  }
297 }
298 
300 {
301  Q_ASSERT( mLayer );
302  emit nameChanged( this, mLayer->name() );
303 }
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void setLayerName(const QString &n)
LayerMatchParams mLooseMatchParams
Only used when loosely matching to layers - eg when creating a composer legend from template If set t...
static QString checkStateToXml(Qt::CheckState state)
Convert Qt::CheckState to QString.
QDomNode appendChild(const QDomNode &newChild)
QString attribute(const QString &name, const QString &defValue) const
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
bool mExpanded
whether the node should be shown in GUI as expanded
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
bool contains(const QString &str, Qt::CaseSensitivity cs) const
void readCommonXML(QDomElement &element)
bool isExpanded() const
Return whether the node should be shown as expanded or collapsed in GUI.
void layerLoaded()
emitted when a previously unavailable layer got loaded
void registryLayersWillBeRemoved(const QStringList &layerIds)
QString layerId() const
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:99
virtual QString name() const =0
Return a provider name.
QgsMapLayer * mLayer
void visibilityChanged(QgsLayerTreeNode *node, Qt::CheckState state)
Emitted when check state of a node within the tree has been changed.
void layerNameChanged()
Emits a nameChanged() signal if layer&#39;s name has changed.
void attachToSource(const LayerMatchParams &source)
Attempts to attach this layer node to a layer with a matching QgsMapLayer::publicSource().
QString name() const override
Get layer&#39;s name.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
QDomDocument ownerDocument() const
void setAttribute(const QString &name, const QString &value)
virtual void writeXML(QDomElement &parentElement) override
Write layer tree to XML.
bool isEmpty() const
This class is a base class for nodes in a layer tree.
static Qt::CheckState checkStateFromXml(const QString &txt)
Convert QString to Qt::CheckState.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
void setVisible(Qt::CheckState visible)
static QgsLayerTreeLayer * createLayerFromParams(const LayerMatchParams &source)
Creates a layer node which will attach to a layer with matching parameters.
void setName(const QString &name)
Set the display name of the layer.
void setName(const QString &n) override
Set layer&#39;s name.
void setExpanded(bool expanded)
Set whether the node should be shown as expanded or collapsed in GUI.
QgsMapLayer * layer() const
leaf node pointing to a layer
QString source
Layer public source.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void writeCommonXML(QDomElement &element)
Parameters for loose layer matching.
void layerWillBeUnloaded()
emitted when a previously available layer got unloaded (from layer registry)
QString layerName() const
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:53
Qt::CheckState mVisible
virtual QString dump() const override
Return string with layer tree structure. For debug purposes only.
void registryLayersAdded(const QList< QgsMapLayer *> &layers)
QgsRasterDataProvider * dataProvider()
Returns the data provider.
QString tagName() const
static QgsLayerTreeLayer * readXML(QDomElement &element, bool looseMatch=false)
Creates a new layer from an XML definition.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
QDomElement createElement(const QString &tagName)
void nameChanged(QgsLayerTreeNode *node, QString name)
Emitted when the name of the node is changed.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
virtual QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
Layer tree node points to a map layer.
QgsLayerTreeLayer(QgsMapLayer *layer)