File indexing completed on 2025-04-20 09:32:20
0001 /* 0002 SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kstarslite.h" 0008 0009 #include "klocalizedcontext.h" 0010 #include "kspaths.h" 0011 #include "ksplanetbase.h" 0012 #include "kstarsdata.h" 0013 #include "ksutils.h" 0014 #include "Options.h" 0015 #include "skymaplite.h" 0016 #include "version.h" 0017 #include "indi/clientmanagerlite.h" 0018 #include "indi/inditelescopelite.h" 0019 #include "kstarslite/imageprovider.h" 0020 #include "kstarslite/dialogs/finddialoglite.h" 0021 #include "kstarslite/dialogs/detaildialoglite.h" 0022 #include "kstarslite/dialogs/locationdialoglite.h" 0023 0024 #include <QGuiApplication> 0025 #include <QQmlContext> 0026 #include <QQuickStyle> 0027 #include <QScreen> 0028 #include <QSurfaceFormat> 0029 0030 KStarsLite *KStarsLite::pinstance = nullptr; 0031 0032 KStarsLite::KStarsLite(bool doSplash, bool startClock, const QString &startDateString) 0033 { 0034 QCoreApplication::setOrganizationName("KStarsLite"); 0035 // Initialize logging settings 0036 /*if (Options::disableLogging()) 0037 KSUtils::Logging::Disable(); 0038 else if (Options::logToFile() && Options::verboseLogFile().isEmpty() == false) 0039 KSUtils::Logging::UseFile(Options::verboseLogFile()); 0040 else 0041 KSUtils::Logging::UseDefault();*/ 0042 0043 // Set pinstance to yourself 0044 // Unlike KStars class we set pinstance at the beginning because SkyMapLite needs access to ClientManagerLite 0045 pinstance = this; 0046 0047 if (doSplash) 0048 showSplash(); 0049 0050 m_KStarsData = KStarsData::Create(); 0051 Q_ASSERT(m_KStarsData); 0052 0053 //INDI Android Client 0054 m_clientManager = new ClientManagerLite(*m_Engine.rootContext()); 0055 m_Engine.rootContext()->setContextProperty("ClientManagerLite", m_clientManager); 0056 0057 //Make instance of KStarsLite and KStarsData available to QML 0058 m_Engine.rootContext()->setContextProperty("KStarsLite", this); 0059 m_Engine.rootContext()->setContextProperty("KStarsData", m_KStarsData); 0060 m_Engine.rootContext()->setContextProperty("Options", Options::self()); 0061 m_Engine.rootContext()->setContextProperty("SimClock", m_KStarsData->clock()); 0062 m_Engine.rootContext()->setContextObject(new KLocalizedContext()); 0063 qmlRegisterUncreatableType<Projector>("KStarsLiteEnums", 1, 0, "Projection", "Provides Projection enum"); 0064 qmlRegisterUncreatableType<KStarsLite>("KStarsLiteEnums", 1, 0, "ObjectsToToggle", 0065 "Enum for togglint the visibility of sky objects"); 0066 0067 //Dialogs 0068 m_findDialogLite = new FindDialogLite; 0069 m_detailDialogLite = new DetailDialogLite; 0070 m_locationDialogLite = new LocationDialogLite; 0071 0072 m_Engine.rootContext()->setContextProperty("FindDialogLite", m_findDialogLite); 0073 m_Engine.rootContext()->setContextProperty("DetailDialogLite", m_detailDialogLite); 0074 m_Engine.rootContext()->setContextProperty("LocationDialogLite", m_locationDialogLite); 0075 0076 //Set Geographic Location from Options 0077 m_KStarsData->setLocationFromOptions(); 0078 0079 //Set style - default is Material 0080 QQuickStyle::setStyle("Material"); 0081 #ifdef Q_OS_ANDROID 0082 QString main = KSPaths::locate(QStandardPaths::AppDataLocation, "kstarslite/qml/main.qml"); 0083 #else 0084 QString main = QString(QML_IMPORT) + QString("/kstarslite/qml/main.qml"); 0085 #endif 0086 0087 /*SkyMapLite has to be loaded before KStarsData is initialized because SkyComponents derived classes 0088 have to add SkyItems to the SkyMapLite*/ 0089 m_SkyMapLite = SkyMapLite::createInstance(); 0090 m_Engine.rootContext()->setContextProperty("SkyMapLite", m_SkyMapLite); 0091 0092 m_Engine.load(QUrl(main)); 0093 Q_ASSERT_X(m_Engine.rootObjects().size(), "loading root object of main.qml", 0094 "QML file was not loaded. Probably syntax error or failed module import."); 0095 0096 m_RootObject = m_Engine.rootObjects()[0]; 0097 m_clientManager->setIndiControlPage(*m_RootObject->findChild<QObject*>("indiControlPanel")); 0098 connect(m_clientManager, &ClientManagerLite::telescopeConnected, 0099 [=](TelescopeLite *telescope) { 0100 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("telescope", true); 0101 connect(telescope, &TelescopeLite::slewRateUpdate, 0102 [=](int index, int count) { 0103 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("slewCount", count); 0104 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("sliderValue", index); 0105 } ); 0106 } ); 0107 connect(m_clientManager, &ClientManagerLite::telescopeDisconnected, 0108 [=]() { 0109 m_RootObject->findChild<QObject*>("bottomMenu")->setProperty("telescope", false); 0110 } ); 0111 0112 // Set the About information 0113 QObject *aboutDialog = m_RootObject->findChild<QObject*>("aboutDialog"); 0114 0115 aboutDialog->setProperty("versionText", i18n("Version: %1", QStringLiteral(KSTARS_VERSION))); 0116 aboutDialog->setProperty("buildText", i18n("Build: %1", QStringLiteral(KSTARS_BUILD_TS))); 0117 aboutDialog->setProperty("teamText", QString("2001-" + QString::number(QDate::currentDate().year()) + i18n("(c), The KStars Team"))); 0118 aboutDialog->setProperty("licenseText", i18n("License: GPLv2")); 0119 0120 QQuickItem *skyMapLiteWrapper = m_RootObject->findChild<QQuickItem *>("skyMapLiteWrapper"); 0121 0122 m_SkyMapLite->initialize(skyMapLiteWrapper); 0123 m_detailDialogLite->initialize(); 0124 0125 m_imgProvider.reset(new ImageProvider); 0126 m_Engine.addImageProvider(QLatin1String("images"), m_imgProvider.get()); 0127 0128 #ifdef Q_OS_ANDROID 0129 QQuickWindow *mainWindow = static_cast<QQuickWindow *>(m_Engine.rootObjects()[0]); 0130 QSurfaceFormat format = mainWindow->format(); 0131 0132 format.setSamples(4); 0133 format.setSwapBehavior(QSurfaceFormat::TripleBuffer); 0134 mainWindow->setFormat(format); 0135 #endif 0136 0137 connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), SLOT(handleStateChange(Qt::ApplicationState))); 0138 0139 //Initialize Time and Date 0140 if (startDateString.isEmpty() == false) 0141 { 0142 KStarsDateTime startDate = KStarsDateTime::fromString(startDateString); 0143 if (startDate.isValid()) 0144 data()->changeDateTime(data()->geo()->LTtoUT(startDate)); 0145 else 0146 data()->changeDateTime(KStarsDateTime::currentDateTimeUtc()); 0147 } 0148 else 0149 data()->changeDateTime(KStarsDateTime::currentDateTimeUtc()); 0150 0151 // Initialize clock. If --paused is not in the command line, look in options 0152 if (startClock) 0153 StartClockRunning = Options::runClock(); 0154 0155 // Setup splash screen 0156 connect(m_KStarsData, SIGNAL(progressText(QString)), m_KStarsData, SLOT(slotConsoleMessage(QString))); 0157 0158 //set up Dark color scheme for application windows 0159 DarkPalette = QPalette(QColor("darkred"), QColor("darkred")); 0160 DarkPalette.setColor(QPalette::Normal, QPalette::Base, QColor("black")); 0161 DarkPalette.setColor(QPalette::Normal, QPalette::Text, QColor(238, 0, 0)); 0162 DarkPalette.setColor(QPalette::Normal, QPalette::Highlight, QColor(238, 0, 0)); 0163 DarkPalette.setColor(QPalette::Normal, QPalette::HighlightedText, QColor("black")); 0164 DarkPalette.setColor(QPalette::Inactive, QPalette::Text, QColor(238, 0, 0)); 0165 DarkPalette.setColor(QPalette::Inactive, QPalette::Base, QColor(30, 10, 10)); 0166 //store original color scheme 0167 OriginalPalette = QGuiApplication::palette(); 0168 if (!m_KStarsData->initialize()) 0169 return; 0170 datainitFinished(); 0171 } 0172 0173 KStarsLite::~KStarsLite() 0174 { 0175 } 0176 0177 QQuickWindow *KStarsLite::getMainWindow() 0178 { 0179 if (!m_Engine.rootContext() || m_Engine.rootObjects().isEmpty()) 0180 return nullptr; 0181 0182 return static_cast<QQuickWindow *>(m_Engine.rootObjects()[0]); 0183 } 0184 0185 void KStarsLite::slotTrack() 0186 { 0187 if (Options::isTracking()) 0188 { 0189 Options::setIsTracking(false); 0190 /*actionCollection()->action("track_object")->setText( i18n( "Engage &Tracking" ) ); 0191 actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-decrypt") ); 0192 0193 KSPlanetBase* planet = dynamic_cast<KSPlanetBase*>( map()->focusObject() ); 0194 if( planet && data()->temporaryTrail ) { 0195 planet->clearTrail(); 0196 data()->temporaryTrail = false; 0197 }*/ // No trail support yet 0198 0199 map()->setClickedObject(nullptr); 0200 map()->setFocusObject(nullptr); //no longer tracking focusObject 0201 map()->setFocusPoint(nullptr); 0202 } 0203 else 0204 { 0205 map()->setClickedPoint(map()->focus()); 0206 map()->setClickedObject(nullptr); 0207 map()->setFocusObject(nullptr); //no longer tracking focusObject 0208 map()->setFocusPoint(map()->clickedPoint()); 0209 Options::setIsTracking(true); 0210 /*actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) ); 0211 actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-encrypt") );*/ 0212 } 0213 0214 map()->forceUpdate(); 0215 } 0216 0217 KStarsLite *KStarsLite::createInstance(bool doSplash, bool clockrunning, const QString &startDateString) 0218 { 0219 delete pinstance; 0220 // pinstance is set directly in constructor. 0221 new KStarsLite(doSplash, clockrunning, startDateString); 0222 Q_ASSERT(pinstance && "pinstance must be non NULL"); 0223 return pinstance; 0224 } 0225 0226 void KStarsLite::fullUpdate() 0227 { 0228 m_KStarsData->setFullTimeUpdate(); 0229 updateTime(); 0230 0231 m_SkyMapLite->forceUpdate(); 0232 } 0233 0234 void KStarsLite::updateTime(const bool automaticDSTchange) 0235 { 0236 // Due to frequently use of this function save data and map pointers for speedup. 0237 // Save options and geo() to a pointer would not speedup because most of time options 0238 // and geo will accessed only one time. 0239 KStarsData *Data = data(); 0240 // dms oldLST( Data->lst()->Degrees() ); 0241 0242 Data->updateTime(Data->geo(), automaticDSTchange); 0243 0244 //We do this outside of kstarsdata just to get the coordinates 0245 //displayed in the infobox to update every second. 0246 // if ( !Options::isTracking() && LST()->Degrees() > oldLST.Degrees() ) { 0247 // int nSec = int( 3600.*( LST()->Hours() - oldLST.Hours() ) ); 0248 // Map->focus()->setRA( Map->focus()->ra().Hours() + double( nSec )/3600. ); 0249 // if ( Options::useAltAz() ) Map->focus()->EquatorialToHorizontal( LST(), geo()->lat() ); 0250 // Map->showFocusCoords(); 0251 // } 0252 0253 //If time is accelerated beyond slewTimescale, then the clock's timer is stopped, 0254 //so that it can be ticked manually after each update, in order to make each time 0255 //step exactly equal to the timeScale setting. 0256 //Wrap the call to manualTick() in a singleshot timer so that it doesn't get called until 0257 //the skymap has been completely updated. 0258 if (Data->clock()->isManualMode() && Data->clock()->isActive()) 0259 { 0260 QTimer::singleShot(0, Data->clock(), SLOT(manualTick())); 0261 } 0262 } 0263 0264 bool KStarsLite::writeConfig() 0265 { 0266 // It seems two config files are saved to android. Must call them both to save all options 0267 // First one save color information, 2nd one rest of config. Bug? 0268 // /data/user/0/org.kde.kstars/files/settings/kstarsrc is used by KSharedConfig::openConfig() 0269 KSharedConfig::openConfig()->sync(); 0270 // /data/data/org.kde.kstars/files/settings/kstarsrc is used by Options::self() 0271 return Options::self()->save(); 0272 0273 //Store current simulation time 0274 //Refer to // FIXME: Used in kstarsdcop.cpp only in kstarsdata.cpp 0275 //data()->StoredDate = data()->lt(); 0276 } 0277 0278 void KStarsLite::handleStateChange(Qt::ApplicationState state) 0279 { 0280 if (state == Qt::ApplicationSuspended) 0281 { 0282 // Delete skymaplite. This required to run destructors and save 0283 // current state in the option. 0284 //delete m_SkyMapLite; 0285 0286 //Store Window geometry in Options object 0287 //Options::setWindowWidth( m_RootObject->width() ); 0288 //Options::setWindowHeight( m_RootObject->height() ); 0289 0290 //explicitly save the colorscheme data to the config file 0291 //data()->colorScheme()->saveToConfig(); 0292 //synch the config file with the Config object 0293 writeConfig(); 0294 } 0295 } 0296 0297 void KStarsLite::loadColorScheme(const QString &name) 0298 { 0299 bool ok = data()->colorScheme()->load(name); 0300 QString filename = data()->colorScheme()->fileName(); 0301 0302 if (ok) 0303 { 0304 //set the application colors for the Night Vision scheme 0305 if (filename == "night.colors") 0306 { 0307 OriginalPalette = QGuiApplication::palette(); 0308 QGuiApplication::setPalette(DarkPalette); 0309 } 0310 else 0311 QGuiApplication::setPalette(OriginalPalette); 0312 0313 Options::setColorSchemeFile(name); 0314 0315 data()->colorScheme()->saveToConfig(); 0316 0317 //writeConfig(); 0318 0319 //Reinitialize stars textures 0320 map()->initStarImages(); 0321 0322 map()->forceUpdate(); 0323 } 0324 } 0325 0326 void KStarsLite::slotSetTime(QDateTime time) 0327 { 0328 KStarsDateTime selectedDateTime(time); 0329 data()->changeDateTime(data()->geo()->LTtoUT(selectedDateTime)); 0330 0331 if (Options::useAltAz()) 0332 { 0333 if (map()->focusObject()) 0334 { 0335 map()->focusObject()->EquatorialToHorizontal(data()->lst(), data()->geo()->lat()); 0336 map()->setFocus(map()->focusObject()); 0337 } 0338 else 0339 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); 0340 } 0341 0342 map()->forceUpdateNow(); 0343 0344 //If focusObject has a Planet Trail, clear it and start anew. 0345 /*KSPlanetBase* planet = dynamic_cast<KSPlanetBase*>( map()->focusObject() ); 0346 if( planet && planet->hasTrail() ) { 0347 planet->clearTrail(); 0348 planet->addToTrail(); 0349 }*/ 0350 } 0351 0352 void KStarsLite::slotToggleTimer() 0353 { 0354 if (data()->clock()->isActive()) 0355 { 0356 data()->clock()->stop(); 0357 updateTime(); 0358 } 0359 else 0360 { 0361 if (fabs(data()->clock()->scale()) > Options::slewTimeScale()) 0362 data()->clock()->setManualMode(true); 0363 data()->clock()->start(); 0364 if (data()->clock()->isManualMode()) 0365 map()->forceUpdate(); 0366 } 0367 0368 // Update clock state in options 0369 Options::setRunClock(data()->clock()->isActive()); 0370 } 0371 0372 void KStarsLite::slotStepForward() 0373 { 0374 if (data()->clock()->isActive()) 0375 data()->clock()->stop(); 0376 data()->clock()->manualTick(true); 0377 map()->forceUpdate(); 0378 } 0379 0380 void KStarsLite::slotStepBackward() 0381 { 0382 if (data()->clock()->isActive()) 0383 data()->clock()->stop(); 0384 data()->clock()->setClockScale(-1.0 * data()->clock()->scale()); //temporarily need negative time step 0385 data()->clock()->manualTick(true); 0386 data()->clock()->setClockScale(-1.0 * data()->clock()->scale()); //reset original sign of time step 0387 map()->forceUpdate(); 0388 } 0389 0390 void KStarsLite::applyConfig(bool doApplyFocus) 0391 { 0392 Q_UNUSED(doApplyFocus); 0393 //color scheme 0394 m_KStarsData->colorScheme()->loadFromConfig(); 0395 QGuiApplication::setPalette(m_KStarsData->colorScheme()->useDarkPalette() ? DarkPalette : OriginalPalette); 0396 } 0397 0398 void KStarsLite::setProjection(uint proj) 0399 { 0400 Options::setProjection(proj); 0401 //We update SkyMapLite 2 times because of the bug in Projector::updateClipPoly() 0402 SkyMapLite::Instance()->forceUpdate(); 0403 } 0404 0405 QColor KStarsLite::getColor(QString schemeColor) 0406 { 0407 return KStarsData::Instance()->colorScheme()->colorNamed(schemeColor); 0408 } 0409 0410 QString KStarsLite::getConfigCScheme() 0411 { 0412 return Options::colorSchemeFile(); 0413 } 0414 0415 void KStarsLite::toggleObjects(ObjectsToToggle toToggle, bool toggle) 0416 { 0417 switch (toToggle) 0418 { 0419 case ObjectsToToggle::Stars: 0420 Options::setShowStars(toggle); 0421 break; 0422 case ObjectsToToggle::DeepSky: 0423 Options::setShowDeepSky(toggle); 0424 break; 0425 case ObjectsToToggle::Planets: 0426 Options::setShowSolarSystem(toggle); 0427 break; 0428 case ObjectsToToggle::CLines: 0429 Options::setShowCLines(toggle); 0430 break; 0431 case ObjectsToToggle::CBounds: 0432 Options::setShowCBounds(toggle); 0433 break; 0434 case ObjectsToToggle::ConstellationArt: 0435 Options::setShowConstellationArt(toggle); 0436 break; 0437 case ObjectsToToggle::MilkyWay: 0438 Options::setShowMilkyWay(toggle); 0439 break; 0440 case ObjectsToToggle::CNames: 0441 Options::setShowCNames(toggle); 0442 break; 0443 case ObjectsToToggle::EquatorialGrid: 0444 Options::setShowEquatorialGrid(toggle); 0445 break; 0446 case ObjectsToToggle::HorizontalGrid: 0447 Options::setShowHorizontalGrid(toggle); 0448 break; 0449 case ObjectsToToggle::Ground: 0450 Options::setShowGround(toggle); 0451 break; 0452 case ObjectsToToggle::Flags: 0453 Options::setShowFlags(toggle); 0454 break; 0455 case ObjectsToToggle::Satellites: 0456 Options::setShowSatellites(toggle); 0457 break; 0458 case ObjectsToToggle::Supernovae: 0459 Options::setShowSupernovae(toggle); 0460 break; 0461 }; 0462 0463 // update time for all objects because they might be not initialized 0464 // it's needed when using horizontal coordinates 0465 data()->setFullTimeUpdate(); 0466 updateTime(); 0467 0468 map()->forceUpdate(); 0469 } 0470 0471 bool KStarsLite::isToggled(ObjectsToToggle toToggle) 0472 { 0473 switch (toToggle) 0474 { 0475 case ObjectsToToggle::Stars: 0476 return Options::showStars(); 0477 case ObjectsToToggle::DeepSky: 0478 return Options::showDeepSky(); 0479 case ObjectsToToggle::Planets: 0480 return Options::showSolarSystem(); 0481 case ObjectsToToggle::CLines: 0482 return Options::showCLines(); 0483 case ObjectsToToggle::CBounds: 0484 return Options::showCBounds(); 0485 case ObjectsToToggle::ConstellationArt: 0486 return Options::showConstellationArt(); 0487 case ObjectsToToggle::MilkyWay: 0488 return Options::showMilkyWay(); 0489 case ObjectsToToggle::CNames: 0490 return Options::showCNames(); 0491 case ObjectsToToggle::EquatorialGrid: 0492 return Options::showEquatorialGrid(); 0493 case ObjectsToToggle::HorizontalGrid: 0494 return Options::showHorizontalGrid(); 0495 case ObjectsToToggle::Ground: 0496 return Options::showGround(); 0497 case ObjectsToToggle::Flags: 0498 return Options::showFlags(); 0499 case ObjectsToToggle::Satellites: 0500 return Options::showSatellites(); 0501 case ObjectsToToggle::Supernovae: 0502 return Options::showSupernovae(); 0503 default: 0504 return false; 0505 }; 0506 } 0507 0508 void KStarsLite::setRunTutorial(bool runTutorial) 0509 { 0510 if (Options::runStartupWizard() != runTutorial) 0511 { 0512 Options::setRunStartupWizard(runTutorial); 0513 emit runTutorialChanged(); 0514 } 0515 } 0516 0517 bool KStarsLite::getRunTutorial() 0518 { 0519 return Options::runStartupWizard(); 0520 }