Skip to content

Commit

Permalink
Avoid unnecessary layer reloads for attribute table
Browse files Browse the repository at this point in the history
On behalf of Faunalia, sponsored by ENEL

(cherry-picked from 6cd97d)
  • Loading branch information
nyalldawson committed Mar 7, 2017
1 parent dbd6538 commit dc2f6bb
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 35 deletions.
12 changes: 2 additions & 10 deletions python/gui/attributetable/qgsdualview.sip
Expand Up @@ -32,16 +32,8 @@ class QgsDualView : QStackedWidget
explicit QgsDualView( QWidget* parent /TransferThis/ = 0 );
virtual ~QgsDualView();

/**
* Has to be called to initialize the dual view.
*
* @param layer The layer which should be used to fetch features
* @param mapCanvas The mapCanvas (used for the FilterMode
* {@link QgsAttributeTableFilterModel::ShowVisible}
* @param request Use a modified request to limit the shown features
* @param context The context in which this view is shown
*/
void init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request = QgsFeatureRequest(), const QgsAttributeEditorContext& context = QgsAttributeEditorContext() );
void init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request = QgsFeatureRequest(), const QgsAttributeEditorContext& context = QgsAttributeEditorContext(),
bool loadFeatures = true );

/**
* Change the current view mode.
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsattributetabledialog.cpp
Expand Up @@ -157,7 +157,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
r.setFlags( QgsFeatureRequest::NoGeometry );

// Initialize dual view
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext );
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext, false );

QgsAttributeTableConfig config = mLayer->attributeTableConfig();
mMainView->setAttributeTableConfig( config );
Expand Down
51 changes: 29 additions & 22 deletions src/gui/attributetable/qgsdualview.cpp
Expand Up @@ -68,7 +68,7 @@ QgsDualView::QgsDualView( QWidget* parent )
connect( mFeatureList, SIGNAL( displayExpressionChanged( QString ) ), this, SLOT( previewExpressionChanged( QString ) ) );
}

void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context )
void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context, bool loadFeatures )
{
mMapCanvas = mapCanvas;

Expand All @@ -85,7 +85,7 @@ void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const Qg
connect( mTableView, SIGNAL( columnResized( int, int ) ), this, SLOT( tableColumnResized( int, int ) ) );

initLayerCache( !( request.flags() & QgsFeatureRequest::NoGeometry ) || !request.filterRect().isNull() );
initModels( mapCanvas, request );
initModels( mapCanvas, request, loadFeatures );

mConditionalFormatWidget->setLayer( mLayer );

Expand Down Expand Up @@ -238,9 +238,6 @@ QgsDualView::ViewMode QgsDualView::view() const

void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filterMode )
{
if ( mFilterModel->filterMode() == filterMode )
return;

// cleanup any existing connections
switch ( mFilterModel->filterMode() )
{
Expand All @@ -262,17 +259,23 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
QgsFeatureRequest r = mMasterModel->request();
bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible;

bool requiresTableReload = ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) // previous request was subset
|| ( needsGeometry && r.flags() & QgsFeatureRequest::NoGeometry ) // no geometry for last request
|| ( mMasterModel->rowCount() == 0 ); // no features

if ( !needsGeometry )
r.setFlags( r.flags() | QgsFeatureRequest::NoGeometry );
else
r.setFlags( r.flags() & ~( QgsFeatureRequest::NoGeometry ) );
r.setFilterFids( QgsFeatureIds() );
r.setFilterRect( QgsRectangle() );
r.disableFilter();

// setup new connections and filter request parameters
switch ( filterMode )
{
case QgsAttributeTableFilterModel::ShowVisible:
connect( mMapCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentChanged() ) );
r.setFilterFids( QgsFeatureIds() );
r.disableFilter();
if ( mMapCanvas )
{
QgsRectangle rect = mMapCanvas->mapSettings().mapToLayerCoordinates( mLayer, mMapCanvas->extent() );
Expand All @@ -283,23 +286,23 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
case QgsAttributeTableFilterModel::ShowAll:
case QgsAttributeTableFilterModel::ShowEdited:
case QgsAttributeTableFilterModel::ShowFilteredList:
r.setFilterFids( QgsFeatureIds() );
r.disableFilter();
break;

case QgsAttributeTableFilterModel::ShowSelected:
connect( masterModel()->layer(), SIGNAL( selectionChanged() ), this, SLOT( updateSelectedFeatures() ) );
if ( masterModel()->layer()->selectedFeatureCount() > 0 )
r.setFilterFids( masterModel()->layer()->selectedFeaturesIds() );
else
r.disableFilter();
break;
}

mMasterModel->setRequest( r );
whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
mMasterModel->loadLayer();
if ( requiresTableReload )
{
mMasterModel->setRequest( r );
whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
mMasterModel->loadLayer();
}

//update filter model
mFilterModel->setFilterMode( filterMode );
emit filterChanged();
}
Expand All @@ -318,12 +321,12 @@ void QgsDualView::initLayerCache( bool cacheGeometry )
mLayerCache->setCacheGeometry( cacheGeometry );
if ( 0 == cacheSize || 0 == ( QgsVectorDataProvider::SelectAtId & mLayer->dataProvider()->capabilities() ) )
{
connect( mLayerCache, SIGNAL(invalidated()), this, SLOT(rebuildFullLayerCache()) );
connect( mLayerCache, SIGNAL( invalidated() ), this, SLOT( rebuildFullLayerCache() ) );
rebuildFullLayerCache();
}
}

void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request )
void QgsDualView::initModels( QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, bool loadFeatures )
{
delete mFeatureListModel;
delete mFilterModel;
Expand All @@ -339,7 +342,8 @@ void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest&

connect( mConditionalFormatWidget, SIGNAL( rulesUpdated( QString ) ), mMasterModel, SLOT( fieldConditionalStyleChanged( QString ) ) );

mMasterModel->loadLayer();
if ( loadFeatures )
mMasterModel->loadLayer();

mFilterModel = new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );

Expand Down Expand Up @@ -714,8 +718,8 @@ void QgsDualView::zoomToCurrentFeature()

void QgsDualView::rebuildFullLayerCache()
{
connect( mLayerCache, SIGNAL(progress(int,bool&)), this, SLOT(progress(int,bool&)), Qt::UniqueConnection );
connect( mLayerCache, SIGNAL(finished()), this, SLOT(finished()), Qt::UniqueConnection );
connect( mLayerCache, SIGNAL( progress( int, bool& ) ), this, SLOT( progress( int, bool& ) ), Qt::UniqueConnection );
connect( mLayerCache, SIGNAL( finished() ), this, SLOT( finished() ), Qt::UniqueConnection );

mLayerCache->setFullCache( true );
}
Expand Down Expand Up @@ -746,6 +750,9 @@ void QgsDualView::sortByPreviewExpression()
void QgsDualView::updateSelectedFeatures()
{
QgsFeatureRequest r = mMasterModel->request();
if ( r.filterType() == QgsFeatureRequest::FilterNone && r.filterRect().isNull() )
return; // already requested all features

if ( masterModel()->layer()->selectedFeatureCount() > 0 )
r.setFilterFids( masterModel()->layer()->selectedFeaturesIds() );
else
Expand All @@ -757,13 +764,13 @@ void QgsDualView::updateSelectedFeatures()
void QgsDualView::extentChanged()
{
QgsFeatureRequest r = mMasterModel->request();
if ( mMapCanvas )
if ( mMapCanvas && ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) )
{
QgsRectangle rect = mMapCanvas->mapSettings().mapToLayerCoordinates( mLayer, mMapCanvas->extent() );
r.setFilterRect( rect );
mMasterModel->setRequest( r );
mMasterModel->loadLayer();
}
mMasterModel->setRequest( r );
mMasterModel->loadLayer();
}

void QgsDualView::featureFormAttributeChanged()
Expand Down
7 changes: 5 additions & 2 deletions src/gui/attributetable/qgsdualview.h
Expand Up @@ -80,8 +80,11 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
* {@link QgsAttributeTableFilterModel::ShowVisible}
* @param request Use a modified request to limit the shown features
* @param context The context in which this view is shown
* @param loadFeatures whether to initially load all features into the view. If set to
* false, limited features can later be loaded using setFilterMode()
*/
void init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request = QgsFeatureRequest(), const QgsAttributeEditorContext& context = QgsAttributeEditorContext() );
void init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request = QgsFeatureRequest(), const QgsAttributeEditorContext &context = QgsAttributeEditorContext(),
bool loadFeatures = true );

/**
* Change the current view mode.
Expand Down Expand Up @@ -326,7 +329,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas

private:
void initLayerCache( bool cacheGeometry );
void initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request );
void initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request, bool loadFeatures );

QgsAttributeEditorContext mEditorContext;
QgsAttributeTableModel* mMasterModel;
Expand Down

0 comments on commit dc2f6bb

Please sign in to comment.