QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
qgslayertreefilterproxymodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayertreefilterproxymodel.cpp
3
4 ---------------------
5 begin : 05.06.2020
6 copyright : (C) 2020 by Denis Rouzaud
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "moc_qgslayertreefilterproxymodel.cpp"
19
20#include "qgslayertree.h"
21#include "qgslayertreemodel.h"
22#include "qgssymbol.h"
23
25 : QSortFilterProxyModel( parent )
26{
27 connect( QgsProject::instance(), &QgsProject::readProject, this, [this] // skip-keyword-check
28 {
29 beginResetModel();
30 endResetModel();
31 } );
32}
33
34void QgsLayerTreeFilterProxyModel::setCheckedLayers( const QList<QgsMapLayer *> layers )
35{
36 // do not use invalidate() since it's not the filter which changes but the data
37 beginResetModel();
38 mCheckedLayers = layers;
39 endResetModel();
40}
41
42int QgsLayerTreeFilterProxyModel::columnCount( const QModelIndex &parent ) const
43{
44 Q_UNUSED( parent )
45 return 1;
46}
47
48Qt::ItemFlags QgsLayerTreeFilterProxyModel::flags( const QModelIndex &idx ) const
49{
50 if ( idx.column() == 0 )
51 {
52 return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
53 }
54 return Qt::NoItemFlags;
55}
56
57QModelIndex QgsLayerTreeFilterProxyModel::index( int row, int column, const QModelIndex &parent ) const
58{
59 QModelIndex newIndex = QSortFilterProxyModel::index( row, 0, parent );
60 if ( column == 0 )
61 return newIndex;
62
63 return createIndex( row, column, newIndex.internalId() );
64}
65
66QModelIndex QgsLayerTreeFilterProxyModel::parent( const QModelIndex &child ) const
67{
68 return QSortFilterProxyModel::parent( createIndex( child.row(), 0, child.internalId() ) );
69}
70
71QModelIndex QgsLayerTreeFilterProxyModel::sibling( int row, int column, const QModelIndex &idx ) const
72{
73 const QModelIndex parent = idx.parent();
74 return index( row, column, parent );
75}
76
78{
79 QgsLayerTreeNode *node = nullptr;
80 if ( idx.column() == 0 )
81 {
82 node = mLayerTreeModel->index2node( mapToSource( idx ) );
83 }
84
85 if ( !node || !QgsLayerTree::isLayer( node ) )
86 return nullptr;
87
88 return QgsLayerTree::toLayer( node )->layer();
89}
90
91void QgsLayerTreeFilterProxyModel::setFilterText( const QString &filterText )
92{
93 if ( filterText == mFilterText )
94 return;
95
96 mFilterText = filterText;
97 invalidateFilter();
98}
99
101{
102 return mLayerTreeModel;
103}
104
106{
107 mLayerTreeModel = layerTreeModel;
108 QSortFilterProxyModel::setSourceModel( layerTreeModel );
109}
110
112{
113 return mShowPrivateLayers;
114}
115
117{
118 if ( showPrivate == mShowPrivateLayers )
119 return;
120
121 mShowPrivateLayers = showPrivate;
122 invalidateFilter();
123}
124
126{
127 mFilters = filters;
128 invalidateFilter();
129}
130
131bool QgsLayerTreeFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
132{
133 QgsLayerTreeNode *node = mLayerTreeModel->index2node( mLayerTreeModel->index( sourceRow, 0, sourceParent ) );
134 return nodeShown( node );
135}
136
138{
139 return mCheckedLayers.contains( layer );
140}
141
143{
144 if ( checked )
145 {
146 mCheckedLayers << layer;
147 }
148 else
149 {
150 mCheckedLayers.removeAll( layer );
151 }
152}
153
154void QgsLayerTreeFilterProxyModel::setLayerCheckedPrivate( QgsMapLayer *layer, bool checked )
155{
156 if ( checked && isLayerChecked( layer ) )
157 return;
158 if ( !checked && !isLayerChecked( layer ) )
159 return;
160
161 QgsLayerTreeNode *node = mLayerTreeModel->rootGroup()->findLayer( layer );
162 const QModelIndex index = mapFromSource( mLayerTreeModel->node2index( node ) );
163
164 setLayerChecked( layer, checked );
165
166 emit dataChanged( index, index );
167}
168
169bool QgsLayerTreeFilterProxyModel::layerShown( QgsMapLayer *layer ) const
170{
171 Q_UNUSED( layer )
172 return true;
173}
174
176{
177 if ( !node )
178 return false;
179 if ( node->nodeType() == QgsLayerTreeNode::NodeGroup )
180 {
181 const auto constChildren = node->children();
182 for ( QgsLayerTreeNode *child : constChildren )
183 {
184 if ( nodeShown( child ) )
185 {
186 return true;
187 }
188 }
189 return false;
190 }
191 else
192 {
193 QgsMapLayer *layer = QgsLayerTree::toLayer( node )->layer();
194 if ( !layer )
195 return false;
196 if ( !mFilterText.isEmpty() && !layer->name().contains( mFilterText, Qt::CaseInsensitive ) )
197 return false;
198 if ( ! mShowPrivateLayers && layer->flags().testFlag( QgsMapLayer::LayerFlag::Private ) )
199 {
200 return false;
201 }
202 if ( !QgsMapLayerProxyModel::layerMatchesFilters( layer, mFilters ) )
203 return false;
204
205 return layerShown( layer );
206 }
207}
208
209QVariant QgsLayerTreeFilterProxyModel::data( const QModelIndex &idx, int role ) const
210{
211 if ( idx.column() == 0 )
212 {
213 if ( role == Qt::CheckStateRole )
214 {
215 QgsMapLayer *layer = mapLayer( idx );
216 if ( layer )
217 {
218 if ( isLayerChecked( layer ) )
219 {
220 return Qt::Checked;
221 }
222 else
223 {
224 return Qt::Unchecked;
225 }
226 }
227 else
228 {
229 // i.e. this is a group, analyze its children
230 bool hasChecked = false, hasUnchecked = false;
231 int n;
232 for ( n = 0; !hasChecked || !hasUnchecked; n++ )
233 {
234 const QVariant v = data( index( n, 0, idx ), role );
235 if ( !v.isValid() )
236 break;
237
238 switch ( v.toInt() )
239 {
240 case Qt::PartiallyChecked:
241 // parent of partially checked child shared state
242 return Qt::PartiallyChecked;
243
244 case Qt::Checked:
245 hasChecked = true;
246 break;
247
248 case Qt::Unchecked:
249 hasUnchecked = true;
250 break;
251 }
252 }
253
254 // unchecked leaf
255 if ( n == 0 )
256 return Qt::Unchecked;
257
258 // both
259 if ( hasChecked && hasUnchecked )
260 return Qt::PartiallyChecked;
261
262 if ( hasChecked )
263 return Qt::Checked;
264
265 Q_ASSERT( hasUnchecked );
266 return Qt::Unchecked;
267 }
268 }
269 else
270 {
271 return mLayerTreeModel->data( mapToSource( idx ), role );
272 }
273 }
274 return QVariant();
275}
276
277bool QgsLayerTreeFilterProxyModel::setData( const QModelIndex &index, const QVariant &value, int role )
278{
279 if ( index.column() == 0 )
280 {
281 if ( role == Qt::CheckStateRole )
282 {
283 int i = 0;
284 for ( i = 0; ; i++ )
285 {
286 const QModelIndex child = QgsLayerTreeFilterProxyModel::index( i, 0, index );
287 if ( !child.isValid() )
288 break;
289
290 setData( child, value, role );
291 }
292
293 if ( i == 0 )
294 {
295 QgsMapLayer *layer = mapLayer( index );
296 if ( !layer )
297 {
298 return false;
299 }
300 if ( value.toInt() == Qt::Checked )
301 setLayerCheckedPrivate( layer, true );
302 else if ( value.toInt() == Qt::Unchecked )
303 setLayerCheckedPrivate( layer, false );
304 else
305 Q_ASSERT( false ); // expected checked or unchecked
306 }
307 emit dataChanged( index, index );
308 return true;
309 }
310
311 return mLayerTreeModel->setData( mapToSource( index ), value, role );
312 }
313
314 return false;
315}
QFlags< LayerFilter > LayerFilters
Definition qgis.h:206
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
bool nodeShown(QgsLayerTreeNode *node) const
Returns true if the specified node will be shown in the model.
virtual void setLayerChecked(QgsMapLayer *layer, bool checked)
This will set if the layer is checked or not.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
void setFilters(Qgis::LayerFilters filters)
Defines the type layers (vector, raster, etc) shown in the tree If the list is empty,...
virtual int columnCount(const QModelIndex &parent) const override
QgsMapLayer * mapLayer(const QModelIndex &idx) const
Returns the map layer at a given index.
void setLayerTreeModel(QgsLayerTreeModel *layerTreeModel)
Sets the layer tree model.
virtual bool isLayerChecked(QgsMapLayer *layer) const
Returns if the layer is checked or not.
virtual void setFilterText(const QString &filterText=QString())
Sets the filter text to search for a layer in the tree.
void setCheckedLayers(const QList< QgsMapLayer * > layers)
Initialize the list of checked layers.
void setShowPrivateLayers(bool showPrivate)
Determines if private layers are shown.
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
QModelIndex parent(const QModelIndex &child) const override
virtual QVariant data(const QModelIndex &index, int role) const override
QgsLayerTreeFilterProxyModel(QObject *parent=nullptr)
Constructor.
virtual Qt::ItemFlags flags(const QModelIndex &idx) const override
bool showPrivateLayers() const
Returns if private layers are shown.
QgsLayerTreeModel * layerTreeModel() const
Rerturns the layer tree model.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
The QgsLayerTreeModel class is model implementation for Qt item views framework.
QModelIndex node2index(QgsLayerTreeNode *node) const
Returns index for a given node. If the node does not belong to the layer tree, the result is undefine...
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QgsLayerTree * rootGroup() const
Returns pointer to the root node of the layer tree. Always a non nullptr value.
QgsLayerTreeNode * index2node(const QModelIndex &index) const
Returns layer tree node for given index.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
This class is a base class for nodes in a layer tree.
@ NodeGroup
Container of other groups and layers.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool layerMatchesFilters(const QgsMapLayer *layer, const Qgis::LayerFilters &filters)
Returns if the layer matches the given filters.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
@ Private
Determines if the layer is meant to be exposed to the GUI, i.e. visible in the layer legend tree.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void readProject(const QDomDocument &document)
Emitted when a project is being read.