Skip to content

Commit 53324bf

Browse files
committedMay 17, 2018
Update currently edited feature in attribute table when selection changes
It's a very common pitfall for people to toggle the selection instead of the edit selection in the form view of the attribute table. I've noticed clicking people repeatedly on the list because they know it's not reliably going to give them what they want. This change updates the active feature in the form view on a selection change if one of the selected entries is visible in the current filter.
1 parent 2f0fbc6 commit 53324bf

File tree

2 files changed

+89
-12
lines changed

2 files changed

+89
-12
lines changed
 

‎src/gui/attributetable/qgsfeaturelistview.cpp

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ void QgsFeatureListView::setModel( QgsFeatureListModel *featureListModel )
5858

5959
mFeatureSelectionModel = new QgsFeatureSelectionModel( featureListModel, featureListModel, mFeatureSelectionManager, this );
6060
setSelectionModel( mFeatureSelectionModel );
61+
connect( featureListModel->layerCache()->layer(), &QgsVectorLayer::selectionChanged, this, [ this ]()
62+
{
63+
ensureEditSelection( true );
64+
} );
6165

6266
if ( mItemDelegate && mItemDelegate->parent() == this )
6367
{
@@ -75,9 +79,9 @@ void QgsFeatureListView::setModel( QgsFeatureListModel *featureListModel )
7579
this, static_cast<void ( QgsFeatureListView::* )()>( &QgsFeatureListView::repaintRequested ) );
7680
connect( mCurrentEditSelectionModel, &QItemSelectionModel::selectionChanged, this, &QgsFeatureListView::editSelectionChanged );
7781
connect( mModel->layerCache()->layer(), &QgsVectorLayer::attributeValueChanged, this, [ = ] { repaintRequested(); } );
78-
connect( featureListModel, &QgsFeatureListModel::rowsRemoved, this, &QgsFeatureListView::ensureEditSelection );
79-
connect( featureListModel, &QgsFeatureListModel::rowsInserted, this, &QgsFeatureListView::ensureEditSelection );
80-
connect( featureListModel, &QgsFeatureListModel::modelReset, this, &QgsFeatureListView::ensureEditSelection );
82+
connect( featureListModel, &QgsFeatureListModel::rowsRemoved, this, [ this ]() { ensureEditSelection(); } );
83+
connect( featureListModel, &QgsFeatureListModel::rowsInserted, this, [ this ]() { ensureEditSelection(); } );
84+
connect( featureListModel, &QgsFeatureListModel::modelReset, this, [ this ]() { ensureEditSelection(); } );
8185
}
8286

8387
bool QgsFeatureListView::setDisplayExpression( const QString &expression )
@@ -334,17 +338,87 @@ void QgsFeatureListView::selectRow( const QModelIndex &index, bool anchor )
334338
mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
335339
}
336340

337-
void QgsFeatureListView::ensureEditSelection()
341+
void QgsFeatureListView::ensureEditSelection( bool inSelection )
338342
{
339-
QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
340-
// If there is no selection or an invalid selection (and there would be something we could select) : select it
341-
if ( ( selectedIndexes.isEmpty()
342-
|| mModel->mapFromMaster( selectedIndexes.first() ).row() == -1 )
343-
&& mModel->rowCount() )
343+
if ( !mModel->rowCount() )
344+
return;
345+
346+
const QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
347+
348+
// We potentially want a new edit selection
349+
// If we it should be in the feature selection
350+
// but we don't find a matching one we might
351+
// still stick to the old edit selection
352+
bool editSelectionUpdateRequested = false;
353+
// There is a valid selection available which we
354+
// could fall back to
355+
bool validEditSelectionAvailable = false;
356+
357+
if ( selectedIndexes.isEmpty() || mModel->mapFromMaster( selectedIndexes.first() ).row() == -1 )
358+
{
359+
validEditSelectionAvailable = false;
360+
}
361+
else
362+
{
363+
validEditSelectionAvailable = true;
364+
}
365+
366+
// If we want to force the edit selection to be within the feature selection
367+
// let's do some additional checks
368+
if ( inSelection )
369+
{
370+
// no valid edit selection, update anyway
371+
if ( !validEditSelectionAvailable )
372+
{
373+
editSelectionUpdateRequested = true;
374+
}
375+
else
376+
{
377+
// valid selection: update only if it's not in the feature selection
378+
const QgsFeatureIds selectedFids = layerCache()->layer()->selectedFeatureIds();
379+
380+
if ( !selectedFids.contains( mModel->idxToFid( mModel->mapFromMaster( selectedIndexes.first() ) ) ) )
381+
{
382+
editSelectionUpdateRequested = true;
383+
}
384+
}
385+
}
386+
else
387+
{
388+
// we don't care if the edit selection is in the feature selection?
389+
// well then, only update if there is no valid edit selection availble
390+
if ( !validEditSelectionAvailable )
391+
editSelectionUpdateRequested = true;
392+
}
393+
394+
if ( editSelectionUpdateRequested )
344395
{
345-
QTimer::singleShot( 0, this, [ this ]()
396+
QTimer::singleShot( 0, this, [ this, inSelection, validEditSelectionAvailable ]()
346397
{
347-
setEditSelection( mModel->mapToMaster( mModel->index( 0, 0 ) ), QItemSelectionModel::ClearAndSelect );
398+
int rowToSelect = -1;
399+
400+
if ( inSelection )
401+
{
402+
const QgsFeatureIds selectedFids = layerCache()->layer()->selectedFeatureIds();
403+
const int rowCount = mModel->rowCount();
404+
405+
for ( int i = 0; i < rowCount; i++ )
406+
{
407+
if ( selectedFids.contains( mModel->idxToFid( mModel->index( i, 0 ) ) ) )
408+
{
409+
rowToSelect = i;
410+
break;
411+
}
412+
413+
if ( rowToSelect == -1 && !validEditSelectionAvailable )
414+
rowToSelect = 0;
415+
}
416+
}
417+
else
418+
rowToSelect = 0;
419+
420+
if ( rowToSelect != -1 )
421+
setEditSelection( mModel->mapToMaster( mModel->index( rowToSelect, 0 ) ), QItemSelectionModel::ClearAndSelect );
348422
} );
349423
}
350424
}

‎src/gui/attributetable/qgsfeaturelistview.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,11 @@ class GUI_EXPORT QgsFeatureListView : public QListView
184184

185185
/**
186186
* Make sure, there is an edit selection. If there is none, choose the first item.
187+
* If \a inSelection is set to true, the edit selection is done in selected entries if
188+
* there is a selected entry visible.
189+
*
187190
*/
188-
void ensureEditSelection();
191+
void ensureEditSelection( bool inSelection = false );
189192

190193
private:
191194
void selectRow( const QModelIndex &index, bool anchor );

0 commit comments

Comments
 (0)
Please sign in to comment.