mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Allow properties/collections to be prepared in advance
This commit is contained in:
parent
ef3f61fc17
commit
93db66ed1f
@ -69,6 +69,13 @@ class QgsAbstractProperty
|
||||
*/
|
||||
void setActive( bool active );
|
||||
|
||||
/**
|
||||
* Prepares the property against a specified expression context. Calling prepare before evaluating the
|
||||
* property multiple times allows precalculation of expensive setup tasks such as parsing expressions.
|
||||
* Returns true if preparation was successful.
|
||||
*/
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
|
||||
/** Returns the set of any fields referenced by the property.
|
||||
* @param context expression context the property will be evaluated against.
|
||||
*/
|
||||
@ -237,6 +244,7 @@ class QgsFieldBasedProperty : QgsAbstractProperty
|
||||
*/
|
||||
QString field() const;
|
||||
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
virtual QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
|
||||
bool writeXml( QDomElement& propertyElem, QDomDocument& doc ) const;
|
||||
@ -283,6 +291,7 @@ class QgsExpressionBasedProperty : QgsAbstractProperty
|
||||
*/
|
||||
QString expressionString() const;
|
||||
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
virtual QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
|
||||
bool writeXml( QDomElement& propertyElem, QDomDocument& doc ) const;
|
||||
|
@ -126,6 +126,13 @@ class QgsAbstractPropertyCollection
|
||||
*/
|
||||
int valueAsInt( int key, const QgsExpressionContext& context, int defaultValue = 0 ) const;
|
||||
|
||||
/**
|
||||
* Prepares the collection against a specified expression context. Calling prepare before evaluating the
|
||||
* collection's properties multiple times allows precalculation of expensive setup tasks such as parsing expressions.
|
||||
* Returns true if preparation was successful.
|
||||
*/
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the set of any fields referenced by the active properties from the collection.
|
||||
* @param context expression context the properties will be evaluated against.
|
||||
@ -215,6 +222,7 @@ class QgsPropertyCollection : QgsAbstractPropertyCollection
|
||||
bool hasProperty( int key ) const;
|
||||
QgsAbstractProperty* property( int key );
|
||||
QVariant value( int key, const QgsExpressionContext& context, const QVariant& defaultValue = QVariant() ) const;
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
bool isActive( int key ) const;
|
||||
bool hasActiveProperties() const;
|
||||
@ -336,6 +344,8 @@ class QgsPropertyCollectionStack : QgsAbstractPropertyCollection
|
||||
*/
|
||||
QVariant value( int key, const QgsExpressionContext& context, const QVariant& defaultValue = QVariant() ) const;
|
||||
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
|
||||
/** Returns the set of any fields referenced by the active properties from the stack.
|
||||
* @param context expression context the properties will be evaluated against.
|
||||
*/
|
||||
|
@ -143,6 +143,11 @@ void QgsDiagramLayerSettings::writeXml( QDomElement& layerElem, QDomDocument& do
|
||||
layerElem.appendChild( diagramLayerElem );
|
||||
}
|
||||
|
||||
bool QgsDiagramLayerSettings::prepare( const QgsExpressionContext& context ) const
|
||||
{
|
||||
return mProperties.prepare( context );
|
||||
}
|
||||
|
||||
void QgsDiagramLayerSettings::init()
|
||||
{
|
||||
if ( sPropertyNameMap.isEmpty() )
|
||||
|
@ -241,6 +241,14 @@ class CORE_EXPORT QgsDiagramLayerSettings
|
||||
void readXml( const QDomElement& elem, const QgsVectorLayer* layer );
|
||||
void writeXml( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const;
|
||||
|
||||
/**
|
||||
* Prepares the diagrams for a specified expression context. Calling prepare before rendering
|
||||
* multiple diagrams allows precalculation of expensive setup tasks such as parsing expressions.
|
||||
* Returns true if preparation was successful.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const;
|
||||
|
||||
/** Returns the set of any fields referenced by the layer's diagrams.
|
||||
* @param context expression context the diagrams will be drawn using
|
||||
* @note added in QGIS 2.16
|
||||
|
@ -233,8 +233,21 @@ bool QgsStaticProperty::readXml( const QDomElement &propertyElem, const QDomDocu
|
||||
QgsFieldBasedProperty::QgsFieldBasedProperty( const QString& field, bool isActive )
|
||||
: QgsAbstractProperty( isActive )
|
||||
, mField( field )
|
||||
{
|
||||
{}
|
||||
|
||||
QgsFieldBasedProperty::QgsFieldBasedProperty( const QgsFieldBasedProperty& other )
|
||||
: QgsAbstractProperty( other )
|
||||
, mField( other.mField )
|
||||
// don't copy cached field index!
|
||||
{}
|
||||
|
||||
QgsFieldBasedProperty& QgsFieldBasedProperty::operator=( const QgsFieldBasedProperty & other )
|
||||
{
|
||||
QgsAbstractProperty::operator=( other );
|
||||
mActive = other.mActive;
|
||||
mField = other.mField;
|
||||
mCachedFieldIdx = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QgsFieldBasedProperty* QgsFieldBasedProperty::clone()
|
||||
@ -242,6 +255,17 @@ QgsFieldBasedProperty* QgsFieldBasedProperty::clone()
|
||||
return new QgsFieldBasedProperty( *this );
|
||||
}
|
||||
|
||||
bool QgsFieldBasedProperty::prepare( const QgsExpressionContext& context ) const
|
||||
{
|
||||
if ( !mActive )
|
||||
return true;
|
||||
|
||||
// cache field index to avoid subsequent lookups
|
||||
QgsFields f = context.fields();
|
||||
mCachedFieldIdx = f.lookupField( mField );
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant QgsFieldBasedProperty::propertyValue( const QgsExpressionContext& context, const QVariant& defaultValue ) const
|
||||
{
|
||||
if ( !mActive )
|
||||
@ -251,6 +275,10 @@ QVariant QgsFieldBasedProperty::propertyValue( const QgsExpressionContext& conte
|
||||
if ( !f.isValid() )
|
||||
return defaultValue;
|
||||
|
||||
//shortcut the field lookup
|
||||
if ( mCachedFieldIdx >= 0 )
|
||||
return f.attribute( mCachedFieldIdx );
|
||||
|
||||
int fieldIdx = f.fieldNameIndex( mField );
|
||||
if ( fieldIdx < 0 )
|
||||
return defaultValue;
|
||||
@ -296,7 +324,6 @@ bool QgsFieldBasedProperty::readXml( const QDomElement& propertyElem, const QDom
|
||||
QgsExpressionBasedProperty::QgsExpressionBasedProperty( const QString& expression, bool isActive )
|
||||
: QgsAbstractProperty( isActive )
|
||||
, mExpressionString( expression )
|
||||
, mPrepared( false )
|
||||
, mExpression( expression )
|
||||
{
|
||||
|
||||
|
@ -93,6 +93,13 @@ class CORE_EXPORT QgsAbstractProperty
|
||||
*/
|
||||
void setActive( bool active ) { mActive = active; }
|
||||
|
||||
/**
|
||||
* Prepares the property against a specified expression context. Calling prepare before evaluating the
|
||||
* property multiple times allows precalculation of expensive setup tasks such as parsing expressions.
|
||||
* Returns true if preparation was successful.
|
||||
*/
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const { Q_UNUSED( context ); return true; }
|
||||
|
||||
/**
|
||||
* Returns the set of any fields referenced by the property.
|
||||
* @param context expression context the property will be evaluated against.
|
||||
@ -262,6 +269,13 @@ class CORE_EXPORT QgsFieldBasedProperty : public QgsAbstractProperty
|
||||
*/
|
||||
QgsFieldBasedProperty( const QString& field = QString(), bool isActive = false );
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
QgsFieldBasedProperty( const QgsFieldBasedProperty& other );
|
||||
|
||||
QgsFieldBasedProperty& operator=( const QgsFieldBasedProperty& other );
|
||||
|
||||
virtual Type propertyType() const override { return FieldBasedProperty; }
|
||||
|
||||
virtual QgsFieldBasedProperty* clone() override;
|
||||
@ -279,6 +293,7 @@ class CORE_EXPORT QgsFieldBasedProperty : public QgsAbstractProperty
|
||||
*/
|
||||
QString field() const { return mField; }
|
||||
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
virtual QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
bool writeXml( QDomElement& propertyElem, QDomDocument& doc ) const override;
|
||||
bool readXml( const QDomElement& propertyElem, const QDomDocument& doc ) override;
|
||||
@ -290,6 +305,7 @@ class CORE_EXPORT QgsFieldBasedProperty : public QgsAbstractProperty
|
||||
private:
|
||||
|
||||
QString mField;
|
||||
mutable int mCachedFieldIdx = -1;
|
||||
|
||||
};
|
||||
|
||||
@ -328,6 +344,7 @@ class CORE_EXPORT QgsExpressionBasedProperty : public QgsAbstractProperty
|
||||
*/
|
||||
QString expressionString() const { return mExpressionString; }
|
||||
|
||||
bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
virtual QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
bool writeXml( QDomElement& propertyElem, QDomDocument& doc ) const override;
|
||||
bool readXml( const QDomElement& propertyElem, const QDomDocument& doc ) override;
|
||||
@ -339,13 +356,11 @@ class CORE_EXPORT QgsExpressionBasedProperty : public QgsAbstractProperty
|
||||
private:
|
||||
|
||||
QString mExpressionString;
|
||||
mutable bool mPrepared;
|
||||
mutable bool mPrepared = false;
|
||||
mutable QgsExpression mExpression;
|
||||
//! Cached set of referenced columns
|
||||
mutable QSet< QString > mReferencedCols;
|
||||
|
||||
bool prepare( const QgsExpressionContext& context ) const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -171,6 +171,20 @@ QVariant QgsPropertyCollection::value( int key, const QgsExpressionContext& cont
|
||||
return prop->value( context, defaultValue );
|
||||
}
|
||||
|
||||
bool QgsPropertyCollection::prepare( const QgsExpressionContext& context ) const
|
||||
{
|
||||
bool result = true;
|
||||
QHash<int, QgsAbstractProperty*>::const_iterator it = mProperties.constBegin();
|
||||
for ( ; it != mProperties.constEnd(); ++it )
|
||||
{
|
||||
if ( !it.value()->isActive() )
|
||||
continue;
|
||||
|
||||
result = result && it.value()->prepare( context );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QSet< QString > QgsPropertyCollection::referencedFields( const QgsExpressionContext &context ) const
|
||||
{
|
||||
QSet< QString > cols;
|
||||
@ -439,6 +453,16 @@ QSet< QString > QgsPropertyCollectionStack::referencedFields( const QgsExpressio
|
||||
return cols;
|
||||
}
|
||||
|
||||
bool QgsPropertyCollectionStack::prepare( const QgsExpressionContext& context ) const
|
||||
{
|
||||
bool result = true;
|
||||
Q_FOREACH ( QgsPropertyCollection* collection, mStack )
|
||||
{
|
||||
result = result && collection->prepare( context );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QSet<int> QgsPropertyCollectionStack::propertyKeys() const
|
||||
{
|
||||
QSet<int> keys;
|
||||
|
@ -38,6 +38,8 @@ class CORE_EXPORT QgsAbstractPropertyCollection
|
||||
|
||||
QgsAbstractPropertyCollection( const QString& name = QString() );
|
||||
|
||||
virtual ~QgsAbstractPropertyCollection() = default;
|
||||
|
||||
/**
|
||||
* Returns the name of the property collection.
|
||||
* @see setName()
|
||||
@ -100,7 +102,6 @@ class CORE_EXPORT QgsAbstractPropertyCollection
|
||||
*/
|
||||
virtual QVariant value( int key, const QgsExpressionContext& context, const QVariant& defaultValue = QVariant() ) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the current value of the property with the specified key and interprets it as a color.
|
||||
* @param key integer key for property to return. The intended use case is that a context specific enum is cast to
|
||||
@ -140,6 +141,13 @@ class CORE_EXPORT QgsAbstractPropertyCollection
|
||||
*/
|
||||
int valueAsInt( int key, const QgsExpressionContext& context, int defaultValue = 0 ) const;
|
||||
|
||||
/**
|
||||
* Prepares the collection against a specified expression context. Calling prepare before evaluating the
|
||||
* collection's properties multiple times allows precalculation of expensive setup tasks such as parsing expressions.
|
||||
* Returns true if preparation was successful.
|
||||
*/
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the set of any fields referenced by the active properties from the collection.
|
||||
* @param context expression context the properties will be evaluated against.
|
||||
@ -231,6 +239,7 @@ class CORE_EXPORT QgsPropertyCollection : public QgsAbstractPropertyCollection
|
||||
QgsAbstractProperty* property( int key ) override;
|
||||
const QgsAbstractProperty* property( int key ) const override;
|
||||
QVariant value( int key, const QgsExpressionContext& context, const QVariant& defaultValue = QVariant() ) const override;
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
bool isActive( int key ) const override;
|
||||
bool hasActiveProperties() const override;
|
||||
@ -386,6 +395,7 @@ class CORE_EXPORT QgsPropertyCollectionStack : public QgsAbstractPropertyCollect
|
||||
* @param context expression context the properties will be evaluated against.
|
||||
*/
|
||||
QSet< QString > referencedFields( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
virtual bool prepare( const QgsExpressionContext& context = QgsExpressionContext() ) const override;
|
||||
|
||||
QSet<int> propertyKeys() const override;
|
||||
bool hasProperty( int key ) const override;
|
||||
|
@ -178,10 +178,12 @@ bool QgsVectorLayerDiagramProvider::prepare( const QgsRenderContext& context, QS
|
||||
|
||||
s2.setRenderer( mDiagRenderer );
|
||||
|
||||
bool result = s2.prepare( context.expressionContext() );
|
||||
|
||||
//add attributes needed by the diagram renderer
|
||||
attributeNames.unite( s2.referencedFields( context.expressionContext() ) );
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -318,6 +318,11 @@ void TestQgsProperty::fieldBasedProperty()
|
||||
QCOMPARE( defaultProperty.value( context, -1 ).toInt(), -1 );
|
||||
QVERIFY( defaultProperty.referencedFields( context ).isEmpty() );
|
||||
|
||||
//test preparation
|
||||
QgsFieldBasedProperty property3( QString( "field1" ), true );
|
||||
QVERIFY( property3.prepare( context ) );
|
||||
QCOMPARE( property3.value( context, -1 ).toInt(), 5 );
|
||||
|
||||
//saving and restoring
|
||||
|
||||
//create a test dom element
|
||||
@ -411,6 +416,13 @@ void TestQgsProperty::expressionBasedProperty()
|
||||
QCOMPARE( defaultProperty.value( context, -1 ).toInt(), -1 );
|
||||
QVERIFY( defaultProperty.referencedFields( context ).isEmpty() );
|
||||
|
||||
//preparation
|
||||
QgsExpressionBasedProperty property3( QString( "\"field1\" + \"field2\"" ), true );
|
||||
QVERIFY( property3.prepare( context ) );
|
||||
QCOMPARE( property3.value( context, -1 ).toInt(), 12 );
|
||||
QgsExpressionBasedProperty property4( QString( "\"field1\" + " ), true );
|
||||
QVERIFY( !property4.prepare( context ) );
|
||||
|
||||
//saving and restoring
|
||||
|
||||
//create a test dom element
|
||||
@ -776,6 +788,9 @@ void TestQgsProperty::propertyCollection()
|
||||
QVERIFY( collection.hasActiveProperties() );
|
||||
QVERIFY( !collection.hasActiveDynamicProperties() );
|
||||
|
||||
//preparation
|
||||
QVERIFY( collection.prepare( context ) );
|
||||
|
||||
//test bad property
|
||||
QVERIFY( !collection.property( Property2 ) );
|
||||
QVERIFY( !collection.value( Property2, context ).isValid() );
|
||||
@ -995,6 +1010,9 @@ void TestQgsProperty::collectionStack()
|
||||
QVERIFY( !stack.hasActiveDynamicProperties() );
|
||||
QVERIFY( stack.hasActiveProperties() );
|
||||
|
||||
//preparation
|
||||
QVERIFY( stack.prepare( context ) );
|
||||
|
||||
//test adding active property later in the stack
|
||||
QgsStaticProperty* property3 = new QgsStaticProperty( "value3", true );
|
||||
collection2->setProperty( Property1, property3 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user