Skip to content
Permalink
Browse files

[needs-docs] Attribute table "show selected features" shows no features

when none are selected

This change is being driven by performance - the "show selected" mode
can be used to speed up the attribute table loading for large layers.
The current behaviour (showing ALL features when none are selected)
breaks this performance benefit, because if users accidently open
the table with no selection then they are forced to wait for the
entire table to load (sometimes takes hours on large tables/slow
connections).
  • Loading branch information
nyalldawson committed Mar 8, 2017
1 parent 95040c1 commit 41d5f309614d985a8c3338b4b02346abdfc64aee
@@ -144,8 +144,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QWidget
}
else if ( initialMode == QgsAttributeTableFilterModel::ShowSelected )
{
if ( layer->selectedFeatureCount() > 0 )
r.setFilterFids( layer->selectedFeatureIds() );
r.setFilterFids( layer->selectedFeatureIds() );
}
if ( !needsGeom )
r.setFlags( QgsFeatureRequest::NoGeometry );
@@ -311,7 +311,7 @@ bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModel
return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );

case ShowSelected:
return layer()->selectedFeatureIds().isEmpty() || layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );
return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );

case ShowVisible:
return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
@@ -245,8 +245,7 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter

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

@@ -718,10 +717,7 @@ void QgsDualView::updateSelectedFeatures()
if ( r.filterType() == QgsFeatureRequest::FilterNone && r.filterRect().isNull() )
return; // already requested all features

if ( masterModel()->layer()->selectedFeatureCount() > 0 )
r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
else
r.disableFilter();
r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
mMasterModel->setRequest( r );
mMasterModel->loadLayer();
emit filterChanged();
@@ -45,6 +45,7 @@ class TestQgsAttributeTable : public QObject
void testFieldCalculation();
void testFieldCalculationArea();
void testNoGeom();
void testSelected();

private:
QgisApp *mQgisApp = nullptr;
@@ -209,6 +210,43 @@ void TestQgsAttributeTable::testNoGeom()

}

void TestQgsAttributeTable::testSelected()
{
// test attribute table opening in show selected mode
QgsSettings s;

std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:3111&field=pk:int&field=col1:double" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
QVERIFY( tempLayer->isValid() );

QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
QgsFeature f2( tempLayer->dataProvider()->fields(), 2 );
QgsFeature f3( tempLayer->dataProvider()->fields(), 3 );
QVERIFY( tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 << f3 ) );

s.setValue( QStringLiteral( "/qgis/attributeTableBehavior" ), QgsAttributeTableFilterModel::ShowSelected );
std::unique_ptr< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( tempLayer.get() ) );

QVERIFY( !dlg->mMainView->masterModel()->layerCache()->cacheGeometry() );
//should be nothing - because no selection!
QCOMPARE( dlg->mMainView->masterModel()->request().filterType(), QgsFeatureRequest::FilterFids );
QVERIFY( dlg->mMainView->masterModel()->request().filterFids().isEmpty() );

// make a selection
tempLayer->selectByIds( QgsFeatureIds() << 1 << 3 );
QCOMPARE( dlg->mMainView->masterModel()->request().filterType(), QgsFeatureRequest::FilterFids );
QCOMPARE( dlg->mMainView->masterModel()->request().filterFids(), QgsFeatureIds() << 1 << 3 );

// another test - start with selection when dialog created
dlg.reset( new QgsAttributeTableDialog( tempLayer.get() ) );
QVERIFY( !dlg->mMainView->masterModel()->layerCache()->cacheGeometry() );
QCOMPARE( dlg->mMainView->masterModel()->request().filterType(), QgsFeatureRequest::FilterFids );
QCOMPARE( dlg->mMainView->masterModel()->request().filterFids(), QgsFeatureIds() << 1 << 3 );
// remove selection
tempLayer->removeSelection();
QCOMPARE( dlg->mMainView->masterModel()->request().filterType(), QgsFeatureRequest::FilterFids );
QVERIFY( dlg->mMainView->masterModel()->request().filterFids().isEmpty() );
}


QGSTEST_MAIN( TestQgsAttributeTable )
#include "testqgsattributetable.moc"
@@ -50,6 +50,7 @@ class TestQgsDualView : public QObject
void testColumnHeaders();

void testData();
void testFilterSelected();

void testSelectAll();

@@ -134,6 +135,36 @@ void TestQgsDualView::testData()
}
}

void TestQgsDualView::testFilterSelected()
{
QgsFeature feature;
QList< QgsFeatureId > ids;
QgsFeatureIterator it = mPointsLayer->getFeatures( QgsFeatureRequest().setOrderBy( QgsFeatureRequest::OrderBy() << QgsFeatureRequest::OrderByClause( "Heading" ) ) );
while ( it.nextFeature( feature ) )
ids << feature.id();

// select some features
QList< QgsFeatureId > selected;
selected << ids.at( 1 ) << ids.at( 3 );
mPointsLayer->selectByIds( selected.toSet() );

mDualView->setFilterMode( QgsAttributeTableFilterModel::ShowSelected );
QCOMPARE( mDualView->tableView()->model()->rowCount(), 2 );

int headingIdx = mPointsLayer->fields().lookupField( "Heading" );
QgsField fld = mPointsLayer->fields().at( headingIdx );
for ( int i = 0; i < selected.count(); ++i )
{
mPointsLayer->getFeatures( QgsFeatureRequest().setFilterFid( selected.at( i ) ) ).nextFeature( feature );
QModelIndex index = mDualView->tableView()->model()->index( i, headingIdx );
QCOMPARE( mDualView->tableView()->model()->data( index ).toString(), fld.displayString( feature.attribute( headingIdx ) ) );
}

// select none
mPointsLayer->removeSelection();
QCOMPARE( mDualView->tableView()->model()->rowCount(), 0 );
}

void TestQgsDualView::testSelectAll()
{
mDualView->setFilterMode( QgsAttributeTableFilterModel::ShowVisible );

0 comments on commit 41d5f30

Please sign in to comment.
You can’t perform that action at this time.