File indexing completed on 2022-12-06 18:58:50

0001 /*
0002     SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "ksnumbers.h"
0008 #include "kspaths.h"
0009 #include "kstars_debug.h"
0010 #include "kstarsdata.h"
0011 #include "ksnotification.h"
0012 #include "kstarsdatetime.h"
0013 #include "catalogsdb.h"
0014 #if defined(KSTARS_LITE)
0015 #include "kstarslite.h"
0016 #endif
0017 #include "ksutils.h"
0018 #include "Options.h"
0019 #include "simclock.h"
0020 #include "version.h"
0021 #if !defined(KSTARS_LITE)
0022 #include "kstars.h"
0023 #include "skymap.h"
0024 #endif
0025 
0026 #if !defined(KSTARS_LITE)
0027 #include <KAboutData>
0028 #include <KCrash>
0029 #endif
0030 #include <KLocalizedString>
0031 
0032 #include <QApplication>
0033 #if !defined(KSTARS_LITE)
0034 #include <QCommandLineParser>
0035 #include <QCommandLineOption>
0036 #endif
0037 #include <QDebug>
0038 #include <QPixmap>
0039 #include <QScreen>
0040 #include <QtGlobal>
0041 #include <QTranslator>
0042 
0043 #if defined(Q_OS_LINUX) || defined(Q_OS_OSX)
0044 #include <signal.h>
0045 #endif
0046 
0047 #ifndef KSTARS_LITE
0048 static const char description[] = I18N_NOOP("Desktop Planetarium");
0049 static const char notice[]      = I18N_NOOP(
0050                                       "Some images in KStars are for non-commercial use only. See README.images.");
0051 #endif
0052 
0053 #if defined(Q_OS_ANDROID)
0054 // __attribute__ is needed because clang-based linking removes the main() symbol from the shared library on Android
0055 Q_DECL_EXPORT
0056 #endif
0057 int main(int argc, char *argv[])
0058 {
0059 #if defined(Q_OS_LINUX) || defined(Q_OS_OSX)
0060     // Ignore SIGPIPE
0061     signal(SIGPIPE, SIG_IGN);
0062 #endif
0063 
0064     QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
0065 
0066     QApplication app(argc, argv);
0067 
0068 #ifdef Q_OS_OSX
0069     //Note, this function will return true on OS X if the data directories are good to go.  If not, quit with error code 1!
0070     if (!KSUtils::setupMacKStarsIfNeeded())
0071     {
0072         KSNotification::sorry(i18n("Sorry, without a KStars Data Directory, KStars "
0073                                    "cannot operate. Exiting program now."));
0074         return 1;
0075     }
0076 #endif
0077     Options::setKStarsFirstRun(false);
0078     app.setApplicationVersion(KSTARS_VERSION);
0079     /**
0080     * enable high dpi support
0081     */
0082     app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0083 
0084     KLocalizedString::setApplicationDomain("kstars");
0085 #if defined(KSTARS_LITE)
0086 #if defined(__ANDROID__)
0087     KLocalizedString::addDomainLocaleDir(
0088         "kstars", "/data/data/org.kde.kstars.lite/qt-reserved-files/share/kstars/locale");
0089 #else
0090     KLocalizedString::addDomainLocaleDir("kstars", "locale");
0091 #endif
0092 #endif
0093 
0094 #ifndef KSTARS_LITE
0095 
0096     // Create writable data dir if it does not exist
0097     QDir writableDir;
0098     writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation));
0099     writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::TempLocation));
0100 
0101     KCrash::initialize();
0102     QString versionString =
0103         QString("%1 %2").arg(KSTARS_VERSION).arg(KSTARS_BUILD_RELEASE);
0104     KAboutData aboutData(
0105         "kstars", i18n("KStars"), versionString, i18n(description), KAboutLicense::GPL,
0106         "2001-" + QString::number(QDate::currentDate().year()) +
0107         i18n(" (c), The KStars Team\n\nThe Gaussian Process Guider Algorithm: (c) "
0108              "2014-2017 Max Planck Society"),
0109         i18nc("Build number followed by copyright notice", "Build: %1\n\n%2\n\n%3",
0110               KSTARS_BUILD_TS,
0111               KSTARS_BUILD_RELEASE == QLatin1String("Beta") ?
0112               "Pre-release beta snapshot. Do not use in production." :
0113               "Stable release.",
0114               i18n(notice)),
0115         "https://edu.kde.org/kstars");
0116     aboutData.addAuthor(i18n("Jason Harris"), i18n("Original Author"),
0117                         "jharris@30doradus.org", "http://www.30doradus.org");
0118     aboutData.addAuthor(i18n("Jasem Mutlaq"), i18n("Current Maintainer"),
0119                         "mutlaqja@ikarustech.com", "https://www.indilib.org");
0120 
0121     // Active developers
0122     aboutData.addAuthor(i18n("Akarsh Simha"), QString(), "akarsh@kde.org",
0123                         "http://www.ph.utexas.edu/~asimha");
0124     aboutData.addAuthor(i18n("Robert Lancaster"),
0125                         i18n("FITSViewer & Ekos Improvements. KStars OSX Port"),
0126                         "rlancaste@gmail.com");
0127     aboutData.addAuthor(i18n("Csaba Kertesz"), QString(), "csaba.kertesz@gmail.com", "");
0128     aboutData.addAuthor(i18n("Eric Dejouhanet"), QString(), "eric.dejouhanet@gmail.com",
0129                         i18n("Ekos Scheduler Improvements"));
0130     aboutData.addAuthor(i18n("Wolfgang Reissenberger"), QString(),
0131                         "sterne-jaeger@t-online.de",
0132                         i18n("Ekos Scheduler & Observatory Improvements"));
0133     aboutData.addAuthor(i18n("Hy Murveit"), QString(), "murveit@gmail.com",
0134                         i18n("FITS, Focus, Guide Improvements"));
0135     aboutData.addAuthor("Valentin Boettcher", QString(), "hiro@protagon.space",
0136                         i18n("Binary Asteroid List, DSO Database & Catalogs"));
0137 
0138     // Inactive developers
0139     aboutData.addAuthor(i18n("Artem Fedoskin"), i18n("KStars Lite"),
0140                         "afedoskin3@gmail.com");
0141     aboutData.addAuthor(i18n("James Bowlin"), QString(), "bowlin@mindspring.com");
0142     aboutData.addAuthor(i18n("Pablo de Vicente"), QString(), "pvicentea@wanadoo.es");
0143     aboutData.addAuthor(i18n("Thomas Kabelmann"), QString(), "tk78@gmx.de");
0144     aboutData.addAuthor(i18n("Heiko Evermann"), QString(), "heiko@evermann.de",
0145                         "https://www.evermann.de");
0146     aboutData.addAuthor(i18n("Carsten Niehaus"), QString(), "cniehaus@gmx.de");
0147     aboutData.addAuthor(i18n("Mark Hollomon"), QString(), "mhh@mindspring.com");
0148     aboutData.addAuthor(i18n("Alexey Khudyakov"), QString(), "alexey.skladnoy@gmail.com");
0149     aboutData.addAuthor(i18n("M&eacute;d&eacute;ric Boquien"), QString(),
0150                         "mboquien@free.fr");
0151     aboutData.addAuthor(i18n("J&eacute;r&ocirc;me Sonrier"), QString(),
0152                         "jsid@emor3j.fr.eu.org");
0153     aboutData.addAuthor(i18n("Prakash Mohan"), QString(), "prakash.mohan@kdemail.net");
0154     aboutData.addAuthor(i18n("Victor Cărbune"), QString(), "victor.carbune@kdemail.net");
0155     aboutData.addAuthor(i18n("Henry de Valence"), QString(), "hdevalence@gmail.com");
0156     aboutData.addAuthor(i18n("Samikshan Bairagya"), QString(),
0157                         "samikshan.bairagya@kdemail.net");
0158     aboutData.addAuthor(i18n("Rafał Kułaga"), QString(), "rl.kulaga@gmail.com");
0159     aboutData.addAuthor(i18n("Rishab Arora"), QString(), "ra.rishab@gmail.com");
0160 
0161     // Contributors
0162     aboutData.addCredit(
0163         i18n("Valery Kharitonov"),
0164         i18n("Converted labels containing technical terms to links to documentation"));
0165     aboutData.addCredit(i18n("Ana-Maria Constantin"),
0166                         i18n("Technical documentation on Astronomy and KStars"));
0167     aboutData.addCredit(i18n("Andrew Stepanenko"),
0168                         i18n("Guiding code based on lin_guider"));
0169     aboutData.addCredit(i18n("Nuno Pinheiro"), i18n("Artwork"));
0170     aboutData.addCredit(
0171         i18n("Utkarsh Simha"),
0172         i18n("Improvements to observation plan execution, star hopper etc."));
0173     aboutData.addCredit(i18n("Daniel Holler"),
0174                         i18n("Extensive testing and suggestions for Ekos/INDI."));
0175     aboutData.addCredit(
0176         i18n("Stephane Lucas"),
0177         i18n("Extensive testing and suggestions for Ekos Scheduler. KStars OSX Port"));
0178     aboutData.addCredit(i18n("Yuri Fabirovsky"),
0179                         i18n("Splash screen for both regular KStars and KStars Lite."));
0180     aboutData.addCredit(i18n("Jamie Smith"), i18n("KStars OSX Port."));
0181     aboutData.addCredit(i18n("Patrick Molenaar"), i18n("Bahtinov Focus Assistant."));
0182 
0183     KAboutData::setApplicationData(aboutData);
0184 
0185     QCommandLineParser parser;
0186     aboutData.setupCommandLine(&parser);
0187     parser.setApplicationDescription(aboutData.shortDescription());
0188 
0189     //parser.addHelpOption(INSERT_DESCRIPTION_HERE);
0190     parser.addOption(QCommandLineOption("dump", i18n("Dump sky image to file."), "file"));
0191     parser.addOption(QCommandLineOption("script", i18n("Script to execute."), "file"));
0192     parser.addOption(QCommandLineOption("width", i18n("Width of sky image."), "value"));
0193     parser.addOption(QCommandLineOption("height", i18n("Height of sky image."), "value"));
0194     parser.addOption(QCommandLineOption("date", i18n("Date and time."), "string"));
0195     parser.addOption(QCommandLineOption("paused", i18n("Start with clock paused.")));
0196 
0197     // urls to open
0198     parser.addPositionalArgument(QStringLiteral("urls"), i18n("FITS file(s) to open."),
0199                                  QStringLiteral("[urls...]"));
0200 
0201     parser.process(app);
0202     aboutData.processCommandLine(&parser);
0203 
0204     if (parser.isSet("dump"))
0205     {
0206         qCDebug(KSTARS) << "Dumping sky image";
0207 
0208         //parse filename and image format
0209         const char *format = "PNG";
0210         QString fname      = parser.value("dump");
0211         QString ext        = fname.mid(fname.lastIndexOf(".") + 1);
0212         if (ext.toLower() == "png")
0213         {
0214             format = "PNG";
0215         }
0216         else if (ext.toLower() == "jpg" || ext.toLower() == "jpeg")
0217         {
0218             format = "JPG";
0219         }
0220         else if (ext.toLower() == "gif")
0221         {
0222             format = "GIF";
0223         }
0224         else if (ext.toLower() == "pnm")
0225         {
0226             format = "PNM";
0227         }
0228         else if (ext.toLower() == "bmp")
0229         {
0230             format = "BMP";
0231         }
0232         else
0233         {
0234             qCWarning(KSTARS) << i18n("Could not parse image format of %1; assuming PNG.",
0235                                       fname);
0236         }
0237 
0238         //parse width and height
0239         bool ok(false);
0240         int w(0), h(0);
0241         w = parser.value("width").toInt(&ok);
0242         if (ok)
0243             h = parser.value("height").toInt(&ok);
0244         if (!ok)
0245         {
0246             qCWarning(KSTARS) << "Unable to parse arguments Width: "
0247                               << parser.value("width")
0248                               << "  Height: " << parser.value("height");
0249             return 1;
0250         }
0251 
0252         KStarsData *dat = KStarsData::Create();
0253         QObject::connect(dat, SIGNAL(progressText(QString)), dat,
0254                          SLOT(slotConsoleMessage(QString)));
0255         dat->initialize();
0256 
0257         //Set Geographic Location
0258         dat->setLocationFromOptions();
0259 
0260         //Set color scheme
0261         dat->colorScheme()->loadFromConfig();
0262 
0263         //set clock now that we have a location:
0264         //Check to see if user provided a date/time string.  If not, use current CPU time
0265         QString datestring = parser.value("date");
0266         KStarsDateTime kdt;
0267         if (!datestring.isEmpty())
0268         {
0269             if (datestring.contains("-")) //assume ISODate format
0270             {
0271                 if (datestring.contains(":")) //also includes time
0272                 {
0273                     //kdt = QDateTime::fromString( datestring, QDateTime::ISODate );
0274                     kdt = KStarsDateTime(QDateTime::fromString(datestring, Qt::ISODate));
0275                 }
0276                 else //string probably contains date only
0277                 {
0278                     //kdt.setDate( QDate::fromString( datestring, Qt::ISODate ) );
0279                     kdt.setDate(QDate::fromString(datestring, Qt::ISODate));
0280                     kdt.setTime(QTime(0, 0, 0));
0281                 }
0282             }
0283             else //assume Text format for date string
0284             {
0285                 kdt = dat->geo()->LTtoUT(
0286                           KStarsDateTime(QDateTime::fromString(datestring, Qt::TextDate)));
0287             }
0288 
0289             if (!kdt.isValid())
0290             {
0291                 qCWarning(KSTARS) << i18n(
0292                                       "Supplied date string is invalid: %1. Using CPU date/time instead.",
0293                                       datestring);
0294 
0295                 kdt = KStarsDateTime::currentDateTimeUtc();
0296             }
0297         }
0298         else
0299         {
0300             kdt = KStarsDateTime::currentDateTimeUtc();
0301         }
0302         dat->clock()->setUTC(kdt);
0303 
0304         SkyMap *map = SkyMap::Create();
0305         map->resize(w, h);
0306         QPixmap sky(w, h);
0307 
0308         dat->setFullTimeUpdate();
0309         dat->updateTime(dat->geo(), map != nullptr);
0310 
0311         SkyPoint dest(Options::focusRA(), Options::focusDec());
0312         map->setDestination(dest);
0313         map->destination()->EquatorialToHorizontal(dat->lst(), dat->geo()->lat());
0314         map->setFocus(map->destination());
0315         map->focus()->EquatorialToHorizontal(dat->lst(), dat->geo()->lat());
0316 
0317         //Execute the specified script
0318         QString scriptfile = parser.value("script");
0319         if (!scriptfile.isEmpty())
0320         {
0321             if (dat->executeScript(scriptfile, map))
0322             {
0323                 std::cout << i18n("Script executed.").toUtf8().data() << std::endl;
0324             }
0325             else
0326             {
0327                 qCWarning(KSTARS) << i18n("Could not execute script.");
0328             }
0329         }
0330 
0331         qApp->processEvents();
0332         map->setupProjector();
0333         map->exportSkyImage(&sky);
0334         qApp->processEvents();
0335 
0336         if (!sky.save(fname, format))
0337             qCWarning(KSTARS) << "Unable to save image: " << fname;
0338         else
0339             qCDebug(KSTARS) << "Saved to file: %1" << fname;
0340 
0341         delete map;
0342         //delete dat;
0343         return 0;
0344     }
0345 
0346     //Try to parse the given date string
0347     QString datestring = parser.value("date");
0348 
0349     if (!datestring.isEmpty() && !KStarsDateTime::fromString(datestring).isValid())
0350     {
0351         qWarning() << i18n("Using CPU date/time instead.");
0352         datestring.clear();
0353     }
0354 
0355 #endif
0356 
0357     // Create writable data dir if it does not exist
0358     QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).mkpath(".");
0359     QDir(KSPaths::writableLocation(QStandardPaths::AppConfigLocation)).mkpath(".");
0360     QDir(KSPaths::writableLocation(QStandardPaths::CacheLocation)).mkpath(".");
0361     QDir(KSPaths::writableLocation(QStandardPaths::TempLocation)).mkpath(qAppName());
0362 
0363 #ifndef KSTARS_LITE
0364     KStars::createInstance(true, !parser.isSet("paused"), datestring);
0365 
0366     // no session.. just start up normally
0367     const QStringList urls = parser.positionalArguments();
0368 
0369     // take arguments
0370     if (!urls.isEmpty())
0371     {
0372         foreach (const QString &url, urls)
0373         {
0374             const QUrl u = QUrl::fromUserInput(url, QDir::currentPath());
0375 
0376             KStars::Instance()->openFITS(u);
0377         }
0378     }
0379     QObject::connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
0380 
0381     app.exec();
0382 #else
0383     KStarsLite::createInstance(true);
0384 
0385     app.exec();
0386 #endif
0387     return 0;
0388 }