QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 }
static QIcon iconRaster()
Definition: qgsdataitem.cpp:75
Base class for all map layer types.
Definition: qgsmaplayer.h:63
QgsMapLayer::LayerType type() const
Returns the type of the layer.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:257
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Stores the map layer ID.
void checkAll(Qt::CheckState checkState)
checkAll changes the checkstate for all the layers
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:272
QModelIndex indexFromLayer(QgsMapLayer *layer) const
indexFromLayer returns the model index for a given layer
static QIcon iconLine()
Definition: qgsdataitem.cpp:60
static QIcon iconPoint()
Definition: qgsdataitem.cpp:55
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.
True if index corresponds to an additional (non map layer) item.
Added in 3.2.
Definition: qgsmaplayer.h:110
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
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.
Qt::ItemFlags flags(const QModelIndex &index) const override
static QIcon iconPolygon()
Definition: qgsdataitem.cpp:65
void addLayers(const QList< QgsMapLayer * > &layers)
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.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
Reads and writes project states.
Definition: qgsproject.h:89
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:288
QList< QgsMapLayer * > mLayers
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:138
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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.
QgsMapLayer * layerFromIndex(const QModelIndex &index) const
Returns the map layer corresponding to the specified index.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:411
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QString authid() const
Returns the authority identifier for the CRS.
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
static QIcon iconTable()
Definition: qgsdataitem.cpp:70
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Definition: qgsmaplayer.h:67
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
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:80
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
bool showCrs() const
Returns true if the model includes layer&#39;s CRS in the display role.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:70
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.