QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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 "moc_qgsvectorlayertemporalproperties.cpp"
28
30 : QgsMapLayerTemporalProperties( parent, enabled )
31{
32}
33
53
55{
56 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
57 if ( !layer )
58 return QgsDateTimeRange();
59
60 switch ( mMode )
61 {
63 return mFixedRange;
64
66 {
67 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
68 if ( fieldIndex >= 0 )
69 {
70 QVariant minVal;
71 QVariant maxVal;
72 vectorLayer->minimumAndMaximumValue( fieldIndex, minVal, maxVal );
73
74 const QDateTime min = minVal.toDateTime();
75 const QDateTime maxStartTime = maxVal.toDateTime();
76 const QgsInterval eventDuration = QgsInterval( mFixedDuration, mDurationUnit );
77 return QgsDateTimeRange( min, maxStartTime + eventDuration );
78 }
79 break;
80 }
81
83 {
84 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
85 const int durationFieldIndex = vectorLayer->fields().lookupField( mDurationFieldName );
86 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
87 {
88 const QDateTime minTime = vectorLayer->minimumValue( fieldIndex ).toDateTime();
89 // no choice here but to loop through all features to calculate max time :(
90
91 QgsFeature f;
92 QgsFeatureIterator it = vectorLayer->getFeatures( QgsFeatureRequest().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() << durationFieldIndex << fieldIndex ) );
93 QDateTime maxTime;
94 while ( it.nextFeature( f ) )
95 {
96 const QDateTime start = f.attribute( fieldIndex ).toDateTime();
97 if ( start.isValid() )
98 {
99 const QVariant durationValue = f.attribute( durationFieldIndex );
100 if ( durationValue.isValid() )
101 {
102 const double duration = durationValue.toDouble();
103 const QDateTime end = start.addMSecs( QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
104 if ( end.isValid() )
105 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
106 }
107 }
108 }
109 return QgsDateTimeRange( minTime, maxTime );
110 }
111 break;
112 }
113
115 {
116 const int startFieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
117 const int endFieldIndex = vectorLayer->fields().lookupField( mEndFieldName );
118 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
119 {
120 QVariant startMinVal;
121 QVariant startMaxVal;
122 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
123 QVariant endMinVal;
124 QVariant endMaxVal;
125 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
126
127 return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
128 endMinVal.toDateTime() ),
129 std::max( startMaxVal.toDateTime(),
130 endMaxVal.toDateTime() ) );
131 }
132 else if ( startFieldIndex >= 0 )
133 {
134 QVariant startMinVal;
135 QVariant startMaxVal;
136 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
137 return QgsDateTimeRange( startMinVal.toDateTime(),
138 startMaxVal.toDateTime() );
139 }
140 else if ( endFieldIndex >= 0 )
141 {
142 QVariant endMinVal;
143 QVariant endMaxVal;
144 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
145 return QgsDateTimeRange( endMinVal.toDateTime(),
146 endMaxVal.toDateTime() );
147 }
148 break;
149 }
150
152 {
153 const bool hasStartExpression = !mStartExpression.isEmpty();
154 const bool hasEndExpression = !mEndExpression.isEmpty();
155 if ( !hasStartExpression && !hasEndExpression )
156 return QgsDateTimeRange();
157
158 QDateTime minTime;
159 QDateTime maxTime;
160
161 // no choice here but to loop through all features
162 QgsExpressionContext context;
164
166 if ( hasStartExpression )
167 {
168 startExpression.setExpression( mStartExpression );
169 startExpression.prepare( &context );
170 }
171
173 if ( hasEndExpression )
174 {
175 endExpression.setExpression( mEndExpression );
176 endExpression.prepare( &context );
177 }
178
179 QSet< QString > fields;
180 if ( hasStartExpression )
181 fields.unite( startExpression.referencedColumns() );
182 if ( hasEndExpression )
183 fields.unite( endExpression.referencedColumns() );
184
185 const bool needsGeom = startExpression.needsGeometry() || endExpression.needsGeometry();
186
188 if ( !needsGeom )
190
191 req.setSubsetOfAttributes( fields, vectorLayer->fields() );
192
193 QgsFeature f;
194 QgsFeatureIterator it = vectorLayer->getFeatures( req );
195 while ( it.nextFeature( f ) )
196 {
197 context.setFeature( f );
198 const QDateTime start = hasStartExpression ? startExpression.evaluate( &context ).toDateTime() : QDateTime();
199 const QDateTime end = hasEndExpression ? endExpression.evaluate( &context ).toDateTime() : QDateTime();
200
201 if ( start.isValid() )
202 {
203 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
204 if ( !hasEndExpression )
205 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
206 }
207 if ( end.isValid() )
208 {
209 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
210 if ( !hasStartExpression )
211 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
212 }
213 }
214 return QgsDateTimeRange( minTime, maxTime );
215 }
216
218 break;
219 }
220
221 return QgsDateTimeRange();
222}
223
228
230{
231 if ( mMode == mode )
232 return;
233 mMode = mode;
234}
235
240
242{
243 if ( mLimitMode == limitMode )
244 return;
245 mLimitMode = limitMode;
246}
247
252
254{
255 mFixedRange = range;
256}
257
259{
260 return mFixedRange;
261}
262
263bool QgsVectorLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
264{
265 Q_UNUSED( context )
266
267 const QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
268
269 setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
270
271 mMode = static_cast< Qgis::VectorTemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
272
273 mLimitMode = static_cast< Qgis::VectorTemporalLimitMode >( temporalNode.attribute( QStringLiteral( "limitMode" ), QStringLiteral( "0" ) ). toInt() );
274 mStartFieldName = temporalNode.attribute( QStringLiteral( "startField" ) );
275 mEndFieldName = temporalNode.attribute( QStringLiteral( "endField" ) );
276 mStartExpression = temporalNode.attribute( QStringLiteral( "startExpression" ) );
277 mEndExpression = temporalNode.attribute( QStringLiteral( "endExpression" ) );
278 mDurationFieldName = temporalNode.attribute( QStringLiteral( "durationField" ) );
279 mDurationUnit = QgsUnitTypes::decodeTemporalUnit( temporalNode.attribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( Qgis::TemporalUnit::Minutes ) ) );
280 mFixedDuration = temporalNode.attribute( QStringLiteral( "fixedDuration" ) ).toDouble();
281 mAccumulateFeatures = temporalNode.attribute( QStringLiteral( "accumulate" ), QStringLiteral( "0" ) ).toInt();
282
283 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
284
285 const QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
286 const QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
287
288 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
289 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
290
291 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate, true, mLimitMode == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd );
292 setFixedTemporalRange( range );
293
294 return true;
295}
296
297QDomElement QgsVectorLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
298{
299 Q_UNUSED( context )
300 if ( element.isNull() )
301 return QDomElement();
302
303 QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
304 temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
305 temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( static_cast< int >( mMode ) ) );
306
307 temporalElement.setAttribute( QStringLiteral( "limitMode" ), QString::number( static_cast< int >( mLimitMode ) ) );
308 temporalElement.setAttribute( QStringLiteral( "startField" ), mStartFieldName );
309 temporalElement.setAttribute( QStringLiteral( "endField" ), mEndFieldName );
310 temporalElement.setAttribute( QStringLiteral( "startExpression" ), mStartExpression );
311 temporalElement.setAttribute( QStringLiteral( "endExpression" ), mEndExpression );
312 temporalElement.setAttribute( QStringLiteral( "durationField" ), mDurationFieldName );
313 temporalElement.setAttribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( mDurationUnit ) );
314 temporalElement.setAttribute( QStringLiteral( "fixedDuration" ), qgsDoubleToString( mFixedDuration ) );
315 temporalElement.setAttribute( QStringLiteral( "accumulate" ), mAccumulateFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
316
317 QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
318
319 QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
320 QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
321
322 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
323 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
324 startElement.appendChild( startText );
325 endElement.appendChild( endText );
326 rangeElement.appendChild( startElement );
327 rangeElement.appendChild( endElement );
328
329 temporalElement.appendChild( rangeElement );
330
331 element.appendChild( temporalElement );
332
333 return element;
334}
335
358
360{
361 return mStartExpression;
362}
363
365{
366 mStartExpression = startExpression;
367}
368
370{
371 return mEndExpression;
372}
373
375{
376 mEndExpression = endExpression;
377}
378
380{
381 return mAccumulateFeatures;
382}
383
388
390{
391 return mFixedDuration;
392}
393
398
400{
401 return mStartFieldName;
402}
403
404void QgsVectorLayerTemporalProperties::setStartField( const QString &startFieldName )
405{
406 mStartFieldName = startFieldName;
407}
408
410{
411 return mEndFieldName;
412}
413
415{
416 mEndFieldName = field;
417}
418
420{
421 return mDurationFieldName;
422}
423
425{
426 mDurationFieldName = field;
427}
428
430{
431 return mDurationUnit;
432}
433
435{
436 mDurationUnit = units;
437}
438
439QString dateTimeExpressionLiteral( const QDateTime &datetime )
440{
441 return QStringLiteral( "make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
442 .arg( datetime.date().month() )
443 .arg( datetime.date().day() )
444 .arg( datetime.time().hour() )
445 .arg( datetime.time().minute() )
446 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
447}
448
450{
451 if ( !isActive() )
452 return QString();
453
454 auto dateTimefieldCast = [ &context ]( const QString & fieldName ) -> QString
455 {
456 if ( context.layer()
457 && context.layer()->fields().lookupField( fieldName ) >= 0
458 && context.layer()->fields().at( context.layer()->fields().lookupField( fieldName ) ).type() != QMetaType::Type::QDateTime )
459 {
460 return QStringLiteral( "to_datetime( %1 )" ) .arg( QgsExpression::quotedColumnRef( fieldName ) );
461 }
462 return QgsExpression::quotedColumnRef( fieldName );
463 };
464
465 switch ( mMode )
466 {
469 return QString();
470
472 {
473 if ( mAccumulateFeatures )
474 {
475 return QStringLiteral( "(%1 %2 %3) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
476 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
477 dateTimeExpressionLiteral( filterRange.end() ) );
478 }
479 else if ( qgsDoubleNear( mFixedDuration, 0.0 ) )
480 {
481 return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
482 filterRange.includeBeginning() ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
483 dateTimeExpressionLiteral( filterRange.begin() ),
484 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
485 dateTimeExpressionLiteral( filterRange.end() ) );
486 }
487 else
488 {
489 // Working with features with events with a duration, so taking this duration into account (+ QgsInterval( -mFixedDuration, mDurationUnit ) ))
490 return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
491 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
492 dateTimeExpressionLiteral( filterRange.begin() + QgsInterval( -mFixedDuration, mDurationUnit ) ),
493 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
494 dateTimeExpressionLiteral( filterRange.end() ) );
495 }
496 }
497
499 {
500 QString intervalExpression;
501 switch ( mDurationUnit )
502 {
504 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1/1000)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
505 break;
506
508 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
509 break;
510
512 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,%1,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
513 break;
514
516 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,%1,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
517 break;
518
520 intervalExpression = QStringLiteral( "make_interval(0,0,0,%1,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
521 break;
522
524 intervalExpression = QStringLiteral( "make_interval(0,0,%1,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
525 break;
526
528 intervalExpression = QStringLiteral( "make_interval(0,%1,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
529 break;
530
532 intervalExpression = QStringLiteral( "make_interval(%1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
533 break;
534
536 intervalExpression = QStringLiteral( "make_interval(10 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
537 break;
538
540 intervalExpression = QStringLiteral( "make_interval(100 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
541 break;
542
545 return QString();
546 }
547 return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND ((%1 + %4 %5 %6) OR %7 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
548 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
549 dateTimeExpressionLiteral( filterRange.end() ),
550 intervalExpression,
551 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
552 dateTimeExpressionLiteral( filterRange.begin() ),
553 QgsExpression::quotedColumnRef( mDurationFieldName ) );
554 }
555
557 {
558 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
559 {
560 return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND (%4 %5 %6 OR %4 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
561 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
562 dateTimeExpressionLiteral( filterRange.end() ),
563 dateTimefieldCast( mEndFieldName ),
564 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
565 dateTimeExpressionLiteral( filterRange.begin() ) );
566
567 }
568 else if ( !mStartFieldName.isEmpty() )
569 {
570 return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
571 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
572 dateTimeExpressionLiteral( filterRange.end() ) );
573 }
574 else if ( !mEndFieldName.isEmpty() )
575 {
576 return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mEndFieldName ),
577 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
578 dateTimeExpressionLiteral( filterRange.begin() ) );
579 }
580 break;
581 }
582
584 {
585 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
586 {
587 return QStringLiteral( "((%1) %2 %3) AND ((%4) %5 %6)" ).arg( mStartExpression,
588 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
589 dateTimeExpressionLiteral( filterRange.end() ),
590 mEndExpression,
591 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
592 dateTimeExpressionLiteral( filterRange.begin() ) );
593 }
594 else if ( !mStartExpression.isEmpty() )
595 {
596 return QStringLiteral( "(%1) %2 %3" ).arg( mStartExpression,
597 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
598 dateTimeExpressionLiteral( filterRange.end() ) );
599 }
600 else if ( !mEndExpression.isEmpty() )
601 {
602 return QStringLiteral( "(%1) %2 %3" ).arg( mEndExpression,
603 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
604 dateTimeExpressionLiteral( filterRange.begin() ) );
605 }
606 break;
607 }
608 }
609
610 return QString();
611}
612
614{
615
616 // Check the fields and keep the first one that matches.
617 // We assume that the user has organized the data with the
618 // more "interesting" field names first.
619 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
620 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
621 // but adding hardcoded localized variants of the strings is encouraged.
622 static const QStringList sStartCandidates{ QStringLiteral( "start" ),
623 QStringLiteral( "begin" ),
624 QStringLiteral( "from" ),
625 QStringLiteral( "since" ),
626 // German candidates
627 QStringLiteral( "anfang" ),
628 QStringLiteral( "von" ),
629 QStringLiteral( "ab" ),
630 QStringLiteral( "seit" ) };
631
632 static const QStringList sEndCandidates{ QStringLiteral( "end" ),
633 QStringLiteral( "last" ),
634 QStringLiteral( "to" ),
635 QStringLiteral( "stop" ),
636 // German candidates
637 QStringLiteral( "ende" ),
638 QStringLiteral( "bis" ) };
639
640
641 static const QStringList sSingleFieldCandidates{ QStringLiteral( "event" ) };
642
643
644 bool foundStart = false;
645 bool foundEnd = false;
646
647 for ( const QgsField &field : fields )
648 {
649 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
650 continue;
651
652 if ( !foundStart )
653 {
654 for ( const QString &candidate : sStartCandidates )
655 {
656 const QString fldName = field.name();
657 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
658 {
659 mStartFieldName = fldName;
660 foundStart = true;
661 }
662 }
663 }
664
665 if ( !foundEnd )
666 {
667 for ( const QString &candidate : sEndCandidates )
668 {
669 const QString fldName = field.name();
670 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
671 {
672 mEndFieldName = fldName;
673 foundEnd = true;
674 }
675 }
676 }
677
678 if ( foundStart && foundEnd )
679 break;
680 }
681
682 if ( !foundStart )
683 {
684 // loop again, looking for likely "single field" candidates
685 for ( const QgsField &field : fields )
686 {
687 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
688 continue;
689
690 for ( const QString &candidate : sSingleFieldCandidates )
691 {
692 const QString fldName = field.name();
693 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
694 {
695 mStartFieldName = fldName;
696 foundStart = true;
697 }
698 }
699
700 if ( foundStart )
701 break;
702 }
703 }
704
705 if ( foundStart && foundEnd )
707 else if ( foundStart )
709
710 // note -- NEVER auto enable temporal properties here! It's just a helper designed
711 // to shortcut the initial field selection
712}
713
715{
716 return mLayer;
717}
718
VectorTemporalMode
Vector layer temporal feature modes.
Definition qgis.h:2580
@ FeatureDateTimeStartAndDurationFromFields
Mode when features have a field for start time and a field for event duration.
Definition qgis.h:2584
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when symbology or...
Definition qgis.h:2586
@ FeatureDateTimeStartAndEndFromExpressions
Mode when features use expressions for start and end times.
Definition qgis.h:2585
@ FeatureDateTimeInstantFromField
Mode when features have a datetime instant taken from a single field.
Definition qgis.h:2582
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Definition qgis.h:2581
@ FeatureDateTimeStartAndEndFromFields
Mode when features have separate fields for start and end times.
Definition qgis.h:2583
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2196
TemporalUnit
Temporal units.
Definition qgis.h:5159
@ IrregularStep
Special 'irregular step' time unit, used for temporal data which uses irregular, non-real-world unit ...
Definition qgis.h:5170
@ Milliseconds
Milliseconds.
Definition qgis.h:5160
@ Hours
Hours.
Definition qgis.h:5163
@ Unknown
Unknown time unit.
Definition qgis.h:5171
@ Centuries
Centuries.
Definition qgis.h:5169
@ Seconds
Seconds.
Definition qgis.h:5161
@ Weeks
Weeks.
Definition qgis.h:5165
@ Years
Years.
Definition qgis.h:5167
@ Decades
Decades.
Definition qgis.h:5168
@ Months
Months.
Definition qgis.h:5166
@ Minutes
Minutes.
Definition qgis.h:5162
@ StoresFeatureDateTimeInstantInField
Dataset has feature datetime instants stored in a single field.
Definition qgis.h:2610
@ StoresFeatureDateTimeStartAndEndInSeparateFields
Dataset stores feature start and end datetimes in separate fields.
Definition qgis.h:2611
@ HasFixedTemporalRange
Entire dataset from provider has a fixed start and end datetime.
Definition qgis.h:2609
VectorTemporalLimitMode
Mode for the handling of the limits of the filtering timeframe for vector features.
Definition qgis.h:2596
@ IncludeBeginIncludeEnd
Mode to include both limits of the filtering timeframe.
Definition qgis.h:2598
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:58
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:54
QMetaType::Type type
Definition qgsfield.h:61
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:47
QgsMapLayerTemporalProperties(QObject *parent, bool enabled=false)
Constructor for QgsMapLayerTemporalProperties, with the specified parent object.
Base class for all map layer types.
Definition qgsmaplayer.h:80
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:446
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:453
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:468
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition qgsrange.h:461
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:482
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:6524
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
QList< int > QgsAttributeList
Definition qgsfield.h:28
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:761
QString dateTimeExpressionLiteral(const QDateTime &datetime)