QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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() && mShownDataItemsKeys.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  if ( ! mShowLayers )
157  {
158  QgsDataItem *item = mModel->dataItem( sourceIndex );
159  if ( qobject_cast< QgsLayerItem * >( item ) )
160  {
161  return false;
162  }
163  }
164 
165  return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
166 }
167 
169 {
170  return mShowLayers;
171 }
172 
173 void QgsBrowserProxyModel::setShowLayers( bool showLayers )
174 {
175  mShowLayers = showLayers;
176 }
177 
179 {
180  return mLayerType;
181 }
182 
184 {
185  mLayerType = type;
186  invalidateFilter();
187 }
188 
189 void QgsBrowserProxyModel::setFilterByLayerType( bool filterByLayerType )
190 {
191  mFilterByLayerType = filterByLayerType;
192  invalidateFilter();
193 }
194 
195 bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
196 {
197  if ( !mModel )
198  return true;
199 
200  if ( mFilterByLayerType )
201  return false;
202 
203  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
204  if ( !sourceParentIndex.isValid() )
205  return false;
206  if ( filterAcceptsItem( sourceParentIndex ) )
207  return true;
208 
209  return filterAcceptsAncestor( sourceParentIndex );
210 }
211 
212 bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
213 {
214  if ( !mModel )
215  return true;
216 
217  for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
218  {
219  QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
220  if ( filterAcceptsItem( sourceChildIndex ) )
221  return true;
222  if ( filterAcceptsDescendant( sourceChildIndex ) )
223  return true;
224  }
225  return false;
226 }
227 
228 bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
229 {
230  if ( !mModel )
231  return true;
232 
233  if ( mFilterByLayerType )
234  {
235  QgsDataItem *item = mModel->dataItem( sourceIndex );
236  if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
237  {
238  if ( layerItem->mapLayerType() != mLayerType )
239  return false;
240  }
241  else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
242  return false;
243  }
244 
245  if ( !mFilter.isEmpty() )
246  {
247  //accept item if either displayed text or comment role matches string
248  QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
249  return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
250  || ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
251  }
252 
253  return true;
254 }
255 
256 bool QgsBrowserProxyModel::filterAcceptsProviderKey( const QModelIndex &sourceIndex ) const
257 {
258  if ( !mModel )
259  return true;
260 
261  const QString providerKey = mModel->data( sourceIndex, QgsBrowserModel::ProviderKeyRole ).toString();
262  if ( providerKey.isEmpty() )
263  return true;
264 
265  return !mHiddenDataItemsKeys.contains( providerKey ) && ( mShownDataItemsKeys.isEmpty() || mShownDataItemsKeys.contains( providerKey ) );
266 }
267 
268 bool QgsBrowserProxyModel::filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const
269 {
270  if ( !mModel )
271  return true;
272 
273  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
274  if ( !sourceParentIndex.isValid() )
275  {
276  return filterAcceptsProviderKey( sourceIndex );
277  }
278 
279  return filterRootAcceptsProviderKey( sourceParentIndex );
280 }
281 
283 {
284  mHiddenDataItemsKeys = filter;
285  invalidateFilter();
286 }
287 
289 {
290  mShownDataItemsKeys = filter;
291  invalidateFilter();
292 }
293 
294 
295 bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const
296 {
297  bool isFertile { QSortFilterProxyModel::hasChildren( parent ) };
298  if ( isFertile && parent.isValid() )
299  {
300  QgsDataItem *item = dataItem( parent );
301  if ( ! mShowLayers )
302  {
303  return ! item->layerCollection();
304  }
305  // Hide everything below layers if filter is set
306  else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) )
307  {
308  return false;
309  }
310  }
311  return isFertile;
312 }
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:52
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: qgsdataitem.h:554
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:69