Skip to content

Commit 66fadee

Browse files
committedApr 18, 2013
[FIX #7609] Fetch and cache data for sorting column in one query
1 parent 046fbee commit 66fadee

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed
 

‎src/gui/attributetable/qgsattributetablefiltermodel.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QMod
8686
return false;
8787
}
8888

89+
void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
90+
{
91+
masterModel()->prefetchColumnData( column );
92+
QSortFilterProxyModel::sort( column, order );
93+
}
94+
8995
void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop )
9096
{
9197
if ( mSelectedOnTop != selectedOnTop )

‎src/gui/attributetable/qgsattributetablefiltermodel.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
142142
*/
143143
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;
144144

145+
/**
146+
* Sort by the given column using the given order.
147+
* Prefetches all the data from the layer to speed up sorting.
148+
*
149+
* @param column The column which should be sorted
150+
* @param order The order ( Qt::AscendingOrder or Qt::DescendingOrder )
151+
*/
152+
virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
153+
145154
public slots:
146155
/**
147156
* Is called upon every change of the visible extents on the map canvas.

‎src/gui/attributetable/qgsattributetablemodel.cpp

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayerCache *layerCache, QObject *parent )
3434
: QAbstractTableModel( parent )
3535
, mLayerCache( layerCache )
36+
, mCachedField( -1 )
3637
{
3738
QgsDebugMsg( "entered." );
3839

@@ -80,7 +81,7 @@ bool QgsAttributeTableModel::loadFeatureAtId( QgsFeatureId fid ) const
8081

8182
void QgsAttributeTableModel::featureDeleted( QgsFeatureId fid )
8283
{
83-
QgsDebugMsgLevel( QString( "deleted fid=%1 => row=%2" ).arg( fid ).arg( idToRow( fid ) ), 3 );
84+
prefetchColumnData( -1 ); // Invalidate cached column data
8485

8586
int row = idToRow( fid );
8687

@@ -131,8 +132,7 @@ bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &
131132

132133
void QgsAttributeTableModel::featureAdded( QgsFeatureId fid, bool newOperation )
133134
{
134-
QgsDebugMsgLevel( QString( "feature %1 added (%2, rows %3, ids %4)" ).arg( fid ).arg( newOperation ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
135-
135+
prefetchColumnData( -1 ); // Invalidate cached column data
136136
int n = mRowIdMap.size();
137137
if ( newOperation )
138138
beginInsertRows( QModelIndex(), n, n );
@@ -172,6 +172,9 @@ void QgsAttributeTableModel::layerDeleted()
172172

173173
void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
174174
{
175+
if ( mCachedField == idx )
176+
mFieldCache[ fid ] = value;
177+
175178
if ( fid == mFeat.id() )
176179
{
177180
mFeat.setValid( false );
@@ -483,17 +486,30 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
483486
return QVariant( Qt::AlignLeft );
484487
}
485488

489+
const QVariant* pVal = NULL;
490+
486491
// if we don't have the row in current cache, load it from layer first
487492
if ( mFeat.id() != rowId || !mFeat.isValid() )
488493
{
489-
if ( !loadFeatureAtId( rowId ) )
494+
if ( mCachedField == fieldId )
495+
{
496+
const QVariant& val = mFieldCache[rowId];
497+
pVal = &val;
498+
}
499+
else if ( !loadFeatureAtId( rowId ) )
490500
return QVariant( "ERROR" );
491501
}
492502

493-
if ( mFeat.id() != rowId )
503+
if ( pVal == NULL && mFeat.id() != rowId )
494504
return QVariant( "ERROR" );
495505

496-
const QVariant &val = mFeat.attribute( fieldId );
506+
if ( !pVal )
507+
{
508+
const QVariant& val = mFeat.attribute( fieldId );
509+
pVal =&val;
510+
}
511+
512+
const QVariant& val = *pVal;
497513

498514
// For sorting return unprocessed value
499515
if ( SortRole == role )
@@ -599,3 +615,30 @@ QgsFeature QgsAttributeTableModel::feature( const QModelIndex &idx ) const
599615

600616
return f;
601617
}
618+
619+
void QgsAttributeTableModel::prefetchColumnData( int column )
620+
{
621+
mFieldCache.clear();
622+
623+
if ( column == -1 )
624+
{
625+
mCachedField = -1;
626+
}
627+
else
628+
{
629+
int fieldId = mAttributes[ column ];
630+
const QgsFields& fields = layer()->pendingFields();
631+
QStringList fldNames;
632+
fldNames << fields[ fieldId ].name();
633+
634+
QgsFeatureIterator it = mLayerCache->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( fldNames, fields ) );
635+
636+
QgsFeature f;
637+
while ( it.nextFeature( f ) )
638+
{
639+
mFieldCache.insert( f.id(), f.attribute( fieldId ) );
640+
}
641+
642+
mCachedField = fieldId;
643+
}
644+
}

‎src/gui/attributetable/qgsattributetablemodel.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <QObject>
2323
#include <QHash>
2424
#include <QQueue>
25+
#include <QMap>
2526

2627
#include "qgsvectorlayer.h" // QgsAttributeList
2728
#include "qgsvectorlayercache.h"
@@ -173,9 +174,20 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
173174
void executeAction( int action, const QModelIndex &idx ) const;
174175

175176
/**
176-
* return feature attributes at given index */
177+
* Return the feature attributes at given model index
178+
* @return feature attributes at given model index
179+
*/
177180
QgsFeature feature( const QModelIndex &idx ) const;
178181

182+
/**
183+
* Caches the entire data for one column. This should be called prior to sorting,
184+
* so the data does not have to be fetched for every single comparison.
185+
* Specify -1 as column to invalidate the cache
186+
*
187+
* @param column The column index of the field to catch
188+
*/
189+
void prefetchColumnData( int column );
190+
179191
signals:
180192
/**
181193
* Model has been changed
@@ -245,6 +257,11 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
245257
virtual bool loadFeatureAtId( QgsFeatureId fid ) const;
246258

247259
QgsFeatureRequest mFeatureRequest;
260+
261+
/** The currently cached column */
262+
int mCachedField;
263+
/** Allows to cache one specific column (used for sorting) */
264+
QMap<QgsFeatureId, QVariant> mFieldCache;
248265
};
249266

250267

0 commit comments

Comments
 (0)
Please sign in to comment.