File indexing completed on 2024-04-21 14:46:54
0001 /* 0002 SPDX-FileCopyrightText: 2002 Pablo de Vicente <vicente@oan.es> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "modcalcdaylength.h" 0008 0009 #include "geolocation.h" 0010 #include "kstarsdata.h" 0011 #include "ksnotification.h" 0012 #include "dialogs/locationdialog.h" 0013 #include "skyobjects/ksmoon.h" 0014 #include "skyobjects/kssun.h" 0015 #include "skyobjects/skyobject.h" 0016 0017 #include <KLineEdit> 0018 0019 // Qt version calming 0020 #include <qtendl.h> 0021 0022 modCalcDayLength::modCalcDayLength(QWidget *parentSplit) : QFrame(parentSplit) 0023 { 0024 setupUi(this); 0025 0026 showCurrentDate(); 0027 initGeo(); 0028 slotComputeAlmanac(); 0029 0030 connect(Date, SIGNAL(dateChanged(QDate)), this, SLOT(slotComputeAlmanac())); 0031 connect(Location, SIGNAL(clicked()), this, SLOT(slotLocation())); 0032 0033 connect(LocationBatch, SIGNAL(clicked()), this, SLOT(slotLocationBatch())); 0034 connect(InputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles())); 0035 connect(OutputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles())); 0036 connect(RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch())); 0037 connect(ViewButtonBatch, SIGNAL(clicked()), this, SLOT(slotViewBatch())); 0038 0039 RunButtonBatch->setEnabled(false); 0040 ViewButtonBatch->setEnabled(false); 0041 0042 show(); 0043 } 0044 0045 void modCalcDayLength::showCurrentDate(void) 0046 { 0047 KStarsDateTime dt(KStarsDateTime::currentDateTime()); 0048 Date->setDate(dt.date()); 0049 } 0050 0051 void modCalcDayLength::initGeo(void) 0052 { 0053 KStarsData *data = KStarsData::Instance(); 0054 geoPlace = data->geo(); 0055 geoBatch = data->geo(); 0056 Location->setText(geoPlace->fullName()); 0057 LocationBatch->setText(geoBatch->fullName()); 0058 } 0059 0060 QTime modCalcDayLength::lengthOfDay(const QTime &setQTime, const QTime &riseQTime) 0061 { 0062 QTime dL(0, 0, 0); 0063 int dds = riseQTime.secsTo(setQTime); 0064 QTime dLength = dL.addSecs(dds); 0065 0066 return dLength; 0067 } 0068 0069 void modCalcDayLength::slotLocation() 0070 { 0071 QPointer<LocationDialog> ld = new LocationDialog(this); 0072 if (ld->exec() == QDialog::Accepted) 0073 { 0074 GeoLocation *newGeo = ld->selectedCity(); 0075 if (newGeo) 0076 { 0077 geoPlace = newGeo; 0078 Location->setText(geoPlace->fullName()); 0079 } 0080 } 0081 delete ld; 0082 0083 slotComputeAlmanac(); 0084 } 0085 0086 void modCalcDayLength::slotLocationBatch() 0087 { 0088 QPointer<LocationDialog> ld = new LocationDialog(this); 0089 if (ld->exec() == QDialog::Accepted) 0090 { 0091 GeoLocation *newGeo = ld->selectedCity(); 0092 if (newGeo) 0093 { 0094 geoBatch = newGeo; 0095 LocationBatch->setText(geoBatch->fullName()); 0096 } 0097 } 0098 delete ld; 0099 } 0100 0101 void modCalcDayLength::updateAlmanac(const QDate &d, GeoLocation *geo) 0102 { 0103 //Determine values needed for the Almanac 0104 long double jd0 = KStarsDateTime(d, QTime(8, 0, 0)).djd(); 0105 KSNumbers num(jd0); 0106 0107 //Sun 0108 KSSun Sun; 0109 Sun.findPosition(&num); 0110 0111 QTime ssTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, false); 0112 QTime srTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, true); 0113 QTime stTime = Sun.transitTime(KStarsDateTime(jd0), geo); 0114 0115 dms ssAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, false); 0116 dms srAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, true); 0117 dms stAlt = Sun.transitAltitude(KStarsDateTime(jd0), geo); 0118 0119 //In most cases, the Sun will rise and set: 0120 if (ssTime.isValid()) 0121 { 0122 ssAzString = ssAz.toDMSString(); 0123 stAltString = stAlt.toDMSString(); 0124 srAzString = srAz.toDMSString(); 0125 0126 ssTimeString = QLocale().toString(ssTime, "hh:mm:ss"); 0127 srTimeString = QLocale().toString(srTime, "hh:mm:ss"); 0128 stTimeString = QLocale().toString(stTime, "hh:mm:ss"); 0129 0130 QTime daylength = lengthOfDay(ssTime, srTime); 0131 //daylengthString = QLocale().toString(daylength); 0132 daylengthString = QLocale().toString(daylength, "hh:mm:ss"); 0133 0134 //...but not always! 0135 } 0136 else if (stAlt.Degrees() > 0.) 0137 { 0138 ssAzString = i18n("Circumpolar"); 0139 stAltString = stAlt.toDMSString(); 0140 srAzString = i18n("Circumpolar"); 0141 0142 ssTimeString = "--:--"; 0143 srTimeString = "--:--"; 0144 stTimeString = QLocale().toString(stTime, "hh:mm:ss"); 0145 daylengthString = "24:00"; 0146 } 0147 else if (stAlt.Degrees() < 0.) 0148 { 0149 ssAzString = i18n("Does not rise"); 0150 stAltString = stAlt.toDMSString(); 0151 srAzString = i18n("Does not set"); 0152 0153 ssTimeString = "--:--"; 0154 srTimeString = "--:--"; 0155 stTimeString = QLocale().toString(stTime, "hh:mm:ss"); 0156 daylengthString = "00:00"; 0157 } 0158 0159 //Moon 0160 KSMoon Moon; 0161 0162 QTime msTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, false); 0163 QTime mrTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, true); 0164 QTime mtTime = Moon.transitTime(KStarsDateTime(jd0), geo); 0165 0166 dms msAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, false); 0167 dms mrAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, true); 0168 dms mtAlt = Moon.transitAltitude(KStarsDateTime(jd0), geo); 0169 0170 //In most cases, the Moon will rise and set: 0171 if (msTime.isValid()) 0172 { 0173 msAzString = msAz.toDMSString(); 0174 mtAltString = mtAlt.toDMSString(); 0175 mrAzString = mrAz.toDMSString(); 0176 0177 msTimeString = QLocale().toString(msTime, "hh:mm:ss"); 0178 mrTimeString = QLocale().toString(mrTime, "hh:mm:ss"); 0179 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss"); 0180 0181 //...but not always! 0182 } 0183 else if (mtAlt.Degrees() > 0.) 0184 { 0185 msAzString = i18n("Circumpolar"); 0186 mtAltString = mtAlt.toDMSString(); 0187 mrAzString = i18n("Circumpolar"); 0188 0189 msTimeString = "--:--"; 0190 mrTimeString = "--:--"; 0191 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss"); 0192 } 0193 else if (mtAlt.Degrees() < 0.) 0194 { 0195 msAzString = i18n("Does not rise"); 0196 mtAltString = mtAlt.toDMSString(); 0197 mrAzString = i18n("Does not rise"); 0198 0199 msTimeString = "--:--"; 0200 mrTimeString = "--:--"; 0201 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss"); 0202 } 0203 0204 //after calling riseSetTime Phase needs to reset, setting it before causes Phase to set nan 0205 Moon.findPosition(&num); 0206 Moon.findPhase(nullptr); 0207 lunarphaseString = Moon.phaseName() + " (" + QString::number(int(100 * Moon.illum())) + "%)"; 0208 0209 //Fix length of Az strings 0210 if (srAz.Degrees() < 100.0) 0211 srAzString = ' ' + srAzString; 0212 if (ssAz.Degrees() < 100.0) 0213 ssAzString = ' ' + ssAzString; 0214 if (mrAz.Degrees() < 100.0) 0215 mrAzString = ' ' + mrAzString; 0216 if (msAz.Degrees() < 100.0) 0217 msAzString = ' ' + msAzString; 0218 } 0219 0220 void modCalcDayLength::slotComputeAlmanac() 0221 { 0222 updateAlmanac(Date->date(), geoPlace); 0223 0224 SunSet->setText(ssTimeString); 0225 SunRise->setText(srTimeString); 0226 SunTransit->setText(stTimeString); 0227 SunSetAz->setText(ssAzString); 0228 SunRiseAz->setText(srAzString); 0229 SunTransitAlt->setText(stAltString); 0230 DayLength->setText(daylengthString); 0231 0232 MoonSet->setText(msTimeString); 0233 MoonRise->setText(mrTimeString); 0234 MoonTransit->setText(mtTimeString); 0235 MoonSetAz->setText(msAzString); 0236 MoonRiseAz->setText(mrAzString); 0237 MoonTransitAlt->setText(mtAltString); 0238 LunarPhase->setText(lunarphaseString); 0239 } 0240 0241 void modCalcDayLength::slotCheckFiles() 0242 { 0243 bool flag = !InputFileBatch->lineEdit()->text().isEmpty() && !OutputFileBatch->lineEdit()->text().isEmpty(); 0244 RunButtonBatch->setEnabled(flag); 0245 } 0246 0247 void modCalcDayLength::slotRunBatch() 0248 { 0249 QString inputFileName = InputFileBatch->url().toLocalFile(); 0250 0251 if (QFile::exists(inputFileName)) 0252 { 0253 QFile f(inputFileName); 0254 if (!f.open(QIODevice::ReadOnly)) 0255 { 0256 QString message = i18n("Could not open file %1.", f.fileName()); 0257 KSNotification::sorry(message, i18n("Could Not Open File")); 0258 return; 0259 } 0260 0261 QTextStream istream(&f); 0262 processLines(istream); 0263 ViewButtonBatch->setEnabled(true); 0264 0265 f.close(); 0266 } 0267 else 0268 { 0269 QString message = i18n("Invalid file: %1", inputFileName); 0270 KSNotification::sorry(message, i18n("Invalid file")); 0271 return; 0272 } 0273 } 0274 0275 void modCalcDayLength::processLines(QTextStream &istream) 0276 { 0277 QFile fOut(OutputFileBatch->url().toLocalFile()); 0278 fOut.open(QIODevice::WriteOnly); 0279 QTextStream ostream(&fOut); 0280 0281 //Write header 0282 ostream << "# " << i18nc("%1 is a location on earth", "Almanac for %1", geoBatch->fullName()) 0283 << QString(" [%1, %2]").arg(geoBatch->lng()->toDMSString(), geoBatch->lat()->toDMSString()) 0284 << "\n# " << i18n("computed by KStars") << Qt::endl 0285 << "# " << "SRise: Sun Rise" << Qt::endl 0286 << "# " << "STran: Sun Transit" << Qt::endl 0287 << "# " << "SSet: Sun Set" << Qt::endl 0288 << "# " << "SRiseAz: Azimuth of Sun Rise" << Qt::endl 0289 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl 0290 << "# " << "SSetAz: Azimuth of Sun Set" << Qt::endl 0291 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl 0292 << "# " << "DayLen: Day Duration in hours" << Qt::endl 0293 << "# " << "MRise: Moon Rise" << Qt::endl 0294 << "# " << "MTran: Moon Transit" << Qt::endl 0295 << "# " << "MSet: Moon Set" << Qt::endl 0296 << "# " << "MRiseAz: Azimuth of Moon Rise" << Qt::endl 0297 << "# " << "MTranAkt: Altitude of Moon Transit" << Qt::endl 0298 << "# " << "MSetAz: Azimuth of Moon Set" << Qt::endl 0299 << "# " << "LunarPhase: Lunar Phase and Illumination Percentage" << Qt::endl 0300 << "# " << Qt::endl 0301 << "# Date,SRise,STran,SSet,SRiseAz,STranAlt,SSetAz,DayLen,MRise,MTran,MSet," 0302 << "MRiseAz,MTranAlt,MSetAz,LunarPhase" << Qt::endl 0303 << "#" << Qt::endl; 0304 0305 QString line; 0306 QDate d; 0307 0308 while (!istream.atEnd()) 0309 { 0310 line = istream.readLine(); 0311 line = line.trimmed(); 0312 0313 //Parse the line as a date, then compute Almanac values 0314 d = QDate::fromString(line, Qt::ISODate); 0315 if (d.isValid()) 0316 { 0317 updateAlmanac(d, geoBatch); 0318 ostream << d.toString(Qt::ISODate) << "," << 0319 srTimeString << "," << 0320 stTimeString << "," << 0321 ssTimeString << "," << 0322 srAzString << "," << 0323 stAltString << "," << 0324 ssAzString << "," << 0325 daylengthString << "," << 0326 mrTimeString << "," << 0327 mtTimeString << "," << 0328 msTimeString << "," << 0329 mrAzString << "," << 0330 mtAltString << "," << 0331 msAzString << "," << 0332 lunarphaseString << Qt::endl; 0333 } 0334 } 0335 } 0336 0337 void modCalcDayLength::slotViewBatch() 0338 { 0339 QFile fOut(OutputFileBatch->url().toLocalFile()); 0340 fOut.open(QIODevice::ReadOnly); 0341 QTextStream istream(&fOut); 0342 QStringList text; 0343 0344 while (!istream.atEnd()) 0345 text.append(istream.readLine()); 0346 0347 fOut.close(); 0348 0349 KMessageBox::informationList(nullptr, i18n("Results of Almanac calculation"), text, OutputFileBatch->url().toLocalFile()); 0350 }