QGIS API Documentation  2.3.0-Master
 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  if ( filterMode != mFilterMode )
136  {
137  if ( filterMode == ShowVisible )
138  {
139  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
141  }
142  else
143  {
144  disconnect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
145  }
146 
147  if ( filterMode == ShowSelected )
148  {
150  }
151 
152  mFilterMode = filterMode;
153  invalidateFilter();
154  }
155 }
156 
157 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
158 {
159  Q_UNUSED( sourceParent );
160  switch ( mFilterMode )
161  {
162  case ShowAll:
163  return true;
164  break;
165 
166  case ShowFilteredList:
167  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
168  break;
169 
170  case ShowSelected:
171  return layer()->selectedFeaturesIds().contains( masterModel()->rowToId( sourceRow ) );
172  break;
173 
174  case ShowVisible:
175  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
176  break;
177 
178  case ShowEdited:
179  {
180  QgsVectorLayerEditBuffer* editBuffer = layer()->editBuffer();
181  if ( editBuffer )
182  {
183  const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
184  const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
185  const QgsFeatureId fid = masterModel()->rowToId( sourceRow );
186  return addedFeatures.contains( fid ) || changedFeatures.contains( fid );
187  }
188  return false;
189  break;
190  }
191 
192  default:
193  Q_ASSERT( false ); // In debug mode complain
194  return true; // In release mode accept row
195  break;
196  }
197  // returns are handled in their respective case statement above
198 }
199 
201 {
203  invalidateFilter();
204 }
205 
207 {
208  if ( ShowSelected == mFilterMode )
209  {
211  invalidateFilter();
212  }
213  else if ( mSelectedOnTop )
214  {
215  sort( sortColumn(), sortOrder() );
216  invalidate();
217  }
218 }
219 
221 {
222  if ( !layer() )
223  return;
224 
225  bool filter = false;
227  QgsRenderContext renderContext;
228  QgsFeatureRendererV2* renderer = layer()->rendererV2();
229 
230  mFilteredFeatures.clear();
231 
232  if ( !renderer )
233  {
234  QgsDebugMsg( "Cannot get renderer" );
235  return;
236  }
237 
238  const QgsMapSettings& ms = mCanvas->mapSettings();
239  if ( layer()->hasScaleBasedVisibility() &&
240  ( layer()->minimumScale() > ms.scale() ||
241  layer()->maximumScale() <= ms.scale() ) )
242  {
243  QgsDebugMsg( "Out of scale limits" );
244  }
245  else
246  {
247  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
248  {
249  // setup scale
250  // mapRenderer()->renderContext()->scale is not automaticaly updated when
251  // render extent changes (because it's scale is used to identify if changed
252  // since last render) -> use local context
253  renderContext.setExtent( ms.visibleExtent() );
254  renderContext.setMapToPixel( ms.mapToPixel() );
255  renderContext.setRendererScale( ms.scale() );
256  }
257 
258  filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
259  }
260 
261  renderer->startRender( renderContext, layer()->pendingFields() );
262 
263  QgsFeatureIterator features = masterModel()->layerCache()->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setFilterRect( rect ) );
264 
265  QgsFeature f;
266 
267  while ( features.nextFeature( f ) )
268  {
269  if ( !filter || renderer->willRenderFeature( f ) )
270  {
271  mFilteredFeatures << f.id();
272  }
273 #if 0
274  if ( t.elapsed() > 5000 )
275  {
276  bool cancel = false;
277  emit progress( i, cancel );
278  if ( cancel )
279  break;
280 
281  t.restart();
282  }
283 #endif
284  }
285 
286  features.close();
287 
288  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
289  {
290  renderer->stopRender( renderContext );
291  }
292 }
293 
295 {
296  return masterModel()->rowToId( mapToSource( row ).row() );
297 }
298 
300 {
301  return mapFromMaster( masterModel()->idToIndex( fid ) );
302 }
303 
305 {
306  QModelIndexList indexes;
307  foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) )
308  {
309  indexes.append( mapFromMaster( idx ) );
310  }
311 
312  return indexes;
313 }
314 
315 QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
316 {
317  // Master is source
318  return mapToSource( proxyIndex );
319 }
320 
321 QModelIndex QgsAttributeTableFilterModel::mapFromMaster( const QModelIndex &sourceIndex ) const
322 {
323  // Master is source
324  return mapFromSource( sourceIndex );
325 }
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.
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
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:326
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
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:114
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:105
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
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)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
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.