Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgstemporalnavigationobject.h 3 : : --------------- 4 : : begin : March 2020 5 : : copyright : (C) 2020 by Samweli Mwakisambwe 6 : : email : samweli at kartoza 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 : : 18 : : 19 : : #ifndef QGSTEMPORALNAVIGATIONOBJECT_H 20 : : #define QGSTEMPORALNAVIGATIONOBJECT_H 21 : : 22 : : #include "qgis_core.h" 23 : : #include "qgsrange.h" 24 : : #include "qgsinterval.h" 25 : : #include "qgstemporalcontroller.h" 26 : : #include "qgsexpressioncontextscopegenerator.h" 27 : : 28 : : #include <QList> 29 : : #include <QTimer> 30 : : 31 : : class QgsMapLayer; 32 : : 33 : : /** 34 : : * \ingroup core 35 : : * \brief Implements a temporal controller based on a frame by frame navigation and animation. 36 : : * 37 : : * \since QGIS 3.14 38 : : */ 39 : 0 : class CORE_EXPORT QgsTemporalNavigationObject : public QgsTemporalController, public QgsExpressionContextScopeGenerator 40 : : { 41 : : Q_OBJECT 42 : : 43 : : public: 44 : : 45 : : /** 46 : : * Constructor for QgsTemporalNavigationObject, with the specified \a parent object. 47 : : */ 48 : : QgsTemporalNavigationObject( QObject *parent SIP_TRANSFERTHIS = nullptr ); 49 : : 50 : : //! Represents the current temporal navigation mode. 51 : : enum NavigationMode 52 : : { 53 : : NavigationOff, //!< Temporal navigation is disabled 54 : : Animated, //!< Temporal navigation relies on frames within a datetime range 55 : : FixedRange, //!< Temporal navigation relies on a fixed datetime range 56 : : }; 57 : : 58 : : //! Represents the current animation state. 59 : : enum AnimationState 60 : : { 61 : : Forward, //!< Animation is playing forward. 62 : : Reverse, //!< Animation is playing in reverse. 63 : : Idle, //!< Animation is paused. 64 : : }; 65 : : 66 : : /** 67 : : * Sets the current animation \a state. 68 : : * 69 : : * \see animationState() 70 : : */ 71 : : void setAnimationState( AnimationState state ); 72 : : 73 : : /** 74 : : * Returns the current animation state. 75 : : * 76 : : * \see setAnimationState() 77 : : */ 78 : : AnimationState animationState() const; 79 : : 80 : : /** 81 : : * Sets the temporal navigation \a mode. 82 : : * 83 : : * \see navigationMode() 84 : : */ 85 : : void setNavigationMode( const NavigationMode mode ); 86 : : 87 : : /** 88 : : * Returns the currenttemporal navigation mode. 89 : : * 90 : : * \see setNavigationMode() 91 : : */ 92 : : NavigationMode navigationMode() const { return mNavigationMode; } 93 : : 94 : : /** 95 : : * Sets the navigation temporal \a extents, which dictate the earliest 96 : : * and latest date time possible in the animation. 97 : : * 98 : : * \note Calling this will reset the currentFrameNumber() to the first frame. 99 : : * 100 : : * \see temporalExtents() 101 : : */ 102 : : void setTemporalExtents( const QgsDateTimeRange &extents ); 103 : : 104 : : /** 105 : : * Returns the navigation temporal extents, which dictate the earliest 106 : : * and latest date time possible in the animation. 107 : : * 108 : : * \see setTemporalExtents() 109 : : */ 110 : : QgsDateTimeRange temporalExtents() const; 111 : : 112 : : /** 113 : : * Sets the list of all available temporal \a ranges which have data available. 114 : : * 115 : : * The \a ranges list can be a list of non-contiguous ranges (i.e. containing gaps) 116 : : * which together describe the complete range of times which contain data. 117 : : * 118 : : * \see availableTemporalRanges() 119 : : * \since QGIS 3.20 120 : : */ 121 : : void setAvailableTemporalRanges( const QList< QgsDateTimeRange > &ranges ); 122 : : 123 : : /** 124 : : * Returns the list of all available temporal ranges which have data available. 125 : : * 126 : : * The ranges list can be a list of non-contiguous ranges (i.e. containing gaps) 127 : : * which together describe the complete range of times which contain data. 128 : : * 129 : : * \see setAvailableTemporalRanges() 130 : : * \since QGIS 3.20 131 : : */ 132 : : QList< QgsDateTimeRange > availableTemporalRanges() const; 133 : : 134 : : /** 135 : : * Sets the current animation \a frame number. 136 : : * 137 : : * Caling this method will change the controllers current datetime range to match, based on the 138 : : * temporalExtents() and frameDuration() values. 139 : : * 140 : : * \see currentFrameNumber() 141 : : */ 142 : : void setCurrentFrameNumber( long long frame ); 143 : : 144 : : /** 145 : : * Returns the current frame number. 146 : : * 147 : : * \see setCurrentFrameNumber() 148 : : */ 149 : : long long currentFrameNumber() const; 150 : : 151 : : /** 152 : : * Sets the frame \a duration, which dictates the temporal length of each frame in the animation. 153 : : * 154 : : * \note Calling this will reset the currentFrameNumber() to the closest temporal match for the previous temporal range. 155 : : * 156 : : * \see frameDuration() 157 : : */ 158 : : void setFrameDuration( const QgsInterval &duration ); 159 : : 160 : : /** 161 : : * Returns the current set frame duration, which dictates the temporal length of each frame in the animation. 162 : : * 163 : : * \see setFrameDuration() 164 : : */ 165 : : QgsInterval frameDuration() const; 166 : : 167 : : /** 168 : : * Calculates the temporal range associated with a particular animation \a frame. 169 : : * 170 : : * This is calculated from the navigation start time (taken from temporalExtents()), 171 : : * the specified \a frame number, and the frame duration (see frameDuration()). 172 : : */ 173 : : QgsDateTimeRange dateTimeRangeForFrameNumber( long long frame ) const; 174 : : 175 : : /** 176 : : * Sets the animation frame \a rate, in frames per second. 177 : : * 178 : : * This setting controls the overall playback speed of the animation, i.e. how quickly 179 : : * a playing animation will advance to the next frame. 180 : : * 181 : : * \see framesPerSecond() 182 : : */ 183 : : void setFramesPerSecond( double rate ); 184 : : 185 : : /** 186 : : * Returns the animation frame rate, in frames per second. 187 : : * 188 : : * This setting controls the overall playback speed of the animation, i.e. how quickly 189 : : * a playing animation will advance to the next frame. 190 : : * 191 : : * \see setFramesPerSecond() 192 : : */ 193 : : double framesPerSecond() const; 194 : : 195 : : /** 196 : : * Sets the animation temporal range as cumulative. 197 : : * 198 : : * \see temporalRangeCumulative() 199 : : */ 200 : : void setTemporalRangeCumulative( bool state ); 201 : : 202 : : /** 203 : : * Returns the animation temporal range cumulative settings. 204 : : * 205 : : * \see setTemporalRangeCumulative() 206 : : */ 207 : : bool temporalRangeCumulative() const; 208 : : 209 : : /** 210 : : * Returns the total number of frames for the navigation. 211 : : */ 212 : : long long totalFrameCount() const; 213 : : 214 : : /** 215 : : * Returns TRUE if the animation should loop after hitting the end or start frame. 216 : : * 217 : : * \see setLooping() 218 : : */ 219 : : bool isLooping() const; 220 : : 221 : : /** 222 : : * Sets whether the animation should \a loop after hitting the end or start frame. 223 : : * 224 : : * \see isLooping() 225 : : */ 226 : : void setLooping( bool loop ); 227 : : 228 : : /** 229 : : * Returns the best suited frame number for the specified datetime, based on the start of the corresponding temporal range. 230 : : */ 231 : : long long findBestFrameNumberForFrameStart( const QDateTime &frameStart ) const; 232 : : 233 : : QgsExpressionContextScope *createExpressionContextScope() const override SIP_FACTORY; 234 : : 235 : : signals: 236 : : 237 : : /** 238 : : * Emitted whenever the animation \a state changes. 239 : : */ 240 : : void stateChanged( AnimationState state ); 241 : : 242 : : /** 243 : : * Emitted whenever the navigation \a mode changes. 244 : : */ 245 : : void navigationModeChanged( NavigationMode mode ); 246 : : 247 : : /** 248 : : * Emitted whenever the temporalExtent \a extent changes. 249 : : */ 250 : : void temporalExtentsChanged( const QgsDateTimeRange &extent ); 251 : : 252 : : /** 253 : : * Emitted whenever the frameDuration \a interval of the controller changes. 254 : : */ 255 : : void temporalFrameDurationChanged( const QgsInterval &interval ); 256 : : 257 : : 258 : : public slots: 259 : : 260 : : /** 261 : : * Starts playing the temporal navigation from its current frame, 262 : : * using the direction specified by animationState() 263 : : */ 264 : : void play(); 265 : : 266 : : /** 267 : : * Pauses the temporal navigation. 268 : : * 269 : : * Calling this slot changes the animation state to idle, preventing 270 : : * automatic advancement of frames. 271 : : * 272 : : * It does not affect the current animation frame number or the current 273 : : * temporal range of the controller. 274 : : */ 275 : : void pause(); 276 : : 277 : : /** 278 : : * Starts the animation playing in a forward direction up till the end of all frames. 279 : : */ 280 : : void playForward(); 281 : : 282 : : /** 283 : : * Starts the animation playing in a reverse direction until the beginning of the time range. 284 : : */ 285 : : void playBackward(); 286 : : 287 : : /** 288 : : * Advances to the next frame. 289 : : * 290 : : * \note Calling this slot does not change the current animation state, i.e. a paused animation 291 : : * will remain paused. 292 : : */ 293 : : void next(); 294 : : 295 : : /** 296 : : * Jumps back to the previous frame. 297 : : * 298 : : * \note Calling this slot does not change the current animation state, i.e. a paused animation 299 : : * will remain paused. 300 : : */ 301 : : void previous(); 302 : : 303 : : /** 304 : : * Rewinds the temporal navigation to start of the temporal extent. 305 : : */ 306 : : void rewindToStart(); 307 : : 308 : : /** 309 : : * Skips the temporal navigation to end of the temporal extent. 310 : : */ 311 : : void skipToEnd(); 312 : : 313 : : private slots: 314 : : 315 : : //! Handles logic when the temporal navigation timer emit a timeout signal. 316 : : void timerTimeout(); 317 : : 318 : : private: 319 : : 320 : : //! The controller temporal navigation extent range. 321 : : QgsDateTimeRange mTemporalExtents; 322 : : 323 : : //! Complete list of time ranges with data available 324 : : QList< QgsDateTimeRange > mAllRanges; 325 : : 326 : : NavigationMode mNavigationMode = NavigationOff; 327 : : 328 : : //! The current set frame value 329 : : long long mCurrentFrameNumber = 0; 330 : : 331 : : //! Frame duration 332 : : QgsInterval mFrameDuration = QgsInterval( 1.0, QgsUnitTypes::TemporalUnit::TemporalHours ); 333 : : 334 : : //! Member for frame rate 335 : : double mFramesPerSecond = 1; 336 : : 337 : : //! Timer to set navigation time interval 338 : : QTimer *mNewFrameTimer = nullptr; 339 : : 340 : : //! Navigation playback mode member 341 : : AnimationState mPlayBackMode = Idle; 342 : : 343 : : bool mLoopAnimation = false; 344 : : 345 : : bool mCumulativeTemporalRange = false; 346 : : 347 : : int mBlockUpdateTemporalRangeSignal = 0; 348 : : 349 : : QgsTemporalNavigationObject( const QgsTemporalNavigationObject & ) = delete; 350 : : QgsTemporalNavigationObject &operator= ( const QgsTemporalNavigationObject & ) = delete; 351 : : }; 352 : : 353 : : #endif // QGSTEMPORALNAVIGATIONOBJECT_H