Skip to content

Commit

Permalink
Allow serialization of QgsProcessingFeatureSourceDefinition through Q…
Browse files Browse the repository at this point in the history
…gsXmlUtils
  • Loading branch information
nyalldawson committed Mar 24, 2020
1 parent 9500020 commit afbe727
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 0 deletions.
Expand Up @@ -75,6 +75,26 @@ the default geometry check method (as dictated by :py:class:`QgsProcessingContex

QgsFeatureRequest::InvalidGeometryCheck geometryCheck;

QVariant toVariant() const;
%Docstring
Saves this source definition to a QVariantMap, wrapped in a QVariant.
You can use QgsXmlUtils.writeVariant to save it to an XML document.

.. seealso:: :py:func:`loadVariant`

.. versionadded:: 3.14
%End

bool loadVariant( const QVariantMap &map );
%Docstring
Loads this source definition from a QVariantMap, wrapped in a QVariant.
You can use QgsXmlUtils.readVariant to load it from an XML document.

.. seealso:: :py:func:`toVariant`

.. versionadded:: 3.14
%End

bool operator==( const QgsProcessingFeatureSourceDefinition &other );

bool operator!=( const QgsProcessingFeatureSourceDefinition &other );
Expand Down
22 changes: 22 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -39,6 +39,28 @@
#include <functional>


QVariant QgsProcessingFeatureSourceDefinition::toVariant() const
{
QVariantMap map;
map.insert( QStringLiteral( "source" ), source.toVariant() );
map.insert( QStringLiteral( "selected_only" ), selectedFeaturesOnly );
map.insert( QStringLiteral( "feature_limit" ), featureLimit );
map.insert( QStringLiteral( "flags" ), static_cast< int >( flags ) );
map.insert( QStringLiteral( "geometry_check" ), static_cast< int >( geometryCheck ) );
return map;
}

bool QgsProcessingFeatureSourceDefinition::loadVariant( const QVariantMap &map )
{
source.loadVariant( map.value( QStringLiteral( "source" ) ) );
selectedFeaturesOnly = map.value( QStringLiteral( "selected_only" ), false ).toBool();
featureLimit = map.value( QStringLiteral( "feature_limit" ), -1 ).toLongLong();
flags = static_cast< Flags >( map.value( QStringLiteral( "flags" ), 0 ).toInt() );
geometryCheck = static_cast< QgsFeatureRequest::InvalidGeometryCheck >( map.value( QStringLiteral( "geometry_check" ), QgsFeatureRequest::GeometryAbortOnInvalid ).toInt() );
return true;
}


QVariant QgsProcessingOutputLayerDefinition::toVariant() const
{
QVariantMap map;
Expand Down
16 changes: 16 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -145,6 +145,22 @@ class CORE_EXPORT QgsProcessingFeatureSourceDefinition
*/
QgsFeatureRequest::InvalidGeometryCheck geometryCheck = QgsFeatureRequest::GeometryAbortOnInvalid;

/**
* Saves this source definition to a QVariantMap, wrapped in a QVariant.
* You can use QgsXmlUtils::writeVariant to save it to an XML document.
* \see loadVariant()
* \since QGIS 3.14
*/
QVariant toVariant() const;

/**
* Loads this source definition from a QVariantMap, wrapped in a QVariant.
* You can use QgsXmlUtils::readVariant to load it from an XML document.
* \see toVariant()
* \since QGIS 3.14
*/
bool loadVariant( const QVariantMap &map );

bool operator==( const QgsProcessingFeatureSourceDefinition &other )
{
return source == other.source
Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsxmlutils.cpp
Expand Up @@ -221,6 +221,13 @@ QDomElement QgsXmlUtils::writeVariant( const QVariant &value, QDomDocument &doc
element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingOutputLayerDefinition" ) );
break;
}
else if ( value.canConvert< QgsProcessingFeatureSourceDefinition >() )
{
QDomElement valueElement = writeVariant( value.value< QgsProcessingFeatureSourceDefinition >().toVariant(), doc );
element.appendChild( valueElement );
element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingFeatureSourceDefinition" ) );
break;
}
Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported user variant type %1" ).arg( QMetaType::typeName( value.userType() ) ).toLocal8Bit() );
break;
}
Expand Down Expand Up @@ -359,6 +366,18 @@ QVariant QgsXmlUtils::readVariant( const QDomElement &element )

return QVariant();
}
else if ( type == QLatin1String( "QgsProcessingFeatureSourceDefinition" ) )
{
QgsProcessingFeatureSourceDefinition res;
const QDomNodeList values = element.childNodes();
if ( values.isEmpty() )
return QVariant();

if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
return res;

return QVariant();
}
else
{
return QVariant();
Expand Down
10 changes: 10 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -7778,6 +7778,16 @@ void TestQgsProcessing::processingFeatureSource()
QVariant fsInVariant = QVariant::fromValue( fs );
QVERIFY( fsInVariant.isValid() );

// test converting to variant map and back
QVariant res = fs.toVariant();
QgsProcessingFeatureSourceDefinition dd;
QVERIFY( dd.loadVariant( res.toMap() ) );
QCOMPARE( dd.source.staticValue().toString(), sourceString );
QVERIFY( dd.selectedFeaturesOnly );
QCOMPARE( dd.featureLimit, 21 );
QCOMPARE( dd.flags, QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck );
QCOMPARE( dd.geometryCheck, QgsFeatureRequest::GeometrySkipInvalid );

QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( fsInVariant );
QCOMPARE( fromVar.source.staticValue().toString(), sourceString );
QVERIFY( fromVar.selectedFeaturesOnly );
Expand Down
22 changes: 22 additions & 0 deletions tests/src/python/test_qgsxmlutils.py
Expand Up @@ -14,8 +14,10 @@
from qgis.core import (QgsXmlUtils,
QgsProperty,
QgsGeometry,
QgsFeatureRequest,
QgsCoordinateReferenceSystem,
QgsProcessingOutputLayerDefinition,
QgsProcessingFeatureSourceDefinition,
NULL)

from qgis.PyQt.QtCore import QDateTime, QDate, QTime
Expand Down Expand Up @@ -242,6 +244,26 @@ def test_time(self):
c = QgsXmlUtils.readVariant(elem)
self.assertEqual(c, NULL)

def test_feature_source_definition(self):
"""
Test that QgsProcessingFeatureSourceDefinition values are correctly loaded and written
"""
doc = QDomDocument("properties")

definition = QgsProcessingFeatureSourceDefinition(QgsProperty.fromValue('my source'))
definition.selectedFeaturesOnly = True
definition.featureLimit = 27
definition.flags = QgsProcessingFeatureSourceDefinition.Flag.FlagCreateIndividualOutputPerInputFeature
definition.geometryCheck = QgsFeatureRequest.GeometrySkipInvalid

elem = QgsXmlUtils.writeVariant(definition, doc)
c = QgsXmlUtils.readVariant(elem)
self.assertEqual(c.source.staticValue(), 'my source')
self.assertTrue(c.selectedFeaturesOnly)
self.assertEqual(c.featureLimit, 27)
self.assertEqual(c.flags, QgsProcessingFeatureSourceDefinition.Flag.FlagCreateIndividualOutputPerInputFeature)
self.assertEqual(c.geometryCheck, QgsFeatureRequest.GeometrySkipInvalid)

def test_output_layer_definition(self):
"""
Test that QgsProcessingOutputLayerDefinition values are correctly loaded and written
Expand Down

0 comments on commit afbe727

Please sign in to comment.