[FEATURE] Boolean field support for memory layers

Adds support for boolean field types to memory layers

Fixes #20844
This commit is contained in:
Nyall Dawson 2018-12-20 15:13:30 +10:00
parent 497a53b9fa
commit 055a166136
3 changed files with 51 additions and 1 deletions

View File

@ -94,6 +94,9 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
// string types
<< QgsVectorDataProvider::NativeType( tr( "Text, unlimited length (text)" ), QStringLiteral( "text" ), QVariant::String, -1, -1, -1, -1 )
// boolean
<< QgsVectorDataProvider::NativeType( tr( "Boolean" ), QStringLiteral( "bool" ), QVariant::Bool )
// blob
<< QgsVectorDataProvider::NativeType( tr( "Binary object (BLOB)" ), QStringLiteral( "binary" ), QVariant::ByteArray )
@ -103,7 +106,7 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
{
QList<QgsField> attributes;
QRegExp reFieldDef( "\\:"
"(int|integer|long|int8|real|double|string|date|time|datetime|binary)" // type
"(int|integer|long|int8|real|double|string|date|time|datetime|binary|bool|boolean)" // type
"(?:\\((\\-?\\d+)" // length
"(?:\\,(\\d+))?" // precision
"\\))?(\\[\\])?" // array
@ -160,6 +163,12 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
typeName = QStringLiteral( "datetime" );
length = -1;
}
else if ( typeName == QLatin1String( "bool" ) || typeName == QLatin1String( "boolean" ) )
{
type = QVariant::Bool;
typeName = QStringLiteral( "boolean" );
length = -1;
}
else if ( typeName == QLatin1String( "binary" ) )
{
type = QVariant::ByteArray;
@ -453,6 +462,7 @@ bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes )
case QVariant::LongLong:
case QVariant::StringList:
case QVariant::List:
case QVariant::Bool:
case QVariant::ByteArray:
break;
default:

View File

@ -47,6 +47,9 @@ QString memoryLayerFieldType( QVariant::Type type )
case QVariant::ByteArray:
return QStringLiteral( "binary" );
case QVariant::Bool:
return QStringLiteral( "boolean" );
default:
break;
}

View File

@ -411,6 +411,7 @@ class TestPyQgsMemoryProvider(unittest.TestCase, ProviderTestCase):
fields.append(QgsField("#complex_name", QVariant.String))
fields.append(QgsField("complex/name", QVariant.String))
fields.append(QgsField("binaryfield", QVariant.ByteArray))
fields.append(QgsField("boolfield", QVariant.Bool))
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
self.assertTrue(layer.isValid())
self.assertFalse(layer.fields().isEmpty())
@ -550,6 +551,42 @@ class TestPyQgsMemoryProvider(unittest.TestCase, ProviderTestCase):
f2 = [f for f in dp.getFeatures()][1]
self.assertEqual(f2.attributes(), [2, NULL, bin_val2])
def testBool(self):
vl = QgsVectorLayer(
'Point?crs=epsg:4326&field=f1:integer&field=f2:bool',
'test', 'memory')
self.assertTrue(vl.isValid())
dp = vl.dataProvider()
fields = dp.fields()
self.assertEqual([f.name() for f in fields], ['f1', 'f2'])
self.assertEqual([f.type() for f in fields], [QVariant.Int, QVariant.Bool])
self.assertEqual([f.typeName() for f in fields], ['integer', 'boolean'])
f = QgsFeature(dp.fields())
f.setAttributes([1, True])
f2 = QgsFeature(dp.fields())
f2.setAttributes([2, False])
f3 = QgsFeature(dp.fields())
f3.setAttributes([3, NULL])
self.assertTrue(dp.addFeatures([f, f2, f3]))
self.assertEqual([f.attributes() for f in dp.getFeatures()], [[1, True], [2, False], [3, NULL]])
# add boolean field
self.assertTrue(dp.addAttributes([QgsField('boolfield2', QVariant.Bool, 'Boolean')]))
fields = dp.fields()
bool2_field = fields[fields.lookupField('boolfield2')]
self.assertEqual(bool2_field.type(), QVariant.Bool)
self.assertEqual(bool2_field.typeName(), 'Boolean')
f = QgsFeature(fields)
f.setAttributes([2, NULL, True])
self.assertTrue(dp.addFeature(f))
self.assertEqual([f.attributes() for f in dp.getFeatures()], [[1, True, NULL], [2, False, NULL], [3, NULL, NULL], [2, NULL, True]])
class TestPyQgsMemoryProviderIndexed(unittest.TestCase, ProviderTestCase):