From 9116a1a1815e28ca3db5f640bb69ba65c7867d63 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Tue, 15 Dec 2020 11:47:44 +0100 Subject: [PATCH] add a simple class to hold parameters information this makes it more futureproof to introduce type (string/number) or domain (attribute vs node value) --- .../symbology/qgsmarkersymbollayer.sip.in | 14 +++++ .../symbology/qgssvgcache.sip.in | 8 +-- .../symbology/qgssvgparameter.sip.in | 60 +++++++++++++++++++ python/core/core_auto.sip | 1 + src/core/CMakeLists.txt | 1 + src/core/layout/qgslayoutitempicture.cpp | 4 +- src/core/symbology/qgsmarkersymbollayer.h | 14 +++++ src/core/symbology/qgssvgcache.cpp | 26 ++++---- src/core/symbology/qgssvgcache.h | 19 +++--- src/core/symbology/qgssvgparameter.h | 56 +++++++++++++++++ tests/src/core/testqgssvgcache.cpp | 3 +- 11 files changed, 177 insertions(+), 29 deletions(-) create mode 100644 python/core/auto_generated/symbology/qgssvgparameter.sip.in create mode 100644 src/core/symbology/qgssvgparameter.h diff --git a/python/core/auto_generated/symbology/qgsmarkersymbollayer.sip.in b/python/core/auto_generated/symbology/qgsmarkersymbollayer.sip.in index 4a593261842..0a8a8fda6e9 100644 --- a/python/core/auto_generated/symbology/qgsmarkersymbollayer.sip.in +++ b/python/core/auto_generated/symbology/qgsmarkersymbollayer.sip.in @@ -656,6 +656,20 @@ if the value set is lower or equal to 0 the aspect ratio will be preserved in re double strokeWidth() const; void setStrokeWidth( double w ); + QgsSvgParameters parameters() const; +%Docstring +Returns the dynamic SVG parameters + +.. versionadded:: 3.18 +%End + + void setParameters( const QgsSvgParameters ¶meters ); +%Docstring +Sets the dynamic SVG parameters + +.. versionadded:: 3.18 +%End + void setStrokeWidthUnit( QgsUnitTypes::RenderUnit unit ); %Docstring Sets the units for the stroke width. diff --git a/python/core/auto_generated/symbology/qgssvgcache.sip.in b/python/core/auto_generated/symbology/qgssvgcache.sip.in index dce49c11eb8..8081d442e80 100644 --- a/python/core/auto_generated/symbology/qgssvgcache.sip.in +++ b/python/core/auto_generated/symbology/qgssvgcache.sip.in @@ -49,7 +49,7 @@ Constructor for QgsSvgCache. QImage svgAsImage( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio = 0, bool blocking = false, - const QMap ¶meters = QMap() ); + const QgsSvgParameters ¶meters = QgsSvgParameters() ); %Docstring Returns an SVG drawing as a QImage. @@ -72,7 +72,7 @@ Returns an SVG drawing as a QImage. QPicture svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput = false, double fixedAspectRatio = 0, bool blocking = false, - const QMap ¶meters = QMap() ); + const QgsSvgParameters ¶meters = QgsSvgParameters() ); %Docstring Returns an SVG drawing as a QPicture. @@ -102,7 +102,7 @@ Returns an SVG drawing as a QPicture. %End QSizeF svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap ¶meters = QMap() ); + double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QgsSvgParameters ¶meters = QgsSvgParameters() ); %Docstring Calculates the viewbox size of a (possibly cached) SVG file. @@ -195,7 +195,7 @@ in the same thread to ensure provided the remote content. %End QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap ¶meters = QMap() ); + double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QgsSvgParameters ¶meters = QgsSvgParameters() ); %Docstring Gets the SVG content corresponding to the given ``path``. diff --git a/python/core/auto_generated/symbology/qgssvgparameter.sip.in b/python/core/auto_generated/symbology/qgssvgparameter.sip.in new file mode 100644 index 00000000000..1c5e3f6611c --- /dev/null +++ b/python/core/auto_generated/symbology/qgssvgparameter.sip.in @@ -0,0 +1,60 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/symbology/qgssvgparameter.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + +class QgsSvgParameter +{ +%Docstring +A simple class to hold information for SVG dynamic parameters + +.. versionadded:: 3.18 +%End + +%TypeHeaderCode +#include "qgssvgparameter.h" +%End + public: + QgsSvgParameter(); +%Docstring +Constructor +%End + + QgsSvgParameter( const QString &name, const QString &value ); +%Docstring +Constructor +%End + QString name() const; +%Docstring +Returns the name of the parameter +%End + void setName( const QString &name ); +%Docstring +Sets the name of the parameter +%End + QString value() const; +%Docstring +Returns the value of the parameter +%End + void setValue( const QString &value ); +%Docstring +Sets the value of the parameter +%End + +}; + +typedef QList QgsSvgParameters; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/symbology/qgssvgparameter.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/core/core_auto.sip b/python/core/core_auto.sip index 7329ab47816..869f5210250 100644 --- a/python/core/core_auto.sip +++ b/python/core/core_auto.sip @@ -570,6 +570,7 @@ %Include auto_generated/symbology/qgsstyleentityvisitor.sip %Include auto_generated/symbology/qgsstylemodel.sip %Include auto_generated/symbology/qgssvgcache.sip +%Include auto_generated/symbology/qgssvgparameter.sip %Include auto_generated/symbology/qgssymbol.sip %Include auto_generated/symbology/qgssymbollayer.sip %Include auto_generated/symbology/qgssymbollayerreference.sip diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c1a2dce8ca1..dc66f8b8db2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1502,6 +1502,7 @@ set(QGIS_CORE_HDRS symbology/qgsstyleentityvisitor.h symbology/qgsstylemodel.h symbology/qgssvgcache.h + symbology/qgssvgparameter.h symbology/qgssymbol.h symbology/qgssymbollayer.h symbology/qgssymbollayerreference.h diff --git a/src/core/layout/qgslayoutitempicture.cpp b/src/core/layout/qgslayoutitempicture.cpp index 333abe5cd74..9864cc32d13 100644 --- a/src/core/layout/qgslayoutitempicture.cpp +++ b/src/core/layout/qgslayoutitempicture.cpp @@ -472,8 +472,8 @@ void QgsLayoutItemPicture::loadPictureUsingCache( const QString &path ) QColor fillColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgBackgroundColor, context, mSvgFillColor ); QColor strokeColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgStrokeColor, context, mSvgStrokeColor ); double strokeWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PictureSvgStrokeWidth, context, mSvgStrokeWidth ); - // TODO parameters - QMap parameters; + // TODO parameters (handle this in the gui part) + QgsSvgParameters parameters; bool isMissingImage = false; const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, rect().width(), fillColor, strokeColor, strokeWidth, 1.0, 0, false, parameters, &isMissingImage ); diff --git a/src/core/symbology/qgsmarkersymbollayer.h b/src/core/symbology/qgsmarkersymbollayer.h index 4a2f5120ce1..efa9e735449 100644 --- a/src/core/symbology/qgsmarkersymbollayer.h +++ b/src/core/symbology/qgsmarkersymbollayer.h @@ -19,6 +19,7 @@ #include "qgis_core.h" #include "qgis_sip.h" #include "qgssymbollayer.h" +#include "qgssvgparameter.h" #define DEFAULT_SIMPLEMARKER_NAME "circle" #define DEFAULT_SIMPLEMARKER_COLOR QColor(255,0,0) @@ -589,6 +590,18 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer double strokeWidth() const { return mStrokeWidth; } void setStrokeWidth( double w ) { mStrokeWidth = w; } + /** + * Returns the dynamic SVG parameters + * \since QGIS 3.18 + */ + QgsSvgParameters parameters() const { return mParameters; } + + /** + * Sets the dynamic SVG parameters + * \since QGIS 3.18 + */ + void setParameters( const QgsSvgParameters ¶meters ) { mParameters = parameters; } + /** * Sets the units for the stroke width. * \param unit width units @@ -636,6 +649,7 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer bool mHasFillParam = false; QColor mStrokeColor; double mStrokeWidth; + QList mParameters; QgsUnitTypes::RenderUnit mStrokeWidthUnit; QgsMapUnitScale mStrokeWidthMapUnitScale; diff --git a/src/core/symbology/qgssvgcache.cpp b/src/core/symbology/qgssvgcache.cpp index 5e413f0b653..f5068601a3d 100644 --- a/src/core/symbology/qgssvgcache.cpp +++ b/src/core/symbology/qgssvgcache.cpp @@ -43,7 +43,7 @@ // QgsSvgCacheEntry // -QgsSvgCacheEntry::QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke, double fixedAspectRatio, const QMap ¶meters ) +QgsSvgCacheEntry::QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke, double fixedAspectRatio, const QgsSvgParameters ¶meters ) : QgsAbstractContentCacheEntry( path ) , size( size ) , strokeWidth( strokeWidth ) @@ -121,7 +121,7 @@ QgsSvgCache::QgsSvgCache( QObject *parent ) } QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio, bool blocking, const QMap ¶meters ) + double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio, bool blocking, const QgsSvgParameters ¶meters ) { QMutexLocker locker( &mMutex ); @@ -181,7 +181,7 @@ QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor & } QPicture QgsSvgCache::svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, bool forceVectorOutput, double fixedAspectRatio, bool blocking, const QMap ¶meters ) + double widthScaleFactor, bool forceVectorOutput, double fixedAspectRatio, bool blocking, const QgsSvgParameters ¶meters ) { QMutexLocker locker( &mMutex ); @@ -205,7 +205,7 @@ QPicture QgsSvgCache::svgAsPicture( const QString &path, double size, const QCol } QByteArray QgsSvgCache::svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio, bool blocking, const QMap ¶meters, bool *isMissingImage ) + double widthScaleFactor, double fixedAspectRatio, bool blocking, const QgsSvgParameters ¶meters, bool *isMissingImage ) { QMutexLocker locker( &mMutex ); @@ -215,7 +215,7 @@ QByteArray QgsSvgCache::svgContent( const QString &path, double size, const QCol } QSizeF QgsSvgCache::svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio, bool blocking, const QMap ¶meters ) + double widthScaleFactor, double fixedAspectRatio, bool blocking, const QgsSvgParameters ¶meters ) { QMutexLocker locker( &mMutex ); @@ -495,7 +495,7 @@ void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput } QgsSvgCacheEntry *QgsSvgCache::cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio, const QMap ¶meters, bool blocking, bool *isMissingImage ) + double widthScaleFactor, double fixedAspectRatio, const QgsSvgParameters ¶meters, bool blocking, bool *isMissingImage ) { QgsSvgCacheEntry *currentEntry = findExistingEntry( new QgsSvgCacheEntry( path, size, strokeWidth, widthScaleFactor, fill, stroke, fixedAspectRatio, parameters ) ); @@ -511,7 +511,7 @@ QgsSvgCacheEntry *QgsSvgCache::cacheEntry( const QString &path, double size, con } -void QgsSvgCache::replaceElemParams( QDomElement &elem, const QColor &fill, const QColor &stroke, double strokeWidth, const QMap ¶meters ) +void QgsSvgCache::replaceElemParams( QDomElement &elem, const QColor &fill, const QColor &stroke, double strokeWidth, const QgsSvgParameters ¶meters ) { if ( elem.isNull() ) { @@ -598,12 +598,12 @@ void QgsSvgCache::replaceElemParams( QDomElement &elem, const QColor &fill, cons } else { - QMap::const_iterator paramIt = parameters.constBegin(); + QgsSvgParameters::const_iterator paramIt = parameters.constBegin(); for ( ; paramIt != parameters.constEnd(); ++paramIt ) { - if ( value.startsWith( QString( QLatin1String( "param(%1)" ) ).arg( paramIt.key() ) ) ) + if ( value.startsWith( QString( QLatin1String( "param(%1)" ) ).arg( paramIt->name() ) ) ) { - elem.setAttribute( attribute.name(), paramIt.value() ); + elem.setAttribute( attribute.name(), paramIt->value() ); break; } } @@ -613,12 +613,12 @@ void QgsSvgCache::replaceElemParams( QDomElement &elem, const QColor &fill, cons if ( elem.nodeValue().startsWith( "param(" ) ) { - QMap::const_iterator paramIt = parameters.constBegin(); + QgsSvgParameters::const_iterator paramIt = parameters.constBegin(); for ( ; paramIt != parameters.constEnd(); ++paramIt ) { - if ( elem.nodeValue().startsWith( QString( QLatin1String( "param(%1)" ) ).arg( paramIt.key() ) ) ) + if ( elem.nodeValue().startsWith( QString( QLatin1String( "param(%1)" ) ).arg( paramIt->name() ) ) ) { - elem.setNodeValue( paramIt.value() ); + elem.setNodeValue( paramIt->value() ); break; } } diff --git a/src/core/symbology/qgssvgcache.h b/src/core/symbology/qgssvgcache.h index 166bbf61a3c..b22fa374bbe 100644 --- a/src/core/symbology/qgssvgcache.h +++ b/src/core/symbology/qgssvgcache.h @@ -20,6 +20,7 @@ #include "qgsabstractcontentcache.h" #include "qgis.h" +#include "qgssvgparameter.h" #include @@ -49,7 +50,7 @@ class CORE_EXPORT QgsSvgCacheEntry : public QgsAbstractContentCacheEntry * \param parameters an optional map of parameters to dynamically replace content in the SVG */ QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke, - double fixedAspectRatio = 0, const QMap ¶meters = QMap() ) ; + double fixedAspectRatio = 0, const QgsSvgParameters ¶meters = QgsSvgParameters() ) ; //! QgsSvgCacheEntry cannot be copied. QgsSvgCacheEntry( const QgsSvgCacheEntry &rh ) = delete; @@ -71,7 +72,7 @@ class CORE_EXPORT QgsSvgCacheEntry : public QgsAbstractContentCacheEntry QColor fill = Qt::black; QColor stroke = Qt::black; - QMap parameters; + QgsSvgParameters parameters; std::unique_ptr< QImage > image; std::unique_ptr< QPicture > picture; @@ -150,7 +151,7 @@ class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry */ QImage svgAsImage( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio = 0, bool blocking = false, - const QMap ¶meters = QMap() ); + const QgsSvgParameters ¶meters = QgsSvgParameters() ); /** * Returns an SVG drawing as a QPicture. @@ -176,7 +177,7 @@ class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry */ QPicture svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput = false, double fixedAspectRatio = 0, bool blocking = false, - const QMap ¶meters = QMap() ); + const QgsSvgParameters ¶meters = QgsSvgParameters() ); /** * Calculates the viewbox size of a (possibly cached) SVG file. @@ -197,7 +198,7 @@ class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry * \since QGIS 2.14 */ QSizeF svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap ¶meters = QMap() ); + double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QgsSvgParameters ¶meters = QgsSvgParameters() ); /** * Tests if an SVG file contains parameters for fill, stroke color, stroke width. If yes, possible default values are returned. If there are several @@ -276,10 +277,10 @@ class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry */ #ifndef SIP_RUN QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap ¶meters = QMap(), bool *isMissingImage = nullptr ); + double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QgsSvgParameters ¶meters = QgsSvgParameters(), bool *isMissingImage = nullptr ); #else QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap ¶meters = QMap() ); + double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QgsSvgParameters ¶meters = QgsSvgParameters() ); #endif signals: @@ -307,10 +308,10 @@ class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry void cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput = false ); //! Returns entry from cache or creates a new entry if it does not exist already QgsSvgCacheEntry *cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, - double widthScaleFactor, double fixedAspectRatio = 0, const QMap ¶meters = QMap(), bool blocking = false, bool *isMissingImage = nullptr ); + double widthScaleFactor, double fixedAspectRatio = 0, const QgsSvgParameters ¶meters = QgsSvgParameters(), bool blocking = false, bool *isMissingImage = nullptr ); //! Replaces parameters in elements of a dom node and calls method for all child nodes - void replaceElemParams( QDomElement &elem, const QColor &fill, const QColor &stroke, double strokeWidth, const QMap ¶meters ); + void replaceElemParams( QDomElement &elem, const QColor &fill, const QColor &stroke, double strokeWidth, const QgsSvgParameters ¶meters ); void containsElemParams( const QDomElement &elem, bool &hasFillParam, bool &hasDefaultFill, QColor &defaultFill, diff --git a/src/core/symbology/qgssvgparameter.h b/src/core/symbology/qgssvgparameter.h new file mode 100644 index 00000000000..8c73a2fa4dd --- /dev/null +++ b/src/core/symbology/qgssvgparameter.h @@ -0,0 +1,56 @@ +#ifndef QGSSVGPARAMETER_H +#define QGSSVGPARAMETER_H +/*************************************************************************** + qgssvgparameter.h + --------------------- + begin : December 2020 + copyright : (C) 2020 by Denis Rouzaud + email : denis@gmail.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "qgis_core.h" + +#include +#include + +/** +\ingroup core +A simple class to hold information for SVG dynamic parameters +\since QGIS 3.18 +*/ +class CORE_EXPORT QgsSvgParameter +{ + public: + //! Constructor + QgsSvgParameter() = default; + + //! Constructor + QgsSvgParameter( const QString &name, const QString &value ) + : mValid( !name.isEmpty() ), mName( name ), mValue( value ) {} + + //! Returns the name of the parameter + QString name() const {return mName;} + //! Sets the name of the parameter + void setName( const QString &name ) {mName = name;} + //! Returns the value of the parameter + QString value() const {return mValue;} + //! Sets the value of the parameter + void setValue( const QString &value ) {mValue = value;} + + private: + bool mValid = false; + QString mName; + QString mValue; +}; + +typedef QList QgsSvgParameters; + +#endif // QGSSVGPARAMETER_H diff --git a/tests/src/core/testqgssvgcache.cpp b/tests/src/core/testqgssvgcache.cpp index 59b46cf09fd..9ebecedd505 100644 --- a/tests/src/core/testqgssvgcache.cpp +++ b/tests/src/core/testqgssvgcache.cpp @@ -24,6 +24,7 @@ #include #include #include +#include "qgssvgparameter.h" #include "qgssvgcache.h" #include "qgsmultirenderchecker.h" #include "qgsapplication.h" @@ -339,7 +340,7 @@ void TestQgsSvgCache::dynamicSvg() QgsSvgCache cache; const QString dynamicImage = TEST_DATA_DIR + QStringLiteral( "/svg/test_dynamic_svg.svg" ); QByteArray svg = cache.svgContent( dynamicImage, 200, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ), 1.0, - 1.0, 0, false, {{"text1", "green?"}, {"text2", "supergreen"}, {"align", "middle"}} ); + 1.0, 0, false, QgsSvgParameters( {QgsSvgParameter( "text1", "green?" ), QgsSvgParameter( "text2", "supergreen" ), QgsSvgParameter( "align", "middle" )} ) ); const QString contolImage = TEST_DATA_DIR + QStringLiteral( "/svg/test_dynamic_svg.svg" ); QByteArray control_svg = cache.svgContent( contolImage, 200, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ), 1.0, 1.0, 0, false, {} );