QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
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
18#include "qgsproperty.h"
19#include "qgsxmlutils.h"
20
21//
22// QgsAbstractPropertyCollection
23//
24
30
31QDateTime QgsAbstractPropertyCollection::valueAsDateTime( int key, const QgsExpressionContext &context, const QDateTime &defaultDateTime, bool *ok ) const
32{
33 if ( ok )
34 *ok = false;
35
36 QgsProperty prop = property( key );
37 if ( !prop || !prop.isActive() )
38 return defaultDateTime;
39
40 return prop.valueAsDateTime( context, defaultDateTime, ok );
41}
42
43QString QgsAbstractPropertyCollection::valueAsString( int key, const QgsExpressionContext &context, const QString &defaultString, bool *ok ) const
44{
45 if ( ok )
46 *ok = false;
47
48 QgsProperty prop = property( key );
49 if ( !prop || !prop.isActive() )
50 return defaultString;
51
52 return prop.valueAsString( context, defaultString, ok );
53}
54
55QColor QgsAbstractPropertyCollection::valueAsColor( int key, const QgsExpressionContext &context, const QColor &defaultColor, bool *ok ) const
56{
57 if ( ok )
58 *ok = false;
59
60 QgsProperty prop = property( key );
61 if ( !prop || !prop.isActive() )
62 return defaultColor;
63
64 return prop.valueAsColor( context, defaultColor, ok );
65}
66
67double QgsAbstractPropertyCollection::valueAsDouble( int key, const QgsExpressionContext &context, double defaultValue, bool *ok ) const
68{
69 if ( ok )
70 *ok = false;
71 QgsProperty prop = property( key );
72 if ( !prop || !prop.isActive() )
73 return defaultValue;
74
75 return prop.valueAsDouble( context, defaultValue, ok );
76}
77
78int QgsAbstractPropertyCollection::valueAsInt( int key, const QgsExpressionContext &context, int defaultValue, bool *ok ) const
79{
80 if ( ok )
81 *ok = false;
82 QgsProperty prop = property( key );
83 if ( !prop || !prop.isActive() )
84 return defaultValue;
85
86 return prop.valueAsInt( context, defaultValue, ok );
87}
88
89bool QgsAbstractPropertyCollection::valueAsBool( int key, const QgsExpressionContext &context, bool defaultValue, bool *ok ) const
90{
91 if ( ok )
92 *ok = false;
93 QgsProperty prop = property( key );
94 if ( !prop || !prop.isActive() )
95 return defaultValue;
96
97 return prop.valueAsBool( context, defaultValue, ok );
98}
99
100bool QgsAbstractPropertyCollection::writeXml( QDomElement &collectionElem, const QgsPropertiesDefinition &definitions ) const
101{
102 QVariant collection = toVariant( definitions );
103 QDomDocument doc = collectionElem.ownerDocument();
104 QDomElement element = QgsXmlUtils::writeVariant( collection, doc );
105 collectionElem.appendChild( element );
106 return true;
107}
108
109bool QgsAbstractPropertyCollection::readXml( const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions )
110{
111 QVariant collection = QgsXmlUtils::readVariant( collectionElem.firstChild().toElement() );
112 return loadVariant( collection.toMap(), definitions );
113}
114
115
116
117//
118// QgsPropertyCollection
119//
120
124
127 , mProperties( other.mProperties )
128 , mDirty( other.mDirty )
129 , mHasActiveProperties( other.mHasActiveProperties )
130 , mHasDynamicProperties( other.mHasDynamicProperties )
131 , mCount( other.mCount )
132{
133 mProperties.detach();
134}
135
137{
138 if ( &other == this )
139 return *this;
140
141 QgsAbstractPropertyCollection::operator=( other );
142 mProperties = other.mProperties;
143 mProperties.detach();
144 mDirty = other.mDirty;
145 mHasActiveProperties = other.mHasActiveProperties;
146 mHasDynamicProperties = other.mHasDynamicProperties;
147 mCount = other.mCount;
148 return *this;
149}
150
152{
153 return mProperties == other.mProperties;
154}
155
157{
158 return !( *this == other );
159}
160
162{
163 if ( !mDirty )
164 return mCount;
165
166 rescan();
167 return mCount;
168}
169
171{
172 QSet<int> keys;
173 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
174 for ( ; it != mProperties.constEnd(); ++it )
175 {
176 if ( it.value() )
177 keys.insert( it.key() );
178 }
179 return keys;
180}
181
183{
184 mProperties.clear();
185 mDirty = false;
186 mHasActiveProperties = false;
187 mHasDynamicProperties = false;
188 mCount = 0;
189}
190
192{
193 if ( property )
194 mProperties.insert( key, property );
195 else
196 mProperties.remove( key );
197
198 mDirty = true;
199}
200
201void QgsPropertyCollection::setProperty( int key, const QVariant &value )
202{
203 mProperties.insert( key, QgsProperty::fromValue( value ) );
204 mDirty = true;
205}
206
208{
209 if ( mProperties.isEmpty() )
210 return false;
211
212 auto it = mProperties.constFind( key );
213 if ( it != mProperties.constEnd() )
214 return static_cast< bool >( *it );
215 return false;
216}
217
219{
220 if ( mProperties.isEmpty() )
221 return QgsProperty();
222
223 return mProperties.value( key );
224}
225
227{
228 mDirty = true;
229 return mProperties[ key ];
230}
231
232QVariant QgsPropertyCollection::value( int key, const QgsExpressionContext &context, const QVariant &defaultValue ) const
233{
234 if ( mProperties.isEmpty() )
235 return defaultValue;
236
237 QgsProperty prop = mProperties.value( key );
238 if ( !prop || !prop.isActive() )
239 return defaultValue;
240
241 return prop.value( context, defaultValue );
242}
243
245{
246 bool result = true;
247 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
248 for ( ; it != mProperties.constEnd(); ++it )
249 {
250 if ( !it.value().isActive() )
251 continue;
252
253 result = result && it.value().prepare( context );
254 }
255 return result;
256}
257
258QSet< QString > QgsPropertyCollection::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
259{
260 QSet< QString > cols;
261 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
262 for ( ; it != mProperties.constEnd(); ++it )
263 {
264 if ( !it.value().isActive() )
265 continue;
266
267 cols.unite( it.value().referencedFields( context, ignoreContext ) );
268 }
269 return cols;
270}
271
273{
274 if ( mProperties.isEmpty() )
275 return false;
276
277 auto it = mProperties.constFind( key );
278 if ( it != mProperties.constEnd() )
279 return ( *it ).isActive();
280 return false;
281}
282
283void QgsPropertyCollection::rescan() const
284{
285 mHasActiveProperties = false;
286 mHasDynamicProperties = false;
287 mCount = 0;
288 if ( !mProperties.isEmpty() )
289 {
290 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
291 for ( ; it != mProperties.constEnd(); ++it )
292 {
293 if ( it.value() )
294 mCount++;
295 if ( it.value().isActive() )
296 {
297 mHasActiveProperties = true;
298 if ( it.value().propertyType() != Qgis::PropertyType::Static )
299 {
300 mHasDynamicProperties = true;
301 }
302 }
303 }
304 }
305 mDirty = false;
306}
307
309{
310 if ( mDirty )
311 rescan();
312
313 return mHasActiveProperties;
314}
315
317{
318 if ( mDirty )
319 rescan();
320
321 return mHasDynamicProperties;
322}
323
325{
326 QVariantMap collection;
327
328 collection.insert( QStringLiteral( "name" ), name() );
329 collection.insert( QStringLiteral( "type" ), QStringLiteral( "collection" ) );
330
331 QVariantMap properties;
332
333 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
334 for ( ; it != mProperties.constEnd(); ++it )
335 {
336 if ( it.value() )
337 {
338 properties.insert( definitions.value( it.key() ).name(), it.value().toVariant() );
339 }
340 }
341 collection.insert( QStringLiteral( "properties" ), properties );
342 return collection;
343}
344
345bool QgsPropertyCollection::loadVariant( const QVariant &collection, const QgsPropertiesDefinition &definitions )
346{
347 clear();
348
349 QVariantMap collectionMap = collection.toMap();
350
351 setName( collectionMap.value( QStringLiteral( "name" ) ).toString() );
352
353 mCount = 0;
354 QVariantMap properties = collectionMap.value( QStringLiteral( "properties" ) ).toMap();
355 for ( auto propertyIterator = properties.constBegin(); propertyIterator != properties.constEnd(); ++propertyIterator )
356 {
357 // match name to int key
358 int key = -1;
359 QgsPropertiesDefinition::const_iterator it = definitions.constBegin();
360 for ( ; it != definitions.constEnd(); ++it )
361 {
362 if ( it->name() == propertyIterator.key() )
363 {
364 key = it.key();
365 break;
366 }
367 }
368
369 if ( key < 0 )
370 continue;
371
372 QgsProperty prop;
373 prop.loadVariant( propertyIterator.value() );
374 mProperties.insert( key, prop );
375
376 mCount++;
377
378 mHasActiveProperties = mHasActiveProperties || prop.isActive();
379 mHasDynamicProperties = mHasDynamicProperties ||
380 ( prop.isActive() &&
383 }
384 return true;
385}
386
387//
388// QgsPropertyCollectionStack
389//
390
395
397 : QgsAbstractPropertyCollection( other ), mStack()
398{
399 clear();
400
401 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
402 {
403 mStack << new QgsPropertyCollection( *collection );
404 }
405}
406
408{
409 if ( &other == this )
410 return *this;
411
412 setName( other.name() );
413 clear();
414
415 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
416 {
417 mStack << new QgsPropertyCollection( *collection );
418 }
419
420 return *this;
421}
422
424{
425 return mStack.size();
426}
427
429{
430 qDeleteAll( mStack );
431 mStack.clear();
432}
433
438
440{
441 return mStack.value( index );
442}
443
445{
446 return mStack.value( index );
447}
448
450{
451 const auto constMStack = mStack;
452 for ( QgsPropertyCollection *collection : constMStack )
453 {
454 if ( collection->name() == name )
455 return collection;
456 }
457 return nullptr;
458}
459
461{
462 const auto constMStack = mStack;
463 for ( const QgsPropertyCollection *collection : constMStack )
464 {
465 if ( collection->hasActiveProperties() )
466 return true;
467 }
468 return false;
469}
470
472{
473 const auto constMStack = mStack;
474 for ( const QgsPropertyCollection *collection : constMStack )
475 {
476 if ( collection->hasDynamicProperties() )
477 return true;
478 }
479 return false;
480}
481
483{
484 return static_cast< bool >( property( key ) );
485}
486
488{
489 //loop through stack looking for last active matching property
490 for ( int i = mStack.size() - 1; i >= 0; --i )
491 {
492 const QgsPropertyCollection *collection = mStack.at( i );
493 QgsProperty property = collection->property( key );
494 if ( property && property.isActive() )
495 {
496 return property;
497 }
498 }
499 //not found
500 return QgsProperty();
501}
502
503
504QVariant QgsPropertyCollectionStack::value( int key, const QgsExpressionContext &context, const QVariant &defaultValue ) const
505{
506 QgsProperty p = property( key );
507 if ( !p )
508 {
509 return defaultValue;
510 }
511 return p.value( context, defaultValue );
512}
513
514QSet< QString > QgsPropertyCollectionStack::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
515{
516 QSet< QString > cols;
517 const auto constMStack = mStack;
518 for ( QgsPropertyCollection *collection : constMStack )
519 {
520 cols.unite( collection->referencedFields( context, ignoreContext ) );
521 }
522 return cols;
523}
524
526{
527 bool result = true;
528 const auto constMStack = mStack;
529 for ( QgsPropertyCollection *collection : constMStack )
530 {
531 result = result && collection->prepare( context );
532 }
533 return result;
534}
535
537{
538 QSet<int> keys;
539 const auto constMStack = mStack;
540 for ( QgsPropertyCollection *collection : constMStack )
541 {
542 keys.unite( collection->propertyKeys() );
543 }
544 return keys;
545}
546
548{
549 const auto constMStack = mStack;
550 for ( QgsPropertyCollection *collection : constMStack )
551 {
552 if ( collection->hasProperty( key ) )
553 return true;
554 }
555 return false;
556}
557
559{
560 QVariantMap collection;
561 collection.insert( QStringLiteral( "type" ), QStringLiteral( "stack" ) );
562 collection.insert( QStringLiteral( "name" ), name() );
563
564 QVariantList properties;
565
566 const auto constMStack = mStack;
567 for ( QgsPropertyCollection *child : constMStack )
568 {
569 properties.append( child->toVariant( definitions ) );
570 }
571
572 collection.insert( QStringLiteral( "properties" ), properties );
573
574 return collection;
575}
576
578{
579 clear();
580
581 QVariantMap collectionMap = collection.toMap();
582
583 setName( collectionMap.value( QStringLiteral( "name" ) ).toString() );
584
585 QVariantList properties = collectionMap.value( QStringLiteral( "properties" ) ).toList();
586
587 const auto constProperties = properties;
588 for ( const QVariant &property : constProperties )
589 {
590 QgsPropertyCollection *propertyCollection = new QgsPropertyCollection();
591 propertyCollection->loadVariant( property.toMap(), definitions );
592 mStack.append( propertyCollection );
593 }
594
595 return true;
596}
@ Field
Field based property.
Definition qgis.h:685
@ Static
Static property.
Definition qgis.h:684
@ Expression
Expression based property.
Definition qgis.h:686
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...
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 ...
void clear() final
Removes all collections from the stack.
QgsPropertyCollectionStack()=default
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 an 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.
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.