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