QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
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
19
20#include "qgsexpression.h"
22#include "qgsfields.h"
23#include "qgsunittypes.h"
25#include "qgsvectorlayer.h"
26
27#include <QString>
28
29#include "moc_qgsvectorlayertemporalproperties.cpp"
30
31using namespace Qt::StringLiterals;
32
34 : QgsMapLayerTemporalProperties( parent, enabled )
35{
36}
37
57
59{
60 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
61 if ( !layer )
62 return QgsDateTimeRange();
63
64 switch ( mMode )
65 {
67 return mFixedRange;
68
70 {
71 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
72 if ( fieldIndex >= 0 )
73 {
74 QVariant minVal;
75 QVariant maxVal;
76 vectorLayer->minimumAndMaximumValue( fieldIndex, minVal, maxVal );
77
78 const QDateTime min = minVal.toDateTime();
79 const QDateTime maxStartTime = maxVal.toDateTime();
80 const QgsInterval eventDuration = QgsInterval( mFixedDuration, mDurationUnit );
81 return QgsDateTimeRange( min, maxStartTime + eventDuration );
82 }
83 break;
84 }
85
87 {
88 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
89 const int durationFieldIndex = vectorLayer->fields().lookupField( mDurationFieldName );
90 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
91 {
92 const QDateTime minTime = vectorLayer->minimumValue( fieldIndex ).toDateTime();
93 // no choice here but to loop through all features to calculate max time :(
94
95 QgsFeature f;
96 QgsFeatureIterator it = vectorLayer->getFeatures( QgsFeatureRequest().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() << durationFieldIndex << fieldIndex ) );
97 QDateTime maxTime;
98 while ( it.nextFeature( f ) )
99 {
100 const QDateTime start = f.attribute( fieldIndex ).toDateTime();
101 if ( start.isValid() )
102 {
103 const QVariant durationValue = f.attribute( durationFieldIndex );
104 if ( durationValue.isValid() )
105 {
106 const double duration = durationValue.toDouble();
107 const QDateTime end = start.addMSecs( QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
108 if ( end.isValid() )
109 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
110 }
111 }
112 }
113 return QgsDateTimeRange( minTime, maxTime );
114 }
115 break;
116 }
117
119 {
120 const int startFieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
121 const int endFieldIndex = vectorLayer->fields().lookupField( mEndFieldName );
122 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
123 {
124 QVariant startMinVal;
125 QVariant startMaxVal;
126 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
127 QVariant endMinVal;
128 QVariant endMaxVal;
129 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
130
131 return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
132 endMinVal.toDateTime() ),
133 std::max( startMaxVal.toDateTime(),
134 endMaxVal.toDateTime() ) );
135 }
136 else if ( startFieldIndex >= 0 )
137 {
138 QVariant startMinVal;
139 QVariant startMaxVal;
140 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
141 return QgsDateTimeRange( startMinVal.toDateTime(),
142 startMaxVal.toDateTime() );
143 }
144 else if ( endFieldIndex >= 0 )
145 {
146 QVariant endMinVal;
147 QVariant endMaxVal;
148 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
149 return QgsDateTimeRange( endMinVal.toDateTime(),
150 endMaxVal.toDateTime() );
151 }
152 break;
153 }
154
156 {
157 const bool hasStartExpression = !mStartExpression.isEmpty();
158 const bool hasEndExpression = !mEndExpression.isEmpty();
159 if ( !hasStartExpression && !hasEndExpression )
160 return QgsDateTimeRange();
161
162 QDateTime minTime;
163 QDateTime maxTime;
164
165 // no choice here but to loop through all features
166 QgsExpressionContext context;
168
170 if ( hasStartExpression )
171 {
172 startExpression.setExpression( mStartExpression );
173 startExpression.prepare( &context );
174 }
175
177 if ( hasEndExpression )
178 {
179 endExpression.setExpression( mEndExpression );
180 endExpression.prepare( &context );
181 }
182
183 QSet< QString > fields;
184 if ( hasStartExpression )
185 fields.unite( startExpression.referencedColumns() );
186 if ( hasEndExpression )
187 fields.unite( endExpression.referencedColumns() );
188
189 const bool needsGeom = startExpression.needsGeometry() || endExpression.needsGeometry();
190
192 if ( !needsGeom )
194
195 req.setSubsetOfAttributes( fields, vectorLayer->fields() );
196
197 QgsFeature f;
198 QgsFeatureIterator it = vectorLayer->getFeatures( req );
199 while ( it.nextFeature( f ) )
200 {
201 context.setFeature( f );
202 const QDateTime start = hasStartExpression ? startExpression.evaluate( &context ).toDateTime() : QDateTime();
203 const QDateTime end = hasEndExpression ? endExpression.evaluate( &context ).toDateTime() : QDateTime();
204
205 if ( start.isValid() )
206 {
207 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
208 if ( !hasEndExpression )
209 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
210 }
211 if ( end.isValid() )
212 {
213 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
214 if ( !hasStartExpression )
215 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
216 }
217 }
218 return QgsDateTimeRange( minTime, maxTime );
219 }
220
222 break;
223 }
224
225 return QgsDateTimeRange();
226}
227
232
234{
235 if ( mMode == mode )
236 return;
237 mMode = mode;
238}
239
244
246{
247 if ( mLimitMode == limitMode )
248 return;
249 mLimitMode = limitMode;
250}
251
256
258{
259 mFixedRange = range;
260}
261
263{
264 return mFixedRange;
265}
266
267bool QgsVectorLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
268{
269 Q_UNUSED( context )
270
271 const QDomElement temporalNode = element.firstChildElement( u"temporal"_s );
272
273 setIsActive( temporalNode.attribute( u"enabled"_s, u"0"_s ).toInt() );
274
275 mMode = static_cast< Qgis::VectorTemporalMode >( temporalNode.attribute( u"mode"_s, u"0"_s ). toInt() );
276
277 mLimitMode = static_cast< Qgis::VectorTemporalLimitMode >( temporalNode.attribute( u"limitMode"_s, u"0"_s ). toInt() );
278 mStartFieldName = temporalNode.attribute( u"startField"_s );
279 mEndFieldName = temporalNode.attribute( u"endField"_s );
280 mStartExpression = temporalNode.attribute( u"startExpression"_s );
281 mEndExpression = temporalNode.attribute( u"endExpression"_s );
282 mDurationFieldName = temporalNode.attribute( u"durationField"_s );
283 mDurationUnit = QgsUnitTypes::decodeTemporalUnit( temporalNode.attribute( u"durationUnit"_s, QgsUnitTypes::encodeUnit( Qgis::TemporalUnit::Minutes ) ) );
284 mFixedDuration = temporalNode.attribute( u"fixedDuration"_s ).toDouble();
285 mAccumulateFeatures = temporalNode.attribute( u"accumulate"_s, u"0"_s ).toInt();
286
287 const QDomNode rangeElement = temporalNode.namedItem( u"fixedRange"_s );
288
289 const QDomNode begin = rangeElement.namedItem( u"start"_s );
290 const QDomNode end = rangeElement.namedItem( u"end"_s );
291
292 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
293 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
294
295 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate, true, mLimitMode == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd );
296 setFixedTemporalRange( range );
297
298 return true;
299}
300
301QDomElement QgsVectorLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
302{
303 Q_UNUSED( context )
304 if ( element.isNull() )
305 return QDomElement();
306
307 QDomElement temporalElement = document.createElement( u"temporal"_s );
308 temporalElement.setAttribute( u"enabled"_s, isActive() ? u"1"_s : u"0"_s );
309 temporalElement.setAttribute( u"mode"_s, QString::number( static_cast< int >( mMode ) ) );
310
311 temporalElement.setAttribute( u"limitMode"_s, QString::number( static_cast< int >( mLimitMode ) ) );
312 temporalElement.setAttribute( u"startField"_s, mStartFieldName );
313 temporalElement.setAttribute( u"endField"_s, mEndFieldName );
314 temporalElement.setAttribute( u"startExpression"_s, mStartExpression );
315 temporalElement.setAttribute( u"endExpression"_s, mEndExpression );
316 temporalElement.setAttribute( u"durationField"_s, mDurationFieldName );
317 temporalElement.setAttribute( u"durationUnit"_s, QgsUnitTypes::encodeUnit( mDurationUnit ) );
318 temporalElement.setAttribute( u"fixedDuration"_s, qgsDoubleToString( mFixedDuration ) );
319 temporalElement.setAttribute( u"accumulate"_s, mAccumulateFeatures ? u"1"_s : u"0"_s );
320
321 QDomElement rangeElement = document.createElement( u"fixedRange"_s );
322
323 QDomElement startElement = document.createElement( u"start"_s );
324 QDomElement endElement = document.createElement( u"end"_s );
325
326 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
327 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
328 startElement.appendChild( startText );
329 endElement.appendChild( endText );
330 rangeElement.appendChild( startElement );
331 rangeElement.appendChild( endElement );
332
333 temporalElement.appendChild( rangeElement );
334
335 element.appendChild( temporalElement );
336
337 return element;
338}
339
362
364{
365 return mStartExpression;
366}
367
369{
370 mStartExpression = startExpression;
371}
372
374{
375 return mEndExpression;
376}
377
379{
380 mEndExpression = endExpression;
381}
382
384{
385 return mAccumulateFeatures;
386}
387
392
394{
395 return mFixedDuration;
396}
397
402
404{
405 return mStartFieldName;
406}
407
408void QgsVectorLayerTemporalProperties::setStartField( const QString &startFieldName )
409{
410 mStartFieldName = startFieldName;
411}
412
414{
415 return mEndFieldName;
416}
417
419{
420 mEndFieldName = field;
421}
422
424{
425 return mDurationFieldName;
426}
427
429{
430 mDurationFieldName = field;
431}
432
434{
435 return mDurationUnit;
436}
437
439{
440 mDurationUnit = units;
441}
442
443QString dateTimeExpressionLiteral( const QDateTime &datetime )
444{
445 return u"make_datetime(%1,%2,%3,%4,%5,%6)"_s.arg( datetime.date().year() )
446 .arg( datetime.date().month() )
447 .arg( datetime.date().day() )
448 .arg( datetime.time().hour() )
449 .arg( datetime.time().minute() )
450 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
451}
452
454{
455 if ( !isActive() )
456 return QString();
457
458 auto dateTimefieldCast = [ &context ]( const QString & fieldName ) -> QString
459 {
460 if ( context.layer()
461 && context.layer()->fields().lookupField( fieldName ) >= 0
462 && context.layer()->fields().at( context.layer()->fields().lookupField( fieldName ) ).type() != QMetaType::Type::QDateTime )
463 {
464 return u"to_datetime( %1 )"_s .arg( QgsExpression::quotedColumnRef( fieldName ) );
465 }
466 return QgsExpression::quotedColumnRef( fieldName );
467 };
468
469 switch ( mMode )
470 {
473 return QString();
474
476 {
477 if ( mAccumulateFeatures )
478 {
479 return u"(%1 %2 %3) OR %1 IS NULL"_s.arg( dateTimefieldCast( mStartFieldName ),
480 filterRange.includeEnd() ? u"<="_s : u"<"_s,
481 dateTimeExpressionLiteral( filterRange.end() ) );
482 }
483 else if ( qgsDoubleNear( mFixedDuration, 0.0 ) )
484 {
485 return u"(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL"_s.arg( dateTimefieldCast( mStartFieldName ),
486 filterRange.includeBeginning() ? u">="_s : u">"_s,
487 dateTimeExpressionLiteral( filterRange.begin() ),
488 filterRange.includeEnd() ? u"<="_s : u"<"_s,
489 dateTimeExpressionLiteral( filterRange.end() ) );
490 }
491 else
492 {
493 // Working with features with events with a duration, so taking this duration into account (+ QgsInterval( -mFixedDuration, mDurationUnit ) ))
494 return u"(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL"_s.arg( dateTimefieldCast( mStartFieldName ),
496 dateTimeExpressionLiteral( filterRange.begin() + QgsInterval( -mFixedDuration, mDurationUnit ) ),
497 filterRange.includeEnd() ? u"<="_s : u"<"_s,
498 dateTimeExpressionLiteral( filterRange.end() ) );
499 }
500 }
501
503 {
504 QString intervalExpression;
505 switch ( mDurationUnit )
506 {
508 intervalExpression = u"make_interval(0,0,0,0,0,0,%1/1000)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
509 break;
510
512 intervalExpression = u"make_interval(0,0,0,0,0,0,%1)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
513 break;
514
516 intervalExpression = u"make_interval(0,0,0,0,0,%1,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
517 break;
518
520 intervalExpression = u"make_interval(0,0,0,0,%1,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
521 break;
522
524 intervalExpression = u"make_interval(0,0,0,%1,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
525 break;
526
528 intervalExpression = u"make_interval(0,0,%1,0,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
529 break;
530
532 intervalExpression = u"make_interval(0,%1,0,0,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
533 break;
534
536 intervalExpression = u"make_interval(%1,0,0,0,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
537 break;
538
540 intervalExpression = u"make_interval(10 * %1,0,0,0,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
541 break;
542
544 intervalExpression = u"make_interval(100 * %1,0,0,0,0,0,0)"_s.arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
545 break;
546
549 return QString();
550 }
551 return u"(%1 %2 %3 OR %1 IS NULL) AND ((%1 + %4 %5 %6) OR %7 IS NULL)"_s.arg( dateTimefieldCast( mStartFieldName ),
552 filterRange.includeEnd() ? u"<="_s : u"<"_s,
553 dateTimeExpressionLiteral( filterRange.end() ),
554 intervalExpression,
556 dateTimeExpressionLiteral( filterRange.begin() ),
557 QgsExpression::quotedColumnRef( mDurationFieldName ) );
558 }
559
561 {
562 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
563 {
564 return u"(%1 %2 %3 OR %1 IS NULL) AND (%4 %5 %6 OR %4 IS NULL)"_s.arg( dateTimefieldCast( mStartFieldName ),
565 filterRange.includeEnd() ? u"<="_s : u"<"_s,
566 dateTimeExpressionLiteral( filterRange.end() ),
567 dateTimefieldCast( mEndFieldName ),
569 dateTimeExpressionLiteral( filterRange.begin() ) );
570
571 }
572 else if ( !mStartFieldName.isEmpty() )
573 {
574 return u"%1 %2 %3 OR %1 IS NULL"_s.arg( dateTimefieldCast( mStartFieldName ),
575 filterRange.includeEnd() ? u"<="_s : u"<"_s,
576 dateTimeExpressionLiteral( filterRange.end() ) );
577 }
578 else if ( !mEndFieldName.isEmpty() )
579 {
580 return u"%1 %2 %3 OR %1 IS NULL"_s.arg( dateTimefieldCast( mEndFieldName ),
582 dateTimeExpressionLiteral( filterRange.begin() ) );
583 }
584 break;
585 }
586
588 {
589 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
590 {
591 return u"((%1) %2 %3) AND ((%4) %5 %6)"_s.arg( mStartExpression,
592 filterRange.includeEnd() ? u"<="_s : u"<"_s,
593 dateTimeExpressionLiteral( filterRange.end() ),
594 mEndExpression,
596 dateTimeExpressionLiteral( filterRange.begin() ) );
597 }
598 else if ( !mStartExpression.isEmpty() )
599 {
600 return u"(%1) %2 %3"_s.arg( mStartExpression,
601 filterRange.includeEnd() ? u"<="_s : u"<"_s,
602 dateTimeExpressionLiteral( filterRange.end() ) );
603 }
604 else if ( !mEndExpression.isEmpty() )
605 {
606 return u"(%1) %2 %3"_s.arg( mEndExpression,
608 dateTimeExpressionLiteral( filterRange.begin() ) );
609 }
610 break;
611 }
612 }
613
614 return QString();
615}
616
618{
619
620 // Check the fields and keep the first one that matches.
621 // We assume that the user has organized the data with the
622 // more "interesting" field names first.
623 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
624 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
625 // but adding hardcoded localized variants of the strings is encouraged.
626 static const QStringList sStartCandidates{ u"start"_s,
627 u"begin"_s,
628 u"from"_s,
629 u"since"_s,
630 // German candidates
631 u"anfang"_s,
632 u"von"_s,
633 u"ab"_s,
634 u"seit"_s };
635
636 static const QStringList sEndCandidates{ u"end"_s,
637 u"last"_s,
638 u"to"_s,
639 u"stop"_s,
640 // German candidates
641 u"ende"_s,
642 u"bis"_s };
643
644
645 static const QStringList sSingleFieldCandidates{ u"event"_s };
646
647
648 bool foundStart = false;
649 bool foundEnd = false;
650
651 for ( const QgsField &field : fields )
652 {
653 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
654 continue;
655
656 if ( !foundStart )
657 {
658 for ( const QString &candidate : sStartCandidates )
659 {
660 const QString fldName = field.name();
661 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
662 {
663 mStartFieldName = fldName;
664 foundStart = true;
665 }
666 }
667 }
668
669 if ( !foundEnd )
670 {
671 for ( const QString &candidate : sEndCandidates )
672 {
673 const QString fldName = field.name();
674 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
675 {
676 mEndFieldName = fldName;
677 foundEnd = true;
678 }
679 }
680 }
681
682 if ( foundStart && foundEnd )
683 break;
684 }
685
686 if ( !foundStart )
687 {
688 // loop again, looking for likely "single field" candidates
689 for ( const QgsField &field : fields )
690 {
691 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
692 continue;
693
694 for ( const QString &candidate : sSingleFieldCandidates )
695 {
696 const QString fldName = field.name();
697 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
698 {
699 mStartFieldName = fldName;
700 foundStart = true;
701 }
702 }
703
704 if ( foundStart )
705 break;
706 }
707 }
708
709 if ( foundStart && foundEnd )
711 else if ( foundStart )
713
714 // note -- NEVER auto enable temporal properties here! It's just a helper designed
715 // to shortcut the initial field selection
716}
717
719{
720 return mLayer;
721}
722
VectorTemporalMode
Vector layer temporal feature modes.
Definition qgis.h:2638
@ FeatureDateTimeStartAndDurationFromFields
Mode when features have a field for start time and a field for event duration.
Definition qgis.h:2642
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when symbology or...
Definition qgis.h:2644
@ FeatureDateTimeStartAndEndFromExpressions
Mode when features use expressions for start and end times.
Definition qgis.h:2643
@ FeatureDateTimeInstantFromField
Mode when features have a datetime instant taken from a single field.
Definition qgis.h:2640
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Definition qgis.h:2639
@ FeatureDateTimeStartAndEndFromFields
Mode when features have separate fields for start and end times.
Definition qgis.h:2641
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2254
TemporalUnit
Temporal units.
Definition qgis.h:5266
@ IrregularStep
Special 'irregular step' time unit, used for temporal data which uses irregular, non-real-world unit ...
Definition qgis.h:5277
@ Milliseconds
Milliseconds.
Definition qgis.h:5267
@ Hours
Hours.
Definition qgis.h:5270
@ Unknown
Unknown time unit.
Definition qgis.h:5278
@ Centuries
Centuries.
Definition qgis.h:5276
@ Seconds
Seconds.
Definition qgis.h:5268
@ Weeks
Weeks.
Definition qgis.h:5272
@ Years
Years.
Definition qgis.h:5274
@ Decades
Decades.
Definition qgis.h:5275
@ Months
Months.
Definition qgis.h:5273
@ Minutes
Minutes.
Definition qgis.h:5269
@ StoresFeatureDateTimeInstantInField
Dataset has feature datetime instants stored in a single field.
Definition qgis.h:2668
@ StoresFeatureDateTimeStartAndEndInSeparateFields
Dataset stores feature start and end datetimes in separate fields.
Definition qgis.h:2669
@ HasFixedTemporalRange
Entire dataset from provider has a fixed start and end datetime.
Definition qgis.h:2667
VectorTemporalLimitMode
Mode for the handling of the limits of the filtering timeframe for vector features.
Definition qgis.h:2654
@ IncludeBeginIncludeEnd
Mode to include both limits of the filtering timeframe.
Definition qgis.h:2656
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.
Handles 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)
Fetch next feature and stores in f, returns true on success.
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...
Definition qgsfeature.h:60
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
QMetaType::Type type
Definition qgsfield.h:63
Container of fields for a vector layer.
Definition qgsfields.h:46
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A representation of the interval between two datetime values.
Definition qgsinterval.h:50
QgsMapLayerTemporalProperties(QObject *parent, bool enabled=false)
Constructor for QgsMapLayerTemporalProperties, with the specified parent object.
Base class for all map layer types.
Definition qgsmaplayer.h:83
A container for the context for various read/write operations on 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.
Definition qgsrange.h:449
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:456
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:471
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition qgsrange.h:464
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:485
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 dataset.
QVariant minimumValue(int index) const final
Returns the minimum value for an attribute column or an invalid variant in case of error.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
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:6852
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6935
QList< int > QgsAttributeList
Definition qgsfield.h:30
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:764
QString dateTimeExpressionLiteral(const QDateTime &datetime)