37 case Qgis::VectorTemporalMode::FixedTemporalRange:
38 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
40 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
41 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
42 case Qgis::VectorTemporalMode::RedrawLayerOnly:
43 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
44 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
52 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
54 return QgsDateTimeRange();
58 case Qgis::VectorTemporalMode::FixedTemporalRange:
61 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
64 if ( fieldIndex >= 0 )
70 const QDateTime min = minVal.toDateTime();
71 const QDateTime maxStartTime = maxVal.toDateTime();
73 return QgsDateTimeRange( min, maxStartTime + eventDuration );
78 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
81 const int durationFieldIndex = vectorLayer->
fields().
lookupField( mDurationFieldName );
82 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
84 const QDateTime minTime = vectorLayer->
minimumValue( fieldIndex ).toDateTime();
92 const QDateTime start = f.
attribute( fieldIndex ).toDateTime();
93 if ( start.isValid() )
95 const QVariant durationValue = f.
attribute( durationFieldIndex );
96 if ( durationValue.isValid() )
98 const double duration = durationValue.toDouble();
99 const QDateTime end = start.addMSecs(
QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
101 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
105 return QgsDateTimeRange( minTime, maxTime );
110 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
112 const int startFieldIndex = vectorLayer->
fields().
lookupField( mStartFieldName );
114 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
116 QVariant startMinVal;
117 QVariant startMaxVal;
123 return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
124 endMinVal.toDateTime() ),
125 std::max( startMaxVal.toDateTime(),
126 endMaxVal.toDateTime() ) );
128 else if ( startFieldIndex >= 0 )
130 QVariant startMinVal;
131 QVariant startMaxVal;
133 return QgsDateTimeRange( startMinVal.toDateTime(),
134 startMaxVal.toDateTime() );
136 else if ( endFieldIndex >= 0 )
141 return QgsDateTimeRange( endMinVal.toDateTime(),
142 endMaxVal.toDateTime() );
147 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
149 const bool hasStartExpression = !mStartExpression.isEmpty();
150 const bool hasEndExpression = !mEndExpression.isEmpty();
151 if ( !hasStartExpression && !hasEndExpression )
152 return QgsDateTimeRange();
162 if ( hasStartExpression )
169 if ( hasEndExpression )
175 QSet< QString > fields;
176 if ( hasStartExpression )
178 if ( hasEndExpression )
194 const QDateTime start = hasStartExpression ?
startExpression.evaluate( &context ).toDateTime() : QDateTime();
195 const QDateTime end = hasEndExpression ?
endExpression.evaluate( &context ).toDateTime() : QDateTime();
197 if ( start.isValid() )
199 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
200 if ( !hasEndExpression )
201 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
205 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
206 if ( !hasStartExpression )
207 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
210 return QgsDateTimeRange( minTime, maxTime );
213 case Qgis::VectorTemporalMode::RedrawLayerOnly:
217 return QgsDateTimeRange();
263 const QDomElement temporalNode = element.firstChildElement( QStringLiteral(
"temporal" ) );
265 setIsActive( temporalNode.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt() );
267 mMode =
static_cast< Qgis::VectorTemporalMode >( temporalNode.attribute( QStringLiteral(
"mode" ), QStringLiteral(
"0" ) ). toInt() );
269 mLimitMode =
static_cast< Qgis::VectorTemporalLimitMode >( temporalNode.attribute( QStringLiteral(
"limitMode" ), QStringLiteral(
"0" ) ). toInt() );
270 mStartFieldName = temporalNode.attribute( QStringLiteral(
"startField" ) );
271 mEndFieldName = temporalNode.attribute( QStringLiteral(
"endField" ) );
272 mStartExpression = temporalNode.attribute( QStringLiteral(
"startExpression" ) );
273 mEndExpression = temporalNode.attribute( QStringLiteral(
"endExpression" ) );
274 mDurationFieldName = temporalNode.attribute( QStringLiteral(
"durationField" ) );
276 mFixedDuration = temporalNode.attribute( QStringLiteral(
"fixedDuration" ) ).toDouble();
277 mAccumulateFeatures = temporalNode.attribute( QStringLiteral(
"accumulate" ), QStringLiteral(
"0" ) ).toInt();
279 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral(
"fixedRange" ) );
281 const QDomNode begin = rangeElement.namedItem( QStringLiteral(
"start" ) );
282 const QDomNode end = rangeElement.namedItem( QStringLiteral(
"end" ) );
284 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
285 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
287 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
296 if ( element.isNull() )
297 return QDomElement();
299 QDomElement temporalElement = document.createElement( QStringLiteral(
"temporal" ) );
300 temporalElement.setAttribute( QStringLiteral(
"enabled" ),
isActive() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
301 temporalElement.setAttribute( QStringLiteral(
"mode" ), QString::number(
static_cast< int >( mMode ) ) );
303 temporalElement.setAttribute( QStringLiteral(
"limitMode" ), QString::number(
static_cast< int >( mLimitMode ) ) );
304 temporalElement.setAttribute( QStringLiteral(
"startField" ), mStartFieldName );
305 temporalElement.setAttribute( QStringLiteral(
"endField" ), mEndFieldName );
306 temporalElement.setAttribute( QStringLiteral(
"startExpression" ), mStartExpression );
307 temporalElement.setAttribute( QStringLiteral(
"endExpression" ), mEndExpression );
308 temporalElement.setAttribute( QStringLiteral(
"durationField" ), mDurationFieldName );
310 temporalElement.setAttribute( QStringLiteral(
"fixedDuration" ),
qgsDoubleToString( mFixedDuration ) );
311 temporalElement.setAttribute( QStringLiteral(
"accumulate" ), mAccumulateFeatures ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
313 QDomElement rangeElement = document.createElement( QStringLiteral(
"fixedRange" ) );
315 QDomElement startElement = document.createElement( QStringLiteral(
"start" ) );
316 QDomElement endElement = document.createElement( QStringLiteral(
"end" ) );
318 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
319 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
320 startElement.appendChild( startText );
321 endElement.appendChild( endText );
322 rangeElement.appendChild( startElement );
323 rangeElement.appendChild( endElement );
325 temporalElement.appendChild( rangeElement );
327 element.appendChild( temporalElement );
336 setIsActive( vectorCaps->hasTemporalCapabilities() );
340 switch ( vectorCaps->mode() )
342 case Qgis::VectorDataProviderTemporalMode::HasFixedTemporalRange:
343 setMode( Qgis::VectorTemporalMode::FixedTemporalRange );
345 case Qgis::VectorDataProviderTemporalMode::StoresFeatureDateTimeInstantInField:
346 setMode( Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField );
348 case Qgis::VectorDataProviderTemporalMode::StoresFeatureDateTimeStartAndEndInSeparateFields:
349 setMode( Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields );
357 return mStartExpression;
367 return mEndExpression;
377 return mAccumulateFeatures;
387 return mFixedDuration;
397 return mStartFieldName;
402 mStartFieldName = startFieldName;
407 return mEndFieldName;
412 mEndFieldName =
field;
417 return mDurationFieldName;
422 mDurationFieldName =
field;
427 return mDurationUnit;
432 mDurationUnit = units;
437 return QStringLiteral(
"make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
438 .arg( datetime.date().month() )
439 .arg( datetime.date().day() )
440 .arg( datetime.time().hour() )
441 .arg( datetime.time().minute() )
442 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
452 case Qgis::VectorTemporalMode::FixedTemporalRange:
453 case Qgis::VectorTemporalMode::RedrawLayerOnly:
456 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
458 if ( mAccumulateFeatures )
461 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
467 filterRange.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
469 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
478 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
483 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
485 QString intervalExpression;
486 switch ( mDurationUnit )
533 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
541 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
543 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
546 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
553 else if ( !mStartFieldName.isEmpty() )
556 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
559 else if ( !mEndFieldName.isEmpty() )
568 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
570 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
572 return QStringLiteral(
"((%1) %2 %3) AND ((%4) %5 %6)" ).arg( mStartExpression,
573 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
579 else if ( !mStartExpression.isEmpty() )
581 return QStringLiteral(
"(%1) %2 %3" ).arg( mStartExpression,
582 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
585 else if ( !mEndExpression.isEmpty() )
587 return QStringLiteral(
"(%1) %2 %3" ).arg( mEndExpression,
607 static const QStringList sStartCandidates{ QStringLiteral(
"start" ),
608 QStringLiteral(
"begin" ),
609 QStringLiteral(
"from" )};
611 static const QStringList sEndCandidates{ QStringLiteral(
"end" ),
612 QStringLiteral(
"last" ),
613 QStringLiteral(
"to" )};
615 static const QStringList sSingleFieldCandidates{ QStringLiteral(
"event" ) };
618 bool foundStart =
false;
619 bool foundEnd =
false;
628 for (
const QString &candidate : sStartCandidates )
631 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
633 mStartFieldName = fldName;
641 for (
const QString &candidate : sEndCandidates )
644 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
646 mEndFieldName = fldName;
652 if ( foundStart && foundEnd )
664 for (
const QString &candidate : sSingleFieldCandidates )
667 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
669 mStartFieldName = fldName;
679 if ( foundStart && foundEnd )
680 mMode = Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields;
681 else if ( foundStart )
682 mMode = Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField;
VectorTemporalMode
Vector layer temporal feature modes.
VectorTemporalLimitMode
Mode for the handling of the limits of the filtering timeframe for vector features.
@ IncludeBeginIncludeEnd
Mode to include both limits of the filtering timeframe.
Base class for handling properties relating to a data provider's temporal capabilities.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A representation of the interval between two datetime values.
Base class for storage of map layer temporal properties.
Base class for all map layer types.
The class is used as a container of context for various read/write operations on other objects.
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
TemporalUnit
Temporal units.
@ TemporalUnknownUnit
Unknown time unit.
@ TemporalMilliseconds
Milliseconds.
@ TemporalIrregularStep
Special "irregular step" time unit, used for temporal data which uses irregular, non-real-world unit ...
@ TemporalDecades
Decades.
@ TemporalCenturies
Centuries.
@ TemporalSeconds
Seconds.
@ TemporalMinutes
Minutes.
static Q_INVOKABLE QgsUnitTypes::TemporalUnit decodeTemporalUnit(const QString &string, bool *ok=nullptr)
Decodes a temporal unit from a string.
Implementation of data provider temporal properties for QgsVectorDataProviders.
Encapsulates the context in which a QgsVectorLayer's temporal capabilities will be applied.
QgsVectorLayer * layer() const
Returns the associated layer.
void setLayer(QgsVectorLayer *layer)
Sets the associated layer.
void guessDefaultsFromFields(const QgsFields &fields)
Attempts to setup the temporal properties by scanning a set of fields and looking for standard naming...
QString endExpression() const
Returns the expression for the end time for the feature's time spans.
void setDurationField(const QString &field)
Sets the name of the duration field, which contains the duration of the event.
void setMode(Qgis::VectorTemporalMode mode)
Sets the temporal properties mode.
QgsVectorLayerTemporalProperties(QObject *parent=nullptr, bool enabled=false)
Constructor for QgsVectorLayerTemporalProperties, with the specified parent object.
void setStartExpression(const QString &expression)
Sets the expression to use for the start time for the feature's time spans.
bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const override
Returns true if the layer should be visible and rendered for the specified time range.
Qgis::VectorTemporalLimitMode limitMode() const
Returns the temporal limit mode (to include or exclude begin/end limits).
void setLimitMode(Qgis::VectorTemporalLimitMode mode)
Sets the temporal limit mode (to include or exclude begin/end limits).
const QgsDateTimeRange & fixedTemporalRange() const
Returns the fixed temporal range for the layer.
double fixedDuration() const
Returns the fixed duration length, which contains the duration of the event.
bool accumulateFeatures() const
Returns true if features will be accumulated over time (i.e.
QgsTemporalProperty::Flags flags() const override
Returns flags associated to the temporal property.
void setFixedTemporalRange(const QgsDateTimeRange &range)
Sets a temporal range to apply to the whole layer.
QgsUnitTypes::TemporalUnit durationUnits() const
Returns the units of the event's duration.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads temporal properties from a DOM element previously written by writeXml().
void setEndExpression(const QString &endExpression)
Sets the expression to use for the end time for the feature's time spans.
QString durationField() const
Returns the name of the duration field, which contains the duration of the event.
QString endField() const
Returns the name of the end datetime field, which contains the end time for the feature's time spans.
void setDurationUnits(QgsUnitTypes::TemporalUnit units)
Sets the units of the event's duration.
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
void setAccumulateFeatures(bool accumulate)
Sets whether features will be accumulated over time (i.e.
void setFixedDuration(double duration)
Sets the fixed event duration, which contains the duration of the event.
void setEndField(const QString &field)
Sets the name of the end datetime field, which contains the end time for the feature's time spans.
QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const override
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Qgis::VectorTemporalMode mode() const
Returns the temporal properties mode.
QString createFilterString(QgsVectorLayerTemporalContext context, const QgsDateTimeRange &range) const
Creates a QGIS expression filter string for filtering features within the specified context to those ...
QString startField() const
Returns the name of the start datetime field, which contains the start time for the feature's time sp...
void setStartField(const QString &field)
Sets the name of the start datetime field, which contains the start time for the feature's time spans...
QString startExpression() const
Returns the expression for the start time for the feature's time spans.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< int > QgsAttributeList
QString dateTimeExpressionLiteral(const QDateTime &datetime)