QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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() != Qgis::PropertyType::Static )
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}
@ Field
Field based property.
@ Static
Static property.
@ Expression
Expression based property.
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.
void clear() FINAL
Removes all collections from 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.
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 hasDynamicProperties() const final
Returns true if the collection has any active, non-static properties, or false if either all non-stat...
QVariant toVariant(const QgsPropertiesDefinition &definitions) const final
Saves this property collection to a QVariantMap, wrapped in a QVariant.
QgsPropertyCollection & operator=(const QgsPropertyCollection &other)
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
bool hasProperty(int key) const final
Returns true if the collection contains a property with the specified key.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool operator!=(const QgsPropertyCollection &other) const
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
bool operator==(const QgsPropertyCollection &other) const
bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions) final
Loads this property collection from a QVariantMap, wrapped in a QVariant.
void clear() final
Removes all properties from the collection.
int count() const
Returns the number of properties contained within the collection.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const final
Prepares the collection against a specified expression context.
bool hasActiveProperties() const final
Returns true if the collection has any active properties, or false if all properties within the colle...
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
QgsPropertyCollection(const QString &name=QString())
Constructor for QgsPropertyCollection.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const final
Returns the set of any fields referenced by the active properties from the collection.
A store for object properties.
Definition: qgsproperty.h:228
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.
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.
Qgis::PropertyType propertyType() const
Returns the property type.
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.
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.