QGIS API Documentation  2.99.0-Master (8ec3eaf)
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 "qgsmaplayerregistry.h"
21 #include "qgsapplication.h"
22 #include "qgsvectorlayer.h"
23 
24 
25 QgsMapLayerModel::QgsMapLayerModel( const QList<QgsMapLayer *>& layers, QObject *parent )
26  : QAbstractItemModel( parent )
27  , mLayersChecked( QMap<QString, Qt::CheckState>() )
28  , mItemCheckable( false )
29  , mAllowEmpty( false )
30  , mShowCrs( false )
31 {
32  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
33  addLayers( layers );
34 }
35 
37  : QAbstractItemModel( parent )
38  , mLayersChecked( QMap<QString, Qt::CheckState>() )
39  , mItemCheckable( false )
40  , mAllowEmpty( false )
41  , mShowCrs( false )
42 {
43  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer*> ) ), this, SLOT( addLayers( QList<QgsMapLayer*> ) ) );
44  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
45  addLayers( QgsMapLayerRegistry::instance()->mapLayers().values() );
46 }
47 
49 {
50  mItemCheckable = checkable;
51 }
52 
53 void QgsMapLayerModel::checkAll( Qt::CheckState checkState )
54 {
55  Q_FOREACH ( const QString& key, mLayersChecked.keys() )
56  {
57  mLayersChecked[key] = checkState;
58  }
59  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) );
60 }
61 
62 void QgsMapLayerModel::setAllowEmptyLayer( bool allowEmpty )
63 {
64  if ( allowEmpty == mAllowEmpty )
65  return;
66 
67  if ( allowEmpty )
68  {
69  beginInsertRows( QModelIndex(), 0, 0 );
70  mAllowEmpty = true;
71  endInsertRows();
72  }
73  else
74  {
75  beginRemoveRows( QModelIndex(), 0, 0 );
76  mAllowEmpty = false;
77  endRemoveRows();
78  }
79 }
80 
82 {
83  if ( mShowCrs == showCrs )
84  return;
85 
86  mShowCrs = showCrs;
87  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::DisplayRole );
88 }
89 
90 QList<QgsMapLayer *> QgsMapLayerModel::layersChecked( Qt::CheckState checkState )
91 {
92  QList<QgsMapLayer *> layers;
93  Q_FOREACH ( QgsMapLayer* layer, mLayers )
94  {
95  if ( mLayersChecked[layer->id()] == checkState )
96  {
97  layers.append( layer );
98  }
99  }
100  return layers;
101 }
102 
104 {
105  int r = mLayers.indexOf( layer );
106  if ( r >= 0 && mAllowEmpty )
107  r++;
108  return index( r, 0 );
109 }
110 
111 void QgsMapLayerModel::setAdditionalItems( const QStringList& items )
112 {
113  if ( items == mAdditionalItems )
114  return;
115 
116  int offset = 0;
117  if ( mAllowEmpty )
118  offset++;
119 
120  offset += mLayers.count();
121 
122  //remove existing
123  if ( !mAdditionalItems.isEmpty() )
124  {
125  beginRemoveRows( QModelIndex(), offset, offset + mAdditionalItems.count() - 1 );
126  mAdditionalItems.clear();
127  endRemoveRows();
128  }
129 
130  //add new
131  beginInsertRows( QModelIndex(), offset, offset + items.count() - 1 );
132  mAdditionalItems = items;
133  endInsertRows();
134 }
135 
136 void QgsMapLayerModel::removeLayers( const QStringList& layerIds )
137 {
138  int offset = 0;
139  if ( mAllowEmpty )
140  offset++;
141 
142  Q_FOREACH ( const QString& layerId, layerIds )
143  {
144  QModelIndex startIndex = index( 0, 0 );
145  QModelIndexList list = match( startIndex, LayerIdRole, layerId, 1 );
146  if ( !list.isEmpty() )
147  {
148  QModelIndex index = list[0];
149  beginRemoveRows( QModelIndex(), index.row(), index.row() );
150  mLayersChecked.remove( layerId );
151  mLayers.removeAt( index.row() - offset );
152  endRemoveRows();
153  }
154  }
155 }
156 
157 void QgsMapLayerModel::addLayers( const QList<QgsMapLayer *>& layers )
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 QModelIndex QgsMapLayerModel::index( int row, int column, const QModelIndex &parent ) const
173 {
174  int offset = 0;
175  if ( mAllowEmpty )
176  offset++;
177 
178  if ( hasIndex( row, column, parent ) )
179  {
180  QgsMapLayer* layer = nullptr;
181  if ( row - offset >= 0 && row - offset < mLayers.count() )
182  layer = mLayers.at( row - offset );
183 
184  return createIndex( row, column, layer );
185  }
186 
187  return QModelIndex();
188 
189 }
190 
191 QModelIndex QgsMapLayerModel::parent( const QModelIndex &child ) const
192 {
193  Q_UNUSED( child );
194  return QModelIndex();
195 }
196 
197 
198 int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
199 {
200  if ( parent.isValid() )
201  return 0;
202 
203  return ( mAllowEmpty ? 1 : 0 ) + mLayers.length() + mAdditionalItems.count();
204 }
205 
206 int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
207 {
208  Q_UNUSED( parent );
209  return 1;
210 }
211 
212 
213 QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
214 {
215  if ( !index.isValid() )
216  return QVariant();
217 
218  bool isEmpty = index.row() == 0 && mAllowEmpty;
219  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
220 
221  switch ( role )
222  {
223  case Qt::DisplayRole:
224  {
225  if ( index.row() == 0 && mAllowEmpty )
226  return QVariant();
227 
228  if ( additionalIndex >= 0 )
229  return mAdditionalItems.at( additionalIndex );
230 
231  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
232  if ( !layer )
233  return QVariant();
234 
235  if ( !mShowCrs )
236  {
237  return layer->name();
238  }
239  else
240  {
241  return tr( "%1 [%2]" ).arg( layer->name(), layer->crs().authid() );
242  }
243  }
244 
245  case LayerIdRole:
246  {
247  if ( isEmpty || additionalIndex >= 0 )
248  return QVariant();
249 
250  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
251  return layer ? layer->id() : QVariant();
252  }
253 
254  case LayerRole:
255  {
256  if ( isEmpty || additionalIndex >= 0 )
257  return QVariant();
258 
259  return QVariant::fromValue<QgsMapLayer*>( static_cast<QgsMapLayer*>( index.internalPointer() ) );
260  }
261 
262  case EmptyRole:
263  return isEmpty;
264 
265  case AdditionalRole:
266  return additionalIndex >= 0;
267 
268  case Qt::CheckStateRole:
269  {
270  if ( mItemCheckable )
271  {
272  if ( isEmpty || additionalIndex >= 0 )
273  return QVariant();
274 
275  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
276  return layer ? mLayersChecked[layer->id()] : QVariant();
277  }
278 
279  return QVariant();
280  }
281 
282  case Qt::ToolTipRole:
283  {
284  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
285  if ( layer )
286  {
287  QString tooltip = "<b>" +
288  ( layer->title().isEmpty() ? layer->shortName() : layer->title() ) + "</b>";
289  if ( !layer->abstract().isEmpty() )
290  tooltip += "<br/>" + layer->abstract().replace( QLatin1String( "\n" ), QLatin1String( "<br/>" ) );
291  tooltip += "<br/><i>" + layer->publicSource() + "</i>";
292  return tooltip;
293  }
294  return QVariant();
295  }
296 
297  case Qt::DecorationRole:
298  {
299  if ( isEmpty || additionalIndex >= 0 )
300  return QVariant();
301 
302  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
303  if ( !layer )
304  return QVariant();
305 
306  QgsMapLayer::LayerType type = layer->type();
307  if ( role == Qt::DecorationRole )
308  {
309  switch ( type )
310  {
312  {
313  return QgsLayerItem::iconRaster();
314  }
315 
317  {
318  QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
319  if ( !vl )
320  {
321  return QIcon();
322  }
323  QgsWkbTypes::GeometryType geomType = vl->geometryType();
324  switch ( geomType )
325  {
327  {
328  return QgsLayerItem::iconPoint();
329  }
331  {
332  return QgsLayerItem::iconPolygon();
333  }
335  {
336  return QgsLayerItem::iconLine();
337  }
339  {
340  return QgsLayerItem::iconTable();
341  }
342  default:
343  {
344  return QIcon();
345  }
346  }
347  }
348  default:
349  {
350  return QIcon();
351  }
352  }
353  }
354  }
355  }
356 
357  return QVariant();
358 }
359 
360 QHash<int, QByteArray> QgsMapLayerModel::roleNames() const
361 {
362  QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
363  roles[LayerIdRole] = "layerId";
364  roles[LayerRole] = "layer";
365 
366  return roles;
367 }
368 
369 Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
370 {
371  if ( !index.isValid() )
372  {
373  return 0;
374  }
375 
376  bool isEmpty = index.row() == 0 && mAllowEmpty;
377  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
378 
379  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
380  if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
381  {
382  flags |= Qt::ItemIsUserCheckable;
383  }
384  return flags;
385 }
386 
387 
388 bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
389 {
390  bool isEmpty = index.row() == 0 && mAllowEmpty;
391  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
392 
393  if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
394  {
395  QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
396  mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
397  emit dataChanged( index, index );
398  return true;
399  }
400 
401  return false;
402 }
QModelIndex indexFromLayer(QgsMapLayer *layer) const
indexFromLayer returns the model index for a given layer
Base class for all map layer types.
Definition: qgsmaplayer.h:49
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:112
static const QIcon & iconPoint()
Definition: qgsdataitem.cpp:99
Stores the map layer ID.
QList< QgsMapLayer * > mLayers
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:140
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Stores pointer to the map layer itself.
QModelIndex parent(const QModelIndex &child) const override
static const QIcon & iconPolygon()
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.
Definition: qgsmaplayer.cpp:97
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 QgsMapLayerRegistry.
Qt::ItemFlags flags(const QModelIndex &index) const override
static const QIcon & iconRaster()
LayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:58
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.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:126
static const QIcon & iconTable()
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
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QHash< int, QByteArray > roleNames() const override
Returns strings for all roles supported by this model.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
static const QIcon & iconLine()
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:53
void setAdditionalItems(const QStringList &items)
Sets a list of additional (non map layer) items to include at the end of the model.
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.