File indexing completed on 2024-07-14 07:17:23

0001 /*
0002     SPDX-FileCopyrightText: 2005 Thomas Kabelmann <thomas.kabelmann@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "skymapcomposite.h"
0008 
0009 #include "artificialhorizoncomponent.h"
0010 #include "catalogsdb.h"
0011 #include "constellationartcomponent.h"
0012 #include "constellationboundarylines.h"
0013 #include "constellationlines.h"
0014 #include "constellationnamescomponent.h"
0015 #include "culturelist.h"
0016 #include "deepstarcomponent.h"
0017 #include "catalogscomponent.h"
0018 #include "ecliptic.h"
0019 #include "equator.h"
0020 #include "equatorialcoordinategrid.h"
0021 #include "horizoncomponent.h"
0022 #include "horizontalcoordinategrid.h"
0023 #include "localmeridiancomponent.h"
0024 #include "ksasteroid.h"
0025 #include "kscomet.h"
0026 #include <kmessagebox.h>
0027 #ifndef KSTARS_LITE
0028 #include "kstars.h"
0029 #endif
0030 #include "kstarsdata.h"
0031 #include "milkyway.h"
0032 #include "satellitescomponent.h"
0033 #include "skylabeler.h"
0034 #include "skypainter.h"
0035 #include "solarsystemcomposite.h"
0036 #include "starcomponent.h"
0037 #include "supernovaecomponent.h"
0038 #include "targetlistcomponent.h"
0039 #include "projections/projector.h"
0040 #include "skyobjects/ksplanet.h"
0041 #include "skyobjects/constellationsart.h"
0042 
0043 #ifndef KSTARS_LITE
0044 #include "flagcomponent.h"
0045 #include "ksutils.h"
0046 #include "observinglist.h"
0047 #include "skymap.h"
0048 #include "hipscomponent.h"
0049 #include "terraincomponent.h"
0050 #include "imageoverlaycomponent.h"
0051 #include "mosaiccomponent.h"
0052 #endif
0053 
0054 #include <QApplication>
0055 
0056 #include <kstars_debug.h>
0057 
0058 SkyMapComposite::SkyMapComposite(SkyComposite *parent)
0059     : SkyComposite(parent), m_reindexNum(J2000)
0060 {
0061     m_skyLabeler.reset(SkyLabeler::Instance());
0062     m_skyMesh = SkyMesh::Create(3); // level 5 mesh = 8192 trixels
0063     m_skyMesh->debug(0);
0064     //  1 => print "indexing ..."
0065     //  2 => prints totals too
0066     // 10 => prints detailed lists
0067     // You can also set the debug level of individual
0068     // appendLine() and appendPoly() calls.
0069 
0070     //Add all components
0071     //Stars must come before constellation lines
0072 #ifdef KSTARS_LITE
0073     addComponent(m_MilkyWay = new MilkyWay(this), 50);
0074     addComponent(m_Stars = StarComponent::Create(this), 10);
0075     addComponent(m_EquatorialCoordinateGrid = new EquatorialCoordinateGrid(this));
0076     addComponent(m_HorizontalCoordinateGrid = new HorizontalCoordinateGrid(this));
0077 
0078     // Do add to components.
0079     addComponent(m_CBoundLines = new ConstellationBoundaryLines(this), 80);
0080     m_Cultures.reset(new CultureList());
0081     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()), 85);
0082     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()), 90);
0083     addComponent(m_Equator = new Equator(this), 95);
0084     addComponent(m_Ecliptic = new Ecliptic(this), 95);
0085     addComponent(m_Horizon = new HorizonComponent(this), 100);
0086     addComponent(
0087         m_ConstellationArt = new ConstellationArtComponent(this, m_Cultures.get()), 100);
0088 
0089     addComponent(m_ArtificialHorizon = new ArtificialHorizonComponent(this), 110);
0090 
0091     QStringList allcatalogs = Options::showCatalogNames();
0092 
0093     Options::setShowCatalogNames(allcatalogs);
0094 
0095     addComponent(m_SolarSystem = new SolarSystemComposite(this), 2);
0096 
0097     //addComponent( m_ObservingList = new TargetListComponent( this , 0, QPen(),
0098     //                                                       &Options::obsListSymbol, &Options::obsListText ), 120 );
0099     addComponent(m_StarHopRouteList = new TargetListComponent(this, 0, QPen()), 130);
0100     addComponent(m_Satellites = new SatellitesComponent(this), 7);
0101     addComponent(m_Supernovae = new SupernovaeComponent(this), 7);
0102     SkyMapLite::Instance()->loadingFinished();
0103 #else
0104     addComponent(m_MilkyWay = new MilkyWay(this), 50);
0105     addComponent(m_Stars = StarComponent::Create(this), 10);
0106     addComponent(m_EquatorialCoordinateGrid = new EquatorialCoordinateGrid(this));
0107     addComponent(m_HorizontalCoordinateGrid = new HorizontalCoordinateGrid(this));
0108     addComponent(m_LocalMeridianComponent = new LocalMeridianComponent(this));
0109 
0110     // Do add to components.
0111     addComponent(m_CBoundLines = new ConstellationBoundaryLines(this), 80);
0112     m_Cultures.reset(new CultureList());
0113     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()), 85);
0114     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()), 90);
0115     addComponent(m_Equator = new Equator(this), 95);
0116     addComponent(m_Ecliptic = new Ecliptic(this), 95);
0117     addComponent(m_Horizon = new HorizonComponent(this), 100);
0118 
0119     const auto &path = CatalogsDB::dso_db_path();
0120     try
0121     {
0122         addComponent(m_Catalogs = new CatalogsComponent(this, path, !QFile::exists(path)),
0123                      5);
0124     }
0125     catch (const CatalogsDB::DatabaseError &e)
0126     {
0127         KMessageBox::detailedError(nullptr, i18n("Failed to load the DSO database."),
0128                                    e.what());
0129 
0130         const auto &backup_path =
0131             QString("%1.%2").arg(path).arg(QDateTime::currentDateTime().toTime_t());
0132 
0133         const auto &answer = KMessageBox::questionYesNo(
0134                                  nullptr,
0135                                  i18n("Do you want to start over with an empty database?\n"
0136                                       "This will move the current DSO database \"%1\"\n"
0137                                       "to \"%2\"",
0138                                       path, backup_path),
0139                                  "Start over?");
0140 
0141         if (answer == KMessageBox::Yes)
0142         {
0143             QFile::rename(path, backup_path);
0144             addComponent(m_Catalogs = new CatalogsComponent(this, path, true), 5);
0145         }
0146         else
0147         {
0148             KStars::Instance()->close();
0149         }
0150     }
0151 
0152     addComponent(
0153         m_ConstellationArt = new ConstellationArtComponent(this, m_Cultures.get()), 100);
0154 
0155     // Hips
0156     addComponent(m_HiPS = new HIPSComponent(this));
0157 
0158     addComponent(m_Terrain = new TerrainComponent(this));
0159 
0160     addComponent(m_ImageOverlay = new ImageOverlayComponent(this));
0161 
0162     // Mosaic Component
0163 #ifdef HAVE_INDI
0164     addComponent(m_Mosaic = new MosaicComponent(this));
0165 #endif
0166 
0167     addComponent(m_ArtificialHorizon = new ArtificialHorizonComponent(this), 110);
0168 
0169     addComponent(m_SolarSystem = new SolarSystemComposite(this), 2);
0170 
0171     addComponent(m_Flags = new FlagComponent(this), 4);
0172 
0173     addComponent(m_ObservingList = new TargetListComponent(this, nullptr, QPen(),
0174             &Options::obsListSymbol,
0175             &Options::obsListText),
0176                  120);
0177     addComponent(m_StarHopRouteList = new TargetListComponent(this, nullptr, QPen()),
0178                  130);
0179     addComponent(m_Satellites = new SatellitesComponent(this), 7);
0180     addComponent(m_Supernovae = new SupernovaeComponent(this), 7);
0181 #endif
0182     connect(this, SIGNAL(progressText(QString)), KStarsData::Instance(),
0183             SIGNAL(progressText(QString)));
0184 }
0185 
0186 void SkyMapComposite::update(KSNumbers *num)
0187 {
0188     //printf("updating SkyMapComposite\n");
0189     //1. Milky Way
0190     //m_MilkyWay->update( data, num );
0191     //2. Coordinate grid
0192     //m_EquatorialCoordinateGrid->update( num );
0193     m_HorizontalCoordinateGrid->update(num);
0194 #ifndef KSTARS_LITE
0195     m_LocalMeridianComponent->update(num);
0196 #endif
0197     //3. Constellation boundaries
0198     //m_CBounds->update( data, num );
0199     //4. Constellation lines
0200     //m_CLines->update( data, num );
0201     //5. Constellation names
0202     if (m_CNames)
0203         m_CNames->update(num);
0204     //6. Equator
0205     //m_Equator->update( data, num );
0206     //7. Ecliptic
0207     //m_Ecliptic->update( data, num );
0208     //8. Deep sky
0209     //m_DeepSky->update( data, num );
0210     //10. Stars
0211     //m_Stars->update( data, num );
0212     //m_CLines->update( data, num );  // MUST follow stars.
0213 
0214     //12. Solar system
0215     m_SolarSystem->update(num);
0216     //13. Satellites
0217     m_Satellites->update(num);
0218     //14. Supernovae
0219     m_Supernovae->update(num);
0220     //15. Horizon
0221     m_Horizon->update(num);
0222 #ifndef KSTARS_LITE
0223     //16. Flags
0224     m_Flags->update(num);
0225 #endif
0226 }
0227 
0228 void SkyMapComposite::updateSolarSystemBodies(KSNumbers *num)
0229 {
0230     m_SolarSystem->updateSolarSystemBodies(num);
0231 }
0232 
0233 void SkyMapComposite::updateMoons(KSNumbers *num)
0234 {
0235     m_SolarSystem->updateMoons(num);
0236 }
0237 
0238 //Reimplement draw function so that we have control over the order of
0239 //elements, and we can add object labels
0240 //
0241 //The order in which components are drawn naturally determines the
0242 //z-ordering (the layering) of the components.  Objects which
0243 //should appear "behind" others should be drawn first.
0244 void SkyMapComposite::draw(SkyPainter *skyp)
0245 {
0246     Q_UNUSED(skyp)
0247 #ifndef KSTARS_LITE
0248     SkyMap *map      = SkyMap::Instance();
0249     KStarsData *data = KStarsData::Instance();
0250 
0251     // We delay one draw cycle before re-indexing
0252     // we MUST ensure CLines do not get re-indexed while we use DRAW_BUF
0253     // so we do it here.
0254     m_CLines->reindex(&m_reindexNum);
0255     // This queues re-indexing for the next draw cycle
0256     m_reindexNum = KSNumbers(data->updateNum()->julianDay());
0257 
0258     // This ensures that the JIT updates are synchronized for the entire draw
0259     // cycle so the sky moves as a single sheet.  May not be needed.
0260     data->syncUpdateIDs();
0261 
0262     // prepare the aperture
0263     // FIXME_FOV: We may want to rejigger this to allow
0264     // wide-angle views --hdevalence
0265     float radius = map->projector()->fov();
0266     if (radius > 180.0)
0267         radius = 180.0;
0268 
0269     if (m_skyMesh->inDraw())
0270     {
0271         printf("Warning: aborting concurrent SkyMapComposite::draw()\n");
0272         return;
0273     }
0274 
0275     m_skyMesh->inDraw(true);
0276     SkyPoint *focus = map->focus();
0277     m_skyMesh->aperture(focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing
0278 
0279     // create the no-precess aperture if needed
0280     if (Options::showEquatorialGrid() || Options::showHorizontalGrid() ||
0281             Options::showCBounds() || Options::showEquator())
0282     {
0283         m_skyMesh->index(focus, radius + 1.0, NO_PRECESS_BUF);
0284     }
0285 
0286     // clear marks from old labels and prep fonts
0287     m_skyLabeler->reset(map);
0288     m_skyLabeler->useStdFont();
0289 
0290     // info boxes have highest label priority
0291     // FIXME: REGRESSION. Labeler now know nothing about infoboxes
0292     // map->infoBoxes()->reserveBoxes( psky );
0293 
0294     // JM 2016-12-01: Why is this done this way?!! It's too inefficient
0295     if (KStars::Instance())
0296     {
0297         auto &obsList = KStarsData::Instance()->observingList()->sessionList();
0298 
0299         if (Options::obsListText())
0300             for (auto &obj_clone : obsList)
0301             {
0302                 // Find the "original" obj
0303                 SkyObject *o = findByName(
0304                                    obj_clone->name()); // FIXME: This is slow.... and can also fail!!!
0305                 if (!o)
0306                     continue;
0307                 SkyLabeler::AddLabel(o, SkyLabeler::RUDE_LABEL);
0308             }
0309     }
0310 
0311     m_MilkyWay->draw(skyp);
0312 
0313     // Draw HIPS after milky way but before everything else
0314     m_HiPS->draw(skyp);
0315 
0316     m_EquatorialCoordinateGrid->draw(skyp);
0317     m_HorizontalCoordinateGrid->draw(skyp);
0318     m_LocalMeridianComponent->draw(skyp);
0319 
0320     //Draw constellation boundary lines only if we draw western constellations
0321     if (m_Cultures->current() == "Western")
0322     {
0323         m_CBoundLines->draw(skyp);
0324         m_ConstellationArt->draw(skyp);
0325     }
0326     else if (m_Cultures->current() == "Inuit")
0327     {
0328         m_ConstellationArt->draw(skyp);
0329     }
0330 
0331     m_CLines->draw(skyp);
0332 
0333     m_Equator->draw(skyp);
0334 
0335     m_Ecliptic->draw(skyp);
0336 
0337     m_Catalogs->draw(skyp);
0338 
0339     m_Stars->draw(skyp);
0340 
0341     m_SolarSystem->drawTrails(skyp);
0342     m_SolarSystem->draw(skyp);
0343 
0344     m_Satellites->draw(skyp);
0345 
0346     m_Supernovae->draw(skyp);
0347 
0348     map->drawObjectLabels(labelObjects());
0349 
0350     m_skyLabeler->drawQueuedLabels();
0351     m_CNames->draw(skyp);
0352     m_Stars->drawLabels();
0353 
0354     m_ObservingList->pen =
0355         QPen(QColor(data->colorScheme()->colorNamed("ObsListColor")), 1.);
0356     m_ObservingList->list2 = KStarsData::Instance()->observingList()->sessionList();
0357     m_ObservingList->draw(skyp);
0358 
0359     m_Flags->draw(skyp);
0360 
0361     m_StarHopRouteList->pen =
0362         QPen(QColor(data->colorScheme()->colorNamed("StarHopRouteColor")), 1.);
0363     m_StarHopRouteList->draw(skyp);
0364 
0365     // Draw fits overlay before mosaic and terrain/horizon, but after most things.
0366     m_ImageOverlay->draw(skyp);
0367 
0368 #ifdef HAVE_INDI
0369     m_Mosaic->draw(skyp);
0370 #endif
0371 
0372     m_ArtificialHorizon->draw(skyp);
0373 
0374     m_Horizon->draw(skyp);
0375 
0376     m_skyMesh->inDraw(false);
0377 
0378     // Draw terrain at the end.
0379     m_Terrain->draw(skyp);
0380 
0381     // DEBUG Edit. Keywords: Trixel boundaries. Currently works only in QPainter mode
0382     // -jbb uncomment these to see trixel outlines:
0383     /*
0384         QPainter *psky = dynamic_cast< QPainter *>( skyp );
0385         if( psky ) {
0386             qCDebug(KSTARS) << "Drawing trixel boundaries for debugging.";
0387             psky->setPen(  QPen( QBrush( QColor( "yellow" ) ), 1, Qt::SolidLine ) );
0388             m_skyMesh->draw( *psky, OBJ_NEAREST_BUF );
0389             SkyMesh *p;
0390             if( p = SkyMesh::Instance( 6 ) ) {
0391                 qCDebug(KSTARS) << "We have a deep sky mesh to draw";
0392                 p->draw( *psky, OBJ_NEAREST_BUF );
0393             }
0394 
0395             psky->setPen( QPen( QBrush( QColor( "green" ) ), 1, Qt::SolidLine ) );
0396             m_skyMesh->draw( *psky, NO_PRECESS_BUF );
0397             if( p )
0398                 p->draw( *psky, NO_PRECESS_BUF );
0399         }
0400         */
0401 #endif
0402 }
0403 
0404 //Select nearest object to the given skypoint, but give preference
0405 //to certain object types.
0406 //we multiply each object type's smallest angular distance by the
0407 //following factors before selecting the final nearest object:
0408 // faint stars > 12th mag = 1.75
0409 // stars > 4 and < 12 = 1.5
0410 // stars brighter than 4th mag = 0.75
0411 // custom object = 0.5
0412 // Solar system = 0.25
0413 SkyObject *SkyMapComposite::objectNearest(SkyPoint *p, double &maxrad)
0414 {
0415     double rTry      = maxrad;
0416     double rBest     = maxrad;
0417     SkyObject *oTry  = nullptr;
0418     SkyObject *oBest = nullptr;
0419 
0420     //printf("%.1f %.1f\n", p->ra().Degrees(), p->dec().Degrees() );
0421     m_skyMesh->aperture(p, maxrad + 1.0, OBJ_NEAREST_BUF);
0422 
0423     oBest = m_Stars->objectNearest(p, rBest);
0424     //reduce rBest by 0.75 for stars brighter than 4th mag
0425     if (oBest && oBest->mag() < 4.0)
0426         rBest *= 0.75;
0427     // For stars fainter than 12th mag
0428     else if (oBest && oBest->mag() > 12.0)
0429         rBest *= 2.00;
0430     // For stars between 4th and 12th mag
0431     else if (oBest)
0432         rBest *= 2.5;
0433 
0434     oTry = m_Satellites->objectNearest(p, rTry);
0435     if (rTry < rBest)
0436     {
0437         rBest = rTry;
0438         oBest = oTry;
0439     }
0440 
0441     for (auto &star : m_DeepStars)
0442     {
0443         rTry = maxrad;
0444         oTry = star->objectNearest(p, rTry);
0445         if (rTry < rBest)
0446         {
0447             rBest = rTry;
0448             oBest = oTry;
0449         }
0450     }
0451 
0452     rTry = maxrad;
0453     oTry = m_Catalogs->objectNearest(p, rTry);
0454     if (oTry && rTry < rBest)
0455     {
0456         rBest = rTry;
0457         oBest = oTry;
0458     }
0459 
0460     rTry = maxrad;
0461     oTry = m_Supernovae->objectNearest(p, rTry);
0462     //qCDebug(KSTARS)<<rTry<<rBest<<maxrad;
0463     if (rTry < rBest)
0464     {
0465         rBest = rTry;
0466         oBest = oTry;
0467     }
0468 
0469     rTry = maxrad;
0470     oTry = m_SolarSystem->objectNearest(p, rTry);
0471     if (!dynamic_cast<KSComet *>(oTry) &&
0472             !dynamic_cast<KSAsteroid *>(
0473                 oTry)) // There are gazillions of faint asteroids and comets; we want to prevent them from getting precedence
0474     {
0475         rTry *=
0476             0.25; // this is either sun, moon, or one of the major planets or their moons.
0477     }
0478     else
0479     {
0480         if (std::isfinite(oTry->mag()) && oTry->mag() < 12.0)
0481         {
0482             rTry *= 0.75; // Bright comets / asteroids get some precedence.
0483         }
0484     }
0485     if (rTry < rBest)
0486     {
0487         rBest = rTry;
0488         oBest = oTry;
0489     }
0490 
0491     //if ( oBest && Options::verboseLogging())
0492     //qCDebug(KSTARS) << "OBEST=" << oBest->name() << " - " << oBest->name2();
0493     maxrad = rBest;
0494     return oBest; //will be 0 if no object nearer than maxrad was found
0495 }
0496 
0497 SkyObject *SkyMapComposite::starNearest(SkyPoint *p, double &maxrad)
0498 {
0499     double rtry     = maxrad;
0500     SkyObject *star = nullptr;
0501 
0502     m_skyMesh->aperture(p, maxrad + 1.0, OBJ_NEAREST_BUF);
0503 
0504     star = m_Stars->objectNearest(p, rtry);
0505     //reduce rBest by 0.75 for stars brighter than 4th mag
0506     if (star && star->mag() < 4.0)
0507         rtry *= 0.75;
0508 
0509     // TODO: Add Deep Star Catalog support
0510 
0511     maxrad = rtry;
0512     return star;
0513 }
0514 
0515 bool SkyMapComposite::addNameLabel(SkyObject *o)
0516 {
0517     if (!o)
0518         return false;
0519     labelObjects().append(o);
0520     return true;
0521 }
0522 
0523 bool SkyMapComposite::removeNameLabel(SkyObject *o)
0524 {
0525     if (!o)
0526         return false;
0527     int index = labelObjects().indexOf(o);
0528     if (index < 0)
0529         return false;
0530     labelObjects().removeAt(index);
0531     return true;
0532 }
0533 
0534 QHash<int, QStringList> &SkyMapComposite::getObjectNames()
0535 {
0536     return m_ObjectNames;
0537 }
0538 
0539 QHash<int, QVector<QPair<QString, const SkyObject *>>> &SkyMapComposite::getObjectLists()
0540 {
0541     return m_ObjectLists;
0542 }
0543 
0544 QList<SkyObject *> SkyMapComposite::findObjectsInArea(const SkyPoint &p1,
0545         const SkyPoint &p2)
0546 {
0547     const SkyRegion &region = m_skyMesh->skyRegion(p1, p2);
0548     QList<SkyObject *> list;
0549     // call objectsInArea( QList<SkyObject*>&, const SkyRegion& ) for each of the
0550     // components of the SkyMapComposite
0551     if (m_Stars->selected())
0552         m_Stars->objectsInArea(list, region);
0553     if (m_Catalogs->selected())
0554         m_Catalogs->objectsInArea(list, region);
0555     return list;
0556 }
0557 
0558 SkyObject *SkyMapComposite::findByName(const QString &name, bool exact)
0559 {
0560 #ifndef KSTARS_LITE
0561     if (KStars::Closing)
0562         return nullptr;
0563 #endif
0564 
0565     //We search the children in an "intelligent" order (most-used
0566     //object types first), in order to avoid wasting too much time
0567     //looking for a match.  The most important part of this ordering
0568     //is that stars should be last (because the stars list is so long)
0569     SkyObject *o = nullptr;
0570     o            = m_SolarSystem->findByName(name);
0571     if (o)
0572         return o;
0573     o = m_Catalogs->findByName(name, exact);
0574     if (o)
0575         return o;
0576     o = m_CNames->findByName(name);
0577     if (o)
0578         return o;
0579     o = m_Stars->findByName(name);
0580     if (o)
0581         return o;
0582     o = m_Supernovae->findByName(name);
0583     if (o)
0584         return o;
0585     o = m_Satellites->findByName(name);
0586     if (o)
0587         return o;
0588 
0589     return nullptr;
0590 }
0591 
0592 SkyObject *SkyMapComposite::findStarByGenetiveName(const QString name)
0593 {
0594     return m_Stars->findStarByGenetiveName(name);
0595 }
0596 
0597 KSPlanetBase *SkyMapComposite::planet(int n)
0598 {
0599     if (n == KSPlanetBase::SUN)
0600         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Sun"))));
0601     if (n == KSPlanetBase::MERCURY)
0602         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Mercury"))));
0603     if (n == KSPlanetBase::VENUS)
0604         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Venus"))));
0605     if (n == KSPlanetBase::MOON)
0606         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Moon"))));
0607     if (n == KSPlanetBase::MARS)
0608         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Mars"))));
0609     if (n == KSPlanetBase::JUPITER)
0610         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Jupiter"))));
0611     if (n == KSPlanetBase::SATURN)
0612         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Saturn"))));
0613     if (n == KSPlanetBase::URANUS)
0614         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Uranus"))));
0615     if (n == KSPlanetBase::NEPTUNE)
0616         return dynamic_cast<KSPlanetBase *>((m_SolarSystem->findByName(i18n("Neptune"))));
0617     //if ( n == KSPlanetBase::PLUTO ) return (KSPlanetBase*)(m_SolarSystem->findByName( i18n( "Pluto" ) ) );
0618 
0619     return nullptr;
0620 }
0621 
0622 void SkyMapComposite::reloadCLines()
0623 {
0624 #ifndef KSTARS_LITE
0625     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
0626     SkyMapDrawAbstract::setDrawLock(
0627         true); // This is not (yet) multithreaded, so I think we don't have to worry about overwriting the state of an existing lock --asimha
0628     removeComponent(m_CLines);
0629     delete m_CLines;
0630     addComponent(m_CLines = new ConstellationLines(this, m_Cultures.get()));
0631     SkyMapDrawAbstract::setDrawLock(false);
0632 #endif
0633 }
0634 
0635 void SkyMapComposite::reloadCNames()
0636 {
0637     //     Q_ASSERT( !SkyMapDrawAbstract::drawLock() );
0638     //     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
0639     //     objectNames(SkyObject::CONSTELLATION).clear();
0640     //     delete m_CNames;
0641     //     m_CNames = 0;
0642     //     m_CNames = new ConstellationNamesComponent( this, m_Cultures.get() );
0643     //     SkyMapDrawAbstract::setDrawLock( false );
0644     objectNames(SkyObject::CONSTELLATION).clear();
0645     objectLists(SkyObject::CONSTELLATION).clear();
0646     removeComponent(m_CNames);
0647     delete m_CNames;
0648     addComponent(m_CNames = new ConstellationNamesComponent(this, m_Cultures.get()));
0649 }
0650 
0651 void SkyMapComposite::reloadConstellationArt()
0652 {
0653 #ifndef KSTARS_LITE
0654     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
0655     SkyMapDrawAbstract::setDrawLock(true);
0656     removeComponent(m_ConstellationArt);
0657     delete m_ConstellationArt;
0658     addComponent(m_ConstellationArt =
0659                      new ConstellationArtComponent(this, m_Cultures.get()));
0660     SkyMapDrawAbstract::setDrawLock(false);
0661 #endif
0662 }
0663 
0664 void SkyMapComposite::reloadDeepSky()
0665 {
0666 #ifndef KSTARS_LITE
0667     Q_ASSERT(!SkyMapDrawAbstract::drawLock());
0668 
0669     // Deselect object if selected! If not deselected then InfoBox tries to
0670     // get the name of an object which may not exist (getLongName)
0671     // FIXME (spacetime): Is there a better way?
0672     // Current Solution: Look for the nearest star in the region and select it.
0673 
0674     SkyMap *current_map   = KStars::Instance()->map();
0675     double maxrad         = 30.0;
0676     SkyPoint center_point = current_map->getCenterPoint();
0677 
0678     current_map->setClickedObject(
0679         KStars::Instance()->data()->skyComposite()->starNearest(&center_point, maxrad));
0680     current_map->setClickedPoint(current_map->clickedObject());
0681     current_map->slotCenter();
0682 
0683     // Remove and Regenerate set of catalog objects
0684     //
0685     // FIXME: Why should we do this? Because it messes up observing
0686     // list really bad to delete and regenerate SkyObjects.
0687     SkyMapDrawAbstract::setDrawLock(true);
0688 
0689     // FIXME: We should also reload anything that refers to SkyObject
0690     // * in memory, because all the old SkyObjects are now gone! This
0691     // includes the observing list. Otherwise, expect a bad, bad crash
0692     // that is hard to debug! -- AS
0693     m_Catalogs->dropCache();
0694     SkyMapDrawAbstract::setDrawLock(false);
0695 #endif
0696 }
0697 
0698 bool SkyMapComposite::isLocalCNames()
0699 {
0700     return m_CNames->isLocalCNames();
0701 }
0702 
0703 void SkyMapComposite::emitProgressText(const QString &message)
0704 {
0705     emit progressText(message);
0706 #ifndef Q_OS_ANDROID
0707     //Can cause crashes on Android, investigate it
0708     qApp->processEvents(); // -jbb: this seemed to make it work.
0709 #endif
0710     //qCDebug(KSTARS) << QString("PROGRESS TEXT: %1\n").arg( message );
0711 }
0712 
0713 const QList<SkyObject *> &SkyMapComposite::constellationNames() const
0714 {
0715     return m_CNames->objectList();
0716 }
0717 
0718 // Returns only named stars, and should not be used
0719 const QList<SkyObject *> &SkyMapComposite::stars() const
0720 {
0721     return m_Stars->objectList();
0722 }
0723 
0724 const QList<SkyObject *> &SkyMapComposite::asteroids() const
0725 {
0726     return m_SolarSystem->asteroids();
0727 }
0728 
0729 const QList<SkyObject *> &SkyMapComposite::comets() const
0730 {
0731     return m_SolarSystem->comets();
0732 }
0733 
0734 const QList<SkyObject *> &SkyMapComposite::supernovae() const
0735 {
0736     return m_Supernovae->objectList();
0737 }
0738 
0739 QList<SkyObject *> SkyMapComposite::planets()
0740 {
0741     return solarSystemComposite()->planetObjects();
0742 }
0743 
0744 //Store it permanently
0745 /*
0746 QList<SkyObject*> SkyMapComposite::moons()
0747 {
0748     QList<SkyObject*> skyObjects;
0749     foreach(PlanetMoonsComponent *pMoons, m_SolarSystem->planetMoonsComponent()) {
0750         PlanetMoons *moons = pMoons->getMoons();
0751         for(int i = 0; i < moons->nMoons(); ++i) {
0752             skyObjects.append(moons->moon(i));
0753         }
0754     }
0755     return skyObjects;
0756 }
0757 */
0758 
0759 const QList<SkyObject *> *SkyMapComposite::getSkyObjectsList(SkyObject::TYPE t)
0760 {
0761     switch (t)
0762     {
0763         case SkyObject::STAR:
0764             return &m_Stars->objectList();
0765         case SkyObject::CATALOG_STAR:
0766             return nullptr;
0767         case SkyObject::PLANET:
0768             return &m_SolarSystem->planetObjects();
0769         case SkyObject::COMET:
0770             return &comets();
0771         case SkyObject::ASTEROID:
0772             return &asteroids();
0773         case SkyObject::MOON:
0774             return &m_SolarSystem->moons();
0775         case SkyObject::GALAXY:
0776         case SkyObject::PLANETARY_NEBULA:
0777         case SkyObject::GASEOUS_NEBULA:
0778         case SkyObject::GLOBULAR_CLUSTER:
0779         case SkyObject::OPEN_CLUSTER:
0780             return nullptr;
0781         case SkyObject::CONSTELLATION:
0782             return &constellationNames();
0783         case SkyObject::SUPERNOVA:
0784             return &supernovae();
0785         default:
0786             return nullptr;
0787     }
0788     //return nullptr;
0789 }
0790 
0791 KSPlanet *SkyMapComposite::earth()
0792 {
0793     return m_SolarSystem->earth();
0794 }
0795 
0796 QStringList SkyMapComposite::getCultureNames()
0797 {
0798     return m_Cultures->getNames();
0799 }
0800 
0801 QString SkyMapComposite::getCultureName(int index)
0802 {
0803     return m_Cultures->getName(index);
0804 }
0805 
0806 void SkyMapComposite::setCurrentCulture(QString culture)
0807 {
0808     m_Cultures->setCurrent(culture);
0809 }
0810 
0811 QString SkyMapComposite::currentCulture()
0812 {
0813     return m_Cultures->current();
0814 }
0815 #ifndef KSTARS_LITE
0816 FlagComponent *SkyMapComposite::flags()
0817 {
0818     return m_Flags;
0819 }
0820 #endif
0821 
0822 SatellitesComponent *SkyMapComposite::satellites()
0823 {
0824     return m_Satellites;
0825 }
0826 
0827 SupernovaeComponent *SkyMapComposite::supernovaeComponent()
0828 {
0829     return m_Supernovae;
0830 }
0831 
0832 ArtificialHorizonComponent *SkyMapComposite::artificialHorizon()
0833 {
0834     return m_ArtificialHorizon;
0835 }
0836 
0837 ImageOverlayComponent *SkyMapComposite::imageOverlay()
0838 {
0839     return m_ImageOverlay;
0840 }