1 /* 2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 3 SPDX-FileCopyrightText: 2021 Valentin Boettcher <hiro at protagon.space; @hiro98:tchncs.de> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #pragma once 9 10 #include "skycomponent.h" 11 #include "catalogsdb.h" 12 #include "catalogobject.h" 13 #include "skymesh.h" 14 #include "trixelcache.h" 15 #include "Options.h" 16 17 #include "polyfills/qstring_hash.h" 18 #include <unordered_map> 19 20 class SkyMesh; 21 class SkyMap; 22 23 /** 24 * \brief Represents objects loaded from an sqlite backed, trixel 25 * indexed catalog. 26 * 27 * The component doesn't follow the traditional list approach and 28 * loads it's skyobjects into an LRU cache (`TrixelCache`). For 29 * puproses of compatiblility with object search etc. some of the 30 * brightest objects are loaded into `m_static_objects` and registered 31 * within the component system. Furthermore, if some part of the code 32 * demands a pointer to a CatalogObject, it will be allocated into 33 * `m_static_objects` on demand. 34 * 35 * If you want to access DSOs in _new_ code you should use a local 36 * instance of `CatalogsDB::DBManager` instead and call `dropCache` if 37 * necessary. 38 * 39 * \sa CatalogsDB::DBManager 40 */ 41 class CatalogsComponent : public SkyComponent 42 { 43 public: 44 using ObjectList = std::vector<CatalogObject>; 45 46 /** 47 * Constructs the Catalogscomponent with a \p parent and a 48 * database file under the path \p db_filename. If \p load_ngc is 49 * specified, an attempt is made to load the default catalog from 50 * the default location into the db. 51 * 52 * The lru cache for the objects will be initialized to a capacity 53 * configurable by Options::dSOCachePercentage. 54 */ 55 explicit CatalogsComponent(SkyComposite *parent, const QString &db_filename, 56 bool load_default = false); 57 58 ~CatalogsComponent() override = default; 59 60 /** 61 * Draws the objects in the currently visible trixels by 62 * dynamically loading them from the database. 63 */ 64 void draw(SkyPainter *skyp) override; 65 66 /** 67 * Set the cache size to the new \p percentage. 68 * 69 * The cache stores the objects of a certain \p percentage of all 70 * trixels. Setting `percentage = 100` short circuits the cache and loads 71 * all the objects into memory. This is reasonable for catalog sizes up 72 * to `10_000` objects. 73 */ resizeCache(const int percentage)74 void resizeCache(const int percentage) 75 { 76 m_cache.set_size(calculateCacheSize(percentage)); 77 }; 78 79 /** 80 * \short Search the underlying database for an object with the \p 81 * name. \sa `CatalogsDB::DBManager::find_object_by_name` for 82 * details. 83 * 84 * If multiple objects match, the one with the hightest magnitude is 85 * returned. 86 * 87 * \return a pointer to the SkyObject whose name matches the argument, or 88 * a nullptr pointer if no match was found. (Due to way KStars works) 89 */ 90 SkyObject *findByName(const QString &name) override; 91 92 void objectsInArea(QList<SkyObject *> &list, const SkyRegion ®ion) override; 93 94 SkyObject *objectNearest(SkyPoint *p, double &maxrad) override; 95 96 /** 97 * Insert an object \p obj into `m_static_objects` and return a 98 * reference to the newly inserted object. If the object is 99 * already present in the list, return a reference to 100 * that. Furthermore the object will be updated 101 * (`CatalogObject::JITupdate`) and inserted into the parent's 102 * `objectLists`. 103 */ 104 CatalogObject &insertStaticObject(const CatalogObject &obj); 105 106 /** 107 * Clear the internal cache and effectively reload all objects 108 * from the database. 109 */ dropCache()110 void dropCache() 111 { 112 m_cache.clear(); 113 m_catalog_colors = m_db_manager.get_catalog_colors(); 114 }; 115 116 /** 117 * Wether to show the DSOs. 118 */ selected()119 bool selected() override 120 { 121 return Options::showDeepSky(); 122 }; 123 124 private: 125 /** 126 * The database interface for the catalog. 127 */ 128 CatalogsDB::DBManager m_db_manager; 129 130 /** 131 * A pointer to a SkyMesh of the appropriate level. 132 * 133 * @note The use of a pointer here is a legacy from the 134 * SkyComponent implementation. 135 */ 136 SkyMesh *m_skyMesh; 137 138 /** 139 * The main container for the currently loaded objects. 140 */ 141 ObjectList m_objects; 142 143 /** 144 * The cache holding the DSOs 145 */ 146 TrixelCache<ObjectList> m_cache; 147 148 /** 149 * A trixel indexed map of lists containing manually loaded 150 * `CatalogObject`s. 151 * 152 * Because some `KStars` internal code requires pointers to SkyObjects 153 * and this component doesn't hold its objects, we have create a space to 154 * to own the objets that we create in methods like `findByName`. Thus it 155 * is expected that this list won't hold many objects and doesn't have to 156 * be emptied at runtime. The objects in this map are not drawn and have 157 * to be updated manually. 158 * 159 * __No objects should ever be removed from this list, as references and 160 * pointers to list members are required to remain valid.__ 161 * 162 * __In new code, a local instance of `CatalogsDB::DBManager` should be 163 * used when access to CatalogObjects is required. Call `dropCache` if 164 * required.__ 165 */ 166 std::unordered_map<Trixel, CatalogsDB::CatalogObjectList> m_static_objects; 167 168 /** 169 * A cache for catalog colors. 170 */ 171 CatalogsDB::ColorMap m_catalog_colors; 172 173 //@{ 174 /** Helpers */ 175 176 void updateSkyMesh(SkyMap &map, MeshBufNum_t buf = DRAW_BUF); calculateCacheSize(const unsigned int percentage)177 size_t calculateCacheSize(const unsigned int percentage) 178 { 179 return m_skyMesh->size() * percentage / 100; 180 } 181 182 /** 183 * Try importing the old skycomponents database. 184 */ 185 void tryImportSkyComponents(); 186 187 //@} 188 }; 189