diff --git a/src/gui/attributetable/qgsattributetablemodel.cpp b/src/gui/attributetable/qgsattributetablemodel.cpp index 7c61243ded3..a22024db18d 100644 --- a/src/gui/attributetable/qgsattributetablemodel.cpp +++ b/src/gui/attributetable/qgsattributetablemodel.cpp @@ -1053,9 +1053,13 @@ void QgsAttributeTableModel::prefetchSortData( const QString &expressionString, widgetData = getWidgetData( cache.sortFieldIndex ); } - const QgsFeatureRequest request = QgsFeatureRequest( mFeatureRequest ) - .setFlags( Qgis::FeatureRequestFlag::NoGeometry ) - .setSubsetOfAttributes( cache.sortCacheAttributes ); + QgsFeatureRequest request = QgsFeatureRequest( mFeatureRequest ) + .setSubsetOfAttributes( cache.sortCacheAttributes ); + + // If expression does not need geometry set NoGeometry flag + if ( !cache.sortCacheExpression.needsGeometry() ) + request.setFlags( request.flags() | Qgis::FeatureRequestFlag::NoGeometry ); + QgsFeatureIterator it = mLayerCache->getFeatures( request ); QgsFeature f; @@ -1094,9 +1098,17 @@ QString QgsAttributeTableModel::sortCacheExpression( unsigned long cacheIndex ) void QgsAttributeTableModel::setRequest( const QgsFeatureRequest &request ) { - mFeatureRequest = request; - if ( mLayer && !mLayer->isSpatial() ) - mFeatureRequest.setFlags( mFeatureRequest.flags() | Qgis::FeatureRequestFlag::NoGeometry ); + if ( ! mFeatureRequest.compare( request ) ) + { + mFeatureRequest = request; + if ( mLayer && !mLayer->isSpatial() ) + mFeatureRequest.setFlags( mFeatureRequest.flags() | Qgis::FeatureRequestFlag::NoGeometry ); + // Prefetch data for sorting, resetting all caches + for ( unsigned long i = 0; i < mSortCaches.size(); ++i ) + { + prefetchSortData( sortCacheExpression( i ), i ); + } + } } const QgsFeatureRequest &QgsAttributeTableModel::request() const diff --git a/tests/src/python/test_qgsattributetablemodel.py b/tests/src/python/test_qgsattributetablemodel.py index 641626ec981..7e771b3bffe 100644 --- a/tests/src/python/test_qgsattributetablemodel.py +++ b/tests/src/python/test_qgsattributetablemodel.py @@ -25,12 +25,13 @@ from qgis.core import ( QgsGeometry, QgsMemoryProviderUtils, QgsPointXY, + QgsPoint, QgsProject, QgsVectorLayer, QgsVectorLayerCache, QgsVectorLayerExporter, ) -from qgis.gui import QgsAttributeTableModel, QgsEditorWidgetFactory, QgsGui +from qgis.gui import QgsAttributeTableModel, QgsAttributeTableFilterModel, QgsEditorWidgetFactory, QgsGui import unittest from qgis.testing import start_app, QgisTestCase @@ -401,6 +402,44 @@ class TestQgsAttributeTableModel(QgisTestCase): self.assertEqual(twf.widgetLoaded, 2) twf.widgetLoaded = 0 + def test_sort_requires_geometry(self): + layer = QgsVectorLayer("Linestring?field=fldint:integer", + "addfeat", "memory") + pr = layer.dataProvider() + features = list() + f = QgsFeature(layer.fields()) + f.setAttributes([2]) + f.setGeometry(QgsGeometry.fromPolyline([QgsPoint(0, 0), QgsPoint(1, 1)])) + features.append(f) + + f = QgsFeature(layer.fields()) + f.setAttributes([1]) + f.setGeometry(QgsGeometry.fromPolyline([QgsPoint(0, 0), QgsPoint(2, 2)])) + features.append(f) + + self.assertTrue(pr.addFeatures(features)) + cache = QgsVectorLayerCache(layer, 100) + am = QgsAttributeTableModel(cache) + am.loadLayer() + + fm = QgsAttributeTableFilterModel(None, am, am) + + fm.sort('"fldint"', Qt.SortOrder.AscendingOrder) + self.assertEqual(fm.data(fm.index(0, 0), Qt.DisplayRole), '1') + self.assertEqual(fm.data(fm.index(1, 0), Qt.DisplayRole), '2') + + fm.sort('"fldint"', Qt.SortOrder.DescendingOrder) + self.assertEqual(fm.data(fm.index(0, 0), Qt.DisplayRole), '2') + self.assertEqual(fm.data(fm.index(1, 0), Qt.DisplayRole), '1') + + fm.sort('$length', Qt.SortOrder.DescendingOrder) + self.assertEqual(fm.data(fm.index(0, 0), Qt.DisplayRole), '1') + self.assertEqual(fm.data(fm.index(1, 0), Qt.DisplayRole), '2') + + fm.sort('$length', Qt.SortOrder.AscendingOrder) + self.assertEqual(fm.data(fm.index(0, 0), Qt.DisplayRole), '2') + self.assertEqual(fm.data(fm.index(1, 0), Qt.DisplayRole), '1') + if __name__ == '__main__': unittest.main()