1 /*
2 SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "kstarslite.h"
8
9 #include "klocalizedcontext.h"
10 #include "kspaths.h"
11 #include "ksplanetbase.h"
12 #include "kstarsdata.h"
13 #include "ksutils.h"
14 #include "Options.h"
15 #include "skymaplite.h"
16 #include "version.h"
17 #include "indi/clientmanagerlite.h"
18 #include "indi/inditelescopelite.h"
19 #include "kstarslite/imageprovider.h"
20 #include "kstarslite/dialogs/finddialoglite.h"
21 #include "kstarslite/dialogs/detaildialoglite.h"
22 #include "kstarslite/dialogs/locationdialoglite.h"
23
24 #include <QGuiApplication>
25 #include <QQmlContext>
26 #include <QQuickStyle>
27 #include <QScreen>
28 #include <QSurfaceFormat>
29
30 KStarsLite *KStarsLite::pinstance = nullptr;
31
KStarsLite(bool doSplash,bool startClock,const QString & startDateString)32 KStarsLite::KStarsLite(bool doSplash, bool startClock, const QString &startDateString)
33 {
34 QCoreApplication::setOrganizationName("KStarsLite");
35 // Initialize logging settings
36 /*if (Options::disableLogging())
37 KSUtils::Logging::Disable();
38 else if (Options::logToFile() && Options::verboseLogFile().isEmpty() == false)
39 KSUtils::Logging::UseFile(Options::verboseLogFile());
40 else
41 KSUtils::Logging::UseDefault();*/
42
43 // Set pinstance to yourself
44 // Unlike KStars class we set pinstance at the beginning because SkyMapLite needs access to ClientManagerLite
45 pinstance = this;
46
47 if (doSplash)
48 showSplash();
49
50 m_KStarsData = KStarsData::Create();
51 Q_ASSERT(m_KStarsData);
52
53 //INDI Android Client
54 m_clientManager = new ClientManagerLite(*m_Engine.rootContext());
55 m_Engine.rootContext()->setContextProperty("ClientManagerLite", m_clientManager);
56
57 //Make instance of KStarsLite and KStarsData available to QML
58 m_Engine.rootContext()->setContextProperty("KStarsLite", this);
59 m_Engine.rootContext()->setContextProperty("KStarsData", m_KStarsData);
60 m_Engine.rootContext()->setContextProperty("Options", Options::self());
61 m_Engine.rootContext()->setContextProperty("SimClock", m_KStarsData->clock());
62 m_Engine.rootContext()->setContextObject(new KLocalizedContext());
63 qmlRegisterUncreatableType<Projector>("KStarsLiteEnums", 1, 0, "Projection", "Provides Projection enum");
64 qmlRegisterUncreatableType<KStarsLite>("KStarsLiteEnums", 1, 0, "ObjectsToToggle",
65 "Enum for togglint the visibility of sky objects");
66
67 //Dialogs
68 m_findDialogLite = new FindDialogLite;
69 m_detailDialogLite = new DetailDialogLite;
70 m_locationDialogLite = new LocationDialogLite;
71
72 m_Engine.rootContext()->setContextProperty("FindDialogLite", m_findDialogLite);
73 m_Engine.rootContext()->setContextProperty("DetailDialogLite", m_detailDialogLite);
74 m_Engine.rootContext()->setContextProperty("LocationDialogLite", m_locationDialogLite);
75
76 //Set Geographic Location from Options
77 m_KStarsData->setLocationFromOptions();
78
79 //Set style - default is Material
80 QQuickStyle::setStyle("Material");
81 #ifdef Q_OS_ANDROID
82 QString main = KSPaths::locate(QStandardPaths::AppDataLocation, "kstarslite/qml/main.qml");
83 #else
84 QString main = QString(QML_IMPORT) + QString("/kstarslite/qml/main.qml");
85 #endif
86
87 /*SkyMapLite has to be loaded before KStarsData is initialized because SkyComponents derived classes
88 have to add SkyItems to the SkyMapLite*/
89 m_SkyMapLite = SkyMapLite::createInstance();
90 m_Engine.rootContext()->setContextProperty("SkyMapLite", m_SkyMapLite);
91
92 m_Engine.load(QUrl(main));
93 Q_ASSERT_X(m_Engine.rootObjects().size(), "loading root object of main.qml",
94 "QML file was not loaded. Probably syntax error or failed module import.");
95
96 m_RootObject = m_Engine.rootObjects()[0];
97 m_clientManager->setIndiControlPage(*m_RootObject->findChild<QObject*>("indiControlPanel"));
98 connect(m_clientManager, &ClientManagerLite::telescopeConnected,
99 [=](TelescopeLite *telescope) {
100 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("telescope", true);
101 connect(telescope, &TelescopeLite::slewRateUpdate,
102 [=](int index, int count) {
103 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("slewCount", count);
104 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("sliderValue", index);
105 } );
106 } );
107 connect(m_clientManager, &ClientManagerLite::telescopeDisconnected,
108 [=]() {
109 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("telescope", false);
110 } );
111
112 // Set the About information
113 QObject *aboutDialog = m_RootObject->findChild<QObject*>("aboutDialog");
114
115 aboutDialog->setProperty("versionText", i18n("Version: %1", QStringLiteral(KSTARS_VERSION)));
116 aboutDialog->setProperty("buildText", i18n("Build: %1", QStringLiteral(KSTARS_BUILD_TS)));
117 aboutDialog->setProperty("teamText", QString("2001-" + QString::number(QDate::currentDate().year()) + i18n("(c), The KStars Team")));
118 aboutDialog->setProperty("licenseText", i18n("License: GPLv2"));
119
120 QQuickItem *skyMapLiteWrapper = m_RootObject->findChild<QQuickItem *>("skyMapLiteWrapper");
121
122 m_SkyMapLite->initialize(skyMapLiteWrapper);
123 m_detailDialogLite->initialize();
124
125 m_imgProvider.reset(new ImageProvider);
126 m_Engine.addImageProvider(QLatin1String("images"), m_imgProvider.get());
127
128 #ifdef Q_OS_ANDROID
129 QQuickWindow *mainWindow = static_cast<QQuickWindow *>(m_Engine.rootObjects()[0]);
130 QSurfaceFormat format = mainWindow->format();
131
132 format.setSamples(4);
133 format.setSwapBehavior(QSurfaceFormat::TripleBuffer);
134 mainWindow->setFormat(format);
135 #endif
136
137 connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), SLOT(handleStateChange(Qt::ApplicationState)));
138
139 //Initialize Time and Date
140 if (startDateString.isEmpty() == false)
141 {
142 KStarsDateTime startDate = KStarsDateTime::fromString(startDateString);
143 if (startDate.isValid())
144 data()->changeDateTime(data()->geo()->LTtoUT(startDate));
145 else
146 data()->changeDateTime(KStarsDateTime::currentDateTimeUtc());
147 }
148 else
149 data()->changeDateTime(KStarsDateTime::currentDateTimeUtc());
150
151 // Initialize clock. If --paused is not in the command line, look in options
152 if (startClock)
153 StartClockRunning = Options::runClock();
154
155 // Setup splash screen
156 connect(m_KStarsData, SIGNAL(progressText(QString)), m_KStarsData, SLOT(slotConsoleMessage(QString)));
157
158 //set up Dark color scheme for application windows
159 DarkPalette = QPalette(QColor("darkred"), QColor("darkred"));
160 DarkPalette.setColor(QPalette::Normal, QPalette::Base, QColor("black"));
161 DarkPalette.setColor(QPalette::Normal, QPalette::Text, QColor(238, 0, 0));
162 DarkPalette.setColor(QPalette::Normal, QPalette::Highlight, QColor(238, 0, 0));
163 DarkPalette.setColor(QPalette::Normal, QPalette::HighlightedText, QColor("black"));
164 DarkPalette.setColor(QPalette::Inactive, QPalette::Text, QColor(238, 0, 0));
165 DarkPalette.setColor(QPalette::Inactive, QPalette::Base, QColor(30, 10, 10));
166 //store original color scheme
167 OriginalPalette = QGuiApplication::palette();
168 if (!m_KStarsData->initialize())
169 return;
170 datainitFinished();
171 }
172
~KStarsLite()173 KStarsLite::~KStarsLite()
174 {
175 }
176
getMainWindow()177 QQuickWindow *KStarsLite::getMainWindow()
178 {
179 if (!m_Engine.rootContext() || m_Engine.rootObjects().isEmpty())
180 return nullptr;
181
182 return static_cast<QQuickWindow *>(m_Engine.rootObjects()[0]);
183 }
184
slotTrack()185 void KStarsLite::slotTrack()
186 {
187 if (Options::isTracking())
188 {
189 Options::setIsTracking(false);
190 /*actionCollection()->action("track_object")->setText( i18n( "Engage &Tracking" ) );
191 actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-decrypt") );
192
193 KSPlanetBase* planet = dynamic_cast<KSPlanetBase*>( map()->focusObject() );
194 if( planet && data()->temporaryTrail ) {
195 planet->clearTrail();
196 data()->temporaryTrail = false;
197 }*/ // No trail support yet
198
199 map()->setClickedObject(nullptr);
200 map()->setFocusObject(nullptr); //no longer tracking focusObject
201 map()->setFocusPoint(nullptr);
202 }
203 else
204 {
205 map()->setClickedPoint(map()->focus());
206 map()->setClickedObject(nullptr);
207 map()->setFocusObject(nullptr); //no longer tracking focusObject
208 map()->setFocusPoint(map()->clickedPoint());
209 Options::setIsTracking(true);
210 /*actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) );
211 actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-encrypt") );*/
212 }
213
214 map()->forceUpdate();
215 }
216
createInstance(bool doSplash,bool clockrunning,const QString & startDateString)217 KStarsLite *KStarsLite::createInstance(bool doSplash, bool clockrunning, const QString &startDateString)
218 {
219 delete pinstance;
220 // pinstance is set directly in constructor.
221 new KStarsLite(doSplash, clockrunning, startDateString);
222 Q_ASSERT(pinstance && "pinstance must be non NULL");
223 return pinstance;
224 }
225
fullUpdate()226 void KStarsLite::fullUpdate()
227 {
228 m_KStarsData->setFullTimeUpdate();
229 updateTime();
230
231 m_SkyMapLite->forceUpdate();
232 }
233
updateTime(const bool automaticDSTchange)234 void KStarsLite::updateTime(const bool automaticDSTchange)
235 {
236 // Due to frequently use of this function save data and map pointers for speedup.
237 // Save options and geo() to a pointer would not speedup because most of time options
238 // and geo will accessed only one time.
239 KStarsData *Data = data();
240 // dms oldLST( Data->lst()->Degrees() );
241
242 Data->updateTime(Data->geo(), automaticDSTchange);
243
244 //We do this outside of kstarsdata just to get the coordinates
245 //displayed in the infobox to update every second.
246 // if ( !Options::isTracking() && LST()->Degrees() > oldLST.Degrees() ) {
247 // int nSec = int( 3600.*( LST()->Hours() - oldLST.Hours() ) );
248 // Map->focus()->setRA( Map->focus()->ra().Hours() + double( nSec )/3600. );
249 // if ( Options::useAltAz() ) Map->focus()->EquatorialToHorizontal( LST(), geo()->lat() );
250 // Map->showFocusCoords();
251 // }
252
253 //If time is accelerated beyond slewTimescale, then the clock's timer is stopped,
254 //so that it can be ticked manually after each update, in order to make each time
255 //step exactly equal to the timeScale setting.
256 //Wrap the call to manualTick() in a singleshot timer so that it doesn't get called until
257 //the skymap has been completely updated.
258 if (Data->clock()->isManualMode() && Data->clock()->isActive())
259 {
260 QTimer::singleShot(0, Data->clock(), SLOT(manualTick()));
261 }
262 }
263
writeConfig()264 bool KStarsLite::writeConfig()
265 {
266 // It seems two config files are saved to android. Must call them both to save all options
267 // First one save color information, 2nd one rest of config. Bug?
268 // /data/user/0/org.kde.kstars/files/settings/kstarsrc is used by KSharedConfig::openConfig()
269 KSharedConfig::openConfig()->sync();
270 // /data/data/org.kde.kstars/files/settings/kstarsrc is used by Options::self()
271 return Options::self()->save();
272
273 //Store current simulation time
274 //Refer to // FIXME: Used in kstarsdcop.cpp only in kstarsdata.cpp
275 //data()->StoredDate = data()->lt();
276 }
277
handleStateChange(Qt::ApplicationState state)278 void KStarsLite::handleStateChange(Qt::ApplicationState state)
279 {
280 if (state == Qt::ApplicationSuspended)
281 {
282 // Delete skymaplite. This required to run destructors and save
283 // current state in the option.
284 //delete m_SkyMapLite;
285
286 //Store Window geometry in Options object
287 //Options::setWindowWidth( m_RootObject->width() );
288 //Options::setWindowHeight( m_RootObject->height() );
289
290 //explicitly save the colorscheme data to the config file
291 //data()->colorScheme()->saveToConfig();
292 //synch the config file with the Config object
293 writeConfig();
294 }
295 }
296
loadColorScheme(const QString & name)297 void KStarsLite::loadColorScheme(const QString &name)
298 {
299 bool ok = data()->colorScheme()->load(name);
300 QString filename = data()->colorScheme()->fileName();
301
302 if (ok)
303 {
304 //set the application colors for the Night Vision scheme
305 if (filename == "night.colors")
306 {
307 OriginalPalette = QGuiApplication::palette();
308 QGuiApplication::setPalette(DarkPalette);
309 }
310 else
311 QGuiApplication::setPalette(OriginalPalette);
312
313 Options::setColorSchemeFile(name);
314
315 data()->colorScheme()->saveToConfig();
316
317 //writeConfig();
318
319 //Reinitialize stars textures
320 map()->initStarImages();
321
322 map()->forceUpdate();
323 }
324 }
325
slotSetTime(QDateTime time)326 void KStarsLite::slotSetTime(QDateTime time)
327 {
328 KStarsDateTime selectedDateTime(time);
329 data()->changeDateTime(data()->geo()->LTtoUT(selectedDateTime));
330
331 if (Options::useAltAz())
332 {
333 if (map()->focusObject())
334 {
335 map()->focusObject()->EquatorialToHorizontal(data()->lst(), data()->geo()->lat());
336 map()->setFocus(map()->focusObject());
337 }
338 else
339 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
340 }
341
342 map()->forceUpdateNow();
343
344 //If focusObject has a Planet Trail, clear it and start anew.
345 /*KSPlanetBase* planet = dynamic_cast<KSPlanetBase*>( map()->focusObject() );
346 if( planet && planet->hasTrail() ) {
347 planet->clearTrail();
348 planet->addToTrail();
349 }*/
350 }
351
slotToggleTimer()352 void KStarsLite::slotToggleTimer()
353 {
354 if (data()->clock()->isActive())
355 {
356 data()->clock()->stop();
357 updateTime();
358 }
359 else
360 {
361 if (fabs(data()->clock()->scale()) > Options::slewTimeScale())
362 data()->clock()->setManualMode(true);
363 data()->clock()->start();
364 if (data()->clock()->isManualMode())
365 map()->forceUpdate();
366 }
367
368 // Update clock state in options
369 Options::setRunClock(data()->clock()->isActive());
370 }
371
slotStepForward()372 void KStarsLite::slotStepForward()
373 {
374 if (data()->clock()->isActive())
375 data()->clock()->stop();
376 data()->clock()->manualTick(true);
377 map()->forceUpdate();
378 }
379
slotStepBackward()380 void KStarsLite::slotStepBackward()
381 {
382 if (data()->clock()->isActive())
383 data()->clock()->stop();
384 data()->clock()->setClockScale(-1.0 * data()->clock()->scale()); //temporarily need negative time step
385 data()->clock()->manualTick(true);
386 data()->clock()->setClockScale(-1.0 * data()->clock()->scale()); //reset original sign of time step
387 map()->forceUpdate();
388 }
389
applyConfig(bool doApplyFocus)390 void KStarsLite::applyConfig(bool doApplyFocus)
391 {
392 Q_UNUSED(doApplyFocus);
393 //color scheme
394 m_KStarsData->colorScheme()->loadFromConfig();
395 QGuiApplication::setPalette(m_KStarsData->colorScheme()->useDarkPalette() ? DarkPalette : OriginalPalette);
396 }
397
setProjection(uint proj)398 void KStarsLite::setProjection(uint proj)
399 {
400 Options::setProjection(proj);
401 //We update SkyMapLite 2 times because of the bug in Projector::updateClipPoly()
402 SkyMapLite::Instance()->forceUpdate();
403 }
404
getColor(QString schemeColor)405 QColor KStarsLite::getColor(QString schemeColor)
406 {
407 return KStarsData::Instance()->colorScheme()->colorNamed(schemeColor);
408 }
409
getConfigCScheme()410 QString KStarsLite::getConfigCScheme()
411 {
412 return Options::colorSchemeFile();
413 }
414
toggleObjects(ObjectsToToggle toToggle,bool toggle)415 void KStarsLite::toggleObjects(ObjectsToToggle toToggle, bool toggle)
416 {
417 switch (toToggle)
418 {
419 case ObjectsToToggle::Stars:
420 Options::setShowStars(toggle);
421 break;
422 case ObjectsToToggle::DeepSky:
423 Options::setShowDeepSky(toggle);
424 break;
425 case ObjectsToToggle::Planets:
426 Options::setShowSolarSystem(toggle);
427 break;
428 case ObjectsToToggle::CLines:
429 Options::setShowCLines(toggle);
430 break;
431 case ObjectsToToggle::CBounds:
432 Options::setShowCBounds(toggle);
433 break;
434 case ObjectsToToggle::ConstellationArt:
435 Options::setShowConstellationArt(toggle);
436 break;
437 case ObjectsToToggle::MilkyWay:
438 Options::setShowMilkyWay(toggle);
439 break;
440 case ObjectsToToggle::CNames:
441 Options::setShowCNames(toggle);
442 break;
443 case ObjectsToToggle::EquatorialGrid:
444 Options::setShowEquatorialGrid(toggle);
445 break;
446 case ObjectsToToggle::HorizontalGrid:
447 Options::setShowHorizontalGrid(toggle);
448 break;
449 case ObjectsToToggle::Ground:
450 Options::setShowGround(toggle);
451 break;
452 case ObjectsToToggle::Flags:
453 Options::setShowFlags(toggle);
454 break;
455 case ObjectsToToggle::Satellites:
456 Options::setShowSatellites(toggle);
457 break;
458 case ObjectsToToggle::Supernovae:
459 Options::setShowSupernovae(toggle);
460 break;
461 };
462
463 // update time for all objects because they might be not initialized
464 // it's needed when using horizontal coordinates
465 data()->setFullTimeUpdate();
466 updateTime();
467
468 map()->forceUpdate();
469 }
470
isToggled(ObjectsToToggle toToggle)471 bool KStarsLite::isToggled(ObjectsToToggle toToggle)
472 {
473 switch (toToggle)
474 {
475 case ObjectsToToggle::Stars:
476 return Options::showStars();
477 case ObjectsToToggle::DeepSky:
478 return Options::showDeepSky();
479 case ObjectsToToggle::Planets:
480 return Options::showSolarSystem();
481 case ObjectsToToggle::CLines:
482 return Options::showCLines();
483 case ObjectsToToggle::CBounds:
484 return Options::showCBounds();
485 case ObjectsToToggle::ConstellationArt:
486 return Options::showConstellationArt();
487 case ObjectsToToggle::MilkyWay:
488 return Options::showMilkyWay();
489 case ObjectsToToggle::CNames:
490 return Options::showCNames();
491 case ObjectsToToggle::EquatorialGrid:
492 return Options::showEquatorialGrid();
493 case ObjectsToToggle::HorizontalGrid:
494 return Options::showHorizontalGrid();
495 case ObjectsToToggle::Ground:
496 return Options::showGround();
497 case ObjectsToToggle::Flags:
498 return Options::showFlags();
499 case ObjectsToToggle::Satellites:
500 return Options::showSatellites();
501 case ObjectsToToggle::Supernovae:
502 return Options::showSupernovae();
503 default:
504 return false;
505 };
506 }
507
setRunTutorial(bool runTutorial)508 void KStarsLite::setRunTutorial(bool runTutorial)
509 {
510 if (Options::runStartupWizard() != runTutorial)
511 {
512 Options::setRunStartupWizard(runTutorial);
513 emit runTutorialChanged();
514 }
515 }
516
getRunTutorial()517 bool KStarsLite::getRunTutorial()
518 {
519 return Options::runStartupWizard();
520 }
521