QGIS API Documentation 4.1.0-Master (60fea48833c)
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 if ( mProperties.isEmpty() )
276 return false;
277
278 auto it = mProperties.constFind( key );
279 if ( it != mProperties.constEnd() )
280 return ( *it ).isActive();
281 return false;
282}
283
284void QgsPropertyCollection::rescan() const
285{
286 mHasActiveProperties = false;
287 mHasDynamicProperties = false;
288 mCount = 0;
289 if ( !mProperties.isEmpty() )
290 {
291 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
292 for ( ; it != mProperties.constEnd(); ++it )
293 {
294 if ( it.value() )
295 mCount++;
296 if ( it.value().isActive() )
297 {
298 mHasActiveProperties = true;
299 if ( it.value().propertyType() != Qgis::PropertyType::Static )
300 {
301 mHasDynamicProperties = true;
302 }
303 }
304 }
305 }
306 mDirty = false;
307}
308
310{
311 if ( mDirty )
312 rescan();
313
314 return mHasActiveProperties;
315}
316
318{
319 if ( mDirty )
320 rescan();
321
322 return mHasDynamicProperties;
323}
324
326{
327 QVariantMap collection;
328
329 collection.insert( u"name"_s, name() );
330 collection.insert( u"type"_s, u"collection"_s );
331
332 QVariantMap properties;
333
334 QHash<int, QgsProperty>::const_iterator it = mProperties.constBegin();
335 for ( ; it != mProperties.constEnd(); ++it )
336 {
337 if ( it.value() )
338 {
339 properties.insert( definitions.value( it.key() ).name(), it.value().toVariant() );
340 }
341 }
342 collection.insert( u"properties"_s, properties );
343 return collection;
344}
345
346bool QgsPropertyCollection::loadVariant( const QVariant &collection, const QgsPropertiesDefinition &definitions )
347{
348 clear();
349
350 QVariantMap collectionMap = collection.toMap();
351
352 setName( collectionMap.value( u"name"_s ).toString() );
353
354 mCount = 0;
355 QVariantMap properties = collectionMap.value( u"properties"_s ).toMap();
356 for ( auto propertyIterator = properties.constBegin(); propertyIterator != properties.constEnd(); ++propertyIterator )
357 {
358 // match name to int key
359 int key = -1;
360 QgsPropertiesDefinition::const_iterator it = definitions.constBegin();
361 for ( ; it != definitions.constEnd(); ++it )
362 {
363 if ( it->name() == propertyIterator.key() )
364 {
365 key = it.key();
366 break;
367 }
368 }
369
370 if ( key < 0 )
371 continue;
372
373 QgsProperty prop;
374 prop.loadVariant( propertyIterator.value() );
375 mProperties.insert( key, prop );
376
377 mCount++;
378
379 mHasActiveProperties = mHasActiveProperties || prop.isActive();
380 mHasDynamicProperties = mHasDynamicProperties || ( prop.isActive() && ( prop.propertyType() == Qgis::PropertyType::Field || prop.propertyType() == Qgis::PropertyType::Expression ) );
381 }
382 return true;
383}
384
385//
386// QgsPropertyCollectionStack
387//
388
393
396 , mStack()
397{
398 clear();
399
400 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
401 {
402 mStack << new QgsPropertyCollection( *collection );
403 }
404}
405
407{
408 if ( &other == this )
409 return *this;
410
411 setName( other.name() );
412 clear();
413
414 for ( QgsPropertyCollection *collection : std::as_const( other.mStack ) )
415 {
416 mStack << new QgsPropertyCollection( *collection );
417 }
418
419 return *this;
420}
421
423{
424 return mStack.size();
425}
426
428{
429 qDeleteAll( mStack );
430 mStack.clear();
431}
432
437
439{
440 return mStack.value( index );
441}
442
444{
445 return mStack.value( index );
446}
447
449{
450 const auto constMStack = mStack;
451 for ( QgsPropertyCollection *collection : constMStack )
452 {
453 if ( collection->name() == name )
454 return collection;
455 }
456 return nullptr;
457}
458
460{
461 const auto constMStack = mStack;
462 for ( const QgsPropertyCollection *collection : constMStack )
463 {
464 if ( collection->hasActiveProperties() )
465 return true;
466 }
467 return false;
468}
469
471{
472 const auto constMStack = mStack;
473 for ( const QgsPropertyCollection *collection : constMStack )
474 {
475 if ( collection->hasDynamicProperties() )
476 return true;
477 }
478 return false;
479}
480
482{
483 return static_cast< bool >( property( key ) );
484}
485
487{
488 //loop through stack looking for last active matching property
489 for ( int i = mStack.size() - 1; i >= 0; --i )
490 {
491 const QgsPropertyCollection *collection = mStack.at( i );
492 QgsProperty property = collection->property( key );
493 if ( property && property.isActive() )
494 {
495 return property;
496 }
497 }
498 //not found
499 return QgsProperty();
500}
501
502
503QVariant QgsPropertyCollectionStack::value( int key, const QgsExpressionContext &context, const QVariant &defaultValue ) const
504{
505 QgsProperty p = property( key );
506 if ( !p )
507 {
508 return defaultValue;
509 }
510 return p.value( context, defaultValue );
511}
512
513QSet< QString > QgsPropertyCollectionStack::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
514{
515 QSet< QString > cols;
516 const auto constMStack = mStack;
517 for ( QgsPropertyCollection *collection : constMStack )
518 {
519 cols.unite( collection->referencedFields( context, ignoreContext ) );
520 }
521 return cols;
522}
523
525{
526 bool result = true;
527 const auto constMStack = mStack;
528 for ( QgsPropertyCollection *collection : constMStack )
529 {
530 result = result && collection->prepare( context );
531 }
532 return result;
533}
534
536{
537 QSet<int> keys;
538 const auto constMStack = mStack;
539 for ( QgsPropertyCollection *collection : constMStack )
540 {
541 keys.unite( collection->propertyKeys() );
542 }
543 return keys;
544}
545
547{
548 const auto constMStack = mStack;
549 for ( QgsPropertyCollection *collection : constMStack )
550 {
551 if ( collection->hasProperty( key ) )
552 return true;
553 }
554 return false;
555}
556
558{
559 QVariantMap collection;
560 collection.insert( u"type"_s, u"stack"_s );
561 collection.insert( u"name"_s, name() );
562
563 QVariantList properties;
564
565 const auto constMStack = mStack;
566 for ( QgsPropertyCollection *child : constMStack )
567 {
568 properties.append( child->toVariant( definitions ) );
569 }
570
571 collection.insert( u"properties"_s, properties );
572
573 return collection;
574}
575
577{
578 clear();
579
580 QVariantMap collectionMap = collection.toMap();
581
582 setName( collectionMap.value( u"name"_s ).toString() );
583
584 QVariantList properties = collectionMap.value( u"properties"_s ).toList();
585
586 const auto constProperties = properties;
587 for ( const QVariant &property : constProperties )
588 {
589 QgsPropertyCollection *propertyCollection = new QgsPropertyCollection();
590 propertyCollection->loadVariant( property.toMap(), definitions );
591 mStack.append( propertyCollection );
592 }
593
594 return true;
595}
@ Field
Field based property.
Definition qgis.h:711
@ Static
Static property.
Definition qgis.h:710
@ Expression
Expression based property.
Definition qgis.h:712
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.