QGIS API Documentation 3.27.0-Master (0a97e3138f)
qgspropertycollection.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspropertycollection.cpp
3 -------------------------
4 Date : January 2017
5 Copyright : (C) 2017 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "qgsproperty.h"
18#include "qgsxmlutils.h"
19
20//
21// QgsAbstractPropertyCollection
22//
23
25 : mName( name )
26{
27
28}
29
30QDateTime QgsAbstractPropertyCollection::valueAsDateTime( int key, const QgsExpressionContext &context, const QDateTime &defaultDateTime, bool *ok ) const
31{
32 if ( ok )
33 *ok = false;
34
35 QgsProperty prop = property( key );
36 if ( !prop || !prop.isActive() )
37 return defaultDateTime;
38
39 return prop.valueAsDateTime( context, defaultDateTime, ok );
40}
41
42QString QgsAbstractPropertyCollection::valueAsString( int key, const QgsExpressionContext &context, const QString &defaultString, bool *ok ) const
43{
44 if ( ok )
45 *ok = false;
46
47 QgsProperty prop = property( key );
48 if ( !prop || !prop.isActive() )
49 return defaultString;
50
51 return prop.valueAsString( context, defaultString, ok );
52}
53
54QColor QgsAbstractPropertyCollection::valueAsColor( int key, const QgsExpressionContext &context, const QColor &defaultColor, bool *ok ) const
55{
56 if ( ok )
57 *ok = false;
58
59 QgsProperty prop = property( key );
60 if ( !prop || !prop.isActive() )
61 return defaultColor;
62
63 return prop.valueAsColor( context, defaultColor, ok );
64}
65
66double QgsAbstractPropertyCollection::valueAsDouble( int key, const QgsExpressionContext &context, double defaultValue, bool *ok ) const
67{
68 if ( ok )
69 *ok = false;
70 QgsProperty prop = property( key );
71 if ( !prop || !prop.isActive() )
72 return defaultValue;
73
74 return prop.valueAsDouble( context, defaultValue, ok );
75}
76
77int QgsAbstractPropertyCollection::valueAsInt( int key, const QgsExpressionContext &context, int defaultValue, bool *ok ) const
78{
79 if ( ok )
80 *ok = false;
81 QgsProperty prop = property( key );
82 if ( !prop || !prop.isActive() )
83 return defaultValue;
84
85 return prop.valueAsInt( context, defaultValue, ok );
86}
87
88bool QgsAbstractPropertyCollection::valueAsBool( int key, const QgsExpressionContext &context, bool defaultValue, bool *ok ) const
89{
90 if ( ok )
91 *ok = false;
92 QgsProperty prop = property( key );
93 if ( !prop || !prop.isActive() )
94 return defaultValue;
95
96 return prop.valueAsBool( context, defaultValue, ok );
97}
98
99bool QgsAbstractPropertyCollection::writeXml( QDomElement &collectionElem, const QgsPropertiesDefinition &definitions ) const
100{
101 QVariant collection = toVariant( definitions );
102 QDomDocument doc = collectionElem.ownerDocument();
103 QDomElement element = QgsXmlUtils::writeVariant( collection, doc );
104 collectionElem.appendChild( element );
105 return true;
106}
107
108bool QgsAbstractPropertyCollection::readXml( const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions )
109{
110 QVariant collection = QgsXmlUtils::readVariant( collectionElem.firstChild().toElement() );
111 return loadVariant( collection.toMap(), definitions );
112}
113
114
115
116//
117// QgsPropertyCollection
118//
119
122{}
123
126 , mProperties( other.mProperties )
127 , mDirty( other.mDirty )
128 , mHasActiveProperties( other.mHasActiveProperties )
129 , mHasDynamicProperties( other.mHasDynamicProperties )
130 , mCount( other.mCount )
131{
132 mProperties.detach();
133}
134
136{
137 QgsAbstractPropertyCollection::operator=( other );
138 mProperties = other.mProperties;
139 mProperties.detach();
140 mDirty = other.mDirty;
141 mHasActiveProperties = other.mHasActiveProperties;
142 mHasDynamicProperties = other.mHasDynamicProperties;
143 mCount = other.mCount;
144 return *this;
145}
146
148{
149 return mProperties == other.mProperties;
150}
151
153{
154 return !( *this == other );
155}
156
158{
159 if ( !mDirty )
160 return mCount;
161
162 rescan();
163 return mCount;
164}
165
167{
168 QSet<int> keys;
169 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
170 for ( ; it != mProperties.constEnd(); ++it )
171 {
172 if ( it.value() )
173 keys.insert( it.key() );
174 }
175 return keys;
176}
177
179{
180 mProperties.clear();
181 mDirty = false;
182 mHasActiveProperties = false;
183 mHasDynamicProperties = false;
184 mCount = 0;
185}
186
187void QgsPropertyCollection::setProperty( int key, const QgsProperty &property )
188{
189 if ( property )
190 mProperties.insert( key, property );
191 else
192 mProperties.remove( key );
193
194 mDirty = true;
195}
196
197void QgsPropertyCollection::setProperty( int key, const QVariant &value )
198{
199 mProperties.insert( key, QgsProperty::fromValue( value ) );
200 mDirty = true;
201}
202
204{
205 if ( mProperties.isEmpty() )
206 return false;
207
208 auto it = mProperties.constFind( key );
209 if ( it != mProperties.constEnd() )
210 return ( *it );
211 return false;
212}
213
215{
216 if ( mProperties.isEmpty() )
217 return QgsProperty();
218
219 return mProperties.value( key );
220}
221
223{
224 mDirty = true;
225 return mProperties[ key ];
226}
227
228QVariant QgsPropertyCollection::value( int key, const QgsExpressionContext &context, const QVariant &defaultValue ) const
229{
230 if ( mProperties.isEmpty() )
231 return defaultValue;
232
233 QgsProperty prop = mProperties.value( key );
234 if ( !prop || !prop.isActive() )
235 return defaultValue;
236
237 return prop.value( context, defaultValue );
238}
239
241{
242 bool result = true;
243 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
244 for ( ; it != mProperties.constEnd(); ++it )
245 {
246 if ( !it.value().isActive() )
247 continue;
248
249 result = result && it.value().prepare( context );
250 }
251 return result;
252}
253
254QSet< QString > QgsPropertyCollection::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
255{
256 QSet< QString > cols;
257 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
258 for ( ; it != mProperties.constEnd(); ++it )
259 {
260 if ( !it.value().isActive() )
261 continue;
262
263 cols.unite( it.value().referencedFields( context, ignoreContext ) );
264 }
265 return cols;
266}
267
269{
270 if ( mProperties.isEmpty() )
271 return false;
272
273 auto it = mProperties.constFind( key );
274 if ( it != mProperties.constEnd() )
275 return ( *it ).isActive();
276 return false;
277}
278
279void QgsPropertyCollection::rescan() const
280{
281 mHasActiveProperties = false;
282 mHasDynamicProperties = false;
283 mCount = 0;
284 if ( !mProperties.isEmpty() )
285 {
286 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
287 for ( ; it != mProperties.constEnd(); ++it )
288 {
289 if ( it.value() )
290 mCount++;
291 if ( it.value().isActive() )
292 {
293 mHasActiveProperties = true;
294 if ( it.value().propertyType() != QgsProperty::StaticProperty )
295 {
296 mHasDynamicProperties = true;
297 }
298 }
299 }
300 }
301 mDirty = false;
302}
303
305{
306 if ( mDirty )
307 rescan();
308
309 return mHasActiveProperties;
310}
311
313{
314 if ( mDirty )
315 rescan();
316
317 return mHasDynamicProperties;
318}
319
321{
322 QVariantMap collection;
323
324 collection.insert( QStringLiteral( "name" ), name() );
325 collection.insert( QStringLiteral( "type" ), QStringLiteral( "collection" ) );
326
327 QVariantMap properties;
328
329 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
330 for ( ; it != mProperties.constEnd(); ++it )
331 {
332 if ( it.value() )
333 {
334 properties.insert( definitions.value( it.key() ).name(), it.value().toVariant() );
335 }
336 }
337 collection.insert( QStringLiteral( "properties" ), properties );
338 return collection;
339}
340
341bool QgsPropertyCollection::loadVariant( const QVariant &collection, const QgsPropertiesDefinition &definitions )
342{
343 clear();
344
345 QVariantMap collectionMap = collection.toMap();
346
347 setName( collectionMap.value( QStringLiteral( "name" ) ).toString() );
348
349 mCount = 0;
350 QVariantMap properties = collectionMap.value( QStringLiteral( "properties" ) ).toMap();
351 for ( auto propertyIterator = properties.constBegin(); propertyIterator != properties.constEnd(); ++propertyIterator )
352 {
353 // match name to int key
354 int key = -1;
355 QgsPropertiesDefinition::const_iterator it = definitions.constBegin();
356 for ( ; it != definitions.constEnd(); ++it )
357 {
358 if ( it->name() == propertyIterator.key() )
359 {
360 key = it.key();
361 break;
362 }
363 }
364
365 if ( key < 0 )
366 continue;
367
368 QgsProperty prop;
369 prop.loadVariant( propertyIterator.value() );
370 mProperties.insert( key, prop );
371
372 mCount++;
373
374 mHasActiveProperties = mHasActiveProperties || prop.isActive();
375 mHasDynamicProperties = mHasDynamicProperties ||
376 ( prop.isActive() &&
379 }
380 return true;
381}
382
383//
384// QgsPropertyCollectionStack
385//
386
388{
389 clear();
390}
391
393 : QgsAbstractPropertyCollection( other ), mStack()
394{
395 clear();
396
397 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
398 {
399 mStack << new QgsPropertyCollection( *collection );
400 }
401}
402
404{
405 setName( other.name() );
406 clear();
407
408 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
409 {
410 mStack << new QgsPropertyCollection( *collection );
411 }
412
413 return *this;
414}
415
417{
418 return mStack.size();
419}
420
422{
423 qDeleteAll( mStack );
424 mStack.clear();
425}
426
428{
429 mStack.append( collection );
430}
431
433{
434 return mStack.value( index );
435}
436
438{
439 return mStack.value( index );
440}
441
443{
444 const auto constMStack = mStack;
445 for ( QgsPropertyCollection *collection : constMStack )
446 {
447 if ( collection->name() == name )
448 return collection;
449 }
450 return nullptr;
451}
452
454{
455 const auto constMStack = mStack;
456 for ( const QgsPropertyCollection *collection : constMStack )
457 {
459 return true;
460 }
461 return false;
462}
463
465{
466 const auto constMStack = mStack;
467 for ( const QgsPropertyCollection *collection : constMStack )
468 {
470 return true;
471 }
472 return false;
473}
474
476{
477 return static_cast< bool >( property( key ) );
478}
479
481{
482 //loop through stack looking for last active matching property
483 for ( int i = mStack.size() - 1; i >= 0; --i )
484 {
485 const QgsPropertyCollection *collection = mStack.at( i );
486 QgsProperty property = collection->property( key );
487 if ( property && property.isActive() )
488 {
489 return property;
490 }
491 }
492 //not found
493 return QgsProperty();
494}
495
496
497QVariant QgsPropertyCollectionStack::value( int key, const QgsExpressionContext &context, const QVariant &defaultValue ) const
498{
499 QgsProperty p = property( key );
500 if ( !p )
501 {
502 return defaultValue;
503 }
504 return p.value( context, defaultValue );
505}
506
507QSet< QString > QgsPropertyCollectionStack::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
508{
509 QSet< QString > cols;
510 const auto constMStack = mStack;
511 for ( QgsPropertyCollection *collection : constMStack )
512 {
513 cols.unite( collection->referencedFields( context, ignoreContext ) );
514 }
515 return cols;
516}
517
519{
520 bool result = true;
521 const auto constMStack = mStack;
522 for ( QgsPropertyCollection *collection : constMStack )
523 {
524 result = result && collection->prepare( context );
525 }
526 return result;
527}
528
530{
531 QSet<int> keys;
532 const auto constMStack = mStack;
533 for ( QgsPropertyCollection *collection : constMStack )
534 {
535 keys.unite( collection->propertyKeys() );
536 }
537 return keys;
538}
539
541{
542 const auto constMStack = mStack;
543 for ( QgsPropertyCollection *collection : constMStack )
544 {
545 if ( collection->hasProperty( key ) )
546 return true;
547 }
548 return false;
549}
550
552{
553 QVariantMap collection;
554 collection.insert( QStringLiteral( "type" ), QStringLiteral( "stack" ) );
555 collection.insert( QStringLiteral( "name" ), name() );
556
557 QVariantList properties;
558
559 const auto constMStack = mStack;
560 for ( QgsPropertyCollection *child : constMStack )
561 {
562 properties.append( child->toVariant( definitions ) );
563 }
564
565 collection.insert( QStringLiteral( "properties" ), properties );
566
567 return collection;
568}
569
570bool QgsPropertyCollectionStack::loadVariant( const QVariant &collection, const QgsPropertiesDefinition &definitions )
571{
572 clear();
573
574 QVariantMap collectionMap = collection.toMap();
575
576 setName( collectionMap.value( QStringLiteral( "name" ) ).toString() );
577
578 QVariantList properties = collectionMap.value( QStringLiteral( "properties" ) ).toList();
579
580 const auto constProperties = properties;
581 for ( const QVariant &property : constProperties )
582 {
583 QgsPropertyCollection *propertyCollection = new QgsPropertyCollection();
584 propertyCollection->loadVariant( property.toMap(), definitions );
585 mStack.append( propertyCollection );
586 }
587
588 return true;
589}
Abstract base class for QgsPropertyCollection like objects.
void setName(const QString &name)
Sets the descriptive name for the property collection.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
QDateTime valueAsDateTime(int key, const QgsExpressionContext &context, const QDateTime &defaultDateTime=QDateTime(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a datetime.
int valueAsInt(int key, const QgsExpressionContext &context, int defaultValue=0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an integer.
virtual QgsProperty property(int key) const =0
Returns a matching property from the collection, if one exists.
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QgsAbstractPropertyCollection(const QString &name=QString())
Constructor for QgsAbstractPropertyCollection.
virtual bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions)=0
Loads this property collection from a QVariantMap, wrapped in a QVariant.
QString name() const
Returns the descriptive name of the property collection.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
virtual QVariant toVariant(const QgsPropertiesDefinition &definitions) const =0
Saves this property collection to a QVariantMap, wrapped in a QVariant.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An ordered stack of QgsPropertyCollection containers, where collections added later to the stack will...
QgsPropertyCollectionStack & operator=(const QgsPropertyCollectionStack &other)
int count() const
Returns the number of collections contained within the stack.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the highest priority property with the specified key from within the ...
QgsPropertyCollectionStack()=default
Constructor for QgsPropertyCollectionStack.
bool hasProperty(int key) const override
Returns true if the collection contains a property with the specified key.
void appendCollection(QgsPropertyCollection *collection)
Appends a collection to the end of the stack, and transfers ownership of the collection to the stack.
QgsPropertyCollection * at(int index)
Returns the collection at the corresponding index from the stack.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const override
Returns the set of any fields referenced by the active properties from the stack.
bool loadVariant(const QVariant &collection, const QgsPropertiesDefinition &definitions) override
Loads this property collection from a QVariantMap, wrapped in a QVariant.
QgsProperty property(int key) const override
Returns the highest priority property with a matching key from within the stack.
void clear() override
Removes all collections from the stack.
bool isActive(int key) const override
Returns true if the stack contains an active property with the specified key.
QgsPropertyCollection * collection(const QString &name)
Returns the first collection with a matching name from the stack.
bool hasDynamicProperties() const override
Returns true if the collection has any active, non-static properties, or false if either all non-stat...
QVariant toVariant(const QgsPropertiesDefinition &definitions) const override
Saves this property collection to a QVariantMap, wrapped in a QVariant.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
bool hasProperty(int key) const override
Returns true if the collection contains a property with the specified key.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QgsPropertyCollection & operator=(const QgsPropertyCollection &other)
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions) override
Loads this property collection from a QVariantMap, wrapped in a QVariant.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const override
Returns the set of any fields referenced by the active properties from the collection.
bool operator!=(const QgsPropertyCollection &other) const
bool operator==(const QgsPropertyCollection &other) const
QVariant toVariant(const QgsPropertiesDefinition &definitions) const override
Saves this property collection to a QVariantMap, wrapped in a QVariant.
bool hasDynamicProperties() const override
Returns true if the collection has any active, non-static properties, or false if either all non-stat...
int count() const
Returns the number of properties contained within the collection.
void clear() override
Removes all properties from the collection.
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
QgsPropertyCollection(const QString &name=QString())
Constructor for QgsPropertyCollection.
A store for object properties.
Definition: qgsproperty.h:231
QDateTime valueAsDateTime(const QgsExpressionContext &context, const QDateTime &defaultDateTime=QDateTime(), bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a datetime.
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
Definition: qgsproperty.h:240
@ StaticProperty
Static property (QgsStaticProperty)
Definition: qgsproperty.h:238
@ FieldBasedProperty
Field based property (QgsFieldBasedProperty)
Definition: qgsproperty.h:239
QColor valueAsColor(const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a color.
QString valueAsString(const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a string.
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
bool isActive() const
Returns whether the property is currently active.
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
int valueAsInt(const QgsExpressionContext &context, int defaultValue=0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as an integer.
bool valueAsBool(const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as an boolean.
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
Type propertyType() const
Returns the property type.
static QgsProperty fromValue(const QVariant &value, bool isActive=true)
Returns a new StaticProperty created from the specified value.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.