QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
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
18#include "qgsbrowsermodel.h"
20#include "qgslayeritem.h"
21
22#include <QRegularExpression>
23#include <QString>
24
25#include "moc_qgsbrowserproxymodel.cpp"
26
27using namespace Qt::StringLiterals;
28
30 : QSortFilterProxyModel( parent )
31{
32 setDynamicSortFilter( true );
33 setSortRole( static_cast< int >( QgsBrowserModel::CustomRole::Sort ) );
34 setSortCaseSensitivity( Qt::CaseInsensitive );
35 sort( 0 );
36}
37
39{
40 mModel = model;
41 setSourceModel( model );
42}
43
44QgsDataItem *QgsBrowserProxyModel::dataItem( const QModelIndex &index ) const
45{
46 const QModelIndex sourceIndex = mapToSource( index );
47 return mModel ? mModel->dataItem( sourceIndex ) : nullptr;
48}
49
51{
52 if ( mPatternSyntax == syntax )
53 return;
54 mPatternSyntax = syntax;
55 updateFilter();
56}
57
62
63void QgsBrowserProxyModel::setFilterString( const QString &filter )
64{
65 if ( mFilter == filter )
66 return;
67 mFilter = filter;
68 updateFilter();
69}
70
72{
73 return mFilter;
74}
75
76void QgsBrowserProxyModel::setFilterCaseSensitivity( Qt::CaseSensitivity sensitivity )
77{
78 mCaseSensitivity = sensitivity;
79 updateFilter();
80}
81
82Qt::CaseSensitivity QgsBrowserProxyModel::caseSensitivity() const
83{
84 return mCaseSensitivity;
85}
86
87void QgsBrowserProxyModel::updateFilter()
88{
89 mREList.clear();
90 switch ( mPatternSyntax )
91 {
92 case Normal:
93 {
94 const QStringList filterParts = mFilter.split( '|' );
95 for ( const QString &f : filterParts )
96 {
97 const QRegularExpression rx( QRegularExpression::wildcardToRegularExpression( u"*%1*"_s.arg( f.trimmed() ) ),
98 mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
99 mREList.append( rx );
100 }
101 break;
102 }
103 case Wildcards:
104 {
105 const QStringList filterParts = mFilter.split( '|' );
106 for ( const QString &f : filterParts )
107 {
108 const QRegularExpression rx( QRegularExpression::wildcardToRegularExpression( f.trimmed() ),
109 mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
110 mREList.append( rx );
111 }
112 break;
113 }
115 {
116 const QRegularExpression rx( mFilter.trimmed(), mCaseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption );
117 mREList.append( rx );
118 break;
119 }
120 }
121 invalidateFilter();
122}
123
124bool QgsBrowserProxyModel::filterAcceptsString( const QString &value ) const
125{
126 for ( const QRegularExpression &rx : mREList )
127 {
128 if ( rx.match( value ).hasMatch() )
129 return true;
130 }
131
132 return false;
133}
134
135bool QgsBrowserProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
136{
137 if ( ( mFilter.isEmpty() && !mFilterByLayerType && mHiddenDataItemsKeys.empty() && mShownDataItemsKeys.empty() ) || !mModel )
138 return true;
139
140 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
141 if ( !filterAcceptsProviderKey( sourceIndex ) || !filterRootAcceptsProviderKey( sourceIndex ) )
142 return false;
143
144 if ( ! mShowLayers )
145 {
146 QgsDataItem *item = mModel->dataItem( sourceIndex );
147 if ( qobject_cast< QgsLayerItem * >( item ) )
148 {
149 return false;
150 }
151 }
152
153 return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
154}
155
157{
158 return mShowLayers;
159}
160
162{
163 mShowLayers = showLayers;
164}
165
167{
168 return mLayerType;
169}
170
172{
173 mLayerType = type;
174 invalidateFilter();
175}
176
178{
179 mFilterByLayerType = filterByLayerType;
180 invalidateFilter();
181}
182
183bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
184{
185 if ( !mModel )
186 return true;
187
188 if ( mFilterByLayerType )
189 return false;
190
191 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
192 if ( !sourceParentIndex.isValid() )
193 return false;
194 if ( filterAcceptsItem( sourceParentIndex ) )
195 return true;
196
197 return filterAcceptsAncestor( sourceParentIndex );
198}
199
200bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
201{
202 if ( !mModel )
203 return true;
204
205 for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
206 {
207 const QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
208 if ( filterAcceptsItem( sourceChildIndex ) )
209 return true;
210 if ( filterAcceptsDescendant( sourceChildIndex ) )
211 return true;
212 }
213 return false;
214}
215
216bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
217{
218 if ( !mModel )
219 return true;
220
221 if ( mFilterByLayerType )
222 {
223 QgsDataItem *item = mModel->dataItem( sourceIndex );
224 if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
225 {
226 if ( layerItem->mapLayerType() != mLayerType )
227 return false;
228 }
229 else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
230 return false;
231 }
232
233 if ( !mFilter.isEmpty() )
234 {
235 //accept item if either displayed text or comment role matches string
236 const QString comment = mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::Comment ) ).toString();
237 return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
238 || ( !comment.isEmpty() && filterAcceptsString( comment ) )
239 || mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::LayerMetadata ) ).value< QgsLayerMetadata >( ).matches( mREList ) );
240 }
241
242 return true;
243}
244
245bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
246{
247 if ( !mModel )
248 return true;
249
250 const QString providerKey = mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::ProviderKey ) ).toString();
251 if ( providerKey.isEmpty() )
252 return true;
253
254 return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
255}
256
257bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
258{
259 if ( !mModel )
260 return true;
261
262 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
263 if ( !sourceParentIndex.isValid() )
264 {
265 return filterAcceptsProviderKey( sourceIndex );
266 }
267
268 return filterRootAcceptsProviderKey( sourceParentIndex );
269}
270
272{
273 mHiddenDataItemsKeys = filter;
274 invalidateFilter();
275}
276
278{
279 mShownDataItemsKeys = filter;
280 invalidateFilter();
281}
282
283
284bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
285{
286 const bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
287 if ( isFertile && parent.isValid() )
288 {
289 QgsDataItem *item = dataItem( parent );
290 if ( item && !mShowLayers )
291 {
292 return !item->layerCollection();
293 }
294 // Hide everything below layers if filter is set
295 else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) )
296 {
297 return false;
298 }
299 }
300 return isFertile;
301}
LayerType
Types of layers that can be added to a map.
Definition qgis.h:193
A model for showing available data sources and other items in a structured tree.
QModelIndex parent(const QModelIndex &index) const override
@ Sort
Custom sort role, see QgsDataItem::sortKey().
@ ProviderKey
Data item provider key that created the item, see QgsDataItem::providerKey().
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 setLayerType(Qgis::LayerType type)
Sets the layer type to filter the model by.
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.
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.
Qgis::LayerType layerType() const
Returns the layer type to filter the model by.
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:50
virtual bool layerCollection() const
Returns true if the data item is a collection of layers The default implementation returns false,...