Skip to content

Commit

Permalink
Merge pull request #36188 from signedav/filterfix
Browse files Browse the repository at this point in the history
Avoid long loading in attribute table on model change
  • Loading branch information
signedav committed May 13, 2020
2 parents 250fa15 + c6823d8 commit 160063a
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 30 deletions.
Expand Up @@ -92,6 +92,16 @@ Gets a list of currently filtered feature ids
Set the filter mode the filter will use.

:param filterMode: Sets the current mode of the filter
%End

void disconnectFilterModeConnections();
%Docstring
Disconnect the connections set for the current filterMode
%End

void connectFilterModeConnections( FilterMode filterMode );
%Docstring
Disconnect the connections set for the new ``filterMode``
%End

FilterMode filterMode();
Expand Down Expand Up @@ -214,6 +224,16 @@ Emitted whenever the sort column is changed

:param column: The sort column
:param order: The sort order
%End

void featuresFiltered();
%Docstring
Emitted when the filtering of the features has been done
%End

void visibleReloaded();
%Docstring
Emitted when the the visible features on extend are reloaded (the list is created)
%End

protected:
Expand Down
105 changes: 84 additions & 21 deletions src/gui/attributetable/qgsattributetablefiltermodel.cpp
Expand Up @@ -40,6 +40,11 @@ QgsAttributeTableFilterModel::QgsAttributeTableFilterModel( QgsMapCanvas *canvas
setDynamicSortFilter( true );
setSortRole( QgsAttributeTableModel::SortRole );
connect( layer(), &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableFilterModel::selectionChanged );

mReloadVisibleTimer.setSingleShot( true );
connect( &mReloadVisibleTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::reloadVisible );
mFilterFeaturesTimer.setSingleShot( true );
connect( &mFilterFeaturesTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::filterFeatures );
}

bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
Expand Down Expand Up @@ -318,32 +323,58 @@ void QgsAttributeTableFilterModel::setFilterMode( FilterMode filterMode )
{
if ( filterMode != mFilterMode )
{
if ( filterMode == ShowVisible )
{
connect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::reloadVisible );
connect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::reloadVisible );
generateListOfVisibleFeatures();
}
else
{
disconnect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::reloadVisible );
disconnect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::reloadVisible );
}

if ( filterMode == ShowFilteredList )
{
connect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::filterFeatures );
}
else
{
disconnect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::filterFeatures );
}

disconnectFilterModeConnections();
connectFilterModeConnections( filterMode );
mFilterMode = filterMode;
invalidateFilter();
}
}

void QgsAttributeTableFilterModel::disconnectFilterModeConnections()
{
// cleanup existing connections
switch ( mFilterMode )
{
case ShowVisible:
disconnect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
break;
case ShowAll:
case ShowEdited:
case ShowSelected:
break;
case ShowFilteredList:
disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
disconnect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
break;
}
}

void QgsAttributeTableFilterModel::connectFilterModeConnections( QgsAttributeTableFilterModel::FilterMode filterMode )
{
// setup new connections
switch ( filterMode )
{
case ShowVisible:
connect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
generateListOfVisibleFeatures();
break;
case ShowAll:
case ShowEdited:
case ShowSelected:
break;
case ShowFilteredList:
connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
connect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
break;
}
}

bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
{
Q_UNUSED( sourceParent )
Expand Down Expand Up @@ -398,6 +429,36 @@ void QgsAttributeTableFilterModel::reloadVisible()
{
generateListOfVisibleFeatures();
invalidateFilter();
emit visibleReloaded();
}

void QgsAttributeTableFilterModel::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
{
Q_UNUSED( fid );
Q_UNUSED( value );

if ( mFilterExpression.referencedAttributeIndexes( layer()->fields() ).contains( idx ) )
{
startTimedFilterFeatures();
}
}

void QgsAttributeTableFilterModel::onGeometryChanged()
{
if ( mFilterExpression.needsGeometry() )
{
startTimedFilterFeatures();
}
}

void QgsAttributeTableFilterModel::startTimedReloadVisible()
{
mReloadVisibleTimer.start( 10 );
}

void QgsAttributeTableFilterModel::startTimedFilterFeatures()
{
mFilterFeaturesTimer.start( 10 );
}

void QgsAttributeTableFilterModel::filterFeatures()
Expand Down Expand Up @@ -449,6 +510,8 @@ void QgsAttributeTableFilterModel::filterFeatures()
setFilteredFeatures( filteredFeatures );

QApplication::restoreOverrideCursor();

emit featuresFiltered();
}


Expand Down
26 changes: 26 additions & 0 deletions src/gui/attributetable/qgsattributetablefiltermodel.h
Expand Up @@ -127,6 +127,16 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
*/
void setFilterMode( FilterMode filterMode );

/**
* Disconnect the connections set for the current filterMode
*/
void disconnectFilterModeConnections();

/**
* Disconnect the connections set for the new \a filterMode
*/
void connectFilterModeConnections( FilterMode filterMode );

/**
* The current filterModel
*/
Expand Down Expand Up @@ -238,6 +248,16 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
*/
void sortColumnChanged( int column, Qt::SortOrder order );

/**
* Emitted when the filtering of the features has been done
*/
void featuresFiltered();

/**
* Emitted when the the visible features on extend are reloaded (the list is created)
*/
void visibleReloaded();

protected:

/**
Expand Down Expand Up @@ -282,6 +302,8 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
void selectionChanged();
void onColumnsChanged();
void reloadVisible();
void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
void onGeometryChanged();

private:
QgsFeatureIds mFilteredFeatures;
Expand All @@ -298,6 +320,10 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
int mapColumnToSource( int column ) const;
int mapColumnFromSource( int column ) const;

QTimer mReloadVisibleTimer;
QTimer mFilterFeaturesTimer;
void startTimedReloadVisible();
void startTimedFilterFeatures();
};

#endif
22 changes: 14 additions & 8 deletions src/gui/attributetable/qgsdualview.cpp
Expand Up @@ -270,11 +270,13 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
{
case QgsAttributeTableFilterModel::ShowVisible:
disconnect( mFilterModel->mapCanvas(), &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged );
disconnect( mFilterModel, &QgsAttributeTableFilterModel::visibleReloaded, this, &QgsDualView::filterChanged );
break;

case QgsAttributeTableFilterModel::ShowAll:
case QgsAttributeTableFilterModel::ShowEdited:
case QgsAttributeTableFilterModel::ShowFilteredList:
disconnect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QgsDualView::filterChanged );
break;

case QgsAttributeTableFilterModel::ShowSelected:
Expand Down Expand Up @@ -307,11 +309,13 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
r.setFilterRect( rect );
}
connect( mFilterModel, &QgsAttributeTableFilterModel::visibleReloaded, this, &QgsDualView::filterChanged );
break;

case QgsAttributeTableFilterModel::ShowAll:
case QgsAttributeTableFilterModel::ShowEdited:
case QgsAttributeTableFilterModel::ShowFilteredList:
connect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QgsDualView::filterChanged );
break;

case QgsAttributeTableFilterModel::ShowSelected:
Expand All @@ -320,14 +324,6 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
break;
}

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


// disable the browsing auto pan/scale if the list only shows visible items
switch ( filterMode )
{
Expand All @@ -343,6 +339,16 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
break;
}

if ( requiresTableReload )
{
//disconnect the connections of the current (old) filtermode before reload
mFilterModel->disconnectFilterModeConnections();

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

//update filter model
mFilterModel->setFilterMode( filterMode );
emit filterChanged();
Expand Down
5 changes: 4 additions & 1 deletion tests/src/app/testqgsattributetable.cpp
Expand Up @@ -428,6 +428,9 @@ void TestQgsAttributeTable::testFilteredFeatures()

std::unique_ptr< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( tempLayer.get(), QgsAttributeTableFilterModel::ShowAll ) );

QEventLoop loop;
connect( qobject_cast<QgsAttributeTableFilterModel *>( dlg->mMainView->mFilterModel ), &QgsAttributeTableFilterModel::featuresFiltered, &loop, &QEventLoop::quit );

// show all (three features)
dlg->mFeatureFilterWidget->filterShowAll();
QCOMPARE( dlg->mMainView->featureCount(), 3 );
Expand Down Expand Up @@ -463,7 +466,7 @@ void TestQgsAttributeTable::testFilteredFeatures()
f6.setAttribute( 1, 12 );
QVERIFY( tempLayer->addFeatures( QgsFeatureList() << f5 << f6 ) );
tempLayer->commitChanges();

loop.exec();
//no filter change -> now two of six features
QCOMPARE( dlg->mMainView->featureCount(), 6 );
QCOMPARE( dlg->mMainView->filteredFeatureCount(), 2 );
Expand Down
5 changes: 5 additions & 0 deletions tests/src/gui/testqgsdualview.cpp
Expand Up @@ -164,14 +164,19 @@ void TestQgsDualView::testFilterSelected()

void TestQgsDualView::testSelectAll()
{

QEventLoop loop;
connect( qobject_cast<QgsAttributeTableFilterModel *>( mDualView->mFilterModel ), &QgsAttributeTableFilterModel::visibleReloaded, &loop, &QEventLoop::quit );
mDualView->setFilterMode( QgsAttributeTableFilterModel::ShowVisible );
// Only show parts of the canvas, so only one selected feature is visible
mCanvas->setExtent( QgsRectangle( -139, 23, -100, 48 ) );
loop.exec();
mDualView->mTableView->selectAll();
QCOMPARE( mPointsLayer->selectedFeatureCount(), 10 );

mPointsLayer->selectByIds( QgsFeatureIds() );
mCanvas->setExtent( QgsRectangle( -110, 40, -100, 48 ) );
loop.exec();
mDualView->mTableView->selectAll();
QCOMPARE( mPointsLayer->selectedFeatureCount(), 1 );
}
Expand Down

0 comments on commit 160063a

Please sign in to comment.