Kstars

main.cpp
1/*
2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "kspaths.h"
8#include "kstars_debug.h"
9#include "kstarsdata.h"
10#include "kstarsdatetime.h"
11#if defined(KSTARS_LITE)
12#include "kstarslite.h"
13#endif
14#include "ksutils.h"
15#include "Options.h"
16#include "simclock.h"
17#include "version.h"
18#if !defined(KSTARS_LITE)
19#include "kstars.h"
20#include "skymap.h"
21#endif
22
23#if !defined(KSTARS_LITE)
24#include <KAboutData>
25#include <KCrash>
26#endif
27
28#include <ki18n_version.h>
29#if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0)
30#include <KLazyLocalizedString>
31#define kde_translate kli18n
32#else
33#include <KLocalizedString>
34#define kde_translate ki18n
35#endif
36
37
38#if defined(Q_OS_MACOS)
39#include <ksnotification.h>
40#endif
41
42#include <QApplication>
43#if !defined(KSTARS_LITE)
44#include <QCommandLineParser>
45#include <QCommandLineOption>
46#endif
47#include <QDebug>
48#include <QPixmap>
49#include <QScreen>
50#include <QtGlobal>
51#include <QTranslator>
52
53#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
54#include <signal.h>
55#endif
56
57#ifndef KSTARS_LITE
58static const auto description = kde_translate("Desktop Planetarium");
59static const auto notice = kde_translate("Some images in KStars are for non-commercial use only. See README.images.");
60#endif
61
62#if defined(Q_OS_ANDROID)
63// __attribute__ is needed because clang-based linking removes the main() symbol from the shared library on Android
64Q_DECL_EXPORT
65#endif
66int main(int argc, char *argv[])
67{
68#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
69 // Ignore SIGPIPE
70 signal(SIGPIPE, SIG_IGN);
71#endif
72
74
75 QApplication app(argc, argv);
76
77#ifdef Q_OS_MACOS
78 //Note, this function will return true on OS X if the data directories are good to go. If not, quit with error code 1!
79 if (!KSUtils::setupMacKStarsIfNeeded())
80 {
81 KSNotification::sorry(i18n("Sorry, without a KStars Data Directory, KStars "
82 "cannot operate. Exiting program now."));
83 return 1;
84 }
85#endif
86 Options::setKStarsFirstRun(false);
87 app.setApplicationVersion(KSTARS_VERSION);
88 /**
89 * enable high dpi support
90 */
91 app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
92
94#if defined(KSTARS_LITE)
95#if defined(__ANDROID__)
97 "kstars", "/data/data/org.kde.kstars.lite/qt-reserved-files/share/kstars/locale");
98#else
99 KLocalizedString::addDomainLocaleDir("kstars", "locale");
100#endif
101#endif
102
103#ifndef KSTARS_LITE
104
105 // Create writable data dir if it does not exist
106 QDir writableDir;
107 writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation));
108 writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::TempLocation));
109
112 QString("%1 %2").arg(KSTARS_VERSION).arg(KSTARS_BUILD_RELEASE);
113 KAboutData aboutData(
114 "kstars", i18n("KStars"), versionString, description.toString(), KAboutLicense::GPL,
115 "2001-" + QString::number(QDate::currentDate().year()) +
116 i18n(" (c), The KStars Team\n\nThe Gaussian Process Guider Algorithm: (c) "
117 "2014-2017 Max Planck Society"),
118 i18nc("Build number followed by copyright notice", "Build: %1\n\n%2\n\n%3",
119 KSTARS_BUILD_TS,
120 KSTARS_BUILD_RELEASE == QLatin1String("Beta") ?
121 "Pre-release beta snapshot. Do not use in production." :
122 "Stable release.",
123 notice.toString()),
124 "https://edu.kde.org/kstars");
125 aboutData.addAuthor(i18n("Jason Harris"), i18n("Original Author"),
126 "jharris@30doradus.org", "http://www.30doradus.org");
127 aboutData.addAuthor(i18n("Jasem Mutlaq"), i18n("Current Maintainer"),
128 "mutlaqja@ikarustech.com", "https://www.indilib.org");
129
130 // Active developers
131 aboutData.addAuthor(i18n("Akarsh Simha"), QString(), "akarsh@kde.org",
132 "http://www.ph.utexas.edu/~asimha");
133 aboutData.addAuthor(i18n("Robert Lancaster"),
134 i18n("FITSViewer & Ekos Improvements. KStars OSX Port"),
135 "rlancaste@gmail.com");
136 aboutData.addAuthor(i18n("Eric Dejouhanet"), QString(), "eric.dejouhanet@gmail.com",
137 i18n("Ekos Scheduler Improvements"));
138 aboutData.addAuthor(i18n("Wolfgang Reissenberger"), QString(),
139 "sterne-jaeger@t-online.de",
140 i18n("Ekos Scheduler & Observatory Improvements"));
141 aboutData.addAuthor(i18n("Hy Murveit"), QString(), "murveit@gmail.com",
142 i18n("FITS, Focus, Guide Improvements"));
143 aboutData.addAuthor(i18n("John Evans"), QString(), "john.e.evans.email@gmail.com",
144 i18n("Focus algorithms"));
145
146 // Inactive developers
147 aboutData.addAuthor(i18n("Csaba Kertesz"), QString(), "csaba.kertesz@gmail.com", "");
148 aboutData.addAuthor("Valentin Boettcher", QString(), "hiro@protagon.space",
149 i18n("Binary Asteroid List, DSO Database & Catalogs"));
150 aboutData.addAuthor(i18n("Artem Fedoskin"), i18n("KStars Lite"),
151 "afedoskin3@gmail.com");
152 aboutData.addAuthor(i18n("James Bowlin"), QString(), "bowlin@mindspring.com");
153 aboutData.addAuthor(i18n("Pablo de Vicente"), QString(), "pvicentea@wanadoo.es");
154 aboutData.addAuthor(i18n("Thomas Kabelmann"), QString(), "tk78@gmx.de");
155 aboutData.addAuthor(i18n("Heiko Evermann"), QString(), "heiko@evermann.de",
156 "https://www.evermann.de");
157 aboutData.addAuthor(i18n("Carsten Niehaus"), QString(), "cniehaus@gmx.de");
158 aboutData.addAuthor(i18n("Mark Hollomon"), QString(), "mhh@mindspring.com");
159 aboutData.addAuthor(i18n("Alexey Khudyakov"), QString(), "alexey.skladnoy@gmail.com");
160 aboutData.addAuthor(i18n("M&eacute;d&eacute;ric Boquien"), QString(),
161 "mboquien@free.fr");
162 aboutData.addAuthor(i18n("J&eacute;r&ocirc;me Sonrier"), QString(),
163 "jsid@emor3j.fr.eu.org");
164 aboutData.addAuthor(i18n("Prakash Mohan"), QString(), "prakash.mohan@kdemail.net");
165 aboutData.addAuthor(i18n("Victor Cărbune"), QString(), "victor.carbune@kdemail.net");
166 aboutData.addAuthor(i18n("Henry de Valence"), QString(), "hdevalence@gmail.com");
167 aboutData.addAuthor(i18n("Samikshan Bairagya"), QString(),
168 "samikshan.bairagya@kdemail.net");
169 aboutData.addAuthor(i18n("Rafał Kułaga"), QString(), "rl.kulaga@gmail.com");
170 aboutData.addAuthor(i18n("Rishab Arora"), QString(), "ra.rishab@gmail.com");
171
172 // Contributors
173 aboutData.addCredit(
174 i18n("Valery Kharitonov"),
175 i18n("Converted labels containing technical terms to links to documentation"));
176 aboutData.addCredit(i18n("Ana-Maria Constantin"),
177 i18n("Technical documentation on Astronomy and KStars"));
178 aboutData.addCredit(i18n("Andrew Stepanenko"),
179 i18n("Guiding code based on lin_guider"));
180 aboutData.addCredit(i18n("Nuno Pinheiro"), i18n("Artwork"));
181 aboutData.addCredit(
182 i18n("Utkarsh Simha"),
183 i18n("Improvements to observation plan execution, star hopper etc."));
184 aboutData.addCredit(i18n("Daniel Holler"),
185 i18n("Extensive testing and suggestions for Ekos/INDI."));
186 aboutData.addCredit(
187 i18n("Stephane Lucas"),
188 i18n("Extensive testing and suggestions for Ekos Scheduler. KStars OSX Port"));
189 aboutData.addCredit(i18n("Yuri Fabirovsky"),
190 i18n("Splash screen for both regular KStars and KStars Lite."));
191 aboutData.addCredit(i18n("Jamie Smith"), i18n("KStars OSX Port."));
192 aboutData.addCredit(i18n("Patrick Molenaar"), i18n("Bahtinov Focus Assistant."));
193 aboutData.addCredit(i18n("Philipp Auersperg-Castell"), i18n("Supernovae daily updates"));
194 aboutData.addCredit(i18n("Tony Schriber"), i18n("Rotator Dialog improvements"));
195 aboutData.addCredit(i18n("Joseph McGee"), i18n("Sub-exposure calculator based on Dr Robin Glover's work"));
196
198 QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("kstars")));
199
200 QCommandLineParser parser;
201 aboutData.setupCommandLine(&parser);
202 parser.setApplicationDescription(aboutData.shortDescription());
203
204 //parser.addHelpOption(INSERT_DESCRIPTION_HERE);
205 parser.addOption(QCommandLineOption("dump", i18n("Dump sky image to file."), "file"));
206 parser.addOption(QCommandLineOption("script", i18n("Script to execute."), "file"));
207 parser.addOption(QCommandLineOption("width", i18n("Width of sky image."), "value"));
208 parser.addOption(QCommandLineOption("height", i18n("Height of sky image."), "value"));
209 parser.addOption(QCommandLineOption("date", i18n("Date and time."), "string"));
210 parser.addOption(QCommandLineOption("paused", i18n("Start with clock paused.")));
211
212 // urls to open
213 parser.addPositionalArgument(QStringLiteral("urls"), i18n("FITS file(s) to open."),
214 QStringLiteral("[urls...]"));
215
216 parser.process(app);
217 aboutData.processCommandLine(&parser);
218
219 if (parser.isSet("dump"))
220 {
221 qCDebug(KSTARS) << "Dumping sky image";
222
223 //parse filename and image format
224 const char *format = "PNG";
225 QString fname = parser.value("dump");
226 QString ext = fname.mid(fname.lastIndexOf(".") + 1);
227 if (ext.toLower() == "png")
228 {
229 format = "PNG";
230 }
231 else if (ext.toLower() == "jpg" || ext.toLower() == "jpeg")
232 {
233 format = "JPG";
234 }
235 else if (ext.toLower() == "gif")
236 {
237 format = "GIF";
238 }
239 else if (ext.toLower() == "pnm")
240 {
241 format = "PNM";
242 }
243 else if (ext.toLower() == "bmp")
244 {
245 format = "BMP";
246 }
247 else
248 {
249 qCWarning(KSTARS) << i18n("Could not parse image format of %1; assuming PNG.",
250 fname);
251 }
252
253 //parse width and height
254 bool ok(false);
255 int w(0), h(0);
256 w = parser.value("width").toInt(&ok);
257 if (ok)
258 h = parser.value("height").toInt(&ok);
259 if (!ok)
260 {
261 qCWarning(KSTARS) << "Unable to parse arguments Width: "
262 << parser.value("width")
263 << " Height: " << parser.value("height");
264 return 1;
265 }
266
267 KStarsData *dat = KStarsData::Create();
268 QObject::connect(dat, SIGNAL(progressText(QString)), dat,
269 SLOT(slotConsoleMessage(QString)));
270 dat->initialize();
271
272 //Set Geographic Location
274
275 //Set color scheme
276 dat->colorScheme()->loadFromConfig();
277
278 //set clock now that we have a location:
279 //Check to see if user provided a date/time string. If not, use current CPU time
280 QString datestring = parser.value("date");
281 KStarsDateTime kdt;
282 if (!datestring.isEmpty())
283 {
284 if (datestring.contains("-")) //assume ISODate format
285 {
286 if (datestring.contains(":")) //also includes time
287 {
288 //kdt = QDateTime::fromString( datestring, QDateTime::ISODate );
290 }
291 else //string probably contains date only
292 {
293 //kdt.setDate( QDate::fromString( datestring, Qt::ISODate ) );
294 kdt.setDate(QDate::fromString(datestring, Qt::ISODate));
295 kdt.setTime(QTime(0, 0, 0));
296 }
297 }
298 else //assume Text format for date string
299 {
300 kdt = dat->geo()->LTtoUT(
302 }
303
304 if (!kdt.isValid())
305 {
306 qCWarning(KSTARS) << i18n(
307 "Supplied date string is invalid: %1. Using CPU date/time instead.",
308 datestring);
309
311 }
312 }
313 else
314 {
316 }
317 dat->clock()->setUTC(kdt);
318
319 SkyMap *map = SkyMap::Create();
320 map->resize(w, h);
321 QPixmap sky(w, h);
322
323 dat->setFullTimeUpdate();
324 dat->updateTime(dat->geo(), map != nullptr);
325
326 SkyPoint dest(Options::focusRA(), Options::focusDec());
327 map->setDestination(dest);
328 map->destination()->EquatorialToHorizontal(dat->lst(), dat->geo()->lat());
329 map->setFocus(map->destination());
330 map->focus()->EquatorialToHorizontal(dat->lst(), dat->geo()->lat());
331
332 //Execute the specified script
333 QString scriptfile = parser.value("script");
334 if (!scriptfile.isEmpty())
335 {
336 if (dat->executeScript(scriptfile, map))
337 {
338 std::cout << i18n("Script executed.").toUtf8().data() << std::endl;
339 }
340 else
341 {
342 qCWarning(KSTARS) << i18n("Could not execute script.");
343 }
344 }
345
346 qApp->processEvents();
347 map->setupProjector();
348 map->exportSkyImage(&sky);
349 qApp->processEvents();
350
351 if (!sky.save(fname, format))
352 qCWarning(KSTARS) << "Unable to save image: " << fname;
353 else
354 qCDebug(KSTARS) << "Saved to file: %1" << fname;
355
356 delete map;
357 //delete dat;
358 return 0;
359 }
360
361 //Try to parse the given date string
362 QString datestring = parser.value("date");
363
364 if (!datestring.isEmpty() && !KStarsDateTime::fromString(datestring).isValid())
365 {
366 qWarning() << i18n("Using CPU date/time instead.");
367 datestring.clear();
368 }
369
370#endif
371
372 // Create writable data dir if it does not exist
373 QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).mkpath(".");
374 QDir(KSPaths::writableLocation(QStandardPaths::AppConfigLocation)).mkpath(".");
375 QDir(KSPaths::writableLocation(QStandardPaths::CacheLocation)).mkpath(".");
376 QDir(KSPaths::writableLocation(QStandardPaths::TempLocation)).mkpath(qAppName());
377
378#ifndef KSTARS_LITE
379 KStars::createInstance(true, !parser.isSet("paused"), datestring);
380
381 // no session.. just start up normally
382 const QStringList urls = parser.positionalArguments();
383
384 // take arguments
385 if (!urls.isEmpty())
386 {
387 foreach (const QString &url, urls)
388 {
390
392 }
393 }
394 QObject::connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
395
396 app.exec();
397#else
399
400 app.exec();
401#endif
402 return 0;
403}
void loadFromConfig()
Read color-scheme data from the Config object.
const CachingDms * lat() const
Definition geolocation.h:70
static void setApplicationData(const KAboutData &aboutData)
static void addDomainLocaleDir(const QByteArray &domain, const QString &path)
static void setApplicationDomain(const QByteArray &domain)
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:232
void setFullTimeUpdate()
The Sky is updated more frequently than the moon, which is updated more frequently than the planets.
void updateTime(GeoLocation *geo, const bool automaticDSTchange=true)
Update the Simulation Clock.
bool initialize()
Initialize KStarsData while running splash screen.
ColorScheme * colorScheme()
Definition kstarsdata.h:180
bool executeScript(const QString &name, SkyMap *map)
Execute a script.
Q_INVOKABLE SimClock * clock()
Definition kstarsdata.h:226
GeoLocation * geo()
Definition kstarsdata.h:238
void setLocationFromOptions()
Set the GeoLocation according to the values stored in the configuration file.
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
static KStarsDateTime fromString(const QString &s)
void setDate(const QDate &d)
Assign the Date according to a QDate object.
static KStarsDateTime currentDateTimeUtc()
void setTime(const QTime &t)
Assign the Time according to a QTime object.
static KStarsLite * createInstance(bool doSplash, bool clockrunning=true, const QString &startDateString=QString())
Create an instance of this class.
static KStars * Instance()
Definition kstars.h:122
Q_SCRIPTABLE Q_NOREPLY void openFITS(const QUrl &imageUrl)
DBUS interface function.
static KStars * createInstance(bool doSplash, bool clockrunning=true, const QString &startDateString=QString())
Create an instance of this class.
Definition kstars.cpp:239
Q_SCRIPTABLE Q_NOREPLY void setUTC(const KStarsDateTime &newtime)
DBUS function to set the time of the SimClock.
Definition simclock.cpp:181
This is the canvas on which the sky is painted.
Definition skymap.h:54
The sky coordinates of a point in the sky.
Definition skypoint.h:45
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
const char * versionString()
KCRASH_EXPORT void initialize()
KGuiItem quit()
bool addOption(const QCommandLineOption &option)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
bool isSet(const QCommandLineOption &option) const const
QStringList positionalArguments() const const
void process(const QCoreApplication &app)
void setApplicationDescription(const QString &description)
QString value(const QCommandLineOption &option) const const
void setAttribute(Qt::ApplicationAttribute attribute, bool on)
QDate currentDate()
QDate fromString(QStringView string, QStringView format, QCalendar cal)
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid() const const
QString currentPath()
bool mkdir(const QString &dirName) const const
bool mkpath(const QString &dirPath) const const
void setWindowIcon(const QIcon &icon)
QIcon fromTheme(const QString &name)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
void clear()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
int toInt(bool *ok, int base) const const
QString toLower() const const
AA_EnableHighDpiScaling
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 28 2025 11:56:02 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.