QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 ) || !mModel )
150  return true;
151 
152  QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
153  return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
154 }
155 
157 {
158  return mLayerType;
159 }
160 
162 {
163  mLayerType = type;
164  invalidateFilter();
165 }
166 
168 {
169  mFilterByLayerType = filterByLayerType;
170  invalidateFilter();
171 }
172 
173 bool QgsBrowserProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
174 {
175  if ( !mModel )
176  return true;
177 
178  if ( mFilterByLayerType )
179  return false;
180 
181  QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
182  if ( !sourceParentIndex.isValid() )
183  return false;
184  if ( filterAcceptsItem( sourceParentIndex ) )
185  return true;
186 
187  return filterAcceptsAncestor( sourceParentIndex );
188 }
189 
190 bool QgsBrowserProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
191 {
192  if ( !mModel )
193  return true;
194 
195  for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
196  {
197  QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
198  if ( filterAcceptsItem( sourceChildIndex ) )
199  return true;
200  if ( filterAcceptsDescendant( sourceChildIndex ) )
201  return true;
202  }
203  return false;
204 }
205 
206 bool QgsBrowserProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
207 {
208  if ( !mModel )
209  return true;
210 
211  if ( mFilterByLayerType )
212  {
213  QgsDataItem *item = mModel->dataItem( sourceIndex );
214  if ( QgsLayerItem *layerItem = qobject_cast< QgsLayerItem * >( item ) )
215  {
216  if ( layerItem->mapLayerType() != mLayerType )
217  return false;
218  }
219  else if ( !qobject_cast< QgsDataCollectionItem * >( item ) )
220  return false;
221  }
222 
223  if ( !mFilter.isEmpty() )
224  {
225  //accept item if either displayed text or comment role matches string
226  QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
227  return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
228  || ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
229  }
230 
231  return true;
232 }
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 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()
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:436
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:65
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index...