QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
16 #include "qgsbrowserproxymodel.h"
17 #include "qgsbrowsermodel.h"
18 #include "qgslayeritem.h"
19 #include "qgsdatacollectionitem.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 
38 QgsDataItem *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 
57 void 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 
70 void QgsBrowserProxyModel::setFilterCaseSensitivity( Qt::CaseSensitivity sensitivity )
71 {
72  mCaseSensitivity = sensitivity;
73  updateFilter();
74 }
75 
76 Qt::CaseSensitivity QgsBrowserProxyModel::caseSensitivity() const
77 {
78  return mCaseSensitivity;
79 }
80 
81 void 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  }
108  case RegularExpression:
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 
118 bool 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 
129 bool 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 
155 void QgsBrowserProxyModel::setShowLayers( bool showLayers )
156 {
157  mShowLayers = showLayers;
158 }
159 
161 {
162  return mLayerType;
163 }
164 
166 {
167  mLayerType = type;
168  invalidateFilter();
169 }
170 
171 void QgsBrowserProxyModel::setFilterByLayerType( bool filterByLayerType )
172 {
173  mFilterByLayerType = filterByLayerType;
174  invalidateFilter();
175 }
176 
177 bool 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 
194 bool 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 
210 bool 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  }
234 
235  return true;
236 }
237 
238 bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
239 {
240  if ( !mModel )
241  return true;
242 
243  const QString providerKey = mModel->data( sourceIndex, QgsBrowserModel::ProviderKeyRole ).toString();
244  if ( providerKey.isEmpty() )
245  return true;
246 
247  return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
248 }
249 
250 bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
251 {
252  if ( !mModel )
253  return true;
254 
255  const QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
256  if ( !sourceParentIndex.isValid() )
257  {
258  return filterAcceptsProviderKey( sourceIndex );
259  }
260 
261  return filterRootAcceptsProviderKey( sourceParentIndex );
262 }
263 
265 {
266  mHiddenDataItemsKeys = filter;
267  invalidateFilter();
268 }
269 
271 {
272  mShownDataItemsKeys = filter;
273  invalidateFilter();
274 }
275 
276 
277 bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
278 {
279  const bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
280  if ( isFertile && parent.isValid() )
281  {
282  QgsDataItem *item = dataItem( parent );
283  if ( ! mShowLayers )
284  {
285  return ! item->layerCollection();
286  }
287  // Hide everything below layers if filter is set
288  else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) )
289  {
290  return false;
291  }
292  }
293  return isFertile;
294 }
QgsBrowserProxyModel::setShowLayers
void setShowLayers(bool showLayers)
Sets show layers to showLayers.
Definition: qgsbrowserproxymodel.cpp:155
QgsBrowserProxyModel::filterSyntax
FilterSyntax filterSyntax() const
Returns the filter syntax.
Definition: qgsbrowserproxymodel.cpp:52
QgsBrowserProxyModel::caseSensitivity
Qt::CaseSensitivity caseSensitivity() const
Returns whether item filtering is case sensitive.
Definition: qgsbrowserproxymodel.cpp:76
QgsBrowserModel::parent
QModelIndex parent(const QModelIndex &index) const override
Definition: qgsbrowsermodel.cpp:556
QgsBrowserModel::ProviderKeyRole
@ ProviderKeyRole
Data item provider key that created the item, see QgsDataItem::providerKey()
Definition: qgsbrowsermodel.h:74
QgsBrowserProxyModel::showLayers
bool showLayers() const
Returns true if layers must be shown, this flag is TRUE by default.
Definition: qgsbrowserproxymodel.cpp:150
QgsMapLayerType
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:46
QgsBrowserProxyModel::QgsBrowserProxyModel
QgsBrowserProxyModel(QObject *parent=nullptr)
Constructor for QgsBrowserProxyModel, with the specified parent object.
Definition: qgsbrowserproxymodel.cpp:23
QgsBrowserProxyModel::hasChildren
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowserproxymodel.cpp:277
QgsBrowserModel::SortRole
@ SortRole
Custom sort role, see QgsDataItem::sortKey()
Definition: qgsbrowsermodel.h:73
QgsDataItem::layerCollection
virtual bool layerCollection() const
Returns true if the data item is a collection of layers The default implementation returns false,...
Definition: qgsdataitem.cpp:402
QgsBrowserModel::CommentRole
@ CommentRole
Item comment.
Definition: qgsbrowsermodel.h:72
QgsBrowserProxyModel::filterAcceptsRow
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Definition: qgsbrowserproxymodel.cpp:129
QgsBrowserProxyModel::setBrowserModel
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
Definition: qgsbrowserproxymodel.cpp:32
QgsBrowserProxyModel::mModel
QgsBrowserModel * mModel
Reference to associated browser model.
Definition: qgsbrowserproxymodel.h:206
QgsBrowserProxyModel::setFilterCaseSensitivity
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
Definition: qgsbrowserproxymodel.cpp:70
qgslayeritem.h
QgsBrowserProxyModel::setFilterByLayerType
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.
Definition: qgsbrowserproxymodel.cpp:171
QgsBrowserProxyModel::RegularExpression
@ RegularExpression
Regular expression filtering.
Definition: qgsbrowserproxymodel.h:42
QgsBrowserModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: qgsbrowsermodel.cpp:289
QgsBrowserProxyModel::filterString
QString filterString() const
Returns the filter string used when filtering items in the model.
Definition: qgsbrowserproxymodel.cpp:65
QgsBrowserProxyModel::Wildcards
@ Wildcards
Wildcard filtering.
Definition: qgsbrowserproxymodel.h:41
QgsBrowserProxyModel::filterByLayerType
bool filterByLayerType() const
Returns true if the model is filtered by map layer type.
Definition: qgsbrowserproxymodel.h:118
QgsBrowserProxyModel::layerType
QgsMapLayerType layerType() const
Returns the layer type to filter the model by.
Definition: qgsbrowserproxymodel.cpp:160
QgsBrowserProxyModel::setHiddenDataItemProviderKeyFilter
void setHiddenDataItemProviderKeyFilter(const QStringList &hiddenItemsFilter)
Sets a filter to hide data items based on QgsDataItem::providerKey() associated with the item.
Definition: qgsbrowserproxymodel.cpp:264
QgsBrowserProxyModel::setShownDataItemProviderKeyFilter
void setShownDataItemProviderKeyFilter(const QStringList &shownItemsFilter)
Sets a filter to show data items based on QgsDataItem::providerKey() associated with the item.
Definition: qgsbrowserproxymodel.cpp:270
QgsBrowserProxyModel::setFilterSyntax
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
Definition: qgsbrowserproxymodel.cpp:44
QgsBrowserProxyModel::Normal
@ Normal
Standard string filtering.
Definition: qgsbrowserproxymodel.h:40
qgsbrowsermodel.h
QgsBrowserModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:378
QgsBrowserProxyModel::dataItem
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index.
Definition: qgsbrowserproxymodel.cpp:38
QgsBrowserModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:545
qgsbrowserproxymodel.h
qgsdatacollectionitem.h
QgsLayerItem
Item that represents a layer that can be opened with one of the providers.
Definition: qgslayeritem.h:29
QgsDataItem
Base class for all items in the model.
Definition: qgsdataitem.h:45
QgsBrowserModel::dataItem
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
Definition: qgsbrowsermodel.cpp:695
QgsBrowserProxyModel::FilterSyntax
FilterSyntax
Filter syntax options.
Definition: qgsbrowserproxymodel.h:38
QgsBrowserProxyModel::setLayerType
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
Definition: qgsbrowserproxymodel.cpp:165
QgsBrowserProxyModel::setFilterString
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
Definition: qgsbrowserproxymodel.cpp:57
QgsBrowserModel
A model for showing available data sources and other items in a structured tree.
Definition: qgsbrowsermodel.h:52