QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 }
QString filterString() const
Returns the filter string used when filtering items in the model.
void setLayerType(QgsMapLayer::LayerType type)
Sets the layer type to filter the model by.
FilterSyntax
Filter syntax options.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
FilterSyntax filterSyntax() const
Returns the filter syntax.
bool filterByLayerType() const
Returns true if the model is filtered by map layer type.
QgsMapLayer::LayerType layerType() const
Returns the layer type to filter the model by.
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
QgsBrowserProxyModel(QObject *parent=nullptr)
Constructor for QgsBrowserProxyModel, with the specified parent object.
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
Qt::CaseSensitivity caseSensitivity() const
Returns whether item filtering is case sensitive.
QModelIndex parent(const QModelIndex &index) const override
LayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:105
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or a nullptr if no item exists at the index...
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
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
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or a nullptr if no item exists at the index...
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:435
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.