File indexing completed on 2024-04-21 03:44:52

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 "modcalcsidtime.h"
0008 
0009 #include "kstarsdata.h"
0010 #include "kstarsdatetime.h"
0011 #include "ksnotification.h"
0012 #include "dialogs/locationdialog.h"
0013 
0014 #include <KLineEdit>
0015 
0016 #include <QTextStream>
0017 
0018 // Qt version calming
0019 #include <qtskipemptyparts.h>
0020 
0021 modCalcSidTime::modCalcSidTime(QWidget *parent) : QFrame(parent)
0022 {
0023     setupUi(this);
0024 
0025     //Preset date and location
0026     showCurrentTimeAndLocation();
0027 
0028     // signals and slots connections
0029     connect(LocationButton, SIGNAL(clicked()), this, SLOT(slotChangeLocation()));
0030     connect(Date, SIGNAL(dateChanged(QDate)), this, SLOT(slotChangeDate()));
0031     connect(LT, SIGNAL(timeChanged(QTime)), this, SLOT(slotConvertST(QTime)));
0032     connect(ST, SIGNAL(timeChanged(QTime)), this, SLOT(slotConvertLT(QTime)));
0033 
0034     connect(LocationCheckBatch, SIGNAL(clicked()), this, SLOT(slotLocationChecked()));
0035     connect(DateCheckBatch, SIGNAL(clicked()), this, SLOT(slotDateChecked()));
0036     connect(LocationCheckBatch, SIGNAL(clicked()), this, SLOT(slotHelpLabel()));
0037     connect(DateCheckBatch, SIGNAL(clicked()), this, SLOT(slotHelpLabel()));
0038     connect(ComputeComboBatch, SIGNAL(currentIndexChanged(int)), this, SLOT(slotHelpLabel()));
0039 
0040     connect(InputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
0041     connect(OutputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
0042     connect(LocationButtonBatch, SIGNAL(clicked()), this, SLOT(slotLocationBatch()));
0043     connect(RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch()));
0044     connect(ViewButtonBatch, SIGNAL(clicked()), this, SLOT(slotViewBatch()));
0045 
0046     RunButtonBatch->setEnabled(false);
0047     ViewButtonBatch->setEnabled(false);
0048 
0049     show();
0050 }
0051 
0052 void modCalcSidTime::showCurrentTimeAndLocation()
0053 {
0054     KStarsData *data = KStarsData::Instance();
0055     LT->setTime(data->lt().time());
0056     Date->setDate(data->lt().date());
0057 
0058     geo = data->geo();
0059     LocationButton->setText(geo->fullName());
0060     geoBatch = data->geo();
0061     LocationButtonBatch->setText(geoBatch->fullName());
0062 
0063     slotConvertST(LT->time());
0064 }
0065 
0066 void modCalcSidTime::slotChangeLocation()
0067 {
0068     QPointer<LocationDialog> ld = new LocationDialog(this);
0069 
0070     if (ld->exec() == QDialog::Accepted)
0071     {
0072         GeoLocation *newGeo = ld->selectedCity();
0073         if (newGeo)
0074         {
0075             geo = newGeo;
0076             LocationButton->setText(geo->fullName());
0077 
0078             //Update the displayed ST
0079             slotConvertST(LT->time());
0080         }
0081     }
0082     delete ld;
0083 }
0084 
0085 void modCalcSidTime::slotChangeDate()
0086 {
0087     slotConvertST(LT->time());
0088 }
0089 
0090 void modCalcSidTime::slotConvertST(const QTime &lt)
0091 {
0092     // blockSignals is used to break signal loop
0093     ST->blockSignals(true);
0094     ST->setTime(computeLTtoST(lt));
0095     ST->blockSignals(false);
0096 }
0097 
0098 void modCalcSidTime::slotConvertLT(const QTime &st)
0099 {
0100     // blockSignals is used to break signal loop
0101     LT->blockSignals(true);
0102     LT->setTime(computeSTtoLT(st));
0103     LT->blockSignals(false);
0104 }
0105 
0106 QTime modCalcSidTime::computeLTtoST(QTime lt)
0107 {
0108     KStarsDateTime utdt = geo->LTtoUT(KStarsDateTime(Date->date(), lt));
0109     dms st              = geo->GSTtoLST(utdt.gst());
0110     return QTime(st.hour(), st.minute(), st.second());
0111 }
0112 
0113 QTime modCalcSidTime::computeSTtoLT(QTime st)
0114 {
0115     KStarsDateTime dt0 = KStarsDateTime(Date->date(), QTime(0, 0, 0));
0116     dms lst;
0117     lst.setH(st.hour(), st.minute(), st.second());
0118     dms gst = geo->LSTtoGST(lst);
0119     return geo->UTtoLT(KStarsDateTime(Date->date(), dt0.GSTtoUT(gst))).time();
0120 }
0121 
0122 //** Batch mode **//
0123 void modCalcSidTime::slotDateChecked()
0124 {
0125     DateBatch->setEnabled(!DateCheckBatch->isChecked());
0126 }
0127 
0128 void modCalcSidTime::slotLocationChecked()
0129 {
0130     LocationButtonBatch->setEnabled(!LocationCheckBatch->isChecked());
0131 
0132     if (LocationCheckBatch->isChecked())
0133     {
0134         QString message = i18n("Location strings consist of the "
0135                                "comma-separated names of the city, province and country.  "
0136                                "If the string contains spaces, enclose it in quotes so it "
0137                                "gets parsed properly.");
0138 
0139         KMessageBox::information(nullptr, message, i18n("Hint for writing location strings"),
0140                                  "DontShowLocationStringMessageBox");
0141     }
0142 }
0143 
0144 void modCalcSidTime::slotHelpLabel()
0145 {
0146     QStringList inList;
0147     if (ComputeComboBatch->currentIndex() == 0)
0148         inList.append(i18n("local time"));
0149     else
0150         inList.append(i18n("sidereal time"));
0151 
0152     if (DateCheckBatch->checkState() == Qt::Checked)
0153         inList.append(i18n("date"));
0154 
0155     if (LocationCheckBatch->checkState() == Qt::Checked)
0156         inList.append(i18n("location"));
0157 
0158     QString inListString = inList[0];
0159     if (inList.size() == 2)
0160         inListString = i18n("%1 and %2", inList[0], inList[1]);
0161     if (inList.size() == 3)
0162         inListString = i18n("%1, %2 and %3", inList[0], inList[1], inList[2]);
0163 
0164     HelpLabel->setText(i18n("Specify %1 in the input file.", inListString));
0165 }
0166 
0167 void modCalcSidTime::slotLocationBatch()
0168 {
0169     QPointer<LocationDialog> ld = new LocationDialog(this);
0170 
0171     if (ld->exec() == QDialog::Accepted)
0172     {
0173         GeoLocation *newGeo = ld->selectedCity();
0174         if (newGeo)
0175         {
0176             geoBatch = newGeo;
0177             LocationButtonBatch->setText(geoBatch->fullName());
0178         }
0179     }
0180     delete ld;
0181 }
0182 
0183 void modCalcSidTime::slotCheckFiles()
0184 {
0185     if (!InputFileBatch->lineEdit()->text().isEmpty() && !OutputFileBatch->lineEdit()->text().isEmpty())
0186     {
0187         RunButtonBatch->setEnabled(true);
0188     }
0189     else
0190     {
0191         RunButtonBatch->setEnabled(false);
0192     }
0193 }
0194 
0195 void modCalcSidTime::slotRunBatch()
0196 {
0197     QString inputFileName = InputFileBatch->url().toLocalFile();
0198 
0199     if (QFile::exists(inputFileName))
0200     {
0201         QFile f(inputFileName);
0202         if (!f.open(QIODevice::ReadOnly))
0203         {
0204             QString message = i18n("Could not open file %1.", f.fileName());
0205             KSNotification::sorry(message, i18n("Could Not Open File"));
0206             inputFileName.clear();
0207             return;
0208         }
0209 
0210         QTextStream istream(&f);
0211         processLines(istream);
0212 
0213         ViewButtonBatch->setEnabled(true);
0214 
0215         f.close();
0216     }
0217     else
0218     {
0219         QString message = i18n("Invalid file: %1", inputFileName);
0220         KSNotification::sorry(message, i18n("Invalid file"));
0221         inputFileName.clear();
0222         return;
0223     }
0224 }
0225 
0226 void modCalcSidTime::processLines(QTextStream &istream)
0227 {
0228     QFile fOut(OutputFileBatch->url().toLocalFile());
0229     fOut.open(QIODevice::WriteOnly);
0230     QTextStream ostream(&fOut);
0231 
0232     QString line;
0233     dms LST;
0234     QTime inTime, outTime;
0235     QDate dt;
0236 
0237     if (!DateCheckBatch->isChecked())
0238         dt = DateBatch->date();
0239 
0240     while (!istream.atEnd())
0241     {
0242         line = istream.readLine();
0243         line = line.trimmed();
0244 
0245         QStringList fields = line.split(' ', Qt::SkipEmptyParts);
0246 
0247         //Find and parse the location string
0248         if (LocationCheckBatch->isChecked())
0249         {
0250             //First, look for a pair of quotation marks, and parse the string between them
0251             QChar q = '\"';
0252             if (line.indexOf(q) == -1)
0253                 q = '\'';
0254             if (line.count(q) == 2)
0255             {
0256                 int iStart             = line.indexOf(q);
0257                 int iEnd               = line.indexOf(q, iStart + 1);
0258                 QString locationString = line.mid(iStart, iEnd - iStart + 1);
0259                 line.remove(locationString);
0260                 fields = line.split(' ', Qt::SkipEmptyParts);
0261                 locationString.remove(q);
0262 
0263                 QStringList locationFields = locationString.split(',', Qt::SkipEmptyParts);
0264                 for (int i = 0; i < locationFields.size(); i++)
0265                     locationFields[i] = locationFields[i].trimmed();
0266 
0267                 if (locationFields.size() == 1)
0268                     locationFields.insert(1, "");
0269                 if (locationFields.size() == 2)
0270                     locationFields.insert(1, "");
0271                 if (locationFields.size() != 3)
0272                 {
0273                     qDebug() << Q_FUNC_INFO << "Error: could not parse location string: " << locationString;
0274                     continue;
0275                 }
0276 
0277                 geoBatch = KStarsData::Instance()->locationNamed(locationFields[0], locationFields[1],
0278                            locationFields[2]);
0279                 if (geoBatch == nullptr)
0280                 {
0281                     qDebug() << Q_FUNC_INFO << "Error: location not found in database: " << locationString;
0282                     continue;
0283                 }
0284             }
0285         }
0286 
0287         if (DateCheckBatch->isChecked())
0288         {
0289             //Parse one of the fields as the date
0290             for (auto &s : fields)
0291             {
0292                 dt = QDate::fromString(s);
0293                 if (dt.isValid())
0294                     break;
0295             }
0296             if (!dt.isValid())
0297             {
0298                 qDebug() << Q_FUNC_INFO << "Error: did not find a valid date string in: " << line;
0299                 continue;
0300             }
0301         }
0302 
0303         //Parse one of the fields as the time
0304         for (auto &s : fields)
0305         {
0306             if (s.contains(':'))
0307             {
0308                 inTime = QTime::fromString(s.length() == 4 ? '0' + s : s);
0309                 if (inTime.isValid())
0310                     break;
0311             }
0312         }
0313         if (!inTime.isValid())
0314         {
0315             qDebug() << Q_FUNC_INFO << "Error: did not find a valid time string in: " << line;
0316             continue;
0317         }
0318 
0319         if (geoBatch != nullptr)
0320         {
0321             if (ComputeComboBatch->currentIndex() == 0)
0322             {
0323                 //inTime is the local time, compute LST
0324                 KStarsDateTime ksdt(dt, inTime);
0325                 ksdt    = geoBatch->LTtoUT(ksdt);
0326                 dms lst = geoBatch->GSTtoLST(ksdt.gst());
0327                 outTime = QTime(lst.hour(), lst.minute(), lst.second());
0328             }
0329             else
0330             {
0331                 //inTime is the sidereal time, compute the local time
0332                 KStarsDateTime ksdt(dt, QTime(0, 0, 0));
0333                 dms lst;
0334                 lst.setH(inTime.hour(), inTime.minute(), inTime.second());
0335                 QTime ut = ksdt.GSTtoUT(geoBatch->LSTtoGST(lst));
0336                 ksdt.setTime(ut);
0337                 ksdt    = geoBatch->UTtoLT(ksdt);
0338                 outTime = ksdt.time();
0339             }
0340 
0341             //Write to output file
0342             ostream << QLocale().toString(dt, QLocale::LongFormat) << "  \"" << geoBatch->fullName() << "\"  "
0343                     << QLocale().toString(inTime) << "  " << QLocale().toString(outTime) << '\n';
0344         }
0345     }
0346 
0347     fOut.close();
0348 }
0349 
0350 void modCalcSidTime::slotViewBatch()
0351 {
0352     QFile fOut(OutputFileBatch->url().toLocalFile());
0353     fOut.open(QIODevice::ReadOnly);
0354     QTextStream istream(&fOut);
0355     QStringList text;
0356 
0357     while (!istream.atEnd())
0358         text.append(istream.readLine());
0359 
0360     fOut.close();
0361 
0362     KMessageBox::informationList(nullptr, i18n("Results of Sidereal time calculation"), text,
0363                                  OutputFileBatch->url().toLocalFile());
0364 }