QGIS API Documentation 3.41.0-Master (3440c17df1d)
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#include "moc_qgsvectorlayertemporalproperties.cpp"
21#include "qgsexpression.h"
22#include "qgsvectorlayer.h"
23#include "qgsfields.h"
25#include "qgsunittypes.h"
26
28 : QgsMapLayerTemporalProperties( parent, enabled )
29{
30}
31
51
53{
54 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
55 if ( !layer )
56 return QgsDateTimeRange();
57
58 switch ( mMode )
59 {
61 return mFixedRange;
62
64 {
65 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
66 if ( fieldIndex >= 0 )
67 {
68 QVariant minVal;
69 QVariant maxVal;
70 vectorLayer->minimumAndMaximumValue( fieldIndex, minVal, maxVal );
71
72 const QDateTime min = minVal.toDateTime();
73 const QDateTime maxStartTime = maxVal.toDateTime();
74 const QgsInterval eventDuration = QgsInterval( mFixedDuration, mDurationUnit );
75 return QgsDateTimeRange( min, maxStartTime + eventDuration );
76 }
77 break;
78 }
79
81 {
82 const int fieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
83 const int durationFieldIndex = vectorLayer->fields().lookupField( mDurationFieldName );
84 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
85 {
86 const QDateTime minTime = vectorLayer->minimumValue( fieldIndex ).toDateTime();
87 // no choice here but to loop through all features to calculate max time :(
88
89 QgsFeature f;
90 QgsFeatureIterator it = vectorLayer->getFeatures( QgsFeatureRequest().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() << durationFieldIndex << fieldIndex ) );
91 QDateTime maxTime;
92 while ( it.nextFeature( f ) )
93 {
94 const QDateTime start = f.attribute( fieldIndex ).toDateTime();
95 if ( start.isValid() )
96 {
97 const QVariant durationValue = f.attribute( durationFieldIndex );
98 if ( durationValue.isValid() )
99 {
100 const double duration = durationValue.toDouble();
101 const QDateTime end = start.addMSecs( QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
102 if ( end.isValid() )
103 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
104 }
105 }
106 }
107 return QgsDateTimeRange( minTime, maxTime );
108 }
109 break;
110 }
111
113 {
114 const int startFieldIndex = vectorLayer->fields().lookupField( mStartFieldName );
115 const int endFieldIndex = vectorLayer->fields().lookupField( mEndFieldName );
116 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
117 {
118 QVariant startMinVal;
119 QVariant startMaxVal;
120 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
121 QVariant endMinVal;
122 QVariant endMaxVal;
123 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
124
125 return QgsDateTimeRange( std::min( startMinVal.toDateTime(),
126 endMinVal.toDateTime() ),
127 std::max( startMaxVal.toDateTime(),
128 endMaxVal.toDateTime() ) );
129 }
130 else if ( startFieldIndex >= 0 )
131 {
132 QVariant startMinVal;
133 QVariant startMaxVal;
134 vectorLayer->minimumAndMaximumValue( startFieldIndex, startMinVal, startMaxVal );
135 return QgsDateTimeRange( startMinVal.toDateTime(),
136 startMaxVal.toDateTime() );
137 }
138 else if ( endFieldIndex >= 0 )
139 {
140 QVariant endMinVal;
141 QVariant endMaxVal;
142 vectorLayer->minimumAndMaximumValue( endFieldIndex, endMinVal, endMaxVal );
143 return QgsDateTimeRange( endMinVal.toDateTime(),
144 endMaxVal.toDateTime() );
145 }
146 break;
147 }
148
150 {
151 const bool hasStartExpression = !mStartExpression.isEmpty();
152 const bool hasEndExpression = !mEndExpression.isEmpty();
153 if ( !hasStartExpression && !hasEndExpression )
154 return QgsDateTimeRange();
155
156 QDateTime minTime;
157 QDateTime maxTime;
158
159 // no choice here but to loop through all features
160 QgsExpressionContext context;
162
164 if ( hasStartExpression )
165 {
166 startExpression.setExpression( mStartExpression );
167 startExpression.prepare( &context );
168 }
169
171 if ( hasEndExpression )
172 {
173 endExpression.setExpression( mEndExpression );
174 endExpression.prepare( &context );
175 }
176
177 QSet< QString > fields;
178 if ( hasStartExpression )
179 fields.unite( startExpression.referencedColumns() );
180 if ( hasEndExpression )
181 fields.unite( endExpression.referencedColumns() );
182
183 const bool needsGeom = startExpression.needsGeometry() || endExpression.needsGeometry();
184
186 if ( !needsGeom )
188
189 req.setSubsetOfAttributes( fields, vectorLayer->fields() );
190
191 QgsFeature f;
192 QgsFeatureIterator it = vectorLayer->getFeatures( req );
193 while ( it.nextFeature( f ) )
194 {
195 context.setFeature( f );
196 const QDateTime start = hasStartExpression ? startExpression.evaluate( &context ).toDateTime() : QDateTime();
197 const QDateTime end = hasEndExpression ? endExpression.evaluate( &context ).toDateTime() : QDateTime();
198
199 if ( start.isValid() )
200 {
201 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
202 if ( !hasEndExpression )
203 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
204 }
205 if ( end.isValid() )
206 {
207 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
208 if ( !hasStartExpression )
209 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
210 }
211 }
212 return QgsDateTimeRange( minTime, maxTime );
213 }
214
216 break;
217 }
218
219 return QgsDateTimeRange();
220}
221
226
228{
229 if ( mMode == mode )
230 return;
231 mMode = mode;
232}
233
238
240{
241 if ( mLimitMode == limitMode )
242 return;
243 mLimitMode = limitMode;
244}
245
250
252{
253 mFixedRange = range;
254}
255
257{
258 return mFixedRange;
259}
260
261bool QgsVectorLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
262{
263 Q_UNUSED( context )
264
265 const QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
266
267 setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
268
269 mMode = static_cast< Qgis::VectorTemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
270
271 mLimitMode = static_cast< Qgis::VectorTemporalLimitMode >( temporalNode.attribute( QStringLiteral( "limitMode" ), QStringLiteral( "0" ) ). toInt() );
272 mStartFieldName = temporalNode.attribute( QStringLiteral( "startField" ) );
273 mEndFieldName = temporalNode.attribute( QStringLiteral( "endField" ) );
274 mStartExpression = temporalNode.attribute( QStringLiteral( "startExpression" ) );
275 mEndExpression = temporalNode.attribute( QStringLiteral( "endExpression" ) );
276 mDurationFieldName = temporalNode.attribute( QStringLiteral( "durationField" ) );
277 mDurationUnit = QgsUnitTypes::decodeTemporalUnit( temporalNode.attribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( Qgis::TemporalUnit::Minutes ) ) );
278 mFixedDuration = temporalNode.attribute( QStringLiteral( "fixedDuration" ) ).toDouble();
279 mAccumulateFeatures = temporalNode.attribute( QStringLiteral( "accumulate" ), QStringLiteral( "0" ) ).toInt();
280
281 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
282
283 const QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
284 const QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
285
286 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
287 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
288
289 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
290 setFixedTemporalRange( range );
291
292 return true;
293}
294
295QDomElement QgsVectorLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
296{
297 Q_UNUSED( context )
298 if ( element.isNull() )
299 return QDomElement();
300
301 QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
302 temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
303 temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( static_cast< int >( mMode ) ) );
304
305 temporalElement.setAttribute( QStringLiteral( "limitMode" ), QString::number( static_cast< int >( mLimitMode ) ) );
306 temporalElement.setAttribute( QStringLiteral( "startField" ), mStartFieldName );
307 temporalElement.setAttribute( QStringLiteral( "endField" ), mEndFieldName );
308 temporalElement.setAttribute( QStringLiteral( "startExpression" ), mStartExpression );
309 temporalElement.setAttribute( QStringLiteral( "endExpression" ), mEndExpression );
310 temporalElement.setAttribute( QStringLiteral( "durationField" ), mDurationFieldName );
311 temporalElement.setAttribute( QStringLiteral( "durationUnit" ), QgsUnitTypes::encodeUnit( mDurationUnit ) );
312 temporalElement.setAttribute( QStringLiteral( "fixedDuration" ), qgsDoubleToString( mFixedDuration ) );
313 temporalElement.setAttribute( QStringLiteral( "accumulate" ), mAccumulateFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
314
315 QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
316
317 QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
318 QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
319
320 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
321 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
322 startElement.appendChild( startText );
323 endElement.appendChild( endText );
324 rangeElement.appendChild( startElement );
325 rangeElement.appendChild( endElement );
326
327 temporalElement.appendChild( rangeElement );
328
329 element.appendChild( temporalElement );
330
331 return element;
332}
333
356
358{
359 return mStartExpression;
360}
361
362void QgsVectorLayerTemporalProperties::setStartExpression( const QString &startExpression )
363{
364 mStartExpression = startExpression;
365}
366
368{
369 return mEndExpression;
370}
371
372void QgsVectorLayerTemporalProperties::setEndExpression( const QString &endExpression )
373{
374 mEndExpression = endExpression;
375}
376
378{
379 return mAccumulateFeatures;
380}
381
383{
384 mAccumulateFeatures = accumulateFeatures;
385}
386
388{
389 return mFixedDuration;
390}
391
393{
394 mFixedDuration = fixedDuration;
395}
396
398{
399 return mStartFieldName;
400}
401
402void QgsVectorLayerTemporalProperties::setStartField( const QString &startFieldName )
403{
404 mStartFieldName = startFieldName;
405}
406
408{
409 return mEndFieldName;
410}
411
413{
414 mEndFieldName = field;
415}
416
418{
419 return mDurationFieldName;
420}
421
423{
424 mDurationFieldName = field;
425}
426
428{
429 return mDurationUnit;
430}
431
433{
434 mDurationUnit = units;
435}
436
437QString dateTimeExpressionLiteral( const QDateTime &datetime )
438{
439 return QStringLiteral( "make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
440 .arg( datetime.date().month() )
441 .arg( datetime.date().day() )
442 .arg( datetime.time().hour() )
443 .arg( datetime.time().minute() )
444 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
445}
446
448{
449 if ( !isActive() )
450 return QString();
451
452 auto dateTimefieldCast = [ &context ]( const QString & fieldName ) -> QString
453 {
454 if ( context.layer()
455 && context.layer()->fields().lookupField( fieldName ) >= 0
456 && context.layer()->fields().at( context.layer()->fields().lookupField( fieldName ) ).type() != QMetaType::Type::QDateTime )
457 {
458 return QStringLiteral( "to_datetime( %1 )" ) .arg( QgsExpression::quotedColumnRef( fieldName ) );
459 }
460 return QgsExpression::quotedColumnRef( fieldName );
461 };
462
463 switch ( mMode )
464 {
467 return QString();
468
470 {
471 if ( mAccumulateFeatures )
472 {
473 return QStringLiteral( "(%1 %2 %3) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
474 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
475 dateTimeExpressionLiteral( filterRange.end() ) );
476 }
477 else if ( qgsDoubleNear( mFixedDuration, 0.0 ) )
478 {
479 return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
480 filterRange.includeBeginning() ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
481 dateTimeExpressionLiteral( filterRange.begin() ),
482 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
483 dateTimeExpressionLiteral( filterRange.end() ) );
484 }
485 else
486 {
487 // Working with features with events with a duration, so taking this duration into account (+ QgsInterval( -mFixedDuration, mDurationUnit ) ))
488 return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
489 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
490 dateTimeExpressionLiteral( filterRange.begin() + QgsInterval( -mFixedDuration, mDurationUnit ) ),
491 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
492 dateTimeExpressionLiteral( filterRange.end() ) );
493 }
494 }
495
497 {
498 QString intervalExpression;
499 switch ( mDurationUnit )
500 {
502 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1/1000)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
503 break;
504
506 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,0,%1)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
507 break;
508
510 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,0,%1,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
511 break;
512
514 intervalExpression = QStringLiteral( "make_interval(0,0,0,0,%1,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
515 break;
516
518 intervalExpression = QStringLiteral( "make_interval(0,0,0,%1,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
519 break;
520
522 intervalExpression = QStringLiteral( "make_interval(0,0,%1,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
523 break;
524
526 intervalExpression = QStringLiteral( "make_interval(0,%1,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
527 break;
528
530 intervalExpression = QStringLiteral( "make_interval(%1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
531 break;
532
534 intervalExpression = QStringLiteral( "make_interval(10 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
535 break;
536
538 intervalExpression = QStringLiteral( "make_interval(100 * %1,0,0,0,0,0,0)" ).arg( QgsExpression::quotedColumnRef( mDurationFieldName ) );
539 break;
540
543 return QString();
544 }
545 return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND ((%1 + %4 %5 %6) OR %7 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
546 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
547 dateTimeExpressionLiteral( filterRange.end() ),
548 intervalExpression,
549 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
550 dateTimeExpressionLiteral( filterRange.begin() ),
551 QgsExpression::quotedColumnRef( mDurationFieldName ) );
552 }
553
555 {
556 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
557 {
558 return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND (%4 %5 %6 OR %4 IS NULL)" ).arg( dateTimefieldCast( mStartFieldName ),
559 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
560 dateTimeExpressionLiteral( filterRange.end() ),
561 dateTimefieldCast( mEndFieldName ),
562 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
563 dateTimeExpressionLiteral( filterRange.begin() ) );
564
565 }
566 else if ( !mStartFieldName.isEmpty() )
567 {
568 return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mStartFieldName ),
569 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
570 dateTimeExpressionLiteral( filterRange.end() ) );
571 }
572 else if ( !mEndFieldName.isEmpty() )
573 {
574 return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( dateTimefieldCast( mEndFieldName ),
575 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
576 dateTimeExpressionLiteral( filterRange.begin() ) );
577 }
578 break;
579 }
580
582 {
583 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
584 {
585 return QStringLiteral( "((%1) %2 %3) AND ((%4) %5 %6)" ).arg( mStartExpression,
586 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
587 dateTimeExpressionLiteral( filterRange.end() ),
588 mEndExpression,
589 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
590 dateTimeExpressionLiteral( filterRange.begin() ) );
591 }
592 else if ( !mStartExpression.isEmpty() )
593 {
594 return QStringLiteral( "(%1) %2 %3" ).arg( mStartExpression,
595 filterRange.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
596 dateTimeExpressionLiteral( filterRange.end() ) );
597 }
598 else if ( !mEndExpression.isEmpty() )
599 {
600 return QStringLiteral( "(%1) %2 %3" ).arg( mEndExpression,
601 limitMode() == Qgis::VectorTemporalLimitMode::IncludeBeginIncludeEnd ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
602 dateTimeExpressionLiteral( filterRange.begin() ) );
603 }
604 break;
605 }
606 }
607
608 return QString();
609}
610
612{
613
614 // Check the fields and keep the first one that matches.
615 // We assume that the user has organized the data with the
616 // more "interesting" field names first.
617 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
618 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
619 // but adding hardcoded localized variants of the strings is encouraged.
620 static const QStringList sStartCandidates{ QStringLiteral( "start" ),
621 QStringLiteral( "begin" ),
622 QStringLiteral( "from" ),
623 QStringLiteral( "since" ),
624 // German candidates
625 QStringLiteral( "anfang" ),
626 QStringLiteral( "von" ),
627 QStringLiteral( "ab" ),
628 QStringLiteral( "seit" ) };
629
630 static const QStringList sEndCandidates{ QStringLiteral( "end" ),
631 QStringLiteral( "last" ),
632 QStringLiteral( "to" ),
633 QStringLiteral( "stop" ),
634 // German candidates
635 QStringLiteral( "ende" ),
636 QStringLiteral( "bis" ) };
637
638
639 static const QStringList sSingleFieldCandidates{ QStringLiteral( "event" ) };
640
641
642 bool foundStart = false;
643 bool foundEnd = false;
644
645 for ( const QgsField &field : fields )
646 {
647 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
648 continue;
649
650 if ( !foundStart )
651 {
652 for ( const QString &candidate : sStartCandidates )
653 {
654 const QString fldName = field.name();
655 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
656 {
657 mStartFieldName = fldName;
658 foundStart = true;
659 }
660 }
661 }
662
663 if ( !foundEnd )
664 {
665 for ( const QString &candidate : sEndCandidates )
666 {
667 const QString fldName = field.name();
668 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
669 {
670 mEndFieldName = fldName;
671 foundEnd = true;
672 }
673 }
674 }
675
676 if ( foundStart && foundEnd )
677 break;
678 }
679
680 if ( !foundStart )
681 {
682 // loop again, looking for likely "single field" candidates
683 for ( const QgsField &field : fields )
684 {
685 if ( field.type() != QMetaType::Type::QDate && field.type() != QMetaType::Type::QDateTime )
686 continue;
687
688 for ( const QString &candidate : sSingleFieldCandidates )
689 {
690 const QString fldName = field.name();
691 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
692 {
693 mStartFieldName = fldName;
694 foundStart = true;
695 }
696 }
697
698 if ( foundStart )
699 break;
700 }
701 }
702
703 if ( foundStart && foundEnd )
705 else if ( foundStart )
707
708 // note -- NEVER auto enable temporal properties here! It's just a helper designed
709 // to shortcut the initial field selection
710}
711
713{
714 return mLayer;
715}
716
718{
719 mLayer = layer;
720}
VectorTemporalMode
Vector layer temporal feature modes.
Definition qgis.h:2412
@ FeatureDateTimeStartAndDurationFromFields
Mode when features have a field for start time and a field for event duration.
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when symbology or...
@ FeatureDateTimeStartAndEndFromExpressions
Mode when features use expressions for start and end times.
@ FeatureDateTimeInstantFromField
Mode when features have a datetime instant taken from a single field.
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
@ FeatureDateTimeStartAndEndFromFields
Mode when features have separate fields for start and end times.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
TemporalUnit
Temporal units.
Definition qgis.h:4823
@ IrregularStep
Special 'irregular step' time unit, used for temporal data which uses irregular, non-real-world unit ...
@ Milliseconds
Milliseconds.
@ Unknown
Unknown time unit.
@ Centuries
Centuries.
@ StoresFeatureDateTimeInstantInField
Dataset has feature datetime instants stored in a single field.
@ StoresFeatureDateTimeStartAndEndInSeparateFields
Dataset stores feature start and end datetimes in separate fields.
@ HasFixedTemporalRange
Entire dataset from provider has a fixed start and end datetime.
VectorTemporalLimitMode
Mode for the handling of the limits of the filtering timeframe for vector features.
Definition qgis.h:2428
@ IncludeBeginIncludeEnd
Mode to include both limits of the filtering timeframe.
Base class for handling properties relating to a data provider's temporal capabilities.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
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:53
QMetaType::Type type
Definition qgsfield.h:60
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:46
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition qgsmaplayer.h:76
The class is used as a container of context for various read/write operations on other objects.
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
T begin() const
Returns the beginning of the range.
Definition qgsrange.h:444
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:451
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:569
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:466
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition qgsrange.h:459
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:480
static Q_INVOKABLE Qgis::TemporalUnit decodeTemporalUnit(const QString &string, bool *ok=nullptr)
Decodes a temporal unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
Implementation of data provider temporal properties for QgsVectorDataProviders.
Encapsulates the context in which a QgsVectorLayer's temporal capabilities will be applied.
QgsVectorLayer * layer() const
Returns the associated layer.
void setLayer(QgsVectorLayer *layer)
Sets the associated layer.
void guessDefaultsFromFields(const QgsFields &fields)
Attempts to setup the temporal properties by scanning a set of fields and looking for standard naming...
QString endExpression() const
Returns the expression for the end time for the feature's time spans.
void setDurationField(const QString &field)
Sets the name of the duration field, which contains the duration of the event.
void setMode(Qgis::VectorTemporalMode mode)
Sets the temporal properties mode.
QgsVectorLayerTemporalProperties(QObject *parent=nullptr, bool enabled=false)
Constructor for QgsVectorLayerTemporalProperties, with the specified parent object.
void setStartExpression(const QString &expression)
Sets the expression to use for the start time for the feature's time spans.
bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const override
Returns true if the layer should be visible and rendered for the specified time range.
Qgis::VectorTemporalLimitMode limitMode() const
Returns the temporal limit mode (to include or exclude begin/end limits).
void setLimitMode(Qgis::VectorTemporalLimitMode mode)
Sets the temporal limit mode (to include or exclude begin/end limits).
const QgsDateTimeRange & fixedTemporalRange() const
Returns the fixed temporal range for the layer.
double fixedDuration() const
Returns the fixed duration length, which contains the duration of the event.
bool accumulateFeatures() const
Returns true if features will be accumulated over time (i.e.
QgsTemporalProperty::Flags flags() const override
Returns flags associated to the temporal property.
void setFixedTemporalRange(const QgsDateTimeRange &range)
Sets a temporal range to apply to the whole layer.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads temporal properties from a DOM element previously written by writeXml().
void setEndExpression(const QString &endExpression)
Sets the expression to use for the end time for the feature's time spans.
QString durationField() const
Returns the name of the duration field, which contains the duration of the event.
void setDurationUnits(Qgis::TemporalUnit units)
Sets the units of the event's duration.
QString endField() const
Returns the name of the end datetime field, which contains the end time for the feature's time spans.
QString createFilterString(const QgsVectorLayerTemporalContext &context, const QgsDateTimeRange &range) const
Creates a QGIS expression filter string for filtering features within the specified context to those ...
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
Qgis::TemporalUnit durationUnits() const
Returns the units of the event's duration.
void setAccumulateFeatures(bool accumulate)
Sets whether features will be accumulated over time (i.e.
void setFixedDuration(double duration)
Sets the fixed event duration, which contains the duration of the event.
void setEndField(const QString &field)
Sets the name of the end datetime field, which contains the end time for the feature's time spans.
QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const override
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Qgis::VectorTemporalMode mode() const
Returns the temporal properties mode.
QString startField() const
Returns the name of the start datetime field, which contains the start time for the feature's time sp...
void setStartField(const QString &field)
Sets the name of the start datetime field, which contains the start time for the feature's time spans...
QString startExpression() const
Returns the expression for the start time for the feature's time spans.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
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:5875
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5958
QList< int > QgsAttributeList
Definition qgsfield.h:27
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:742
QString dateTimeExpressionLiteral(const QDateTime &datetime)