QGIS API Documentation  2.14.11-Essen
qgsattributetablefiltermodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsAttributeTableFilterModel.cpp
3  --------------------------------------
4  Date : Feb 2009
5  Copyright : (C) 2009 Vita Cizek
6  Email : weetya (at) gmail.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 <QItemSelectionModel>
17 
18 #include "qgis.h"
20 #include "qgsattributetablemodel.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsfeature.h"
23 #include "qgsmapcanvas.h"
24 #include "qgslogger.h"
25 #include "qgsrendererv2.h"
28 // Filter Model //
30 
32  : QSortFilterProxyModel( parent )
33  , mCanvas( canvas )
34  , mFilterMode( ShowAll )
35  , mSelectedOnTop( false )
36 {
37  setSourceModel( sourceModel );
38  setDynamicSortFilter( true );
40  connect( layer(), SIGNAL( selectionChanged() ), SLOT( selectionChanged() ) );
41 }
42 
43 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
44 {
45  if ( mSelectedOnTop )
46  {
47  bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) );
48  bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) );
49 
50  if ( leftSelected && !rightSelected )
51  {
52  return sortOrder() == Qt::AscendingOrder;
53  }
54  else if ( rightSelected && !leftSelected )
55  {
56  return sortOrder() == Qt::DescendingOrder;
57  }
58  }
59 
62 }
63 
64 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
65 {
66  masterModel()->prefetchColumnData( column );
67  QSortFilterProxyModel::sort( column, order );
68 }
69 
71 {
72  if ( mSelectedOnTop != selectedOnTop )
73  {
74  mSelectedOnTop = selectedOnTop;
75 
76  if ( sortColumn() == -1 )
77  {
78  sort( 0 );
79  }
80  invalidate();
81  }
82 }
83 
85 {
86  mTableModel = sourceModel;
87 
89 }
90 
92 {
93  return mSelectedOnTop;
94 }
95 
97 {
98  mFilteredFeatures = ids;
101 }
102 
104 {
105  QgsFeatureIds ids;
106  for ( int i = 0; i < rowCount(); ++i )
107  {
108  QModelIndex row = index( i, 0 );
109  ids << rowToId( row );
110  }
111  return ids;
112 }
113 
115 {
116  if ( filterMode != mFilterMode )
117  {
118  if ( filterMode == ShowVisible )
119  {
120  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
122  }
123  else
124  {
125  disconnect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
126  }
127 
128  if ( filterMode == ShowSelected )
129  {
131  }
132 
133  mFilterMode = filterMode;
135  }
136 }
137 
138 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
139 {
140  Q_UNUSED( sourceParent );
141  switch ( mFilterMode )
142  {
143  case ShowAll:
144  return true;
145 
146  case ShowFilteredList:
147  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
148 
149  case ShowSelected:
150  return layer()->selectedFeaturesIds().isEmpty() || layer()->selectedFeaturesIds().contains( masterModel()->rowToId( sourceRow ) );
151 
152  case ShowVisible:
153  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
154 
155  case ShowEdited:
156  {
157  QgsVectorLayerEditBuffer* editBuffer = layer()->editBuffer();
158  if ( editBuffer )
159  {
160  const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
161  const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
162  const QList<QgsFeatureId> changedGeometries = editBuffer->changedGeometries().keys();
163  const QgsFeatureId fid = masterModel()->rowToId( sourceRow );
164  return addedFeatures.contains( fid ) || changedFeatures.contains( fid ) || changedGeometries.contains( fid );
165  }
166  return false;
167  }
168 
169  default:
170  Q_ASSERT( false ); // In debug mode complain
171  return true; // In release mode accept row
172  }
173  // returns are handled in their respective case statement above
174 }
175 
177 {
180 }
181 
182 void QgsAttributeTableFilterModel::selectionChanged()
183 {
184  if ( ShowSelected == mFilterMode )
185  {
188  }
189  else if ( mSelectedOnTop )
190  {
191  sort( sortColumn(), sortOrder() );
192  invalidate();
193  }
194 }
195 
197 {
198  if ( !layer() )
199  return;
200 
201  bool filter = false;
202  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
203  QgsRenderContext renderContext;
207  QgsFeatureRendererV2* renderer = layer()->rendererV2();
208 
209  mFilteredFeatures.clear();
210 
211  if ( !renderer )
212  {
213  QgsDebugMsg( "Cannot get renderer" );
214  return;
215  }
216 
217  const QgsMapSettings& ms = mCanvas->mapSettings();
218  if ( layer()->hasScaleBasedVisibility() &&
219  ( layer()->minimumScale() > ms.scale() ||
220  layer()->maximumScale() <= ms.scale() ) )
221  {
222  QgsDebugMsg( "Out of scale limits" );
223  }
224  else
225  {
226  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
227  {
228  // setup scale
229  // mapRenderer()->renderContext()->scale is not automaticaly updated when
230  // render extent changes (because it's scale is used to identify if changed
231  // since last render) -> use local context
232  renderContext.setExtent( ms.visibleExtent() );
233  renderContext.setMapToPixel( ms.mapToPixel() );
234  renderContext.setRendererScale( ms.scale() );
235  }
236 
237  filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
238  }
239 
240  renderer->startRender( renderContext, layer()->fields() );
241 
242  QgsFeatureRequest r( masterModel()->request() );
243  if ( !r.filterRect().isNull() )
244  {
245  r.setFilterRect( r.filterRect().intersect( &rect ) );
246  }
247  else
248  {
249  r.setFilterRect( rect );
250  }
252 
253  QgsFeature f;
254 
255  while ( features.nextFeature( f ) )
256  {
257  renderContext.expressionContext().setFeature( f );
258  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
259  {
260  mFilteredFeatures << f.id();
261  }
262 #if 0
263  if ( t.elapsed() > 5000 )
264  {
265  bool cancel = false;
266  emit progress( i, cancel );
267  if ( cancel )
268  break;
269 
270  t.restart();
271  }
272 #endif
273  }
274 
275  features.close();
276 
277  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
278  {
279  renderer->stopRender( renderContext );
280  }
281 }
282 
284 {
285  return masterModel()->rowToId( mapToSource( row ).row() );
286 }
287 
289 {
290  return mapFromMaster( masterModel()->idToIndex( fid ) );
291 }
292 
294 {
295  QModelIndexList indexes;
296  Q_FOREACH ( const QModelIndex& idx, masterModel()->idToIndexList( fid ) )
297  {
298  indexes.append( mapFromMaster( idx ) );
299  }
300 
301  return indexes;
302 }
303 
305 {
306  // Master is source
307  return mapToSource( proxyIndex );
308 }
309 
311 {
312  // Master is source
313  return mapFromSource( sourceIndex );
314 }
void generateListOfVisibleFeatures()
Updates the list of currently visible features on the map canvas.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
const QgsGeometryMap & changedGeometries()
Changed geometries which are not commited.
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
Wrapper for iterator of features from vector data provider or vector layer.
void setSortRole(int role)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Returns true if the source row will be accepted.
bool selectedOnTop()
Returns if selected features are currently shown on top.
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
virtual void sort(int column, Qt::SortOrder order)
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
virtual void setSourceModel(QAbstractItemModel *sourceModel)
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setRendererScale(double scale)
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Used by the sorting algorithm.
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
const QgsRectangle & filterRect() const
Get the rectangle from which features will be taken.
virtual Q_DECL_DEPRECATED bool willRenderFeature(QgsFeature &feat)
Returns whether the renderer will render a feature or not.
void setExtent(const QgsRectangle &extent)
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
virtual int rowCount(const QModelIndex &parent) const
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:267
QgsAttributeTableFilterModel(QgsMapCanvas *canvas, QgsAttributeTableModel *sourceModel, QObject *parent=nullptr)
Make sure, the master model is already loaded, so the selection will get synchronized.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
Needs to be called when a new render cycle is started.
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
The QgsMapSettings class contains configuration for rendering of the map.
virtual void stopRender(QgsRenderContext &context)=0
Needs to be called when a render cycle has finished to clean up.
QList< Key > keys() const
float maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
FilterMode filterMode()
The current filterModel.
double scale() const
Return the calculated scale of the map.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
int row() const
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
void setDynamicSortFilter(bool enable)
const QgsMapToPixel & mapToPixel() const
void setSourceModel(QgsAttributeTableModel *sourceModel)
Set the attribute table model that backs this model.
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
void extentsChanged()
Is called upon every change of the visible extents on the map canvas.
bool contains(const T &value) const
QgsExpressionContext & expressionContext()
Gets the expression context.
bool contains(const T &value) const
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
const QgsFeatureMap & addedFeatures()
New features which are not commited.
Contains information about the context of a rendering operation.
QAbstractItemModel * sourceModel() const
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
Qt::SortOrder sortOrder() const
QVariant data(int role) const
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer&#39;s CRS
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
void setMapToPixel(const QgsMapToPixel &mtp)
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
bool isEmpty() const
QgsFeatureId rowToId(int row) const
Maps row to feature id.
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QgsFeatureIds filteredFeatures()
Get a list of currently filtered feature ids.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
virtual int capabilities()
returns bitwise OR-ed capabilities of the renderer
bool nextFeature(QgsFeature &f)
void clear()
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QModelIndexList fidToIndexList(QgsFeatureId fid)
int sortColumn() const
void prefetchColumnData(int column)
Caches the entire data for one column.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
QModelIndex fidToIndex(QgsFeatureId fid) override