QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 true;
52  }
53  else if ( rightSelected && !leftSelected )
54  {
55  return false;
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  {
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 
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  break;
176 
177  case ShowFilteredList:
178  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
179  break;
180 
181  case ShowSelected:
182  return layer()->selectedFeaturesIds().contains( masterModel()->rowToId( sourceRow ) );
183  break;
184 
185  case ShowVisible:
186  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
187  break;
188 
189  case ShowEdited:
190  {
191  QgsVectorLayerEditBuffer* editBuffer = layer()->editBuffer();
192  if ( editBuffer )
193  {
194  const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
195  const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
196  const QgsFeatureId fid = masterModel()->rowToId( sourceRow );
197  return addedFeatures.contains( fid ) || changedFeatures.contains( fid );
198  }
199  return false;
200  break;
201  }
202 
203  default:
204  Q_ASSERT( false ); // In debug mode complain
205  return true; // In release mode accept row
206  break;
207  }
208  // returns are handled in their respective case statement above
209 }
210 
212 {
214  invalidateFilter();
215 }
216 
218 {
219  if ( ShowSelected == mFilterMode )
220  {
222  invalidateFilter();
223  }
224  else if ( mSelectedOnTop )
225  {
226  sort( sortColumn(), sortOrder() );
227  invalidate();
228  }
229 }
230 
232 {
233  if ( !layer() )
234  return;
235 
236  bool filter = false;
238  QgsRenderContext renderContext;
239  QgsFeatureRendererV2* renderer = layer()->rendererV2();
240 
241  mFilteredFeatures.clear();
242 
243  if ( !renderer )
244  {
245  QgsDebugMsg( "Cannot get renderer" );
246  return;
247  }
248 
249  const QgsMapSettings& ms = mCanvas->mapSettings();
250  if ( layer()->hasScaleBasedVisibility() &&
251  ( layer()->minimumScale() > ms.scale() ||
252  layer()->maximumScale() <= ms.scale() ) )
253  {
254  QgsDebugMsg( "Out of scale limits" );
255  }
256  else
257  {
258  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
259  {
260  // setup scale
261  // mapRenderer()->renderContext()->scale is not automaticaly updated when
262  // render extent changes (because it's scale is used to identify if changed
263  // since last render) -> use local context
264  renderContext.setExtent( ms.visibleExtent() );
265  renderContext.setMapToPixel( ms.mapToPixel() );
266  renderContext.setRendererScale( ms.scale() );
267  }
268 
269  filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
270  }
271 
272  renderer->startRender( renderContext, layer()->pendingFields() );
273 
274  QgsFeatureIterator features = masterModel()->layerCache()->getFeatures( QgsFeatureRequest().setFilterRect( rect ) );
275 
276  QgsFeature f;
277 
278  while ( features.nextFeature( f ) )
279  {
280  if ( !filter || renderer->willRenderFeature( f ) )
281  {
282  mFilteredFeatures << f.id();
283  }
284 #if 0
285  if ( t.elapsed() > 5000 )
286  {
287  bool cancel = false;
288  emit progress( i, cancel );
289  if ( cancel )
290  break;
291 
292  t.restart();
293  }
294 #endif
295  }
296 
297  features.close();
298 
299  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
300  {
301  renderer->stopRender( renderContext );
302  }
303 }
304 
306 {
307  return masterModel()->rowToId( mapToSource( row ).row() );
308 }
309 
311 {
312  return mapFromMaster( masterModel()->idToIndex( fid ) );
313 }
314 
316 {
317  QModelIndexList indexes;
318  foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) )
319  {
320  indexes.append( mapFromMaster( idx ) );
321  }
322 
323  return indexes;
324 }
325 
326 QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
327 {
328  // Master is source
329  return mapToSource( proxyIndex );
330 }
331 
332 QModelIndex QgsAttributeTableFilterModel::mapFromMaster( const QModelIndex &sourceIndex ) const
333 {
334  // Master is source
335  return mapFromSource( sourceIndex );
336 }
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.
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.
QgsAttributeTableFilterModel(QgsMapCanvas *canvas, QgsAttributeTableModel *sourceModel, QObject *parent=NULL)
Make sure, the master model is already loaded, so the selection will get synchronized.
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
QModelIndex fidToIndex(QgsFeatureId fid)
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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:325
bool lessThan(const QModelIndex &left, const QModelIndex &right) const
Used by the sorting algorithm.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
Returns true if the source row will be accepted.
void setRendererScale(double scale)
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:113
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
void setExtent(const QgsRectangle &extent)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:104
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...
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
float maximumScale() 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 setSourceModel(QgsAttributeTableModel *sourceModel)
void extentsChanged()
Is called upon every change of the visible extents on the map canvas.
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
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 sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
Sort by the given column using the given order.
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.