26 mNewFrameTimer =
new QTimer(
this );
28 connect( mNewFrameTimer, &QTimer::timeout,
29 this, &QgsTemporalNavigationObject::timerTimeout );
32void QgsTemporalNavigationObject::timerTimeout()
34 switch ( mPlayBackMode )
36 case AnimationState::Forward:
41 mCurrentFrameNumber = -1;
47 case AnimationState::Reverse:
49 if ( mCurrentFrameNumber <= 0 )
58 case AnimationState::Idle:
66 return mLoopAnimation;
71 mLoopAnimation = loopAnimation;
76 std::unique_ptr< QgsExpressionContextScope > scope = std::make_unique< QgsExpressionContextScope >( QStringLiteral(
"temporal" ) );
77 scope->setVariable( QStringLiteral(
"frame_rate" ), mFramesPerSecond,
true );
78 scope->setVariable( QStringLiteral(
"frame_number" ), mCurrentFrameNumber,
true );
79 scope->setVariable( QStringLiteral(
"frame_duration" ), mFrameDuration,
true );
80 scope->setVariable( QStringLiteral(
"frame_timestep" ), mFrameDuration.
originalDuration(),
true );
81 scope->setVariable( QStringLiteral(
"frame_timestep_unit" ),
static_cast< int >( mFrameDuration.
originalUnit() ),
true );
83 scope->setVariable( QStringLiteral(
"animation_start_time" ), mTemporalExtents.begin(),
true );
84 scope->setVariable( QStringLiteral(
"animation_end_time" ), mTemporalExtents.end(),
true );
85 scope->setVariable( QStringLiteral(
"animation_interval" ),
QgsInterval( mTemporalExtents.end() - mTemporalExtents.begin() ),
true );
87 scope->addHiddenVariable( QStringLiteral(
"frame_timestep_unit" ) );
89 return scope.release();
94 const QDateTime start = mTemporalExtents.begin();
99 const long long nextFrame = frame + 1;
103 if ( mFrameDuration.
originalUnit() == Qgis::TemporalUnit::IrregularStep )
105 if ( mAllRanges.empty() )
106 return QgsDateTimeRange();
108 return frame < mAllRanges.size() ? mAllRanges.at( frame ) : mAllRanges.constLast();
116 QDateTime frameStart = begin;
118 if ( mCumulativeTemporalRange )
121 return QgsDateTimeRange( frameStart, end,
true,
false );
126 if ( mNavigationMode == mode )
129 mNavigationMode = mode;
132 if ( !mBlockUpdateTemporalRangeSignal )
134 switch ( mNavigationMode )
160 switch ( mNavigationMode )
172 if ( !mBlockUpdateTemporalRangeSignal )
183 return mTemporalExtents;
198 if ( mCurrentFrameNumber != frameNumber )
200 mCurrentFrameNumber = std::max( 0LL, std::min( frameNumber,
totalFrameCount() - 1 ) );
203 if ( !mBlockUpdateTemporalRangeSignal )
210 return mCurrentFrameNumber;
229 if ( !mBlockUpdateTemporalRangeSignal && mNavigationMode ==
Animated )
235 return mFrameDuration;
240 if ( framesPerSeconds > 0 )
242 mFramesPerSecond = framesPerSeconds;
243 mNewFrameTimer->setInterval(
static_cast< int >( ( 1.0 / mFramesPerSecond ) * 1000 ) );
249 return mFramesPerSecond;
254 mCumulativeTemporalRange = state;
259 return mCumulativeTemporalRange;
264 mNewFrameTimer->start(
static_cast< int >( ( 1.0 / mFramesPerSecond ) * 1000 ) );
269 mNewFrameTimer->stop();
287 if ( mPlayBackMode ==
Idle && mCurrentFrameNumber <= 0 )
320 if ( mFrameDuration.
originalUnit() == Qgis::TemporalUnit::IrregularStep )
322 return mAllRanges.count();
326 const QgsInterval totalAnimationLength = mTemporalExtents.end() - mTemporalExtents.begin();
327 return static_cast< long long >( std::ceil( totalAnimationLength.
seconds() / mFrameDuration.
seconds() ) );
333 if ( mode != mPlayBackMode )
335 mPlayBackMode = mode;
342 return mPlayBackMode;
347 long long bestFrame = 0;
348 if ( mFrameDuration.
originalUnit() == Qgis::TemporalUnit::IrregularStep )
350 for (
const QgsDateTimeRange &range : mAllRanges )
352 if ( range.contains( frameStart ) )
354 else if ( range.begin() > frameStart )
356 return std::max( 0LL, bestFrame - 1 );
359 return mAllRanges.count() - 1;
363 const QgsDateTimeRange testFrame = QgsDateTimeRange( frameStart, frameStart );
365 long long roughFrameStart = 0;
369 if ( mFrameDuration.
originalUnit() != Qgis::TemporalUnit::Months && mFrameDuration.
originalUnit() != Qgis::TemporalUnit::Years && mFrameDuration.
originalUnit() != Qgis::TemporalUnit::Decades && mFrameDuration.
originalUnit() != Qgis::TemporalUnit::Centuries )
373 if ( mTemporalExtents.contains( frameStart ) )
375 roughFrameStart =
static_cast< long long >( std::floor(
QgsInterval( frameStart - mTemporalExtents.begin() ).
seconds() / mFrameDuration.
seconds() ) );
377 roughFrameEnd = roughFrameStart + 100;
379 for (
long long i = roughFrameStart; i < roughFrameEnd; ++i )
382 if ( range.overlaps( testFrame ) )
Single scope for storing variables and functions for use within a QgsExpressionContext.
A representation of the interval between two datetime values.
double originalDuration() const
Returns the original interval duration.
double seconds() const
Returns the interval duration in seconds.
Qgis::TemporalUnit originalUnit() const
Returns the original interval temporal unit.
A controller base class for temporal objects, contains a signal for notifying updates of the objects ...
void updateTemporalRange(const QgsDateTimeRange &range)
Signals that a temporal range has changed and needs to be updated in all connected objects.
bool isLooping() const
Returns true if the animation should loop after hitting the end or start frame.
void previous()
Jumps back to the previous frame.
double framesPerSecond() const
Returns the animation frame rate, in frames per second.
void setAvailableTemporalRanges(const QList< QgsDateTimeRange > &ranges)
Sets the list of all available temporal ranges which have data available.
void setFrameDuration(const QgsInterval &duration)
Sets the frame duration, which dictates the temporal length of each frame in the animation.
long long findBestFrameNumberForFrameStart(const QDateTime &frameStart) const
Returns the best suited frame number for the specified datetime, based on the start of the correspond...
void stateChanged(QgsTemporalNavigationObject::AnimationState state)
Emitted whenever the animation state changes.
QgsExpressionContextScope * createExpressionContextScope() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void playForward()
Starts the animation playing in a forward direction up till the end of all frames.
NavigationMode
Represents the current temporal navigation mode.
@ NavigationOff
Temporal navigation is disabled.
@ FixedRange
Temporal navigation relies on a fixed datetime range.
@ Animated
Temporal navigation relies on frames within a datetime range.
long long currentFrameNumber() const
Returns the current frame number.
void rewindToStart()
Rewinds the temporal navigation to start of the temporal extent.
void pause()
Pauses the temporal navigation.
void setCurrentFrameNumber(long long frame)
Sets the current animation frame number.
long long totalFrameCount() const
Returns the total number of frames for the navigation.
void skipToEnd()
Skips the temporal navigation to end of the temporal extent.
void temporalFrameDurationChanged(const QgsInterval &interval)
Emitted whenever the frameDuration interval of the controller changes.
void setFramesPerSecond(double rate)
Sets the animation frame rate, in frames per second.
QgsDateTimeRange temporalExtents() const
Returns the navigation temporal extents, which dictate the earliest and latest date time possible in ...
AnimationState
Represents the current animation state.
@ Idle
Animation is paused.
bool temporalRangeCumulative() const
Returns the animation temporal range cumulative settings.
void next()
Advances to the next frame.
QgsDateTimeRange dateTimeRangeForFrameNumber(long long frame) const
Calculates the temporal range associated with a particular animation frame.
void setTemporalExtents(const QgsDateTimeRange &extents)
Sets the navigation temporal extents, which dictate the earliest and latest date time possible in the...
void setTemporalRangeCumulative(bool state)
Sets the animation temporal range as cumulative.
QList< QgsDateTimeRange > availableTemporalRanges() const
Returns the list of all available temporal ranges which have data available.
void navigationModeChanged(QgsTemporalNavigationObject::NavigationMode mode)
Emitted whenever the navigation mode changes.
void play()
Starts playing the temporal navigation from its current frame, using the direction specified by anima...
void setLooping(bool loop)
Sets whether the animation should loop after hitting the end or start frame.
void playBackward()
Starts the animation playing in a reverse direction until the beginning of the time range.
void temporalExtentsChanged(const QgsDateTimeRange &extent)
Emitted whenever the temporalExtent extent changes.
void setAnimationState(AnimationState state)
Sets the current animation state.
void setNavigationMode(const NavigationMode mode)
Sets the temporal navigation mode.
QgsTemporalNavigationObject(QObject *parent=nullptr)
Constructor for QgsTemporalNavigationObject, with the specified parent object.
AnimationState animationState() const
Returns the current animation state.
QgsInterval frameDuration() const
Returns the current set frame duration, which dictates the temporal length of each frame in the anima...
static QDateTime calculateFrameTime(const QDateTime &start, const long long frame, const QgsInterval &interval)
Calculates the frame time for an animation.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.