Kstars

modcalcdaylength.cpp
1/*
2 SPDX-FileCopyrightText: 2002 Pablo de Vicente <vicente@oan.es>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "modcalcdaylength.h"
8
9#include "geolocation.h"
10#include "kstarsdata.h"
11#include "ksnotification.h"
12#include "dialogs/locationdialog.h"
13#include "skyobjects/ksmoon.h"
14#include "skyobjects/kssun.h"
15#include "skyobjects/skyobject.h"
16
17#include <KLineEdit>
18#include <KLocalizedString>
19
20// Qt version calming
21#include <qtendl.h>
22
23modCalcDayLength::modCalcDayLength(QWidget *parentSplit) : QFrame(parentSplit)
24{
25 setupUi(this);
26
27 showCurrentDate();
28 initGeo();
29 slotComputeAlmanac();
30
31 connect(Date, SIGNAL(dateChanged(QDate)), this, SLOT(slotComputeAlmanac()));
32 connect(Location, SIGNAL(clicked()), this, SLOT(slotLocation()));
33
34 connect(LocationBatch, SIGNAL(clicked()), this, SLOT(slotLocationBatch()));
35 connect(InputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
36 connect(OutputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
37 connect(RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch()));
38 connect(ViewButtonBatch, SIGNAL(clicked()), this, SLOT(slotViewBatch()));
39
40 RunButtonBatch->setEnabled(false);
41 ViewButtonBatch->setEnabled(false);
42
43 show();
44}
45
46void modCalcDayLength::showCurrentDate(void)
47{
48 KStarsDateTime dt(KStarsDateTime::currentDateTime());
49 Date->setDate(dt.date());
50}
51
52void modCalcDayLength::initGeo(void)
53{
54 KStarsData *data = KStarsData::Instance();
55 geoPlace = data->geo();
56 geoBatch = data->geo();
57 Location->setText(geoPlace->fullName());
58 LocationBatch->setText(geoBatch->fullName());
59}
60
61QTime modCalcDayLength::lengthOfDay(const QTime &setQTime, const QTime &riseQTime)
62{
63 QTime dL(0, 0, 0);
64 int dds = riseQTime.secsTo(setQTime);
65 QTime dLength = dL.addSecs(dds);
66
67 return dLength;
68}
69
70void modCalcDayLength::slotLocation()
71{
72 QPointer<LocationDialog> ld = new LocationDialog(this);
73 if (ld->exec() == QDialog::Accepted)
74 {
75 GeoLocation *newGeo = ld->selectedCity();
76 if (newGeo)
77 {
78 geoPlace = newGeo;
79 Location->setText(geoPlace->fullName());
80 }
81 }
82 delete ld;
83
84 slotComputeAlmanac();
85}
86
87void modCalcDayLength::slotLocationBatch()
88{
89 QPointer<LocationDialog> ld = new LocationDialog(this);
90 if (ld->exec() == QDialog::Accepted)
91 {
92 GeoLocation *newGeo = ld->selectedCity();
93 if (newGeo)
94 {
95 geoBatch = newGeo;
96 LocationBatch->setText(geoBatch->fullName());
97 }
98 }
99 delete ld;
100}
101
102void modCalcDayLength::updateAlmanac(const QDate &d, GeoLocation *geo)
103{
104 //Determine values needed for the Almanac
105 long double jd0 = KStarsDateTime(d, QTime(8, 0, 0)).djd();
106 KSNumbers num(jd0);
107
108 //Sun
109 KSSun Sun;
110 Sun.findPosition(&num);
111
112 QTime ssTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, false);
113 QTime srTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, true);
114 QTime stTime = Sun.transitTime(KStarsDateTime(jd0), geo);
115
116 dms ssAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, false);
117 dms srAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, true);
118 dms stAlt = Sun.transitAltitude(KStarsDateTime(jd0), geo);
119
120 //In most cases, the Sun will rise and set:
121 if (ssTime.isValid())
122 {
123 ssAzString = ssAz.toDMSString();
124 stAltString = stAlt.toDMSString();
125 srAzString = srAz.toDMSString();
126
127 ssTimeString = QLocale().toString(ssTime, "hh:mm:ss");
128 srTimeString = QLocale().toString(srTime, "hh:mm:ss");
129 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
130
131 QTime daylength = lengthOfDay(ssTime, srTime);
132 //daylengthString = QLocale().toString(daylength);
133 daylengthString = QLocale().toString(daylength, "hh:mm:ss");
134
135 //...but not always!
136 }
137 else if (stAlt.Degrees() > 0.)
138 {
139 ssAzString = i18n("Circumpolar");
140 stAltString = stAlt.toDMSString();
141 srAzString = i18n("Circumpolar");
142
143 ssTimeString = "--:--";
144 srTimeString = "--:--";
145 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
146 daylengthString = "24:00";
147 }
148 else if (stAlt.Degrees() < 0.)
149 {
150 ssAzString = i18n("Does not rise");
151 stAltString = stAlt.toDMSString();
152 srAzString = i18n("Does not set");
153
154 ssTimeString = "--:--";
155 srTimeString = "--:--";
156 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
157 daylengthString = "00:00";
158 }
159
160 //Moon
161 KSMoon Moon;
162
163 QTime msTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, false);
164 QTime mrTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, true);
165 QTime mtTime = Moon.transitTime(KStarsDateTime(jd0), geo);
166
167 dms msAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, false);
168 dms mrAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, true);
169 dms mtAlt = Moon.transitAltitude(KStarsDateTime(jd0), geo);
170
171 //In most cases, the Moon will rise and set:
172 if (msTime.isValid())
173 {
174 msAzString = msAz.toDMSString();
175 mtAltString = mtAlt.toDMSString();
176 mrAzString = mrAz.toDMSString();
177
178 msTimeString = QLocale().toString(msTime, "hh:mm:ss");
179 mrTimeString = QLocale().toString(mrTime, "hh:mm:ss");
180 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
181
182 //...but not always!
183 }
184 else if (mtAlt.Degrees() > 0.)
185 {
186 msAzString = i18n("Circumpolar");
187 mtAltString = mtAlt.toDMSString();
188 mrAzString = i18n("Circumpolar");
189
190 msTimeString = "--:--";
191 mrTimeString = "--:--";
192 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
193 }
194 else if (mtAlt.Degrees() < 0.)
195 {
196 msAzString = i18n("Does not rise");
197 mtAltString = mtAlt.toDMSString();
198 mrAzString = i18n("Does not rise");
199
200 msTimeString = "--:--";
201 mrTimeString = "--:--";
202 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
203 }
204
205 //after calling riseSetTime Phase needs to reset, setting it before causes Phase to set nan
206 Moon.findPosition(&num);
207 Moon.findPhase(nullptr);
208 lunarphaseString = i18nc("%2 is the value, % is the percent sign", "%1 (%2%)", Moon.phaseName(), QString::number(int(100 * Moon.illum())));
209
210 //Fix length of Az strings
211 if (srAz.Degrees() < 100.0)
212 srAzString = ' ' + srAzString;
213 if (ssAz.Degrees() < 100.0)
214 ssAzString = ' ' + ssAzString;
215 if (mrAz.Degrees() < 100.0)
216 mrAzString = ' ' + mrAzString;
217 if (msAz.Degrees() < 100.0)
218 msAzString = ' ' + msAzString;
219}
220
221void modCalcDayLength::slotComputeAlmanac()
222{
223 updateAlmanac(Date->date(), geoPlace);
224
225 SunSet->setText(ssTimeString);
226 SunRise->setText(srTimeString);
227 SunTransit->setText(stTimeString);
228 SunSetAz->setText(ssAzString);
229 SunRiseAz->setText(srAzString);
230 SunTransitAlt->setText(stAltString);
231 DayLength->setText(daylengthString);
232
233 MoonSet->setText(msTimeString);
234 MoonRise->setText(mrTimeString);
235 MoonTransit->setText(mtTimeString);
236 MoonSetAz->setText(msAzString);
237 MoonRiseAz->setText(mrAzString);
238 MoonTransitAlt->setText(mtAltString);
239 LunarPhase->setText(lunarphaseString);
240}
241
242void modCalcDayLength::slotCheckFiles()
243{
244 bool flag = !InputFileBatch->lineEdit()->text().isEmpty() && !OutputFileBatch->lineEdit()->text().isEmpty();
245 RunButtonBatch->setEnabled(flag);
246}
247
248void modCalcDayLength::slotRunBatch()
249{
250 QString inputFileName = InputFileBatch->url().toLocalFile();
251
252 if (QFile::exists(inputFileName))
253 {
254 QFile f(inputFileName);
255 if (!f.open(QIODevice::ReadOnly))
256 {
257 QString message = i18n("Could not open file %1.", f.fileName());
258 KSNotification::sorry(message, i18n("Could Not Open File"));
259 return;
260 }
261
262 QTextStream istream(&f);
263 processLines(istream);
264 ViewButtonBatch->setEnabled(true);
265
266 f.close();
267 }
268 else
269 {
270 QString message = i18n("Invalid file: %1", inputFileName);
271 KSNotification::sorry(message, i18n("Invalid file"));
272 return;
273 }
274}
275
276void modCalcDayLength::processLines(QTextStream &istream)
277{
278 QFile fOut(OutputFileBatch->url().toLocalFile());
279 fOut.open(QIODevice::WriteOnly);
280 QTextStream ostream(&fOut);
281
282 //Write header
283 ostream << "# " << i18nc("%1 is a location on earth", "Almanac for %1", geoBatch->fullName())
284 << QString(" [%1, %2]").arg(geoBatch->lng()->toDMSString(), geoBatch->lat()->toDMSString())
285 << "\n# " << i18n("computed by KStars") << Qt::endl
286 << "# " << "SRise: Sun Rise" << Qt::endl
287 << "# " << "STran: Sun Transit" << Qt::endl
288 << "# " << "SSet: Sun Set" << Qt::endl
289 << "# " << "SRiseAz: Azimuth of Sun Rise" << Qt::endl
290 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl
291 << "# " << "SSetAz: Azimuth of Sun Set" << Qt::endl
292 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl
293 << "# " << "DayLen: Day Duration in hours" << Qt::endl
294 << "# " << "MRise: Moon Rise" << Qt::endl
295 << "# " << "MTran: Moon Transit" << Qt::endl
296 << "# " << "MSet: Moon Set" << Qt::endl
297 << "# " << "MRiseAz: Azimuth of Moon Rise" << Qt::endl
298 << "# " << "MTranAkt: Altitude of Moon Transit" << Qt::endl
299 << "# " << "MSetAz: Azimuth of Moon Set" << Qt::endl
300 << "# " << "LunarPhase: Lunar Phase and Illumination Percentage" << Qt::endl
301 << "# " << Qt::endl
302 << "# Date,SRise,STran,SSet,SRiseAz,STranAlt,SSetAz,DayLen,MRise,MTran,MSet,"
303 << "MRiseAz,MTranAlt,MSetAz,LunarPhase" << Qt::endl
304 << "#" << Qt::endl;
305
306 QString line;
307 QDate d;
308
309 while (!istream.atEnd())
310 {
311 line = istream.readLine();
312 line = line.trimmed();
313
314 //Parse the line as a date, then compute Almanac values
316 if (d.isValid())
317 {
318 updateAlmanac(d, geoBatch);
319 ostream << d.toString(Qt::ISODate) << "," <<
320 srTimeString << "," <<
321 stTimeString << "," <<
322 ssTimeString << "," <<
323 srAzString << "," <<
324 stAltString << "," <<
325 ssAzString << "," <<
326 daylengthString << "," <<
327 mrTimeString << "," <<
328 mtTimeString << "," <<
329 msTimeString << "," <<
330 mrAzString << "," <<
331 mtAltString << "," <<
332 msAzString << "," <<
333 lunarphaseString << Qt::endl;
334 }
335 }
336}
337
338void modCalcDayLength::slotViewBatch()
339{
340 QFile fOut(OutputFileBatch->url().toLocalFile());
341 fOut.open(QIODevice::ReadOnly);
342 QTextStream istream(&fOut);
343 QStringList text;
344
345 while (!istream.atEnd())
346 text.append(istream.readLine());
347
348 fOut.close();
349
350 KMessageBox::informationList(nullptr, i18n("Results of Almanac calculation"), text, OutputFileBatch->url().toLocalFile());
351}
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
QString phaseName() const
Definition ksmoon.cpp:288
double illum() const
Definition ksmoon.h:49
void findPhase(const KSSun *Sun=nullptr)
Determine the phase angle of the moon, and assign the appropriate moon image.
Definition ksmoon.cpp:268
void findPosition(const KSNumbers *num, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, const KSPlanetBase *Earth=nullptr)
Find position, including correction for Figure-of-the-Earth.
GeoLocation * geo()
Definition kstarsdata.h:238
static KStarsDateTime currentDateTime()
dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const
dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo) const
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
Definition skyobject.cpp:93
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:287
const double & Degrees() const
Definition dms.h:141
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void informationList(QWidget *parent, const QString &text, const QStringList &strlist, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
QDate fromString(QStringView string, QStringView format, QCalendar cal)
bool exists() const const
void append(QList< T > &&value)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QString trimmed() const const
QTextStream & endl(QTextStream &stream)
bool atEnd() const const
QString readLine(qint64 maxlen)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isValid(int h, int m, int s, int ms)
int secsTo(QTime t) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:53:03 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.