File indexing completed on 2024-05-19 14:57:52

0001 /*
0002     SPDX-FileCopyrightText: 2002 Jason Harris <kstars@30doradus.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "focusdialog.h"
0008 
0009 #include "dms.h"
0010 #include "kstars.h"
0011 #include "kstarsdata.h"
0012 #include "ksnotification.h"
0013 #include "skymap.h"
0014 #include "skyobjects/skypoint.h"
0015 
0016 #include <KLocalizedString>
0017 #include <QDoubleValidator>
0018 #include <KMessageBox>
0019 #include <QPushButton>
0020 
0021 #include <QVBoxLayout>
0022 
0023 FocusDialogUI::FocusDialogUI(QWidget *parent) : QFrame(parent)
0024 {
0025     setupUi(this);
0026 }
0027 
0028 FocusDialog::FocusDialog() : QDialog(KStars::Instance())
0029 {
0030 #ifdef Q_OS_OSX
0031     setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
0032 #endif
0033     //initialize point to the current focus position
0034     Point = SkyMap::Instance()->focus();
0035 
0036     constexpr const char* J2000EpochString = "2000.0";
0037     fd = new FocusDialogUI(this);
0038 
0039     QVBoxLayout *mainLayout = new QVBoxLayout;
0040     mainLayout->addWidget(fd);
0041     setLayout(mainLayout);
0042 
0043     setWindowTitle(i18nc("@title:window", "Set Coordinates Manually"));
0044 
0045     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0046     mainLayout->addWidget(buttonBox);
0047     connect(buttonBox, SIGNAL(accepted()), this, SLOT(validatePoint()));
0048     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0049 
0050     okB = buttonBox->button(QDialogButtonBox::Ok);
0051     okB->setEnabled(false);
0052 
0053     fd->epochBox->setText(J2000EpochString);
0054     fd->epochBox->setValidator(new QDoubleValidator(fd->epochBox));
0055     fd->raBox->setMinimumWidth(fd->raBox->fontMetrics().boundingRect("00h 00m 00s").width());
0056     fd->azBox->setMinimumWidth(fd->raBox->fontMetrics().boundingRect("00h 00m 00s").width());
0057 
0058     fd->raBox->setUnits(dmsBox::HOURS); //RA box should be HMS-style
0059     fd->raBox->setFocus();        //set input focus
0060 
0061     const SkyPoint *center {nullptr};
0062     if (SkyMap::Instance()->focusObject())
0063         center = dynamic_cast<const SkyPoint*>(SkyMap::Instance()->focusObject());
0064     else
0065         center = const_cast<const SkyPoint*>(SkyMap::Instance()->focusPoint());
0066 
0067     if (center)
0068     {
0069         // Make a copy so as to not affect the existing center point / object
0070         SkyPoint centerCopy {*center};
0071         //center->deprecess(KStarsData::Instance()->updateNum());
0072         centerCopy.catalogueCoord(KStarsData::Instance()->updateNum()->julianDay());
0073         fd->raBox->show(centerCopy.ra());
0074         fd->decBox->show(centerCopy.dec());
0075 
0076         fd->azBox->show(centerCopy.az());
0077         fd->altBox->show(centerCopy.alt());
0078 
0079         checkLineEdits();
0080     }
0081 
0082     connect(fd->raBox, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
0083     connect(fd->decBox, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
0084     connect(fd->azBox, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
0085     connect(fd->altBox, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
0086 
0087     connect(fd->J2000B, &QPushButton::clicked, this, [&]()
0088     {
0089         fd->epochBox->setText(J2000EpochString);
0090     });
0091     connect(fd->JNowB, &QPushButton::clicked, this, [&]()
0092     {
0093         fd->epochBox->setText(QString::number(KStarsData::Instance()->lt().epoch(), 'f', 3));
0094     });
0095 
0096 }
0097 
0098 void FocusDialog::checkLineEdits()
0099 {
0100     bool raOk(false), decOk(false), azOk(false), altOk(false);
0101 
0102     fd->raBox->createDms(&raOk);
0103     fd->decBox->createDms(&decOk);
0104     fd->azBox->createDms(&azOk);
0105     fd->altBox->createDms(&altOk);
0106 
0107     if ((raOk && decOk) || (azOk && altOk))
0108         okB->setEnabled(true);
0109     else
0110         okB->setEnabled(false);
0111 }
0112 
0113 void FocusDialog::validatePoint()
0114 {
0115     bool raOk(false), decOk(false), azOk(false), altOk(false);
0116     QString message;
0117 
0118     if (fd->fdTab->currentWidget() == fd->rdTab)
0119     {
0120         //false means expressed in hours
0121         dms ra(fd->raBox->createDms(&raOk));
0122         dms dec(fd->decBox->createDms(&decOk));
0123 
0124         if (raOk && decOk)
0125         {
0126             //make sure values are in valid range
0127             if (ra.Hours() < 0.0 || ra.Hours() > 24.0)
0128                 message = i18n("The Right Ascension value must be between 0.0 and 24.0.");
0129             if (dec.Degrees() < -90.0 || dec.Degrees() > 90.0)
0130                 message += '\n' + i18n("The Declination value must be between -90.0 and 90.0.");
0131             if (!message.isEmpty())
0132             {
0133                 KSNotification::sorry(message, i18n("Invalid Coordinate Data"));
0134                 return;
0135             }
0136 
0137             bool ok { false };
0138             double epoch0   = KStarsDateTime::stringToEpoch(fd->epochBox->text(), ok);
0139             if (!ok)
0140             {
0141                 KSNotification::sorry(message, i18n("Invalid Epoch format"));
0142                 return;
0143             }
0144             long double jd0 = KStarsDateTime::epochToJd(epoch0);
0145 
0146             // Set RA and Dec to whatever epoch we have been given (may be J2000, JNow or something completely different)
0147             Point->setRA(ra);
0148             Point->setDec(dec);
0149 
0150             if (jd0 != J2000)
0151             {
0152                 // Compute and set the J2000 coordinates of Point
0153                 Point->catalogueCoord(jd0);
0154             }
0155             else
0156             {
0157                 Point->setRA0(ra);
0158                 Point->setDec0(dec);
0159             }
0160 
0161             // N.B. At this point (ra, dec) and (ra0, dec0) are both
0162             // J2000.0 values Therefore, we precess again to get the
0163             // values for the present draw epoch into (ra, dec)
0164             Point->apparentCoord(static_cast<long double>(J2000), KStarsData::Instance()->updateNum()->julianDay());
0165 
0166             Point->EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
0167             // At this point, both (RA, Dec) and (Alt, Az) should correspond to current time
0168             // (RA0, Dec0) will be J2000.0 -- asimha
0169 
0170             QDialog::accept();
0171         }
0172         else
0173         {
0174             QDialog::reject();
0175         }
0176     }
0177     else  // Az/Alt tab is active
0178     {
0179         dms az(fd->azBox->createDms(&azOk));
0180         dms alt(fd->altBox->createDms(&altOk));
0181 
0182         if (azOk && altOk)
0183         {
0184             //make sure values are in valid range
0185             if (az.Degrees() < 0.0 || az.Degrees() > 360.0)
0186                 message = i18n("The Azimuth value must be between 0.0 and 360.0.");
0187             if (alt.Degrees() < -90.0 || alt.Degrees() > 90.0)
0188                 message += '\n' + i18n("The Altitude value must be between -90.0 and 90.0.");
0189             if (!message.isEmpty())
0190             {
0191                 KSNotification::sorry(message, i18n("Invalid Coordinate Data"));
0192                 return;
0193             }
0194 
0195             Point->setAz(az);
0196             Point->setAltRefracted(alt);
0197             Point->HorizontalToEquatorial(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
0198 
0199             UsedAltAz = true;
0200 
0201             QDialog::accept();
0202         }
0203         else
0204         {
0205             QDialog::reject();
0206         }
0207     }
0208 }
0209 
0210 QSize FocusDialog::sizeHint() const
0211 {
0212     return QSize(350, 210);
0213 }
0214 
0215 void FocusDialog::activateAzAltPage() const
0216 {
0217     fd->fdTab->setCurrentWidget(fd->aaTab);
0218     fd->azBox->setFocus();
0219 }