QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsvectorlayertemporalproperties.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayertemporalproperties.cpp
3  ---------------
4  begin : May 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
20 #include "qgsexpression.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsfields.h"
24 
26  : QgsMapLayerTemporalProperties( parent, enabled )
27 {
28 }
29 
30 bool QgsVectorLayerTemporalProperties::isVisibleInTemporalRange( const QgsDateTimeRange &range ) const
31 {
32  if ( !isActive() )
33  return true;
34 
35  switch ( mMode )
36  {
38  return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
39 
45  return true;
46  }
47  return true;
48 }
49 
51 {
52  QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
53  if ( !layer )
54  return QgsDateTimeRange();
55 
56  switch ( mMode )
57  {
59  return mFixedRange;
60 
62  {
63  const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
64  if ( fieldIndex >= 0 )
65  {
66  QVariant minVal;
67  QVariant maxVal;
68  vectorLayer->minimumAndMaximumValue( fieldIndex, minVal, maxVal );
69 
70  const QDateTime min = minVal.toDateTime();
71  const QDateTime maxStartTime = maxVal.toDateTime();
72  const QgsInterval eventDuration = QgsInterval( mFixedDuration, mDurationUnit );
73  return QgsDateTimeRange( min, maxStartTime + eventDuration );
74  }
75  break;
76  }
77 
79  {
80  const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
81  const int durationFieldIndex = vectorLayer->fields().lookupField( mDurationFieldName );
82  if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
83  {
84  const QDateTime minTime = vectorLayer->minimumValue( fieldIndex ).toDateTime();
85  // no choice here but to loop through all features to calculate max time :(
86 
87  QgsFeature f;
88  QgsFeatureIterator it = vectorLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() << durationFieldIndex << fieldIndex ) );
89  QDateTime maxTime;
90  while ( it.nextFeature( f ) )
91  {
92  const QDateTime start = f.attribute( fieldIndex ).toDateTime();
93  if ( start.isValid() )
94  {
95  const QVariant durationValue = f.attribute( durationFieldIndex );
96  if ( durationValue.isValid() )
97  {
98  const double duration = durationValue.toDouble();
99  const QDateTime end = start.addMSecs( QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
100  if ( end.isValid() )
101  maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
102  }
103  }
104  }
105  return QgsDateTimeRange( minTime, maxTime );
106  }
107  break;
108  }
109 
111  {
112  const int startFieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
113  const int endFieldIndex = vectorLayer->fields().lookupField( mEndFieldName );
114  if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
115  {
116  QVariant startMinVal;
117  QVariant startMaxVal;
118  vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
119  QVariant endMinVal;
120  QVariant endMaxVal;
121  vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
122 
123  return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
124  endMinVal.toDateTime() ),
125  std::max( startMaxVal.toDateTime(),
126  endMaxVal.toDateTime() ) );
127  }
128  else if ( startFieldIndex >= 0 )
129  {
130  QVariant startMinVal;
131  QVariant startMaxVal;
132  vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
133  return QgsDateTimeRange( startMinVal.toDateTime(),
134  startMaxVal.toDateTime() );
135  }
136  else if ( endFieldIndex >= 0 )
137  {
138  QVariant endMinVal;
139  QVariant endMaxVal;
140  vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
141  return QgsDateTimeRange( endMinVal.toDateTime(),
142  endMaxVal.toDateTime() );
143  }
144  break;
145  }
146 
148  {
149  bool hasStartExpression = !mStartExpression.isEmpty();
150  bool hasEndExpression = !mEndExpression.isEmpty();
151  if ( !hasStartExpression && !hasEndExpression )
152  return QgsDateTimeRange();
153 
154  QDateTime minTime;
155  QDateTime maxTime;
156 
157  // no choice here but to loop through all features
158  QgsExpressionContext context;
160 
162  if ( hasStartExpression )
163  {
164  startExpression.setExpression( mStartExpression );
165  startExpression.prepare( &context );
166  }
167 
169  if ( hasEndExpression )
170  {
171  endExpression.setExpression( mEndExpression );
172  endExpression.prepare( &context );
173  }
174 
175  QSet< QString > fields;
176  if ( hasStartExpression )
177  fields.unite( startExpression.referencedColumns() );
178  if ( hasEndExpression )
179  fields.unite( endExpression.referencedColumns() );
180 
181  const bool needsGeom = startExpression.needsGeometry() || endExpression.needsGeometry();
182 
183  QgsFeatureRequest req;
184  if ( !needsGeom )
186 
187  req.setSubsetOfAttributes( fields, vectorLayer->fields() );
188 
189  QgsFeature f;
190  QgsFeatureIterator it = vectorLayer->getFeatures( req );
191  while ( it.nextFeature( f ) )
192  {
193  context.setFeature( f );
194  const QDateTime start = hasStartExpression ? startExpression.evaluate( &context ).toDateTime() : QDateTime();
195  const QDateTime end = hasEndExpression ? endExpression.evaluate( &context ).toDateTime() : QDateTime();
196 
197  if ( start.isValid() )
198  {
199  minTime = minTime.isValid() ? std::min( minTime, start ) : start;
200  if ( !hasEndExpression )
201  maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
202  }
203  if ( end.isValid() )
204  {
205  maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
206  if ( !hasStartExpression )
207  minTime = minTime.isValid() ? std::min( minTime, end ) : end;
208  }
209  }
210  return QgsDateTimeRange( minTime, maxTime );
211  }
212 
214  break;
215  }
216 
217  return QgsDateTimeRange();
218 }
219 
221 {
222  return mMode;
223 }
224 
226 {
227  if ( mMode == mode )
228  return;
229  mMode = mode;
230 }
231 
232 QgsTemporalProperty::Flags QgsVectorLayerTemporalProperties::flags() const
233 {
235 }
236 
237 void QgsVectorLayerTemporalProperties::setFixedTemporalRange( const QgsDateTimeRange &range )
238 {
239  mFixedRange = range;
240 }
241 
243 {
244  return mFixedRange;
245 }
246 
247 bool QgsVectorLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
248 {
249  Q_UNUSED( context )
250 
251  QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
252 
253  setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
254 
255  mMode = static_cast< TemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
256 
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" ) );
262  mDurationUnit = QgsUnitTypes::decodeTemporalUnit( temporalNode.attribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( QgsUnitTypes::TemporalMinutes ) ) );
263  mFixedDuration = temporalNode.attribute( QStringLiteral( "fixedDuration" ) ).toDouble();
264  mAccumulateFeatures = temporalNode.attribute( QStringLiteral( "accumulate" ), QStringLiteral( "0" ) ).toInt();
265 
266  QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
267 
268  QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
269  QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
270 
271  QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
272  QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
273 
274  QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
275  setFixedTemporalRange( range );
276 
277  return true;
278 }
279 
280 QDomElement QgsVectorLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
281 {
282  Q_UNUSED( context )
283  if ( element.isNull() )
284  return QDomElement();
285 
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 ) );
289 
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 );
295  temporalElement.setAttribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( mDurationUnit ) );
296  temporalElement.setAttribute( QStringLiteral( "fixedDuration" ), qgsDoubleToString( mFixedDuration ) );
297  temporalElement.setAttribute( QStringLiteral( "accumulate" ), mAccumulateFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
298 
299  QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
300 
301  QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
302  QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
303 
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 );
310 
311  temporalElement.appendChild( rangeElement );
312 
313  element.appendChild( temporalElement );
314 
315  return element;
316 }
317 
319 {
320  if ( const QgsVectorDataProviderTemporalCapabilities *vectorCaps = dynamic_cast< const QgsVectorDataProviderTemporalCapabilities *>( capabilities ) )
321  {
322  setIsActive( vectorCaps->hasTemporalCapabilities() );
323  setFixedTemporalRange( vectorCaps->availableTemporalRange() );
324  setStartField( vectorCaps->startField() );
325  setEndField( vectorCaps->endField() );
326  switch ( vectorCaps->mode() )
327  {
330  break;
333  break;
336  break;
337  }
338  }
339 }
340 
342 {
343  return mStartExpression;
344 }
345 
346 void QgsVectorLayerTemporalProperties::setStartExpression( const QString &startExpression )
347 {
348  mStartExpression = startExpression;
349 }
350 
352 {
353  return mEndExpression;
354 }
355 
356 void QgsVectorLayerTemporalProperties::setEndExpression( const QString &endExpression )
357 {
358  mEndExpression = endExpression;
359 }
360 
362 {
363  return mAccumulateFeatures;
364 }
365 
367 {
368  mAccumulateFeatures = accumulateFeatures;
369 }
370 
372 {
373  return mFixedDuration;
374 }
375 
377 {
378  mFixedDuration = fixedDuration;
379 }
380 
382 {
383  return mStartFieldName;
384 }
385 
386 void QgsVectorLayerTemporalProperties::setStartField( const QString &startFieldName )
387 {
388  mStartFieldName = startFieldName;
389 }
390 
392 {
393  return mEndFieldName;
394 }
395 
397 {
398  mEndFieldName = field;
399 }
400 
402 {
403  return mDurationFieldName;
404 }
405 
407 {
408  mDurationFieldName = field;
409 }
410 
412 {
413  return mDurationUnit;
414 }
415 
417 {
418  mDurationUnit = units;
419 }
420 
421 QString dateTimeExpressionLiteral( const QDateTime &datetime )
422 {
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 );
429 }
430 
431 QString QgsVectorLayerTemporalProperties::createFilterString( QgsVectorLayerTemporalContext, const QgsDateTimeRange &filterRange ) const
432 {
433  if ( !isActive() )
434  return QString();
435 
436  switch ( mMode )
437  {
439  case ModeRedrawLayerOnly:
440  return QString();
441 
443  {
444  if ( mAccumulateFeatures )
445  {
446  return QStringLiteral( "(%1 %2 %3) OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
447  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
448  dateTimeExpressionLiteral( filterRange.end() ) );
449  }
450  else if ( qgsDoubleNear( mFixedDuration, 0.0 ) )
451  {
452  return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
453  filterRange.includeBeginning() ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
454  dateTimeExpressionLiteral( filterRange.begin() ),
455  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
456  dateTimeExpressionLiteral( filterRange.end() ) );
457  }
458  else
459  {
460  // Working with features with events with a duration, so taking this duration into account (+ QgsInterval( -mFixedDuration, mDurationUnit ) ))
461  return QStringLiteral( "(%1 > %2 AND %1 %3 %4) OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
462  dateTimeExpressionLiteral( filterRange.begin() + QgsInterval( -mFixedDuration, mDurationUnit ) ),
463  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
464  dateTimeExpressionLiteral( filterRange.end() ) );
465  }
466  }
467 
469  {
470  QString intervalExpression;
471  switch ( mDurationUnit )
472  {
474  intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1/1000)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
475  break;
476 
478  intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
479  break;
480 
482  intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,%1,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
483  break;
484 
486  intervalExpression = QStringLiteral( "make_interval(0,0,0,0,%1,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
487  break;
488 
490  intervalExpression = QStringLiteral( "make_interval(0,0,0,%1,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
491  break;
492 
494  intervalExpression = QStringLiteral( "make_interval(0,0,%1,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
495  break;
496 
498  intervalExpression = QStringLiteral( "make_interval(0,%1,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
499  break;
500 
502  intervalExpression = QStringLiteral( "make_interval(%1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
503  break;
504 
506  intervalExpression = QStringLiteral( "make_interval(10 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
507  break;
508 
510  intervalExpression = QStringLiteral( "make_interval(100 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
511  break;
512 
515  return QString();
516  }
517  return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND ((%1 + %4 > %5) OR %6 IS NULL)" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
518  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
519  dateTimeExpressionLiteral( filterRange.end() ),
520  intervalExpression,
521  dateTimeExpressionLiteral( filterRange.begin() ),
522  QgsExpression::quotedColumnRef( mDurationFieldName ) );
523  }
524 
526  {
527  if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
528  {
529  return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND (%4 > %5 OR %4 IS NULL)" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
530  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
531  dateTimeExpressionLiteral( filterRange.end() ),
532  QgsExpression::quotedColumnRef( mEndFieldName ),
533  dateTimeExpressionLiteral( filterRange.begin() ) );
534  }
535  else if ( !mStartFieldName.isEmpty() )
536  {
537  return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
538  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
539  dateTimeExpressionLiteral( filterRange.end() ) );
540  }
541  else if ( !mEndFieldName.isEmpty() )
542  {
543  return QStringLiteral( "%1 > %2 OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mEndFieldName ),
544  dateTimeExpressionLiteral( filterRange.begin() ) );
545  }
546  break;
547  }
548 
550  {
551  if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
552  {
553  return QStringLiteral( "((%1) %2 %3) AND ((%4) > %5)" ).arg( mStartExpression,
554  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
555  dateTimeExpressionLiteral( filterRange.end() ),
556  mEndExpression,
557  dateTimeExpressionLiteral( filterRange.begin() ) );
558  }
559  else if ( !mStartExpression.isEmpty() )
560  {
561  return QStringLiteral( "(%1) %2 %3" ).arg( mStartExpression,
562  filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
563  dateTimeExpressionLiteral( filterRange.end() ) );
564  }
565  else if ( !mEndExpression.isEmpty() )
566  {
567  return QStringLiteral( "(%1) > %2" ).arg( mEndExpression,
568  dateTimeExpressionLiteral( filterRange.begin() ) );
569  }
570  break;
571  }
572  }
573 
574  return QString();
575 }
576 
578 {
579 
580  // Check the fields and keep the first one that matches.
581  // We assume that the user has organized the data with the
582  // more "interesting" field names first.
583  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
584  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
585  // but adding hardcoded localized variants of the strings is encouraged.
586  static QStringList sStartCandidates{ QStringLiteral( "start" ),
587  QStringLiteral( "begin" ),
588  QStringLiteral( "from" )};
589 
590  static QStringList sEndCandidates{ QStringLiteral( "end" ),
591  QStringLiteral( "last" ),
592  QStringLiteral( "to" )};
593 
594  static QStringList sSingleFieldCandidates{ QStringLiteral( "event" ) };
595 
596 
597  bool foundStart = false;
598  bool foundEnd = false;
599 
600  for ( const QgsField &field : fields )
601  {
602  if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
603  continue;
604 
605  if ( !foundStart )
606  {
607  for ( const QString &candidate : sStartCandidates )
608  {
609  QString fldName = field.name();
610  if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
611  {
612  mStartFieldName = fldName;
613  foundStart = true;
614  }
615  }
616  }
617 
618  if ( !foundEnd )
619  {
620  for ( const QString &candidate : sEndCandidates )
621  {
622  QString fldName = field.name();
623  if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
624  {
625  mEndFieldName = fldName;
626  foundEnd = true;
627  }
628  }
629  }
630 
631  if ( foundStart && foundEnd )
632  break;
633  }
634 
635  if ( !foundStart )
636  {
637  // loop again, looking for likely "single field" candidates
638  for ( const QgsField &field : fields )
639  {
640  if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
641  continue;
642 
643  for ( const QString &candidate : sSingleFieldCandidates )
644  {
645  QString fldName = field.name();
646  if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
647  {
648  mStartFieldName = fldName;
649  foundStart = true;
650  }
651  }
652 
653  if ( foundStart )
654  break;
655  }
656  }
657 
658  if ( foundStart && foundEnd )
660  else if ( foundStart )
662 
663  // note -- NEVER auto enable temporal properties here! It's just a helper designed
664  // to shortcut the initial field selection
665 }
666 
668 {
669  return mLayer;
670 }
671 
673 {
674  mLayer = layer;
675 }
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...
Definition: qgsfeature.h:56
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:302
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
QVariant::Type type
Definition: qgsfield.h:58
Container of fields for a vector layer.
Definition: qgsfields.h:45
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
A representation of the interval between two datetime values.
Definition: qgsinterval.h:42
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
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.
Definition: qgsunittypes.h:150
@ TemporalMonths
Months.
Definition: qgsunittypes.h:157
@ TemporalUnknownUnit
Unknown time unit.
Definition: qgsunittypes.h:162
@ TemporalWeeks
Weeks.
Definition: qgsunittypes.h:156
@ TemporalMilliseconds
Milliseconds.
Definition: qgsunittypes.h:151
@ TemporalIrregularStep
Special "irregular step" time unit, used for temporal data which uses irregular, non-real-world unit ...
Definition: qgsunittypes.h:161
@ TemporalDays
Days.
Definition: qgsunittypes.h:155
@ TemporalDecades
Decades.
Definition: qgsunittypes.h:159
@ TemporalCenturies
Centuries.
Definition: qgsunittypes.h:160
@ TemporalSeconds
Seconds.
Definition: qgsunittypes.h:152
@ TemporalMinutes
Minutes.
Definition: qgsunittypes.h:153
@ TemporalYears
Years.
Definition: qgsunittypes.h:158
@ TemporalHours
Hours.
Definition: qgsunittypes.h:154
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.
Definition: qgis.h:550
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:598
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
QString dateTimeExpressionLiteral(const QDateTime &datetime)