QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgsproperty.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsproperty.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
16#include "qgsproperty.h"
17
18#include "qgsexpression.h"
19#include "qgsfeature.h"
20#include "qgsproperty_p.h"
21#include "qgssymbollayerutils.h"
22
23#include <QRegularExpression>
24#include <QString>
25
26using namespace Qt::StringLiterals;
27
29 : mName( name )
30 , mDescription( description )
31 , mStandardType( type )
32 , mOrigin( origin )
33 , mComment( comment )
34{
35 switch ( mStandardType )
36 {
37 case Boolean:
38 mTypes = DataTypeBoolean;
39 mHelpText = QObject::tr( "bool [<b>1</b>=True|<b>0</b>=False]" );
40 break;
41
42 case Integer:
43 mTypes = DataTypeNumeric;
44 mHelpText = QObject::tr( "int [≤ 0 ≥]" );
45 break;
46
47 case IntegerPositive:
48 mTypes = DataTypeNumeric;
49 mHelpText = QObject::tr( "int [≥ 0]" );
50 break;
51
53 mTypes = DataTypeNumeric;
54 mHelpText = QObject::tr( "int [≥ 1]" );
55 break;
56
57 case Double:
58 mTypes = DataTypeNumeric;
59 mHelpText = QObject::tr( "double [≤ 0.0 ≥]" );
60 break;
61
62 case DoublePositive:
63 mTypes = DataTypeNumeric;
64 mHelpText = QObject::tr( "double [≥ 0.0]" );
65 break;
66
67 case Double0To1:
68 mTypes = DataTypeNumeric;
69 mHelpText = QObject::tr( "double [0.0-1.0]" );
70 break;
71
72 case Rotation:
73 mTypes = DataTypeNumeric;
74 mHelpText = QObject::tr( "double [0.0-360.0]" );
75 break;
76
77 case String:
78 mTypes = DataTypeString;
79 mHelpText = QObject::tr( "string of variable length" );
80 break;
81
82 case Opacity:
83 mTypes = DataTypeNumeric;
84 mHelpText = QObject::tr( "int [0-100]" );
85 break;
86
87 case RenderUnits:
88 mTypes = DataTypeString;
89 mHelpText = trString() + u"[<b>MM</b>|<b>MapUnit</b>|<b>Pixel</b>|<b>Point</b>]"_s;
90 break;
91
92 case ColorWithAlpha:
93 mTypes = DataTypeString;
94 mHelpText = QObject::tr( "string [<b>r,g,b,a</b>] as int 0-255 or #<b>AARRGGBB</b> as hex or <b>color</b> as color's name" );
95 break;
96
97 case ColorNoAlpha:
98 mTypes = DataTypeString;
99 mHelpText = QObject::tr( "string [<b>r,g,b</b>] as int 0-255 or #<b>RRGGBB</b> as hex or <b>color</b> as color's name" );
100 break;
101
102 case PenJoinStyle:
103 mTypes = DataTypeString;
104 mHelpText = trString() + u"[<b>bevel</b>|<b>miter</b>|<b>round</b>]"_s;
105 break;
106
107 case BlendMode:
108 mTypes = DataTypeString;
109 mHelpText = trString()
110 + QStringLiteral(
111 "[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
112 "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
113 "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>]"
114 );
115 break;
116
117 case Point:
118 mTypes = DataTypeString;
119 mHelpText = QObject::tr( "double coord [<b>X,Y</b>]" );
120 break;
121
122 case Size:
123 mTypes = DataTypeNumeric;
124 mHelpText = QObject::tr( "double [≥ 0.0]" );
125 break;
126
127 case Size2D:
128 mTypes = DataTypeString;
129 mHelpText = QObject::tr( "string of doubles '<b>width,height</b>' or array of doubles <b>[width, height]</b>" );
130 break;
131
132 case LineStyle:
133 mTypes = DataTypeString;
134 mHelpText = trString() + u"[<b>no</b>|<b>solid</b>|<b>dash</b>|<b>dot</b>|<b>dash dot</b>|<b>dash dot dot</b>]"_s;
135 break;
136
137 case StrokeWidth:
138 mTypes = DataTypeNumeric;
139 mHelpText = QObject::tr( "double [≥ 0.0]" );
140 break;
141
142 case FillStyle:
143 mTypes = DataTypeString;
144 mHelpText = trString()
145 + QStringLiteral(
146 "[<b>solid</b>|<b>horizontal</b>|<b>vertical</b>|<b>cross</b>|<b>b_diagonal</b>|<b>f_diagonal"
147 "</b>|<b>diagonal_x</b>|<b>dense1</b>|<b>dense2</b>|<b>dense3</b>|<b>dense4</b>|<b>dense5"
148 "</b>|<b>dense6</b>|<b>dense7</b>|<b>no]"
149 );
150 break;
151
152 case CapStyle:
153 mTypes = DataTypeString;
154 mHelpText = trString() + u"[<b>square</b>|<b>flat</b>|<b>round</b>]"_s;
155 break;
156
157 case HorizontalAnchor:
158 mTypes = DataTypeString;
159 mHelpText = trString() + u"[<b>left</b>|<b>center</b>|<b>right</b>]"_s;
160 break;
161
162 case VerticalAnchor:
163 mTypes = DataTypeString;
164 mHelpText = trString() + u"[<b>top</b>|<b>center</b>|<b>bottom</b>]"_s;
165 break;
166
167 case SvgPath:
168 mTypes = DataTypeString;
169 mHelpText = trString()
170 + QStringLiteral(
171 "[<b>filepath</b>] as<br>"
172 "<b>''</b>=empty|absolute|search-paths-relative|<br>"
173 "project-relative|URL"
174 );
175 break;
176
177 case Offset:
178 mTypes = DataTypeString;
179 mHelpText = QObject::tr( "string of doubles '<b>x,y</b>' or array of doubles <b>[x, y]</b>" );
180 break;
181
182 case DateTime:
183 mTypes = DataTypeString;
184 mHelpText = QObject::tr( "DateTime or string representation of a DateTime" );
185 break;
186
187 case Custom:
188 mTypes = DataTypeString;
189 }
190}
191
192QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText, const QString &origin, const QString &comment )
193 : mName( name )
194 , mDescription( description )
195 , mTypes( dataType )
196 , mHelpText( helpText )
197 , mOrigin( origin )
198 , mComment( comment )
199{}
200
202{
203 return mTypes == DataTypeNumeric || mStandardType == Size || mStandardType == StrokeWidth || mStandardType == ColorNoAlpha || mStandardType == ColorWithAlpha || mStandardType == Rotation;
204}
205
206QString QgsPropertyDefinition::trString()
207{
208 // just something to reduce translation redundancy
209 return QObject::tr( "string " );
210}
211
212//
213// QgsProperty
214//
215
216QVariantMap QgsProperty::propertyMapToVariantMap( const QMap<QString, QgsProperty> &propertyMap )
217{
218 QVariantMap variantMap;
219 QMap<QString, QgsProperty>::const_iterator it = propertyMap.constBegin();
220 for ( ; it != propertyMap.constEnd(); ++it )
221 variantMap.insert( it.key(), it.value().toVariant() );
222 return variantMap;
223}
224
225QMap<QString, QgsProperty> QgsProperty::variantMapToPropertyMap( const QVariantMap &variantMap )
226{
227 QMap<QString, QgsProperty> propertyMap;
228 QVariantMap::const_iterator it = variantMap.constBegin();
229 for ( ; it != variantMap.constEnd(); ++it )
230 {
231 QgsProperty property;
232 if ( property.loadVariant( it.value() ) )
233 propertyMap.insert( it.key(), property );
234 }
235 return propertyMap;
236}
237
239{
240 d = new QgsPropertyPrivate();
241}
242
243QgsProperty::~QgsProperty() = default;
244
245QgsProperty QgsProperty::fromExpression( const QString &expression, bool isActive )
246{
247 QgsProperty p;
248 p.setExpressionString( expression );
249 p.setActive( isActive );
250 return p;
251}
252
253QgsProperty QgsProperty::fromField( const QString &fieldName, bool isActive )
254{
255 QgsProperty p;
256 p.setField( fieldName );
257 p.setActive( isActive );
258 return p;
259}
260
262{
263 QgsProperty p;
265 p.setActive( isActive );
266 return p;
267}
268
269QgsProperty::QgsProperty( const QgsProperty &other ) //NOLINT
270 : d( other.d )
271{}
272
274{
275 if ( &other == this )
276 return *this;
277
278 d = other.d;
279 return *this;
280}
281
282bool QgsProperty::operator==( const QgsProperty &other ) const
283{
284 return d->active == other.d->active
285 && d->type == other.d->type
286 && ( d->type != Qgis::PropertyType::Static || d->staticValue == other.d->staticValue )
287 && ( d->type != Qgis::PropertyType::Field || d->fieldName == other.d->fieldName )
288 && ( d->type != Qgis::PropertyType::Expression || d->expressionString == other.d->expressionString )
289 && ( ( !d->transformer && !other.d->transformer ) || ( d->transformer && other.d->transformer && d->transformer->toExpression( QString() ) == other.d->transformer->toExpression( QString() ) ) );
290}
291
292bool QgsProperty::operator!=( const QgsProperty &other ) const
293{
294 return ( !( ( *this ) == other ) );
295}
296
298{
299 return d->type;
300}
301
303{
304 return d->type != Qgis::PropertyType::Invalid && d->active;
305}
306
308{
309 staticValue = QVariant();
310 switch ( d->type )
311 {
313 return true;
314
316 staticValue = d->staticValue;
317 return true;
318
320 return false;
321
323 {
324 QgsExpression exp = d->expression;
325 if ( exp.prepare( &context ) && exp.rootNode() )
326 {
327 if ( exp.rootNode()->hasCachedStaticValue() )
328 {
330 return true;
331 }
332 }
333 return false;
334 }
335 }
336 return false;
337}
338
339void QgsProperty::setActive( bool active )
340{
341 d.detach();
342 d->active = active;
343}
344
345void QgsProperty::setStaticValue( const QVariant &value )
346{
347 d.detach();
349 d->staticValue = value;
350}
351
353{
354 if ( d->type != Qgis::PropertyType::Static )
355 return QVariant();
356
357 return d->staticValue;
358}
359
360void QgsProperty::setField( const QString &field )
361{
362 d.detach();
364 d->fieldName = field;
365 d->cachedFieldIdx = -1;
366}
367
368QString QgsProperty::field() const
369{
370 if ( d->type != Qgis::PropertyType::Field )
371 return QString();
372
373 return d->fieldName;
374}
375
376QgsProperty::operator bool() const
377{
378 return d->type != Qgis::PropertyType::Invalid;
379}
380
381void QgsProperty::setExpressionString( const QString &expression )
382{
383 d.detach();
384 d->expressionString = expression;
385 d->expression = QgsExpression( expression );
386 d->expressionPrepared = false;
387 d->expressionIsInvalid = false;
388
389 if ( d->expressionString.isEmpty() )
390 {
391 d->active = false;
393 }
394 else
395 {
397 }
398}
399
401{
402 if ( d->type != Qgis::PropertyType::Expression )
403 return QString();
404
405 return d->expressionString;
406}
407
408
410{
411 QString exp;
412 switch ( d->type )
413 {
415 exp = QgsExpression::quotedValue( d->staticValue );
416 break;
417
419 exp = QgsExpression::quotedColumnRef( d->fieldName );
420 break;
421
423 exp = d->expressionString;
424 break;
425
427 exp = QString();
428 break;
429 }
430 return d->transformer ? d->transformer->toExpression( exp ) : exp;
431}
432
433bool QgsProperty::prepare( const QgsExpressionContext &context ) const
434{
435 if ( !d->active )
436 return true;
437
438 switch ( d->type )
439 {
441 return true;
442
444 {
445 d.detach();
446 // cache field index to avoid subsequent lookups
447 const QgsFields f = context.fields();
448 d->cachedFieldIdx = f.lookupField( d->fieldName );
449 return true;
450 }
451
453 {
454 d.detach();
455 if ( !d->expression.prepare( &context ) )
456 {
457 d->expressionReferencedCols.clear();
458 d->expressionPrepared = false;
459 d->expressionIsInvalid = true;
460 return false;
461 }
462
463 d->expressionPrepared = true;
464 d->expressionIsInvalid = false;
465 d->expressionReferencedCols = d->expression.referencedColumns();
466 return true;
467 }
468
470 return true;
471 }
472
473 return false;
474}
475
476QSet<QString> QgsProperty::referencedFields( const QgsExpressionContext &context, bool ignoreContext ) const
477{
478 if ( !d->active )
479 return QSet<QString>();
480
481 switch ( d->type )
482 {
485 return QSet<QString>();
486
488 {
489 QSet< QString > fields;
490 if ( !d->fieldName.isEmpty() )
491 fields.insert( d->fieldName );
492 return fields;
493 }
494
496 {
497 if ( ignoreContext )
498 {
499 return d->expression.referencedColumns();
500 }
501
502 if ( d->expressionIsInvalid )
503 return QSet< QString >();
504
505 d.detach();
506 if ( !d->expressionPrepared && !prepare( context ) )
507 {
508 d->expressionIsInvalid = true;
509 return QSet< QString >();
510 }
511
512 return d->expressionReferencedCols;
513 }
514 }
515 return QSet<QString>();
516}
517
519{
520 if ( !d->active || d->type != Qgis::PropertyType::Expression )
521 return {};
522 return d->expression.referencedVariables();
523}
524
526{
527 const thread_local QRegularExpression rx( u"^project_color(_object|)\\('.*'\\)$"_s );
528 return d->type == Qgis::PropertyType::Expression && !d->expressionString.isEmpty() && rx.match( d->expressionString ).hasMatch();
529}
530
531QVariant QgsProperty::propertyValue( const QgsExpressionContext &context, const QVariant &defaultValue, bool *ok ) const
532{
533 if ( ok )
534 *ok = false;
535
536 if ( !d->active )
537 return defaultValue;
538
539 switch ( d->type )
540 {
542 {
543 if ( ok )
544 *ok = true;
545 return d->staticValue;
546 }
547
549 {
550 const QgsFeature f = context.feature();
551 if ( !f.isValid() )
552 return defaultValue;
553
554 //shortcut the field lookup
555 if ( d->cachedFieldIdx >= 0 )
556 {
557 if ( ok )
558 *ok = true;
559 return f.attribute( d->cachedFieldIdx );
560 }
561 prepare( context );
562 if ( d->cachedFieldIdx < 0 )
563 return defaultValue;
564
565 if ( ok )
566 *ok = true;
567 return f.attribute( d->cachedFieldIdx );
568 }
569
571 {
572 if ( d->expressionIsInvalid )
573 return defaultValue;
574
575 if ( !d->expressionPrepared && !prepare( context ) )
576 return defaultValue;
577
578 QVariant result = d->expression.evaluate( &context );
579 if ( !QgsVariantUtils::isNull( result ) )
580 {
581 if ( ok )
582 *ok = true;
583 return result;
584 }
585 else
586 {
587 return defaultValue;
588 }
589 }
590
592 return defaultValue;
593 }
594
595 return QVariant();
596}
597
598
599QVariant QgsProperty::value( const QgsExpressionContext &context, const QVariant &defaultValue, bool *ok ) const
600{
601 if ( ok )
602 *ok = false;
603
604 bool valOk = false;
605 QVariant val = propertyValue( context, defaultValue, &valOk );
606 if ( !d->transformer && !valOk ) // if transformer present, let it handle null values
607 return defaultValue;
608
609 if ( d->transformer )
610 {
611 if ( !valOk )
612 val = QVariant();
613 val = d->transformer->transform( context, val );
614 }
615
616 if ( ok )
617 *ok = true;
618
619 return val;
620}
621
622QDateTime QgsProperty::valueAsDateTime( const QgsExpressionContext &context, const QDateTime &defaultDateTime, bool *ok ) const
623{
624 bool valOk = false;
625 const QVariant val = value( context, defaultDateTime, &valOk );
626
627 if ( !valOk || QgsVariantUtils::isNull( val ) )
628 {
629 if ( ok )
630 *ok = false;
631 return defaultDateTime;
632 }
633
634 QDateTime dateTime;
635 if ( val.userType() == QMetaType::Type::QDateTime )
636 {
637 dateTime = val.value<QDateTime>();
638 }
639 else
640 {
641 dateTime = val.toDateTime();
642 }
643
644 if ( !dateTime.isValid() )
645 return defaultDateTime;
646 else
647 {
648 if ( ok )
649 *ok = true;
650 return dateTime;
651 }
652}
653
654QString QgsProperty::valueAsString( const QgsExpressionContext &context, const QString &defaultString, bool *ok ) const
655{
656 bool valOk = false;
657 const QVariant val = value( context, defaultString, &valOk );
658
659 if ( !valOk || QgsVariantUtils::isNull( val ) )
660 {
661 if ( ok )
662 *ok = false;
663 return defaultString;
664 }
665 else
666 {
667 if ( ok )
668 *ok = true;
669 return val.toString();
670 }
671}
672
673QColor QgsProperty::valueAsColor( const QgsExpressionContext &context, const QColor &defaultColor, bool *ok ) const
674{
675 if ( ok )
676 *ok = false;
677
678 bool valOk = false;
679 const QVariant val = value( context, defaultColor, &valOk );
680
681 if ( !valOk || QgsVariantUtils::isNull( val ) )
682 return defaultColor;
683
684 QColor color;
685 if ( val.userType() == QMetaType::Type::QColor )
686 {
687 color = val.value<QColor>();
688 }
689 else
690 {
691 color = QgsSymbolLayerUtils::decodeColor( val.toString() );
692 }
693
694 if ( !color.isValid() )
695 return defaultColor;
696 else
697 {
698 if ( ok )
699 *ok = true;
700 return color;
701 }
702}
703
704double QgsProperty::valueAsDouble( const QgsExpressionContext &context, double defaultValue, bool *ok ) const
705{
706 if ( ok )
707 *ok = false;
708
709 bool valOk = false;
710 const QVariant val = value( context, defaultValue, &valOk );
711
712 if ( !valOk || QgsVariantUtils::isNull( val ) )
713 return defaultValue;
714
715 bool convertOk = false;
716 const double dbl = val.toDouble( &convertOk );
717 if ( !convertOk )
718 return defaultValue;
719 else
720 {
721 if ( ok )
722 *ok = true;
723 return dbl;
724 }
725}
726
727int QgsProperty::valueAsInt( const QgsExpressionContext &context, int defaultValue, bool *ok ) const
728{
729 if ( ok )
730 *ok = false;
731
732 bool valOk = false;
733 const QVariant val = value( context, defaultValue, &valOk );
734
735 if ( !valOk || QgsVariantUtils::isNull( val ) )
736 return defaultValue;
737
738 bool convertOk = false;
739 const int integer = val.toInt( &convertOk );
740 if ( !convertOk )
741 {
742 //one more option to try
743 const double dbl = val.toDouble( &convertOk );
744 if ( convertOk )
745 {
746 if ( ok )
747 *ok = true;
748 return std::round( dbl );
749 }
750 else
751 {
752 return defaultValue;
753 }
754 }
755 else
756 {
757 if ( ok )
758 *ok = true;
759 return integer;
760 }
761}
762
763bool QgsProperty::valueAsBool( const QgsExpressionContext &context, bool defaultValue, bool *ok ) const
764{
765 if ( ok )
766 *ok = false;
767
768 bool valOk = false;
769 const QVariant val = value( context, defaultValue, &valOk );
770
771 if ( !valOk || QgsVariantUtils::isNull( val ) )
772 return defaultValue;
773
774 if ( ok )
775 *ok = true;
776 return val.toBool();
777}
778
780{
781 QVariantMap propertyMap;
782
783 propertyMap.insert( u"active"_s, d->active );
784 propertyMap.insert( u"type"_s, static_cast< int >( d->type ) );
785
786 switch ( d->type )
787 {
789 // propertyMap.insert( u"valType"_s, d->staticValue.typeName() );
790 propertyMap.insert( u"val"_s, d->staticValue.toString() );
791 break;
792
794 propertyMap.insert( u"field"_s, d->fieldName );
795 break;
796
798 propertyMap.insert( u"expression"_s, d->expressionString );
799 break;
800
802 break;
803 }
804
805 if ( d->transformer )
806 {
807 QVariantMap transformer;
808 transformer.insert( u"t"_s, d->transformer->transformerType() );
809 transformer.insert( u"d"_s, d->transformer->toVariant() );
810
811 propertyMap.insert( u"transformer"_s, transformer );
812 }
813
814 return propertyMap;
815}
816
817bool QgsProperty::loadVariant( const QVariant &property )
818{
819 const QVariantMap propertyMap = property.toMap();
820
821 d.detach();
822 d->active = propertyMap.value( u"active"_s ).toBool();
823 d->type = static_cast< Qgis::PropertyType >( propertyMap.value( u"type"_s, static_cast< int >( Qgis::PropertyType::Invalid ) ).toInt() );
824
825 switch ( d->type )
826 {
828 d->staticValue = propertyMap.value( u"val"_s );
829 // d->staticValue.convert( QVariant::nameToType( propertyElem.attribute( "valType", "QString" ).toLocal8Bit().constData() ) );
830 break;
831
833 d->fieldName = propertyMap.value( u"field"_s ).toString();
834 if ( d->fieldName.isEmpty() )
835 d->active = false;
836 break;
837
839 d->expressionString = propertyMap.value( u"expression"_s ).toString();
840 if ( d->expressionString.isEmpty() )
841 d->active = false;
842
843 d->expression = QgsExpression( d->expressionString );
844 d->expressionPrepared = false;
845 d->expressionIsInvalid = false;
846 d->expressionReferencedCols.clear();
847 break;
848
850 break;
851 }
852
853 //restore transformer if present
854 delete d->transformer;
855 d->transformer = nullptr;
856
857
858 const QVariant transform = propertyMap.value( u"transformer"_s );
859
860 if ( transform.isValid() )
861 {
862 const QVariantMap transformerMap = transform.toMap();
863
864 const QgsPropertyTransformer::Type type = static_cast< QgsPropertyTransformer::Type >( transformerMap.value( u"t"_s, QgsPropertyTransformer::GenericNumericTransformer ).toInt() );
865 std::unique_ptr< QgsPropertyTransformer > transformer( QgsPropertyTransformer::create( type ) );
866
867 if ( transformer )
868 {
869 if ( transformer->loadVariant( transformerMap.value( u"d"_s ) ) )
870 d->transformer = transformer.release();
871 }
872 }
873
874 return true;
875}
876
877
879{
880 d.detach();
881 d->transformer = transformer;
882}
883
885{
886 return d->transformer;
887}
888
890{
891 if ( d->type != Qgis::PropertyType::Expression )
892 return false;
893
894 if ( d->transformer )
895 return false; // already a transformer
896
897 QString baseExpression;
898 QString fieldName;
899 std::unique_ptr< QgsPropertyTransformer > transformer( QgsPropertyTransformer::fromExpression( d->expressionString, baseExpression, fieldName ) );
900 if ( !transformer )
901 return false;
902
903 d.detach();
904 d->transformer = transformer.release();
905 if ( !fieldName.isEmpty() )
906 setField( fieldName );
907 else
908 setExpressionString( baseExpression );
909 return true;
910}
PropertyType
Property types.
Definition qgis.h:709
@ Invalid
Invalid (not set) property.
Definition qgis.h:710
@ Field
Field based property.
Definition qgis.h:712
@ Static
Static property.
Definition qgis.h:711
@ Expression
Expression based property.
Definition qgis.h:713
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
QVariant cachedStaticValue() const
Returns the node's static cached value.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QString expression() const
Returns the original, unmodified expression string.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Container of fields for a vector layer.
Definition qgsfields.h:46
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
QString helpText() const
Helper text for using the property, including a description of the valid values for the property.
QString comment() const
Returns the comment of the property.
DataType dataType() const
Returns the allowable field/value data type for the property.
QString description() const
Descriptive name of the property.
StandardPropertyTemplate
Predefined standard property templates.
Definition qgsproperty.h:51
@ HorizontalAnchor
Horizontal anchor point.
Definition qgsproperty.h:74
@ Double
Double value (including negative values).
Definition qgsproperty.h:56
@ VerticalAnchor
Vertical anchor point.
Definition qgsproperty.h:75
@ Double0To1
Double value between 0-1 (inclusive).
Definition qgsproperty.h:58
@ FillStyle
Fill style (eg solid, lines).
Definition qgsproperty.h:72
@ StrokeWidth
Line stroke width.
Definition qgsproperty.h:71
@ LineStyle
Line style (eg solid/dashed).
Definition qgsproperty.h:70
@ Integer
Integer value (including negative values).
Definition qgsproperty.h:53
@ String
Any string value.
Definition qgsproperty.h:60
@ DateTime
DateTime value.
Definition qgsproperty.h:78
@ BlendMode
Blend mode.
Definition qgsproperty.h:66
@ Boolean
Boolean value.
Definition qgsproperty.h:52
@ RenderUnits
Render units (eg mm/pixels/map units).
Definition qgsproperty.h:62
@ PenJoinStyle
Pen join style.
Definition qgsproperty.h:65
@ SvgPath
Path to an SVG file.
Definition qgsproperty.h:76
@ IntegerPositiveGreaterZero
Non-zero positive integer values.
Definition qgsproperty.h:55
@ IntegerPositive
Positive integer values (including 0).
Definition qgsproperty.h:54
@ Opacity
Opacity (0-100).
Definition qgsproperty.h:61
@ CapStyle
Line cap style (eg round).
Definition qgsproperty.h:73
@ ColorNoAlpha
Color with no alpha channel.
Definition qgsproperty.h:64
@ Rotation
Rotation (value between 0-360 degrees).
Definition qgsproperty.h:59
@ Custom
Custom property types.
Definition qgsproperty.h:79
@ Size
1D size (eg marker radius, or square marker height/width)
Definition qgsproperty.h:68
@ ColorWithAlpha
Color with alpha channel.
Definition qgsproperty.h:63
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:57
@ Size2D
2D size (width/height different)
Definition qgsproperty.h:69
QString name() const
Returns the name of the property.
bool supportsAssistant() const
Returns true if the property is of a type which is compatible with property override assistants.
QgsPropertyDefinition()=default
Constructs an empty property.
QString origin() const
Returns the origin of the property.
DataType
Valid data types required by property.
Definition qgsproperty.h:84
@ DataTypeString
Property requires a string value.
Definition qgsproperty.h:91
@ DataTypeBoolean
Property requires a boolean value.
@ DataTypeNumeric
Property requires a numeric value.
Definition qgsproperty.h:98
Abstract base class for objects which transform the calculated value of a property.
static QgsPropertyTransformer * fromExpression(const QString &expression, QString &baseExpression, QString &fieldName)
Attempts to parse an expression into a corresponding property transformer.
@ GenericNumericTransformer
Generic transformer for numeric values (QgsGenericNumericTransformer).
static QgsPropertyTransformer * create(Type type)
Factory method for creating a new property transformer of the specified type.
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.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const
Returns the set of any fields referenced by the property for a specified expression context.
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
bool operator==(const QgsProperty &other) const
static QVariantMap propertyMapToVariantMap(const QMap< QString, QgsProperty > &propertyMap)
Convert a map of QgsProperty to a map of QVariant This is useful to save a map of properties.
QString expressionString() const
Returns the expression used for the property value.
bool convertToTransformer()
Attempts to convert an existing expression based property to a base expression with corresponding tra...
void setTransformer(QgsPropertyTransformer *transformer)
Sets an optional transformer to use for manipulating the calculated values for the property.
void setStaticValue(const QVariant &value)
Sets the static value for the property.
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.
QString field() const
Returns the current field name the property references.
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property,...
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...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
QVariant toVariant() const
Saves this property to a QVariantMap, wrapped in a QVariant.
QSet< QString > referencedVariables() const
Returns the set of any variables referenced by the property's expression.
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.
static QMap< QString, QgsProperty > variantMapToPropertyMap(const QVariantMap &variantMap)
Convert a map of QVariant to a map of QgsProperty This is useful to restore a map of properties.
void setField(const QString &field)
Sets the field name the property references.
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 prepare(const QgsExpressionContext &context=QgsExpressionContext()) const
Prepares the property against a specified expression context.
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
QVariant staticValue() const
Returns the current static value for the property.
bool operator!=(const QgsProperty &other) const
bool isStaticValueInContext(const QgsExpressionContext &context, QVariant &staticValue) const
Returns true if the property is effectively a static value in the specified context.
void setExpressionString(const QString &expression)
Sets the expression to use for the property value.
QgsProperty & operator=(const QgsProperty &other)
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
QgsProperty()
Constructor for a QgsProperty.
static QgsProperty fromValue(const QVariant &value, bool isActive=true)
Returns a new StaticProperty created from the specified value.
void setActive(bool active)
Sets whether the property is currently active.
static QColor decodeColor(const QString &str)
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.