QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
22  : QSortFilterProxyModel( parent )
23 {
24  setDynamicSortFilter( true );
25  setSortRole( QgsBrowserModel::SortRole );
26  setSortCaseSensitivity( Qt::CaseInsensitive );
27  sort( 0 );
28 }
29 
31 {
32  mModel = model;
33  setSourceModel( model );
34 }
35 
36 QgsDataItem *QgsBrowserProxyModel::dataItem( const QModelIndex &index ) const
37 {
38  const QModelIndex sourceIndex = mapToSource( index );
39  return mModel ? mModel->dataItem( sourceIndex ) : nullptr;
40 }
41 
43 {
44  if ( mPatternSyntax == syntax )
45  return;
46  mPatternSyntax = syntax;
47  updateFilter();
48 }
49 
51 {
52  return mPatternSyntax;
53 }
54 
55 void QgsBrowserProxyModel::setFilterString( const QString &filter )
56 {
57  if ( mFilter == filter )
58  return;
59  mFilter = filter;
60  updateFilter();
61 }
62 
64 {
65  return mFilter;
66 }
67 
68 void QgsBrowserProxyModel::setFilterCaseSensitivity( Qt::CaseSensitivity sensitivity )
69 {
70  mCaseSensitivity = sensitivity;
71  updateFilter();
72 }
73 
74 Qt::CaseSensitivity QgsBrowserProxyModel::caseSensitivity() const
75 {
76  return mCaseSensitivity;
77 }
78 
79 void QgsBrowserProxyModel::updateFilter()
80 {
81  mREList.clear();
82  switch ( mPatternSyntax )
83  {
84  case Normal:
85  {
86  const QStringList filterParts = mFilter.split( '|' );
87  for ( const QString &f : filterParts )
88  {
89  QRegExp rx( QStringLiteral( "*%1*" ).arg( f.trimmed() ) );
90  rx.setPatternSyntax( QRegExp::Wildcard );
91  rx.setCaseSensitivity( mCaseSensitivity );
92  mREList.append( rx );
93  }
94  break;
95  }
96  case Wildcards:
97  {
98  const QStringList filterParts = mFilter.split( '|' );
99  for ( const QString &f : filterParts )
100  {
101  QRegExp rx( f.trimmed() );
102  rx.setPatternSyntax( QRegExp::Wildcard );
103  rx.setCaseSensitivity( mCaseSensitivity );
104  mREList.append( rx );
105  }
106  break;
107  }
108  case RegularExpression:
109  {
110  QRegExp rx( mFilter.trimmed() );
111  rx.setPatternSyntax( QRegExp::RegExp );
112  rx.setCaseSensitivity( mCaseSensitivity );
113  mREList.append( rx );
114  break;
115  }
116  }
117  invalidateFilter();
118 }
119 
120 bool QgsBrowserProxyModel::filterAcceptsString( const QString &value ) const
121 {
122  switch ( mPatternSyntax )
123  {
124  case Normal:
125  case Wildcards:
126  {
127  for ( const QRegExp &rx : mREList )
128  {
129  if ( rx.exactMatch( value ) )
130  return true;
131  }
132  break;
133  }
134 
135  case RegularExpression:
136  {
137  for ( const QRegExp &rx : mREList )
138  {
139  if ( rx.indexIn( value ) != -1 )
140  return true;
141  }
142  break;
143  }
144  }
145 
146  return false;
147 }
148 
149 bool QgsBrowserProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
150 {
151  if ( ( mFilter.isEmpty() && !mFilterByLayerType && mHiddenDataItemsKeys.empty() && mShownDataItemsKeys.empty() ) || !mModel )
152  return true;
153 
154  QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
155  if ( !filterAcceptsProviderKey( sourceIndex ) || !filterRootAcceptsProviderKey( sourceIndex ) )
156  return false;
157 
158  if ( ! mShowLayers )
159  {
160  QgsDataItem *item = mModel->dataItem( sourceIndex );
161  if ( qobject_cast< QgsLayerItem * >( item ) )
162  {
163  return false;
164  }
165  }
166 
167  return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
168 }
169 
171 {
172  return mShowLayers;
173 }
174 
175 void QgsBrowserProxyModel::setShowLayers( bool showLayers )
176 {
177  mShowLayers = showLayers;
178 }
179 
181 {
182  return mLayerType;
183 }
184 
186 {
187  mLayerType = type;
188  invalidateFilter();
189 }
190 
191 void QgsBrowserProxyModel::setFilterByLayerType( bool filterByLayerType )
192 {
193  mFilterByLayerType = filterByLayerType;
194  invalidateFilter();
195 }
196 
197 bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
198 {
199  if ( !mModel )
200  return true;
201 
202  if ( mFilterByLayerType )
203  return false;
204 
205  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
206  if ( !sourceParentIndex.isValid() )
207  return false;
208  if ( filterAcceptsItem( sourceParentIndex ) )
209  return true;
210 
211  return filterAcceptsAncestor( sourceParentIndex );
212 }
213 
214 bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
215 {
216  if ( !mModel )
217  return true;
218 
219  for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
220  {
221  QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
222  if ( filterAcceptsItem( sourceChildIndex ) )
223  return true;
224  if ( filterAcceptsDescendant( sourceChildIndex ) )
225  return true;
226  }
227  return false;
228 }
229 
230 bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
231 {
232  if ( !mModel )
233  return true;
234 
235  if ( mFilterByLayerType )
236  {
237  QgsDataItem *item = mModel->dataItem( sourceIndex );
238  if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
239  {
240  if ( layerItem->mapLayerType() != mLayerType )
241  return false;
242  }
243  else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
244  return false;
245  }
246 
247  if ( !mFilter.isEmpty() )
248  {
249  //accept item if either displayed text or comment role matches string
250  QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
251  return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
252  || ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
253  }
254 
255  return true;
256 }
257 
258 bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
259 {
260  if ( !mModel )
261  return true;
262 
263  const QString providerKey = mModel->data( sourceIndex, QgsBrowserModel::ProviderKeyRole ).toString();
264  if ( providerKey.isEmpty() )
265  return true;
266 
267  return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
268 }
269 
270 bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
271 {
272  if ( !mModel )
273  return true;
274 
275  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 
297 bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
298 {
299  bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
300  if ( isFertile && parent.isValid() )
301  {
302  QgsDataItem *item = dataItem( parent );
303  if ( ! 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 }
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
@ CommentRole
Item comment.
@ ProviderKeyRole
Data item provider key that created the item, see QgsDataItem::providerKey()
@ SortRole
Custom sort role, see QgsDataItem::sortKey()
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 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.
QgsMapLayerType layerType() const
Returns the layer type to filter the model by.
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
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.
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.
Definition: qgslayeritem.h:30
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:46