File indexing completed on 2024-04-21 14:47:09

0001 /*
0002     SPDX-FileCopyrightText: 2002 Thomas Kabelmann <tk78@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 //KStars DBUS functions
0008 
0009 #include "kstars.h"
0010 
0011 #include "colorscheme.h"
0012 #include "eyepiecefield.h"
0013 #include "imageexporter.h"
0014 #include "ksdssdownloader.h"
0015 #include "kstarsdata.h"
0016 #include "observinglist.h"
0017 #include "Options.h"
0018 #include "skymap.h"
0019 #include "skycomponents/constellationboundarylines.h"
0020 #include "skycomponents/skymapcomposite.h"
0021 #include "skyobjects/catalogobject.h"
0022 #include "catalogsdb.h"
0023 #include "skyobjects/ksplanetbase.h"
0024 #include "skyobjects/starobject.h"
0025 #include "tools/whatsinteresting/wiview.h"
0026 #include "dialogs/finddialog.h"
0027 #include "tools/nameresolver.h"
0028 
0029 #ifdef HAVE_CFITSIO
0030 #include "fitsviewer/fitsviewer.h"
0031 #ifdef HAVE_INDI
0032 #include "ekos/manager.h"
0033 #endif
0034 #endif
0035 
0036 #include <KActionCollection>
0037 
0038 #include <QPrintDialog>
0039 #include <QPrinter>
0040 #include <QElapsedTimer>
0041 
0042 #include "kstars_debug.h"
0043 
0044 void KStars::setRaDec(double ra, double dec)
0045 {
0046     SkyPoint p(ra, dec);
0047     map()->setClickedPoint(&p);
0048     map()->slotCenter();
0049 }
0050 
0051 void KStars::setRaDecJ2000(double ra0, double dec0)
0052 {
0053     SkyPoint p;
0054     p.setRA0(ra0);
0055     p.setDec0(dec0);
0056     p.updateCoordsNow(data()->updateNum());
0057     map()->setClickedPoint(&p);
0058     map()->slotCenter();
0059 }
0060 
0061 void KStars::setAltAz(double alt, double az, bool altIsRefracted)
0062 {
0063     SkyPoint p;
0064     if (altIsRefracted)
0065     {
0066         alt = SkyPoint::unrefract(alt);
0067     }
0068     p.setAlt(alt);
0069     p.setAz(az);
0070     p.HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0071     map()->setClickedPoint(&p);
0072     map()->slotCenter();
0073 }
0074 
0075 void KStars::lookTowards(const QString &direction)
0076 {
0077     QString dir = direction.toLower();
0078     if (dir == i18n("zenith") || dir == "z")
0079     {
0080         actionCollection()->action("zenith")->trigger();
0081     }
0082     else if (dir == i18n("north") || dir == "n")
0083     {
0084         actionCollection()->action("north")->trigger();
0085     }
0086     else if (dir == i18n("east") || dir == "e")
0087     {
0088         actionCollection()->action("east")->trigger();
0089     }
0090     else if (dir == i18n("south") || dir == "s")
0091     {
0092         actionCollection()->action("south")->trigger();
0093     }
0094     else if (dir == i18n("west") || dir == "w")
0095     {
0096         actionCollection()->action("west")->trigger();
0097     }
0098     else if (dir == i18n("northeast") || dir == "ne")
0099     {
0100         map()->stopTracking();
0101         map()->clickedPoint()->setAlt(15.0);
0102         map()->clickedPoint()->setAz(45.0);
0103         map()->clickedPoint()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0104         map()->slotCenter();
0105     }
0106     else if (dir == i18n("southeast") || dir == "se")
0107     {
0108         map()->stopTracking();
0109         map()->clickedPoint()->setAlt(15.0);
0110         map()->clickedPoint()->setAz(135.0);
0111         map()->clickedPoint()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0112         map()->slotCenter();
0113     }
0114     else if (dir == i18n("southwest") || dir == "sw")
0115     {
0116         map()->stopTracking();
0117         map()->clickedPoint()->setAlt(15.0);
0118         map()->clickedPoint()->setAz(225.0);
0119         map()->clickedPoint()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0120         map()->slotCenter();
0121     }
0122     else if (dir == i18n("northwest") || dir == "nw")
0123     {
0124         map()->stopTracking();
0125         map()->clickedPoint()->setAlt(15.0);
0126         map()->clickedPoint()->setAz(315.0);
0127         map()->clickedPoint()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0128         map()->slotCenter();
0129     }
0130     else
0131     {
0132         SkyObject *target = data()->objectNamed(direction);
0133         if (target != nullptr)
0134         {
0135             map()->setClickedObject(target);
0136             map()->setClickedPoint(target);
0137             map()->slotCenter();
0138         }
0139     }
0140 }
0141 
0142 void KStars::addLabel(const QString &name)
0143 {
0144     SkyObject *target = data()->objectNamed(name);
0145     if (target != nullptr)
0146     {
0147         data()->skyComposite()->addNameLabel(target);
0148         map()->forceUpdate();
0149     }
0150 }
0151 
0152 void KStars::removeLabel(const QString &name)
0153 {
0154     SkyObject *target = data()->objectNamed(name);
0155     if (target != nullptr)
0156     {
0157         data()->skyComposite()->removeNameLabel(target);
0158         map()->forceUpdate();
0159     }
0160 }
0161 
0162 void KStars::addTrail(const QString &name)
0163 {
0164     TrailObject *target = dynamic_cast<TrailObject *>(data()->objectNamed(name));
0165     if (target)
0166     {
0167         target->addToTrail();
0168         map()->forceUpdate();
0169     }
0170 }
0171 
0172 void KStars::removeTrail(const QString &name)
0173 {
0174     TrailObject *target = dynamic_cast<TrailObject *>(data()->objectNamed(name));
0175     if (target)
0176     {
0177         target->clearTrail();
0178         map()->forceUpdate();
0179     }
0180 }
0181 
0182 void KStars::zoom(double z)
0183 {
0184     map()->setZoomFactor(z);
0185 }
0186 
0187 void KStars::zoomIn()
0188 {
0189     map()->slotZoomIn();
0190 }
0191 
0192 void KStars::zoomOut()
0193 {
0194     map()->slotZoomOut();
0195 }
0196 
0197 void KStars::defaultZoom()
0198 {
0199     map()->slotZoomDefault();
0200 }
0201 
0202 void KStars::setLocalTime(int yr, int mth, int day, int hr, int min, int sec)
0203 {
0204     data()->changeDateTime(data()->geo()->LTtoUT(KStarsDateTime(QDate(yr, mth, day), QTime(hr, min, sec))));
0205 }
0206 
0207 void KStars::setTimeToNow()
0208 {
0209     slotSetTimeToNow();
0210 }
0211 
0212 void KStars::waitFor(double sec)
0213 {
0214     QElapsedTimer tm;
0215     tm.start();
0216     while (tm.elapsed() < int(1000. * sec))
0217     {
0218         qApp->processEvents();
0219     }
0220 }
0221 
0222 void KStars::waitForKey(const QString &k)
0223 {
0224     data()->resumeKey = QKeySequence::fromString(k);
0225     if (!data()->resumeKey.isEmpty())
0226     {
0227         //When the resumeKey is pressed, resumeKey is set to empty
0228         while (!data()->resumeKey.isEmpty())
0229             qApp->processEvents();
0230     }
0231     else
0232     {
0233         qDebug() << Q_FUNC_INFO << "Error [D-Bus waitForKey()]: Invalid key requested.";
0234     }
0235 }
0236 
0237 void KStars::setTracking(bool track)
0238 {
0239     if (track != Options::isTracking())
0240         slotTrack();
0241 }
0242 
0243 void KStars::popupMessage(int /*x*/, int /*y*/, const QString & /*message*/)
0244 {
0245     //Show a small popup window at (x,y) with a text message
0246 }
0247 
0248 void KStars::drawLine(int /*x1*/, int /*y1*/, int /*x2*/, int /*y2*/, int /*speed*/)
0249 {
0250     //Draw a line on the skymap display
0251 }
0252 
0253 QString KStars::location()
0254 {
0255     GeoLocation *currentLocation = data()->geo();
0256 
0257     QJsonObject locationInfo =
0258     {
0259         {"name", currentLocation->name()},
0260         {"province", currentLocation->province()},
0261         {"country", currentLocation->country()},
0262         {"longitude", currentLocation->lng()->Degrees()},
0263         {"latitude", currentLocation->lat()->Degrees()},
0264         {"tz0", currentLocation->TZ0()},
0265         {"tz", currentLocation->TZ()}
0266     };
0267 
0268     return QJsonDocument(locationInfo).toJson(QJsonDocument::Compact);
0269 }
0270 
0271 bool KStars::setGeoLocation(const QString &city, const QString &province, const QString &country)
0272 {
0273     //Set the geographic location
0274     bool cityFound(false);
0275 
0276     foreach (GeoLocation *loc, data()->geoList)
0277     {
0278         if (loc->translatedName() == city && (province.isEmpty() || loc->translatedProvince() == province) &&
0279                 loc->translatedCountry() == country)
0280         {
0281             cityFound = true;
0282 
0283             data()->setLocation(*loc);
0284 
0285             //configure time zone rule
0286             KStarsDateTime ltime = loc->UTtoLT(data()->ut());
0287             loc->tzrule()->reset_with_ltime(ltime, loc->TZ0(), data()->isTimeRunningForward());
0288             data()->setNextDSTChange(loc->tzrule()->nextDSTChange());
0289 
0290             //reset LST
0291             data()->syncLST();
0292 
0293             //make sure planets, etc. are updated immediately
0294             data()->setFullTimeUpdate();
0295 
0296             // If the sky is in Horizontal mode and not tracking, reset focus such that
0297             // Alt/Az remain constant.
0298             if (!Options::isTracking() && Options::useAltAz())
0299             {
0300                 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
0301             }
0302 
0303             // recalculate new times and objects
0304             data()->setSnapNextFocus();
0305             updateTime();
0306 
0307             //no need to keep looking, we're done.
0308             break;
0309         }
0310     }
0311 
0312     if (!cityFound)
0313     {
0314         if (province.isEmpty())
0315             qDebug()
0316                     << QString("Error [D-Bus setGeoLocation]: city %1, %2 not found in database.").arg(city, country);
0317         else
0318             qDebug() << Q_FUNC_INFO << QString("Error [D-Bus setGeoLocation]: city %1, %2, %3 not found in database.")
0319                      .arg(city, province, country);
0320     }
0321 
0322     return cityFound;
0323 }
0324 
0325 bool KStars::setGPSLocation(double longitude, double latitude, double elevation, double tz0)
0326 {
0327     GeoLocation *geo = data()->geo();
0328     std::unique_ptr<GeoLocation> tempGeo;
0329 
0330     QString newLocationName("GPS Location");
0331 
0332     dms lng(longitude), lat(latitude);
0333 
0334     GeoLocation *nearest = data()->nearestLocation(longitude, latitude);
0335 
0336     if (nearest)
0337         tempGeo.reset(new GeoLocation(lng, lat, newLocationName, "", "", nearest->TZ0(), nearest->tzrule(), elevation));
0338     else
0339         tempGeo.reset(new GeoLocation(lng, lat, newLocationName, "", "", tz0, new TimeZoneRule(), elevation));
0340 
0341     geo = tempGeo.get();
0342 
0343     qCInfo(KSTARS) << "Setting location from DBus. Longitude:" << longitude << "Latitude:" << latitude;
0344 
0345     data()->setLocation(*geo);
0346 
0347     return true;
0348 }
0349 
0350 void KStars::readConfig()
0351 {
0352     //Load config file values into Options object
0353     Options::self()->load();
0354 
0355     applyConfig();
0356 
0357     //Reset date, if one was stored
0358     if (data()->StoredDate.isValid())
0359     {
0360         data()->changeDateTime(data()->geo()->LTtoUT(data()->StoredDate));
0361         data()->StoredDate = KStarsDateTime(QDateTime()); //invalidate StoredDate
0362     }
0363 
0364     map()->forceUpdate();
0365 }
0366 
0367 void KStars::writeConfig()
0368 {
0369     Options::self()->save();
0370 
0371     //Store current simulation time
0372     data()->StoredDate = data()->lt();
0373 }
0374 
0375 QString KStars::getOption(const QString &name)
0376 {
0377     //Some config items are not stored in the Options object while
0378     //the program is running; catch these here and returntheir current value.
0379     if (name == "FocusRA")
0380     {
0381         return QString::number(map()->focus()->ra().Hours(), 'f', 6);
0382     }
0383     if (name == "FocusDec")
0384     {
0385         return QString::number(map()->focus()->dec().Degrees(), 'f', 6);
0386     }
0387 
0388     KConfigSkeletonItem *it = Options::self()->findItem(name);
0389     if (it)
0390         return it->property().toString();
0391     else
0392         return QString();
0393 }
0394 
0395 QString KStars::getFocusInformationXML()
0396 {
0397     QString output;
0398     QXmlStreamWriter stream(&output);
0399     SkyPoint* focus = map()->focus();
0400     Q_ASSERT(!!focus);
0401     stream.setAutoFormatting(true);
0402     stream.writeStartDocument();
0403     stream.writeStartElement("focus");
0404     stream.writeTextElement("FOV_Degrees", QString::number(map()->fov()));
0405     stream.writeTextElement("RA_JNow_Degrees", QString::number(focus->ra().Degrees()));
0406     stream.writeTextElement("Dec_JNow_Degrees", QString::number(focus->dec().Degrees()));
0407     stream.writeTextElement("RA_JNow_HMS", focus->ra().toHMSString());
0408     stream.writeTextElement("Dec_JNow_DMS", focus->dec().toDMSString());
0409     stream.writeTextElement("Altitude_Degrees", QString::number(focus->alt().Degrees()));
0410     stream.writeTextElement("Azimuth_Degrees", QString::number(focus->az().Degrees()));
0411     stream.writeTextElement("Altitude_DMS", focus->alt().toDMSString());
0412     stream.writeTextElement("Azimuth_DMS", focus->az().toDMSString());
0413     stream.writeTextElement("Focused_Object", map()->focusObject() ? map()->focusObject()->name() : QString());
0414     stream.writeEndElement(); // focus
0415     stream.writeEndDocument();
0416     return output;
0417 }
0418 
0419 void KStars::changeViewOption(const QString &op, const QString &val)
0420 {
0421     bool bOk(false), dOk(false);
0422 
0423     //parse bool value
0424     bool bVal(false);
0425     if (val.toLower() == "true")
0426     {
0427         bOk  = true;
0428         bVal = true;
0429     }
0430     if (val.toLower() == "false")
0431     {
0432         bOk  = true;
0433         bVal = false;
0434     }
0435     if (val == "1")
0436     {
0437         bOk  = true;
0438         bVal = true;
0439     }
0440     if (val == "0")
0441     {
0442         bOk  = true;
0443         bVal = false;
0444     }
0445 
0446     //parse double value
0447     double dVal = val.toDouble(&dOk);
0448 
0449     //[GUI]
0450     if (op == "ShowInfoBoxes" && bOk)
0451         Options::setShowInfoBoxes(bVal);
0452     if (op == "ShowTimeBox" && bOk)
0453         Options::setShowTimeBox(bVal);
0454     if (op == "ShowGeoBox" && bOk)
0455         Options::setShowGeoBox(bVal);
0456     if (op == "ShowFocusBox" && bOk)
0457         Options::setShowFocusBox(bVal);
0458     if (op == "ShadeTimeBox" && bOk)
0459         Options::setShadeTimeBox(bVal);
0460     if (op == "ShadeGeoBox" && bOk)
0461         Options::setShadeGeoBox(bVal);
0462     if (op == "ShadeFocusBox" && bOk)
0463         Options::setShadeFocusBox(bVal);
0464 
0465     //[View]
0466     // FIXME: REGRESSION
0467     //     if ( op == "FOVName"                ) Options::setFOVName(         val );
0468     //     if ( op == "FOVSizeX"         && dOk ) Options::setFOVSizeX( (float)dVal );
0469     //     if ( op == "FOVSizeY"         && dOk ) Options::setFOVSizeY( (float)dVal );
0470     //     if ( op == "FOVShape"        && nOk ) Options::setFOVShape(       nVal );
0471     //     if ( op == "FOVColor"               ) Options::setFOVColor(        val );
0472     if (op == "ShowStars" && bOk)
0473         Options::setShowStars(bVal);
0474     if (op == "ShowCLines" && bOk)
0475         Options::setShowCLines(bVal);
0476     if (op == "ShowCBounds" && bOk)
0477         Options::setShowCBounds(bVal);
0478     if (op == "ShowCNames" && bOk)
0479         Options::setShowCNames(bVal);
0480     if (op == "ShowMilkyWay" && bOk)
0481         Options::setShowMilkyWay(bVal);
0482     if (op == "AutoSelectGrid" && bOk)
0483         Options::setAutoSelectGrid(bVal);
0484     if (op == "ShowEquatorialGrid" && bOk)
0485         Options::setShowEquatorialGrid(bVal);
0486     if (op == "ShowHorizontalGrid" && bOk)
0487         Options::setShowHorizontalGrid(bVal);
0488     if (op == "ShowEquator" && bOk)
0489         Options::setShowEquator(bVal);
0490     if (op == "ShowEcliptic" && bOk)
0491         Options::setShowEcliptic(bVal);
0492     if (op == "ShowHorizon" && bOk)
0493         Options::setShowHorizon(bVal);
0494     if (op == "ShowGround" && bOk)
0495         Options::setShowGround(bVal);
0496     if (op == "ShowSun" && bOk)
0497         Options::setShowSun(bVal);
0498     if (op == "ShowMoon" && bOk)
0499         Options::setShowMoon(bVal);
0500     if (op == "ShowMercury" && bOk)
0501         Options::setShowMercury(bVal);
0502     if (op == "ShowVenus" && bOk)
0503         Options::setShowVenus(bVal);
0504     if (op == "ShowMars" && bOk)
0505         Options::setShowMars(bVal);
0506     if (op == "ShowJupiter" && bOk)
0507         Options::setShowJupiter(bVal);
0508     if (op == "ShowSaturn" && bOk)
0509         Options::setShowSaturn(bVal);
0510     if (op == "ShowUranus" && bOk)
0511         Options::setShowUranus(bVal);
0512     if (op == "ShowNeptune" && bOk)
0513         Options::setShowNeptune(bVal);
0514     //if ( op == "ShowPluto"       && bOk ) Options::setShowPluto(    bVal );
0515     if (op == "ShowAsteroids" && bOk)
0516         Options::setShowAsteroids(bVal);
0517     if (op == "ShowComets" && bOk)
0518         Options::setShowComets(bVal);
0519     if (op == "ShowSolarSystem" && bOk)
0520         Options::setShowSolarSystem(bVal);
0521     if (op == "ShowDeepSky" && bOk)
0522         Options::setShowDeepSky(bVal);
0523     if (op == "ShowSupernovae" && bOk)
0524         Options::setShowSupernovae(bVal);
0525     if (op == "ShowStarNames" && bOk)
0526         Options::setShowStarNames(bVal);
0527     if (op == "ShowStarMagnitudes" && bOk)
0528         Options::setShowStarMagnitudes(bVal);
0529     if (op == "ShowAsteroidNames" && bOk)
0530         Options::setShowAsteroidNames(bVal);
0531     if (op == "ShowCometNames" && bOk)
0532         Options::setShowCometNames(bVal);
0533     if (op == "ShowPlanetNames" && bOk)
0534         Options::setShowPlanetNames(bVal);
0535     if (op == "ShowPlanetImages" && bOk)
0536         Options::setShowPlanetImages(bVal);
0537     if (op == "HideOnSlew" && bOk)
0538         Options::setHideOnSlew(bVal);
0539     if (op == "HideStars" && bOk)
0540         Options::setHideStars(bVal);
0541     if (op == "HidePlanets" && bOk)
0542         Options::setHidePlanets(bVal);
0543     if (op == "HideMilkyWay" && bOk)
0544         Options::setHideMilkyWay(bVal);
0545     if (op == "HideCNames" && bOk)
0546         Options::setHideCNames(bVal);
0547     if (op == "HideCLines" && bOk)
0548         Options::setHideCLines(bVal);
0549     if (op == "HideCBounds" && bOk)
0550         Options::setHideCBounds(bVal);
0551     if (op == "HideGrids" && bOk)
0552         Options::setHideGrids(bVal);
0553     if (op == "HideLabels" && bOk)
0554         Options::setHideLabels(bVal);
0555 
0556     if (op == "UseAltAz" && bOk)
0557         Options::setUseAltAz(bVal);
0558     if (op == "UseRefraction" && bOk)
0559         Options::setUseRefraction(bVal);
0560     if (op == "UseAutoLabel" && bOk)
0561         Options::setUseAutoLabel(bVal);
0562     if (op == "UseHoverLabel" && bOk)
0563         Options::setUseHoverLabel(bVal);
0564     if (op == "UseAutoTrail" && bOk)
0565         Options::setUseAutoTrail(bVal);
0566     if (op == "UseAnimatedSlewing" && bOk)
0567         Options::setUseAnimatedSlewing(bVal);
0568     if (op == "FadePlanetTrails" && bOk)
0569         Options::setFadePlanetTrails(bVal);
0570     if (op == "SlewTimeScale" && dOk)
0571         Options::setSlewTimeScale(dVal);
0572     if (op == "ZoomFactor" && dOk)
0573         Options::setZoomFactor(dVal);
0574     //    if ( op == "MagLimitDrawStar"     && dOk )    Options::setMagLimitDrawStar(    dVal );
0575     if (op == "MagLimitDrawDeepSky" && dOk)
0576         Options::setMagLimitDrawDeepSky(dVal);
0577     if (op == "StarDensity" && dOk)
0578         Options::setStarDensity(dVal);
0579     //    if ( op == "MagLimitDrawStarZoomOut" && dOk ) Options::setMagLimitDrawStarZoomOut(        dVal );
0580     if (op == "MagLimitDrawDeepSkyZoomOut" && dOk)
0581         Options::setMagLimitDrawDeepSkyZoomOut(dVal);
0582     if (op == "StarLabelDensity" && dOk)
0583         Options::setStarLabelDensity(dVal);
0584     if (op == "MagLimitHideStar" && dOk)
0585         Options::setMagLimitHideStar(dVal);
0586     if (op == "MagLimitAsteroid" && dOk)
0587         Options::setMagLimitAsteroid(dVal);
0588     if (op == "AsteroidLabelDensity" && dOk)
0589         Options::setAsteroidLabelDensity(dVal);
0590     if (op == "MaxRadCometName" && dOk)
0591         Options::setMaxRadCometName(dVal);
0592 
0593     //these three are a "radio group"
0594     if (op == "UseLatinConstellationNames" && bOk)
0595     {
0596         Options::setUseLatinConstellNames(true);
0597         Options::setUseLocalConstellNames(false);
0598         Options::setUseAbbrevConstellNames(false);
0599     }
0600     if (op == "UseLocalConstellationNames" && bOk)
0601     {
0602         Options::setUseLatinConstellNames(false);
0603         Options::setUseLocalConstellNames(true);
0604         Options::setUseAbbrevConstellNames(false);
0605     }
0606     if (op == "UseAbbrevConstellationNames" && bOk)
0607     {
0608         Options::setUseLatinConstellNames(false);
0609         Options::setUseLocalConstellNames(false);
0610         Options::setUseAbbrevConstellNames(true);
0611     }
0612 
0613     map()->forceUpdate();
0614 }
0615 
0616 void KStars::setColor(const QString &name, const QString &value)
0617 {
0618     ColorScheme *cs = data()->colorScheme();
0619     if (cs->hasColorNamed(name))
0620     {
0621         cs->setColor(name, value);
0622         map()->forceUpdate();
0623     }
0624 }
0625 
0626 QString KStars::colorScheme() const
0627 {
0628     return data()->colorScheme()->fileName();
0629 }
0630 
0631 void KStars::loadColorScheme(const QString &name)
0632 {
0633     data()->colorScheme()->load(name);
0634 
0635 #if 0
0636     if (ok)
0637     {
0638         //set the application colors for the Night Vision scheme
0639         if (Options::darkAppColors())
0640         {
0641             //OriginalPalette = QApplication::palette();
0642             QApplication::setPalette(DarkPalette);
0643             if (KStars::Instance()->wiView())
0644                 KStars::Instance()->wiView()->setNightVisionOn(true);
0645             //Note:  This uses style sheets to set the dark colors, this is cross platform.  Palettes have a different behavior on OS X and Windows as opposed to Linux.
0646             //It might be a good idea to use stylesheets in the future instead of palettes but this will work for now for OS X.
0647             //This is also in KStars.cpp.  If you change it, change it in BOTH places.
0648 #ifdef Q_OS_OSX
0649             qDebug() << Q_FUNC_INFO << "setting dark stylesheet";
0650             qApp->setStyleSheet(
0651                 "QWidget { background-color: black; color:red; "
0652                 "selection-background-color:rgb(30,30,30);selection-color:white}"
0653                 "QToolBar { border:none }"
0654                 "QTabBar::tab:selected { background-color:rgb(50,50,50) }"
0655                 "QTabBar::tab:!selected { background-color:rgb(30,30,30) }"
0656                 "QPushButton { background-color:rgb(50,50,50);border-width:1px; border-style:solid;border-color:black}"
0657                 "QPushButton::disabled { background-color:rgb(10,10,10);border-width:1px; "
0658                 "border-style:solid;border-color:black }"
0659                 "QToolButton:Checked { background-color:rgb(30,30,30); border:none }"
0660                 "QComboBox { background-color:rgb(30,30,30); }"
0661                 "QComboBox::disabled { background-color:rgb(10,10,10) }"
0662                 "QScrollBar::handle { background: rgb(30,30,30) }"
0663                 "QSpinBox { border-width: 1px; border-style:solid; border-color:rgb(30,30,30) }"
0664                 "QDoubleSpinBox { border-width:1px; border-style:solid; border-color:rgb(30,30,30) }"
0665                 "QLineEdit { border-width: 1px; border-style: solid; border-color:rgb(30,30,30) }"
0666                 "QCheckBox::indicator:unchecked { background-color:rgb(30,30,30);border-width:1px; "
0667                 "border-style:solid;border-color:black }"
0668                 "QCheckBox::indicator:checked { background-color:red;border-width:1px; "
0669                 "border-style:solid;border-color:black }"
0670                 "QRadioButton::indicator:unchecked { background-color:rgb(30,30,30) }"
0671                 "QRadioButton::indicator:checked { background-color:red }"
0672                 "QRoundProgressBar { alternate-background-color:black }"
0673                 "QDateTimeEdit {background-color:rgb(30,30,30); border-width: 1px; border-style:solid; "
0674                 "border-color:rgb(30,30,30) }"
0675                 "QHeaderView { color:red;background-color:black }"
0676                 "QHeaderView::Section { background-color:rgb(30,30,30) }"
0677                 "QTableCornerButton::section{ background-color:rgb(30,30,30) }"
0678                 "");
0679             qDebug() << Q_FUNC_INFO << "stylesheet set";
0680 #endif
0681         }
0682         else
0683         {
0684             if (KStars::Instance()->wiView())
0685                 KStars::Instance()->wiView()->setNightVisionOn(false);
0686             QApplication::setPalette(OriginalPalette);
0687 #ifdef Q_OS_OSX
0688             qDebug() << Q_FUNC_INFO << "setting light stylesheet";
0689             qApp->setStyleSheet("");
0690             qDebug() << Q_FUNC_INFO << "stylesheet set";
0691 #endif
0692         }
0693     }
0694 #endif
0695 
0696     Options::setColorSchemeFile(name);
0697 
0698     emit colorSchemeChanged();
0699 
0700     map()->forceUpdate();
0701 }
0702 
0703 void KStars::exportImage(const QString &url, int w, int h, bool includeLegend)
0704 {
0705     ImageExporter *m_ImageExporter = m_KStarsData->imageExporter();
0706 
0707     if (w <= 0)
0708         w = map()->width();
0709     if (h <= 0)
0710         h = map()->height();
0711 
0712     QSize size(w, h);
0713 
0714     m_ImageExporter->includeLegend(includeLegend);
0715     m_ImageExporter->setRasterOutputSize(&size);
0716     m_ImageExporter->exportImage(url);
0717 }
0718 
0719 QString KStars::getDSSURL(const QString &objectName)
0720 {
0721     SkyObject *target = data()->objectNamed(objectName);
0722     if (!target)
0723     {
0724         return QString("ERROR");
0725     }
0726     else
0727     {
0728         return KSDssDownloader::getDSSURL(target);
0729     }
0730 }
0731 
0732 QString KStars::getDSSURL(double RA_J2000, double Dec_J2000, float width, float height)
0733 {
0734     dms ra(RA_J2000), dec(Dec_J2000);
0735     return KSDssDownloader::getDSSURL(ra, dec, width, height);
0736 }
0737 
0738 QString KStars::getObjectDataXML(const QString &objectName, bool fallbackToInternet, bool storeInternetResolved)
0739 {
0740     bool deleteTargetAfterUse = false;
0741     const SkyObject *target = data()->objectNamed(objectName);
0742     if (!target && fallbackToInternet)
0743     {
0744         if (!storeInternetResolved)
0745         {
0746             const auto &cedata = NameResolver::resolveName(objectName);
0747             if (cedata.first)
0748             {
0749                 target = cedata.second.clone(); // We have to free this since we own the pointer
0750                 deleteTargetAfterUse = true; // so note that down
0751             }
0752         }
0753         else
0754         {
0755             CatalogsDB::DBManager db_manager { CatalogsDB::dso_db_path() };
0756             target = FindDialog::resolveAndAdd(db_manager, objectName);
0757         }
0758 
0759     }
0760     if (!target)
0761     {
0762         return QString("<xml></xml>");
0763     }
0764     QString output;
0765     QXmlStreamWriter stream(&output);
0766     stream.setAutoFormatting(true);
0767     stream.writeStartDocument();
0768     stream.writeStartElement("object");
0769     stream.writeTextElement("Name", target->name());
0770     stream.writeTextElement("Alt_Name", target->name2());
0771     stream.writeTextElement("Long_Name", target->longname());
0772     stream.writeTextElement("Constellation",
0773                             KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName(target));
0774     stream.writeTextElement("RA_Dec_Epoch_JD", QString::number(target->getLastPrecessJD(), 'f', 3));
0775     stream.writeTextElement("RA_HMS", target->ra().toHMSString());
0776     stream.writeTextElement("Dec_DMS", target->dec().toDMSString());
0777     stream.writeTextElement("RA_J2000_HMS", target->ra0().toHMSString());
0778     stream.writeTextElement("Dec_J2000_DMS", target->dec0().toDMSString());
0779     stream.writeTextElement("RA_Degrees", QString::number(target->ra().Degrees()));
0780     stream.writeTextElement("Dec_Degrees", QString::number(target->dec().Degrees()));
0781     stream.writeTextElement("RA_J2000_Degrees", QString::number(target->ra0().Degrees()));
0782     stream.writeTextElement("Dec_J2000_Degrees", QString::number(target->dec0().Degrees()));
0783     stream.writeTextElement("Type", target->typeName());
0784     stream.writeTextElement("Magnitude", QString::number(target->mag(), 'g', 2));
0785     stream.writeTextElement("Position_Angle", QString::number(target->pa(), 'g', 3));
0786     auto *star = dynamic_cast<const StarObject *>(target);
0787     auto *dso = dynamic_cast<const CatalogObject *>(target);
0788     if (star)
0789     {
0790         stream.writeTextElement("Spectral_Type", star->sptype());
0791         stream.writeTextElement("Genetive_Name", star->gname());
0792         stream.writeTextElement("Greek_Letter", star->greekLetter());
0793         stream.writeTextElement("Proper_Motion", QString::number(star->pmMagnitude()));
0794         stream.writeTextElement("Proper_Motion_RA", QString::number(star->pmRA()));
0795         stream.writeTextElement("Proper_Motion_Dec", QString::number(star->pmDec()));
0796         stream.writeTextElement("Parallax_mas", QString::number(star->parallax()));
0797         stream.writeTextElement("Distance_pc", QString::number(star->distance()));
0798         stream.writeTextElement("Henry_Draper", QString::number(star->getHDIndex()));
0799         stream.writeTextElement("BV_Index", QString::number(star->getBVIndex()));
0800     }
0801     else if (dso)
0802     {
0803         stream.writeTextElement("Catalog", dso->getCatalog().name);
0804         stream.writeTextElement("Major_Axis", QString::number(dso->a()));
0805         stream.writeTextElement("Minor_Axis", QString::number(dso->a() * dso->e()));
0806     }
0807     stream.writeEndElement(); // object
0808     stream.writeEndDocument();
0809 
0810     if (deleteTargetAfterUse)
0811     {
0812         Q_ASSERT(!!target);
0813         delete target;
0814     }
0815 
0816     return output;
0817 }
0818 
0819 QString KStars::getObjectPositionInfo(const QString &objectName)
0820 {
0821     Q_ASSERT(data());
0822     const SkyObject *obj = data()->objectNamed(objectName); // make sure we work with a clone
0823     if (!obj)
0824     {
0825         return QString("<xml></xml>");
0826     }
0827     SkyObject *target = obj->clone();
0828     if (!target) // should not happen
0829     {
0830         qWarning() << "ERROR: Could not clone SkyObject " << objectName << "!";
0831         return QString("<xml></xml>");
0832     }
0833 
0834     const KSNumbers *updateNum = data()->updateNum();
0835     const KStarsDateTime ut    = data()->ut();
0836     const GeoLocation *geo     = data()->geo();
0837     QString riseTimeString, setTimeString, transitTimeString;
0838     QString riseAzString, setAzString, transitAltString;
0839 
0840     // Make sure the coordinates of the SkyObject are updated
0841     target->updateCoords(updateNum, true, geo->lat(), data()->lst(), true);
0842     target->EquatorialToHorizontal(data()->lst(), geo->lat());
0843 
0844     // Compute rise, set and transit times and parameters -- Code pulled from DetailDialog
0845     QTime riseTime    = target->riseSetTime(ut, geo, true);   //true = use rise time
0846     dms riseAz        = target->riseSetTimeAz(ut, geo, true); //true = use rise time
0847     QTime transitTime = target->transitTime(ut, geo);
0848     dms transitAlt    = target->transitAltitude(ut, geo);
0849     if (transitTime < riseTime)
0850     {
0851         transitTime = target->transitTime(ut.addDays(1), geo);
0852         transitAlt  = target->transitAltitude(ut.addDays(1), geo);
0853     }
0854     //If set time is before rise time, use set time for tomorrow
0855     QTime setTime = target->riseSetTime(ut, geo, false);   //false = use set time
0856     dms setAz     = target->riseSetTimeAz(ut, geo, false); //false = use set time
0857     if (setTime < riseTime)
0858     {
0859         setTime = target->riseSetTime(ut.addDays(1), geo, false);   //false = use set time
0860         setAz   = target->riseSetTimeAz(ut.addDays(1), geo, false); //false = use set time
0861     }
0862     if (riseTime.isValid())
0863     {
0864         riseTimeString = QString::asprintf("%02d:%02d", riseTime.hour(), riseTime.minute());
0865         setTimeString  = QString::asprintf("%02d:%02d", setTime.hour(), setTime.minute());
0866         riseAzString   = riseAz.toDMSString(true, true);
0867         setAzString    = setAz.toDMSString(true, true);
0868     }
0869     else
0870     {
0871         if (target->alt().Degrees() > 0.0)
0872         {
0873             riseTimeString = setTimeString = QString("Circumpolar");
0874         }
0875         else
0876         {
0877             riseTimeString = setTimeString = QString("Never Rises");
0878         }
0879         riseAzString = setAzString = QString("N/A");
0880     }
0881 
0882     transitTimeString = QString::asprintf("%02d:%02d", transitTime.hour(), transitTime.minute());
0883     transitAltString  = transitAlt.toDMSString(true, true);
0884 
0885     QString output;
0886     QXmlStreamWriter stream(&output);
0887     stream.setAutoFormatting(true);
0888     stream.writeStartDocument();
0889     stream.writeStartElement("object");
0890     stream.writeTextElement("Name", target->name());
0891     stream.writeTextElement("RA_Dec_Epoch_JD", QString::number(target->getLastPrecessJD(), 'f', 3));
0892     stream.writeTextElement("AltAz_JD", QString::number(data()->ut().djd(), 'f', 3));
0893     stream.writeTextElement("RA_HMS", target->ra().toHMSString(true));
0894     stream.writeTextElement("Dec_DMS", target->dec().toDMSString(true, true));
0895     stream.writeTextElement("RA_J2000_HMS", target->ra0().toHMSString(true));
0896     stream.writeTextElement("Dec_J2000_DMS", target->dec0().toDMSString(true, true));
0897     stream.writeTextElement("RA_Degrees", QString::number(target->ra().Degrees()));
0898     stream.writeTextElement("Dec_Degrees", QString::number(target->dec().Degrees()));
0899     stream.writeTextElement("RA_J2000_Degrees", QString::number(target->ra0().Degrees()));
0900     stream.writeTextElement("Dec_J2000_Degrees", QString::number(target->dec0().Degrees()));
0901     stream.writeTextElement("Altitude_DMS", target->alt().toDMSString(true, true));
0902     stream.writeTextElement("Azimuth_DMS", target->az().toDMSString(true, true));
0903     stream.writeTextElement("Altitude_Degrees", QString::number(target->alt().Degrees()));
0904     stream.writeTextElement("Azimuth_Degrees", QString::number(target->az().Degrees()));
0905     stream.writeTextElement("Rise", riseTimeString);
0906     stream.writeTextElement("Rise_Az_DMS", riseAzString);
0907     stream.writeTextElement("Set", setTimeString);
0908     stream.writeTextElement("Set_Az_DMS", setAzString);
0909     stream.writeTextElement("Transit", transitTimeString);
0910     stream.writeTextElement("Transit_Alt_DMS", transitAltString);
0911     stream.writeTextElement("Time_Zone_Offset", QString::asprintf("%02.2f", geo->TZ()));
0912 
0913     stream.writeEndElement(); // object
0914     stream.writeEndDocument();
0915     return output;
0916 }
0917 
0918 void KStars::renderEyepieceView(const QString &objectName, const QString &destPathChart, const double fovWidth,
0919                                 const double fovHeight, const double rotation, const double scale, const bool flip,
0920                                 const bool invert, QString imagePath, const QString &destPathImage, const bool overlay,
0921                                 const bool invertColors)
0922 {
0923     const SkyObject *obj = data()->objectNamed(objectName);
0924     if (!obj)
0925     {
0926         qCWarning(KSTARS) << "Object named " << objectName << " was not found!";
0927         return;
0928     }
0929     SkyObject *target          = obj->clone();
0930     const KSNumbers *updateNum = data()->updateNum();
0931     const KStarsDateTime ut    = data()->ut();
0932     const GeoLocation *geo     = data()->geo();
0933     QPixmap *renderChart       = new QPixmap();
0934     QPixmap *renderImage       = nullptr;
0935     QTemporaryFile tempFile;
0936     if (overlay || (!destPathImage.isEmpty()))
0937     {
0938         if (!QFile::exists(imagePath))
0939         {
0940             // We must download a DSS image
0941             tempFile.open();
0942             QEventLoop loop;
0943             std::function<void(bool)> slot = [&loop](bool unused)
0944             {
0945                 Q_UNUSED(unused);
0946                 loop.quit();
0947             };
0948             new KSDssDownloader(target, tempFile.fileName(), slot, this);
0949             qDebug() << Q_FUNC_INFO << "DSS download requested. Waiting for download to complete...";
0950             loop.exec(); // wait for download to complete
0951             imagePath = tempFile.fileName();
0952         }
0953         if (QFile::exists(imagePath)) // required because DSS Download may fail
0954             renderImage = new QPixmap();
0955     }
0956 
0957     // Make sure the coordinates of the SkyObject are updated
0958     target->updateCoords(updateNum, true, geo->lat(), data()->lst(), true);
0959     target->EquatorialToHorizontal(data()->lst(), geo->lat());
0960 
0961     EyepieceField::renderEyepieceView(target, renderChart, fovWidth, fovHeight, rotation, scale, flip, invert,
0962                                       imagePath, renderImage, overlay, invertColors);
0963     renderChart->save(destPathChart);
0964     delete renderChart;
0965     if (renderImage)
0966     {
0967         renderImage->save(destPathImage);
0968         delete renderImage;
0969     }
0970 }
0971 QString KStars::getObservingWishListObjectNames()
0972 {
0973     QString output;
0974 
0975     for (auto &object : KStarsData::Instance()->observingList()->obsList())
0976     {
0977         output.append(object->name() + '\n');
0978     }
0979     return output;
0980 }
0981 
0982 QString KStars::getObservingSessionPlanObjectNames()
0983 {
0984     QString output;
0985 
0986     for (auto &object : KStarsData::Instance()->observingList()->sessionList())
0987     {
0988         output.append(object->name() + '\n');
0989     }
0990     return output;
0991 }
0992 
0993 void KStars::setApproxFOV(double FOV_Degrees)
0994 {
0995     zoom(map()->width() / (FOV_Degrees * dms::DegToRad));
0996 }
0997 
0998 QString KStars::getSkyMapDimensions()
0999 {
1000     return (QString::number(map()->width()) + 'x' + QString::number(map()->height()));
1001 }
1002 void KStars::printImage(bool usePrintDialog, bool useChartColors)
1003 {
1004     //QPRINTER_FOR_NOW
1005     //    KPrinter printer( true, QPrinter::HighResolution );
1006     QPrinter printer(QPrinter::HighResolution);
1007     printer.setFullPage(false);
1008 
1009     //Set up the printer (either with the Print Dialog,
1010     //or using the default settings)
1011     bool ok(false);
1012     if (usePrintDialog)
1013     {
1014         //QPRINTER_FOR_NOW
1015         //        ok = printer.setup( this, i18n("Print Sky") );
1016         //QPrintDialog *dialog = KdePrint::createPrintDialog(&printer, this);
1017         QPrintDialog *dialog = new QPrintDialog(&printer, this);
1018         dialog->setWindowTitle(i18nc("@title:window", "Print Sky"));
1019         if (dialog->exec() == QDialog::Accepted)
1020             ok = true;
1021         delete dialog;
1022     }
1023     else
1024     {
1025         //QPRINTER_FOR_NOW
1026         //        ok = printer.autoConfigure();
1027         ok = true;
1028     }
1029 
1030     if (ok)
1031     {
1032         QApplication::setOverrideCursor(Qt::WaitCursor);
1033 
1034         //Save current ColorScheme file name and switch to Star Chart
1035         //scheme (if requested)
1036         QString schemeName = data()->colorScheme()->fileName();
1037         if (useChartColors)
1038         {
1039             loadColorScheme("chart.colors");
1040         }
1041 
1042         map()->setupProjector();
1043         map()->exportSkyImage(&printer, true);
1044 
1045         //Restore old color scheme if necessary
1046         //(if printing was aborted, the ColorScheme is still restored)
1047         if (useChartColors)
1048         {
1049             loadColorScheme(schemeName);
1050             map()->forceUpdate();
1051         }
1052 
1053         QApplication::restoreOverrideCursor();
1054     }
1055 }
1056 
1057 void KStars::openFITS(const QUrl &imageURL)
1058 {
1059 #ifndef HAVE_CFITSIO
1060     qWarning() << "KStars does not support loading FITS. Please recompile KStars with FITS support.";
1061 #else
1062     QSharedPointer<FITSViewer> fv = createFITSViewer();
1063     fv->loadFile(imageURL);
1064 #endif
1065 }