QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 }
QgsBrowserProxyModel::setShowLayers
void setShowLayers(bool showLayers)
Sets show layers to showLayers.
Definition: qgsbrowserproxymodel.cpp:173
QgsBrowserProxyModel::filterSyntax
FilterSyntax filterSyntax() const
Returns the filter syntax.
Definition: qgsbrowserproxymodel.cpp:48
QgsBrowserProxyModel::caseSensitivity
Qt::CaseSensitivity caseSensitivity() const
Returns whether item filtering is case sensitive.
Definition: qgsbrowserproxymodel.cpp:72
QgsBrowserModel::parent
QModelIndex parent(const QModelIndex &index) const override
Definition: qgsbrowsermodel.cpp:525
QgsBrowserModel::ProviderKeyRole
@ ProviderKeyRole
Data item provider key that created the item, see QgsDataItem::providerKey()
Definition: qgsbrowsermodel.h:95
QgsBrowserProxyModel::showLayers
bool showLayers() const
Returns true if layers must be shown, this flag is TRUE by default.
Definition: qgsbrowserproxymodel.cpp:168
QgsMapLayerType
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:68
QgsBrowserProxyModel::QgsBrowserProxyModel
QgsBrowserProxyModel(QObject *parent=nullptr)
Constructor for QgsBrowserProxyModel, with the specified parent object.
Definition: qgsbrowserproxymodel.cpp:19
QgsBrowserProxyModel::hasChildren
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowserproxymodel.cpp:295
QgsBrowserModel::SortRole
@ SortRole
Custom sort role, see QgsDataItem::sortKey()
Definition: qgsbrowsermodel.h:94
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:636
QgsBrowserModel::CommentRole
@ CommentRole
Item comment.
Definition: qgsbrowsermodel.h:93
QgsBrowserProxyModel::filterAcceptsRow
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Definition: qgsbrowserproxymodel.cpp:147
QgsBrowserProxyModel::setBrowserModel
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
Definition: qgsbrowserproxymodel.cpp:28
QgsBrowserProxyModel::setFilterCaseSensitivity
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
Definition: qgsbrowserproxymodel.cpp:66
QgsBrowserProxyModel::setFilterByLayerType
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.
Definition: qgsbrowserproxymodel.cpp:189
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:262
QgsBrowserProxyModel::filterString
QString filterString() const
Returns the filter string used when filtering items in the model.
Definition: qgsbrowserproxymodel.cpp:61
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:178
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:282
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:288
QgsBrowserProxyModel::setFilterSyntax
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
Definition: qgsbrowserproxymodel.cpp:40
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:350
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:34
QgsBrowserModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:514
qgsbrowserproxymodel.h
QgsLayerItem
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:507
QgsDataItem
Base class for all items in the model.
Definition: qgsdataitem.h:51
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:658
QgsBrowserProxyModel::FilterSyntax
FilterSyntax
Filter syntax options.
Definition: qgsbrowserproxymodel.h:39
QgsBrowserProxyModel::setLayerType
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
Definition: qgsbrowserproxymodel.cpp:183
QgsBrowserProxyModel::setFilterString
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
Definition: qgsbrowserproxymodel.cpp:53
QgsBrowserModel
A model for showing available data sources and other items in a structured tree.
Definition: qgsbrowsermodel.h:74