1 /*
2     SPDX-FileCopyrightText: 2002 Mark Hollomon <mhh@mindspring.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "simclock.h"
8 
9 #ifndef KSTARS_LITE
10 #include "kstars.h"
11 #include "simclockadaptor.h"
12 #endif
13 
14 #include <kstars_debug.h>
15 
16 int SimClock::TimerInterval = 100; //msec
17 
SimClock(QObject * parent,const KStarsDateTime & when)18 SimClock::SimClock(QObject *parent, const KStarsDateTime &when) : QObject(parent), tmr(this)
19 {
20 #ifndef KSTARS_LITE
21     new SimClockAdaptor(this);
22     QDBusConnection::sessionBus().registerObject("/KStars/SimClock", this);
23 #endif
24     if (!when.isValid())
25         tmr.stop();
26     setUTC(when);
27     julianmark = UTC.djd();
28 
29     QObject::connect(&tmr, SIGNAL(timeout()), this, SLOT(tick()));
30 }
31 
tick()32 void SimClock::tick()
33 {
34     if (!ManualMode) //only tick if ManualMode is false
35     {
36         long mselapsed = sysmark.elapsed();
37         if (mselapsed < lastelapsed)
38         {
39             // The sysmark timer has wrapped after 24 hours back to 0 ms.
40             // Reset sysmark and julianmark
41             julianmark = UTC.djd();
42             sysmark.start();
43             lastelapsed = 0;
44         }
45         else
46         {
47             lastelapsed = mselapsed;
48         }
49 
50         long double scaledsec = static_cast<long double>(mselapsed) * static_cast<long double>(Scale) / 1000.0;
51         UTC.setDJD(julianmark + scaledsec / (24. * 3600.));
52 
53         // 		qDebug() << "tick() : JD = " << QLocale().toString( UTC.djd(), 7 ) <<
54         // 			" mselapsed = " << mselapsed << " scale = " << Scale <<
55         // 			"  scaledsec = " << double(scaledsec);
56 
57         emit timeAdvanced();
58     }
59 }
60 
setManualMode(bool on)61 void SimClock::setManualMode(bool on)
62 {
63     if (on)
64     {
65         //Turn on manual ticking.
66         ManualActive = tmr.isActive();
67         tmr.stop();
68     }
69     else
70     {
71         //Turn off manual ticking.  If the Manual clock was active, start the timer.
72         if (isActive())
73         {
74             sysmark.start();
75             julianmark  = UTC.djd();
76             lastelapsed = 0;
77             tmr.start(TimerInterval);
78         }
79     }
80     ManualMode = on;
81 }
82 
manualTick(bool force,bool backward)83 void SimClock::manualTick(bool force, bool backward)
84 {
85     if (force || (ManualMode && ManualActive))
86     {
87         //The single shot timer is needed because otherwise the animation is happening so frequently
88         //that the kstars interface becomes too unresponsive.
89         //QTimer::singleShot(1, [this,backward] { setUTC(UTC.addSecs(static_cast<long double>Scale * (backward ? -1 : 1))); });
90         setUTC(UTC.addSecs(static_cast<long double>(Scale) * (backward ? -1 : 1)));
91     }
92     else if (!ManualMode)
93         tick();
94 }
95 
isActive()96 bool SimClock::isActive()
97 {
98     if (ManualMode)
99         return ManualActive;
100     else
101         return tmr.isActive();
102 }
103 
stop()104 void SimClock::stop()
105 {
106     if (ManualMode && ManualActive)
107     {
108         ManualActive = false;
109         emit clockToggled(true);
110     }
111 
112     if (!ManualMode && tmr.isActive())
113     {
114         qCDebug(KSTARS) << "Stopping the timer";
115         tmr.stop();
116         emit clockToggled(true);
117     }
118 }
119 
start()120 void SimClock::start()
121 {
122     if (ManualMode && !ManualActive)
123     {
124         ManualActive = true;
125         sysmark.start();
126         julianmark  = UTC.djd();
127         lastelapsed = 0;
128         emit clockToggled(false);
129         //emit timeChanged() in order to restart calls to updateTime()
130         emit timeChanged();
131     }
132     else if (!ManualMode && !tmr.isActive())
133     {
134         qCDebug(KSTARS) << "Starting the timer";
135         sysmark.start();
136         julianmark  = UTC.djd();
137         lastelapsed = 0;
138         tmr.start(TimerInterval);
139         emit clockToggled(false);
140     }
141 }
142 
setUTC(const KStarsDateTime & newtime)143 void SimClock::setUTC(const KStarsDateTime &newtime)
144 {
145     //DEBUG
146     //qDebug() << newtime.toString();
147     //qDebug() << "is dateTime valid? " << newtime.isValid();
148 
149     if (newtime.isValid())
150     {
151         UTC = newtime;
152         if (tmr.isActive())
153         {
154             julianmark = UTC.djd();
155             sysmark.start();
156             lastelapsed = 0;
157         }
158 
159         // N.B. Too much log spam when in manual mode
160         //qCInfo(KSTARS) << QString("Setting clock:  UTC: %1  JD: %2").arg(UTC.toString(), QLocale().toString((double)UTC.djd(), 'f', 2));
161         emit timeChanged();
162     }
163     else
164     {
165         qCWarning(KSTARS) << "Cannot set SimClock:  Invalid Date/Time.";
166     }
167 }
168 
setClockScale(float s)169 void SimClock::setClockScale(float s)
170 {
171     if (Scale != s)
172     {
173         qCInfo(KSTARS) << "New clock scale: " << s << " sec";
174         emit scaleChanged(s);
175         Scale = s;
176         if (tmr.isActive())
177         {
178             julianmark = UTC.djd();
179             sysmark.start();
180             lastelapsed = 0;
181         }
182     }
183 }
184