1 /*
2     SPDX-FileCopyrightText: 2002 Mark Hollomon <mhh@mindspring.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include "kstarsdatetime.h"
10 
11 #ifndef KSTARS_LITE
12 #include <QtDBus/QtDBus>
13 #endif
14 #include <QTime>
15 #include <QElapsedTimer>
16 #include <QTimer>
17 
18 /** @class SimClock
19 	*@short kstars simulation clock
20 	*@author Mark Hollomon
21 	*@version 1.0
22 	*/
23 
24 class SimClock : public QObject
25 {
26     Q_OBJECT
27     Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.SimClock")
28   public:
29     /**
30          * Constructor
31          * @param parent parent object for the clock
32          * @param when the date/time to which the SimClock should be initialized in UTC
33          */
34     explicit SimClock(QObject *parent = nullptr, const KStarsDateTime &when = KStarsDateTime::currentDateTimeUtc());
35 
36     /** @return const reference to the current simulation Universal Time. */
utc()37     const KStarsDateTime &utc() const { return UTC; }
38 
39     /** Whether the clock is active or not is a bit complicated by the
40         	*introduction of "manual mode".  In manual mode, SimClock's internal timer
41         	*is stopped, because the clock is ticked manually when the current update
42         	*has finished.  So, if ManualMode is true, then isActive() checks
43         	*whether ManualActive is true.  Otherwise, it checks whether the timer is
44         	*running.
45         	*@returns true if the Simulation clock is actively running.
46         	*/
47     Q_INVOKABLE bool isActive();
48 
49     /** @returns the current timestep setting */
scale()50     double scale() const { return Scale; }
51 
52     /** Manual Mode is a new (04/2002) addition to the SimClock.  It is
53         	*intended to be activated for large timesteps, when we want each frame
54         	*drawn to the screen to be precisely Scale seconds later than the
55         	*previous frame.  (i.e., if the timescale is 1 year, then each successive
56         	*frame should be 1 year later than the previous frame).  ManualMode
57         	*accomplishes this by stopping the internal timer and allowing the clock
58         	*to be advanced manually (the manualTick() slot is called at the end of each
59         	*KStars::updateTime()).
60         	*@returns whether Manual Mode is active.
61         	*/
isManualMode()62     bool isManualMode() const { return ManualMode; }
63 
64     /**Sets Manual Mode on/off according to the bool argument. */
65     void setManualMode(bool on = true);
66 
67   public Q_SLOTS:
68 #ifndef KSTARS_LITE
69     /** DBUS function to stop the SimClock. */
70     Q_SCRIPTABLE Q_NOREPLY void stop();
71 
72     /** DBUS function to start the SimClock. */
73     Q_SCRIPTABLE Q_NOREPLY void start();
74 
75     /** DBUS function to set the time of the SimClock. */
76     Q_SCRIPTABLE Q_NOREPLY void setUTC(const KStarsDateTime &newtime);
77 
78     /** DBUS function to set scale of simclock. */
79     Q_SCRIPTABLE Q_NOREPLY void setClockScale(float s);
80 #else
81     // Define non-DBUS versions of functions above for use within KStarsLite
82     /** Function to stop the SimClock. */
83     void stop();
84 
85     /** Function to start the SimClock. */
86     void start();
87 
88     /** Function to set the time of the SimClock. */
89     void setUTC(const KStarsDateTime &newtime);
90 
91     /** Function to set scale of simclock. */
92     void setClockScale(float s);
93 #endif
94 
95     /** Respond to the QTimer::timeout signal */
96     void tick();
97 
98     /** Equivalent of tick() for manual mode.
99          * If ManualActive is true, add Scale seconds to the SimClock time.
100          * (we may want to modify this slightly...e.g., the number of seconds in a
101          * year is not constant (leap years), so it is better to increment the
102          * year, instead of adding 31 million seconds.
103          * set backward to true to reverse sign of Scale value
104    */
105 
106     void manualTick(bool force = false, bool backward = false);
107 
108   signals:
109     /** The time has changed (emitted by setUTC() ) */
110     void timeChanged();
111 
112     /** The clock has ticked (emitted by tick() )*/
113     void timeAdvanced();
114 
115     /** The timestep has changed*/
116     void scaleChanged(float);
117 
118     /** This is an signal that is called on either clock start or
119             clock stop with an appropriate boolean argument. Required so
120             that we can bind it to KToggleAction::slotToggled(bool) */
121     void clockToggled(bool);
122 
123   private:
124     long double julianmark { 0 };
125     KStarsDateTime UTC;
126     QTimer tmr;
127     double Scale { 1 };
128     QElapsedTimer sysmark;
129     int lastelapsed { 0 };
130     bool ManualMode { false };
131     bool ManualActive { false };
132 
133     // used to generate names for dcop interfaces
134     //static int idgen;
135     // how often to update
136     static int TimerInterval;
137 
138     // Disallow copying
139     SimClock(const SimClock &);
140     SimClock &operator=(const SimClock &);
141 };
142