QGIS API Documentation  2.99.0-Master (25b0421)
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 
104 void QgsMapLayerModel::setAdditionalItems( const QStringList &items )
105 {
106  if ( items == mAdditionalItems )
107  return;
108 
109  int offset = 0;
110  if ( mAllowEmpty )
111  offset++;
112 
113  offset += mLayers.count();
114 
115  //remove existing
116  if ( !mAdditionalItems.isEmpty() )
117  {
118  beginRemoveRows( QModelIndex(), offset, offset + mAdditionalItems.count() - 1 );
119  mAdditionalItems.clear();
120  endRemoveRows();
121  }
122 
123  //add new
124  beginInsertRows( QModelIndex(), offset, offset + items.count() - 1 );
125  mAdditionalItems = items;
126  endInsertRows();
127 }
128 
129 void QgsMapLayerModel::removeLayers( const QStringList &layerIds )
130 {
131  int offset = 0;
132  if ( mAllowEmpty )
133  offset++;
134 
135  Q_FOREACH ( const QString &layerId, layerIds )
136  {
137  QModelIndex startIndex = index( 0, 0 );
138  QModelIndexList list = match( startIndex, LayerIdRole, layerId, 1 );
139  if ( !list.isEmpty() )
140  {
141  QModelIndex index = list[0];
142  beginRemoveRows( QModelIndex(), index.row(), index.row() );
143  mLayersChecked.remove( layerId );
144  mLayers.removeAt( index.row() - offset );
145  endRemoveRows();
146  }
147  }
148 }
149 
150 void QgsMapLayerModel::addLayers( const QList<QgsMapLayer *> &layers )
151 {
152  int offset = 0;
153  if ( mAllowEmpty )
154  offset++;
155 
156  beginInsertRows( QModelIndex(), mLayers.count() + offset, mLayers.count() + layers.count() - 1 + offset );
157  Q_FOREACH ( QgsMapLayer *layer, layers )
158  {
159  mLayers.append( layer );
160  mLayersChecked.insert( layer->id(), Qt::Unchecked );
161  }
162  endInsertRows();
163 }
164 
165 QModelIndex QgsMapLayerModel::index( int row, int column, const QModelIndex &parent ) const
166 {
167  int offset = 0;
168  if ( mAllowEmpty )
169  offset++;
170 
171  if ( hasIndex( row, column, parent ) )
172  {
173  QgsMapLayer *layer = nullptr;
174  if ( row - offset >= 0 && row - offset < mLayers.count() )
175  layer = mLayers.at( row - offset );
176 
177  return createIndex( row, column, layer );
178  }
179 
180  return QModelIndex();
181 
182 }
183 
184 QModelIndex QgsMapLayerModel::parent( const QModelIndex &child ) const
185 {
186  Q_UNUSED( child );
187  return QModelIndex();
188 }
189 
190 
191 int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
192 {
193  if ( parent.isValid() )
194  return 0;
195 
196  return ( mAllowEmpty ? 1 : 0 ) + mLayers.length() + mAdditionalItems.count();
197 }
198 
199 int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
200 {
201  Q_UNUSED( parent );
202  return 1;
203 }
204 
205 
206 QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
207 {
208  if ( !index.isValid() )
209  return QVariant();
210 
211  bool isEmpty = index.row() == 0 && mAllowEmpty;
212  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
213 
214  switch ( role )
215  {
216  case Qt::DisplayRole:
217  {
218  if ( index.row() == 0 && mAllowEmpty )
219  return QVariant();
220 
221  if ( additionalIndex >= 0 )
222  return mAdditionalItems.at( additionalIndex );
223 
224  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
225  if ( !layer )
226  return QVariant();
227 
228  if ( !mShowCrs )
229  {
230  return layer->name();
231  }
232  else
233  {
234  return tr( "%1 [%2]" ).arg( layer->name(), layer->crs().authid() );
235  }
236  }
237 
238  case LayerIdRole:
239  {
240  if ( isEmpty || additionalIndex >= 0 )
241  return QVariant();
242 
243  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
244  return layer ? layer->id() : QVariant();
245  }
246 
247  case LayerRole:
248  {
249  if ( isEmpty || additionalIndex >= 0 )
250  return QVariant();
251 
252  return QVariant::fromValue<QgsMapLayer *>( static_cast<QgsMapLayer *>( index.internalPointer() ) );
253  }
254 
255  case EmptyRole:
256  return isEmpty;
257 
258  case AdditionalRole:
259  return additionalIndex >= 0;
260 
261  case Qt::CheckStateRole:
262  {
263  if ( mItemCheckable )
264  {
265  if ( isEmpty || additionalIndex >= 0 )
266  return QVariant();
267 
268  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
269  return layer ? mLayersChecked[layer->id()] : QVariant();
270  }
271 
272  return QVariant();
273  }
274 
275  case Qt::ToolTipRole:
276  {
277  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
278  if ( layer )
279  {
280  QStringList parts;
281  QString title = layer->title().isEmpty() ? layer->shortName() : layer->title();
282  if ( title.isEmpty() )
283  title = layer->name();
284  title = "<b>" + title + "</b>";
285  if ( layer->crs().isValid() )
286  title = tr( "%1 (%2)" ).arg( title, layer->crs().authid() );
287 
288  parts << title;
289 
290  if ( !layer->abstract().isEmpty() )
291  parts << "<br/>" + layer->abstract().replace( QLatin1String( "\n" ), QLatin1String( "<br/>" ) );
292  parts << "<i>" + layer->publicSource() + "</i>";
293  return parts.join( QStringLiteral( "<br/>" ) );
294  }
295  return QVariant();
296  }
297 
298  case Qt::DecorationRole:
299  {
300  if ( isEmpty || additionalIndex >= 0 )
301  return QVariant();
302 
303  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
304  if ( !layer )
305  return QVariant();
306 
307  return iconForLayer( layer );
308  }
309  }
310 
311  return QVariant();
312 }
313 
314 QHash<int, QByteArray> QgsMapLayerModel::roleNames() const
315 {
316  QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
317  roles[LayerIdRole] = "layerId";
318  roles[LayerRole] = "layer";
319 
320  return roles;
321 }
322 
323 Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
324 {
325  if ( !index.isValid() )
326  {
327  return 0;
328  }
329 
330  bool isEmpty = index.row() == 0 && mAllowEmpty;
331  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
332 
333  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
334  if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
335  {
336  flags |= Qt::ItemIsUserCheckable;
337  }
338  return flags;
339 }
340 
342 {
343  switch ( layer->type() )
344  {
346  {
347  return QgsLayerItem::iconRaster();
348  }
349 
351  {
352  QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
353  if ( !vl )
354  {
355  return QIcon();
356  }
357  QgsWkbTypes::GeometryType geomType = vl->geometryType();
358  switch ( geomType )
359  {
361  {
362  return QgsLayerItem::iconPoint();
363  }
365  {
366  return QgsLayerItem::iconPolygon();
367  }
369  {
370  return QgsLayerItem::iconLine();
371  }
373  {
374  return QgsLayerItem::iconTable();
375  }
376  default:
377  {
378  return QIcon();
379  }
380  }
381  }
382  default:
383  {
384  return QIcon();
385  }
386  }
387 }
388 
389 
390 bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
391 {
392  bool isEmpty = index.row() == 0 && mAllowEmpty;
393  int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();
394 
395  if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
396  {
397  QgsMapLayer *layer = static_cast<QgsMapLayer *>( index.internalPointer() );
398  mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
399  emit dataChanged( index, index );
400  return true;
401  }
402 
403  return false;
404 }
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:175
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:206
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:190
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 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.