Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsproperty.h
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 : : #ifndef QGSPROPERTY_H
16 : : #define QGSPROPERTY_H
17 : :
18 : : #include "qgis_core.h"
19 : : #include "qgis_sip.h"
20 : : #include "qgsexpression.h"
21 : : #include "qgsexpressioncontext.h"
22 : : #include "qgscolorramp.h"
23 : :
24 : : #include <QVariant>
25 : : #include <QHash>
26 : : #include <QString>
27 : : #include <QStringList>
28 : : #include <QDomElement>
29 : : #include <QDomDocument>
30 : : #include <QColor>
31 : : #include <QDateTime>
32 : :
33 : : class QgsPropertyTransformer;
34 : : class QgsPropertyPrivate;
35 : :
36 : : /**
37 : : * \ingroup core
38 : : * \class QgsPropertyDefinition
39 : : * \brief Definition for a property.
40 : : *
41 : : * QgsPropertyDefinition defines the type of values allowed for a property, and
42 : : * handles descriptive names and help text for using the property. Definitions
43 : : * can use one of the predefined standard templates to simplify definition of
44 : : * commonly used property types, such as colors and blend modes.
45 : : * \since QGIS 3.0
46 : : */
47 : 1570 : class CORE_EXPORT QgsPropertyDefinition
48 : : {
49 : : public:
50 : :
51 : : //! Predefined standard property templates
52 : : enum StandardPropertyTemplate
53 : : {
54 : : Boolean = 0, //!< Boolean value
55 : : Integer, //!< Integer value (including negative values)
56 : : IntegerPositive, //!< Positive integer values (including 0)
57 : : IntegerPositiveGreaterZero, //!< Non-zero positive integer values
58 : : Double, //!< Double value (including negative values)
59 : : DoublePositive, //!< Positive double value (including 0)
60 : : Double0To1, //!< Double value between 0-1 (inclusive)
61 : : Rotation, //!< Rotation (value between 0-360 degrees)
62 : : String, //!< Any string value
63 : : Opacity, //!< Opacity (0-100)
64 : : RenderUnits, //!< Render units (eg mm/pixels/map units)
65 : : ColorWithAlpha, //!< Color with alpha channel
66 : : ColorNoAlpha, //!< Color with no alpha channel
67 : : PenJoinStyle, //!< Pen join style
68 : : BlendMode, //!< Blend mode
69 : : Point, //!< 2D point
70 : : Size, //!< 1D size (eg marker radius, or square marker height/width)
71 : : Size2D, //!< 2D size (width/height different)
72 : : LineStyle, //!< Line style (eg solid/dashed)
73 : : StrokeWidth, //!< Line stroke width
74 : : FillStyle, //!< Fill style (eg solid, lines)
75 : : CapStyle, //!< Line cap style (eg round)
76 : : HorizontalAnchor, //!< Horizontal anchor point
77 : : VerticalAnchor, //!< Vertical anchor point
78 : : SvgPath, //!< Path to an SVG file
79 : : Offset, //!< 2D offset
80 : : DateTime, //!< DateTime value
81 : : Custom = 3000, //!< Custom property types
82 : : };
83 : :
84 : : //! Valid data types required by property
85 : : enum DataType
86 : : {
87 : :
88 : : /**
89 : : * Property requires a string value. No numeric values are acceptable by the property.
90 : : * Use this for properties which require a string value such as 'dashed' which cannot
91 : : * be stored in a non-string field.
92 : : */
93 : : DataTypeString = 0,
94 : :
95 : : /**
96 : : * Property requires a numeric value. Note that setting DataTypeNumeric as the required type
97 : : * means that the property also accepts string fields and inputs, as those may be convertible
98 : : * to a numeric value (Eg "1.0" -> 1.0)
99 : : */
100 : : DataTypeNumeric,
101 : :
102 : : /**
103 : : * Property requires a boolean value. Note that setting DataTypeBoolean as the required type
104 : : * means that the property also accepts string and numeric fields, as those may be convertible
105 : : * to a boolean value (Eg "1.0" -> TRUE)
106 : : */
107 : : DataTypeBoolean,
108 : : };
109 : :
110 : : /**
111 : : * Constructs an empty property.
112 : : */
113 : 5 : QgsPropertyDefinition() = default;
114 : :
115 : : /**
116 : : * Constructor for QgsPropertyDefinition, using a standard property template.
117 : : * \param name is used internally and should be a unique, alphanumeric string.
118 : : * \param description can be any localised string describing what the property is used for.
119 : : * \param type one of the predefined standard property template
120 : : * \param origin The origin of the property
121 : : * \param comment A free comment for the property
122 : : */
123 : : QgsPropertyDefinition( const QString &name, const QString &description, StandardPropertyTemplate type, const QString &origin = QString(), const QString &comment = QString() );
124 : :
125 : : /**
126 : : * Constructor for custom QgsPropertyDefinitions.
127 : : * \param name is used internally and should be a unique, alphanumeric string.
128 : : * \param dataType the data type for the property
129 : : * \param description can be any localised string describing what the property is used for.
130 : : * \param helpText parameter should specify a descriptive string for users outlining the types
131 : : * of value acceptable by the property (eg 'dashed' or 'solid' for a line style property).
132 : : * \param origin The origin of the property
133 : : * \param comment A free comment for the property
134 : : */
135 : : QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText, const QString &origin = QString(), const QString &comment = QString() );
136 : :
137 : : /**
138 : : * Returns the name of the property. This is used internally and should be a unique, alphanumeric string.
139 : : */
140 : 0 : QString name() const { return mName; }
141 : :
142 : : /**
143 : : * Sets the name of the property
144 : : */
145 : 0 : void setName( const QString &name ) { mName = name; }
146 : :
147 : : /**
148 : : * Returns the origin of the property. For example, a PAL property has an
149 : : * origin set to "labeling" while a diagram property has an origin set to
150 : : * "diagram".
151 : : */
152 : 0 : QString origin() const { return mOrigin; }
153 : :
154 : : /**
155 : : * Sets the origin of the property. For example, a PAL property has an
156 : : * origin set to "labeling" while a diagram property has an origin set to
157 : : * "diagram".
158 : : */
159 : 0 : void setOrigin( const QString &origin ) { mOrigin = origin; }
160 : :
161 : : /**
162 : : * Descriptive name of the property.
163 : : */
164 : : QString description() const { return mDescription; }
165 : :
166 : : /**
167 : : * Returns the comment of the property
168 : : */
169 : 0 : QString comment() const { return mComment; }
170 : :
171 : : /**
172 : : * Sets comment of the property
173 : : */
174 : 0 : void setComment( const QString &comment ) { mComment = comment; }
175 : :
176 : : /**
177 : : * Helper text for using the property, including a description of the valid values for the property.
178 : : */
179 : : QString helpText() const { return mHelpText; }
180 : :
181 : : /**
182 : : * Sets the data type
183 : : */
184 : 0 : void setDataType( DataType type ) { mTypes = type; }
185 : :
186 : : /**
187 : : * Returns the allowable field/value data type for the property.
188 : : */
189 : 0 : DataType dataType() const { return mTypes; }
190 : :
191 : : /**
192 : : * Returns the property's standard template, if applicable. Non standard
193 : : * types will return the Custom template.
194 : : */
195 : 0 : StandardPropertyTemplate standardTemplate() const { return mStandardType; }
196 : :
197 : : /**
198 : : * Returns TRUE if the property is of a type which is compatible with property
199 : : * override assistants.
200 : : */
201 : : bool supportsAssistant() const;
202 : :
203 : : private:
204 : :
205 : : QString mName;
206 : : QString mDescription;
207 : 5 : DataType mTypes = DataTypeString;
208 : : QString mHelpText;
209 : 5 : StandardPropertyTemplate mStandardType = Custom;
210 : : QString mOrigin;
211 : : QString mComment;
212 : :
213 : : static QString trString();
214 : : };
215 : :
216 : :
217 : : /**
218 : : * \ingroup core
219 : : * \class QgsProperty
220 : : * \brief A store for object properties.
221 : : *
222 : : * QgsProperty objects are used for storing properties for objects, which can then be transformed to
223 : : * a QVariant value by evaluating them against a supplied QgsExpressionContext. Multiple QgsProperty objects
224 : : * can be grouped using a QgsPropertyCollection for easier bulk storage, retrieval and evaluation.
225 : : *
226 : : * QgsProperty objects are implicitly shared and can be inexpensively copied.
227 : : *
228 : : * \since QGIS 3.0
229 : : */
230 : :
231 : : class CORE_EXPORT QgsProperty
232 : : {
233 : : public:
234 : :
235 : : //! Property types
236 : : enum Type
237 : : {
238 : : InvalidProperty, //!< Invalid (not set) property
239 : : StaticProperty, //!< Static property (QgsStaticProperty)
240 : : FieldBasedProperty, //!< Field based property (QgsFieldBasedProperty)
241 : : ExpressionBasedProperty, //!< Expression based property (QgsExpressionBasedProperty)
242 : : };
243 : :
244 : : /**
245 : : * Constructor for a QgsProperty. The property will be set to an InvalidProperty type.
246 : : */
247 : : QgsProperty();
248 : :
249 : : ~QgsProperty();
250 : :
251 : : /**
252 : : * Returns a new ExpressionBasedProperty created from the specified expression.
253 : : */
254 : : static QgsProperty fromExpression( const QString &expression, bool isActive = true );
255 : :
256 : : /**
257 : : * Returns a new FieldBasedProperty created from the specified field name.
258 : : */
259 : : static QgsProperty fromField( const QString &fieldName, bool isActive = true );
260 : :
261 : : /**
262 : : * Returns a new StaticProperty created from the specified value.
263 : : */
264 : : static QgsProperty fromValue( const QVariant &value, bool isActive = true );
265 : :
266 : : //! Copy constructor
267 : : QgsProperty( const QgsProperty &other );
268 : :
269 : : QgsProperty &operator=( const QgsProperty &other );
270 : :
271 : : /**
272 : : * Returns TRUE if the property is not an invalid type.
273 : : */
274 : : operator bool() const;
275 : :
276 : : bool operator==( const QgsProperty &other ) const;
277 : : bool operator!=( const QgsProperty &other ) const;
278 : :
279 : : /**
280 : : * Returns the property type.
281 : : */
282 : : Type propertyType() const;
283 : :
284 : : /**
285 : : * Returns whether the property is currently active.
286 : : * \see setActive()
287 : : */
288 : : bool isActive() const;
289 : :
290 : : /**
291 : : * Sets whether the property is currently active.
292 : : * \see isActive()
293 : : */
294 : : void setActive( bool active );
295 : :
296 : : /**
297 : : * Sets the static value for the property. Calling this will
298 : : * transform the property into an StaticProperty.
299 : : * \see staticValue()
300 : : */
301 : : void setStaticValue( const QVariant &value );
302 : :
303 : : /**
304 : : * Returns the current static value for the property. If the property
305 : : * is not a StaticProperty this will return an invalid variant.
306 : : * \see setStaticValue()
307 : : */
308 : : QVariant staticValue() const;
309 : :
310 : : /**
311 : : * Sets the field name the property references. Calling this will
312 : : * transform the property into an FieldBasedProperty.
313 : : * \see field()
314 : : */
315 : : void setField( const QString &field );
316 : :
317 : : /**
318 : : * Returns the current field name the property references. If the property
319 : : * is not a FieldBasedProperty this will return an empty string.
320 : : * \see setField()
321 : : */
322 : : QString field() const;
323 : :
324 : : /**
325 : : * Sets the expression to use for the property value. Calling this will
326 : : * transform the property into an ExpressionBasedProperty.
327 : : * \see expressionString()
328 : : */
329 : : void setExpressionString( const QString &expression );
330 : :
331 : : /**
332 : : * Returns the expression used for the property value. If the property
333 : : * is not a ExpressionBasedProperty this will return an empty string.
334 : : * \see setExpressionString()
335 : : */
336 : : QString expressionString() const;
337 : :
338 : : /**
339 : : * Returns an expression string representing the state of the property, or an empty
340 : : * string if the property could not be converted to an expression
341 : : */
342 : : QString asExpression() const;
343 : :
344 : : /**
345 : : * Prepares the property against a specified expression context. Calling prepare before evaluating the
346 : : * property multiple times allows precalculation of expensive setup tasks such as parsing expressions.
347 : : * Returns TRUE if preparation was successful.
348 : : */
349 : : bool prepare( const QgsExpressionContext &context = QgsExpressionContext() ) const;
350 : :
351 : : /**
352 : : * Returns the set of any fields referenced by the property for a specified
353 : : * expression context.
354 : : * \note The optional argument ignoreContext has been added in QGIS 3.14. When set to TRUE,
355 : : * even fields not set in context's fields() will be reported - this is useful e.g. with vector tiles
356 : : * where the actual available field names may not be known beforehand.
357 : : */
358 : : QSet< QString > referencedFields( const QgsExpressionContext &context = QgsExpressionContext(), bool ignoreContext = false ) const;
359 : :
360 : : /**
361 : : * Returns TRUE if the property is set to a linked project color.
362 : : *
363 : : * \since QGIS 3.6
364 : : */
365 : : bool isProjectColor() const;
366 : :
367 : : /**
368 : : * Calculates the current value of the property, including any transforms which are set for the property
369 : : * \param context QgsExpressionContext to evaluate the property for. The variables and functions contained
370 : : * in the expression context can be used to alter the calculated value for the property, so that a property
371 : : * is able to respond to the current environment, layers and features within QGIS.
372 : : * \param defaultValue default value to return if the property is not active or cannot be calculated
373 : : * \param ok if specified, will be set to TRUE if conversion was successful
374 : : * \returns calculated value for property
375 : : * \see valueAsString()
376 : : * \see valueAsColor()
377 : : * \see valueAsDouble()
378 : : * \see valueAsInt()
379 : : * \see valueAsBool()
380 : : */
381 : : QVariant value( const QgsExpressionContext &context, const QVariant &defaultValue = QVariant(), bool *ok SIP_OUT = nullptr ) const;
382 : :
383 : : /**
384 : : * Calculates the current value of the property and interprets it as a datetime.
385 : : * \param context QgsExpressionContext to evaluate the property for.
386 : : * \param defaultDateTime default datetime to return if the property cannot be calculated as a datetime
387 : : * \param ok if specified, will be set to TRUE if conversion was successful
388 : : * \returns value parsed to datetime
389 : : * \see value()
390 : : * \see valueAsString()
391 : : * \see valueAsColor()
392 : : * \see valueAsDouble()
393 : : * \see valueAsInt()
394 : : * \see valueAsBool()
395 : : * \since QGIS 3.14
396 : : */
397 : : QDateTime valueAsDateTime( const QgsExpressionContext &context, const QDateTime &defaultDateTime = QDateTime(), bool *ok SIP_OUT = nullptr ) const;
398 : :
399 : : /**
400 : : * Calculates the current value of the property and interprets it as a string.
401 : : * \param context QgsExpressionContext to evaluate the property for.
402 : : * \param defaultString default string to return if the property cannot be calculated as a string
403 : : * \param ok if specified, will be set to TRUE if conversion was successful
404 : : * \returns value parsed to string
405 : : * \see value()
406 : : * \see valueAsDateTime()
407 : : * \see valueAsColor()
408 : : * \see valueAsDouble()
409 : : * \see valueAsInt()
410 : : * \see valueAsBool()
411 : : */
412 : : QString valueAsString( const QgsExpressionContext &context, const QString &defaultString = QString(), bool *ok SIP_OUT = nullptr ) const;
413 : :
414 : : /**
415 : : * Calculates the current value of the property and interprets it as a color.
416 : : * \param context QgsExpressionContext to evaluate the property for.
417 : : * \param defaultColor default color to return if the property cannot be calculated as a color
418 : : * \param ok if specified, will be set to TRUE if conversion was successful
419 : : * \returns value parsed to color
420 : : * \see value()
421 : : * \see valueAsDateTime()
422 : : * \see valueAsString()
423 : : * \see valueAsDouble()
424 : : * \see valueAsInt()
425 : : * \see valueAsBool()
426 : : */
427 : : QColor valueAsColor( const QgsExpressionContext &context, const QColor &defaultColor = QColor(), bool *ok SIP_OUT = nullptr ) const;
428 : :
429 : : /**
430 : : * Calculates the current value of the property and interprets it as a double.
431 : : * \param context QgsExpressionContext to evaluate the property for.
432 : : * \param defaultValue default double to return if the property cannot be calculated as a double
433 : : * \param ok if specified, will be set to TRUE if conversion was successful
434 : : * \returns value parsed to double
435 : : * \see value()
436 : : * \see valueAsDateTime()
437 : : * \see valueAsString()
438 : : * \see valueAsColor()
439 : : * \see valueAsInt()
440 : : * \see valueAsBool()
441 : : */
442 : : double valueAsDouble( const QgsExpressionContext &context, double defaultValue = 0.0, bool *ok SIP_OUT = nullptr ) const;
443 : :
444 : : /**
445 : : * Calculates the current value of the property and interprets it as an integer.
446 : : * \param context QgsExpressionContext to evaluate the property for.
447 : : * \param defaultValue default integer to return if the property cannot be calculated as an integer
448 : : * \param ok if specified, will be set to TRUE if conversion was successful
449 : : * \returns value parsed to integer
450 : : * \see value()
451 : : * \see valueAsDateTime()
452 : : * \see valueAsString()
453 : : * \see valueAsColor()
454 : : * \see valueAsDouble()
455 : : * \see valueAsBool()
456 : : */
457 : : int valueAsInt( const QgsExpressionContext &context, int defaultValue = 0, bool *ok SIP_OUT = nullptr ) const;
458 : :
459 : : /**
460 : : * Calculates the current value of the property and interprets it as an boolean.
461 : : * \param context QgsExpressionContext to evaluate the property for.
462 : : * \param defaultValue default boolean to return if the property cannot be calculated as an boolean
463 : : * \param ok if specified, will be set to TRUE if conversion was successful
464 : : * \returns value parsed to boolean
465 : : * \see value()
466 : : * \see valueAsDateTime()
467 : : * \see valueAsString()
468 : : * \see valueAsColor()
469 : : * \see valueAsDouble()
470 : : * \see valueAsInt()
471 : : */
472 : : bool valueAsBool( const QgsExpressionContext &context, bool defaultValue = false, bool *ok SIP_OUT = nullptr ) const;
473 : :
474 : : /**
475 : : * Saves this property to a QVariantMap, wrapped in a QVariant.
476 : : * You can use QgsXmlUtils::writeVariant to save it to an XML document.
477 : : *
478 : : * \see loadVariant()
479 : : */
480 : : QVariant toVariant() const;
481 : :
482 : : /**
483 : : * Loads this property from a QVariantMap, wrapped in a QVariant.
484 : : * You can use QgsXmlUtils::readVariant to load it from an XML document.
485 : : *
486 : : * \see toVariant()
487 : : */
488 : : bool loadVariant( const QVariant &property );
489 : :
490 : : /**
491 : : * Sets an optional transformer to use for manipulating the calculated values for the property.
492 : : * \param transformer transformer to install. Ownership is transferred to the property, and any
493 : : * existing transformer will be deleted. Set to NULLPTR to remove an existing transformer.
494 : : * \see transformer()
495 : : */
496 : : void setTransformer( QgsPropertyTransformer *transformer SIP_TRANSFER );
497 : :
498 : : /**
499 : : * Returns the existing transformer used for manipulating the calculated values for the property, if set.
500 : : * \see setTransformer()
501 : : */
502 : : const QgsPropertyTransformer *transformer() const;
503 : :
504 : : /**
505 : : * Attempts to convert an existing expression based property to a base expression with
506 : : * corresponding transformer. Returns TRUE if conversion was successful. Note that
507 : : * calling this method requires multiple parsing of expressions, so it should only
508 : : * be called in non-performance critical code.
509 : : */
510 : : bool convertToTransformer();
511 : :
512 : : //! Allows direct construction of QVariants from properties.
513 : 0 : operator QVariant() const
514 : : {
515 : 0 : return QVariant::fromValue( *this );
516 : : }
517 : :
518 : :
519 : : #ifdef SIP_RUN
520 : : SIP_PYOBJECT __repr__();
521 : : % MethodCode
522 : : QString typeString;
523 : : QString definitionString;
524 : : switch ( sipCpp->propertyType() )
525 : : {
526 : : case QgsProperty::StaticProperty:
527 : : typeString = QStringLiteral( "static" );
528 : : definitionString = sipCpp->staticValue().toString();
529 : : break;
530 : :
531 : : case QgsProperty::FieldBasedProperty:
532 : : typeString = QStringLiteral( "field" );
533 : : definitionString = sipCpp->field();
534 : : break;
535 : :
536 : : case QgsProperty::ExpressionBasedProperty:
537 : : typeString = QStringLiteral( "expression" );
538 : : definitionString = sipCpp->expressionString();
539 : : break;
540 : :
541 : : case QgsProperty::InvalidProperty:
542 : : typeString = QStringLiteral( "invalid" );
543 : : break;
544 : : }
545 : :
546 : : QString str = QStringLiteral( "<QgsProperty: %1%2%3>" ).arg( !sipCpp->isActive() && sipCpp->propertyType() != QgsProperty::InvalidProperty ? QStringLiteral( "INACTIVE " ) : QString(),
547 : : typeString,
548 : : definitionString.isEmpty() ? QString() : QStringLiteral( " (%1)" ).arg( definitionString ) );
549 : : sipRes = PyUnicode_FromString( str.toUtf8().constData() );
550 : : % End
551 : : #endif
552 : :
553 : : private:
554 : :
555 : : mutable QExplicitlySharedDataPointer<QgsPropertyPrivate> d;
556 : :
557 : : /**
558 : : * Calculates the current value of the property, before any transformations or
559 : : * conversions are applied.
560 : : */
561 : : QVariant propertyValue( const QgsExpressionContext &context, const QVariant &defaultValue = QVariant(), bool *ok = nullptr ) const;
562 : :
563 : : };
564 : :
565 : 10 : Q_DECLARE_METATYPE( QgsProperty )
566 : :
567 : : #endif // QGSPROPERTY_H
|