38 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
52 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
54 return QgsDateTimeRange();
64 if ( fieldIndex >= 0 )
70 const QDateTime min = minVal.toDateTime();
71 const QDateTime maxStartTime = maxVal.toDateTime();
73 return QgsDateTimeRange( min, maxStartTime + eventDuration );
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 );
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() );
149 bool hasStartExpression = !mStartExpression.isEmpty();
150 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 );
217 return QgsDateTimeRange();
251 QDomElement temporalNode = element.firstChildElement( QStringLiteral(
"temporal" ) );
253 setIsActive( temporalNode.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt() );
255 mMode =
static_cast< TemporalMode >( temporalNode.attribute( QStringLiteral(
"mode" ), QStringLiteral(
"0" ) ). toInt() );
257 mStartFieldName = temporalNode.attribute( QStringLiteral(
"startField" ) );
258 mEndFieldName = temporalNode.attribute( QStringLiteral(
"endField" ) );
259 mStartExpression = temporalNode.attribute( QStringLiteral(
"startExpression" ) );
260 mEndExpression = temporalNode.attribute( QStringLiteral(
"endExpression" ) );
261 mDurationFieldName = temporalNode.attribute( QStringLiteral(
"durationField" ) );
263 mFixedDuration = temporalNode.attribute( QStringLiteral(
"fixedDuration" ) ).toDouble();
264 mAccumulateFeatures = temporalNode.attribute( QStringLiteral(
"accumulate" ), QStringLiteral(
"0" ) ).toInt();
266 QDomNode rangeElement = temporalNode.namedItem( QStringLiteral(
"fixedRange" ) );
268 QDomNode begin = rangeElement.namedItem( QStringLiteral(
"start" ) );
269 QDomNode end = rangeElement.namedItem( QStringLiteral(
"end" ) );
271 QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
272 QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
274 QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
283 if ( element.isNull() )
284 return QDomElement();
286 QDomElement temporalElement = document.createElement( QStringLiteral(
"temporal" ) );
287 temporalElement.setAttribute( QStringLiteral(
"enabled" ),
isActive() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
288 temporalElement.setAttribute( QStringLiteral(
"mode" ), QString::number( mMode ) );
290 temporalElement.setAttribute( QStringLiteral(
"startField" ), mStartFieldName );
291 temporalElement.setAttribute( QStringLiteral(
"endField" ), mEndFieldName );
292 temporalElement.setAttribute( QStringLiteral(
"startExpression" ), mStartExpression );
293 temporalElement.setAttribute( QStringLiteral(
"endExpression" ), mEndExpression );
294 temporalElement.setAttribute( QStringLiteral(
"durationField" ), mDurationFieldName );
296 temporalElement.setAttribute( QStringLiteral(
"fixedDuration" ),
qgsDoubleToString( mFixedDuration ) );
297 temporalElement.setAttribute( QStringLiteral(
"accumulate" ), mAccumulateFeatures ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
299 QDomElement rangeElement = document.createElement( QStringLiteral(
"fixedRange" ) );
301 QDomElement startElement = document.createElement( QStringLiteral(
"start" ) );
302 QDomElement endElement = document.createElement( QStringLiteral(
"end" ) );
304 QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
305 QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
306 startElement.appendChild( startText );
307 endElement.appendChild( endText );
308 rangeElement.appendChild( startElement );
309 rangeElement.appendChild( endElement );
311 temporalElement.appendChild( rangeElement );
313 element.appendChild( temporalElement );
322 setIsActive( vectorCaps->hasTemporalCapabilities() );
326 switch ( vectorCaps->mode() )
343 return mStartExpression;
353 return mEndExpression;
363 return mAccumulateFeatures;
373 return mFixedDuration;
383 return mStartFieldName;
388 mStartFieldName = startFieldName;
393 return mEndFieldName;
398 mEndFieldName =
field;
403 return mDurationFieldName;
408 mDurationFieldName =
field;
413 return mDurationUnit;
418 mDurationUnit = units;
423 return QStringLiteral(
"make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
424 .arg( datetime.date().month() )
425 .arg( datetime.date().day() )
426 .arg( datetime.time().hour() )
427 .arg( datetime.time().minute() )
428 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
444 if ( mAccumulateFeatures )
447 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
453 filterRange.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
455 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
463 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
470 QString intervalExpression;
471 switch ( mDurationUnit )
518 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
527 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
530 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
535 else if ( !mStartFieldName.isEmpty() )
538 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
541 else if ( !mEndFieldName.isEmpty() )
551 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
553 return QStringLiteral(
"((%1) %2 %3) AND ((%4) > %5)" ).arg( mStartExpression,
554 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
559 else if ( !mStartExpression.isEmpty() )
561 return QStringLiteral(
"(%1) %2 %3" ).arg( mStartExpression,
562 filterRange.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
565 else if ( !mEndExpression.isEmpty() )
567 return QStringLiteral(
"(%1) > %2" ).arg( mEndExpression,
586 static QStringList sStartCandidates{ QStringLiteral(
"start" ),
587 QStringLiteral(
"begin" ),
588 QStringLiteral(
"from" )};
590 static QStringList sEndCandidates{ QStringLiteral(
"end" ),
591 QStringLiteral(
"last" ),
592 QStringLiteral(
"to" )};
594 static QStringList sSingleFieldCandidates{ QStringLiteral(
"event" ) };
597 bool foundStart =
false;
598 bool foundEnd =
false;
607 for (
const QString &candidate : sStartCandidates )
610 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
612 mStartFieldName = fldName;
620 for (
const QString &candidate : sEndCandidates )
623 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
625 mEndFieldName = fldName;
631 if ( foundStart && foundEnd )
643 for (
const QString &candidate : sSingleFieldCandidates )
646 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
648 mStartFieldName = fldName;
658 if ( foundStart && foundEnd )
660 else if ( foundStart )
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.
@ ProviderHasFixedTemporalRange
Entire dataset from provider has a fixed start and end datetime.
@ ProviderStoresFeatureDateTimeStartAndEndInSeparateFields
Dataset stores feature start and end datetimes in separate fields.
@ ProviderStoresFeatureDateTimeInstantInField
Dataset has feature datetime instants stored in a single field.
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.
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.
void setMode(TemporalMode mode)
Sets the temporal properties mode.
bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const override
Returns true if the layer should be visible and rendered for the specified time range.
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.
TemporalMode
Mode of the vector temporal properties.
@ ModeFeatureDateTimeStartAndDurationFromFields
Mode when features have a field for start time and a field for event duration.
@ ModeFeatureDateTimeInstantFromField
Mode when features have a datetime instant taken from a single field.
@ ModeFixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
@ ModeFeatureDateTimeStartAndEndFromFields
Mode when features have separate fields for start and end times.
@ ModeRedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when symbology or...
@ ModeFeatureDateTimeStartAndEndFromExpressions
Mode when features use expressions for start and end times.
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().
TemporalMode mode() const
Returns the temporal properties mode.
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...
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)