QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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#include "qgsproperty_p.h"
18
19#include "qgslogger.h"
20#include "qgsexpression.h"
21#include "qgsfeature.h"
22#include "qgssymbollayerutils.h"
23#include "qgscolorramp.h"
25
26#include <QRegularExpression>
27
28QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, const QString &description, QgsPropertyDefinition::StandardPropertyTemplate type, const QString &origin, const QString &comment )
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() + QStringLiteral( "[<b>MM</b>|<b>MapUnit</b>|<b>Pixel</b>|<b>Point</b>]" );
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() + QStringLiteral( "[<b>bevel</b>|<b>miter</b>|<b>round</b>]" );
105 break;
106
107 case BlendMode:
108 mTypes = DataTypeString;
109 mHelpText = trString() + QStringLiteral( "[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
110 "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
111 "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>]" );
112 break;
113
114 case Point:
115 mTypes = DataTypeString;
116 mHelpText = QObject::tr( "double coord [<b>X,Y</b>]" );
117 break;
118
119 case Size:
120 mTypes = DataTypeNumeric;
121 mHelpText = QObject::tr( "double [≥ 0.0]" );
122 break;
123
124 case Size2D:
125 mTypes = DataTypeString;
126 mHelpText = QObject::tr( "string of doubles '<b>width,height</b>' or array of doubles <b>[width, height]</b>" );
127 break;
128
129 case LineStyle:
130 mTypes = DataTypeString;
131 mHelpText = trString() + QStringLiteral( "[<b>no</b>|<b>solid</b>|<b>dash</b>|<b>dot</b>|<b>dash dot</b>|<b>dash dot dot</b>]" );
132 break;
133
134 case StrokeWidth:
135 mTypes = DataTypeNumeric;
136 mHelpText = QObject::tr( "double [≥ 0.0]" );
137 break;
138
139 case FillStyle:
140 mTypes = DataTypeString;
141 mHelpText = trString() + QStringLiteral( "[<b>solid</b>|<b>horizontal</b>|<b>vertical</b>|<b>cross</b>|<b>b_diagonal</b>|<b>f_diagonal"
142 "</b>|<b>diagonal_x</b>|<b>dense1</b>|<b>dense2</b>|<b>dense3</b>|<b>dense4</b>|<b>dense5"
143 "</b>|<b>dense6</b>|<b>dense7</b>|<b>no]" );
144 break;
145
146 case CapStyle:
147 mTypes = DataTypeString;
148 mHelpText = trString() + QStringLiteral( "[<b>square</b>|<b>flat</b>|<b>round</b>]" );
149 break;
150
151 case HorizontalAnchor:
152 mTypes = DataTypeString;
153 mHelpText = trString() + QStringLiteral( "[<b>left</b>|<b>center</b>|<b>right</b>]" );
154 break;
155
156 case VerticalAnchor:
157 mTypes = DataTypeString;
158 mHelpText = trString() + QStringLiteral( "[<b>top</b>|<b>center</b>|<b>bottom</b>]" );
159 break;
160
161 case SvgPath:
162 mTypes = DataTypeString;
163 mHelpText = trString() + QStringLiteral( "[<b>filepath</b>] as<br>"
164 "<b>''</b>=empty|absolute|search-paths-relative|<br>"
165 "project-relative|URL" );
166 break;
167
168 case Offset:
169 mTypes = DataTypeString;
170 mHelpText = QObject::tr( "string of doubles '<b>x,y</b>' or array of doubles <b>[x, y]</b>" );
171 break;
172
173 case DateTime:
174 mTypes = DataTypeString;
175 mHelpText = QObject::tr( "DateTime or string representation of a DateTime" );
176 break;
177
178 case Custom:
179 mTypes = DataTypeString;
180 }
181}
182
183QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText, const QString &origin, const QString &comment )
184 : mName( name )
185 , mDescription( description )
186 , mTypes( dataType )
187 , mHelpText( helpText )
188 , mOrigin( origin )
189 , mComment( comment )
190{}
191
193{
194 return mTypes == DataTypeNumeric || mStandardType == Size || mStandardType == StrokeWidth || mStandardType == ColorNoAlpha || mStandardType == ColorWithAlpha
195 || mStandardType == Rotation;
196}
197
198QString QgsPropertyDefinition::trString()
199{
200 // just something to reduce translation redundancy
201 return QObject::tr( "string " );
202}
203
204//
205// QgsProperty
206//
207
208QVariantMap QgsProperty::propertyMapToVariantMap( const QMap<QString, QgsProperty> &propertyMap )
209{
210 QVariantMap variantMap;
211 QMap<QString, QgsProperty>::const_iterator it = propertyMap.constBegin();
212 for ( ; it != propertyMap.constEnd(); ++it )
213 variantMap.insert( it.key(), it.value().toVariant() );
214 return variantMap;
215}
216
217QMap<QString, QgsProperty> QgsProperty::variantMapToPropertyMap( const QVariantMap &variantMap )
218{
219 QMap<QString, QgsProperty> propertyMap;
220 QVariantMap::const_iterator it = variantMap.constBegin();
221 for ( ; it != variantMap.constEnd(); ++it )
222 {
223 QgsProperty property;
224 if ( property.loadVariant( it.value() ) )
225 propertyMap.insert( it.key(), property );
226 }
227 return propertyMap;
228}
229
231{
232 d = new QgsPropertyPrivate();
233}
234
235QgsProperty::~QgsProperty() = default;
236
237QgsProperty QgsProperty::fromExpression( const QString &expression, bool isActive )
238{
239 QgsProperty p;
240 p.setExpressionString( expression );
241 p.setActive( isActive );
242 return p;
243}
244
245QgsProperty QgsProperty::fromField( const QString &fieldName, bool isActive )
246{
247 QgsProperty p;
248 p.setField( fieldName );
249 p.setActive( isActive );
250 return p;
251}
252
253QgsProperty QgsProperty::fromValue( const QVariant &value, bool isActive )
254{
255 QgsProperty p;
257 p.setActive( isActive );
258 return p;
259}
260
261QgsProperty::QgsProperty( const QgsProperty &other ) //NOLINT
262 : d( other.d )
263{}
264
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 != StaticProperty || d->staticValue == other.d->staticValue )
276 && ( d->type != FieldBasedProperty || d->fieldName == other.d->fieldName )
277 && ( d->type != ExpressionBasedProperty || 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 static_cast< Type >( d->type );
289}
290
292{
293 return d->type != InvalidProperty && d->active;
294}
295
296bool QgsProperty::isStaticValueInContext( const QgsExpressionContext &context, QVariant &staticValue ) const
297{
298 staticValue = QVariant();
299 switch ( d->type )
300 {
301 case InvalidProperty:
302 return true;
303
304 case StaticProperty:
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();
337 d->type = StaticProperty;
338 d->staticValue = value;
339}
340
342{
343 if ( d->type != StaticProperty )
344 return QVariant();
345
346 return d->staticValue;
347}
348
349void QgsProperty::setField( const QString &field )
350{
351 d.detach();
352 d->type = FieldBasedProperty;
353 d->fieldName = field;
354 d->cachedFieldIdx = -1;
355}
356
357QString QgsProperty::field() const
358{
359 if ( d->type != FieldBasedProperty )
360 return QString();
361
362 return d->fieldName;
363}
364
365QgsProperty::operator bool() const
366{
367 return d->type != InvalidProperty;
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;
381 d->type = InvalidProperty;
382 }
383 else
384 {
385 d->type = ExpressionBasedProperty;
386 }
387}
388
390{
391 if ( d->type != ExpressionBasedProperty )
392 return QString();
393
394 return d->expressionString;
395}
396
397
399{
400 QString exp;
401 switch ( d->type )
402 {
403 case StaticProperty:
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
415 case InvalidProperty:
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 {
429 case StaticProperty:
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
458 case InvalidProperty:
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 {
473 case StaticProperty:
474 case InvalidProperty:
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 QRegularExpression rx( QStringLiteral( "^project_color\\('.*'\\)$" ) );
512 return d->type == QgsProperty::ExpressionBasedProperty && !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 {
526 case StaticProperty:
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
576 case InvalidProperty:
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.type() == QVariant::DateTime )
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.type() == QVariant::Color )
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" ), d->type );
771
772 switch ( d->type )
773 {
774 case StaticProperty:
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
787 case InvalidProperty:
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< Type >( propertyMap.value( QStringLiteral( "type" ), InvalidProperty ).toInt() );
810
811 switch ( d->type )
812 {
813 case StaticProperty:
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
835 case InvalidProperty:
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 != ExpressionBasedProperty )
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}
898
899
900
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.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:219
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:338
Container of fields for a vector layer.
Definition: qgsfields.h:45
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
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
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.
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.
Definition: qgsproperty.h:105
@ 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.
virtual bool loadVariant(const QVariant &transformer)
Loads this transformer from a QVariantMap, wrapped in a QVariant.
@ GenericNumericTransformer
Generic transformer for numeric values (QgsGenericNumericTransformer)
static QgsPropertyTransformer * create(Type type)
Factory method for creating a new property transformer of the specified type.
A store for object properties.
Definition: qgsproperty.h:230
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.
Type
Property types.
Definition: qgsproperty.h:235
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
Definition: qgsproperty.h:239
@ StaticProperty
Static property (QgsStaticProperty)
Definition: qgsproperty.h:237
@ FieldBasedProperty
Field based property (QgsFieldBasedProperty)
Definition: qgsproperty.h:238
@ InvalidProperty
Invalid (not set) property.
Definition: qgsproperty.h:236
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.
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.
Type propertyType() const
Returns the property type.
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)
Returns true if the specified variant should be considered a NULL value.
const QgsField & field
Definition: qgsfield.h:463