Kstars

scheduleraltitudegraph.cpp
1/*
2 SPDX-FileCopyrightText: 2024 Hy Murveit <hy@murveit.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "scheduleraltitudegraph.h"
8#include "ui_scheduleraltitudegraph.h"
9#include "kplotwidget.h"
10#include "kplotobject.h"
11#include "kplotaxis.h"
12#include "ksalmanac.h"
13#include "schedulerjob.h"
14#include "schedulerutils.h"
15
16// This is just to get the time (including simulated time).
17#include "schedulermodulestate.h"
18
19
20namespace Ekos
21{
22
23SchedulerAltitudeGraph::SchedulerAltitudeGraph(QWidget * parent) : QFrame(parent)
24{
25 setupUi(this);
26 setup();
27}
28
29void SchedulerAltitudeGraph::setState(QSharedPointer<SchedulerModuleState> state)
30{
31 m_State = state;
32}
33
34// The job table gets updated constantly (e.g. every second), so this
35// reduces the rate that the altitude graphs get regenerated.
36void SchedulerAltitudeGraph::tickle()
37{
38 if (m_State->jobs().isEmpty() ||
39 !m_AltitudeGraphUpdateTime.isValid() ||
40 m_AltitudeGraphUpdateTime.secsTo(SchedulerModuleState::getLocalTime()) > 120)
41 {
42 m_AltGraphDay = 0;
43 plot();
44 }
45}
46
47void SchedulerAltitudeGraph::next()
48{
49 m_AltGraphDay++;
50 if (m_AltGraphDay > 2)
51 m_AltGraphDay = 2;
52 plot();
53}
54void SchedulerAltitudeGraph::prev()
55{
56 m_AltGraphDay--;
57 if (m_AltGraphDay < 0)
58 m_AltGraphDay = 0;
59 plot();
60}
61
62void SchedulerAltitudeGraph::setup()
63{
64 // Hide the buttons and disable them
65 altMoveLeftB->setStyleSheet("background-color: black;");
66 altMoveRightB->setStyleSheet("background-color: black;");
67 altMoveLeftB->setIcon(QIcon());
68 altMoveRightB->setIcon(QIcon());
69 altMoveLeftB->setEnabled(false);
70 altMoveRightB->setEnabled(false);
71 altMoveLeftB->setFixedWidth(16);
72 altMoveRightB->setFixedWidth(16);
73 altMoveLeftB->setFixedHeight(16);
74 altMoveRightB->setFixedHeight(16);
75
76 altGraph->setAltitudeAxis(-20.0, 90.0);
77 altGraph->setTopPadding(0);
78 altGraph->setBottomPadding(25);
79 altGraph->setLeftPadding(25);
80 altGraph->setRightPadding(10);
81 altGraph->disableAxis(KPlotWidget::TopAxis);
82
83 connect(altMoveRightB, &QPushButton::clicked, this, &SchedulerAltitudeGraph::next);
84 connect(altMoveLeftB, &QPushButton::clicked, this, &SchedulerAltitudeGraph::prev);
85}
86
87void SchedulerAltitudeGraph::handleButtons(bool disable)
88{
89
90 if (disable)
91 {
92 m_AltGraphDay = 0;
93 altGraphLabel->setText("");
94 altMoveLeftB->setEnabled(false);
95 altMoveLeftB->setIcon(QIcon());
96 altMoveRightB->setEnabled(false);
97 altMoveRightB->setIcon(QIcon());
98 }
99 else if (m_AltGraphDay == 1)
100 {
101 altGraphLabel->setText("Tomorrow");
102 altMoveLeftB->setEnabled(true);
103 altMoveRightB->setEnabled(true);
104 altMoveLeftB->setIcon(QIcon::fromTheme("arrow-left"));
105 altMoveRightB->setIcon(QIcon::fromTheme("arrow-right"));
106 }
107 else if (m_AltGraphDay == 2)
108 {
109 altGraphLabel->setText("Day After Tomorrow");
110 altMoveLeftB->setEnabled(true);
111 altMoveLeftB->setIcon(QIcon::fromTheme("arrow-left"));
112 altMoveRightB->setEnabled(false);
113 altMoveRightB->setIcon(QIcon());
114 }
115 else
116 {
117 m_AltGraphDay = 0;
118 altGraphLabel->setText("");
119 altMoveLeftB->setEnabled(false);
120 altMoveLeftB->setIcon(QIcon());
121 altMoveRightB->setEnabled(true);
122 altMoveRightB->setIcon(QIcon::fromTheme("arrow-right"));
123 }
124}
125
126void SchedulerAltitudeGraph::plot()
127{
128 if (m_State->jobs().size() == 0)
129 {
130 altGraph->removeAllPlotObjects();
131 altGraph->update();
132 m_AltGraphDay = 0;
133 handleButtons(true);
134 return;
135 }
136 m_AltitudeGraphUpdateTime = SchedulerModuleState::getLocalTime();
137 const QDateTime now = SchedulerModuleState::getLocalTime().addDays(m_AltGraphDay), start, end;
138 QDateTime nextDawn, nextDusk;
139 SchedulerModuleState::calculateDawnDusk(now, nextDawn, nextDusk);
140 QDateTime plotStart = (nextDusk < nextDawn) ? nextDusk : nextDusk.addDays(-1);
141
142 KStarsDateTime midnight = KStarsDateTime(now.date().addDays(1), QTime(0, 1), Qt::LocalTime);
143 // Midnight not quite right if it's in the wee hours before dawn.
144 // Then we use the midnight before now.
145 if (now.secsTo(nextDawn) < now.secsTo(nextDusk) && now.date() == nextDawn.date())
146 midnight = KStarsDateTime(now.date(), QTime(0, 1), Qt::LocalTime);
147 const KStarsDateTime ut = SchedulerModuleState::getGeo()->LTtoUT(KStarsDateTime(midnight));
148 KSAlmanac ksal(ut, SchedulerModuleState::getGeo());
149
150 // Start the plot 1 hour before dusk and end it an hour after dawn.
151 plotStart = plotStart.addSecs(-1 * 3600);
152 auto plotEnd = nextDawn.addSecs(1 * 3600);
153
154 handleButtons();
155
156 const int currentPosition = m_State->currentPosition();
157
158 for (int index = 0; index < m_State->jobs().size(); index++)
159 {
160 auto t = plotStart;
161 QVector<double> times, alts;
162 auto job = m_State->jobs().at(index);
163 while (t.secsTo(plotEnd) > 0)
164 {
165 double alt = SchedulerUtils::findAltitude(job->getTargetCoords(), t);
166 alts.push_back(alt);
167 double hour = midnight.secsTo(t) / 3600.0;
168 times.push_back(hour);
169 t = t.addSecs(60 * 10);
170 }
171
172 const int lineWidth = (index == currentPosition) ? 2 : 1;
173 if (index == 0)
174 altGraph->plot(SchedulerModuleState::getGeo(), &ksal, times, alts, lineWidth, Qt::white);
175 else
176 altGraph->plotOverlay(times, alts, lineWidth, Qt::white);
177 }
178
179 altGraph->setCurrentLine(currentPosition);
180
181 // The below isn't part of the above loop because we want the altitude plot objects created above
182 // to have the same indexes as the jobs to simplify the connection between clicking a line
183 // and knowing what job it is.
184 //
185 // Create additional plots overlaying the above, that are the intervals that the job is scheduled to run.
186 for (int index = 0; index < m_State->jobs().size(); index++)
187 {
188 auto job = m_State->jobs().at(index);
189 for (const auto &jobSchedule : job->getSimulatedSchedule())
190 {
191 auto startTime = jobSchedule.startTime;
192 auto stopTime = jobSchedule.stopTime;
193 if (startTime.isValid() && startTime < plotEnd && stopTime.isValid() && stopTime > plotStart)
194 {
195 if (startTime < plotStart) startTime = plotStart;
196 if (stopTime > plotEnd)
197 stopTime = plotEnd;
198
199 QVector<double> runTimes, runAlts;
200 auto t = startTime;
201 while (t.secsTo(stopTime) >= 0)
202 {
203 double alt = SchedulerUtils::findAltitude(job->getTargetCoords(), t);
204 runAlts.push_back(alt);
205 double hour = midnight.secsTo(t) / 3600.0;
206 runTimes.push_back(hour);
207 int secsToStop = t.secsTo(stopTime);
208 if (secsToStop <= 0) break;
209 t = t.addSecs(std::min(60 * 1, secsToStop));
210 }
211
212 altGraph->plotOverlay(runTimes, runAlts, 4, Qt::green);
213 }
214 }
215 }
216}
217}
A class that implements methods to find sun rise, sun set, twilight begin / end times,...
Definition ksalmanac.h:27
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
void clicked(bool checked)
QDate addDays(qint64 ndays) const const
QDateTime addDays(qint64 ndays) const const
QDateTime addSecs(qint64 s) const const
QDate date() const const
qint64 secsTo(const QDateTime &other) const const
QIcon fromTheme(const QString &name)
const_reference at(qsizetype i) const const
void push_back(parameter_type value)
LocalTime
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 7 2025 11:55:44 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.