From 10475a6adf370af634f47c67e3ca911d36f14fa0 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 8 May 2018 19:17:42 +1000 Subject: [PATCH] Really accept strings for arrow data defined properties --- python/core/symbology/qgssymbollayer.sip.in | 1 + .../core/symbology/qgssymbollayerutils.sip.in | 14 +++++ src/app/qgsmaptooloffsetpointsymbol.cpp | 1 + src/core/symbology/qgs25drenderer.cpp | 1 + src/core/symbology/qgsarrowsymbollayer.cpp | 9 +-- src/core/symbology/qgsellipsesymbollayer.cpp | 1 + src/core/symbology/qgssymbollayer.cpp | 1 + src/core/symbology/qgssymbollayer.h | 5 +- src/core/symbology/qgssymbollayerutils.cpp | 50 ++++++++++++++++ src/core/symbology/qgssymbollayerutils.h | 13 +++++ .../symbology/qgsvectorfieldsymbollayer.cpp | 1 + tests/src/core/testqgsproject.cpp | 2 +- tests/src/core/testqgssvgmarker.cpp | 1 + tests/src/python/test_qgssymbollayerutils.py | 58 ++++++++++++++++++- 14 files changed, 151 insertions(+), 7 deletions(-) diff --git a/python/core/symbology/qgssymbollayer.sip.in b/python/core/symbology/qgssymbollayer.sip.in index 5ac95333a8f..b9352a5d6d3 100644 --- a/python/core/symbology/qgssymbollayer.sip.in +++ b/python/core/symbology/qgssymbollayer.sip.in @@ -11,6 +11,7 @@ + class QgsSymbolLayer { diff --git a/python/core/symbology/qgssymbollayerutils.sip.in b/python/core/symbology/qgssymbollayerutils.sip.in index 20cf08337c3..a50bf6e7c75 100644 --- a/python/core/symbology/qgssymbollayerutils.sip.in +++ b/python/core/symbology/qgssymbollayerutils.sip.in @@ -55,6 +55,20 @@ class QgsSymbolLayerUtils static QString encodeSldBrushStyle( Qt::BrushStyle style ); static Qt::BrushStyle decodeSldBrushStyle( const QString &str ); + static QgsArrowSymbolLayer::HeadType decodeArrowHeadType( const QVariant &value, bool *ok /Out/ = 0 ); +%Docstring +Decodes a ``value`` representing an arrow head type. + +.. versionadded:: 3.2 +%End + + static QgsArrowSymbolLayer::ArrowType decodeArrowType( const QVariant &value, bool *ok /Out/ = 0 ); +%Docstring +Decodes a ``value`` representing an arrow type. + +.. versionadded:: 3.2 +%End + static QString encodePoint( QPointF point ); %Docstring Encodes a QPointF to a string. diff --git a/src/app/qgsmaptooloffsetpointsymbol.cpp b/src/app/qgsmaptooloffsetpointsymbol.cpp index e185f5b3523..ec64181cb08 100644 --- a/src/app/qgsmaptooloffsetpointsymbol.cpp +++ b/src/app/qgsmaptooloffsetpointsymbol.cpp @@ -24,6 +24,7 @@ #include "qgssymbollayer.h" #include "qgisapp.h" #include "qgsproperty.h" +#include "qgssymbollayerutils.h" #include #include diff --git a/src/core/symbology/qgs25drenderer.cpp b/src/core/symbology/qgs25drenderer.cpp index 9337dc5a281..d471313fe38 100644 --- a/src/core/symbology/qgs25drenderer.cpp +++ b/src/core/symbology/qgs25drenderer.cpp @@ -20,6 +20,7 @@ #include "qgseffectstack.h" #include "qgsgloweffect.h" #include "qgsproperty.h" +#include "qgssymbollayerutils.h" #define ROOF_EXPRESSION \ "translate(" \ diff --git a/src/core/symbology/qgsarrowsymbollayer.cpp b/src/core/symbology/qgsarrowsymbollayer.cpp index c2fe604b3eb..164a3cf3550 100644 --- a/src/core/symbology/qgsarrowsymbollayer.cpp +++ b/src/core/symbology/qgsarrowsymbollayer.cpp @@ -14,6 +14,7 @@ ***************************************************************************/ #include "qgsarrowsymbollayer.h" +#include "qgssymbollayerutils.h" QgsArrowSymbolLayer::QgsArrowSymbolLayer() { @@ -648,10 +649,10 @@ void QgsArrowSymbolLayer::_resolveDataDefined( QgsSymbolRenderContext &context ) { context.setOriginalValueVariable( headType() ); exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyArrowHeadType, context.renderContext().expressionContext() ); - int h = exprVal.toInt( &ok ); + HeadType h = QgsSymbolLayerUtils::decodeArrowHeadType( exprVal, &ok ); if ( ok ) { - mComputedHeadType = static_cast( h ); + mComputedHeadType = h; } } @@ -659,10 +660,10 @@ void QgsArrowSymbolLayer::_resolveDataDefined( QgsSymbolRenderContext &context ) { context.setOriginalValueVariable( arrowType() ); exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyArrowType, context.renderContext().expressionContext() ); - int h = exprVal.toInt( &ok ); + ArrowType h = QgsSymbolLayerUtils::decodeArrowType( exprVal, &ok ); if ( ok ) { - mComputedArrowType = static_cast( h ); + mComputedArrowType = h; } } } diff --git a/src/core/symbology/qgsellipsesymbollayer.cpp b/src/core/symbology/qgsellipsesymbollayer.cpp index b2a717dd8eb..b6fbf7c87b5 100644 --- a/src/core/symbology/qgsellipsesymbollayer.cpp +++ b/src/core/symbology/qgsellipsesymbollayer.cpp @@ -21,6 +21,7 @@ #include "qgslogger.h" #include "qgsunittypes.h" #include "qgsproperty.h" +#include "qgssymbollayerutils.h" #include #include diff --git a/src/core/symbology/qgssymbollayer.cpp b/src/core/symbology/qgssymbollayer.cpp index 9092a29d564..98d2983a119 100644 --- a/src/core/symbology/qgssymbollayer.cpp +++ b/src/core/symbology/qgssymbollayer.cpp @@ -25,6 +25,7 @@ #include "qgspainteffectregistry.h" #include "qgsproperty.h" #include "qgsexpressioncontext.h" +#include "qgssymbollayerutils.h" #include #include diff --git a/src/core/symbology/qgssymbollayer.h b/src/core/symbology/qgssymbollayer.h index 8996730facb..2bc1d12aac6 100644 --- a/src/core/symbology/qgssymbollayer.h +++ b/src/core/symbology/qgssymbollayer.h @@ -28,7 +28,6 @@ #include #include "qgssymbol.h" -#include "qgssymbollayerutils.h" // QgsStringMap #include "qgsfields.h" #include "qgspropertycollection.h" @@ -41,6 +40,10 @@ class QgsExpression; class QgsRenderContext; class QgsPaintEffect; +#ifndef SIP_RUN +typedef QMap QgsStringMap; +#endif + /** * \ingroup core * \class QgsSymbolLayer diff --git a/src/core/symbology/qgssymbollayerutils.cpp b/src/core/symbology/qgssymbollayerutils.cpp index cba9a60062b..69a1be03444 100644 --- a/src/core/symbology/qgssymbollayerutils.cpp +++ b/src/core/symbology/qgssymbollayerutils.cpp @@ -371,6 +371,56 @@ Qt::BrushStyle QgsSymbolLayerUtils::decodeSldBrushStyle( const QString &str ) return Qt::NoBrush; } +QgsArrowSymbolLayer::HeadType QgsSymbolLayerUtils::decodeArrowHeadType( const QVariant &value, bool *ok ) +{ + if ( ok ) + *ok = true; + + bool intOk = false; + QString s = value.toString().toLower().trimmed(); + if ( s == QLatin1String( "single" ) ) + return QgsArrowSymbolLayer::HeadSingle; + else if ( s == QLatin1String( "reversed" ) ) + return QgsArrowSymbolLayer::HeadReversed; + else if ( s == QLatin1String( "double" ) ) + return QgsArrowSymbolLayer::HeadDouble; + else if ( value.toInt() == 1 ) + return QgsArrowSymbolLayer::HeadReversed; + else if ( value.toInt() == 2 ) + return QgsArrowSymbolLayer::HeadDouble; + else if ( value.toInt( &intOk ) == 0 && intOk ) + return QgsArrowSymbolLayer::HeadSingle; + + if ( ok ) + *ok = false; + return QgsArrowSymbolLayer::HeadSingle; +} + +QgsArrowSymbolLayer::ArrowType QgsSymbolLayerUtils::decodeArrowType( const QVariant &value, bool *ok ) +{ + if ( ok ) + *ok = true; + + bool intOk = false; + QString s = value.toString().toLower().trimmed(); + if ( s == QLatin1String( "plain" ) ) + return QgsArrowSymbolLayer::ArrowPlain; + else if ( s == QLatin1String( "lefthalf" ) ) + return QgsArrowSymbolLayer::ArrowLeftHalf; + else if ( s == QLatin1String( "righthalf" ) ) + return QgsArrowSymbolLayer::ArrowRightHalf; + else if ( value.toInt() == 1 ) + return QgsArrowSymbolLayer::ArrowLeftHalf; + else if ( value.toInt() == 2 ) + return QgsArrowSymbolLayer::ArrowRightHalf; + else if ( value.toInt( &intOk ) == 0 && intOk ) + return QgsArrowSymbolLayer::ArrowPlain; + + if ( ok ) + *ok = false; + return QgsArrowSymbolLayer::ArrowPlain; +} + QString QgsSymbolLayerUtils::encodePoint( QPointF point ) { return QStringLiteral( "%1,%2" ).arg( qgsDoubleToString( point.x() ), qgsDoubleToString( point.y() ) ); diff --git a/src/core/symbology/qgssymbollayerutils.h b/src/core/symbology/qgssymbollayerutils.h index ee7573d0896..41ac99a321d 100644 --- a/src/core/symbology/qgssymbollayerutils.h +++ b/src/core/symbology/qgssymbollayerutils.h @@ -29,6 +29,7 @@ #include "qgis.h" #include "qgsmapunitscale.h" #include "qgscolorramp.h" +#include "qgsarrowsymbollayer.h" class QgsExpression; class QgsPathResolver; @@ -87,6 +88,18 @@ class CORE_EXPORT QgsSymbolLayerUtils static QString encodeSldBrushStyle( Qt::BrushStyle style ); static Qt::BrushStyle decodeSldBrushStyle( const QString &str ); + /** + * Decodes a \a value representing an arrow head type. + * \since QGIS 3.2 + */ + static QgsArrowSymbolLayer::HeadType decodeArrowHeadType( const QVariant &value, bool *ok SIP_OUT = nullptr ); + + /** + * Decodes a \a value representing an arrow type. + * \since QGIS 3.2 + */ + static QgsArrowSymbolLayer::ArrowType decodeArrowType( const QVariant &value, bool *ok SIP_OUT = nullptr ); + /** * Encodes a QPointF to a string. * \see decodePoint() diff --git a/src/core/symbology/qgsvectorfieldsymbollayer.cpp b/src/core/symbology/qgsvectorfieldsymbollayer.cpp index 4fe46c3b9a2..30b054b2037 100644 --- a/src/core/symbology/qgsvectorfieldsymbollayer.cpp +++ b/src/core/symbology/qgsvectorfieldsymbollayer.cpp @@ -18,6 +18,7 @@ #include "qgsvectorfieldsymbollayer.h" #include "qgsvectorlayer.h" #include "qgsunittypes.h" +#include "qgssymbollayerutils.h" QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer() { diff --git a/tests/src/core/testqgsproject.cpp b/tests/src/core/testqgsproject.cpp index 9e2f37abdc0..5ddb5b7705d 100644 --- a/tests/src/core/testqgsproject.cpp +++ b/tests/src/core/testqgsproject.cpp @@ -24,7 +24,7 @@ #include "qgssettings.h" #include "qgsunittypes.h" #include "qgsvectorlayer.h" - +#include "qgssymbollayerutils.h" class TestQgsProject : public QObject { diff --git a/tests/src/core/testqgssvgmarker.cpp b/tests/src/core/testqgssvgmarker.cpp index 651e0b89391..6b1d098a13a 100644 --- a/tests/src/core/testqgssvgmarker.cpp +++ b/tests/src/core/testqgssvgmarker.cpp @@ -32,6 +32,7 @@ #include #include "qgsmarkersymbollayer.h" #include "qgsproperty.h" +#include "qgssymbollayerutils.h" //qgis test includes #include "qgsrenderchecker.h" diff --git a/tests/src/python/test_qgssymbollayerutils.py b/tests/src/python/test_qgssymbollayerutils.py index 488cfb12063..0e67d091b0c 100644 --- a/tests/src/python/test_qgssymbollayerutils.py +++ b/tests/src/python/test_qgssymbollayerutils.py @@ -14,7 +14,9 @@ __revision__ = '$Format:%H$' import qgis # NOQA -from qgis.core import QgsSymbolLayerUtils, QgsMarkerSymbol +from qgis.core import (QgsSymbolLayerUtils, + QgsMarkerSymbol, + QgsArrowSymbolLayer) from qgis.PyQt.QtGui import QColor from qgis.PyQt.QtCore import QSizeF, QPointF from qgis.testing import unittest, start_app @@ -52,6 +54,60 @@ class PyQgsSymbolLayerUtils(unittest.TestCase): s2 = QgsSymbolLayerUtils.decodePoint('') self.assertEqual(s2, QPointF()) + def testDecodeArrowHeadType(self): + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(0) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('single') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(' SINGLE ') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(1) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadReversed) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('reversed') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadReversed) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(2) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadDouble) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('double') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.HeadDouble) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('xxxxx') + self.assertFalse(ok) + type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(34) + self.assertFalse(ok) + + def testDecodeArrowType(self): + type, ok = QgsSymbolLayerUtils.decodeArrowType(0) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) + type, ok = QgsSymbolLayerUtils.decodeArrowType('plain') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) + type, ok = QgsSymbolLayerUtils.decodeArrowType(' PLAIN ') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) + type, ok = QgsSymbolLayerUtils.decodeArrowType(1) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowLeftHalf) + type, ok = QgsSymbolLayerUtils.decodeArrowType('lefthalf') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowLeftHalf) + type, ok = QgsSymbolLayerUtils.decodeArrowType(2) + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowRightHalf) + type, ok = QgsSymbolLayerUtils.decodeArrowType('righthalf') + self.assertTrue(ok) + self.assertEqual(type, QgsArrowSymbolLayer.ArrowRightHalf) + type, ok = QgsSymbolLayerUtils.decodeArrowType('xxxxx') + self.assertFalse(ok) + type, ok = QgsSymbolLayerUtils.decodeArrowType(34) + self.assertFalse(ok) + def testSymbolToFromMimeData(self): """ Test converting symbols to and from mime data