QGIS API Documentation  3.6.0-Noosa (5873452)
qgsmaplayermodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayermodel.cpp
3  --------------------------------------
4  Date : 01.04.2014
5  Copyright : (C) 2014 Denis Rouzaud
6  Email : [email protected]
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 <QIcon>
17 
18 #include "qgsdataitem.h"
19 #include "qgsmaplayermodel.h"
20 #include "qgsproject.h"
21 #include "qgsapplication.h"
22 #include "qgsvectorlayer.h"
23 
24 
25 QgsMapLayerModel::QgsMapLayerModel( const QList<QgsMapLayer *> &layers, QObject *parent )
26  : QAbstractItemModel( parent )
27 {
28  connect( QgsProject::instance(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsMapLayerModel::removeLayers );
29  addLayers( layers );
30 }
31 
33  : QAbstractItemModel( parent )
34 {
36  connect( QgsProject::instance(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsMapLayerModel::removeLayers );
37  addLayers( QgsProject::instance()->mapLayers().values() );
38 }
39 
41 {
42  mItemCheckable = checkable;
43 }
44 
45 void QgsMapLayerModel::checkAll( Qt::CheckState checkState )
46 {
47  QMap<QString, Qt::CheckState>::iterator i = mLayersChecked.begin();
48  for ( ; i != mLayersChecked.end(); ++i )
49  {
50  *i = checkState;
51  }
52  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) );
53 }
54 
55 void QgsMapLayerModel::setAllowEmptyLayer( bool allowEmpty )
56 {
57  if ( allowEmpty == mAllowEmpty )
58  return;
59 
60  if ( allowEmpty )
61  {
62  beginInsertRows( QModelIndex(), 0, 0 );
63  mAllowEmpty = true;
64  endInsertRows();
65  }
66  else
67  {
68  beginRemoveRows( QModelIndex(), 0, 0 );
69  mAllowEmpty = false;
70  endRemoveRows();
71  }
72 }
73 
75 {
76  if ( mShowCrs == showCrs )
77  return;
78 
79  mShowCrs = showCrs;
80  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::DisplayRole );
81 }
82 
83 QList<QgsMapLayer *> QgsMapLayerModel::layersChecked( Qt::CheckState checkState )
84 {
85  QList<QgsMapLayer *> layers;
86  Q_FOREACH ( QgsMapLayer *layer, mLayers )
87  {
88  if ( mLayersChecked[layer->id()] == checkState )
89  {
90  layers.append( layer );
91  }
92  }
93  return layers;
94 }
95 
96 QModelIndex QgsMapLayerModel::indexFromLayer( QgsMapLayer *layer ) const
97 {
98  int r = mLayers.indexOf( layer );
99  if ( r >= 0 && mAllowEmpty )
100  r++;
101  return index( r, 0 );
102 }
103 
105 {
106  return static_cast<QgsMapLayer *>( index.internalPointer() );
107 }
108 
109 void QgsMapLayerModel::setAdditionalItems( const QStringList &items )
110 {
111  if ( items == mAdditionalItems )
112  return;
113 
114  int offset = 0;
115  if ( mAllowEmpty )
116  offset++;
117 
118  offset += mLayers.count();
119 
120  //remove existing
121  if ( !mAdditionalItems.isEmpty() )
122  {
123  beginRemoveRows( QModelIndex(), offset, offset + mAdditionalItems.count() - 1 );
124  mAdditionalItems.clear();
125  endRemoveRows();
126  }
127 
128  //add new
129  beginInsertRows( QModelIndex(), offset, offset + items.count() - 1 );
130  mAdditionalItems = items;
131  endInsertRows();
132 }
133 
134 void QgsMapLayerModel::removeLayers( const QStringList &layerIds )
135 {
136  int offset = 0;
137  if ( mAllowEmpty )
138  offset++;
139 
140  Q_FOREACH ( const QString &layerId, layerIds )
141  {
142  QModelIndex startIndex = index( 0, 0 );
143  QModelIndexList list = match( startIndex, LayerIdRole, layerId, 1 );
144  if ( !list.isEmpty() )
145  {
146  QModelIndex index = list[0];
147  beginRemoveRows( QModelIndex(), index.row(), index.row() );
148  mLayersChecked.remove( layerId );
149  mLayers.removeAt( index.row() - offset );
150  endRemoveRows();
151  }
152  }
153 }
154 
155 void QgsMapLayerModel::addLayers( const QList<QgsMapLayer *> &layers )
156 {
157  if ( !layers.empty( ) )
158  {
159  int offset = 0;
160  if ( mAllowEmpty )
161  offset++;
162 
163  beginInsertRows( QModelIndex(), mLayers.count() + offset, mLayers.count() + layers.count() - 1 + offset );
164  Q_FOREACH ( QgsMapLayer *layer, layers )
165  {
166  mLayers.append( layer );
167  mLayersChecked.insert( layer->id(), Qt::Unchecked );
168  }
169  endInsertRows();
170  }
171 }
172 
173 QModelIndex QgsMapLayerModel::index( int row, int column, const QModelIndex &parent ) const
174 {
175  int offset = 0;
176  if ( mAllowEmpty )
177  offset++;
178 
179  if ( hasIndex( row, column, parent ) )
180  {
181  QgsMapLayer *layer = nullptr;
182  if ( row - offset >= 0 && row - offset < mLayers.count() )
183  layer = mLayers.at( row - offset );
184 
185  return createIndex( row, column, layer );
186  }
187 
188  return QModelIndex();
189 
190 }
191 
192 QModelIndex QgsMapLayerModel::parent( const QModelIndex &child ) const
193 {
194  Q_UNUSED( child );
195  return QModelIndex();
196 }
197 
198 
199 int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
200 {
201  if ( parent.isValid() )
202  return 0;
203 
204  return ( mAllowEmpty ? 1 : 0 ) + mLayers.length() + mAdditionalItems.count();
205 }
206 
207 int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
208 {
209  Q_UNUSED( parent );
210  return 1;
211 }
212 
213 
214 QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
215 {
216  if ( !index.isValid() )
217  return QVariant();
218 
219  bool isEmpty = index.row() == 0 && mAllowEmpty;
220  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
221 
222  switch ( role )
223  {
224  case Qt::DisplayRole:
225  {
226  if ( index.row() == 0 && mAllowEmpty )
227  return QVariant();
228 
229  if ( additionalIndex >= 0 )
230  return mAdditionalItems.at( additionalIndex );
231 
232  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
233  if ( !layer )
234  return QVariant();
235 
236  if ( !mShowCrs || !layer->isSpatial() )
237  {
238  return layer->name();
239  }
240  else
241  {
242  return tr( "%1 [%2]" ).arg( layer->name(), layer->crs().authid() );
243  }
244  }
245 
246  case LayerIdRole:
247  {
248  if ( isEmpty || additionalIndex >= 0 )
249  return QVariant();
250 
251  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
252  return layer ? layer->id() : QVariant();
253  }
254 
255  case LayerRole:
256  {
257  if ( isEmpty || additionalIndex >= 0 )
258  return QVariant();
259 
260  return QVariant::fromValue<QgsMapLayer *>( static_cast<QgsMapLayer *>( index.internalPointer() ) );
261  }
262 
263  case EmptyRole:
264  return isEmpty;
265 
266  case AdditionalRole:
267  return additionalIndex >= 0;
268 
269  case Qt::CheckStateRole:
270  {
271  if ( mItemCheckable )
272  {
273  if ( isEmpty || additionalIndex >= 0 )
274  return QVariant();
275 
276  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
277  return layer ? mLayersChecked[layer->id()] : QVariant();
278  }
279 
280  return QVariant();
281  }
282 
283  case Qt::ToolTipRole:
284  {
285  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
286  if ( layer )
287  {
288  QStringList parts;
289  QString title = layer->title().isEmpty() ? layer->shortName() : layer->title();
290  if ( title.isEmpty() )
291  title = layer->name();
292  title = "<b>" + title + "</b>";
293  if ( layer->isSpatial() && layer->crs().isValid() )
294  {
295  if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
296  title = tr( "%1 (%2 - %3)" ).arg( title, QgsWkbTypes::displayString( vl->wkbType() ), layer->crs().authid() );
297  else
298  title = tr( "%1 (%2) " ).arg( title, layer->crs().authid() );
299  }
300  parts << title;
301 
302  if ( !layer->abstract().isEmpty() )
303  parts << "<br/>" + layer->abstract().replace( QLatin1String( "\n" ), QLatin1String( "<br/>" ) );
304  parts << "<i>" + layer->publicSource() + "</i>";
305  return parts.join( QStringLiteral( "<br/>" ) );
306  }
307  return QVariant();
308  }
309 
310  case Qt::DecorationRole:
311  {
312  if ( isEmpty || additionalIndex >= 0 )
313  return QVariant();
314 
315  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
316  if ( !layer )
317  return QVariant();
318 
319  return iconForLayer( layer );
320  }
321  }
322 
323  return QVariant();
324 }
325 
326 QHash<int, QByteArray> QgsMapLayerModel::roleNames() const
327 {
328  QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
329  roles[LayerIdRole] = "layerId";
330  roles[LayerRole] = "layer";
331 
332  return roles;
333 }
334 
335 Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
336 {
337  if ( !index.isValid() )
338  {
339  return nullptr;
340  }
341 
342  bool isEmpty = index.row() == 0 && mAllowEmpty;
343  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
344 
345  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
346  if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
347  {
348  flags |= Qt::ItemIsUserCheckable;
349  }
350  return flags;
351 }
352 
354 {
355  switch ( layer->type() )
356  {
358  {
359  return QgsLayerItem::iconRaster();
360  }
361 
363  {
364  return QgsLayerItem::iconMesh();
365  }
366 
368  {
369  QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
370  if ( !vl )
371  {
372  return QIcon();
373  }
374  QgsWkbTypes::GeometryType geomType = vl->geometryType();
375  switch ( geomType )
376  {
378  {
379  return QgsLayerItem::iconPoint();
380  }
382  {
383  return QgsLayerItem::iconPolygon();
384  }
386  {
387  return QgsLayerItem::iconLine();
388  }
390  {
391  return QgsLayerItem::iconTable();
392  }
393  default:
394  {
395  return QIcon();
396  }
397  }
398  }
399  default:
400  {
401  return QIcon();
402  }
403  }
404 }
405 
406 
407 bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
408 {
409  bool isEmpty = index.row() == 0 && mAllowEmpty;
410  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
411 
412  if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
413  {
414  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
415  mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
416  emit dataChanged( index, index );
417  return true;
418  }
419 
420  return false;
421 }
QgsMapLayer * layerFromIndex(const QModelIndex &index) const
Returns the map layer corresponding to the specified index.
static QIcon iconRaster()
Definition: qgsdataitem.cpp:72
QModelIndex indexFromLayer(QgsMapLayer *layer) const
indexFromLayer returns the model index for a given layer
Base class for all map layer types.
Definition: qgsmaplayer.h:64
void layersAdded(const QList< QgsMapLayer *> &layers)
Emitted when one or more layers were added to the registry.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:258
Stores the map layer ID.
void checkAll(Qt::CheckState checkState)
checkAll changes the checkstate for all the layers
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:289
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
static QIcon iconLine()
Definition: qgsdataitem.cpp:57
static QIcon iconPoint()
Definition: qgsdataitem.cpp:52
Stores pointer to the map layer itself.
QModelIndex parent(const QModelIndex &child) const override
void setItemsCheckable(bool checkable)
setItemsCheckable defines if layers should be selectable in the widget
QgsMapLayerModel(QObject *parent=nullptr)
QgsMapLayerModel creates a model to display layers in widgets.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
True if index corresponds to an additional (non map layer) item.
void addLayers(const QList< QgsMapLayer *> &layers)
Added in 3.2.
Definition: qgsmaplayer.h:111
void removeLayers(const QStringList &layerIds)
void setShowCrs(bool showCrs)
Sets whether the CRS of layers is also included in the model&#39;s display role.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
Qt::ItemFlags flags(const QModelIndex &index) const override
static QIcon iconPolygon()
Definition: qgsdataitem.cpp:62
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QMap< QString, Qt::CheckState > mLayersChecked
void setAllowEmptyLayer(bool allowEmpty)
Sets whether an optional empty layer ("not set") option is present in the model.
Reads and writes project states.
Definition: qgsproject.h:89
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
QList< QgsMapLayer * > mLayers
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:273
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:138
bool showCrs() const
Returns true if the model includes layer&#39;s CRS in the display role.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QHash< int, QByteArray > roleNames() const override
Returns strings for all roles supported by this model.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:430
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
static QIcon iconTable()
Definition: qgsdataitem.cpp:67
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Definition: qgsmaplayer.h:68
void setAdditionalItems(const QStringList &items)
Sets a list of additional (non map layer) items to include at the end of the model.
static QIcon iconForLayer(QgsMapLayer *layer)
Returns the icon corresponding to a specified map layer.
Represents a vector layer which manages a vector based data sets.
static QIcon iconMesh()
Returns icon for mesh layer type.
Definition: qgsdataitem.cpp:77
QString authid() const
Returns the authority identifier for the CRS.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:71
QList< QgsMapLayer * > layersChecked(Qt::CheckState checkState=Qt::Checked)
layersChecked returns the list of layers which are checked (or unchecked)
True if index corresponds to the empty (not set) value.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.