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