53  QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
 
   65      if ( fieldIndex >= 0 )
 
   71        const QDateTime min = minVal.toDateTime();
 
   72        const QDateTime maxStartTime = maxVal.toDateTime();
 
   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;
 
  113      const int startFieldIndex = vectorLayer->
fields().
lookupField( mStartFieldName );
 
  115      if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
 
  117        QVariant startMinVal;
 
  118        QVariant startMaxVal;
 
  125                                           endMinVal.toDateTime() ),
 
  126                                 std::max( startMaxVal.toDateTime(),
 
  127                                           endMaxVal.toDateTime() ) );
 
  129      else if ( startFieldIndex >= 0 )
 
  131        QVariant startMinVal;
 
  132        QVariant startMaxVal;
 
  135                                 startMaxVal.toDateTime() );
 
  137      else if ( endFieldIndex >= 0 )
 
  143                                 endMaxVal.toDateTime() );
 
  150      const bool hasStartExpression = !mStartExpression.isEmpty();
 
  151      const bool hasEndExpression = !mEndExpression.isEmpty();
 
  152      if ( !hasStartExpression && !hasEndExpression )
 
  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;
 
 
  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 );
 
 
  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() )
 
 
  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
 
  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( 
"<" ),
 
  497      QString intervalExpression;
 
  498      switch ( mDurationUnit )
 
  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( 
"<" ),
 
  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 ),
 
  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" ),
 
  622      QStringLiteral( 
"since" ),
 
  624      QStringLiteral( 
"anfang" ),
 
  625      QStringLiteral( 
"von" ),
 
  626      QStringLiteral( 
"ab" ),
 
  627      QStringLiteral( 
"seit" ) };
 
  629  static const QStringList sEndCandidates{ QStringLiteral( 
"end" ),
 
  630      QStringLiteral( 
"last" ),
 
  631      QStringLiteral( 
"to" ),
 
  632      QStringLiteral( 
"stop" ),
 
  634      QStringLiteral( 
"ende" ),
 
  635      QStringLiteral( 
"bis" ) };
 
  638  static const QStringList sSingleFieldCandidates{ QStringLiteral( 
"event" ) };
 
  641  bool foundStart = 
false;
 
  642  bool foundEnd = 
false;
 
  644  for ( 
const QgsField &field : fields )
 
  646    if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
 
  651      for ( 
const QString &candidate : sStartCandidates )
 
  653        const QString fldName = field.name();
 
  654        if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
 
  656          mStartFieldName = fldName;
 
  664      for ( 
const QString &candidate : sEndCandidates )
 
  666        const QString fldName = field.name();
 
  667        if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
 
  669          mEndFieldName = fldName;
 
  675    if ( foundStart && foundEnd )
 
  682    for ( 
const QgsField &field : fields )
 
  684      if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
 
  687      for ( 
const QString &candidate : sSingleFieldCandidates )
 
  689        const QString fldName = field.name();
 
  690        if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
 
  692          mStartFieldName = fldName;
 
  702  if ( foundStart && foundEnd )
 
  704  else if ( foundStart )
 
 
VectorTemporalMode
Vector layer temporal feature modes.
@ FeatureDateTimeStartAndDurationFromFields
Mode when features have a field for start time and a field for event duration.
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when symbology or...
@ FeatureDateTimeStartAndEndFromExpressions
Mode when features use expressions for start and end times.
@ FeatureDateTimeInstantFromField
Mode when features have a datetime instant taken from a single field.
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
@ FeatureDateTimeStartAndEndFromFields
Mode when features have separate fields for start and end times.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
TemporalUnit
Temporal units.
@ IrregularStep
Special 'irregular step' time unit, used for temporal data which uses irregular, non-real-world unit ...
@ Milliseconds
Milliseconds.
@ Unknown
Unknown time unit.
@ StoresFeatureDateTimeInstantInField
Dataset has feature datetime instants stored in a single field.
@ StoresFeatureDateTimeStartAndEndInSeparateFields
Dataset stores feature start and end datetimes in separate fields.
@ HasFixedTemporalRange
Entire dataset from provider has a fixed start and end datetime.
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").
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
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)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
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.
T begin() const
Returns the beginning of the range.
T end() const
Returns the upper bound of the range.
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
bool isInfinite() const
Returns true if the range consists of all possible values.
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
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
QString dateTimeExpressionLiteral(const QDateTime &datetime)