File indexing completed on 2024-04-14 14:11:35

0001 /*
0002     SPDX-FileCopyrightText: 2001-2005 Pablo de Vicente <p.devicente@wanadoo.es>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "astrocalc.h"
0008 
0009 #include "modcalcjd.h"
0010 #include "modcalcgeodcoord.h"
0011 #include "modcalcgalcoord.h"
0012 #include "modcalcsidtime.h"
0013 #include "modcalcapcoord.h"
0014 #include "modcalcdaylength.h"
0015 #include "modcalcaltaz.h"
0016 #include "modcalcsimple.h"
0017 #include "modcalcplanets.h"
0018 #include "modcalceclipticcoords.h"
0019 #include "modcalcangdist.h"
0020 #include "modcalcvizequinox.h"
0021 #include "modcalcvlsr.h"
0022 #include "conjunctions.h"
0023 #include "eclipsetool.h"
0024 
0025 #include <QDialogButtonBox>
0026 #include <QSplitter>
0027 #include <QStackedWidget>
0028 #include <QTextEdit>
0029 #include <QTreeWidget>
0030 #include <QTreeWidgetItem>
0031 
0032 AstroCalc::AstroCalc(QWidget *parent) : QDialog(parent)
0033 {
0034 #ifdef Q_OS_OSX
0035     setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
0036 #endif
0037 
0038     // List of messages. Maybe there is better place for it...
0039     QString message      = i18n("<QT>"
0040                            "<H2>KStars Astrocalculator</H2>"
0041                            "<P>"
0042                            "The KStars Astrocalculator contains several <B>modules</b> "
0043                            "which perform a variety of astronomy-related calculations.  "
0044                            "The modules are organized into several categories: "
0045                            "<UL>"
0046                            "<LI><B>Time calculators: </B>"
0047                            "Convert between time systems, and predict the timing of celestial events</LI>"
0048                            "<LI><B>Coordinate converters: </B>"
0049                            "Convert between various coordinate systems</LI>"
0050                            "<LI><B>Solar system: </B>"
0051                            "Predict the position of any planet, from a given location on Earth at a given time</LI>"
0052                            "</UL>"
0053                            "</QT>");
0054     QString messageTime  = i18n("<QT>"
0055                                "Section which includes algorithms for computing time ephemeris"
0056                                "<UL><LI>"
0057                                "<B>Julian Day:</B> Julian Day/Calendar conversion"
0058                                "</LI><LI>"
0059                                "<B>Sidereal Time:</B> Sidereal/Universal time conversion"
0060                                "</LI><LI>"
0061                                "<B>Almanac:</B> Rise/Set/Transit timing and position data "
0062                                "for the Sun and Moon"
0063                                "</LI><LI>"
0064                                "<B>Equinoxes & Solstices:</B> Equinoxes, Solstices and duration of the "
0065                                "seasons"
0066                                "</LI></UL>"
0067                                "</QT>");
0068     QString messageCoord = i18n("<QT>"
0069                                 "Section with algorithms for the conversion of "
0070                                 "different astronomical systems of coordinates"
0071                                 "<UL><LI>"
0072                                 "<B>Galactic:</B> Galactic/Equatorial coordinates conversion"
0073                                 "</LI><LI>"
0074                                 "<B>Apparent:</B> Computation of current equatorial coordinates"
0075                                 " from a given epoch"
0076                                 "</LI><LI>"
0077                                 "<B>Ecliptic:</B> Ecliptic/Equatorial coordinates conversion"
0078                                 "</LI><LI>"
0079                                 "<B>Horizontal:</B> Computation of azimuth and elevation for a "
0080                                 "given source, time, and location on the Earth"
0081                                 "</LI><LI>"
0082                                 "<B>Simple:</B> Conversion between angles in hrs and degrees."
0083                                 "</LI><LI>"
0084                                 "<B>Angular Distance:</B> Computation of angular distance between "
0085                                 "two objects whose positions are given in equatorial coordinates"
0086                                 "</LI><LI>"
0087                                 "<B>Geodetic Coords:</B> Geodetic/XYZ coordinate conversion"
0088                                 "</LI><LI>"
0089                                 "<B>LSR Velocity:</B> Computation of the heliocentric, geocentric "
0090                                 "and topocentric radial velocity of a source from its LSR velocity"
0091                                 "</LI></UL>"
0092                                 "</QT>");
0093     QString messageSolar = i18n("<QT>"
0094                                 "Section with algorithms regarding information "
0095                                 "on solar system bodies coordinates and times"
0096                                 "<UL><LI>"
0097                                 "<B>Planets Coords:</B> Coordinates for the planets, moon and sun "
0098                                 "at a given time and from a given position on Earth "
0099                                 "</LI></UL>"
0100                                 "</QT>");
0101 
0102     QSplitter *split = new QSplitter(this);
0103 
0104     QVBoxLayout *mainLayout = new QVBoxLayout;
0105     mainLayout->addWidget(split);
0106     setLayout(mainLayout);
0107 
0108     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
0109     mainLayout->addWidget(buttonBox);
0110     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0111 
0112     setWindowTitle(i18nc("@title:window", "Calculator"));
0113 
0114     // Create navigation panel
0115     navigationPanel = new QTreeWidget(split);
0116     navigationPanel->setColumnCount(1);
0117     navigationPanel->setHeaderLabels(QStringList(i18n("Calculator modules")));
0118     navigationPanel->setSortingEnabled(false);
0119     //FIXME: Would be better to make the navigationPanel fit its contents,
0120     //but I wasn't able to make it work
0121     navigationPanel->setMinimumWidth(200);
0122 
0123     acStack = new QStackedWidget(split);
0124 
0125     splashScreen = new QTextEdit(message, acStack);
0126     splashScreen->setReadOnly(true);
0127     //FIXME: Minimum size is set to resize calculator to correct size
0128     //when no modules is loaded. This is simply biggest size of
0129     //calculator modules. I think it should be set in more cleverly.
0130     splashScreen->setMinimumSize(640, 550);
0131     acStack->addWidget(splashScreen);
0132 
0133     // Load icons
0134     // JM 2016-10-02: Those are missing, disabling the icons for now
0135     /*
0136     QIcon jdIcon = QIcon ("jd.png");
0137     QIcon geodIcon = QIcon ("geodetic.png");
0138     QIcon solarIcon = QIcon ("geodetic.png");
0139     // QIcon sunsetIcon = QIcon ("sunset.png"); // Its usage is commented out.
0140     QIcon timeIcon = QIcon ("sunclock.png");*/
0141 
0142     /* Populate the tree widget and widget stack */
0143     // Time-related entries
0144     QTreeWidgetItem *timeItem = addTreeTopItem(navigationPanel, i18n("Time Calculators"), messageTime);
0145     //timeItem->setIcon(0,timeIcon);
0146 
0147     //addTreeItem<modCalcJD>       (timeItem, i18n("Julian Day"))->setIcon(0,jdIcon);
0148     addTreeItem<modCalcJD>(timeItem, i18n("Julian Day"));
0149     addTreeItem<modCalcSidTime>(timeItem, i18n("Sidereal Time"));
0150     addTreeItem<modCalcDayLength>(timeItem, i18n("Almanac"));
0151     addTreeItem<modCalcEquinox>(timeItem, i18n("Equinoxes & Solstices"));
0152     //  dayItem->setIcon(0,sunsetIcon);
0153 
0154     // Coordinate-related entries
0155     QTreeWidgetItem *coordItem = addTreeTopItem(navigationPanel, i18n("Coordinate Converters"), messageCoord);
0156     addTreeItem<modCalcGalCoord>(coordItem, i18n("Equatorial/Galactic"));
0157     addTreeItem<modCalcApCoord>(coordItem, i18n("Apparent Coordinates"));
0158     addTreeItem<modCalcAltAz>(coordItem, i18n("Horizontal Coordinates"));
0159     addTreeItem<modCalcSimple>(coordItem, i18n("Simple Coordinates"));
0160     addTreeItem<modCalcEclCoords>(coordItem, i18n("Ecliptic Coordinates"));
0161     addTreeItem<modCalcAngDist>(coordItem, i18n("Angular Distance"));
0162     addTreeItem<modCalcGeodCoord>(coordItem, i18n("Geodetic Coordinates"));
0163     addTreeItem<modCalcVlsr>(coordItem, i18n("LSR Velocity"));
0164 
0165     // Solar System related entries
0166     QTreeWidgetItem *solarItem = addTreeTopItem(navigationPanel, i18n("Solar System"), messageSolar);
0167     //solarItem->setIcon(0,solarIcon);
0168     addTreeItem<modCalcPlanets>(solarItem, i18n("Planets Coordinates"));
0169     addTreeItem<ConjunctionsTool>(solarItem, i18n("Conjunctions"));
0170     addTreeItem<EclipseTool>(solarItem, i18n("Eclipses"));
0171 
0172     acStack->setCurrentWidget(splashScreen);
0173     connect(navigationPanel, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this,
0174             SLOT(slotItemSelection(QTreeWidgetItem*)));
0175 }
0176 
0177 template <typename T>
0178 QWidget *AstroCalc::addToStack()
0179 {
0180     T *t = new T(acStack);
0181     acStack->addWidget(t);
0182     return t;
0183 }
0184 
0185 template <typename T>
0186 QTreeWidgetItem *AstroCalc::addTreeItem(QTreeWidgetItem *parent, const QString &title)
0187 {
0188     QTreeWidgetItem *item = new QTreeWidgetItem(parent, QStringList(title));
0189     dispatchTable.insert(item, WidgetThunk(this, &AstroCalc::addToStack<T>));
0190     return item;
0191 }
0192 
0193 QTreeWidgetItem *AstroCalc::addTreeTopItem(QTreeWidget *parent, const QString &title, const QString &html)
0194 {
0195     QTreeWidgetItem *item = new QTreeWidgetItem(parent, QStringList(title));
0196 
0197     htmlTable.insert(item, html);
0198     return item;
0199 }
0200 
0201 void AstroCalc::slotItemSelection(QTreeWidgetItem *item)
0202 {
0203     if (item == nullptr)
0204         return;
0205     // Lookup in HTML table
0206     QMap<QTreeWidgetItem *, QString>::iterator iterHTML = htmlTable.find(item);
0207     if (iterHTML != htmlTable.end())
0208     {
0209         splashScreen->setHtml(*iterHTML);
0210         acStack->setCurrentWidget(splashScreen);
0211         return;
0212     }
0213     // Lookup in frames table
0214     QMap<QTreeWidgetItem *, WidgetThunk>::iterator iter = dispatchTable.find(item);
0215     if (iter != dispatchTable.end())
0216     {
0217         acStack->setCurrentWidget(iter->eval());
0218     }
0219 }
0220 
0221 QSize AstroCalc::sizeHint() const
0222 {
0223     return QSize(640, 430);
0224 }
0225 
0226 QWidget *AstroCalc::WidgetThunk::eval()
0227 {
0228     if (widget == nullptr)
0229     {
0230         // This is pointer to member function call.
0231         widget = (calc->*func)();
0232     }
0233     return widget;
0234 }