QGIS API Documentation  2.8.6-Wien
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 
19 #include "qgsattributetablemodel.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsfeature.h"
22 #include "qgsmapcanvas.h"
23 #include "qgslogger.h"
24 #include "qgsrendererv2.h"
27 // Filter Model //
29 
31  : QSortFilterProxyModel( parent )
32  , mCanvas( canvas )
33  , mFilterMode( ShowAll )
34  , mSelectedOnTop( false )
35 {
36  setSourceModel( sourceModel );
37  setDynamicSortFilter( true );
38  setSortRole( QgsAttributeTableModel::SortRole );
39  connect( layer(), SIGNAL( selectionChanged() ), SLOT( selectionChanged() ) );
40 }
41 
42 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
43 {
44  if ( mSelectedOnTop )
45  {
46  bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) );
47  bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) );
48 
49  if ( leftSelected && !rightSelected )
50  {
51  return sortOrder() == Qt::AscendingOrder;
52  }
53  else if ( rightSelected && !leftSelected )
54  {
55  return sortOrder() == Qt::DescendingOrder;
56  }
57  }
58 
59 
60  QVariant leftData = left.data( QgsAttributeTableModel::SortRole );
61  QVariant rightData = right.data( QgsAttributeTableModel::SortRole );
62 
63  if ( leftData.isNull() )
64  return true;
65 
66  if ( rightData.isNull() )
67  return false;
68 
69  switch ( leftData.type() )
70  {
71  case QVariant::Int:
72  case QVariant::UInt:
73  case QVariant::LongLong:
74  case QVariant::ULongLong:
75  return leftData.toLongLong() < rightData.toLongLong();
76 
77  case QVariant::Double:
78  return leftData.toDouble() < rightData.toDouble();
79 
80  case QVariant::Date:
81  return leftData.toDate() < rightData.toDate();
82 
83  case QVariant::DateTime:
84  return leftData.toDateTime() < rightData.toDateTime();
85 
86  default:
87  return leftData.toString().localeAwareCompare( rightData.toString() ) < 0;
88  }
89 
90  // Avoid warning. Will never reach this
91  return false;
92 }
93 
94 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
95 {
96  masterModel()->prefetchColumnData( column );
97  QSortFilterProxyModel::sort( column, order );
98 }
99 
101 {
102  if ( mSelectedOnTop != selectedOnTop )
103  {
104  mSelectedOnTop = selectedOnTop;
105 
106  if ( sortColumn() == -1 )
107  {
108  sort( 0 );
109  }
110  invalidate();
111  }
112 }
113 
115 {
116  mTableModel = sourceModel;
117 
118  QSortFilterProxyModel::setSourceModel( sourceModel );
119 }
120 
122 {
123  return mSelectedOnTop;
124 }
125 
127 {
128  mFilteredFeatures = ids;
130  invalidateFilter();
131 }
132 
134 {
135  QgsFeatureIds ids;
136  for ( int i = 0; i < rowCount(); ++i )
137  {
138  QModelIndex row = index( i, 0 );
139  ids << rowToId( row );
140  }
141  return ids;
142 }
143 
145 {
146  if ( filterMode != mFilterMode )
147  {
148  if ( filterMode == ShowVisible )
149  {
150  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
152  }
153  else
154  {
155  disconnect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
156  }
157 
158  if ( filterMode == ShowSelected )
159  {
161  }
162 
163  mFilterMode = filterMode;
164  invalidateFilter();
165  }
166 }
167 
168 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
169 {
170  Q_UNUSED( sourceParent );
171  switch ( mFilterMode )
172  {
173  case ShowAll:
174  return true;
175 
176  case ShowFilteredList:
177  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
178 
179  case ShowSelected:
180  return layer()->selectedFeaturesIds().contains( masterModel()->rowToId( sourceRow ) );
181 
182  case ShowVisible:
183  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
184 
185  case ShowEdited:
186  {
187  QgsVectorLayerEditBuffer* editBuffer = layer()->editBuffer();
188  if ( editBuffer )
189  {
190  const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
191  const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
192  const QList<QgsFeatureId> changedGeometries = editBuffer->changedGeometries().keys();
193  const QgsFeatureId fid = masterModel()->rowToId( sourceRow );
194  return addedFeatures.contains( fid ) || changedFeatures.contains( fid ) || changedGeometries.contains( fid );
195  }
196  return false;
197  }
198 
199  default:
200  Q_ASSERT( false ); // In debug mode complain
201  return true; // In release mode accept row
202  }
203  // returns are handled in their respective case statement above
204 }
205 
207 {
209  invalidateFilter();
210 }
211 
212 void QgsAttributeTableFilterModel::selectionChanged()
213 {
214  if ( ShowSelected == mFilterMode )
215  {
217  invalidateFilter();
218  }
219  else if ( mSelectedOnTop )
220  {
221  sort( sortColumn(), sortOrder() );
222  invalidate();
223  }
224 }
225 
227 {
228  if ( !layer() )
229  return;
230 
231  bool filter = false;
232  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
233  QgsRenderContext renderContext;
234  QgsFeatureRendererV2* renderer = layer()->rendererV2();
235 
236  mFilteredFeatures.clear();
237 
238  if ( !renderer )
239  {
240  QgsDebugMsg( "Cannot get renderer" );
241  return;
242  }
243 
244  const QgsMapSettings& ms = mCanvas->mapSettings();
245  if ( layer()->hasScaleBasedVisibility() &&
246  ( layer()->minimumScale() > ms.scale() ||
247  layer()->maximumScale() <= ms.scale() ) )
248  {
249  QgsDebugMsg( "Out of scale limits" );
250  }
251  else
252  {
253  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
254  {
255  // setup scale
256  // mapRenderer()->renderContext()->scale is not automaticaly updated when
257  // render extent changes (because it's scale is used to identify if changed
258  // since last render) -> use local context
259  renderContext.setExtent( ms.visibleExtent() );
260  renderContext.setMapToPixel( ms.mapToPixel() );
261  renderContext.setRendererScale( ms.scale() );
262  }
263 
264  filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
265  }
266 
267  renderer->startRender( renderContext, layer()->pendingFields() );
268 
269  QgsFeatureRequest r( masterModel()->request() );
271  {
272  r.setFilterRect( r.filterRect().intersect( &rect ) );
273  }
274  else
275  {
276  r.setFilterRect( rect );
277  }
279 
280  QgsFeature f;
281 
282  while ( features.nextFeature( f ) )
283  {
284  if ( !filter || renderer->willRenderFeature( f ) )
285  {
286  mFilteredFeatures << f.id();
287  }
288 #if 0
289  if ( t.elapsed() > 5000 )
290  {
291  bool cancel = false;
292  emit progress( i, cancel );
293  if ( cancel )
294  break;
295 
296  t.restart();
297  }
298 #endif
299  }
300 
301  features.close();
302 
303  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
304  {
305  renderer->stopRender( renderContext );
306  }
307 }
308 
310 {
311  return masterModel()->rowToId( mapToSource( row ).row() );
312 }
313 
315 {
316  return mapFromMaster( masterModel()->idToIndex( fid ) );
317 }
318 
320 {
321  QModelIndexList indexes;
322  foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) )
323  {
324  indexes.append( mapFromMaster( idx ) );
325  }
326 
327  return indexes;
328 }
329 
330 QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
331 {
332  // Master is source
333  return mapToSource( proxyIndex );
334 }
335 
336 QModelIndex QgsAttributeTableFilterModel::mapFromMaster( const QModelIndex &sourceIndex ) const
337 {
338  // Master is source
339  return mapFromSource( sourceIndex );
340 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
void generateListOfVisibleFeatures()
Updates the list of currently visible features on the map canvas.
const QgsGeometryMap & changedGeometries()
Changed geometries which are not commited.
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
Wrapper for iterator of features from vector data provider or vector layer.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static unsigned index
virtual bool willRenderFeature(QgsFeature &feat)
return whether the renderer will render a feature or not.
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.
double scale() const
Return the calculated scale of the map.
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
const QgsRectangle & filterRect() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:360
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 visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
const QgsMapToPixel & mapToPixel() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:156
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer&#39;s CRS
void setExtent(const QgsRectangle &extent)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
The QgsMapSettings class contains configuration for rendering of the map.
virtual void stopRender(QgsRenderContext &context)=0
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
QgsAttributeTableFilterModel(QgsMapCanvas *canvas, QgsAttributeTableModel *sourceModel, QObject *parent=0)
Make sure, the master model is already loaded, so the selection will get synchronized.
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
float maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Filter using a rectangle, no need to set NoGeometry.
FilterType filterType() const
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
void setSourceModel(QgsAttributeTableModel *sourceModel)
void extentsChanged()
Is called upon every change of the visible extents on the map canvas.
void sort(double *heap, int *x, int *y, int N)
Definition: util.cpp:72
const QgsFeatureMap & addedFeatures()
New features which are not commited.
Contains information about the context of a rendering operation.
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
void setMapToPixel(const QgsMapToPixel &mtp)
qint64 QgsFeatureId
Definition: qgsfeature.h:30
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
virtual int capabilities()
returns bitwise OR-ed capabilities of the renderer
bool nextFeature(QgsFeature &f)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QModelIndexList fidToIndexList(QgsFeatureId fid)
virtual void setFilteredFeatures(QgsFeatureIds ids)
Specify a list of features, which the filter will accept.
void prefetchColumnData(int column)
Caches the entire data for one column.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
QModelIndex fidToIndex(QgsFeatureId fid) override