1 /*
2     SPDX-FileCopyrightText: 2005 Thomas Kabelmann <thomas.kabelmann@gmx.de>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "skymapcomposite.h"
8 
9 #include "artificialhorizoncomponent.h"
10 #include "catalogsdb.h"
11 #include "constellationartcomponent.h"
12 #include "constellationboundarylines.h"
13 #include "constellationlines.h"
14 #include "constellationnamescomponent.h"
15 #include "culturelist.h"
16 #include "deepstarcomponent.h"
17 #include "catalogscomponent.h"
18 #include "ecliptic.h"
19 #include "equator.h"
20 #include "equatorialcoordinategrid.h"
21 #include "horizoncomponent.h"
22 #include "horizontalcoordinategrid.h"
23 #include "localmeridiancomponent.h"
24 #include "ksasteroid.h"
25 #include "kscomet.h"
26 #include <kmessagebox.h>
27 #ifndef KSTARS_LITE
28 #include "kstars.h"
29 #endif
30 #include "kstarsdata.h"
31 #include "milkyway.h"
32 #include "satellitescomponent.h"
33 #include "skylabeler.h"
34 #include "skypainter.h"
35 #include "solarsystemcomposite.h"
36 #include "starcomponent.h"
37 #include "supernovaecomponent.h"
38 #include "targetlistcomponent.h"
39 #include "projections/projector.h"
40 #include "skyobjects/ksplanet.h"
41 #include "skyobjects/constellationsart.h"
42 
43 #ifndef KSTARS_LITE
44 #include "flagcomponent.h"
45 #include "ksutils.h"
46 #include "observinglist.h"
47 #include "skymap.h"
48 #include "hipscomponent.h"
49 #include "terraincomponent.h"
50 #endif
51 
52 #include <QApplication>
53 
54 #include <kstars_debug.h>
55 
SkyMapComposite(SkyComposite * parent)56 SkyMapComposite::SkyMapComposite(SkyComposite *parent)
57     : SkyComposite(parent), m_reindexNum(J2000)
58 {
59     m_skyLabeler.reset(SkyLabeler::Instance());
60     m_skyMesh = SkyMesh::Create(3); // level 5 mesh = 8192 trixels
61     m_skyMesh->debug(0);
62     //  1 => print "indexing ..."
63     //  2 => prints totals too
64     // 10 => prints detailed lists
65     // You can also set the debug level of individual
66     // appendLine() and appendPoly() calls.
67 
68     //Add all components
69     //Stars must come before constellation lines
70 #ifdef KSTARS_LITE
71     addComponent(m_MilkyWay = new MilkyWay(this), 50);
72     addComponent(m_Stars = StarComponent::Create(this), 10);
73     addComponent(m_EquatorialCoordinateGrid = new EquatorialCoordinateGrid(this));
74     addComponent(m_HorizontalCoordinateGrid = new HorizontalCoordinateGrid(this));
75 
76     // Do add to components.
77     addComponent(m_CBoundLines = new ConstellationBoundaryLines(this), 80);
78     m_Cultures.reset(new CultureList());
79     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()), 85);
80     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()), 90);
81     addComponent(m_Equator = new Equator(this), 95);
82     addComponent(m_Ecliptic = new Ecliptic(this), 95);
83     addComponent(m_Horizon = new HorizonComponent(this), 100);
84     addComponent(
85         m_ConstellationArt = new ConstellationArtComponent(this, m_Cultures.get()), 100);
86 
87     addComponent(m_ArtificialHorizon = new ArtificialHorizonComponent(this), 110);
88 
89     QStringList allcatalogs = Options::showCatalogNames();
90 
91     Options::setShowCatalogNames(allcatalogs);
92 
93     addComponent(m_SolarSystem = new SolarSystemComposite(this), 2);
94 
95     //addComponent( m_ObservingList = new TargetListComponent( this , 0, QPen(),
96     //                                                       &Options::obsListSymbol, &Options::obsListText ), 120 );
97     addComponent(m_StarHopRouteList = new TargetListComponent(this, 0, QPen()), 130);
98     addComponent(m_Satellites = new SatellitesComponent(this), 7);
99     addComponent(m_Supernovae = new SupernovaeComponent(this), 7);
100     SkyMapLite::Instance()->loadingFinished();
101 #else
102     addComponent(m_MilkyWay = new MilkyWay(this), 50);
103     addComponent(m_Stars = StarComponent::Create(this), 10);
104     addComponent(m_EquatorialCoordinateGrid = new EquatorialCoordinateGrid(this));
105     addComponent(m_HorizontalCoordinateGrid = new HorizontalCoordinateGrid(this));
106     addComponent(m_LocalMeridianComponent = new LocalMeridianComponent(this));
107 
108     // Do add to components.
109     addComponent(m_CBoundLines = new ConstellationBoundaryLines(this), 80);
110     m_Cultures.reset(new CultureList());
111     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()), 85);
112     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()), 90);
113     addComponent(m_Equator = new Equator(this), 95);
114     addComponent(m_Ecliptic = new Ecliptic(this), 95);
115     addComponent(m_Horizon = new HorizonComponent(this), 100);
116 
117     const auto &path = CatalogsDB::dso_db_path();
118     try
119     {
120         addComponent(m_Catalogs = new CatalogsComponent(this, path, !QFile::exists(path)),
121                      5);
122     }
123     catch (const CatalogsDB::DatabaseError &e)
124     {
125         KMessageBox::detailedError(nullptr, i18n("Failed to load the DSO database."),
126                                    e.what());
127 
128         const auto &backup_path =
129             QString("%1.%2").arg(path).arg(QDateTime::currentDateTime().toTime_t());
130 
131         const auto &answer = KMessageBox::questionYesNo(
132             nullptr,
133             i18n("Do you want to start over with an empty database?\n"
134                  "This will move the current DSO database \"%1\"\n"
135                  "to \"%2\"",
136                  path, backup_path),
137             "Start over?");
138 
139         if (answer == KMessageBox::Yes)
140         {
141             QFile::rename(path, backup_path);
142             addComponent(m_Catalogs = new CatalogsComponent(this, path, true), 5);
143         }
144         else
145         {
146             KStars::Instance()->close();
147         }
148     }
149 
150     addComponent(
151         m_ConstellationArt = new ConstellationArtComponent(this, m_Cultures.get()), 100);
152 
153     // Hips
154     addComponent(m_HiPS = new HIPSComponent(this));
155 
156     addComponent(m_Terrain = new TerrainComponent(this));
157 
158     addComponent(m_ArtificialHorizon = new ArtificialHorizonComponent(this), 110);
159 
160     addComponent(m_SolarSystem = new SolarSystemComposite(this), 2);
161 
162     addComponent(m_Flags = new FlagComponent(this), 4);
163 
164     addComponent(m_ObservingList = new TargetListComponent(this, nullptr, QPen(),
165                                                            &Options::obsListSymbol,
166                                                            &Options::obsListText),
167                  120);
168     addComponent(m_StarHopRouteList = new TargetListComponent(this, nullptr, QPen()),
169                  130);
170     addComponent(m_Satellites = new SatellitesComponent(this), 7);
171     addComponent(m_Supernovae = new SupernovaeComponent(this), 7);
172 #endif
173     connect(this, SIGNAL(progressText(QString)), KStarsData::Instance(),
174             SIGNAL(progressText(QString)));
175 }
176 
update(KSNumbers * num)177 void SkyMapComposite::update(KSNumbers *num)
178 {
179     //printf("updating SkyMapComposite\n");
180     //1. Milky Way
181     //m_MilkyWay->update( data, num );
182     //2. Coordinate grid
183     //m_EquatorialCoordinateGrid->update( num );
184     m_HorizontalCoordinateGrid->update(num);
185 #ifndef KSTARS_LITE
186     m_LocalMeridianComponent->update(num);
187 #endif
188     //3. Constellation boundaries
189     //m_CBounds->update( data, num );
190     //4. Constellation lines
191     //m_CLines->update( data, num );
192     //5. Constellation names
193     if (m_CNames)
194         m_CNames->update(num);
195     //6. Equator
196     //m_Equator->update( data, num );
197     //7. Ecliptic
198     //m_Ecliptic->update( data, num );
199     //8. Deep sky
200     //m_DeepSky->update( data, num );
201     //10. Stars
202     //m_Stars->update( data, num );
203     //m_CLines->update( data, num );  // MUST follow stars.
204 
205     //12. Solar system
206     m_SolarSystem->update(num);
207     //13. Satellites
208     m_Satellites->update(num);
209     //14. Supernovae
210     m_Supernovae->update(num);
211     //15. Horizon
212     m_Horizon->update(num);
213 #ifndef KSTARS_LITE
214     //16. Flags
215     m_Flags->update(num);
216 #endif
217 }
218 
updateSolarSystemBodies(KSNumbers * num)219 void SkyMapComposite::updateSolarSystemBodies(KSNumbers *num)
220 {
221     m_SolarSystem->updateSolarSystemBodies(num);
222 }
223 
updateMoons(KSNumbers * num)224 void SkyMapComposite::updateMoons(KSNumbers *num)
225 {
226     m_SolarSystem->updateMoons(num);
227 }
228 
229 //Reimplement draw function so that we have control over the order of
230 //elements, and we can add object labels
231 //
232 //The order in which components are drawn naturally determines the
233 //z-ordering (the layering) of the components.  Objects which
234 //should appear "behind" others should be drawn first.
draw(SkyPainter * skyp)235 void SkyMapComposite::draw(SkyPainter *skyp)
236 {
237     Q_UNUSED(skyp)
238 #ifndef KSTARS_LITE
239     SkyMap *map      = SkyMap::Instance();
240     KStarsData *data = KStarsData::Instance();
241 
242     // We delay one draw cycle before re-indexing
243     // we MUST ensure CLines do not get re-indexed while we use DRAW_BUF
244     // so we do it here.
245     m_CLines->reindex(&m_reindexNum);
246     // This queues re-indexing for the next draw cycle
247     m_reindexNum = KSNumbers(data->updateNum()->julianDay());
248 
249     // This ensures that the JIT updates are synchronized for the entire draw
250     // cycle so the sky moves as a single sheet.  May not be needed.
251     data->syncUpdateIDs();
252 
253     // prepare the aperture
254     // FIXME_FOV: We may want to rejigger this to allow
255     // wide-angle views --hdevalence
256     float radius = map->projector()->fov();
257     if (radius > 180.0)
258         radius = 180.0;
259 
260     if (m_skyMesh->inDraw())
261     {
262         printf("Warning: aborting concurrent SkyMapComposite::draw()\n");
263         return;
264     }
265 
266     m_skyMesh->inDraw(true);
267     SkyPoint *focus = map->focus();
268     m_skyMesh->aperture(focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing
269 
270     // create the no-precess aperture if needed
271     if (Options::showEquatorialGrid() || Options::showHorizontalGrid() ||
272         Options::showCBounds() || Options::showEquator())
273     {
274         m_skyMesh->index(focus, radius + 1.0, NO_PRECESS_BUF);
275     }
276 
277     // clear marks from old labels and prep fonts
278     m_skyLabeler->reset(map);
279     m_skyLabeler->useStdFont();
280 
281     // info boxes have highest label priority
282     // FIXME: REGRESSION. Labeler now know nothing about infoboxes
283     // map->infoBoxes()->reserveBoxes( psky );
284 
285     // JM 2016-12-01: Why is this done this way?!! It's too inefficient
286     if (KStars::Instance())
287     {
288         auto &obsList = KStarsData::Instance()->observingList()->sessionList();
289 
290         if (Options::obsListText())
291             for (auto &obj_clone : obsList)
292             {
293                 // Find the "original" obj
294                 SkyObject *o = findByName(
295                     obj_clone->name()); // FIXME: This is slow.... and can also fail!!!
296                 if (!o)
297                     continue;
298                 SkyLabeler::AddLabel(o, SkyLabeler::RUDE_LABEL);
299             }
300     }
301 
302     m_MilkyWay->draw(skyp);
303 
304     // Draw HIPS after milky way but before everything else
305     m_HiPS->draw(skyp);
306 
307     m_EquatorialCoordinateGrid->draw(skyp);
308     m_HorizontalCoordinateGrid->draw(skyp);
309     m_LocalMeridianComponent->draw(skyp);
310 
311     //Draw constellation boundary lines only if we draw western constellations
312     if (m_Cultures->current() == "Western")
313     {
314         m_CBoundLines->draw(skyp);
315         m_ConstellationArt->draw(skyp);
316     }
317     else if (m_Cultures->current() == "Inuit")
318     {
319         m_ConstellationArt->draw(skyp);
320     }
321 
322     m_CLines->draw(skyp);
323 
324     m_Equator->draw(skyp);
325 
326     m_Ecliptic->draw(skyp);
327 
328     m_Catalogs->draw(skyp);
329 
330     m_Stars->draw(skyp);
331 
332     m_SolarSystem->drawTrails(skyp);
333     m_SolarSystem->draw(skyp);
334 
335     m_Satellites->draw(skyp);
336 
337     m_Supernovae->draw(skyp);
338 
339     map->drawObjectLabels(labelObjects());
340 
341     m_skyLabeler->drawQueuedLabels();
342     m_CNames->draw(skyp);
343     m_Stars->drawLabels();
344 
345     m_ObservingList->pen =
346         QPen(QColor(data->colorScheme()->colorNamed("ObsListColor")), 1.);
347     m_ObservingList->list2 = KStarsData::Instance()->observingList()->sessionList();
348     m_ObservingList->draw(skyp);
349 
350     m_Flags->draw(skyp);
351 
352     m_StarHopRouteList->pen =
353         QPen(QColor(data->colorScheme()->colorNamed("StarHopRouteColor")), 1.);
354     m_StarHopRouteList->draw(skyp);
355 
356     m_ArtificialHorizon->draw(skyp);
357 
358     m_Horizon->draw(skyp);
359 
360     m_skyMesh->inDraw(false);
361 
362     // Draw terrain at the end.
363     m_Terrain->draw(skyp);
364 
365     // DEBUG Edit. Keywords: Trixel boundaries. Currently works only in QPainter mode
366     // -jbb uncomment these to see trixel outlines:
367     /*
368         QPainter *psky = dynamic_cast< QPainter *>( skyp );
369         if( psky ) {
370             qCDebug(KSTARS) << "Drawing trixel boundaries for debugging.";
371             psky->setPen(  QPen( QBrush( QColor( "yellow" ) ), 1, Qt::SolidLine ) );
372             m_skyMesh->draw( *psky, OBJ_NEAREST_BUF );
373             SkyMesh *p;
374             if( p = SkyMesh::Instance( 6 ) ) {
375                 qCDebug(KSTARS) << "We have a deep sky mesh to draw";
376                 p->draw( *psky, OBJ_NEAREST_BUF );
377             }
378 
379             psky->setPen( QPen( QBrush( QColor( "green" ) ), 1, Qt::SolidLine ) );
380             m_skyMesh->draw( *psky, NO_PRECESS_BUF );
381             if( p )
382                 p->draw( *psky, NO_PRECESS_BUF );
383         }
384         */
385 #endif
386 }
387 
388 //Select nearest object to the given skypoint, but give preference
389 //to certain object types.
390 //we multiply each object type's smallest angular distance by the
391 //following factors before selecting the final nearest object:
392 // faint stars > 12th mag = 1.75
393 // stars > 4 and < 12 = 1.5
394 // stars brighter than 4th mag = 0.75
395 // custom object = 0.5
396 // Solar system = 0.25
objectNearest(SkyPoint * p,double & maxrad)397 SkyObject *SkyMapComposite::objectNearest(SkyPoint *p, double &maxrad)
398 {
399     double rTry      = maxrad;
400     double rBest     = maxrad;
401     SkyObject *oTry  = nullptr;
402     SkyObject *oBest = nullptr;
403 
404     //printf("%.1f %.1f\n", p->ra().Degrees(), p->dec().Degrees() );
405     m_skyMesh->aperture(p, maxrad + 1.0, OBJ_NEAREST_BUF);
406 
407     oBest = m_Stars->objectNearest(p, rBest);
408     //reduce rBest by 0.75 for stars brighter than 4th mag
409     if (oBest && oBest->mag() < 4.0)
410         rBest *= 0.75;
411     // For stars fainter than 12th mag
412     else if (oBest && oBest->mag() > 12.0)
413         rBest *= 1.75;
414     // For stars between 4th and 12th mag
415     else if (oBest)
416         rBest *= 1.5;
417 
418     oTry = m_Satellites->objectNearest(p, rTry);
419     if (rTry < rBest)
420     {
421         rBest = rTry;
422         oBest = oTry;
423     }
424 
425     for (auto &star : m_DeepStars)
426     {
427         rTry = maxrad;
428         oTry = star->objectNearest(p, rTry);
429         if (rTry < rBest)
430         {
431             rBest = rTry;
432             oBest = oTry;
433         }
434     }
435 
436     // TODO: Add support for deep star catalogs
437     rTry = rBest;
438     oTry = m_Catalogs->objectNearest(p, rTry);
439     if (oTry && rTry < rBest)
440     {
441         rBest = rTry;
442         oBest = oTry;
443     }
444 
445     rTry = maxrad;
446     oTry = m_Supernovae->objectNearest(p, rTry);
447     //qCDebug(KSTARS)<<rTry<<rBest<<maxrad;
448     if (rTry < rBest)
449     {
450         rBest = rTry;
451         oBest = oTry;
452     }
453 
454     rTry = maxrad;
455     oTry = m_SolarSystem->objectNearest(p, rTry);
456     if (!dynamic_cast<KSComet *>(oTry) &&
457         !dynamic_cast<KSAsteroid *>(
458             oTry)) // There are gazillions of faint asteroids and comets; we want to prevent them from getting precedence
459     {
460         rTry *=
461             0.25; // this is either sun, moon, or one of the major planets or their moons.
462     }
463     else
464     {
465         if (std::isfinite(oTry->mag()) && oTry->mag() < 12.0)
466         {
467             rTry *= 0.75; // Bright comets / asteroids get some precedence.
468         }
469     }
470     if (rTry < rBest)
471     {
472         rBest = rTry;
473         oBest = oTry;
474     }
475 
476     //if ( oBest && Options::verboseLogging())
477     //qCDebug(KSTARS) << "OBEST=" << oBest->name() << " - " << oBest->name2();
478     maxrad = rBest;
479     return oBest; //will be 0 if no object nearer than maxrad was found
480 }
481 
starNearest(SkyPoint * p,double & maxrad)482 SkyObject *SkyMapComposite::starNearest(SkyPoint *p, double &maxrad)
483 {
484     double rtry     = maxrad;
485     SkyObject *star = nullptr;
486 
487     m_skyMesh->aperture(p, maxrad + 1.0, OBJ_NEAREST_BUF);
488 
489     star = m_Stars->objectNearest(p, rtry);
490     //reduce rBest by 0.75 for stars brighter than 4th mag
491     if (star && star->mag() < 4.0)
492         rtry *= 0.75;
493 
494     // TODO: Add Deep Star Catalog support
495 
496     maxrad = rtry;
497     return star;
498 }
499 
addNameLabel(SkyObject * o)500 bool SkyMapComposite::addNameLabel(SkyObject *o)
501 {
502     if (!o)
503         return false;
504     labelObjects().append(o);
505     return true;
506 }
507 
removeNameLabel(SkyObject * o)508 bool SkyMapComposite::removeNameLabel(SkyObject *o)
509 {
510     if (!o)
511         return false;
512     int index = labelObjects().indexOf(o);
513     if (index < 0)
514         return false;
515     labelObjects().removeAt(index);
516     return true;
517 }
518 
getObjectNames()519 QHash<int, QStringList> &SkyMapComposite::getObjectNames()
520 {
521     return m_ObjectNames;
522 }
523 
getObjectLists()524 QHash<int, QVector<QPair<QString, const SkyObject *>>> &SkyMapComposite::getObjectLists()
525 {
526     return m_ObjectLists;
527 }
528 
findObjectsInArea(const SkyPoint & p1,const SkyPoint & p2)529 QList<SkyObject *> SkyMapComposite::findObjectsInArea(const SkyPoint &p1,
530                                                       const SkyPoint &p2)
531 {
532     const SkyRegion &region = m_skyMesh->skyRegion(p1, p2);
533     QList<SkyObject *> list;
534     // call objectsInArea( QList<SkyObject*>&, const SkyRegion& ) for each of the
535     // components of the SkyMapComposite
536     if (m_Stars->selected())
537         m_Stars->objectsInArea(list, region);
538     if (m_Catalogs->selected())
539         m_Catalogs->objectsInArea(list, region);
540     return list;
541 }
542 
findByName(const QString & name)543 SkyObject *SkyMapComposite::findByName(const QString &name)
544 {
545 #ifndef KSTARS_LITE
546     if (KStars::Closing)
547         return nullptr;
548 #endif
549 
550     //We search the children in an "intelligent" order (most-used
551     //object types first), in order to avoid wasting too much time
552     //looking for a match.  The most important part of this ordering
553     //is that stars should be last (because the stars list is so long)
554     SkyObject *o = nullptr;
555     o            = m_SolarSystem->findByName(name);
556     if (o)
557         return o;
558     o = m_Catalogs->findByName(name);
559     if (o)
560         return o;
561     o = m_CNames->findByName(name);
562     if (o)
563         return o;
564     o = m_Stars->findByName(name);
565     if (o)
566         return o;
567     o = m_Supernovae->findByName(name);
568     if (o)
569         return o;
570     o = m_Satellites->findByName(name);
571     if (o)
572         return o;
573 
574     return nullptr;
575 }
576 
findStarByGenetiveName(const QString name)577 SkyObject *SkyMapComposite::findStarByGenetiveName(const QString name)
578 {
579     return m_Stars->findStarByGenetiveName(name);
580 }
581 
planet(int n)582 KSPlanetBase *SkyMapComposite::planet(int n)
583 {
584     if (n == KSPlanetBase::SUN)
585         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Sun"))));
586     if (n == KSPlanetBase::MERCURY)
587         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Mercury"))));
588     if (n == KSPlanetBase::VENUS)
589         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Venus"))));
590     if (n == KSPlanetBase::MOON)
591         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Moon"))));
592     if (n == KSPlanetBase::MARS)
593         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Mars"))));
594     if (n == KSPlanetBase::JUPITER)
595         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Jupiter"))));
596     if (n == KSPlanetBase::SATURN)
597         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Saturn"))));
598     if (n == KSPlanetBase::URANUS)
599         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Uranus"))));
600     if (n == KSPlanetBase::NEPTUNE)
601         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Neptune"))));
602     //if ( n == KSPlanetBase::PLUTO ) return (KSPlanetBase*)(m_SolarSystem->findByName( i18n( "Pluto" ) ) );
603 
604     return nullptr;
605 }
606 
reloadCLines()607 void SkyMapComposite::reloadCLines()
608 {
609 #ifndef KSTARS_LITE
610     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
611     SkyMapDrawAbstract::setDrawLock(
612         true); // This is not (yet) multithreaded, so I think we don't have to worry about overwriting the state of an existing lock --asimha
613     removeComponent(m_CLines);
614     delete m_CLines;
615     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()));
616     SkyMapDrawAbstract::setDrawLock(false);
617 #endif
618 }
619 
reloadCNames()620 void SkyMapComposite::reloadCNames()
621 {
622     //     Q_ASSERT( !SkyMapDrawAbstract::drawLock() );
623     //     SkyMapDrawAbstract::setDrawLock( true ); // This is not (yet) multithreaded, so I think we don't have to worry about overwriting the state of an existing lock --asimha
624     //     objectNames(SkyObject::CONSTELLATION).clear();
625     //     delete m_CNames;
626     //     m_CNames = 0;
627     //     m_CNames = new ConstellationNamesComponent( this, m_Cultures.get() );
628     //     SkyMapDrawAbstract::setDrawLock( false );
629     objectNames(SkyObject::CONSTELLATION).clear();
630     objectLists(SkyObject::CONSTELLATION).clear();
631     removeComponent(m_CNames);
632     delete m_CNames;
633     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()));
634 }
635 
reloadConstellationArt()636 void SkyMapComposite::reloadConstellationArt()
637 {
638 #ifndef KSTARS_LITE
639     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
640     SkyMapDrawAbstract::setDrawLock(true);
641     removeComponent(m_ConstellationArt);
642     delete m_ConstellationArt;
643     addComponent(m_ConstellationArt =
644                      new ConstellationArtComponent(this, m_Cultures.get()));
645     SkyMapDrawAbstract::setDrawLock(false);
646 #endif
647 }
648 
reloadDeepSky()649 void SkyMapComposite::reloadDeepSky()
650 {
651 #ifndef KSTARS_LITE
652     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
653 
654     // Deselect object if selected! If not deselected then InfoBox tries to
655     // get the name of an object which may not exist (getLongName)
656     // FIXME (spacetime): Is there a better way?
657     // Current Solution: Look for the nearest star in the region and select it.
658 
659     SkyMap *current_map   = KStars::Instance()->map();
660     double maxrad         = 30.0;
661     SkyPoint center_point = current_map->getCenterPoint();
662 
663     current_map->setClickedObject(
664         KStars::Instance()->data()->skyComposite()->starNearest(&center_point, maxrad));
665     current_map->setClickedPoint(current_map->clickedObject());
666     current_map->slotCenter();
667 
668     // Remove and Regenerate set of catalog objects
669     //
670     // FIXME: Why should we do this? Because it messes up observing
671     // list really bad to delete and regenerate SkyObjects.
672     SkyMapDrawAbstract::setDrawLock(true);
673 
674     // FIXME: We should also reload anything that refers to SkyObject
675     // * in memory, because all the old SkyObjects are now gone! This
676     // includes the observing list. Otherwise, expect a bad, bad crash
677     // that is hard to debug! -- AS
678     m_Catalogs->dropCache();
679     SkyMapDrawAbstract::setDrawLock(false);
680 #endif
681 }
682 
isLocalCNames()683 bool SkyMapComposite::isLocalCNames()
684 {
685     return m_CNames->isLocalCNames();
686 }
687 
emitProgressText(const QString & message)688 void SkyMapComposite::emitProgressText(const QString &message)
689 {
690     emit progressText(message);
691 #ifndef Q_OS_ANDROID
692     //Can cause crashes on Android, investigate it
693     qApp->processEvents(); // -jbb: this seemed to make it work.
694 #endif
695     //qCDebug(KSTARS) << QString("PROGRESS TEXT: %1\n").arg( message );
696 }
697 
constellationNames() const698 const QList<SkyObject *> &SkyMapComposite::constellationNames() const
699 {
700     return m_CNames->objectList();
701 }
702 
703 // Returns only named stars, and should not be used
stars() const704 const QList<SkyObject *> &SkyMapComposite::stars() const
705 {
706     return m_Stars->objectList();
707 }
708 
asteroids() const709 const QList<SkyObject *> &SkyMapComposite::asteroids() const
710 {
711     return m_SolarSystem->asteroids();
712 }
713 
comets() const714 const QList<SkyObject *> &SkyMapComposite::comets() const
715 {
716     return m_SolarSystem->comets();
717 }
718 
supernovae() const719 const QList<SkyObject *> &SkyMapComposite::supernovae() const
720 {
721     return m_Supernovae->objectList();
722 }
723 
planets()724 QList<SkyObject *> SkyMapComposite::planets()
725 {
726     return solarSystemComposite()->planetObjects();
727 }
728 
729 //Store it permanently
730 /*
731 QList<SkyObject*> SkyMapComposite::moons()
732 {
733     QList<SkyObject*> skyObjects;
734     foreach(PlanetMoonsComponent *pMoons, m_SolarSystem->planetMoonsComponent()) {
735         PlanetMoons *moons = pMoons->getMoons();
736         for(int i = 0; i < moons->nMoons(); ++i) {
737             skyObjects.append(moons->moon(i));
738         }
739     }
740     return skyObjects;
741 }
742 */
743 
getSkyObjectsList(SkyObject::TYPE t)744 const QList<SkyObject *> *SkyMapComposite::getSkyObjectsList(SkyObject::TYPE t)
745 {
746     switch (t)
747     {
748         case SkyObject::STAR:
749             return &m_Stars->objectList();
750         case SkyObject::CATALOG_STAR:
751             return nullptr;
752         case SkyObject::PLANET:
753             return &m_SolarSystem->planetObjects();
754         case SkyObject::COMET:
755             return &comets();
756         case SkyObject::ASTEROID:
757             return &asteroids();
758         case SkyObject::MOON:
759             return &m_SolarSystem->moons();
760         case SkyObject::GALAXY:
761         case SkyObject::PLANETARY_NEBULA:
762         case SkyObject::GASEOUS_NEBULA:
763         case SkyObject::GLOBULAR_CLUSTER:
764         case SkyObject::OPEN_CLUSTER:
765             return nullptr;
766         case SkyObject::CONSTELLATION:
767             return &constellationNames();
768         case SkyObject::SUPERNOVA:
769             return &supernovae();
770         default:
771             return nullptr;
772     }
773     //return nullptr;
774 }
775 
earth()776 KSPlanet *SkyMapComposite::earth()
777 {
778     return m_SolarSystem->earth();
779 }
780 
getCultureNames()781 QStringList SkyMapComposite::getCultureNames()
782 {
783     return m_Cultures->getNames();
784 }
785 
getCultureName(int index)786 QString SkyMapComposite::getCultureName(int index)
787 {
788     return m_Cultures->getName(index);
789 }
790 
setCurrentCulture(QString culture)791 void SkyMapComposite::setCurrentCulture(QString culture)
792 {
793     m_Cultures->setCurrent(culture);
794 }
795 
currentCulture()796 QString SkyMapComposite::currentCulture()
797 {
798     return m_Cultures->current();
799 }
800 #ifndef KSTARS_LITE
flags()801 FlagComponent *SkyMapComposite::flags()
802 {
803     return m_Flags;
804 }
805 #endif
806 
satellites()807 SatellitesComponent *SkyMapComposite::satellites()
808 {
809     return m_Satellites;
810 }
811 
supernovaeComponent()812 SupernovaeComponent *SkyMapComposite::supernovaeComponent()
813 {
814     return m_Supernovae;
815 }
816 
artificialHorizon()817 ArtificialHorizonComponent *SkyMapComposite::artificialHorizon()
818 {
819     return m_ArtificialHorizon;
820 }
821