Skip to content

Commit

Permalink
Merge pull request #34293 from elpaso/bugfix-gh28643-NULL-representat…
Browse files Browse the repository at this point in the history
…ion-3_10

Merge pull request #34157 from elpaso/bugfix-gh28643-NULL-representation
  • Loading branch information
elpaso committed Feb 7, 2020
2 parents 68ad59b + 2004d86 commit 032ed31
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 3 deletions.
9 changes: 8 additions & 1 deletion src/core/qgsfieldformatter.cpp
Expand Up @@ -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 ) )
{
return defVal;
}
else
{
return layer->fields().at( fieldIndex ).displayString( value.isNull() ? defVal : value );
}
}

QVariant QgsFieldFormatter::sortValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const
Expand Down
172 changes: 170 additions & 2 deletions tests/src/python/test_qgsfieldformatters.py
Expand Up @@ -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()

Expand Down Expand Up @@ -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 032ed31

Please sign in to comment.