38 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
52 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
54 return QgsDateTimeRange();
64 if ( fieldIndex >= 0 )
66 const QDateTime min = vectorLayer->
minimumValue( fieldIndex ).toDateTime();
67 const QDateTime maxStartTime = vectorLayer->
maximumValue( fieldIndex ).toDateTime();
69 return QgsDateTimeRange( min, maxStartTime + eventDuration );
77 const int durationFieldIndex = vectorLayer->
fields().
lookupField( mDurationFieldName );
78 if ( fieldIndex >= 0 && durationFieldIndex >= 0 )
80 const QDateTime minTime = vectorLayer->
minimumValue( fieldIndex ).toDateTime();
88 const QDateTime start = f.
attribute( fieldIndex ).toDateTime();
89 if ( start.isValid() )
91 const QVariant durationValue = f.
attribute( durationFieldIndex );
92 if ( durationValue.isValid() )
94 const double duration = durationValue.toDouble();
95 const QDateTime end = start.addMSecs(
QgsInterval( duration, mDurationUnit ).seconds() * 1000.0 );
97 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
101 return QgsDateTimeRange( minTime, maxTime );
108 const int startFieldIndex = vectorLayer->
fields().
lookupField( mStartFieldName );
110 if ( startFieldIndex >= 0 && endFieldIndex >= 0 )
112 return QgsDateTimeRange( std::min( vectorLayer->
minimumValue( startFieldIndex ).toDateTime(),
113 vectorLayer->
minimumValue( endFieldIndex ).toDateTime() ),
114 std::max( vectorLayer->
maximumValue( startFieldIndex ).toDateTime(),
115 vectorLayer->
maximumValue( endFieldIndex ).toDateTime() ) );
117 else if ( startFieldIndex >= 0 )
119 return QgsDateTimeRange( vectorLayer->
minimumValue( startFieldIndex ).toDateTime(),
120 vectorLayer->
maximumValue( startFieldIndex ).toDateTime() );
122 else if ( endFieldIndex >= 0 )
124 return QgsDateTimeRange( vectorLayer->
minimumValue( endFieldIndex ).toDateTime(),
125 vectorLayer->
maximumValue( endFieldIndex ).toDateTime() );
132 bool hasStartExpression = !mStartExpression.isEmpty();
133 bool hasEndExpression = !mEndExpression.isEmpty();
134 if ( !hasStartExpression && !hasEndExpression )
135 return QgsDateTimeRange();
145 if ( hasStartExpression )
152 if ( hasEndExpression )
158 QSet< QString > fields;
159 if ( hasStartExpression )
161 if ( hasEndExpression )
177 const QDateTime start = hasStartExpression ?
startExpression.evaluate( &context ).toDateTime() : QDateTime();
178 const QDateTime end = hasEndExpression ?
endExpression.evaluate( &context ).toDateTime() : QDateTime();
180 if ( start.isValid() )
182 minTime = minTime.isValid() ? std::min( minTime, start ) : start;
183 if ( !hasEndExpression )
184 maxTime = maxTime.isValid() ? std::max( maxTime, start ) : start;
188 maxTime = maxTime.isValid() ? std::max( maxTime, end ) : end;
189 if ( !hasStartExpression )
190 minTime = minTime.isValid() ? std::min( minTime, end ) : end;
193 return QgsDateTimeRange( minTime, maxTime );
200 return QgsDateTimeRange();
234 QDomElement temporalNode = element.firstChildElement( QStringLiteral(
"temporal" ) );
236 setIsActive( temporalNode.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt() );
238 mMode =
static_cast< TemporalMode >( temporalNode.attribute( QStringLiteral(
"mode" ), QStringLiteral(
"0" ) ). toInt() );
240 mStartFieldName = temporalNode.attribute( QStringLiteral(
"startField" ) );
241 mEndFieldName = temporalNode.attribute( QStringLiteral(
"endField" ) );
242 mStartExpression = temporalNode.attribute( QStringLiteral(
"startExpression" ) );
243 mEndExpression = temporalNode.attribute( QStringLiteral(
"endExpression" ) );
244 mDurationFieldName = temporalNode.attribute( QStringLiteral(
"durationField" ) );
246 mFixedDuration = temporalNode.attribute( QStringLiteral(
"fixedDuration" ) ).toDouble();
247 mAccumulateFeatures = temporalNode.attribute( QStringLiteral(
"accumulate" ), QStringLiteral(
"0" ) ).toInt();
249 QDomNode rangeElement = temporalNode.namedItem( QStringLiteral(
"fixedRange" ) );
251 QDomNode begin = rangeElement.namedItem( QStringLiteral(
"start" ) );
252 QDomNode end = rangeElement.namedItem( QStringLiteral(
"end" ) );
254 QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
255 QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
257 QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
266 if ( element.isNull() )
267 return QDomElement();
269 QDomElement temporalElement = document.createElement( QStringLiteral(
"temporal" ) );
270 temporalElement.setAttribute( QStringLiteral(
"enabled" ),
isActive() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
271 temporalElement.setAttribute( QStringLiteral(
"mode" ), QString::number( mMode ) );
273 temporalElement.setAttribute( QStringLiteral(
"startField" ), mStartFieldName );
274 temporalElement.setAttribute( QStringLiteral(
"endField" ), mEndFieldName );
275 temporalElement.setAttribute( QStringLiteral(
"startExpression" ), mStartExpression );
276 temporalElement.setAttribute( QStringLiteral(
"endExpression" ), mEndExpression );
277 temporalElement.setAttribute( QStringLiteral(
"durationField" ), mDurationFieldName );
279 temporalElement.setAttribute( QStringLiteral(
"fixedDuration" ),
qgsDoubleToString( mFixedDuration ) );
280 temporalElement.setAttribute( QStringLiteral(
"accumulate" ), mAccumulateFeatures ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
282 QDomElement rangeElement = document.createElement( QStringLiteral(
"fixedRange" ) );
284 QDomElement startElement = document.createElement( QStringLiteral(
"start" ) );
285 QDomElement endElement = document.createElement( QStringLiteral(
"end" ) );
287 QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
288 QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
289 startElement.appendChild( startText );
290 endElement.appendChild( endText );
291 rangeElement.appendChild( startElement );
292 rangeElement.appendChild( endElement );
294 temporalElement.appendChild( rangeElement );
296 element.appendChild( temporalElement );
305 setIsActive( vectorCaps->hasTemporalCapabilities() );
309 switch ( vectorCaps->mode() )
326 return mStartExpression;
336 return mEndExpression;
346 return mAccumulateFeatures;
356 return mFixedDuration;
366 return mStartFieldName;
371 mStartFieldName = startFieldName;
376 return mEndFieldName;
381 mEndFieldName = field;
386 return mDurationFieldName;
391 mDurationFieldName = field;
396 return mDurationUnit;
401 mDurationUnit = units;
406 return QStringLiteral(
"make_datetime(%1,%2,%3,%4,%5,%6)" ).arg( datetime.date().year() )
407 .arg( datetime.date().month() )
408 .arg( datetime.date().day() )
409 .arg( datetime.time().hour() )
410 .arg( datetime.time().minute() )
411 .arg( datetime.time().second() + datetime.time().msec() / 1000.0 );
427 if ( mAccumulateFeatures )
430 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
436 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
438 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
444 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
446 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
453 QString intervalExpression;
454 switch ( mDurationUnit )
500 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
503 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
511 if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
514 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
517 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
520 else if ( !mStartFieldName.isEmpty() )
523 range.includeBeginning() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
526 else if ( !mEndFieldName.isEmpty() )
529 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
537 if ( !mStartExpression.isEmpty() && !mEndExpression.isEmpty() )
539 return QStringLiteral(
"((%1) %2 %3) AND ((%4) %5 %6)" ).arg( mStartExpression,
540 range.includeEnd() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
543 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
546 else if ( !mStartExpression.isEmpty() )
548 return QStringLiteral(
"(%1) %2 %3" ).arg( mStartExpression,
549 range.includeBeginning() ? QStringLiteral(
"<=" ) : QStringLiteral(
"<" ),
552 else if ( !mEndExpression.isEmpty() )
554 return QStringLiteral(
"(%1) %2 %3" ).arg( mEndExpression,
555 range.includeBeginning() ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
574 static QStringList sStartCandidates{ QStringLiteral(
"start" ),
575 QStringLiteral(
"begin" ),
576 QStringLiteral(
"from" )};
578 static QStringList sEndCandidates{ QStringLiteral(
"end" ),
579 QStringLiteral(
"last" ),
580 QStringLiteral(
"to" )};
582 static QStringList sSingleFieldCandidates{ QStringLiteral(
"event" ) };
585 bool foundStart =
false;
586 bool foundEnd =
false;
588 for (
const QgsField &field : fields )
590 if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
595 for (
const QString &candidate : sStartCandidates )
597 QString fldName = field.name();
598 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
600 mStartFieldName = fldName;
608 for (
const QString &candidate : sEndCandidates )
610 QString fldName = field.name();
611 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
613 mEndFieldName = fldName;
619 if ( foundStart && foundEnd )
626 for (
const QgsField &field : fields )
628 if ( field.type() != QVariant::Date && field.type() != QVariant::DateTime )
631 for (
const QString &candidate : sSingleFieldCandidates )
633 QString fldName = field.name();
634 if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
636 mStartFieldName = fldName;
646 if ( foundStart && foundEnd )
648 else if ( foundStart )