Skip to content

Commit

Permalink
Move partial responsibility for filtering attribute table to
Browse files Browse the repository at this point in the history
dual view master model

This avoids requiring the table to load ALL features when the
table is set to just display selected or visible features

Dramatically improves load time of the attribute table when
working with large layers, so long as the table is set to
display selected features or visible features by default

On behalf of Faunalia, sponsored by ENEL
  • Loading branch information
nyalldawson committed Mar 5, 2017
1 parent 8a050de commit 4d8f886
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/app/qgsattributetabledialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QWidget

QgsFeatureRequest r;
bool needsGeom = false;
QgsAttributeTableFilterModel::FilterMode initialMode = static_cast< QgsAttributeTableFilterModel::FilterMode>( settings.value( QStringLiteral( "/qgis/attributeTableBehavior" ), QgsAttributeTableFilterModel::ShowAll ).toInt() );
if ( mLayer->geometryType() != QgsWkbTypes::NullGeometry &&
settings.value( QStringLiteral( "/qgis/attributeTableBehavior" ), QgsAttributeTableFilterModel::ShowAll ).toInt() == QgsAttributeTableFilterModel::ShowVisible )
initialMode == QgsAttributeTableFilterModel::ShowVisible )
{
QgsMapCanvas *mc = QgisApp::instance()->mapCanvas();
QgsRectangle extent( mc->mapSettings().mapToLayerCoordinates( layer, mc->extent() ) );
Expand All @@ -147,6 +148,11 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QWidget
mActionShowAllFilter->setText( tr( "Show All Features In Initial Canvas Extent" ) );
needsGeom = true;
}
else if ( initialMode == QgsAttributeTableFilterModel::ShowSelected )
{
if ( theLayer->selectedFeatureCount() > 0 )
r.setFilterFids( theLayer->selectedFeatureIds() );
}
if ( !needsGeom )
r.setFlags( QgsFeatureRequest::NoGeometry );

Expand Down
78 changes: 77 additions & 1 deletion src/gui/attributetable/qgsdualview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ QgsDualView::QgsDualView( QWidget *parent )

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

if ( !layer )
return;

Expand Down Expand Up @@ -192,15 +194,66 @@ QgsDualView::ViewMode QgsDualView::view() const

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

// cleanup any existing connections
switch ( mFilterModel->filterMode() )
{
case QgsAttributeTableFilterModel::ShowVisible:
disconnect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged );
break;

case QgsAttributeTableFilterModel::ShowAll:
case QgsAttributeTableFilterModel::ShowEdited:
case QgsAttributeTableFilterModel::ShowFilteredList:
break;

case QgsAttributeTableFilterModel::ShowSelected:
disconnect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
break;
}

QgsFeatureRequest r = mMasterModel->request();
bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible;

if ( !needsGeometry )
r.setFlags( r.flags() | QgsFeatureRequest::NoGeometry );
else
r.setFlags( r.flags() & ~( QgsFeatureRequest::NoGeometry ) );

switch ( filterMode )
{
case QgsAttributeTableFilterModel::ShowVisible:
connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged );
r.setFilterFids( QgsFeatureIds() );
r.disableFilter();
if ( mMapCanvas )
{
QgsRectangle rect = mMapCanvas->mapSettings().mapToLayerCoordinates( mLayer, mMapCanvas->extent() );
r.setFilterRect( rect );
}
break;

case QgsAttributeTableFilterModel::ShowAll:
case QgsAttributeTableFilterModel::ShowEdited:
case QgsAttributeTableFilterModel::ShowFilteredList:
r.setFilterFids( QgsFeatureIds() );
r.disableFilter();
break;

case QgsAttributeTableFilterModel::ShowSelected:
connect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
if ( masterModel()->layer()->selectedFeatureCount() > 0 )
r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
else
r.disableFilter();
break;
}

mMasterModel->setRequest( r );
whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
mMasterModel->loadLayer();

mFilterModel->setFilterMode( filterMode );
emit filterChanged();
Expand Down Expand Up @@ -649,6 +702,29 @@ void QgsDualView::sortByPreviewExpression()
setSortExpression( mFeatureList->displayExpression(), sortOrder );
}

void QgsDualView::updateSelectedFeatures()
{
QgsFeatureRequest r = mMasterModel->request();
if ( masterModel()->layer()->selectedFeatureCount() > 0 )
r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
else
r.disableFilter();
mMasterModel->setRequest( r );
mMasterModel->loadLayer();
}

void QgsDualView::extentChanged()
{
QgsFeatureRequest r = mMasterModel->request();
if ( mMapCanvas )
{
QgsRectangle rect = mMapCanvas->mapSettings().mapToLayerCoordinates( mLayer, mMapCanvas->extent() );
r.setFilterRect( rect );
}
mMasterModel->setRequest( r );
mMasterModel->loadLayer();
}

void QgsDualView::featureFormAttributeChanged()
{
mFeatureList->setCurrentFeatureEdited( true );
Expand Down
5 changes: 5 additions & 0 deletions src/gui/attributetable/qgsdualview.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas

void sortByPreviewExpression();

void updateSelectedFeatures();

void extentChanged();

/**
* Will be called whenever the currently shown feature form changes.
* Will forward this signal to the feature list to visually represent
Expand Down Expand Up @@ -343,6 +347,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
QString mDisplayExpression;
QgsAttributeTableConfig mConfig;
QScrollArea *mAttributeEditorScrollArea = nullptr;
QgsMapCanvas *mMapCanvas = nullptr;

friend class TestQgsDualView;
};
Expand Down

0 comments on commit 4d8f886

Please sign in to comment.