QGIS API Documentation  2.11.0-Master
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 );
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 
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 
119 }
120 
122 {
123  return mSelectedOnTop;
124 }
125 
127 {
128  mFilteredFeatures = ids;
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;
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().isEmpty() || 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 QgsFeatureId fid = masterModel()->rowToId( sourceRow );
193  return addedFeatures.contains( fid ) || changedFeatures.contains( fid );
194  }
195  return false;
196  }
197 
198  default:
199  Q_ASSERT( false ); // In debug mode complain
200  return true; // In release mode accept row
201  }
202  // returns are handled in their respective case statement above
203 }
204 
206 {
209 }
210 
211 void QgsAttributeTableFilterModel::selectionChanged()
212 {
213  if ( ShowSelected == mFilterMode )
214  {
217  }
218  else if ( mSelectedOnTop )
219  {
220  sort( sortColumn(), sortOrder() );
221  invalidate();
222  }
223 }
224 
226 {
227  if ( !layer() )
228  return;
229 
230  bool filter = false;
231  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
232  QgsRenderContext renderContext;
236  QgsFeatureRendererV2* renderer = layer()->rendererV2();
237 
238  mFilteredFeatures.clear();
239 
240  if ( !renderer )
241  {
242  QgsDebugMsg( "Cannot get renderer" );
243  return;
244  }
245 
246  const QgsMapSettings& ms = mCanvas->mapSettings();
247  if ( layer()->hasScaleBasedVisibility() &&
248  ( layer()->minimumScale() > ms.scale() ||
249  layer()->maximumScale() <= ms.scale() ) )
250  {
251  QgsDebugMsg( "Out of scale limits" );
252  }
253  else
254  {
255  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
256  {
257  // setup scale
258  // mapRenderer()->renderContext()->scale is not automaticaly updated when
259  // render extent changes (because it's scale is used to identify if changed
260  // since last render) -> use local context
261  renderContext.setExtent( ms.visibleExtent() );
262  renderContext.setMapToPixel( ms.mapToPixel() );
263  renderContext.setRendererScale( ms.scale() );
264  }
265 
266  filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
267  }
268 
269  renderer->startRender( renderContext, layer()->fields() );
270 
271  QgsFeatureRequest r( masterModel()->request() );
272  if ( !r.filterRect().isNull() )
273  {
274  r.setFilterRect( r.filterRect().intersect( &rect ) );
275  }
276  else
277  {
278  r.setFilterRect( rect );
279  }
281 
282  QgsFeature f;
283 
284  while ( features.nextFeature( f ) )
285  {
286  renderContext.expressionContext().setFeature( f );
287  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
288  {
289  mFilteredFeatures << f.id();
290  }
291 #if 0
292  if ( t.elapsed() > 5000 )
293  {
294  bool cancel = false;
295  emit progress( i, cancel );
296  if ( cancel )
297  break;
298 
299  t.restart();
300  }
301 #endif
302  }
303 
304  features.close();
305 
306  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
307  {
308  renderer->stopRender( renderContext );
309  }
310 }
311 
313 {
314  return masterModel()->rowToId( mapToSource( row ).row() );
315 }
316 
318 {
319  return mapFromMaster( masterModel()->idToIndex( fid ) );
320 }
321 
323 {
324  QModelIndexList indexes;
325  foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) )
326  {
327  indexes.append( mapFromMaster( idx ) );
328  }
329 
330  return indexes;
331 }
332 
334 {
335  // Master is source
336  return mapToSource( proxyIndex );
337 }
338 
340 {
341  // Master is source
342  return mapFromSource( sourceIndex );
343 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:51
void generateListOfVisibleFeatures()
Updates the list of currently visible features on the map canvas.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
qlonglong toLongLong(bool *ok) const
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.
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.
double scale() const
Return the calculated scale of the map.
int localeAwareCompare(const QString &other) const
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.
const QgsRectangle & filterRect() 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
QDateTime toDateTime() const
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.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
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:162
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's CRS
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual Q_DECL_DEPRECATED bool willRenderFeature(QgsFeature &feat)
return whether the renderer will render a feature or not.
void setExtent(const QgsRectangle &extent)
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
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
Needs to be called when a new render cycle is started.
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.
QList< Key > keys() const
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.
bool isNull() const
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.
int row() const
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setDynamicSortFilter(bool enable)
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
void setSourceModel(QgsAttributeTableModel *sourceModel)
Set the attribute table model that backs this model.
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 QgsFeatureMap & addedFeatures()
New features which are not commited.
QDate toDate() const
Contains information about the context of a rendering operation.
QAbstractItemModel * sourceModel() const
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
Qt::SortOrder sortOrder() const
QVariant data(int role) const
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
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
void setMapToPixel(const QgsMapToPixel &mtp)
bool isEmpty() const
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QgsFeatureIds filteredFeatures()
Get a list of currently filtered feature ids.
double toDouble(bool *ok) const
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
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()
Type type() const
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
QString toString() const
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