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