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