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 altMoveLeftB->setEnabled(false);
94 altMoveLeftB->setIcon(QIcon());
95 altMoveRightB->setEnabled(false);
96 altMoveRightB->setIcon(QIcon());
97 }
98 else if (m_AltGraphDay == 1)
99 {
100 altMoveLeftB->setEnabled(true);
101 altMoveRightB->setEnabled(true);
102 altMoveLeftB->setIcon(QIcon::fromTheme("arrow-left"));
103 altMoveRightB->setIcon(QIcon::fromTheme("arrow-right"));
104 }
105 else if (m_AltGraphDay == 2)
106 {
107 altMoveLeftB->setEnabled(true);
108 altMoveLeftB->setIcon(QIcon::fromTheme("arrow-left"));
109 altMoveRightB->setEnabled(false);
110 altMoveRightB->setIcon(QIcon());
111 }
112 else
113 {
114 m_AltGraphDay = 0;
115 altMoveLeftB->setEnabled(false);
116 altMoveLeftB->setIcon(QIcon());
117 altMoveRightB->setEnabled(true);
118 altMoveRightB->setIcon(QIcon::fromTheme("arrow-right"));
119 }
120}
121
122void SchedulerAltitudeGraph::plot()
123{
124 if (m_State->jobs().size() == 0)
125 {
126 altGraph->removeAllPlotObjects();
127 altGraph->update();
128 m_AltGraphDay = 0;
129 altGraphLabel->setText("");
130 handleButtons(true);
131 return;
132 }
133 m_AltitudeGraphUpdateTime = SchedulerModuleState::getLocalTime();
134 const QDateTime now = SchedulerModuleState::getLocalTime().addDays(m_AltGraphDay), start, end;
135 QDateTime nextDawn, nextDusk;
136 SchedulerModuleState::calculateDawnDusk(now, nextDawn, nextDusk);
137 QDateTime plotStart = (nextDusk < nextDawn) ? nextDusk : nextDusk.addDays(-1);
138
139 KStarsDateTime midnight = KStarsDateTime(now.date().addDays(1), QTime(0, 1), Qt::LocalTime);
140 // Midnight not quite right if it's in the wee hours before dawn.
141 // Then we use the midnight before now.
142 if (now.secsTo(nextDawn) < now.secsTo(nextDusk) && now.date() == nextDawn.date())
143 midnight = KStarsDateTime(now.date(), QTime(0, 1), Qt::LocalTime);
144
145 const QString dayName = m_AltGraphDay == 1 ? i18n("Tomorrow") : (m_AltGraphDay == 2 ? i18n("Day After Tomorrow") :
146 i18n("Tonight"));
147 const QString plotTitle = QString("%1 -- %2 -- %3")
148 .arg(midnight.addSecs(-6 * 3600).date().toString("MMM d"))
149 .arg(dayName)
150 .arg(midnight.date().toString("MMM d"));
151 altGraphLabel->setText(plotTitle);
152
153 const KStarsDateTime ut = SchedulerModuleState::getGeo()->LTtoUT(KStarsDateTime(midnight));
154 KSAlmanac ksal(ut, SchedulerModuleState::getGeo());
155
156 // Start the plot 1 hour before dusk and end it an hour after dawn.
157 plotStart = plotStart.addSecs(-1 * 3600);
158 auto plotEnd = nextDawn.addSecs(1 * 3600);
159
160 handleButtons(false);
161
162 const int currentPosition = m_State->currentPosition();
163
164 for (int index = 0; index < m_State->jobs().size(); index++)
165 {
166 auto t = plotStart;
167 QVector<double> times, alts;
168 auto job = m_State->jobs().at(index);
169 while (t.secsTo(plotEnd) > 0)
170 {
171 double alt = SchedulerUtils::findAltitude(job->getTargetCoords(), t);
172 alts.push_back(alt);
173 double hour = midnight.secsTo(t) / 3600.0;
174 times.push_back(hour);
175 t = t.addSecs(60 * 10);
176 }
177
178 const int lineWidth = (index == currentPosition) ? 2 : 1;
179 if (index == 0)
180 altGraph->plot(SchedulerModuleState::getGeo(), &ksal, times, alts, lineWidth, Qt::white, job->getName());
181 else
182 altGraph->plotOverlay(times, alts, lineWidth, Qt::white, job->getName());
183 }
184
185 altGraph->setCurrentLine(currentPosition);
186
187 // The below isn't part of the above loop because we want the altitude plot objects created above
188 // to have the same indexes as the jobs to simplify the connection between clicking a line
189 // and knowing what job it is.
190 //
191 // Create additional plots overlaying the above, that are the intervals that the job is scheduled to run.
192 for (int index = 0; index < m_State->jobs().size(); index++)
193 {
194 auto job = m_State->jobs().at(index);
195 for (const auto &jobSchedule : job->getSimulatedSchedule())
196 {
197 auto startTime = jobSchedule.startTime;
198 auto stopTime = jobSchedule.stopTime;
199 if (!startTime.isValid())
200 continue;
201 if (startTime < plotStart)
202 startTime = plotStart;
203 if (!stopTime.isValid() || stopTime > plotEnd)
204 stopTime = plotEnd;
205 if (startTime.isValid() && startTime < plotEnd && stopTime.isValid() && stopTime > plotStart)
206 {
207 QVector<double> runTimes, runAlts;
208 auto t = startTime;
209 while (t.secsTo(stopTime) >= 0)
210 {
211 double alt = SchedulerUtils::findAltitude(job->getTargetCoords(), t);
212 runAlts.push_back(alt);
213 double hour = midnight.secsTo(t) / 3600.0;
214 runTimes.push_back(hour);
215 int secsToStop = t.secsTo(stopTime);
216 if (secsToStop <= 0) break;
217 t = t.addSecs(std::min(60 * 1, secsToStop));
218 }
219
220 altGraph->plotOverlay(runTimes, runAlts, 4, Qt::green);
221 }
222 }
223 }
224}
225}
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,...
KStarsDateTime addSecs(double s) const
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
const QList< QKeySequence > & end()
void clicked(bool checked)
QDate addDays(qint64 ndays) const const
QString toString(QStringView format, QCalendar cal) 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)
QString arg(Args &&... args) const const
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 Apr 18 2025 12:01:33 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.