38 case Qgis::VectorTemporalMode::FixedTemporalRange:
39 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
41 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
42 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
43 case Qgis::VectorTemporalMode::RedrawLayerOnly:
44 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
45 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
53 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
55 return QgsDateTimeRange();
59 case Qgis::VectorTemporalMode::FixedTemporalRange:
62 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
65 if ( fieldIndex >= 0 )
71 const QDateTime min = minVal.toDateTime();
72 const QDateTime maxStartTime = maxVal.toDateTime();
74 return QgsDateTimeRange( min, maxStartTime + eventDuration );
79 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
82 const int durationFieldIndex = vectorLayer->
fields().
lookupField( mDurationFieldName );
83 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
85 const QDateTime minTime = vectorLayer->
minimumValue( fieldIndex ).toDateTime();
93 const QDateTime start = f.
attribute( fieldIndex ).toDateTime();
94 if ( start.isValid() )
96 const QVariant durationValue = f.
attribute( durationFieldIndex );
97 if ( durationValue.isValid() )
99 const double duration = durationValue.toDouble();
100 const QDateTime end = start.addMSecs(
QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
102 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
106 return QgsDateTimeRange( minTime, maxTime );
111 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
113 const int startFieldIndex = vectorLayer->
fields().
lookupField( mStartFieldName );
115 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
117 QVariant startMinVal;
118 QVariant startMaxVal;
124 return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
125 endMinVal.toDateTime() ),
126 std::max( startMaxVal.toDateTime(),
127 endMaxVal.toDateTime() ) );
129 else if ( startFieldIndex >= 0 )
131 QVariant startMinVal;
132 QVariant startMaxVal;
134 return QgsDateTimeRange( startMinVal.toDateTime(),
135 startMaxVal.toDateTime() );
137 else if ( endFieldIndex >= 0 )
142 return QgsDateTimeRange( endMinVal.toDateTime(),
143 endMaxVal.toDateTime() );
148 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
150 const bool hasStartExpression = !mStartExpression.isEmpty();
151 const bool hasEndExpression = !mEndExpression.isEmpty();
152 if ( !hasStartExpression && !hasEndExpression )
153 return QgsDateTimeRange();
163 if ( hasStartExpression )
170 if ( hasEndExpression )
176 QSet< QString > fields;
177 if ( hasStartExpression )
179 if ( hasEndExpression )
195 const QDateTime start = hasStartExpression ?
startExpression.evaluate( &context ).toDateTime() : QDateTime();
196 const QDateTime end = hasEndExpression ?
endExpression.evaluate( &context ).toDateTime() : QDateTime();
198 if ( start.isValid() )
200 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
201 if ( !hasEndExpression )
202 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
206 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
207 if ( !hasStartExpression )
208 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
211 return QgsDateTimeRange( minTime, maxTime );
214 case Qgis::VectorTemporalMode::RedrawLayerOnly:
218 return QgsDateTimeRange();
264 const QDomElement temporalNode = element.firstChildElement( QStringLiteral(
"temporal" ) );
266 setIsActive( temporalNode.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt() );
268 mMode =
static_cast< Qgis::VectorTemporalMode >( temporalNode.attribute( QStringLiteral(
"mode" ), QStringLiteral(
"0" ) ). toInt() );
270 mLimitMode =
static_cast< Qgis::VectorTemporalLimitMode >( temporalNode.attribute( QStringLiteral(
"limitMode" ), QStringLiteral(
"0" ) ). toInt() );
271 mStartFieldName = temporalNode.attribute( QStringLiteral(
"startField" ) );
272 mEndFieldName = temporalNode.attribute( QStringLiteral(
"endField" ) );
273 mStartExpression = temporalNode.attribute( QStringLiteral(
"startExpression" ) );
274 mEndExpression = temporalNode.attribute( QStringLiteral(
"endExpression" ) );
275 mDurationFieldName = temporalNode.attribute( QStringLiteral(
"durationField" ) );
277 mFixedDuration = temporalNode.attribute( QStringLiteral(
"fixedDuration" ) ).toDouble();
278 mAccumulateFeatures = temporalNode.attribute( QStringLiteral(
"accumulate" ), QStringLiteral(
"0" ) ).toInt();
280 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral(
"fixedRange" ) );
282 const QDomNode begin = rangeElement.namedItem( QStringLiteral(
"start" ) );
283 const QDomNode end = rangeElement.namedItem( QStringLiteral(
"end" ) );
285 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
286 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
288 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
297 if ( element.isNull() )
298 return QDomElement();
300 QDomElement temporalElement = document.createElement( QStringLiteral(
"temporal" ) );
301 temporalElement.setAttribute( QStringLiteral(
"enabled" ),
isActive() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
302 temporalElement.setAttribute( QStringLiteral(
"mode" ), QString::number(
static_cast< int >( mMode ) ) );
304 temporalElement.setAttribute( QStringLiteral(
"limitMode" ), QString::number(
static_cast< int >( mLimitMode ) ) );
305 temporalElement.setAttribute( QStringLiteral(
"startField" ), mStartFieldName );
306 temporalElement.setAttribute( QStringLiteral(
"endField" ), mEndFieldName );
307 temporalElement.setAttribute( QStringLiteral(
"startExpression" ), mStartExpression );
308 temporalElement.setAttribute( QStringLiteral(
"endExpression" ), mEndExpression );
309 temporalElement.setAttribute( QStringLiteral(
"durationField" ), mDurationFieldName );
311 temporalElement.setAttribute( QStringLiteral(
"fixedDuration" ),
qgsDoubleToString( mFixedDuration ) );
312 temporalElement.setAttribute( QStringLiteral(
"accumulate" ), mAccumulateFeatures ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
314 QDomElement rangeElement = document.createElement( QStringLiteral(
"fixedRange" ) );
316 QDomElement startElement = document.createElement( QStringLiteral(
"start" ) );
317 QDomElement endElement = document.createElement( QStringLiteral(
"end" ) );
319 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
320 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
321 startElement.appendChild( startText );
322 endElement.appendChild( endText );
323 rangeElement.appendChild( startElement );
324 rangeElement.appendChild( endElement );
326 temporalElement.appendChild( rangeElement );
328 element.appendChild( temporalElement );
337 setIsActive( vectorCaps->hasTemporalCapabilities() );
341 switch ( vectorCaps->mode() )
343 case Qgis::VectorDataProviderTemporalMode::HasFixedTemporalRange:
344 setMode( Qgis::VectorTemporalMode::FixedTemporalRange );
346 case Qgis::VectorDataProviderTemporalMode::StoresFeatureDateTimeInstantInField:
347 setMode( Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField );
349 case Qgis::VectorDataProviderTemporalMode::StoresFeatureDateTimeStartAndEndInSeparateFields:
350 setMode( Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields );
358 return mStartExpression;
368 return mEndExpression;
378 return mAccumulateFeatures;
388 return mFixedDuration;
398 return mStartFieldName;
403 mStartFieldName = startFieldName;
408 return mEndFieldName;
413 mEndFieldName =
field;
418 return mDurationFieldName;
423 mDurationFieldName =
field;
428 return mDurationUnit;
433 mDurationUnit = units;
438 return QStringLiteral(
"make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
439 .arg( datetime.date().month() )
440 .arg( datetime.date().day() )
441 .arg( datetime.time().hour() )
442 .arg( datetime.time().minute() )
443 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
451 auto dateTimefieldCast = [ &context ](
const QString & fieldName ) -> QString
464 case Qgis::VectorTemporalMode::FixedTemporalRange:
465 case Qgis::VectorTemporalMode::RedrawLayerOnly:
468 case Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField:
470 if ( mAccumulateFeatures )
472 return QStringLiteral(
"(%1 %2 %3) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
473 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
478 return QStringLiteral(
"(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
479 filterRange.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
481 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
487 return QStringLiteral(
"(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
490 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
495 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndDurationFromFields:
497 QString intervalExpression;
498 switch ( mDurationUnit )
500 case Qgis::TemporalUnit::Milliseconds:
504 case Qgis::TemporalUnit::Seconds:
508 case Qgis::TemporalUnit::Minutes:
512 case Qgis::TemporalUnit::Hours:
516 case Qgis::TemporalUnit::Days:
520 case Qgis::TemporalUnit::Weeks:
524 case Qgis::TemporalUnit::Months:
528 case Qgis::TemporalUnit::Years:
532 case Qgis::TemporalUnit::Decades:
536 case Qgis::TemporalUnit::Centuries:
540 case Qgis::TemporalUnit::Unknown:
541 case Qgis::TemporalUnit::IrregularStep:
544 return QStringLiteral(
"(%1 %2 %3 OR %1 IS NULL) AND ((%1 + %4 %5 %6) OR %7 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
545 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
553 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields:
555 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
557 return QStringLiteral(
"(%1 %2 %3 OR %1 IS NULL) AND (%4 %5 %6 OR %4 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
558 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
560 dateTimefieldCast( mEndFieldName ),
565 else if ( !mStartFieldName.isEmpty() )
567 return QStringLiteral(
"%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
568 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
571 else if ( !mEndFieldName.isEmpty() )
573 return QStringLiteral(
"%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mEndFieldName ),
580 case Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromExpressions:
582 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
584 return QStringLiteral(
"((%1) %2 %3) AND ((%4) %5 %6)" ).arg( mStartExpression,
585 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
591 else if ( !mStartExpression.isEmpty() )
593 return QStringLiteral(
"(%1) %2 %3" ).arg( mStartExpression,
594 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
597 else if ( !mEndExpression.isEmpty() )
599 return QStringLiteral(
"(%1) %2 %3" ).arg( mEndExpression,
619 static const QStringList sStartCandidates{ QStringLiteral(
"start" ),
620 QStringLiteral(
"begin" ),
621 QStringLiteral(
"from" )};
623 static const QStringList sEndCandidates{ QStringLiteral(
"end" ),
624 QStringLiteral(
"last" ),
625 QStringLiteral(
"to" )};
627 static const QStringList sSingleFieldCandidates{ QStringLiteral(
"event" ) };
630 bool foundStart =
false;
631 bool foundEnd =
false;
640 for (
const QString &candidate : sStartCandidates )
643 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
645 mStartFieldName = fldName;
653 for (
const QString &candidate : sEndCandidates )
656 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
658 mEndFieldName = fldName;
664 if ( foundStart && foundEnd )
676 for (
const QString &candidate : sSingleFieldCandidates )
679 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
681 mStartFieldName = fldName;
691 if ( foundStart && foundEnd )
692 mMode = Qgis::VectorTemporalMode::FeatureDateTimeStartAndEndFromFields;
693 else if ( foundStart )
694 mMode = Qgis::VectorTemporalMode::FeatureDateTimeInstantFromField;
VectorTemporalMode
Vector layer temporal feature modes.
TemporalUnit
Temporal units.
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.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
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 Qgis::TemporalUnit decodeTemporalUnit(const QString &string, bool *ok=nullptr)
Decodes a temporal unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to 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.
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.
void setDurationUnits(Qgis::TemporalUnit units)
Sets the units of the event's duration.
QString endField() const
Returns the name of the end datetime field, which contains the end time for the feature's time spans.
QString createFilterString(const QgsVectorLayerTemporalContext &context, const QgsDateTimeRange &range) const
Creates a QGIS expression filter string for filtering features within the specified context to those ...
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
Qgis::TemporalUnit durationUnits() const
Returns the units of the event's duration.
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 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)