Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Custom properties for QgsComposition and QgsComposerObject
  • Loading branch information
nyalldawson committed Aug 11, 2015
1 parent 2ef2414 commit 3898d84
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 2 deletions.
38 changes: 38 additions & 0 deletions python/core/composer/qgscomposerobject.sip
Expand Up @@ -94,6 +94,44 @@ class QgsComposerObject : QObject
* @note this method was added in version 2.5
*/
void setDataDefinedProperty( const DataDefinedProperty property, const bool active, const bool useExpression, const QString &expression, const QString &field );

/** 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()
* @note added in QGIS 2.12
*/
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()
* @note added in QGIS 2.12
*/
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()
* @note added in QGIS 2.12
*/
void removeCustomProperty( const QString &key );

/** Return list of keys stored in custom properties for the object.
* @see setCustomProperty()
* @see customProperty()
* @see removeCustomProperty()
* @note added in QGIS 2.12
*/
QStringList customProperties() const;

public slots:

Expand Down
38 changes: 38 additions & 0 deletions python/core/composer/qgscomposition.sip
Expand Up @@ -604,6 +604,44 @@ class QgsComposition : QGraphicsScene
*/
QgsComposerModel * itemsModel();

/** Set a custom property for the composition.
* @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()
* @note added in QGIS 2.12
*/
void setCustomProperty( const QString &key, const QVariant &value );

/** Read a custom property from the composition.
* @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()
* @note added in QGIS 2.12
*/
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;

/** Remove a custom property from the composition.
* @param key property key
* @see setCustomProperty()
* @see customProperty()
* @see customProperties()
* @note added in QGIS 2.12
*/
void removeCustomProperty( const QString &key );

/** Return list of keys stored in custom properties for composition.
* @see setCustomProperty()
* @see customProperty()
* @see removeCustomProperty()
* @note added in QGIS 2.12
*/
QStringList customProperties() const;

public slots:
/** Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );
Expand Down
26 changes: 26 additions & 0 deletions src/core/composer/qgscomposerobject.cpp
Expand Up @@ -68,6 +68,9 @@ bool QgsComposerObject::writeXML( QDomElement &elem, QDomDocument &doc ) const
//data defined properties
QgsComposerUtils::writeDataDefinedPropertyMap( elem, doc, &mDataDefinedNames, &mDataDefinedProperties );

//custom properties
mCustomProperties.writeXml( elem, doc );

return true;
}

Expand All @@ -82,6 +85,9 @@ bool QgsComposerObject::readXML( const QDomElement &itemElem, const QDomDocument
//data defined properties
QgsComposerUtils::readDataDefinedPropertyMap( itemElem, &mDataDefinedNames, &mDataDefinedProperties );

//custom properties
mCustomProperties.readXml( itemElem );

return true;
}

Expand Down Expand Up @@ -174,3 +180,23 @@ void QgsComposerObject::prepareDataDefinedExpressions() const
it.value()->prepareExpression( atlasLayer );
}
}

void QgsComposerObject::setCustomProperty( const QString& key, const QVariant& value )
{
mCustomProperties.setValue( key, value );
}

QVariant QgsComposerObject::customProperty( const QString& key, const QVariant& defaultValue ) const
{
return mCustomProperties.value( key, defaultValue );
}

void QgsComposerObject::removeCustomProperty( const QString& key )
{
mCustomProperties.remove( key );
}

QStringList QgsComposerObject::customProperties() const
{
return mCustomProperties.keys();
}
44 changes: 42 additions & 2 deletions src/core/composer/qgscomposerobject.h
Expand Up @@ -17,10 +17,9 @@
#ifndef QGSCOMPOSEROBJECT_H
#define QGSCOMPOSEROBJECT_H

#include "qgsobjectcustomproperties.h"
#include <QObject>
#include <QDomNode>
#include <QPointF>
#include <QRectF>
#include <QMap>

class QgsComposition;
Expand Down Expand Up @@ -122,6 +121,44 @@ class CORE_EXPORT QgsComposerObject: public QObject
*/
void setDataDefinedProperty( const DataDefinedProperty property, const bool active, const bool useExpression, const QString &expression, const QString &field );

/** 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()
* @note added in QGIS 2.12
*/
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()
* @note added in QGIS 2.12
*/
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()
* @note added in QGIS 2.12
*/
void removeCustomProperty( const QString &key );

/** Return list of keys stored in custom properties for the object.
* @see setCustomProperty()
* @see customProperty()
* @see removeCustomProperty()
* @note added in QGIS 2.12
*/
QStringList customProperties() const;

public slots:

/** Triggers a redraw for the item*/
Expand All @@ -143,6 +180,9 @@ class CORE_EXPORT QgsComposerObject: public QObject
/** Map of data defined properties for the item to string name to use when exporting item to xml*/
QMap< QgsComposerObject::DataDefinedProperty, QString > mDataDefinedNames;

/** Custom properties for object*/
QgsObjectCustomProperties mCustomProperties;

/** Evaluate a data defined property and return the calculated value
* @returns true if data defined property could be successfully evaluated
* @param property data defined property to evaluate
Expand Down
26 changes: 26 additions & 0 deletions src/core/composer/qgscomposition.cpp
Expand Up @@ -847,6 +847,9 @@ bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
//data defined properties
QgsComposerUtils::writeDataDefinedPropertyMap( compositionElem, doc, &mDataDefinedNames, &mDataDefinedProperties );

//custom properties
mCustomProperties.writeXml( compositionElem, doc );

return true;
}

Expand Down Expand Up @@ -915,6 +918,9 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
//data defined properties
QgsComposerUtils::readDataDefinedPropertyMap( compositionElem, &mDataDefinedNames, &mDataDefinedProperties );

//custom properties
mCustomProperties.readXml( compositionElem );

updatePaperItems();

updateBounds();
Expand Down Expand Up @@ -3036,6 +3042,26 @@ void QgsComposition::setDataDefinedProperty( const QgsComposerObject::DataDefine
}
}

void QgsComposition::setCustomProperty( const QString& key, const QVariant& value )
{
mCustomProperties.setValue( key, value );
}

QVariant QgsComposition::customProperty( const QString& key, const QVariant& defaultValue ) const
{
return mCustomProperties.value( key, defaultValue );
}

void QgsComposition::removeCustomProperty( const QString& key )
{
mCustomProperties.remove( key );
}

QStringList QgsComposition::customProperties() const
{
return mCustomProperties.keys();
}

bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
{
if ( property == QgsComposerObject::NoProperty || property == QgsComposerObject::AllProperties )
Expand Down
41 changes: 41 additions & 0 deletions src/core/composer/qgscomposition.h
Expand Up @@ -35,6 +35,7 @@
#include "qgspaperitem.h"
#include "qgscomposerobject.h"
#include "qgscomposeritem.h"
#include "qgsobjectcustomproperties.h"

class QgisApp;
class QgsComposerFrame;
Expand Down Expand Up @@ -666,6 +667,44 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
*/
QgsComposerModel * itemsModel() { return mItemsModel; }

/** Set a custom property for the composition.
* @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()
* @note added in QGIS 2.12
*/
void setCustomProperty( const QString &key, const QVariant &value );

/** Read a custom property from the composition.
* @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()
* @note added in QGIS 2.12
*/
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;

/** Remove a custom property from the composition.
* @param key property key
* @see setCustomProperty()
* @see customProperty()
* @see customProperties()
* @note added in QGIS 2.12
*/
void removeCustomProperty( const QString &key );

/** Return list of keys stored in custom properties for composition.
* @see setCustomProperty()
* @see customProperty()
* @see removeCustomProperty()
* @note added in QGIS 2.12
*/
QStringList customProperties() const;

public slots:
/** Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );
Expand Down Expand Up @@ -777,6 +816,8 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
/** Map of current data defined properties to QgsDataDefined for the composition*/
QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* > mDataDefinedProperties;

QgsObjectCustomProperties mCustomProperties;

QgsComposition(); //default constructor is forbidden

/** Calculates the bounds of all non-gui items in the composition. Ignores snap lines and mouse handles*/
Expand Down
66 changes: 66 additions & 0 deletions tests/src/core/testqgscomposerobject.cpp
Expand Up @@ -47,6 +47,8 @@ class TestQgsComposerObject : public QObject
void setRetrieveDDProperty(); //test setting and retreiving a data defined property
void evaluateDDProperty(); //test evaluating data defined properties
void writeRetrieveDDProperty(); //test writing and retrieving dd properties from xml
void customProperties(); //test setting/getting custom properties
void writeRetrieveCustomProperties(); //test writing/retreiving custom properties from xml

private:
bool renderCheck( QString testName, QImage &image, int mismatchCount = 0 );
Expand Down Expand Up @@ -230,6 +232,70 @@ void TestQgsComposerObject::writeRetrieveDDProperty()
delete readObject;
}

void TestQgsComposerObject::customProperties()
{
QgsComposerObject* object = new QgsComposerObject( mComposition );

QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
QVERIFY( object->customProperties().isEmpty() );
object->setCustomProperty( "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( "badprop" );

object->removeCustomProperty( "testprop" );
QVERIFY( object->customProperties().isEmpty() );
QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );

object->setCustomProperty( "testprop1", "testval1" );
object->setCustomProperty( "testprop2", "testval2" );
QStringList keys = object->customProperties();
QCOMPARE( keys.length(), 2 );
QVERIFY( keys.contains( "testprop1" ) );
QVERIFY( keys.contains( "testprop2" ) );

delete object;
}

void TestQgsComposerObject::writeRetrieveCustomProperties()
{
QgsComposerObject* object = new QgsComposerObject( mComposition );
object->setCustomProperty( "testprop", "testval" );
object->setCustomProperty( "testprop2", 5 );

//test writing object with custom properties
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
"qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( "qgis" );
QDomElement composerObjectElem = doc.createElement( "ComposerObject" );
rootNode.appendChild( composerObjectElem );
QVERIFY( object->writeXML( composerObjectElem, doc ) );

//check if object node was written
QDomNodeList evalNodeList = rootNode.elementsByTagName( "ComposerObject" );
QCOMPARE( evalNodeList.count(), 1 );

//test reading node containing custom properties
QgsComposerObject* readObject = new QgsComposerObject( mComposition );
QVERIFY( readObject->readXML( composerObjectElem, doc ) );

//test retrieved custom properties
QCOMPARE( readObject->customProperties().length(), 2 );
QVERIFY( readObject->customProperties().contains( QString( "testprop" ) ) );
QVERIFY( readObject->customProperties().contains( QString( "testprop2" ) ) );
QCOMPARE( readObject->customProperty( "testprop" ).toString(), QString( "testval" ) );
QCOMPARE( readObject->customProperty( "testprop2" ).toInt(), 5 );

delete object;
delete readObject;
}

bool TestQgsComposerObject::renderCheck( QString testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";
Expand Down

0 comments on commit 3898d84

Please sign in to comment.