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