1 /*
2     SPDX-FileCopyrightText: 2012 Samikshan Bairagya <samikshan@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "modelmanager.h"
8 
9 #include "ksfilereader.h"
10 #include "kstars.h"
11 #include "kstarsdata.h"
12 #include "obsconditions.h"
13 #include "skymapcomposite.h"
14 #include "skyobjitem.h"
15 #include "skyobjlistmodel.h"
16 #include "starobject.h"
17 #include "catalogsdb.h"
18 
19 #include <QtConcurrent>
20 
ModelManager(ObsConditions * obs)21 ModelManager::ModelManager(ObsConditions *obs)
22 {
23     m_ObsConditions = obs;
24 
25     tempModel = new SkyObjListModel();
26 
27     m_ModelList  = QList<SkyObjListModel *>();
28     m_ObjectList = QList<QList<SkyObjItem *>>();
29 
30     favoriteClusters = QList<SkyObjItem *>();
31     favoriteNebulas  = QList<SkyObjItem *>();
32     favoriteGalaxies = QList<SkyObjItem *>();
33 
34     for (int i = 0; i < NumberOfLists; i++)
35     {
36         m_ModelList.append(new SkyObjListModel());
37         m_ObjectList.append(QList<SkyObjItem *>());
38     }
39 
40     QtConcurrent::run(this, &ModelManager::loadLists);
41 }
42 
~ModelManager()43 ModelManager::~ModelManager()
44 {
45     qDeleteAll(m_ModelList);
46     foreach (QList<SkyObjItem *> list, m_ObjectList)
47         qDeleteAll(list);
48     delete tempModel;
49 }
50 
loadLists()51 void ModelManager::loadLists()
52 {
53     if (KStars::Closing)
54         return;
55 
56     emit loadProgressUpdated(0);
57     KStarsData *data = KStarsData::Instance();
58     QVector<QPair<QString, const SkyObject *>> listStars;
59     listStars.append(data->skyComposite()->objectLists(SkyObject::STAR));
60     for (int i = 0; i < listStars.size(); i++)
61     {
62         QPair<QString, const SkyObject *> pair = listStars.value(i);
63         const StarObject *star                 = dynamic_cast<const StarObject *>(pair.second);
64         if (star != nullptr && star->hasLatinName())
65             m_ObjectList[Stars].append(new SkyObjItem((SkyObject *)(star)));
66     }
67     QString prevName;
68     for (int i = 0; i < m_ObjectList[Stars].size(); i++)
69     {
70         SkyObjItem *star = m_ObjectList[Stars].at(i);
71         if (prevName == star->getName())
72         {
73             m_ObjectList[Stars].removeAt(i);
74             i--;
75         }
76         prevName = star->getName();
77     }
78 
79     KSFileReader fileReader;
80     if (!fileReader.open("Interesting.dat"))
81         return;
82 
83     while (fileReader.hasMoreLines())
84     {
85         if (KStars::Closing)
86             return;
87 
88         QString line = fileReader.readLine();
89 
90         if (line.length() == 0 || line[0] == '#')
91             continue;
92 
93         SkyObject *o;
94         if ((o = data->skyComposite()->findByName(line)))
95         {
96             //qDebug()<<o->longname()<<o->typeName();
97             switch (o->type())
98             {
99                 case SkyObject::OPEN_CLUSTER:
100                 case SkyObject::GLOBULAR_CLUSTER:
101                 case SkyObject::GALAXY_CLUSTER:
102                     favoriteClusters.append(new SkyObjItem(o));
103                     break;
104                 case SkyObject::PLANETARY_NEBULA:
105                 case SkyObject::DARK_NEBULA:
106                 case SkyObject::GASEOUS_NEBULA:
107                     favoriteNebulas.append(new SkyObjItem(o));
108                     break;
109                 case SkyObject::GALAXY:
110                     favoriteGalaxies.append(new SkyObjItem(o));
111                     break;
112             }
113         }
114     }
115 
116     emit loadProgressUpdated(0.20);
117 
118     loadObjectList(m_ObjectList[Asteroids], SkyObject::ASTEROID);
119     emit loadProgressUpdated(0.30);
120     loadObjectList(m_ObjectList[Comets], SkyObject::COMET);
121     emit loadProgressUpdated(0.40);
122     loadObjectList(m_ObjectList[Satellites], SkyObject::SATELLITE);
123     loadObjectList(m_ObjectList[Supernovas], SkyObject::SUPERNOVA);
124     emit loadProgressUpdated(0.50);
125     loadObjectList(m_ObjectList[Constellations], SkyObject::CONSTELLATION);
126     emit loadProgressUpdated(0.55);
127     loadObjectList(m_ObjectList[Planets], SkyObject::PLANET);
128     emit loadProgressUpdated(0.60);
129 
130     loadObjectList(m_ObjectList[Galaxies], SkyObject::GALAXY);
131     emit loadProgressUpdated(0.70);
132 
133     loadObjectList(m_ObjectList[Clusters], SkyObject::OPEN_CLUSTER);
134     loadObjectList(m_ObjectList[Clusters], SkyObject::GLOBULAR_CLUSTER);
135     loadObjectList(m_ObjectList[Clusters], SkyObject::GALAXY_CLUSTER);
136     emit loadProgressUpdated(0.80);
137 
138     loadObjectList(m_ObjectList[Nebulas], SkyObject::PLANETARY_NEBULA);
139     loadObjectList(m_ObjectList[Nebulas], SkyObject::SUPERNOVA_REMNANT);
140     loadObjectList(m_ObjectList[Nebulas], SkyObject::GASEOUS_NEBULA);
141     loadObjectList(m_ObjectList[Nebulas], SkyObject::DARK_NEBULA);
142 
143     emit loadProgressUpdated(0.90);
144     emit loadProgressUpdated(1);
145 }
146 
updateAllModels(ObsConditions * obs)147 void ModelManager::updateAllModels(ObsConditions *obs)
148 {
149     m_ObsConditions = obs;
150     resetAllModels();
151 
152     for (int i = 0; i < NumberOfLists; i++)
153         loadObjectsIntoModel(*m_ModelList[i], m_ObjectList[i]);
154 }
155 
updateModel(ObsConditions * obs,QString modelName)156 void ModelManager::updateModel(ObsConditions *obs, QString modelName)
157 {
158     m_ObsConditions        = obs;
159     SkyObjListModel *model = returnModel(modelName);
160     const auto modelNumber = getModelNumber(modelName);
161 
162     if (modelNumber > -1 && model)
163     {
164         model->resetModel();
165         if (showOnlyFavorites && modelName == "galaxies")
166             loadObjectsIntoModel(*m_ModelList[modelNumber], favoriteGalaxies);
167         else if (showOnlyFavorites && modelName == "nebulas")
168             loadObjectsIntoModel(*m_ModelList[modelNumber], favoriteNebulas);
169         else if (showOnlyFavorites && modelName == "clusters")
170             loadObjectsIntoModel(*m_ModelList[modelNumber], favoriteClusters);
171         else
172             loadObjectsIntoModel(*m_ModelList[modelNumber], m_ObjectList[modelNumber]);
173         emit modelUpdated();
174     }
175 }
176 
loadObjectList(QList<SkyObjItem * > & skyObjectList,int type)177 void ModelManager::loadObjectList(QList<SkyObjItem *> &skyObjectList, int type)
178 {
179     if (KStars::Closing)
180         return;
181 
182     KStarsData *data                                   = KStarsData::Instance();
183     QVector<QPair<QString, const SkyObject *>> objects = data->skyComposite()->objectLists(type);
184 
185     for (int i = 0; i < objects.size(); i++)
186     {
187         if (KStars::Closing)
188             return;
189 
190         QPair<QString, const SkyObject *> pair = objects.value(i);
191         const SkyObject *listObject            = pair.second;
192         if (listObject->name() != i18n("Sun"))
193             skyObjectList.append(new SkyObjItem(const_cast<SkyObject *>(listObject)));
194     }
195     QString prevName;
196     for (int i = 0; i < skyObjectList.size(); i++)
197     {
198         if (KStars::Closing)
199             return;
200 
201         SkyObjItem *obj = skyObjectList.at(i);
202         if (prevName == obj->getName())
203         {
204             skyObjectList.removeAt(i);
205             i--;
206         }
207         prevName = obj->getName();
208     }
209 }
210 
loadObjectsIntoModel(SkyObjListModel & model,QList<SkyObjItem * > & skyObjectList)211 void ModelManager::loadObjectsIntoModel(SkyObjListModel &model, QList<SkyObjItem *> &skyObjectList)
212 {
213     KStarsData *data = KStarsData::Instance();
214 
215     foreach (SkyObjItem *soitem, skyObjectList)
216     {
217         bool isVisible =
218             (showOnlyVisible) ? (m_ObsConditions->isVisible(data->geo(), data->lst(), soitem->getSkyObject())) : true;
219         if (isVisible)
220             model.addSkyObject(soitem);
221     }
222 }
223 
resetAllModels()224 void ModelManager::resetAllModels()
225 {
226     foreach (SkyObjListModel *model, m_ModelList)
227         model->resetModel();
228 }
229 
getModelNumber(QString modelName)230 int ModelManager::getModelNumber(QString modelName)
231 {
232     if (modelName == "planets")
233         return Planets;
234     if (modelName == "stars")
235         return Stars;
236     if (modelName == "constellations")
237         return Constellations;
238     if (modelName == "galaxies")
239         return Galaxies;
240     if (modelName == "clusters")
241         return Clusters;
242     if (modelName == "nebulas")
243         return Nebulas;
244     if (modelName == "asteroids")
245         return Asteroids;
246     if (modelName == "comets")
247         return Comets;
248     if (modelName == "supernovas")
249         return Supernovas;
250     if (modelName == "satellites")
251         return Satellites;
252     if (modelName == "messier")
253         return Messier;
254     if (modelName == "ngc")
255         return NGC;
256     if (modelName == "ic")
257         return IC;
258     if (modelName == "sharpless")
259         return Sharpless;
260     else
261         return -1;
262 }
263 
returnModel(QString modelName)264 SkyObjListModel *ModelManager::returnModel(QString modelName)
265 {
266     int modelNumber = getModelNumber(modelName);
267     if (modelNumber > -1 && modelNumber < NumberOfLists)
268         return m_ModelList[modelNumber];
269     else
270         return tempModel;
271 }
272 
loadCatalog(const QString & name)273 void ModelManager::loadCatalog(const QString &name)
274 {
275     const auto id = getModelNumber(name);
276     if (m_CatalogMap.count(id) > 0)
277         return;
278 
279     const std::unordered_map<QString, QString> search_prefixes{
280         { "ngc", "NGC " }, { "ic", "IC " }, { "messier", "M " }, { "sharpless", "Sh2 " }
281     };
282 
283     CatalogsDB::DBManager manager{ CatalogsDB::dso_db_path() };
284 
285     const auto &prefix = search_prefixes.at(name);
286     const int offset   = prefix.size();
287 
288     m_CatalogMap[id] = std::get<2>(manager.general_master_query(
289         QString("name LIKE '%1'").arg(prefix + "%"),
290         QString("CAST(SUBSTR(name,%1) AS INT)").arg(offset)));
291 
292     auto &lst = m_CatalogSkyObjItems[id];
293 
294     for (auto &obj : m_CatalogMap[id])
295     {
296         obj.updateCoordsNow(KStarsData::Instance()->updateNum());
297         lst.emplace_back(&obj);
298     }
299 
300     auto &p_lst = m_ObjectList[id];
301     for (auto &obj : lst)
302         p_lst.append(&obj);
303 
304     updateModel(m_ObsConditions, name);
305     emit loadProgressUpdated(1);
306 };
307