QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 
20  : QSortFilterProxyModel( parent )
21 {
22  setDynamicSortFilter( true );
23  setSortRole( QgsBrowserModel::SortRole );
24  setSortCaseSensitivity( Qt::CaseInsensitive );
25  sort( 0 );
26 }
27 
29 {
30  mModel = model;
31  setSourceModel( model );
32 }
33 
34 QgsDataItem *QgsBrowserProxyModel::dataItem( const QModelIndex &index ) const
35 {
36  const QModelIndex sourceIndex = mapToSource( index );
37  return mModel ? mModel->dataItem( sourceIndex ) : nullptr;
38 }
39 
41 {
42  if ( mPatternSyntax == syntax )
43  return;
44  mPatternSyntax = syntax;
45  updateFilter();
46 }
47 
49 {
50  return mPatternSyntax;
51 }
52 
53 void QgsBrowserProxyModel::setFilterString( const QString &filter )
54 {
55  if ( mFilter == filter )
56  return;
57  mFilter = filter;
58  updateFilter();
59 }
60 
62 {
63  return mFilter;
64 }
65 
66 void QgsBrowserProxyModel::setFilterCaseSensitivity( Qt::CaseSensitivity sensitivity )
67 {
68  mCaseSensitivity = sensitivity;
69  updateFilter();
70 }
71 
72 Qt::CaseSensitivity QgsBrowserProxyModel::caseSensitivity() const
73 {
74  return mCaseSensitivity;
75 }
76 
77 void QgsBrowserProxyModel::updateFilter()
78 {
79  mREList.clear();
80  switch ( mPatternSyntax )
81  {
82  case Normal:
83  {
84  const QStringList filterParts = mFilter.split( '|' );
85  for ( const QString &f : filterParts )
86  {
87  QRegExp rx( QStringLiteral( "*%1*" ).arg( f.trimmed() ) );
88  rx.setPatternSyntax( QRegExp::Wildcard );
89  rx.setCaseSensitivity( mCaseSensitivity );
90  mREList.append( rx );
91  }
92  break;
93  }
94  case Wildcards:
95  {
96  const QStringList filterParts = mFilter.split( '|' );
97  for ( const QString &f : filterParts )
98  {
99  QRegExp rx( f.trimmed() );
100  rx.setPatternSyntax( QRegExp::Wildcard );
101  rx.setCaseSensitivity( mCaseSensitivity );
102  mREList.append( rx );
103  }
104  break;
105  }
106  case RegularExpression:
107  {
108  QRegExp rx( mFilter.trimmed() );
109  rx.setPatternSyntax( QRegExp::RegExp );
110  rx.setCaseSensitivity( mCaseSensitivity );
111  mREList.append( rx );
112  break;
113  }
114  }
115  invalidateFilter();
116 }
117 
118 bool QgsBrowserProxyModel::filterAcceptsString( const QString &value ) const
119 {
120  switch ( mPatternSyntax )
121  {
122  case Normal:
123  case Wildcards:
124  {
125  for ( const QRegExp &rx : mREList )
126  {
127  if ( rx.exactMatch( value ) )
128  return true;
129  }
130  break;
131  }
132 
133  case RegularExpression:
134  {
135  for ( const QRegExp &rx : mREList )
136  {
137  if ( rx.indexIn( value ) != -1 )
138  return true;
139  }
140  break;
141  }
142  }
143 
144  return false;
145 }
146 
147 bool QgsBrowserProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
148 {
149  if ( ( mFilter.isEmpty() && !mFilterByLayerType && mHiddenDataItemsKeys.empty() ) || !mModel )
150  return true;
151 
152  QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
153  if ( !filterAcceptsProviderKey( sourceIndex ) || !filterRootAcceptsProviderKey( sourceIndex ) )
154  return false;
155 
156  return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
157 }
158 
160 {
161  return mLayerType;
162 }
163 
165 {
166  mLayerType = type;
167  invalidateFilter();
168 }
169 
171 {
172  mFilterByLayerType = filterByLayerType;
173  invalidateFilter();
174 }
175 
176 bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
177 {
178  if ( !mModel )
179  return true;
180 
181  if ( mFilterByLayerType )
182  return false;
183 
184  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
185  if ( !sourceParentIndex.isValid() )
186  return false;
187  if ( filterAcceptsItem( sourceParentIndex ) )
188  return true;
189 
190  return filterAcceptsAncestor( sourceParentIndex );
191 }
192 
193 bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
194 {
195  if ( !mModel )
196  return true;
197 
198  for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
199  {
200  QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
201  if ( filterAcceptsItem( sourceChildIndex ) )
202  return true;
203  if ( filterAcceptsDescendant( sourceChildIndex ) )
204  return true;
205  }
206  return false;
207 }
208 
209 bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
210 {
211  if ( !mModel )
212  return true;
213 
214  if ( mFilterByLayerType )
215  {
216  QgsDataItem *item = mModel->dataItem( sourceIndex );
217  if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
218  {
219  if ( layerItem->mapLayerType() != mLayerType )
220  return false;
221  }
222  else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
223  return false;
224  }
225 
226  if ( !mFilter.isEmpty() )
227  {
228  //accept item if either displayed text or comment role matches string
229  QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
230  return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
231  || ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
232  }
233 
234  return true;
235 }
236 
237 bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
238 {
239  if ( !mModel )
240  return true;
241 
242  const QString providerKey = mModel->data( sourceIndex, QgsBrowserModel::ProviderKeyRole ).toString();
243  if ( providerKey.isEmpty() )
244  return true;
245 
246  return !mHiddenDataItemsKeys.contains( providerKey );
247 }
248 
249 bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
250 {
251  if ( !mModel )
252  return true;
253 
254  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
255  if ( !sourceParentIndex.isValid() )
256  {
257  return filterAcceptsProviderKey( sourceIndex );
258  }
259 
260  return filterRootAcceptsProviderKey( sourceParentIndex );
261 }
262 
263 void QgsBrowserProxyModel::setDataItemProviderKeyFilter( const QStringList &filter )
264 {
265  mHiddenDataItemsKeys = filter;
266  invalidateFilter();
267 }
Qt::CaseSensitivity caseSensitivity() const
Returns whether item filtering is case sensitive.
FilterSyntax filterSyntax() const
Returns the filter syntax.
FilterSyntax
Filter syntax options.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
void setDataItemProviderKeyFilter(const QStringList &filter)
Sets the customization filters for data items based on item&#39;s data provider key.
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
QgsMapLayerType layerType() const
Returns the layer type to filter the model by.
QgsBrowserProxyModel(QObject *parent=nullptr)
Constructor for QgsBrowserProxyModel, with the specified parent object.
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
QModelIndex parent(const QModelIndex &index) const override
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index...
QString filterString() const
Returns the filter string used when filtering items in the model.
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
bool filterByLayerType() const
Returns true if the model is filtered by map layer type.
Base class for all items in the model.
Definition: qgsdataitem.h:49
Custom sort role, see QgsDataItem::sortKey()
Data item provider key that created the item,.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Standard string filtering.
A model for showing available data sources and other items in a structured tree.
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:485
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:66
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index...