QGIS API Documentation  2.99.0-Master (dc72e14)
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  , mLayersChecked( QMap<QString, Qt::CheckState>() )
28  , mItemCheckable( false )
29  , mAllowEmpty( false )
30  , mShowCrs( false )
31 {
32  connect( QgsProject::instance(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsMapLayerModel::removeLayers );
33  addLayers( layers );
34 }
35 
37  : QAbstractItemModel( parent )
38  , mLayersChecked( QMap<QString, Qt::CheckState>() )
39  , mItemCheckable( false )
40  , mAllowEmpty( false )
41  , mShowCrs( false )
42 {
44  connect( QgsProject::instance(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsMapLayerModel::removeLayers );
45  addLayers( QgsProject::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  QStringList parts;
288  QString title = layer->title().isEmpty() ? layer->shortName() : layer->title();
289  if ( title.isEmpty() )
290  title = layer->name();
291  title = "<b>" + title + "</b>";
292  if ( layer->crs().isValid() )
293  title = tr( "%1 (%2)" ).arg( title, layer->crs().authid() );
294 
295  parts << title;
296 
297  if ( !layer->abstract().isEmpty() )
298  parts << "<br/>" + layer->abstract().replace( QLatin1String( "\n" ), QLatin1String( "<br/>" ) );
299  parts << "<i>" + layer->publicSource() + "</i>";
300  return parts.join( "<br/>" );
301  }
302  return QVariant();
303  }
304 
305  case Qt::DecorationRole:
306  {
307  if ( isEmpty || additionalIndex >= 0 )
308  return QVariant();
309 
310  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
311  if ( !layer )
312  return QVariant();
313 
314  return iconForLayer( layer );
315  }
316  }
317 
318  return QVariant();
319 }
320 
321 QHash<int, QByteArray> QgsMapLayerModel::roleNames() const
322 {
323  QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
324  roles[LayerIdRole] = "layerId";
325  roles[LayerRole] = "layer";
326 
327  return roles;
328 }
329 
330 Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
331 {
332  if ( !index.isValid() )
333  {
334  return 0;
335  }
336 
337  bool isEmpty = index.row() == 0 && mAllowEmpty;
338  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
339 
340  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
341  if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
342  {
343  flags |= Qt::ItemIsUserCheckable;
344  }
345  return flags;
346 }
347 
349 {
350  switch ( layer->type() )
351  {
353  {
354  return QgsLayerItem::iconRaster();
355  }
356 
358  {
359  QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
360  if ( !vl )
361  {
362  return QIcon();
363  }
364  QgsWkbTypes::GeometryType geomType = vl->geometryType();
365  switch ( geomType )
366  {
368  {
369  return QgsLayerItem::iconPoint();
370  }
372  {
373  return QgsLayerItem::iconPolygon();
374  }
376  {
377  return QgsLayerItem::iconLine();
378  }
380  {
381  return QgsLayerItem::iconTable();
382  }
383  default:
384  {
385  return QIcon();
386  }
387  }
388  }
389  default:
390  {
391  return QIcon();
392  }
393  }
394 }
395 
396 
397 bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
398 {
399  bool isEmpty = index.row() == 0 && mAllowEmpty;
400  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
401 
402  if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
403  {
404  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
405  mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
406  emit dataChanged( index, index );
407  return true;
408  }
409 
410  return false;
411 }
static QIcon iconRaster()
Definition: qgsdataitem.cpp:68
QModelIndex indexFromLayer(QgsMapLayer *layer) const
indexFromLayer returns the model index for a given layer
Base class for all map layer types.
Definition: qgsmaplayer.h:54
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:166
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:193
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
static QIcon iconLine()
Definition: qgsdataitem.cpp:53
static QIcon iconPoint()
Definition: qgsdataitem.cpp:48
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: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.
Reads and writes project states.
Definition: qgsproject.h:79
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:179
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:136
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:379
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
static QIcon iconTable()
Definition: qgsdataitem.cpp:63
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Definition: qgsmaplayer.h:58
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.