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