QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgsmaplayerproxymodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayerproxymodel.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 "qgsmaplayerproxymodel.h"
17 #include "qgsmaplayermodel.h"
18 #include "qgsmaplayer.h"
19 #include "qgsproject.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsrasterlayer.h"
22 #include "qgsmeshlayer.h"
23 #include "qgsvectordataprovider.h"
24 #include "qgsrasterdataprovider.h"
25 #include "qgsmeshdataprovider.h"
26 
28  : QSortFilterProxyModel( parent )
29  , mFilters( All )
30  , mModel( new QgsMapLayerModel( parent ) )
31 {
32  setSourceModel( mModel );
33  setDynamicSortFilter( true );
34  setSortLocaleAware( true );
35  setFilterCaseSensitivity( Qt::CaseInsensitive );
36  sort( 0 );
37 }
38 
40 {
41  mFilters = filters;
42  invalidateFilter();
43  return this;
44 }
45 
46 bool QgsMapLayerProxyModel::layerMatchesFilters( const QgsMapLayer *layer, const Filters &filters )
47 {
48  if ( filters.testFlag( All ) )
49  return true;
50 
51  // layer type
52  if ( ( filters.testFlag( RasterLayer ) && layer->type() == QgsMapLayerType::RasterLayer ) ||
53  ( filters.testFlag( VectorLayer ) && layer->type() == QgsMapLayerType::VectorLayer ) ||
54  ( filters.testFlag( MeshLayer ) && layer->type() == QgsMapLayerType::MeshLayer ) ||
55  ( filters.testFlag( VectorTileLayer ) && layer->type() == QgsMapLayerType::VectorTileLayer ) ||
56  ( filters.testFlag( PointCloudLayer ) && layer->type() == QgsMapLayerType::PointCloudLayer ) ||
57  ( filters.testFlag( AnnotationLayer ) && layer->type() == QgsMapLayerType::AnnotationLayer ) ||
58  ( filters.testFlag( PluginLayer ) && layer->type() == QgsMapLayerType::PluginLayer ) )
59  return true;
60 
61  // geometry type
62  const bool detectGeometry = filters.testFlag( NoGeometry ) ||
63  filters.testFlag( PointLayer ) ||
64  filters.testFlag( LineLayer ) ||
65  filters.testFlag( PolygonLayer ) ||
66  filters.testFlag( HasGeometry );
67  if ( detectGeometry && layer->type() == QgsMapLayerType::VectorLayer )
68  {
69  if ( const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( layer ) )
70  {
71  if ( filters.testFlag( HasGeometry ) && vl->isSpatial() )
72  return true;
73  if ( filters.testFlag( NoGeometry ) && vl->geometryType() == QgsWkbTypes::NullGeometry )
74  return true;
75  if ( filters.testFlag( PointLayer ) && vl->geometryType() == QgsWkbTypes::PointGeometry )
76  return true;
77  if ( filters.testFlag( LineLayer ) && vl->geometryType() == QgsWkbTypes::LineGeometry )
78  return true;
79  if ( filters.testFlag( PolygonLayer ) && vl->geometryType() == QgsWkbTypes::PolygonGeometry )
80  return true;
81  }
82  }
83 
84  return false;
85 }
86 
87 void QgsMapLayerProxyModel::setLayerWhitelist( const QList<QgsMapLayer *> &layers )
88 {
89  setLayerAllowlist( layers );
90 }
91 
92 void QgsMapLayerProxyModel::setLayerAllowlist( const QList<QgsMapLayer *> &layers )
93 {
94  if ( mLayerAllowlist == layers )
95  return;
96 
97  mLayerAllowlist = layers;
98  invalidateFilter();
99 }
100 
101 void QgsMapLayerProxyModel::setExceptedLayerList( const QList<QgsMapLayer *> &exceptList )
102 {
103  if ( mExceptList == exceptList )
104  return;
105 
106  mExceptList = exceptList;
107  invalidateFilter();
108 }
109 
110 void QgsMapLayerProxyModel::setExceptedLayerIds( const QStringList &ids )
111 {
112  mExceptList.clear();
113 
114  const auto constIds = ids;
115  for ( const QString &id : constIds )
116  {
118  if ( l )
119  mExceptList << l;
120  }
121  invalidateFilter();
122 }
123 
125 {
126  QStringList lst;
127 
128  const auto constMExceptList = mExceptList;
129  for ( QgsMapLayer *l : constMExceptList )
130  lst << l->id();
131 
132  return lst;
133 }
134 
135 void QgsMapLayerProxyModel::setExcludedProviders( const QStringList &providers )
136 {
137  mExcludedProviders = providers;
138  invalidateFilter();
139 }
140 
142 {
143  if ( !layer )
144  return false;
145 
146  if ( !mLayerAllowlist.isEmpty() && !mLayerAllowlist.contains( layer ) )
147  return false;
148 
149  if ( mExceptList.contains( layer ) )
150  return false;
151 
152  if ( layer->dataProvider() && mExcludedProviders.contains( layer->providerType() ) )
153  return false;
154 
155  if ( mFilters.testFlag( WritableLayer ) && layer->readOnly() )
156  return false;
157 
158  if ( !layer->name().contains( mFilterString, Qt::CaseInsensitive ) )
159  return false;
160 
161  return layerMatchesFilters( layer, mFilters );
162 }
163 
164 void QgsMapLayerProxyModel::setFilterString( const QString &filter )
165 {
166  mFilterString = filter;
167  invalidateFilter();
168 }
169 
170 bool QgsMapLayerProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
171 {
172  if ( mFilters.testFlag( All ) && mExceptList.isEmpty() && mLayerAllowlist.isEmpty() && mExcludedProviders.isEmpty() && mFilterString.isEmpty() )
173  return true;
174 
175  const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
176 
177  if ( sourceModel()->data( index, QgsMapLayerModel::EmptyRole ).toBool()
178  || sourceModel()->data( index, QgsMapLayerModel::AdditionalRole ).toBool() )
179  return true;
180 
181  return acceptsLayer( static_cast<QgsMapLayer *>( index.internalPointer() ) );
182 }
183 
184 bool QgsMapLayerProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
185 {
186  // empty row is always first
187  if ( sourceModel()->data( left, QgsMapLayerModel::EmptyRole ).toBool() )
188  return true;
189  else if ( sourceModel()->data( right, QgsMapLayerModel::EmptyRole ).toBool() )
190  return false;
191 
192  // additional rows are always last
193  const bool leftAdditional = sourceModel()->data( left, QgsMapLayerModel::AdditionalRole ).toBool();
194  const bool rightAdditional = sourceModel()->data( right, QgsMapLayerModel::AdditionalRole ).toBool();
195 
196  if ( leftAdditional && !rightAdditional )
197  return false;
198  else if ( rightAdditional && !leftAdditional )
199  return true;
200 
201  // default mode is alphabetical order
202  const QString leftStr = sourceModel()->data( left ).toString();
203  const QString rightStr = sourceModel()->data( right ).toString();
204  return QString::localeAwareCompare( leftStr, rightStr ) < 0;
205 }
The QgsMapLayerModel class is a model to display layers in widgets.
@ EmptyRole
True if index corresponds to the empty (not set) value.
@ AdditionalRole
True if index corresponds to an additional (non map layer) item.
The QgsMapLayerProxyModel class provides an easy to use model to display the list of layers in widget...
QgsMapLayerProxyModel::Filters filters
static bool layerMatchesFilters(const QgsMapLayer *layer, const Filters &filters)
Returns if the layer matches the given filters.
QgsMapLayerProxyModel * setFilters(QgsMapLayerProxyModel::Filters filters)
Sets filter flags which affect how layers are filtered within the model.
void setExceptedLayerIds(const QStringList &ids)
Sets a blocklist of layers (by layer ID) to exclude from the model.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
void setFilterString(const QString &filter)
Sets a filter string, such that only layers with names matching the specified string will be shown.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
QgsMapLayerProxyModel(QObject *parent=nullptr)
QgsMapLayerProxModel creates a proxy model with a QgsMapLayerModel as source model.
bool acceptsLayer(QgsMapLayer *layer) const
Returns true if the proxy model accepts the specified map layer.
void setExcludedProviders(const QStringList &providers)
Sets a blocklist of data providers which should be excluded from the model.
void setLayerAllowlist(const QList< QgsMapLayer * > &layers)
Sets an allowlist of layers to include within the model.
@ AnnotationLayer
QgsAnnotationLayer.
@ VectorTileLayer
QgsVectorTileLayer.
@ PointCloudLayer
QgsPointCloudLayer.
Q_DECL_DEPRECATED void setLayerWhitelist(const QList< QgsMapLayer * > &layers)
Sets an allowlist of layers to include within the model.
void setExceptedLayerList(const QList< QgsMapLayer * > &exceptList)
Sets a blocklist of layers to exclude from the model.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
bool readOnly() const
Returns if this layer is read only.
Definition: qgsmaplayer.h:529
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
Represents a vector layer which manages a vector based data sets.
@ PointCloudLayer
Added in 3.18.
@ MeshLayer
Added in 3.2.
@ VectorTileLayer
Added in 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.