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 }