1 /* 2 SPDX-FileCopyrightText: 2001 Heiko Evermann <heiko@evermann.de> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #pragma once 8 9 #include "colorscheme.h" 10 #include "geolocation.h" 11 #include "ksnumbers.h" 12 #include "kstarsdatetime.h" 13 #include "ksuserdb.h" 14 #include "simclock.h" 15 #include "skyobjectuserdata.h" 16 #include <qobject.h> 17 #ifndef KSTARS_LITE 18 #include "oal/oal.h" 19 #include "oal/log.h" 20 #include "polyfills/qstring_hash.h" 21 #endif 22 23 #include <QList> 24 #include <QMap> 25 #include <QKeySequence> 26 27 #include <iostream> 28 #include <memory> 29 #include <unordered_map> 30 31 #define MINZOOM 250. 32 #define MAXZOOM 5000000. 33 #define DEFAULTZOOM 2000. 34 #define DZOOM 1.189207115 // 2^(1/4) 35 #define AU_KM 1.49605e8 //km in one AU 36 37 class QFile; 38 39 class Execute; 40 class FOV; 41 class ImageExporter; 42 class SkyMap; 43 class SkyMapComposite; 44 class SkyObject; 45 class ObservingList; 46 class TimeZoneRule; 47 48 #ifdef KSTARS_LITE 49 //Will go away when details window will be implemented in KStars Lite 50 struct ADVTreeData 51 { 52 QString Name; 53 QString Link; 54 int Type; 55 }; 56 #else 57 struct ADVTreeData; 58 #endif 59 60 /** 61 * @class KStarsData 62 * KStarsData is the backbone of KStars. It contains all the data used by KStars, 63 * including the SkyMapComposite that contains all items in the skymap 64 * (stars, deep-sky objects, planets, constellations, etc). Other kinds of data 65 * are stored here as well: the geographic locations, the timezone rules, etc. 66 * 67 * @author Heiko Evermann 68 * @version 1.0 69 */ 70 class KStarsData : public QObject 71 { 72 Q_OBJECT 73 74 protected: 75 /** Constructor. */ 76 KStarsData(); 77 78 public: 79 // FIXME: It uses temporary trail. There must be way to 80 // this better. And resumeKey in DBUS code 81 friend class KStars; 82 // FIXME: it uses temporary trail and resumeKey 83 friend class SkyMap; 84 // FIXME: uses geoList and changes it. 85 friend class LocationDialog; 86 friend class LocationDialogLite; 87 88 static KStarsData *Create(); 89 Instance()90 static inline KStarsData *Instance() 91 { 92 return pinstance; 93 } 94 95 /** 96 * Initialize KStarsData while running splash screen. 97 * @return true on success. 98 */ 99 bool initialize(); 100 101 /** Destructor. Delete data objects. */ 102 ~KStarsData() override; 103 104 /** 105 * Set the NextDSTChange member. 106 * Need this accessor because I could not make KStars::privatedata a friend 107 * class for some reason...:/ 108 */ setNextDSTChange(const KStarsDateTime & dt)109 void setNextDSTChange(const KStarsDateTime &dt) 110 { 111 NextDSTChange = dt; 112 } 113 114 /** 115 * Returns true if time is running forward else false. Used by KStars to prevent 116 * double calculations of daylight saving change time. 117 */ isTimeRunningForward()118 bool isTimeRunningForward() const 119 { 120 return TimeRunsForward; 121 } 122 123 /** @return pointer to the localization (KLocale) object */ 124 //KLocale *getLocale() { return locale; } 125 126 /** 127 * @short Find object by name. 128 * @param name Object name to find 129 * @return pointer to SkyObject matching this name 130 */ 131 SkyObject *objectNamed(const QString &name); 132 133 /** 134 * The Sky is updated more frequently than the moon, which is updated more frequently 135 * than the planets. The date of the last update for each category is recorded so we 136 * know when we need to do it again (see KStars::updateTime()). 137 * Initializing these to -1000000.0 ensures they will be updated immediately 138 * on the first call to KStars::updateTime(). 139 */ 140 void setFullTimeUpdate(); 141 142 /** 143 * Change the current simulation date/time to the KStarsDateTime argument. 144 * Specified DateTime is always universal time. 145 * @param newDate the DateTime to set. 146 */ 147 void changeDateTime(const KStarsDateTime &newDate); 148 149 /** @return pointer to the current simulation local time */ lt()150 const KStarsDateTime <() const 151 { 152 return LTime; 153 } 154 155 /** @return reference to the current simulation universal time */ ut()156 const KStarsDateTime &ut() const 157 { 158 return Clock.utc(); 159 } 160 161 /** Sync the LST with the simulation clock. */ 162 void syncLST(); 163 164 /** @return pointer to SkyComposite */ skyComposite()165 SkyMapComposite *skyComposite() 166 { 167 return m_SkyComposite.get(); 168 } 169 170 /** @return pointer to the ColorScheme object */ colorScheme()171 ColorScheme *colorScheme() 172 { 173 return &CScheme; 174 } 175 176 /** @return file name of current color scheme **/ colorSchemeFileName()177 Q_INVOKABLE QString colorSchemeFileName() { return CScheme.fileName(); } 178 179 /** @return file name of the color scheme with the name \p name **/ colorSchemeFileName(const QString & name)180 QString colorSchemeFileName(const QString &name) 181 { 182 return m_color_schemes.count(name) > 0 ? m_color_schemes.at(name) : ""; 183 } 184 185 /** @return file name of the current color scheme **/ colorSchemeName()186 Q_INVOKABLE QString colorSchemeName() 187 { 188 return colorSchemeName(CScheme.fileName()); 189 } 190 191 /** @return the name of the color scheme with the name \p name **/ colorSchemeName(const QString & fileName)192 QString colorSchemeName(const QString &fileName) 193 { 194 return m_color_scheme_names.count(fileName) > 0 ? m_color_scheme_names.at(fileName) : ""; 195 } 196 197 /** @return if the color scheme with the name or filename \p scheme is loaded **/ hasColorScheme(const QString & scheme)198 bool hasColorScheme(const QString &scheme) 199 { 200 return m_color_scheme_names.count(scheme) || m_color_schemes.count(scheme); 201 } 202 203 /** Register a color scheme with \p filename and \p name. */ add_color_scheme(const QString & filename,const QString & name)204 void add_color_scheme(const QString &filename, const QString &name) 205 { 206 m_color_schemes[name] = filename; 207 m_color_scheme_names[filename] = name; 208 }; 209 210 /** \return a map of color scheme names and filenames */ color_schemes()211 const std::map<QString, QString> color_schemes() { return m_color_schemes; }; 212 213 /** @return pointer to the KSUserDB object */ userdb()214 KSUserDB *userdb() { return &m_ksuserdb; } 215 216 /** @return pointer to the simulation Clock object */ clock()217 Q_INVOKABLE SimClock *clock() 218 { 219 return &Clock; 220 } 221 222 /** @return pointer to the local sidereal time: a dms object */ lst()223 CachingDms *lst() 224 { 225 return &LST; 226 } 227 228 /** @return pointer to the GeoLocation object*/ geo()229 GeoLocation *geo() 230 { 231 return &m_Geo; 232 } 233 234 /** @return list of all geographic locations */ getGeoList()235 QList<GeoLocation *> &getGeoList() 236 { 237 return geoList; 238 } 239 240 GeoLocation *locationNamed(const QString &city, const QString &province = QString(), 241 const QString &country = QString()); 242 243 /** 244 * @brief nearestLocation Return nearest location to the given longitude and latitude coordinates 245 * @param longitude Longitude (-180 to +180) 246 * @param latitude Latitude (-90 to +90) 247 * @return nearest geographical location to the parameters above. 248 */ 249 GeoLocation *nearestLocation(double longitude, double latitude); 250 251 /** 252 * Set the GeoLocation according to the argument. 253 * @param l reference to the new GeoLocation 254 */ 255 void setLocation(const GeoLocation &l); 256 257 /** Set the GeoLocation according to the values stored in the configuration file. */ 258 void setLocationFromOptions(); 259 260 /** Return map for daylight saving rules. */ getRulebook()261 const QMap<QString, TimeZoneRule> &getRulebook() const 262 { 263 return Rulebook; 264 } 265 266 /** @return whether the next Focus change will omit the slewing animation. */ snapNextFocus()267 bool snapNextFocus() const 268 { 269 return snapToFocus; 270 } 271 272 /** 273 * Disable or re-enable the slewing animation for the next Focus change. 274 * @note If the user has turned off all animated slewing, setSnapNextFocus(false) 275 * will *NOT* enable animation on the next slew. A false argument would only 276 * be used if you have previously called setSnapNextFocus(true), but then decided 277 * you didn't want that after all. In other words, it's extremely unlikely you'd 278 * ever want to use setSnapNextFocus(false). 279 * @param b when true (the default), the next Focus change will omit the slewing 280 * animation. 281 */ 282 void setSnapNextFocus(bool b = true) 283 { 284 snapToFocus = b; 285 } 286 287 /** 288 * Execute a script. This function actually duplicates the DCOP functionality 289 * for those cases when invoking DCOP is not practical (i.e., when preparing 290 * a sky image in command-line dump mode). 291 * @param name the filename of the script to "execute". 292 * @param map pointer to the SkyMap object. 293 * @return true if the script was successfully parsed. 294 */ 295 bool executeScript(const QString &name, SkyMap *map); 296 297 /** Synchronize list of visible FOVs and list of selected FOVs in Options */ 298 #ifndef KSTARS_LITE 299 void syncFOV(); 300 #endif 301 302 /** 303 * @return the list of visible FOVs 304 */ getVisibleFOVs()305 inline const QList<FOV *> getVisibleFOVs() const 306 { 307 return visibleFOVs; 308 } 309 310 /** 311 * @return the list of available FOVs 312 */ getAvailableFOVs()313 inline const QList<FOV *> getAvailableFOVs() const 314 { 315 return availFOVs; 316 } 317 318 /** 319 * @brief addTransientFOV Adds a new FOV to the list. 320 * @param newFOV pointer to FOV object. 321 */ addTransientFOV(std::shared_ptr<FOV> newFOV)322 inline void addTransientFOV(std::shared_ptr<FOV> newFOV) 323 { 324 transientFOVs.append(newFOV); 325 } clearTransientFOVs()326 inline void clearTransientFOVs() 327 { 328 transientFOVs.clear(); 329 } 330 331 /** 332 * @return the list of transient FOVs 333 */ getTransientFOVs()334 inline const QList<std::shared_ptr<FOV>> getTransientFOVs() const 335 { 336 return transientFOVs; 337 } 338 #ifndef KSTARS_LITE 339 /** Return log object */ logObject()340 OAL::Log *logObject() 341 { 342 return m_LogObject.get(); 343 } 344 345 /** Return ADV Tree */ avdTree()346 QList<ADVTreeData *> avdTree() 347 { 348 return ADVtreeList; 349 } 350 observingList()351 inline ObservingList *observingList() const 352 { 353 return m_ObservingList; 354 } 355 356 ImageExporter *imageExporter(); 357 358 Execute *executeSession(); 359 #endif 360 /*@short Increments the updateID, forcing a recomputation of star positions as well */ 361 unsigned int incUpdateID(); 362 updateID()363 unsigned int updateID() const 364 { 365 return m_updateID; 366 } updateNumID()367 unsigned int updateNumID() const 368 { 369 return m_updateNumID; 370 } updateNum()371 KSNumbers *updateNum() 372 { 373 return &m_updateNum; 374 } 375 void syncUpdateIDs(); 376 377 signals: 378 /** Signal that specifies the text that should be drawn in the KStarsSplash window. */ 379 void progressText(const QString &text); 380 381 /** Should be used to refresh skymap. */ 382 void skyUpdate(bool); 383 384 /** If data changed, emit clearCache signal. */ 385 void clearCache(); 386 387 /** Emitted when geo location changed */ 388 void geoChanged(); 389 390 public slots: 391 /** @short send a message to the console*/ slotConsoleMessage(QString s)392 void slotConsoleMessage(QString s) 393 { 394 std::cout << (const char *)(s.toLocal8Bit()) << std::endl; 395 } 396 397 /** 398 * Update the Simulation Clock. Update positions of Planets. Update 399 * Alt/Az coordinates of objects. Update precession. 400 * emit the skyUpdate() signal so that SkyMap / whatever draws the sky can update itself 401 * 402 * This is ugly. 403 * It _will_ change! 404 * (JH:)hey, it's much less ugly now...can we lose the comment yet? :p 405 */ 406 void updateTime(GeoLocation *geo, const bool automaticDSTchange = true); 407 408 /** 409 * Sets the direction of time and stores it in bool TimeRunForwards. If scale >= 0 410 * time is running forward else time runs backward. We need this to calculate just 411 * one daylight saving change time (previous or next DST change). 412 */ 413 void setTimeDirection(float scale); 414 415 // What follows is mostly a port of Arkashs auxdata stuff to a 416 // more centralized approach that does not store the data in 417 // the skyobjects as they are ephemeral in the new DSO implementation 418 // 419 // I've tried to reuse as much code as possible and maintain 420 // compatibility with peoples data. 421 // 422 // -- Valentin Boettcher 423 424 /** 425 * Get a reference to the user data of an object with the name \p name. 426 */ 427 const SkyObjectUserdata::Data &getUserData(const QString &name); 428 429 /** 430 * Adds a link \p data to the user data for the object with \p 431 * name, both in memory and on disk. 432 * 433 * @returns {success, error_message} 434 */ 435 std::pair<bool, QString> addToUserData(const QString &name, 436 const SkyObjectUserdata::LinkData &data); 437 438 /** 439 * Replace \p data in the user data at \p index for the object with \p 440 * name, both in memory and on disk. 441 * 442 * @returns {success, error_message} 443 */ 444 std::pair<bool, QString> editUserData(const QString &name, 445 const unsigned int index, 446 const SkyObjectUserdata::LinkData &data); 447 448 /** 449 * Remove data of \p type from the user data at \p index for 450 * the object with \p name, both in memory and on disk. 451 * 452 * @returns {success, error_message} 453 */ 454 std::pair<bool, QString> deleteUserData(const QString &name, 455 const unsigned int index, 456 SkyObjectUserdata::Type type); 457 /** 458 * Update the user log of the object with the \p name to 459 * contain \p newLog (find and replace). 460 * 461 * @returns {success, error_message} 462 */ 463 std::pair<bool, QString> updateUserLog(const QString &name, 464 const QString &newLog); 465 466 private: 467 /** 468 * Populate list of geographic locations from "citydb.sqlite" database. Also check for custom 469 * locations file "mycitydb.sqlite" database, but don't require it. Each line in the file 470 * provides the information required to create one GeoLocation object. 471 * @short Fill list of geographic locations from file(s) 472 * @return true if at least one city read successfully. 473 * @see KStarsData::processCity() 474 */ 475 bool readCityData(); 476 477 /** Read the data file that contains daylight savings time rules. */ 478 bool readTimeZoneRulebook(); 479 480 //TODO JM: ADV tree should use XML instead 481 /** 482 * Read Advanced interface structure to be used later to construct the list view in 483 * the advanced tab in the Detail Dialog. 484 * @li KSLABEL designates a top-level parent label 485 * @li KSINTERFACE designates a common URL interface for several objects 486 * @li END designates the end of a sub tree structure 487 * @short read online database lookup structure. 488 * @return true if data is successfully read. 489 */ 490 bool readADVTreeData(); 491 492 /** Read INDI hosts from an XML file */ 493 bool readINDIHosts(); 494 495 //TODO JM: Use XML instead; The logger should have more features 496 // that allow users to enter details about their observation logs 497 // objects observed, eye pieces, telescope, conditions, mag..etc 498 /** 499 * @short read user logs. 500 * 501 * Read user logs. The log file is formatted as following: 502 * @li KSLABEL designates the beginning of a log 503 * @li KSLogEnd designates the end of a log. 504 * 505 * @return true if data is successfully read. 506 */ 507 bool readUserLog(); 508 509 /** 510 * Read in URLs to be attached to a named object's right-click popup menu. At this 511 * point, there is no way to attach URLs to unnamed objects. There are two 512 * kinds of URLs, each with its own data file: image links and webpage links. In addition, 513 * there may be user-specific versions with custom URLs. Each line contains 3 fields 514 * separated by colons (":"). Note that the last field is the URL, and as such it will 515 * generally contain a colon itself. Only the first two colons encountered are treated 516 * as field separators. The fields are: 517 * 518 * @li Object name. This must be the "primary" name of the object (the name at the top of the popup menu). 519 * @li Menu text. The string that should appear in the popup menu to activate the link. 520 * @li URL. 521 * @short Read in image and information URLs. 522 * @return true if data files were successfully read. 523 */ 524 bool readURLData(const QString &url, 525 SkyObjectUserdata::Type type = SkyObjectUserdata::Type::website); 526 527 /** 528 * @short open a file containing URL links. 529 * @param urlfile string representation of the filename to open 530 * @param file reference to the QFile object which will be opened to this file. 531 * @return true if file successfully opened. 532 */ 533 bool openUrlFile(const QString &urlfile, QFile &file); 534 535 /** 536 * Reset local time to new daylight saving time. Use this function if DST has changed. 537 * Used by updateTime(). 538 */ 539 void resetToNewDST(GeoLocation *geo, const bool automaticDSTchange); 540 541 /** 542 * As KStarsData::getUserData just non-const. 543 * @warning This method is not thread safe :) so take care of that when you use it. 544 */ 545 SkyObjectUserdata::Data &findUserData(const QString &name); 546 547 QList<ADVTreeData *> ADVtreeList; 548 std::unique_ptr<SkyMapComposite> m_SkyComposite; 549 550 GeoLocation m_Geo; 551 SimClock Clock; 552 KStarsDateTime LTime; 553 KSUserDB m_ksuserdb; 554 ColorScheme CScheme; 555 std::map<QString, QString> m_color_schemes; // name: filename 556 std::map<QString, QString> m_color_scheme_names; // filename: name 557 558 #ifndef KSTARS_LITE 559 ObservingList* m_ObservingList { nullptr }; 560 std::unique_ptr<OAL::Log> m_LogObject; 561 std::unique_ptr<Execute> m_Execute; 562 std::unique_ptr<ImageExporter> m_ImageExporter; 563 #endif 564 565 //EquipmentWriter *m_equipmentWriter; 566 567 bool TimeRunsForward { false }; 568 bool temporaryTrail { false }; 569 // FIXME: Used in SkyMap only. Check! 570 bool snapToFocus { false }; 571 572 //KLocale *locale; 573 574 CachingDms LST; 575 576 QKeySequence resumeKey; 577 578 QList<FOV *> availFOVs; // List of all available FOVs 579 QList<FOV *> visibleFOVs; // List of visible FOVs. Cached from Options::FOVNames 580 QList<std::shared_ptr<FOV>> transientFOVs; // List of non-permenant transient FOVs. 581 582 KStarsDateTime LastNumUpdate, LastSkyUpdate, LastPlanetUpdate, LastMoonUpdate; 583 KStarsDateTime NextDSTChange; 584 // FIXME: Used in kstarsdcop.cpp only 585 KStarsDateTime StoredDate; 586 587 QList<GeoLocation *> geoList; 588 QMap<QString, TimeZoneRule> Rulebook; 589 590 quint32 m_preUpdateID, m_updateID; 591 quint32 m_preUpdateNumID, m_updateNumID; 592 KSNumbers m_preUpdateNum, m_updateNum; 593 594 static KStarsData *pinstance; 595 596 std::unordered_map<QString, SkyObjectUserdata::Data> m_user_data; 597 QMutex m_user_data_mutex; // for m_user_data 598 }; 599