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

0001 /*
0002     SPDX-FileCopyrightText: 2001 Heiko Evermann <heiko@evermann.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "colorscheme.h"
0010 #include "geolocation.h"
0011 #include "ksnumbers.h"
0012 #include "kstarsdatetime.h"
0013 #include "ksuserdb.h"
0014 #include "simclock.h"
0015 #include "skyobjectuserdata.h"
0016 #include <qobject.h>
0017 #ifndef KSTARS_LITE
0018 #include "oal/oal.h"
0019 #include "oal/log.h"
0020 #include "polyfills/qstring_hash.h"
0021 #endif
0022 
0023 #include <QList>
0024 #include <QMap>
0025 #include <QKeySequence>
0026 
0027 #include <iostream>
0028 #include <memory>
0029 #include <unordered_map>
0030 
0031 #define MINZOOM     250.
0032 #define MAXZOOM     5000000.
0033 #define DEFAULTZOOM 2000.
0034 #define DZOOM       1.189207115 // 2^(1/4)
0035 #define AU_KM       1.49605e8   //km in one AU
0036 
0037 class QFile;
0038 
0039 class Execute;
0040 class FOV;
0041 class ImageExporter;
0042 class SkyMap;
0043 class SkyMapComposite;
0044 class SkyObject;
0045 class ObservingList;
0046 class TimeZoneRule;
0047 
0048 #ifdef KSTARS_LITE
0049 //Will go away when details window will be implemented in KStars Lite
0050 struct ADVTreeData
0051 {
0052     QString Name;
0053     QString Link;
0054     int Type;
0055 };
0056 #else
0057 struct ADVTreeData;
0058 #endif
0059 
0060 /**
0061  * @class KStarsData
0062  * KStarsData is the backbone of KStars.  It contains all the data used by KStars,
0063  * including the SkyMapComposite that contains all items in the skymap
0064  * (stars, deep-sky objects, planets, constellations, etc).  Other kinds of data
0065  * are stored here as well: the geographic locations, the timezone rules, etc.
0066  *
0067  * @author Heiko Evermann
0068  * @version 1.0
0069  */
0070 class KStarsData : public QObject
0071 {
0072         Q_OBJECT
0073 
0074     protected:
0075         /** Constructor. */
0076         KStarsData();
0077 
0078     public:
0079         // FIXME: It uses temporary trail. There must be way to
0080         //        this better. And resumeKey in DBUS code
0081         friend class KStars;
0082         // FIXME: it uses temporary trail and resumeKey
0083         friend class SkyMap;
0084         // FIXME: uses geoList and changes it.
0085         friend class LocationDialog;
0086         friend class LocationDialogLite;
0087 
0088         static KStarsData *Create();
0089 
0090         static inline KStarsData *Instance()
0091         {
0092             return pinstance;
0093         }
0094 
0095         /**
0096          * Initialize KStarsData while running splash screen.
0097          * @return true on success.
0098          */
0099         bool initialize();
0100 
0101         /** Destructor.  Delete data objects. */
0102         ~KStarsData() override;
0103 
0104         /**
0105          * Set the NextDSTChange member.
0106          *  Need this accessor because I could not make KStars::privatedata a friend
0107          *  class for some reason...:/
0108          */
0109         void setNextDSTChange(const KStarsDateTime &dt)
0110         {
0111             NextDSTChange = dt;
0112         }
0113 
0114         /**
0115          * Returns true if time is running forward else false. Used by KStars to prevent
0116          *  double calculations of daylight saving change time.
0117          */
0118         bool isTimeRunningForward() const
0119         {
0120             return TimeRunsForward;
0121         }
0122 
0123         /** @return pointer to the localization (KLocale) object */
0124         //KLocale *getLocale() { return locale; }
0125 
0126         /**
0127          * @short Find object by name.
0128          * @param name Object name to find
0129          * @return pointer to SkyObject matching this name
0130          */
0131         SkyObject *objectNamed(const QString &name);
0132 
0133         /**
0134          * The Sky is updated more frequently than the moon, which is updated more frequently
0135          * than the planets.  The date of the last update for each category is recorded so we
0136          * know when we need to do it again (see KStars::updateTime()).
0137          * Initializing these to -1000000.0 ensures they will be updated immediately
0138          * on the first call to KStars::updateTime().
0139          */
0140         void setFullTimeUpdate();
0141 
0142         /**
0143          * Change the current simulation date/time to the KStarsDateTime argument.
0144          * Specified DateTime is always universal time.
0145          * @param newDate the DateTime to set.
0146          */
0147         void changeDateTime(const KStarsDateTime &newDate);
0148 
0149         /** @return pointer to the current simulation local time */
0150         const KStarsDateTime &lt() const
0151         {
0152             return LTime;
0153         }
0154 
0155         /** @return reference to the current simulation universal time */
0156         const KStarsDateTime &ut() const
0157         {
0158             return Clock.utc();
0159         }
0160 
0161         /** Sync the LST with the simulation clock. */
0162         void syncLST();
0163 
0164         /** @return pointer to SkyComposite */
0165         SkyMapComposite *skyComposite()
0166         {
0167             return m_SkyComposite.get();
0168         }
0169 
0170         /** @return pointer to the ColorScheme object */
0171         ColorScheme *colorScheme()
0172         {
0173             return &CScheme;
0174         }
0175 
0176         /** @return file name of current color scheme **/
0177         Q_INVOKABLE QString colorSchemeFileName() { return CScheme.fileName(); }
0178 
0179         /** @return file name of the color scheme with the name \p name **/
0180         QString colorSchemeFileName(const QString &name)
0181         {
0182             return m_color_schemes.count(name) > 0 ? m_color_schemes.at(name) : "";
0183         }
0184 
0185         /** @return file name of the current color scheme **/
0186         Q_INVOKABLE QString colorSchemeName()
0187         {
0188             return colorSchemeName(CScheme.fileName());
0189         }
0190 
0191         /** @return the name of the color scheme with the name \p name **/
0192         QString colorSchemeName(const QString &fileName)
0193         {
0194             return m_color_scheme_names.count(fileName) > 0 ? m_color_scheme_names.at(fileName) : "";
0195         }
0196 
0197         /** @return if the color scheme with the name or filename \p scheme is loaded **/
0198         bool hasColorScheme(const QString &scheme)
0199         {
0200             return m_color_scheme_names.count(scheme) || m_color_schemes.count(scheme);
0201         }
0202 
0203         /** Register a color scheme with \p filename and \p name. */
0204         void add_color_scheme(const QString &filename, const QString &name)
0205         {
0206             m_color_schemes[name] = filename;
0207             m_color_scheme_names[filename] = name;
0208         };
0209 
0210         /** \return a map of color scheme names and filenames */
0211         const std::map<QString, QString> color_schemes() { return m_color_schemes; };
0212 
0213         /** @return pointer to the KSUserDB object */
0214         KSUserDB *userdb() { return &m_ksuserdb; }
0215 
0216         /** @return pointer to the simulation Clock object */
0217         Q_INVOKABLE SimClock *clock()
0218         {
0219             return &Clock;
0220         }
0221 
0222         /** @return pointer to the local sidereal time: a dms object */
0223         CachingDms *lst()
0224         {
0225             return &LST;
0226         }
0227 
0228         /** @return pointer to the GeoLocation object*/
0229         GeoLocation *geo()
0230         {
0231             return &m_Geo;
0232         }
0233 
0234         /** @return list of all geographic locations */
0235         QList<GeoLocation *> &getGeoList()
0236         {
0237             return geoList;
0238         }
0239 
0240         GeoLocation *locationNamed(const QString &city, const QString &province = QString(),
0241                                    const QString &country = QString());
0242 
0243         /**
0244          * @brief nearestLocation Return nearest location to the given longitude and latitude coordinates
0245          * @param longitude Longitude (-180 to +180)
0246          * @param latitude Latitude (-90 to +90)
0247          * @return nearest geographical location to the parameters above.
0248          */
0249         GeoLocation *nearestLocation(double longitude, double latitude);
0250 
0251         /**
0252          * Set the GeoLocation according to the argument.
0253          * @param l reference to the new GeoLocation
0254          */
0255         void setLocation(const GeoLocation &l);
0256 
0257         /** Set the GeoLocation according to the values stored in the configuration file. */
0258         void setLocationFromOptions();
0259 
0260         /** Return map for daylight saving rules. */
0261         const QMap<QString, TimeZoneRule> &getRulebook() const
0262         {
0263             return Rulebook;
0264         }
0265 
0266         /** @return whether the next Focus change will omit the slewing animation. */
0267         bool snapNextFocus() const
0268         {
0269             return snapToFocus;
0270         }
0271 
0272         /**
0273          * Disable or re-enable the slewing animation for the next Focus change.
0274          * @note If the user has turned off all animated slewing, setSnapNextFocus(false)
0275          * will *NOT* enable animation on the next slew.  A false argument would only
0276          * be used if you have previously called setSnapNextFocus(true), but then decided
0277          * you didn't want that after all.  In other words, it's extremely unlikely you'd
0278          * ever want to use setSnapNextFocus(false).
0279          * @param b when true (the default), the next Focus change will omit the slewing
0280          * animation.
0281          */
0282         void setSnapNextFocus(bool b = true)
0283         {
0284             snapToFocus = b;
0285         }
0286 
0287         /**
0288          * Execute a script.  This function actually duplicates the DCOP functionality
0289          * for those cases when invoking DCOP is not practical (i.e., when preparing
0290          * a sky image in command-line dump mode).
0291          * @param name the filename of the script to "execute".
0292          * @param map pointer to the SkyMap object.
0293          * @return true if the script was successfully parsed.
0294          */
0295         bool executeScript(const QString &name, SkyMap *map);
0296 
0297         /** Synchronize list of visible FOVs and list of selected FOVs in Options */
0298 #ifndef KSTARS_LITE
0299         void syncFOV();
0300 #endif
0301 
0302         /**
0303          * @return the list of visible FOVs
0304          */
0305         inline const QList<FOV *> getVisibleFOVs() const
0306         {
0307             return visibleFOVs;
0308         }
0309 
0310         /**
0311          * @return the list of available FOVs
0312          */
0313         inline const QList<FOV *> getAvailableFOVs() const
0314         {
0315             return availFOVs;
0316         }
0317 
0318         /**
0319          * @brief addTransientFOV Adds a new FOV to the list.
0320          * @param newFOV pointer to FOV object.
0321          */
0322         inline void addTransientFOV(std::shared_ptr<FOV> newFOV)
0323         {
0324             transientFOVs.append(newFOV);
0325         }
0326         inline void clearTransientFOVs()
0327         {
0328             transientFOVs.clear();
0329         }
0330 
0331         /**
0332          * @return the list of transient FOVs
0333          */
0334         inline const QList<std::shared_ptr<FOV>> getTransientFOVs() const
0335         {
0336             return transientFOVs;
0337         }
0338 #ifndef KSTARS_LITE
0339         /** Return log object */
0340         OAL::Log *logObject()
0341         {
0342             return m_LogObject.get();
0343         }
0344 
0345         /** Return ADV Tree */
0346         QList<ADVTreeData *> avdTree()
0347         {
0348             return ADVtreeList;
0349         }
0350 
0351         inline ObservingList *observingList() const
0352         {
0353             return m_ObservingList;
0354         }
0355 
0356         ImageExporter *imageExporter();
0357 
0358         Execute *executeSession();
0359 #endif
0360         /*@short Increments the updateID, forcing a recomputation of star positions as well */
0361         unsigned int incUpdateID();
0362 
0363         unsigned int updateID() const
0364         {
0365             return m_updateID;
0366         }
0367         unsigned int updateNumID() const
0368         {
0369             return m_updateNumID;
0370         }
0371         KSNumbers *updateNum()
0372         {
0373             return &m_updateNum;
0374         }
0375         void syncUpdateIDs();
0376 
0377     signals:
0378         /** Signal that specifies the text that should be drawn in the KStarsSplash window. */
0379         void progressText(const QString &text);
0380 
0381         /** Should be used to refresh skymap. */
0382         void skyUpdate(bool);
0383 
0384         /** If data changed, emit clearCache signal. */
0385         void clearCache();
0386 
0387         /** Emitted when geo location changed */
0388         void geoChanged();
0389 
0390     public slots:
0391         /** @short send a message to the console*/
0392         void slotConsoleMessage(QString s)
0393         {
0394             std::cout << (const char *)(s.toLocal8Bit()) << std::endl;
0395         }
0396 
0397         /**
0398          * Update the Simulation Clock.  Update positions of Planets.  Update
0399          * Alt/Az coordinates of objects.  Update precession.
0400          * emit the skyUpdate() signal so that SkyMap / whatever draws the sky can update itself
0401          *
0402          * This is ugly.
0403          * It _will_ change!
0404          * (JH:)hey, it's much less ugly now...can we lose the comment yet? :p
0405          */
0406         void updateTime(GeoLocation *geo, const bool automaticDSTchange = true);
0407 
0408         /**
0409          * Sets the direction of time and stores it in bool TimeRunForwards. If scale >= 0
0410          * time is running forward else time runs backward. We need this to calculate just
0411          * one daylight saving change time (previous or next DST change).
0412          */
0413         void setTimeDirection(float scale);
0414 
0415         // What follows is mostly a port of Arkashs auxdata stuff to a
0416         // more centralized approach that does not store the data in
0417         // the skyobjects as they are ephemeral in the new DSO implementation
0418         //
0419         // I've tried to reuse as much code as possible and maintain
0420         // compatibility with peoples data.
0421         //
0422         // -- Valentin Boettcher
0423 
0424         /**
0425          * Get a reference to the user data of an object with the name \p name.
0426          */
0427         const SkyObjectUserdata::Data &getUserData(const QString &name);
0428 
0429         /**
0430          * Adds a link \p data to the user data for the object with \p
0431          * name, both in memory and on disk.
0432          *
0433          * @returns {success, error_message}
0434          */
0435         std::pair<bool, QString> addToUserData(const QString &name,
0436                                                const SkyObjectUserdata::LinkData &data);
0437 
0438         /**
0439          * Replace \p data in the user data at \p index for the object with \p
0440          * name, both in memory and on disk.
0441          *
0442          * @returns {success, error_message}
0443          */
0444         std::pair<bool, QString> editUserData(const QString &name,
0445                                               const unsigned int index,
0446                                               const SkyObjectUserdata::LinkData &data);
0447 
0448         /**
0449          * Remove data of \p type from the user data at \p index for
0450          * the object with \p name, both in memory and on disk.
0451          *
0452          * @returns {success, error_message}
0453          */
0454         std::pair<bool, QString> deleteUserData(const QString &name,
0455                                                 const unsigned int index,
0456                                                 SkyObjectUserdata::Type type);
0457         /**
0458          * Update the user log of the object with the \p name to
0459          * contain \p newLog (find and replace).
0460          *
0461          * @returns {success, error_message}
0462          */
0463         std::pair<bool, QString> updateUserLog(const QString &name,
0464                                                const QString &newLog);
0465 
0466       private:
0467         /**
0468          * Populate list of geographic locations from "citydb.sqlite" database. Also check for custom
0469          * locations file "mycitydb.sqlite" database, but don't require it.  Each line in the file
0470          * provides the information required to create one GeoLocation object.
0471          * @short Fill list of geographic locations from file(s)
0472          * @return true if at least one city read successfully.
0473          * @see KStarsData::processCity()
0474          */
0475         bool readCityData();
0476 
0477         /** Read the data file that contains daylight savings time rules. */
0478         bool readTimeZoneRulebook();
0479 
0480         //TODO JM: ADV tree should use XML instead
0481         /**
0482          * Read Advanced interface structure to be used later to construct the list view in
0483          * the advanced tab in the Detail Dialog.
0484          * @li KSLABEL designates a top-level parent label
0485          * @li KSINTERFACE designates a common URL interface for several objects
0486          * @li END designates the end of a sub tree structure
0487          * @short read online database lookup structure.
0488          * @return true if data is successfully read.
0489          */
0490         bool readADVTreeData();
0491 
0492         /** Read INDI hosts from an XML file */
0493         bool readINDIHosts();
0494 
0495         //TODO JM: Use XML instead; The logger should have more features
0496         // that allow users to enter details about their observation logs
0497         // objects observed, eye pieces, telescope, conditions, mag..etc
0498         /**
0499          * @short read user logs.
0500          *
0501          * Read user logs. The log file is formatted as following:
0502          * @li KSLABEL designates the beginning of a log
0503          * @li KSLogEnd designates the end of a log.
0504          *
0505          * @return true if data is successfully read.
0506          */
0507         bool readUserLog();
0508 
0509         /**
0510          * Read in URLs to be attached to a named object's right-click popup menu.  At this
0511          * point, there is no way to attach URLs to unnamed objects.  There are two
0512          * kinds of URLs, each with its own data file: image links and webpage links.  In addition,
0513          * there may be user-specific versions with custom URLs.  Each line contains 3 fields
0514          * separated by colons (":").  Note that the last field is the URL, and as such it will
0515          * generally contain a colon itself.  Only the first two colons encountered are treated
0516          * as field separators.  The fields are:
0517          *
0518          * @li Object name.  This must be the "primary" name of the object (the name at the top of the popup menu).
0519          * @li Menu text.  The string that should appear in the popup menu to activate the link.
0520          * @li URL.
0521          * @short Read in image and information URLs.
0522          * @return true if data files were successfully read.
0523          */
0524         bool readURLData(const QString &url,
0525                          SkyObjectUserdata::Type type = SkyObjectUserdata::Type::website);
0526 
0527         /**
0528          * @short open a file containing URL links.
0529          * @param urlfile string representation of the filename to open
0530          * @param file reference to the QFile object which will be opened to this file.
0531          * @return true if file successfully opened.
0532          */
0533         bool openUrlFile(const QString &urlfile, QFile &file);
0534 
0535         /**
0536          * Reset local time to new daylight saving time. Use this function if DST has changed.
0537          * Used by updateTime().
0538          */
0539         void resetToNewDST(GeoLocation *geo, const bool automaticDSTchange);
0540 
0541         /**
0542          * As KStarsData::getUserData just non-const.
0543          * @warning This method is not thread safe :) so take care of that when you use it.
0544          */
0545         SkyObjectUserdata::Data &findUserData(const QString &name);
0546 
0547         QList<ADVTreeData *> ADVtreeList;
0548         std::unique_ptr<SkyMapComposite> m_SkyComposite;
0549 
0550         GeoLocation m_Geo;
0551         SimClock Clock;
0552         KStarsDateTime LTime;
0553         KSUserDB m_ksuserdb;
0554         ColorScheme CScheme;
0555         std::map<QString, QString> m_color_schemes; // name: filename
0556         std::map<QString, QString> m_color_scheme_names; // filename: name
0557 
0558 #ifndef KSTARS_LITE
0559         ObservingList* m_ObservingList { nullptr };
0560         std::unique_ptr<OAL::Log> m_LogObject;
0561         std::unique_ptr<Execute> m_Execute;
0562         std::unique_ptr<ImageExporter> m_ImageExporter;
0563 #endif
0564 
0565         //EquipmentWriter *m_equipmentWriter;
0566 
0567         bool TimeRunsForward { false };
0568         bool temporaryTrail { false };
0569         // FIXME: Used in SkyMap only. Check!
0570         bool snapToFocus { false };
0571 
0572         //KLocale *locale;
0573 
0574         CachingDms LST;
0575 
0576         QKeySequence resumeKey;
0577 
0578         QList<FOV *> availFOVs;         // List of all available FOVs
0579         QList<FOV *> visibleFOVs;       // List of visible FOVs. Cached from Options::FOVNames
0580         QList<std::shared_ptr<FOV>> transientFOVs;     // List of non-permenant transient FOVs.
0581 
0582         KStarsDateTime LastNumUpdate, LastSkyUpdate, LastPlanetUpdate, LastMoonUpdate;
0583         KStarsDateTime NextDSTChange;
0584         // FIXME: Used in kstarsdcop.cpp only
0585         KStarsDateTime StoredDate;
0586 
0587         QList<GeoLocation *> geoList;
0588         QMap<QString, TimeZoneRule> Rulebook;
0589 
0590         quint32 m_preUpdateID, m_updateID;
0591         quint32 m_preUpdateNumID, m_updateNumID;
0592         KSNumbers m_preUpdateNum, m_updateNum;
0593 
0594         static KStarsData *pinstance;
0595 
0596         std::unordered_map<QString, SkyObjectUserdata::Data> m_user_data;
0597         QMutex m_user_data_mutex; // for m_user_data
0598 };