QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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
19#include "qgslayertree.h"
20#include "qgslayertreemodel.h"
21#include "qgssymbol.h"
22
23#include "moc_qgslayertreefilterproxymodel.cpp"
24
26 : QSortFilterProxyModel( parent )
27{
28 connect(
29 QgsProject::instance(), // skip-keyword-check
31 this,
32 [this] {
33 beginResetModel();
34 endResetModel();
35 }
36 );
37}
38
39void QgsLayerTreeFilterProxyModel::setCheckedLayers( const QList<QgsMapLayer *> layers )
40{
41 // do not use invalidate() since it's not the filter which changes but the data
42 beginResetModel();
43 mCheckedLayers = layers;
44 endResetModel();
45}
46
48{
49 Q_UNUSED( parent )
50 return 1;
51}
52
53Qt::ItemFlags QgsLayerTreeFilterProxyModel::flags( const QModelIndex &idx ) const
54{
55 if ( idx.column() == 0 )
56 {
57 return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
58 }
59 return Qt::NoItemFlags;
60}
61
62QModelIndex QgsLayerTreeFilterProxyModel::index( int row, int column, const QModelIndex &parent ) const
63{
64 QModelIndex newIndex = QSortFilterProxyModel::index( row, 0, parent );
65 if ( column == 0 )
66 return newIndex;
67
68 return createIndex( row, column, newIndex.internalId() );
69}
70
71QModelIndex QgsLayerTreeFilterProxyModel::parent( const QModelIndex &child ) const
72{
73 return QSortFilterProxyModel::parent( createIndex( child.row(), 0, child.internalId() ) );
74}
75
76QModelIndex QgsLayerTreeFilterProxyModel::sibling( int row, int column, const QModelIndex &idx ) const
77{
78 const QModelIndex parent = idx.parent();
79 return index( row, column, parent );
80}
81
83{
84 QgsLayerTreeNode *node = nullptr;
85 if ( idx.column() == 0 )
86 {
87 node = mLayerTreeModel->index2node( mapToSource( idx ) );
88 }
89
90 if ( !node || !QgsLayerTree::isLayer( node ) )
91 return nullptr;
92
93 return QgsLayerTree::toLayer( node )->layer();
94}
95
96void QgsLayerTreeFilterProxyModel::setFilterText( const QString &filterText )
97{
98 if ( filterText == mFilterText )
99 return;
100
101 mFilterText = filterText;
102 invalidateFilter();
103}
104
106{
107 return mLayerTreeModel;
108}
109
111{
112 mLayerTreeModel = layerTreeModel;
113 QSortFilterProxyModel::setSourceModel( layerTreeModel );
114}
115
117{
118 return mShowPrivateLayers;
119}
120
122{
123 if ( showPrivate == mShowPrivateLayers )
124 return;
125
126 mShowPrivateLayers = showPrivate;
127 invalidateFilter();
128}
129
131{
132 mFilters = filters;
133 invalidateFilter();
134}
135
136bool QgsLayerTreeFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
137{
138 QgsLayerTreeNode *node = mLayerTreeModel->index2node( mLayerTreeModel->index( sourceRow, 0, sourceParent ) );
139 return nodeShown( node );
140}
141
143{
144 return mCheckedLayers.contains( layer );
145}
146
148{
149 if ( checked )
150 {
151 mCheckedLayers << layer;
152 }
153 else
154 {
155 mCheckedLayers.removeAll( layer );
156 }
157}
158
159void QgsLayerTreeFilterProxyModel::setLayerCheckedPrivate( QgsMapLayer *layer, bool checked )
160{
161 if ( checked && isLayerChecked( layer ) )
162 return;
163 if ( !checked && !isLayerChecked( layer ) )
164 return;
165
166 QgsLayerTreeNode *node = mLayerTreeModel->rootGroup()->findLayer( layer );
167 const QModelIndex index = mapFromSource( mLayerTreeModel->node2index( node ) );
168
169 setLayerChecked( layer, checked );
170
171 emit dataChanged( index, index );
172}
173
174bool QgsLayerTreeFilterProxyModel::layerShown( QgsMapLayer *layer ) const
175{
176 Q_UNUSED( layer )
177 return true;
178}
179
181{
182 if ( !node )
183 return false;
184 if ( node->nodeType() == QgsLayerTreeNode::NodeGroup )
185 {
186 const auto constChildren = node->children();
187 for ( QgsLayerTreeNode *child : constChildren )
188 {
189 if ( nodeShown( child ) )
190 {
191 return true;
192 }
193 }
194 return false;
195 }
196 else
197 {
198 QgsMapLayer *layer = QgsLayerTree::toLayer( node )->layer();
199 if ( !layer )
200 return false;
201 if ( !mFilterText.isEmpty() && !layer->name().contains( mFilterText, Qt::CaseInsensitive ) )
202 return false;
203 if ( !mShowPrivateLayers && layer->flags().testFlag( QgsMapLayer::LayerFlag::Private ) )
204 {
205 return false;
206 }
207 if ( !QgsMapLayerProxyModel::layerMatchesFilters( layer, mFilters ) )
208 return false;
209
210 return layerShown( layer );
211 }
212}
213
214QVariant QgsLayerTreeFilterProxyModel::data( const QModelIndex &idx, int role ) const
215{
216 if ( idx.column() == 0 )
217 {
218 if ( role == Qt::CheckStateRole )
219 {
220 QgsMapLayer *layer = mapLayer( idx );
221 if ( layer )
222 {
223 if ( isLayerChecked( layer ) )
224 {
225 return Qt::Checked;
226 }
227 else
228 {
229 return Qt::Unchecked;
230 }
231 }
232 else
233 {
234 // i.e. this is a group, analyze its children
235 bool hasChecked = false, hasUnchecked = false;
236 int n;
237 for ( n = 0; !hasChecked || !hasUnchecked; n++ )
238 {
239 const QVariant v = data( index( n, 0, idx ), role );
240 if ( !v.isValid() )
241 break;
242
243 switch ( v.toInt() )
244 {
245 case Qt::PartiallyChecked:
246 // parent of partially checked child shared state
247 return Qt::PartiallyChecked;
248
249 case Qt::Checked:
250 hasChecked = true;
251 break;
252
253 case Qt::Unchecked:
254 hasUnchecked = true;
255 break;
256 }
257 }
258
259 // unchecked leaf
260 if ( n == 0 )
261 return Qt::Unchecked;
262
263 // both
264 if ( hasChecked && hasUnchecked )
265 return Qt::PartiallyChecked;
266
267 if ( hasChecked )
268 return Qt::Checked;
269
270 Q_ASSERT( hasUnchecked );
271 return Qt::Unchecked;
272 }
273 }
274 else
275 {
276 return mLayerTreeModel->data( mapToSource( idx ), role );
277 }
278 }
279 return QVariant();
280}
281
282bool QgsLayerTreeFilterProxyModel::setData( const QModelIndex &index, const QVariant &value, int role )
283{
284 if ( index.column() == 0 )
285 {
286 if ( role == Qt::CheckStateRole )
287 {
288 int i = 0;
289 for ( i = 0;; i++ )
290 {
291 const QModelIndex child = QgsLayerTreeFilterProxyModel::index( i, 0, index );
292 if ( !child.isValid() )
293 break;
294
295 setData( child, value, role );
296 }
297
298 if ( i == 0 )
299 {
300 QgsMapLayer *layer = mapLayer( index );
301 if ( !layer )
302 {
303 return false;
304 }
305 if ( value.toInt() == Qt::Checked )
306 setLayerCheckedPrivate( layer, true );
307 else if ( value.toInt() == Qt::Unchecked )
308 setLayerCheckedPrivate( layer, false );
309 else
310 Q_ASSERT( false ); // expected checked or unchecked
311 }
312 emit dataChanged( index, index );
313 return true;
314 }
315
316 return mLayerTreeModel->setData( mapToSource( index ), value, role );
317 }
318
319 return false;
320}
QFlags< LayerFilter > LayerFilters
Definition qgis.h:243
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
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,...
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
QVariant data(const QModelIndex &index, int role) const override
QgsLayerTreeFilterProxyModel(QObject *parent=nullptr)
Constructor.
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.
A model representing the layer tree, including layers and groups of layers.
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...
QgsLayerTree * rootGroup() const
Returns pointer to the root node of the layer tree. Always a non nullptr value.
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:83
QString name
Definition qgsmaplayer.h:87
QgsMapLayer::LayerFlags flags
Definition qgsmaplayer.h:99
@ 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.