QGIS API Documentation  2.99.0-Master (19b062c)
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 : denis.rouzaud@gmail.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 <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  int offset = 0;
158  if ( mAllowEmpty )
159  offset++;
160 
161  beginInsertRows( QModelIndex(), mLayers.count() + offset, mLayers.count() + layers.count() - 1 + offset );
162  Q_FOREACH ( QgsMapLayer *layer, layers )
163  {
164  mLayers.append( layer );
165  mLayersChecked.insert( layer->id(), Qt::Unchecked );
166  }
167  endInsertRows();
168 }
169 
170 QModelIndex QgsMapLayerModel::index( int row, int column, const QModelIndex &parent ) const
171 {
172  int offset = 0;
173  if ( mAllowEmpty )
174  offset++;
175 
176  if ( hasIndex( row, column, parent ) )
177  {
178  QgsMapLayer *layer = nullptr;
179  if ( row - offset >= 0 && row - offset < mLayers.count() )
180  layer = mLayers.at( row - offset );
181 
182  return createIndex( row, column, layer );
183  }
184 
185  return QModelIndex();
186 
187 }
188 
189 QModelIndex QgsMapLayerModel::parent( const QModelIndex &child ) const
190 {
191  Q_UNUSED( child );
192  return QModelIndex();
193 }
194 
195 
196 int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
197 {
198  if ( parent.isValid() )
199  return 0;
200 
201  return ( mAllowEmpty ? 1 : 0 ) + mLayers.length() + mAdditionalItems.count();
202 }
203 
204 int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
205 {
206  Q_UNUSED( parent );
207  return 1;
208 }
209 
210 
211 QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
212 {
213  if ( !index.isValid() )
214  return QVariant();
215 
216  bool isEmpty = index.row() == 0 && mAllowEmpty;
217  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
218 
219  switch ( role )
220  {
221  case Qt::DisplayRole:
222  {
223  if ( index.row() == 0 && mAllowEmpty )
224  return QVariant();
225 
226  if ( additionalIndex >= 0 )
227  return mAdditionalItems.at( additionalIndex );
228 
229  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
230  if ( !layer )
231  return QVariant();
232 
233  if ( !mShowCrs )
234  {
235  return layer->name();
236  }
237  else
238  {
239  return tr( "%1 [%2]" ).arg( layer->name(), layer->crs().authid() );
240  }
241  }
242 
243  case LayerIdRole:
244  {
245  if ( isEmpty || additionalIndex >= 0 )
246  return QVariant();
247 
248  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
249  return layer ? layer->id() : QVariant();
250  }
251 
252  case LayerRole:
253  {
254  if ( isEmpty || additionalIndex >= 0 )
255  return QVariant();
256 
257  return QVariant::fromValue<QgsMapLayer *>( static_cast<QgsMapLayer *>( index.internalPointer() ) );
258  }
259 
260  case EmptyRole:
261  return isEmpty;
262 
263  case AdditionalRole:
264  return additionalIndex >= 0;
265 
266  case Qt::CheckStateRole:
267  {
268  if ( mItemCheckable )
269  {
270  if ( isEmpty || additionalIndex >= 0 )
271  return QVariant();
272 
273  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
274  return layer ? mLayersChecked[layer->id()] : QVariant();
275  }
276 
277  return QVariant();
278  }
279 
280  case Qt::ToolTipRole:
281  {
282  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
283  if ( layer )
284  {
285  QStringList parts;
286  QString title = layer->title().isEmpty() ? layer->shortName() : layer->title();
287  if ( title.isEmpty() )
288  title = layer->name();
289  title = "<b>" + title + "</b>";
290  if ( layer->crs().isValid() )
291  {
292  if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
293  title = tr( "%1 (%2 - %3)" ).arg( title, QgsWkbTypes::displayString( vl->wkbType() ), layer->crs().authid() );
294  else
295  title = tr( "%1 (%2) " ).arg( title, layer->crs().authid() );
296  }
297  parts << title;
298 
299  if ( !layer->abstract().isEmpty() )
300  parts << "<br/>" + layer->abstract().replace( QLatin1String( "\n" ), QLatin1String( "<br/>" ) );
301  parts << "<i>" + layer->publicSource() + "</i>";
302  return parts.join( QStringLiteral( "<br/>" ) );
303  }
304  return QVariant();
305  }
306 
307  case Qt::DecorationRole:
308  {
309  if ( isEmpty || additionalIndex >= 0 )
310  return QVariant();
311 
312  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
313  if ( !layer )
314  return QVariant();
315 
316  return iconForLayer( layer );
317  }
318  }
319 
320  return QVariant();
321 }
322 
323 QHash<int, QByteArray> QgsMapLayerModel::roleNames() const
324 {
325  QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
326  roles[LayerIdRole] = "layerId";
327  roles[LayerRole] = "layer";
328 
329  return roles;
330 }
331 
332 Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
333 {
334  if ( !index.isValid() )
335  {
336  return 0;
337  }
338 
339  bool isEmpty = index.row() == 0 && mAllowEmpty;
340  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
341 
342  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
343  if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
344  {
345  flags |= Qt::ItemIsUserCheckable;
346  }
347  return flags;
348 }
349 
351 {
352  switch ( layer->type() )
353  {
355  {
356  return QgsLayerItem::iconRaster();
357  }
358 
360  {
361  QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
362  if ( !vl )
363  {
364  return QIcon();
365  }
366  QgsWkbTypes::GeometryType geomType = vl->geometryType();
367  switch ( geomType )
368  {
370  {
371  return QgsLayerItem::iconPoint();
372  }
374  {
375  return QgsLayerItem::iconPolygon();
376  }
378  {
379  return QgsLayerItem::iconLine();
380  }
382  {
383  return QgsLayerItem::iconTable();
384  }
385  default:
386  {
387  return QIcon();
388  }
389  }
390  }
391  default:
392  {
393  return QIcon();
394  }
395  }
396 }
397 
398 
399 bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
400 {
401  bool isEmpty = index.row() == 0 && mAllowEmpty;
402  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
403 
404  if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
405  {
406  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
407  mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
408  emit dataChanged( index, index );
409  return true;
410  }
411 
412  return false;
413 }
QgsMapLayer * layerFromIndex(const QModelIndex &index) const
Returns the map layer corresponding to the specified index.
static QIcon iconRaster()
Definition: qgsdataitem.cpp:69
QModelIndex indexFromLayer(QgsMapLayer *layer) const
indexFromLayer returns the model index for a given layer
Base class for all map layer types.
Definition: qgsmaplayer.h:56
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:169
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:200
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
static QIcon iconLine()
Definition: qgsdataitem.cpp:54
static QIcon iconPoint()
Definition: qgsdataitem.cpp:49
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)
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:59
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.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
Reads and writes project states.
Definition: qgsproject.h:81
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:184
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:137
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:383
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...
static QIcon iconTable()
Definition: qgsdataitem.cpp:64
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Definition: qgsmaplayer.h:60
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.
QString authid() const
Returns the authority identifier for the CRS.
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.