QGIS API Documentation 4.1.0-Master (3b8ef1f72a3)
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
98 rx( QRegularExpression::wildcardToRegularExpression( u"*%1*"_s.arg( f.trimmed() ) ), 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
109 rx( QRegularExpression::wildcardToRegularExpression( f.trimmed() ), 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 ( !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 QgsDataItem *item = mModel->dataItem( sourceIndex );
145 if ( !mShowLayers )
146 {
147 if ( qobject_cast< QgsLayerItem * >( item ) )
148 {
149 return false;
150 }
151 }
152 else if ( item && !mFilterByLayerType )
153 {
155 return false;
156 }
157
158 return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
159}
160
162{
163 return mShowLayers;
164}
165
167{
168 mShowLayers = showLayers;
169}
170
172{
173 return mLayerType;
174}
175
177{
178 mLayerType = type;
179 invalidateFilter();
180}
181
183{
184 mFilterByLayerType = filterByLayerType;
185 invalidateFilter();
186}
187
188bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
189{
190 if ( !mModel )
191 return true;
192
193 if ( mFilterByLayerType )
194 return false;
195
196 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
197 if ( !sourceParentIndex.isValid() )
198 return false;
199 if ( filterAcceptsItem( sourceParentIndex ) )
200 return true;
201
202 return filterAcceptsAncestor( sourceParentIndex );
203}
204
205bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
206{
207 if ( !mModel )
208 return true;
209
210 for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
211 {
212 const QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
213 if ( filterAcceptsItem( sourceChildIndex ) )
214 return true;
215 if ( filterAcceptsDescendant( sourceChildIndex ) )
216 return true;
217 }
218 return false;
219}
220
221bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
222{
223 if ( !mModel )
224 return true;
225
226 QgsDataItem *item = mModel->dataItem( sourceIndex );
227 if ( mFilterByLayerType )
228 {
229 if ( !item )
230 return false;
231 if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
232 {
233 if ( layerItem->mapLayerType() != mLayerType )
234 return false;
235 }
236 else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
237 return false;
238 }
240 {
241 return false;
242 }
243
244 if ( !mFilter.isEmpty() )
245 {
246 //accept item if either displayed text or comment role matches string
247 const QString comment = mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::Comment ) ).toString();
248 return (
249 filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
250 || ( !comment.isEmpty() && filterAcceptsString( comment ) )
251 || mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::LayerMetadata ) ).value< QgsLayerMetadata >().matches( mREList )
252 );
253 }
254
255 return true;
256}
257
258bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
259{
260 if ( !mModel )
261 return true;
262
263 const QString providerKey = mModel->data( sourceIndex, static_cast< int >( QgsBrowserModel::CustomRole::ProviderKey ) ).toString();
264 if ( providerKey.isEmpty() )
265 return true;
266
267 return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
268}
269
270bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
271{
272 if ( !mModel )
273 return true;
274
275 const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
276 if ( !sourceParentIndex.isValid() )
277 {
278 return filterAcceptsProviderKey( sourceIndex );
279 }
280
281 return filterRootAcceptsProviderKey( sourceParentIndex );
282}
283
285{
286 mHiddenDataItemsKeys = filter;
287 invalidateFilter();
288}
289
291{
292 mShownDataItemsKeys = filter;
293 invalidateFilter();
294}
295
296
297bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
298{
299 const bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
300 if ( isFertile && parent.isValid() )
301 {
302 QgsDataItem *item = dataItem( parent );
303 if ( item && !mShowLayers )
304 {
305 return !item->layerCollection();
306 }
307 // Hide everything below layers if filter is set
308 else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) )
309 {
310 return false;
311 }
312 }
313 return isFertile;
314}
LayerType
Types of layers that can be added to a map.
Definition qgis.h:206
@ HideWhenNotFilteringByLayerType
Item should be hidden from the view when no layer type filter is in place.
Definition qgis.h:1022
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,...
virtual Qgis::BrowserItemFilterFlags filterFlags() const
Returns the filter flags for the data item.