mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-10 00:04:23 -04:00
Merge pull request #52045 from signedav/yellow_index_lost
Fix lost index on selection change in Attribute Table
This commit is contained in:
commit
08c7d66e30
@ -34,6 +34,22 @@ QgsFeatureListView::QgsFeatureListView( QWidget *parent )
|
|||||||
: QListView( parent )
|
: QListView( parent )
|
||||||
{
|
{
|
||||||
setSelectionMode( QAbstractItemView::ExtendedSelection );
|
setSelectionMode( QAbstractItemView::ExtendedSelection );
|
||||||
|
|
||||||
|
mUpdateEditSelectionTimerWithSelection.setSingleShot( true );
|
||||||
|
connect( &mUpdateEditSelectionTimerWithSelection, &QTimer::timeout, this, [ this ]()
|
||||||
|
{
|
||||||
|
updateEditSelection( true );
|
||||||
|
} );
|
||||||
|
|
||||||
|
mUpdateEditSelectionTimerWithSelection.setInterval( 0 );
|
||||||
|
|
||||||
|
mUpdateEditSelectionTimerWithoutSelection.setSingleShot( true );
|
||||||
|
connect( &mUpdateEditSelectionTimerWithoutSelection, &QTimer::timeout, this, [ this ]()
|
||||||
|
{
|
||||||
|
updateEditSelection( false );
|
||||||
|
} );
|
||||||
|
|
||||||
|
mUpdateEditSelectionTimerWithoutSelection.setInterval( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsVectorLayerCache *QgsFeatureListView::layerCache()
|
QgsVectorLayerCache *QgsFeatureListView::layerCache()
|
||||||
@ -406,6 +422,19 @@ void QgsFeatureListView::selectRow( const QModelIndex &index, bool anchor )
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QgsFeatureListView::ensureEditSelection( bool inSelection )
|
void QgsFeatureListView::ensureEditSelection( bool inSelection )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( inSelection )
|
||||||
|
{
|
||||||
|
mUpdateEditSelectionTimerWithSelection.start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mUpdateEditSelectionTimerWithoutSelection.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsFeatureListView::updateEditSelection( bool inSelection )
|
||||||
{
|
{
|
||||||
if ( !mModel->rowCount() )
|
if ( !mModel->rowCount() )
|
||||||
{
|
{
|
||||||
@ -464,11 +493,6 @@ void QgsFeatureListView::ensureEditSelection( bool inSelection )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( editSelectionUpdateRequested )
|
if ( editSelectionUpdateRequested )
|
||||||
{
|
|
||||||
if ( !mUpdateEditSelectionTimer.isSingleShot() )
|
|
||||||
{
|
|
||||||
mUpdateEditSelectionTimer.setSingleShot( true );
|
|
||||||
connect( &mUpdateEditSelectionTimer, &QTimer::timeout, this, [ this, inSelection, validEditSelectionAvailable ]()
|
|
||||||
{
|
{
|
||||||
// The layer might have been removed between timer start and timer triggered
|
// The layer might have been removed between timer start and timer triggered
|
||||||
// in this case there is nothing left for us to do.
|
// in this case there is nothing left for us to do.
|
||||||
@ -501,10 +525,6 @@ void QgsFeatureListView::ensureEditSelection( bool inSelection )
|
|||||||
{
|
{
|
||||||
setEditSelection( mModel->mapToMaster( mModel->index( rowToSelect, 0 ) ), QItemSelectionModel::ClearAndSelect );
|
setEditSelection( mModel->mapToMaster( mModel->index( rowToSelect, 0 ) ), QItemSelectionModel::ClearAndSelect );
|
||||||
}
|
}
|
||||||
} );
|
|
||||||
mUpdateEditSelectionTimer.setInterval( 0 );
|
|
||||||
}
|
|
||||||
mUpdateEditSelectionTimer.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +234,8 @@ class GUI_EXPORT QgsFeatureListView : public QListView
|
|||||||
private:
|
private:
|
||||||
void selectRow( const QModelIndex &index, bool anchor );
|
void selectRow( const QModelIndex &index, bool anchor );
|
||||||
|
|
||||||
|
void updateEditSelection( bool inSelection = false );
|
||||||
|
|
||||||
enum PositionInList
|
enum PositionInList
|
||||||
{
|
{
|
||||||
First,
|
First,
|
||||||
@ -264,7 +266,8 @@ class GUI_EXPORT QgsFeatureListView : public QListView
|
|||||||
int mRowAnchor = 0;
|
int mRowAnchor = 0;
|
||||||
QItemSelectionModel::SelectionFlags mCtrlDragSelectionFlag;
|
QItemSelectionModel::SelectionFlags mCtrlDragSelectionFlag;
|
||||||
|
|
||||||
QTimer mUpdateEditSelectionTimer;
|
QTimer mUpdateEditSelectionTimerWithSelection;
|
||||||
|
QTimer mUpdateEditSelectionTimerWithoutSelection;
|
||||||
|
|
||||||
friend class QgsDualView;
|
friend class QgsDualView;
|
||||||
};
|
};
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include "qgsgui.h"
|
#include "qgsgui.h"
|
||||||
#include "qgseditorwidgetregistry.h"
|
#include "qgseditorwidgetregistry.h"
|
||||||
|
|
||||||
|
#include <QSignalSpy>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup UnitTests
|
* \ingroup UnitTests
|
||||||
* This is a unit test for the attribute table dialog
|
* This is a unit test for the attribute table dialog
|
||||||
@ -66,6 +68,7 @@ class TestQgsAttributeTable : public QObject
|
|||||||
void testStartMultiEditNoChanges();
|
void testStartMultiEditNoChanges();
|
||||||
void testMultiEditMakeUncommittedChanges();
|
void testMultiEditMakeUncommittedChanges();
|
||||||
void testInvalidView();
|
void testInvalidView();
|
||||||
|
void testEnsureEditSelection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QgisApp *mQgisApp = nullptr;
|
QgisApp *mQgisApp = nullptr;
|
||||||
@ -830,5 +833,68 @@ void TestQgsAttributeTable::testInvalidView()
|
|||||||
QCOMPARE( dlg->mMainView->filteredFeatures(), QgsFeatureIds() << 1 << 3 );
|
QCOMPARE( dlg->mMainView->filteredFeatures(), QgsFeatureIds() << 1 << 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsAttributeTable::testEnsureEditSelection()
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsVectorLayer > layer = std::make_unique< QgsVectorLayer >( QStringLiteral( "Point?field=col0:integer&field=col1:integer" ), QStringLiteral( "test" ), QStringLiteral( "memory" ) );
|
||||||
|
QVERIFY( layer->isValid() );
|
||||||
|
|
||||||
|
QgsFeature ft1( layer->dataProvider()->fields(), 1 );
|
||||||
|
ft1.setAttributes( QgsAttributes() << 1 << 2 );
|
||||||
|
layer->dataProvider()->addFeature( ft1 );
|
||||||
|
QgsFeature ft2( layer->dataProvider()->fields(), 2 );
|
||||||
|
ft2.setAttributes( QgsAttributes() << 3 << 4 );
|
||||||
|
layer->dataProvider()->addFeature( ft2 );
|
||||||
|
QgsFeature ft3( layer->dataProvider()->fields(), 3 );
|
||||||
|
ft3.setAttributes( QgsAttributes() << 5 << 6 );
|
||||||
|
layer->dataProvider()->addFeature( ft3 );
|
||||||
|
QgsFeature ft4( layer->dataProvider()->fields(), 4 );
|
||||||
|
ft4.setAttributes( QgsAttributes() << 7 << 8 );
|
||||||
|
layer->dataProvider()->addFeature( ft4 );
|
||||||
|
|
||||||
|
layer->removeSelection();
|
||||||
|
|
||||||
|
std::unique_ptr< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( layer.get() ) );
|
||||||
|
|
||||||
|
//since the update is done by timer, we have to wait (at least one millisecond) or until the current edit selection changed
|
||||||
|
qRegisterMetaType<QgsFeature>( "QgsFeature&" );
|
||||||
|
QSignalSpy spy( dlg->mMainView->mFeatureListView, &QgsFeatureListView::currentEditSelectionChanged );
|
||||||
|
|
||||||
|
// we set the index to ft3
|
||||||
|
dlg->mMainView->setCurrentEditSelection( {ft3.id()} );
|
||||||
|
// ... and the currentEditSelection is on ft3
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 3 ) );
|
||||||
|
|
||||||
|
// we make a featureselection on ft1, ft2 and ft3
|
||||||
|
layer->selectByIds( QgsFeatureIds() << 1 << 2 << 3 );
|
||||||
|
spy.wait( 1 );
|
||||||
|
// ... and the currentEditSelection stays on ft3 (since it's in the featureselection)
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 3 ) );
|
||||||
|
|
||||||
|
// we release the featureselection
|
||||||
|
layer->removeSelection();
|
||||||
|
spy.wait( 1 );
|
||||||
|
// ... and the currentEditSelection persists on 3 (since it does not make an update)
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 3 ) );
|
||||||
|
|
||||||
|
// we make afeatureselection on ft4
|
||||||
|
layer->selectByIds( QgsFeatureIds() << 4 );
|
||||||
|
spy.wait( 1 );
|
||||||
|
// ... and the currentEditSelection goes to ft4
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 4 ) );
|
||||||
|
|
||||||
|
// we make afeatureselection on ft2 and ft3
|
||||||
|
layer->selectByIds( QgsFeatureIds() << 2 << 3 );
|
||||||
|
spy.wait( 1 );
|
||||||
|
// ... and the currentEditSelection goes to the first one of the featureselection (means ft2)
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 2 ) );
|
||||||
|
|
||||||
|
// we reload the layer
|
||||||
|
layer->reload();
|
||||||
|
spy.wait( 1 );
|
||||||
|
// ... and the currentEditSelection jumps to the first one (instead of staying at 2, since it's NOT persistend)
|
||||||
|
QVERIFY( dlg->mMainView->mFeatureListView->currentEditSelection().contains( 1 ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsAttributeTable )
|
QGSTEST_MAIN( TestQgsAttributeTable )
|
||||||
#include "testqgsattributetable.moc"
|
#include "testqgsattributetable.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user