QGIS API Documentation 3.29.0-Master (006c3c0232)
qgsbrowserproxymodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsbrowserproxymodel.cpp
3 ---------------------
4 begin : October 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
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
17#include "qgsbrowsermodel.h"
18#include "qgslayeritem.h"
20
21#include <QRegularExpression>
22
24 : QSortFilterProxyModel( parent )
25{
26 setDynamicSortFilter( true );
27 setSortRole( QgsBrowserModel::SortRole );
28 setSortCaseSensitivity( Qt::CaseInsensitive );
29 sort( 0 );
30}
31
33{
34 mModel = model;
35 setSourceModel( model );
36}
37
38QgsDataItem *QgsBrowserProxyModel::dataItem( const QModelIndex &index ) const
39{
40 const QModelIndex sourceIndex = mapToSource( index );
41 return mModel ? mModel->dataItem( sourceIndex ) : nullptr;
42}
43
45{
46 if ( mPatternSyntax == syntax )
47 return;
48 mPatternSyntax = syntax;
49 updateFilter();
50}
51
53{
54 return mPatternSyntax;
55}
56
57void QgsBrowserProxyModel::setFilterString( const QString &filter )
58{
59 if ( mFilter == filter )
60 return;
61 mFilter = filter;
62 updateFilter();
63}
64
66{
67 return mFilter;
68}
69
70void QgsBrowserProxyModel::setFilterCaseSensitivity( Qt::CaseSensitivity sensitivity )
71{
72 mCaseSensitivity = sensitivity;
73 updateFilter();
74}
75
76Qt::CaseSensitivity QgsBrowserProxyModel::caseSensitivity() const
77{
78 return mCaseSensitivity;
79}
80
81void QgsBrowserProxyModel::updateFilter()
82{
83 mREList.clear();
84 switch ( mPatternSyntax )
85 {
86 case Normal:
87 {
88 const QStringList filterParts = mFilter.split( '|' );
89 for ( const QString &f : filterParts )
90 {
91 const QRegularExpression rx( QRegularExpression::wildcardToRegularExpression( QStringLiteral( "*%1*" ).arg( f.trimmed() ) ),
92 mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
93 mREList.append( rx );
94 }
95 break;
96 }
97 case Wildcards:
98 {
99 const QStringList filterParts = mFilter.split( '|' );
100 for ( const QString &f : filterParts )
101 {
102 const QRegularExpression rx( QRegularExpression::wildcardToRegularExpression( f.trimmed() ),
103 mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
104 mREList.append( rx );
105 }
106 break;
107 }
109 {
110 const QRegularExpression rx( mFilter.trimmed(), mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
111 mREList.append( rx );
112 break;
113 }
114 }
115 invalidateFilter();
116}
117
118bool QgsBrowserProxyModel::filterAcceptsString( const QString &value ) const
119{
120 for ( const QRegularExpression &rx : mREList )
121 {
122 if ( rx.match( value ).hasMatch() )
123 return true;
124 }
125
126 return false;
127}
128
129bool QgsBrowserProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
130{
131 if ( ( mFilter.isEmpty() && !mFilterByLayerType && mHiddenDataItemsKeys.empty() && mShownDataItemsKeys.empty() ) || !mModel )
132 return true;
133
134 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
135 if ( !filterAcceptsProviderKey( sourceIndex ) || !filterRootAcceptsProviderKey( sourceIndex ) )
136 return false;
137
138 if ( ! mShowLayers )
139 {
140 QgsDataItem *item = mModel->dataItem( sourceIndex );
141 if ( qobject_cast< QgsLayerItem * >( item ) )
142 {
143 return false;
144 }
145 }
146
147 return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
148}
149
151{
152 return mShowLayers;
153}
154
156{
157 mShowLayers = showLayers;
158}
159
161{
162 return mLayerType;
163}
164
166{
167 mLayerType = type;
168 invalidateFilter();
169}
170
171void QgsBrowserProxyModel::setFilterByLayerType( bool filterByLayerType )
172{
173 mFilterByLayerType = filterByLayerType;
174 invalidateFilter();
175}
176
177bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
178{
179 if ( !mModel )
180 return true;
181
182 if ( mFilterByLayerType )
183 return false;
184
185 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
186 if ( !sourceParentIndex.isValid() )
187 return false;
188 if ( filterAcceptsItem( sourceParentIndex ) )
189 return true;
190
191 return filterAcceptsAncestor( sourceParentIndex );
192}
193
194bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
195{
196 if ( !mModel )
197 return true;
198
199 for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
200 {
201 const QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
202 if ( filterAcceptsItem( sourceChildIndex ) )
203 return true;
204 if ( filterAcceptsDescendant( sourceChildIndex ) )
205 return true;
206 }
207 return false;
208}
209
210bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
211{
212 if ( !mModel )
213 return true;
214
215 if ( mFilterByLayerType )
216 {
217 QgsDataItem *item = mModel->dataItem( sourceIndex );
218 if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
219 {
220 if ( layerItem->mapLayerType() != mLayerType )
221 return false;
222 }
223 else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
224 return false;
225 }
226
227 if ( !mFilter.isEmpty() )
228 {
229 //accept item if either displayed text or comment role matches string
230 const QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
231 return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
232 || ( !comment.isEmpty() && filterAcceptsString( comment ) )
233 || mModel->data( sourceIndex, QgsBrowserModel::ItemDataRole::LayerMetadataRole ).value< QgsLayerMetadata >( ).matches( mREList ) );
234 }
235
236 return true;
237}
238
239bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
240{
241 if ( !mModel )
242 return true;
243
244 const QString providerKey = mModel->data( sourceIndex, QgsBrowserModel::ProviderKeyRole ).toString();
245 if ( providerKey.isEmpty() )
246 return true;
247
248 return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
249}
250
251bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
252{
253 if ( !mModel )
254 return true;
255
256 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
257 if ( !sourceParentIndex.isValid() )
258 {
259 return filterAcceptsProviderKey( sourceIndex );
260 }
261
262 return filterRootAcceptsProviderKey( sourceParentIndex );
263}
264
266{
267 mHiddenDataItemsKeys = filter;
268 invalidateFilter();
269}
270
272{
273 mShownDataItemsKeys = filter;
274 invalidateFilter();
275}
276
277
278bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
279{
280 const bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
281 if ( isFertile && parent.isValid() )
282 {
283 QgsDataItem *item = dataItem( parent );
284 if ( ! mShowLayers )
285 {
286 return ! item->layerCollection();
287 }
288 // Hide everything below layers if filter is set
289 else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) )
290 {
291 return false;
292 }
293 }
294 return isFertile;
295}
A model for showing available data sources and other items in a structured tree.
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex parent(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
@ CommentRole
Item comment.
@ ProviderKeyRole
Data item provider key that created the item, see QgsDataItem::providerKey()
@ SortRole
Custom sort role, see QgsDataItem::sortKey()
void setShowLayers(bool showLayers)
Sets show layers to showLayers.
FilterSyntax
Filter syntax options.
@ RegularExpression
Regular expression filtering.
@ Wildcards
Wildcard filtering.
@ Normal
Standard string filtering.
void setShownDataItemProviderKeyFilter(const QStringList &shownItemsFilter)
Sets a filter to show data items based on QgsDataItem::providerKey() associated with the item.
void setHiddenDataItemProviderKeyFilter(const QStringList &hiddenItemsFilter)
Sets a filter to hide data items based on QgsDataItem::providerKey() associated with the item.
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
QString filterString() const
Returns the filter string used when filtering items in the model.
QgsBrowserProxyModel(QObject *parent=nullptr)
Constructor for QgsBrowserProxyModel, with the specified parent object.
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
QgsMapLayerType layerType() const
Returns the layer type to filter the model by.
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
Qt::CaseSensitivity caseSensitivity() const
Returns whether item filtering is case sensitive.
bool filterByLayerType() const
Returns true if the model is filtered by map layer type.
bool showLayers() const
Returns true if layers must be shown, this flag is TRUE by default.
FilterSyntax filterSyntax() const
Returns the filter syntax.
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
QgsBrowserModel * mModel
Reference to associated browser model.
Base class for all items in the model.
Definition: qgsdataitem.h:46
virtual bool layerCollection() const
Returns true if the data item is a collection of layers The default implementation returns false,...
Item that represents a layer that can be opened with one of the providers.
Definition: qgslayeritem.h:31
A structured metadata store for a map layer.
bool matches(const QVector< QRegularExpression > &searchReList) const
Returns true if the metadata identifier, title, abstract, keywords or categories matches any regular ...
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47