File indexing completed on 2024-04-14 03:43:33

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 }