diff --git a/python/core/layout/qgslayoutobject.sip b/python/core/layout/qgslayoutobject.sip
index f98934c4c4e..225c74fcd6e 100644
--- a/python/core/layout/qgslayoutobject.sip
+++ b/python/core/layout/qgslayoutobject.sip
@@ -21,6 +21,63 @@ class QgsLayoutObject: QObject
%End
public:
+ enum DataDefinedProperty
+ {
+ NoProperty,
+ AllProperties,
+ TestProperty,
+ //composer
+ PresetPaperSize,
+ PaperWidth,
+ PaperHeight,
+ NumPages,
+ PaperOrientation,
+ //general
+ PageNumber,
+ PositionX,
+ PositionY,
+ ItemWidth,
+ ItemHeight,
+ ItemRotation,
+ Transparency,
+ Opacity,
+ BlendMode,
+ ExcludeFromExports,
+ FrameColor,
+ BackgroundColor,
+ //composer
+ MapRotation,
+ MapScale,
+ MapXMin,
+ MapYMin,
+ MapXMax,
+ MapYMax,
+ MapAtlasMargin,
+ MapLayers,
+ MapStylePreset,
+ //composer
+ PictureSource,
+ PictureSvgBackgroundColor,
+ PictureSvgStrokeColor,
+ PictureSvgStrokeWidth,
+ //html
+ SourceUrl,
+ //legend
+ LegendTitle,
+ LegendColumnCount,
+ //scalebar
+ ScalebarFillColor,
+ ScalebarFillColor2,
+ ScalebarLineColor,
+ ScalebarLineWidth,
+ };
+
+ static const QgsPropertiesDefinition &propertyDefinitions();
+%Docstring
+ Returns the layout object property definitions.
+ :rtype: QgsPropertiesDefinition
+%End
+
QgsLayoutObject( QgsLayout *layout );
%Docstring
Constructor for QgsLayoutObject, with the specified parent ``layout``.
@@ -38,9 +95,67 @@ class QgsLayoutObject: QObject
:rtype: QgsLayout
%End
+ QgsPropertyCollection &dataDefinedProperties();
+%Docstring
+ Returns a reference to the object's property collection, used for data defined overrides.
+.. seealso:: setDataDefinedProperties()
+ :rtype: QgsPropertyCollection
+%End
+
+
+ void setDataDefinedProperties( const QgsPropertyCollection &collection );
+%Docstring
+ Sets the objects's property collection, used for data defined overrides.
+ \param collection property collection. Existing properties will be replaced.
+.. seealso:: dataDefinedProperties()
+%End
+
+
+ void setCustomProperty( const QString &key, const QVariant &value );
+%Docstring
+ Set a custom property for the object.
+ \param key property key. If a property with the same key already exists it will be overwritten.
+ \param value property value
+.. seealso:: customProperty()
+.. seealso:: removeCustomProperty()
+.. seealso:: customProperties()
+%End
+
+ QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
+%Docstring
+ Read a custom property from the object.
+ \param key property key
+ \param defaultValue default value to return if property with matching key does not exist
+ :return: value of matching property
+.. seealso:: setCustomProperty()
+.. seealso:: removeCustomProperty()
+.. seealso:: customProperties()
+ :rtype: QVariant
+%End
+
+ void removeCustomProperty( const QString &key );
+%Docstring
+ Remove a custom property from the object.
+ \param key property key
+.. seealso:: setCustomProperty()
+.. seealso:: customProperty()
+.. seealso:: customProperties()
+%End
+
+ QStringList customProperties() const;
+%Docstring
+ Return list of keys stored in custom properties for the object.
+.. seealso:: setCustomProperty()
+.. seealso:: customProperty()
+.. seealso:: removeCustomProperty()
+ :rtype: list of str
+%End
+
protected:
+
+
};
/************************************************************************
diff --git a/src/core/layout/qgslayoutobject.cpp b/src/core/layout/qgslayoutobject.cpp
index 188186729c9..1ee14df8d55 100644
--- a/src/core/layout/qgslayoutobject.cpp
+++ b/src/core/layout/qgslayoutobject.cpp
@@ -20,8 +20,93 @@
#include "qgslayout.h"
#include "qgslayoutobject.h"
+
+QgsPropertiesDefinition QgsLayoutObject::sPropertyDefinitions;
+
+void QgsLayoutObject::initPropertyDefinitions()
+{
+ if ( !sPropertyDefinitions.isEmpty() )
+ return;
+
+ sPropertyDefinitions = QgsPropertiesDefinition
+ {
+ { QgsLayoutObject::TestProperty, QgsPropertyDefinition( "dataDefinedProperty", QgsPropertyDefinition::DataTypeString, "invalid property", QString() ) },
+ {
+ QgsLayoutObject::PresetPaperSize, QgsPropertyDefinition( "dataDefinedPaperSize", QgsPropertyDefinition::DataTypeString, QObject::tr( "Paper size" ), QObject::tr( "string " ) + QLatin1String( "[A5|A4|A3|A2|A1|A0"
+ "B5|B4|B3|B2|B1|B0"
+ "Legal|Ansi A|Ansi B|Ansi C|Ansi D|Ansi E"
+ "Arch A|Arch B|Arch C|Arch D|Arch E|Arch E1]"
+ ) )
+ },
+ { QgsLayoutObject::PaperWidth, QgsPropertyDefinition( "dataDefinedPaperWidth", QObject::tr( "Page width" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::PaperHeight, QgsPropertyDefinition( "dataDefinedPaperHeight", QObject::tr( "Page height" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::NumPages, QgsPropertyDefinition( "dataDefinedNumPages", QObject::tr( "Number of pages" ), QgsPropertyDefinition::IntegerPositive ) },
+ { QgsLayoutObject::PaperOrientation, QgsPropertyDefinition( "dataDefinedPaperOrientation", QgsPropertyDefinition::DataTypeString, QObject::tr( "Symbol size" ), QObject::tr( "string " ) + QLatin1String( "[portrait|landscape]" ) ) },
+ { QgsLayoutObject::PageNumber, QgsPropertyDefinition( "dataDefinedPageNumber", QObject::tr( "Page number" ), QgsPropertyDefinition::IntegerPositive ) },
+ { QgsLayoutObject::PositionX, QgsPropertyDefinition( "dataDefinedPositionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::PositionY, QgsPropertyDefinition( "dataDefinedPositionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::ItemWidth, QgsPropertyDefinition( "dataDefinedWidth", QObject::tr( "Width" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::ItemHeight, QgsPropertyDefinition( "dataDefinedHeight", QObject::tr( "Height" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::ItemRotation, QgsPropertyDefinition( "dataDefinedRotation", QObject::tr( "Rotation angle" ), QgsPropertyDefinition::Rotation ) },
+ { QgsLayoutObject::Transparency, QgsPropertyDefinition( "dataDefinedTransparency", QObject::tr( "Transparency" ), QgsPropertyDefinition::Opacity ) },
+ { QgsLayoutObject::Opacity, QgsPropertyDefinition( "dataDefinedOpacity", QObject::tr( "Opacity" ), QgsPropertyDefinition::Opacity ) },
+ { QgsLayoutObject::BlendMode, QgsPropertyDefinition( "dataDefinedBlendMode", QObject::tr( "Blend mode" ), QgsPropertyDefinition::BlendMode ) },
+ { QgsLayoutObject::ExcludeFromExports, QgsPropertyDefinition( "dataDefinedExcludeExports", QObject::tr( "Exclude item from exports" ), QgsPropertyDefinition::Boolean ) },
+ { QgsLayoutObject::FrameColor, QgsPropertyDefinition( "dataDefinedFrameColor", QObject::tr( "Frame color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::BackgroundColor, QgsPropertyDefinition( "dataDefinedBackgroundColor", QObject::tr( "Background color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::MapRotation, QgsPropertyDefinition( "dataDefinedMapRotation", QObject::tr( "Map rotation" ), QgsPropertyDefinition::Rotation ) },
+ { QgsLayoutObject::MapScale, QgsPropertyDefinition( "dataDefinedMapScale", QObject::tr( "Map scale" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::MapXMin, QgsPropertyDefinition( "dataDefinedMapXMin", QObject::tr( "Extent minimum X" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::MapYMin, QgsPropertyDefinition( "dataDefinedMapYMin", QObject::tr( "Extent minimum Y" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::MapXMax, QgsPropertyDefinition( "dataDefinedMapXMax", QObject::tr( "Extent maximum X" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::MapYMax, QgsPropertyDefinition( "dataDefinedMapYMax", QObject::tr( "Extent maximum Y" ), QgsPropertyDefinition::Double ) },
+ { QgsLayoutObject::MapAtlasMargin, QgsPropertyDefinition( "dataDefinedMapAtlasMargin", QObject::tr( "Atlas margin" ), QgsPropertyDefinition::DoublePositive ) },
+ { QgsLayoutObject::MapLayers, QgsPropertyDefinition( "dataDefinedMapLayers", QgsPropertyDefinition::DataTypeString, QObject::tr( "Symbol size" ), tr( "list of map layer names separated by | characters" ) ) },
+ { QgsLayoutObject::MapStylePreset, QgsPropertyDefinition( "dataDefinedMapStylePreset", QgsPropertyDefinition::DataTypeString, QObject::tr( "Symbol size" ), tr( "list of map layer names separated by | characters" ) ) },
+ { QgsLayoutObject::PictureSource, QgsPropertyDefinition( "dataDefinedSource", QObject::tr( "Picture source (URL)" ), QgsPropertyDefinition::String ) },
+ { QgsLayoutObject::SourceUrl, QgsPropertyDefinition( "dataDefinedSourceUrl", QObject::tr( "Source URL" ), QgsPropertyDefinition::String ) },
+ { QgsLayoutObject::PictureSvgBackgroundColor, QgsPropertyDefinition( "dataDefinedSvgBackgroundColor", QObject::tr( "SVG background color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::PictureSvgStrokeColor, QgsPropertyDefinition( "dataDefinedSvgStrokeColor", QObject::tr( "SVG stroke color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::PictureSvgStrokeWidth, QgsPropertyDefinition( "dataDefinedSvgStrokeWidth", QObject::tr( "SVG stroke width" ), QgsPropertyDefinition::StrokeWidth ) },
+ { QgsLayoutObject::LegendTitle, QgsPropertyDefinition( "dataDefinedLegendTitle", QObject::tr( "Legend title" ), QgsPropertyDefinition::String ) },
+ { QgsLayoutObject::LegendColumnCount, QgsPropertyDefinition( "dataDefinedLegendColumns", QObject::tr( "Number of columns" ), QgsPropertyDefinition::IntegerPositiveGreaterZero ) },
+ { QgsLayoutObject::ScalebarFillColor, QgsPropertyDefinition( "dataDefinedScalebarFill", QObject::tr( "Fill color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::ScalebarFillColor2, QgsPropertyDefinition( "dataDefinedScalebarFill2", QObject::tr( "Secondary fill color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::ScalebarLineColor, QgsPropertyDefinition( "dataDefinedScalebarLineColor", QObject::tr( "Line color" ), QgsPropertyDefinition::ColorWithAlpha ) },
+ { QgsLayoutObject::ScalebarLineWidth, QgsPropertyDefinition( "dataDefinedScalebarLineWidth", QObject::tr( "Line width" ), QgsPropertyDefinition::StrokeWidth ) },
+ };
+}
+
+const QgsPropertiesDefinition &QgsLayoutObject::propertyDefinitions()
+{
+ QgsLayoutObject::initPropertyDefinitions();
+ return sPropertyDefinitions;
+}
+
QgsLayoutObject::QgsLayoutObject( QgsLayout *layout )
: QObject( nullptr )
, mLayout( layout )
{
+ initPropertyDefinitions();
+}
+
+
+void QgsLayoutObject::setCustomProperty( const QString &key, const QVariant &value )
+{
+ mCustomProperties.setValue( key, value );
+}
+
+QVariant QgsLayoutObject::customProperty( const QString &key, const QVariant &defaultValue ) const
+{
+ return mCustomProperties.value( key, defaultValue );
+}
+
+void QgsLayoutObject::removeCustomProperty( const QString &key )
+{
+ mCustomProperties.remove( key );
+}
+
+QStringList QgsLayoutObject::customProperties() const
+{
+ return mCustomProperties.keys();
}
diff --git a/src/core/layout/qgslayoutobject.h b/src/core/layout/qgslayoutobject.h
index b9d26483b00..bdedcbb418e 100644
--- a/src/core/layout/qgslayoutobject.h
+++ b/src/core/layout/qgslayoutobject.h
@@ -19,6 +19,8 @@
#include "qgis_core.h"
#include "qgis_sip.h"
+#include "qgspropertycollection.h"
+#include "qgsobjectcustomproperties.h"
#include
#include
#include
@@ -36,6 +38,64 @@ class CORE_EXPORT QgsLayoutObject: public QObject
Q_OBJECT
public:
+ /** Data defined properties for different item types
+ */
+ enum DataDefinedProperty
+ {
+ NoProperty = 0, //!< No property
+ AllProperties, //!< All properties for item
+ TestProperty, //!< Dummy property with no effect on item
+ //composer page properties
+ PresetPaperSize, //!< Preset paper size for composition
+ PaperWidth, //!< Paper width
+ PaperHeight, //!< Paper height
+ NumPages, //!< Number of pages in composition
+ PaperOrientation, //!< Paper orientation
+ //general composer item properties
+ PageNumber, //!< Page number for item placement
+ PositionX, //!< X position on page
+ PositionY, //!< Y position on page
+ ItemWidth, //!< Width of item
+ ItemHeight, //!< Height of item
+ ItemRotation, //!< Rotation of item
+ Transparency, //!< Item transparency (deprecated)
+ Opacity, //!< Item opacity
+ BlendMode, //!< Item blend mode
+ ExcludeFromExports, //!< Exclude item from exports
+ FrameColor, //!< Item frame color
+ BackgroundColor, //!< Item background color
+ //composer map
+ MapRotation, //!< Map rotation
+ MapScale, //!< Map scale
+ MapXMin, //!< Map extent x minimum
+ MapYMin, //!< Map extent y minimum
+ MapXMax, //!< Map extent x maximum
+ MapYMax, //!< Map extent y maximum
+ MapAtlasMargin, //!< Map atlas margin
+ MapLayers, //!< Map layer set
+ MapStylePreset, //!< Layer and style map theme
+ //composer picture
+ PictureSource, //!< Picture source url
+ PictureSvgBackgroundColor, //!< SVG background color
+ PictureSvgStrokeColor, //!< SVG stroke color
+ PictureSvgStrokeWidth, //!< SVG stroke width
+ //html item
+ SourceUrl, //!< Html source url
+ //legend item
+ LegendTitle, //!< Legend title
+ LegendColumnCount, //!< Legend column count
+ //scalebar item
+ ScalebarFillColor, //!< Scalebar fill color
+ ScalebarFillColor2, //!< Scalebar secondary fill color
+ ScalebarLineColor, //!< Scalebar line color
+ ScalebarLineWidth, //!< Scalebar line width
+ };
+
+ /**
+ * Returns the layout object property definitions.
+ */
+ static const QgsPropertiesDefinition &propertyDefinitions();
+
/**
* Constructor for QgsLayoutObject, with the specified parent \a layout.
* \note While ownership of a QgsLayoutObject is not passed to the layout,
@@ -54,12 +114,80 @@ class CORE_EXPORT QgsLayoutObject: public QObject
*/
QgsLayout *layout() { return mLayout; }
+ /**
+ * Returns a reference to the object's property collection, used for data defined overrides.
+ * \see setDataDefinedProperties()
+ */
+ QgsPropertyCollection &dataDefinedProperties() { return mDataDefinedProperties; }
+
+ /**
+ * Returns a reference to the object's property collection, used for data defined overrides.
+ * \see setDataDefinedProperties()
+ */
+ const QgsPropertyCollection &dataDefinedProperties() const { return mDataDefinedProperties; } SIP_SKIP
+
+ /**
+ * Sets the objects's property collection, used for data defined overrides.
+ * \param collection property collection. Existing properties will be replaced.
+ * \see dataDefinedProperties()
+ */
+ void setDataDefinedProperties( const QgsPropertyCollection &collection ) { mDataDefinedProperties = collection; }
+
+
+ /**
+ * Set a custom property for the object.
+ * \param key property key. If a property with the same key already exists it will be overwritten.
+ * \param value property value
+ * \see customProperty()
+ * \see removeCustomProperty()
+ * \see customProperties()
+ */
+ void setCustomProperty( const QString &key, const QVariant &value );
+
+ /**
+ * Read a custom property from the object.
+ * \param key property key
+ * \param defaultValue default value to return if property with matching key does not exist
+ * \returns value of matching property
+ * \see setCustomProperty()
+ * \see removeCustomProperty()
+ * \see customProperties()
+ */
+ QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
+
+ /**
+ * Remove a custom property from the object.
+ * \param key property key
+ * \see setCustomProperty()
+ * \see customProperty()
+ * \see customProperties()
+ */
+ void removeCustomProperty( const QString &key );
+
+ /**
+ * Return list of keys stored in custom properties for the object.
+ * \see setCustomProperty()
+ * \see customProperty()
+ * \see removeCustomProperty()
+ */
+ QStringList customProperties() const;
+
protected:
QgsLayout *mLayout = nullptr;
+ QgsPropertyCollection mDataDefinedProperties;
+
+ //! Custom properties for object
+ QgsObjectCustomProperties mCustomProperties;
+
private:
+ //! Property definitions
+ static QgsPropertiesDefinition sPropertyDefinitions;
+
+ static void initPropertyDefinitions();
+
friend class TestQgsLayoutObject;
};
diff --git a/tests/src/core/testqgslayoutobject.cpp b/tests/src/core/testqgslayoutobject.cpp
index efc268ce4c9..927ca58a717 100644
--- a/tests/src/core/testqgslayoutobject.cpp
+++ b/tests/src/core/testqgslayoutobject.cpp
@@ -30,6 +30,7 @@ class TestQgsLayoutObject: public QObject
void cleanup();// will be called after every testfunction.
void creation(); //test creation of QgsLayoutObject
void layout(); //test fetching layout from QgsLayoutObject
+ void customProperties();
private:
QgsLayout *mLayout = nullptr;
@@ -81,5 +82,34 @@ void TestQgsLayoutObject::layout()
delete object;
}
+void TestQgsLayoutObject::customProperties()
+{
+ QgsLayoutObject *object = new QgsLayoutObject( mLayout );
+
+ QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
+ QVERIFY( object->customProperties().isEmpty() );
+ object->setCustomProperty( QStringLiteral( "testprop" ), "testval" );
+ QCOMPARE( object->customProperty( "testprop", "defaultval" ).toString(), QString( "testval" ) );
+ QCOMPARE( object->customProperties().length(), 1 );
+ QCOMPARE( object->customProperties().at( 0 ), QString( "testprop" ) );
+
+ //test no crash
+ object->removeCustomProperty( QStringLiteral( "badprop" ) );
+
+ object->removeCustomProperty( QStringLiteral( "testprop" ) );
+ QVERIFY( object->customProperties().isEmpty() );
+ QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
+
+ object->setCustomProperty( QStringLiteral( "testprop1" ), "testval1" );
+ object->setCustomProperty( QStringLiteral( "testprop2" ), "testval2" );
+ QStringList keys = object->customProperties();
+ QCOMPARE( keys.length(), 2 );
+ QVERIFY( keys.contains( "testprop1" ) );
+ QVERIFY( keys.contains( "testprop2" ) );
+
+ delete object;
+}
+
+
QGSTEST_MAIN( TestQgsLayoutObject )
#include "testqgslayoutobject.moc"