Skip to content

Commit

Permalink
Ensure that dataChanged signal is raised for DisplayRole in
Browse files Browse the repository at this point in the history
QgsAttributeTableModel when a feature attribute is changed

Otherwise the attribute table will show the outdated value
until it is repainted

(cherry picked from commit 98afd4b)
  • Loading branch information
nyalldawson committed Dec 20, 2022
1 parent 3565fd1 commit d211a9d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/gui/attributetable/qgsattributetablemodel.cpp
Expand Up @@ -344,7 +344,11 @@ void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, c
if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
{
if ( loadFeatureAtId( fid ) )
setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
{
const QModelIndex modelIndex = index( idToRow( fid ), fieldCol( idx ) );
setData( modelIndex, value, Qt::EditRole );
emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
}
}
else
{
Expand All @@ -360,7 +364,9 @@ void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, c
else
{
// Update representation
setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
const QModelIndex modelIndex = index( idToRow( fid ), fieldCol( idx ) );
setData( modelIndex, value, Qt::EditRole );
emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
}
}
else
Expand Down
57 changes: 57 additions & 0 deletions tests/src/python/test_qgsattributetablemodel.py
Expand Up @@ -21,9 +21,12 @@
QgsVectorLayer,
QgsVectorLayerCache,
QgsConditionalStyle,
QgsFeatureRequest
)
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtTest import QSignalSpy

from qgis.testing import (start_app,
unittest
)
Expand Down Expand Up @@ -106,7 +109,19 @@ def testEdit(self):

# change attribute value for a feature and commit
self.layer.startEditing()

spy = QSignalSpy(self.am.dataChanged)

self.layer.changeAttributeValue(fid, field_idx, new_value)

# ensure that dataChanged signal was raised
self.assertEqual(len(spy), 1)
self.assertEqual(spy[-1][0].row(), model_index.row())
self.assertEqual(spy[-1][0].column(), field_idx)
self.assertEqual(spy[-1][1].row(), model_index.row())
self.assertEqual(spy[-1][1].column(), field_idx)
self.assertEqual(spy[-1][2], [Qt.DisplayRole])

self.layer.commitChanges()

# check the feature in layer is good
Expand All @@ -117,6 +132,48 @@ def testEdit(self):
model_index = self.am.idToIndex(fid)
feature_model = self.am.feature(model_index)

def testEditWithFilter(self):
fid = 2
field_idx = 1
new_value = 334

# get the same feature from model and layer
feature = self.layer.getFeature(fid)
am = QgsAttributeTableModel(self.cache)
am.setRequest(QgsFeatureRequest().setFilterFid(fid))
am.loadLayer()

model_index = am.idToIndex(fid)
feature_model = am.feature(model_index)

# check that feature from layer and model are sync
self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx))

# change attribute value for a feature and commit
self.layer.startEditing()

spy = QSignalSpy(am.dataChanged)

self.layer.changeAttributeValue(fid, field_idx, new_value)

# ensure that dataChanged signal was raised
self.assertEqual(len(spy), 1)
self.assertEqual(spy[-1][0].row(), model_index.row())
self.assertEqual(spy[-1][0].column(), field_idx)
self.assertEqual(spy[-1][1].row(), model_index.row())
self.assertEqual(spy[-1][1].column(), field_idx)
self.assertEqual(spy[-1][2], [Qt.DisplayRole])

self.layer.commitChanges()

# check the feature in layer is good
feature = self.layer.getFeature(fid)
self.assertEqual(feature.attribute(field_idx), new_value)

# get the same feature from model and layer
model_index = am.idToIndex(fid)
feature_model = am.feature(model_index)

# check that index from layer and model are sync
self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx))

Expand Down

0 comments on commit d211a9d

Please sign in to comment.