Skip to content
Permalink
Browse files

Fix field formatter NULL representation

Fixes #28643
  • Loading branch information
elpaso committed Jan 30, 2020
1 parent 14e7316 commit 83e384a239de583d722af33efbf786a66c9cd57b
Showing with 178 additions and 3 deletions.
  1. +8 −1 src/core/qgsfieldformatter.cpp
  2. +170 −2 tests/src/python/test_qgsfieldformatters.py
@@ -30,7 +30,14 @@ QString QgsFieldFormatter::representValue( QgsVectorLayer *layer, int fieldIndex
if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginProvider && layer->dataProvider() )
defVal = layer->dataProvider()->defaultValueClause( layer->fields().fieldOriginIndex( fieldIndex ) );

return value == defVal ? defVal : layer->fields().at( fieldIndex ).displayString( value );
if ( layer->fields().exists( fieldIndex ) && ( defVal.isNull() || defVal != value ) )
{
return layer->fields().at( fieldIndex ).displayString( value );
}
else
{
return defVal;
}
}

QVariant QgsFieldFormatter::sortValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const
@@ -10,15 +10,20 @@
__date__ = '05/12/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'


import tempfile

import qgis # NOQA

from qgis.core import (QgsFeature, QgsProject, QgsRelation, QgsVectorLayer,
QgsValueMapFieldFormatter, QgsValueRelationFieldFormatter,
QgsRelationReferenceFieldFormatter, QgsRangeFieldFormatter,
QgsCheckBoxFieldFormatter, QgsSettings, QgsGeometry, QgsPointXY)
QgsCheckBoxFieldFormatter, QgsFallbackFieldFormatter,
QgsSettings, QgsGeometry, QgsPointXY, QgsVectorFileWriter)

from qgis.PyQt.QtCore import QCoreApplication, QLocale
from qgis.PyQt.QtCore import QCoreApplication, QLocale, QVariant
from qgis.testing import start_app, unittest
from utilities import writeShape

start_app()

@@ -391,5 +396,168 @@ def test_representValue(self):
self.assertEqual(field_formatter.representValue(layer, 1, {'UncheckedState': 'nooh', 'CheckedState': 'yeah'}, None, 'oops'), "(oops)")


class TestQgsFallbackFieldFormatter(unittest.TestCase):

@classmethod
def setUpClass(cls):
"""Run before all tests"""
QCoreApplication.setOrganizationName("QGIS_Test")
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsFieldFormatter.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsFieldFormatter")
QgsSettings().clear()
QLocale.setDefault(QLocale(QLocale.English))
start_app()

@classmethod
def tearDownClass(cls):
"""Reset locale"""
QLocale.setDefault(QLocale(QLocale.English))

def test_representValue(self):

def _test(layer, is_gpkg=False):

# Skip fid and precision tests
offset = 1 if is_gpkg else 0

fieldFormatter = QgsFallbackFieldFormatter()

QLocale.setDefault(QLocale('en'))

# Precision is ignored for integers and longlongs
self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, '123'), '123')
self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, '123000'), '123,000')
self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, '9999999'), '9,999,999')
self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, None), 'NULL')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '123'), '123')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '123000'), '123,000')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '9999999'), '9,999,999')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, None), 'NULL')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, None), 'NULL')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123'), '123.00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123'), '123')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, None), 'NULL')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123,000.00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123,000')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '0'), '0')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '0.127'), '0.127')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '1.27e-1'), '0.127')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-123'), '-123.00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-123'), '-123')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-0.127'), '-0.127')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-1.27e-1'), '-0.127')

# Check with Italian locale
QLocale.setDefault(QLocale('it'))

self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, '9999999'),
'9.999.999') # scientific notation for integers!
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '123'), '123')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '123000'), '123.000')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '9999999'), '9.999.999')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, None), 'NULL')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, None), 'NULL')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123.000,00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123.000')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '0'), '0')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123'), '123,00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123'), '123')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '0.127'), '0,127')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '1.27e-1'), '0,127')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-123'), '-123,00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-123'), '-123')

self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-0.127'), '-0,127')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '-1.27e-1'), '-0,127')

# Check with custom locale without thousand separator

custom = QLocale('en')
custom.setNumberOptions(QLocale.OmitGroupSeparator)
QLocale.setDefault(custom)

self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, '9999999'),
'9999999') # scientific notation for integers!
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '123'), '123')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, '9999999'), '9999999')

if not is_gpkg:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123000.00000')
else:
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, '123000'), '123000')

# Check string
self.assertEqual(fieldFormatter.representValue(layer, 3 + offset, {}, None, '123'), '123')
self.assertEqual(fieldFormatter.representValue(layer, 3 + offset, {}, None, 'a string'), 'a string')
self.assertEqual(fieldFormatter.representValue(layer, 3 + offset, {}, None, ''), '')
self.assertEqual(fieldFormatter.representValue(layer, 3 + offset, {}, None, None), 'NULL')

# Check NULLs (this is what happens in real life inside QGIS)
self.assertEqual(fieldFormatter.representValue(layer, 0 + offset, {}, None, QVariant(QVariant.String)), 'NULL')
self.assertEqual(fieldFormatter.representValue(layer, 1 + offset, {}, None, QVariant(QVariant.String)), 'NULL')
self.assertEqual(fieldFormatter.representValue(layer, 2 + offset, {}, None, QVariant(QVariant.String)), 'NULL')
self.assertEqual(fieldFormatter.representValue(layer, 3 + offset, {}, None, QVariant(QVariant.String)), 'NULL')

memory_layer = QgsVectorLayer("point?field=int:integer&field=double:double&field=long:long&field=string:string",
"layer", "memory")
self.assertTrue(memory_layer.isValid())

_test(memory_layer)

# Test a shapefile
shape_path = writeShape(memory_layer, 'test_qgsfieldformatters.shp')

shapefile_layer = QgsVectorLayer(shape_path, 'test', 'ogr')
self.assertTrue(shapefile_layer.isValid())

_test(shapefile_layer)

gpkg_path = tempfile.mktemp('.gpkg')

# Test a geopackage
_, _ = QgsVectorFileWriter.writeAsVectorFormat(
memory_layer,
gpkg_path,
'utf-8',
memory_layer.crs(),
'GPKG',
False,
[],
[],
False
)

gpkg_layer = QgsVectorLayer(gpkg_path, 'test', 'ogr')
self.assertTrue(gpkg_layer.isValid())

# No precision here
_test(gpkg_layer, True)


if __name__ == '__main__':
unittest.main()

0 comments on commit 83e384a

Please sign in to comment.
You can’t perform that action at this time.