File indexing completed on 2025-04-20 06:34:39
0001 /* 0002 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kspopupmenu.h" 0008 0009 #include "config-kstars.h" 0010 0011 #include "kstars.h" 0012 #include "kstarsdata.h" 0013 #include "skymap.h" 0014 #include "skyobjects/skyobject.h" 0015 #include "skyobjects/starobject.h" 0016 #include "skyobjects/trailobject.h" 0017 #include "skyobjects/catalogobject.h" 0018 #include "skyobjects/ksmoon.h" 0019 #include "skyobjects/satellite.h" 0020 #include "skyobjects/supernova.h" 0021 #include "skycomponents/constellationboundarylines.h" 0022 #include "skycomponents/flagcomponent.h" 0023 #include "skycomponents/skymapcomposite.h" 0024 #include "skyobjectuserdata.h" 0025 #include "tools/whatsinteresting/wiview.h" 0026 #include "catalogsdb.h" 0027 #include "observinglist.h" 0028 0029 #ifdef HAVE_INDI 0030 #include "indi/indilistener.h" 0031 #include "indi/guimanager.h" 0032 #include "indi/driverinfo.h" 0033 #include "indi/indistd.h" 0034 #include "indi/indidevice.h" 0035 #include "indi/indigroup.h" 0036 #include "indi/indiproperty.h" 0037 #include "indi/indielement.h" 0038 #include "indi/indimount.h" 0039 #include <basedevice.h> 0040 #endif 0041 0042 #include <KLocalizedString> 0043 0044 #include <QWidgetAction> 0045 0046 namespace 0047 { 0048 // Convert magnitude to string representation for QLabel 0049 QString magToStr(double m) 0050 { 0051 if (m > -30 && m < 90) 0052 return QString("%1<sup>m</sup>").arg(m, 0, 'f', 2); 0053 else 0054 return QString(); 0055 } 0056 0057 // Return object name 0058 QString getObjectName(SkyObject *obj) 0059 { 0060 // FIXME: make logic less convoluted. 0061 if (obj->longname() != obj->name()) // Object has proper name 0062 { 0063 return obj->translatedLongName() + ", " + obj->translatedName(); 0064 } 0065 else 0066 { 0067 if (!obj->translatedName2().isEmpty()) 0068 return obj->translatedName() + ", " + obj->translatedName2(); 0069 else 0070 return obj->translatedName(); 0071 } 0072 } 0073 0074 // String representation for rise/set time of object. If object 0075 // doesn't rise/set returns descriptive string. 0076 // 0077 // Second parameter choose between raise and set. 'true' for 0078 // raise, 'false' for set. 0079 QString riseSetTimeLabel(SkyObject *o, bool isRaise) 0080 { 0081 KStarsData *data = KStarsData::Instance(); 0082 QTime t = o->riseSetTime(data->ut(), data->geo(), isRaise); 0083 if (t.isValid()) 0084 { 0085 //We can round to the nearest minute by simply adding 30 seconds to the time. 0086 QString time = QLocale().toString(t.addSecs(30), QLocale::ShortFormat); 0087 return isRaise ? i18n("Rise time: %1", time) : 0088 i18nc("the time at which an object falls below the horizon", 0089 "Set time: %1", time); 0090 } 0091 if (o->alt().Degrees() > 0) 0092 return isRaise ? i18n("No rise time: Circumpolar") : 0093 i18n("No set time: Circumpolar"); 0094 else 0095 return isRaise ? i18n("No rise time: Never rises") : 0096 i18n("No set time: Never rises"); 0097 } 0098 0099 // String representation for transit time for object 0100 QString transitTimeLabel(SkyObject *o) 0101 { 0102 KStarsData *data = KStarsData::Instance(); 0103 QTime t = o->transitTime(data->ut(), data->geo()); 0104 if (t.isValid()) 0105 //We can round to the nearest minute by simply adding 30 seconds to the time. 0106 return i18n("Transit time: %1", 0107 QLocale().toString(t.addSecs(30), QLocale::ShortFormat)); 0108 else 0109 return "--:--"; 0110 } 0111 } // namespace 0112 0113 KSPopupMenu::KSPopupMenu() 0114 : QMenu(KStars::Instance()), m_CurrentFlagIdx(-1), m_EditActionMapping(nullptr), 0115 m_DeleteActionMapping(nullptr) 0116 { 0117 } 0118 0119 KSPopupMenu::~KSPopupMenu() 0120 { 0121 if (m_EditActionMapping) 0122 { 0123 delete m_EditActionMapping; 0124 } 0125 0126 if (m_DeleteActionMapping) 0127 { 0128 delete m_DeleteActionMapping; 0129 } 0130 } 0131 0132 void KSPopupMenu::createEmptyMenu(SkyPoint *nullObj) 0133 { 0134 KStars *ks = KStars::Instance(); 0135 SkyObject o(SkyObject::TYPE_UNKNOWN, nullObj->ra(), nullObj->dec()); 0136 o.setAlt(nullObj->alt()); 0137 o.setAz(nullObj->az()); 0138 initPopupMenu(&o, i18n("Empty sky"), QString(), QString(), false, false); 0139 addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), 0140 SLOT(slotSDSS())); 0141 addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), 0142 SLOT(slotDSS())); 0143 } 0144 0145 void KSPopupMenu::slotEditFlag() 0146 { 0147 if (m_CurrentFlagIdx != -1) 0148 { 0149 KStars::Instance()->map()->slotEditFlag(m_CurrentFlagIdx); 0150 } 0151 } 0152 0153 void KSPopupMenu::slotDeleteFlag() 0154 { 0155 if (m_CurrentFlagIdx != -1) 0156 { 0157 KStars::Instance()->map()->slotDeleteFlag(m_CurrentFlagIdx); 0158 } 0159 } 0160 0161 void KSPopupMenu::slotEditFlag(QAction *action) 0162 { 0163 int idx = m_EditActionMapping->value(action, -1); 0164 0165 if (idx == -1) 0166 { 0167 return; 0168 } 0169 0170 else 0171 { 0172 KStars::Instance()->map()->slotEditFlag(idx); 0173 } 0174 } 0175 0176 void KSPopupMenu::slotDeleteFlag(QAction *action) 0177 { 0178 int idx = m_DeleteActionMapping->value(action, -1); 0179 0180 if (idx == -1) 0181 { 0182 return; 0183 } 0184 0185 else 0186 { 0187 KStars::Instance()->map()->slotDeleteFlag(idx); 0188 } 0189 } 0190 0191 void KSPopupMenu::createStarMenu(StarObject *star) 0192 { 0193 KStars *ks = KStars::Instance(); 0194 //Add name, rise/set time, center/track, and detail-window items 0195 QString name; 0196 if (star->name() != "star") 0197 { 0198 name = star->translatedLongName(); 0199 } 0200 else 0201 { 0202 if (star->getHDIndex()) 0203 { 0204 name = QString("HD%1").arg(QString::number(star->getHDIndex())); 0205 } 0206 else 0207 { 0208 // FIXME: this should be some catalog name too 0209 name = "Star"; 0210 } 0211 } 0212 initPopupMenu(star, name, i18n("star"), 0213 i18n("%1<sup>m</sup>, %2", star->mag(), star->sptype())); 0214 //If the star is named, add custom items to popup menu based on object's ImageList and InfoList 0215 if (star->name() != "star") 0216 { 0217 addLinksToMenu(star); 0218 } 0219 else 0220 { 0221 addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), 0222 SLOT(slotSDSS())); 0223 addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), 0224 SLOT(slotDSS())); 0225 } 0226 } 0227 0228 void KSPopupMenu::createCatalogObjectMenu(CatalogObject *obj) 0229 { 0230 QString name = getObjectName(obj); 0231 QString typeName = obj->typeName(); 0232 0233 QString info = QString("%1<br>Catalog: %2") 0234 .arg(magToStr(obj->mag())) 0235 .arg(obj->getCatalog().name); 0236 0237 if (obj->a() > 0) 0238 { 0239 float a = obj->a(); 0240 float b = obj->b() > 0 ? obj->b() : obj->a(); // Assume circular if a != 0 but b == 0 0241 info += QString("<br>%1′×%2′").arg(a).arg(b); 0242 } 0243 0244 initPopupMenu(obj, name, typeName, info); 0245 addLinksToMenu(obj); 0246 } 0247 0248 void KSPopupMenu::createPlanetMenu(SkyObject *p) 0249 { 0250 QString info = magToStr(p->mag()); 0251 QString type = i18n("Solar system object"); 0252 initPopupMenu(p, p->translatedName(), type, info); 0253 addLinksToMenu(p, false); //don't offer DSS images for planets 0254 } 0255 0256 void KSPopupMenu::createMoonMenu(KSMoon *moon) 0257 { 0258 QString info = QString("%1, %2").arg(magToStr(moon->mag()), moon->phaseName()); 0259 initPopupMenu(moon, moon->translatedName(), QString(), info); 0260 addLinksToMenu(moon, false); //don't offer DSS images for planets 0261 } 0262 0263 void KSPopupMenu::createSatelliteMenu(Satellite *satellite) 0264 { 0265 KStars *ks = KStars::Instance(); 0266 QString velocity, altitude, range; 0267 velocity.setNum(satellite->velocity()); 0268 altitude.setNum(satellite->altitude()); 0269 range.setNum(satellite->range()); 0270 0271 clear(); 0272 0273 addFancyLabel(satellite->name()); 0274 addFancyLabel(satellite->id()); 0275 addFancyLabel(i18n("satellite")); 0276 addFancyLabel(KStarsData::Instance() 0277 ->skyComposite() 0278 ->constellationBoundary() 0279 ->constellationName(satellite)); 0280 0281 addSeparator(); 0282 0283 addFancyLabel(i18n("Velocity: %1 km/s", velocity), -2); 0284 addFancyLabel(i18n("Altitude: %1 km", altitude), -2); 0285 addFancyLabel(i18n("Range: %1 km", range), -2); 0286 0287 addSeparator(); 0288 0289 //Insert item for centering on object 0290 addAction(QIcon::fromTheme("snap-nodes-center"), i18n("Center && Track"), ks->map(), 0291 SLOT(slotCenter())); 0292 //Insert item for measuring distances 0293 //FIXME: add key shortcut to menu items properly! 0294 addAction(QIcon::fromTheme("kruler-east"), 0295 i18n("Angular Distance To... ["), ks->map(), 0296 SLOT(slotBeginAngularDistance())); 0297 addAction(QIcon::fromTheme("show-path-outline"), 0298 i18n("Starhop from here to... "), ks->map(), 0299 SLOT(slotBeginStarHop())); 0300 addAction(QIcon::fromTheme("edit-copy"), i18n("Copy TLE to Clipboard"), ks->map(), 0301 SLOT(slotCopyTLE())); 0302 0303 //Insert "Add/Remove Label" item 0304 if (ks->map()->isObjectLabeled(satellite)) 0305 addAction(QIcon::fromTheme("list-remove"), i18n("Remove Label"), ks->map(), 0306 SLOT(slotRemoveObjectLabel())); 0307 else 0308 addAction(QIcon::fromTheme("label"), i18n("Attach Label"), ks->map(), 0309 SLOT(slotAddObjectLabel())); 0310 0311 addSeparator(); 0312 addINDI(); 0313 } 0314 0315 void KSPopupMenu::createSupernovaMenu(Supernova *supernova) 0316 { 0317 QString name = supernova->name(); 0318 float mag = supernova->mag(); 0319 float z = supernova->getRedShift(); 0320 QString type = supernova->getType(); 0321 0322 QString info; 0323 0324 if (mag < 99) 0325 info += QString("%1<sup>m</sup> ").arg(mag); 0326 info += type; 0327 if (z < 99) 0328 info += QString(" z: %1").arg(QString::number(z, 'f', 2)); 0329 0330 initPopupMenu(supernova, name, i18n("supernova"), info); 0331 } 0332 0333 void KSPopupMenu::initPopupMenu(SkyObject *obj, const QString &name, const QString &type, 0334 QString info, bool showDetails, bool showObsList, 0335 bool showFlags) 0336 { 0337 KStarsData *data = KStarsData::Instance(); 0338 SkyMap *map = SkyMap::Instance(); 0339 0340 clear(); 0341 bool showLabel = (name != i18n("star") && !name.isEmpty()); 0342 QString Name = name; 0343 0344 if (Name.isEmpty()) 0345 Name = i18n("Empty sky"); 0346 0347 addFancyLabel(Name); 0348 addFancyLabel(type); 0349 addFancyLabel(info); 0350 addFancyLabel(KStarsData::Instance() 0351 ->skyComposite() 0352 ->constellationBoundary() 0353 ->constellationName(obj)); 0354 0355 //Insert Rise/Set/Transit labels 0356 SkyObject *o = obj->clone(); 0357 addSeparator(); 0358 addFancyLabel(riseSetTimeLabel(o, true), -2); 0359 addFancyLabel(riseSetTimeLabel(o, false), -2); 0360 addFancyLabel(transitTimeLabel(o), -2); 0361 addSeparator(); 0362 delete o; 0363 0364 // Show 'Select this object' item when in object pointing mode and when obj is not empty sky 0365 if (map->isInObjectPointingMode() && obj->type() != 21) 0366 { 0367 addAction(i18n("Select this object"), map, SLOT(slotObjectSelected())); 0368 } 0369 0370 //Insert item for centering on object 0371 addAction(QIcon::fromTheme("snap-nodes-center"), i18n("Center && Track"), map, 0372 SLOT(slotCenter())); 0373 0374 if (showFlags) 0375 { 0376 //Insert actions for flag operations 0377 initFlagActions(obj); 0378 } 0379 0380 //Insert item for measuring distances 0381 //FIXME: add key shortcut to menu items properly! 0382 addAction(QIcon::fromTheme("kruler-east"), 0383 i18n("Angular Distance To... ["), map, 0384 SLOT(slotBeginAngularDistance())); 0385 addAction(QIcon::fromTheme("show-path-outline"), 0386 i18n("Starhop from here to... "), map, SLOT(slotBeginStarHop())); 0387 0388 //Insert item for Showing details dialog 0389 if (showDetails) 0390 addAction(QIcon::fromTheme("view-list-details"), 0391 i18nc("Show Detailed Information Dialog", "Details"), map, 0392 SLOT(slotDetail())); 0393 0394 addAction(QIcon::fromTheme("edit-copy"), i18n("Copy Coordinates"), map, 0395 SLOT(slotCopyCoordinates())); 0396 0397 //Insert "Add/Remove Label" item 0398 if (showLabel) 0399 { 0400 if (map->isObjectLabeled(obj)) 0401 { 0402 addAction(QIcon::fromTheme("list-remove"), i18n("Remove Label"), map, 0403 SLOT(slotRemoveObjectLabel())); 0404 } 0405 else 0406 { 0407 addAction(QIcon::fromTheme("label"), i18n("Attach Label"), map, 0408 SLOT(slotAddObjectLabel())); 0409 } 0410 } 0411 // Should show observing list 0412 if (showObsList) 0413 { 0414 if (data->observingList()->contains(obj)) 0415 addAction(QIcon::fromTheme("list-remove"), 0416 i18n("Remove From Observing WishList"), data->observingList(), 0417 SLOT(slotRemoveObject())); 0418 else 0419 addAction(QIcon::fromTheme("bookmarks"), i18n("Add to Observing WishList"), 0420 data->observingList(), SLOT(slotAddObject())); 0421 } 0422 // Should we show trail actions 0423 TrailObject *t = dynamic_cast<TrailObject *>(obj); 0424 if (t) 0425 { 0426 if (t->hasTrail()) 0427 addAction(i18n("Remove Trail"), map, SLOT(slotRemovePlanetTrail())); 0428 else 0429 addAction(i18n("Add Trail"), map, SLOT(slotAddPlanetTrail())); 0430 } 0431 0432 addAction(QIcon::fromTheme("redeyes"), i18n("Simulate Eyepiece View"), map, 0433 SLOT(slotEyepieceView())); 0434 0435 addSeparator(); 0436 if (obj->isSolarSystem() && 0437 obj->type() != 0438 SkyObject:: 0439 COMET) // FIXME: We now have asteroids -- so should this not be isMajorPlanet() || Pluto? 0440 { 0441 addAction(i18n("View in XPlanet"), map, SLOT(slotStartXplanetViewer())); 0442 } 0443 addSeparator(); 0444 addINDI(); 0445 0446 addAction(QIcon::fromTheme("view-list-details"), i18n("View in What's Interesting"), 0447 this, SLOT(slotViewInWI())); 0448 } 0449 0450 void KSPopupMenu::initFlagActions(SkyObject *obj) 0451 { 0452 KStars *ks = KStars::Instance(); 0453 0454 QList<int> flags = ks->data()->skyComposite()->flags()->getFlagsNearPix(obj, 5); 0455 0456 if (flags.isEmpty()) 0457 { 0458 // There is no flag around clicked SkyObject 0459 addAction(QIcon::fromTheme("flag"), i18n("Add Flag..."), ks->map(), 0460 SLOT(slotAddFlag())); 0461 } 0462 0463 else if (flags.size() == 1) 0464 { 0465 // There is only one flag around clicked SkyObject 0466 addAction(QIcon::fromTheme("document-edit"), i18n("Edit Flag"), this, 0467 SLOT(slotEditFlag())); 0468 addAction(QIcon::fromTheme("delete"), i18n("Delete Flag"), this, 0469 SLOT(slotDeleteFlag())); 0470 0471 m_CurrentFlagIdx = flags.first(); 0472 } 0473 0474 else 0475 { 0476 // There are more than one flags around clicked SkyObject - we need to create submenus 0477 QMenu *editMenu = new QMenu(i18n("Edit Flag..."), KStars::Instance()); 0478 editMenu->setIcon(QIcon::fromTheme("document-edit")); 0479 QMenu *deleteMenu = new QMenu(i18n("Delete Flag..."), KStars::Instance()); 0480 deleteMenu->setIcon(QIcon::fromTheme("delete")); 0481 0482 connect(editMenu, SIGNAL(triggered(QAction *)), this, 0483 SLOT(slotEditFlag(QAction *))); 0484 connect(deleteMenu, SIGNAL(triggered(QAction *)), this, 0485 SLOT(slotDeleteFlag(QAction *))); 0486 0487 if (m_EditActionMapping) 0488 { 0489 delete m_EditActionMapping; 0490 } 0491 0492 if (m_DeleteActionMapping) 0493 { 0494 delete m_DeleteActionMapping; 0495 } 0496 0497 m_EditActionMapping = new QHash<QAction *, int>; 0498 m_DeleteActionMapping = new QHash<QAction *, int>; 0499 0500 foreach (int idx, flags) 0501 { 0502 QIcon flagIcon( 0503 QPixmap::fromImage(ks->data()->skyComposite()->flags()->image(idx))); 0504 0505 QString flagLabel = ks->data()->skyComposite()->flags()->label(idx); 0506 if (flagLabel.size() > 35) 0507 { 0508 flagLabel = flagLabel.left(35); 0509 flagLabel.append("..."); 0510 } 0511 0512 QAction *editAction = new QAction(flagIcon, flagLabel, ks); 0513 editAction->setIconVisibleInMenu(true); 0514 editMenu->addAction(editAction); 0515 m_EditActionMapping->insert(editAction, idx); 0516 0517 QAction *deleteAction = new QAction(flagIcon, flagLabel, ks); 0518 deleteAction->setIconVisibleInMenu(true); 0519 deleteMenu->addAction(deleteAction); 0520 m_DeleteActionMapping->insert(deleteAction, idx); 0521 } 0522 0523 addMenu(editMenu); 0524 addMenu(deleteMenu); 0525 } 0526 } 0527 0528 void KSPopupMenu::addLinksToMenu(SkyObject *obj, bool showDSS) 0529 { 0530 KStars *ks = KStars::Instance(); 0531 0532 const auto &user_data = KStarsData::Instance()->getUserData(obj->name()); 0533 const auto &image_list = user_data.images(); 0534 const auto &website_list = user_data.websites(); 0535 for (const auto &res : std::list < 0536 std::tuple<QString, SkyObjectUserdata::LinkList, SkyObjectUserdata::Type >> 0537 { 0538 { i18n("Image Resources"), image_list, SkyObjectUserdata::Type::image }, 0539 { i18n("Web Links"), website_list, SkyObjectUserdata::Type::website } 0540 }) 0541 { 0542 const auto &title = std::get<0>(res); 0543 const auto &list = std::get<1>(res); 0544 const auto &type = std::get<2>(res); 0545 0546 if (!list.empty()) 0547 { 0548 QMenu *LinkSubMenu = new QMenu(); 0549 LinkSubMenu->setTitle(title); 0550 for (const auto &entry : list) 0551 { 0552 QString t = QString(entry.title); 0553 QAction *action; 0554 if (type == SkyObjectUserdata::Type::website) 0555 action = LinkSubMenu->addAction( 0556 i18nc("Image/info menu item (should be translated)", 0557 t.toLocal8Bit()), 0558 ks->map(), SLOT(slotInfo())); 0559 else 0560 action = LinkSubMenu->addAction( 0561 i18nc("Image/info menu item (should be translated)", 0562 t.toLocal8Bit()), 0563 ks->map(), SLOT(slotImage())); 0564 0565 action->setData(entry.url); 0566 } 0567 addMenu(LinkSubMenu); 0568 } 0569 } 0570 0571 // Look for a custom object 0572 { 0573 auto *object = dynamic_cast<CatalogObject *>(obj); 0574 if (object) 0575 { 0576 CatalogsDB::DBManager manager{ CatalogsDB::dso_db_path() }; 0577 0578 if (object->getCatalog().mut && 0579 manager.get_object(object->getObjectId()).first) 0580 { 0581 addAction(i18n("Remove From Local Catalog"), ks->map(), 0582 SLOT(slotRemoveCustomObject())); 0583 } 0584 } 0585 } 0586 0587 if (showDSS) 0588 { 0589 addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), 0590 SLOT(slotSDSS())); 0591 addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), 0592 SLOT(slotDSS())); 0593 } 0594 0595 if (showDSS) 0596 addSeparator(); 0597 } 0598 0599 void KSPopupMenu::addINDI() 0600 { 0601 #ifdef HAVE_INDI 0602 if (INDIListener::Instance()->size() == 0) 0603 return; 0604 0605 for (auto &oneDevice : INDIListener::devices()) 0606 { 0607 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0608 continue; 0609 0610 0611 auto mount = oneDevice->getMount(); 0612 if (!mount) 0613 continue; 0614 0615 QMenu *mountMenu = new QMenu(mount->getDeviceName()); 0616 mountMenu->setIcon(QIcon::fromTheme("kstars")); 0617 addMenu(mountMenu); 0618 0619 if (mount->canGoto() || mount->canSync()) 0620 { 0621 if (mount->canGoto()) 0622 { 0623 QAction *a = mountMenu->addAction(QIcon::fromTheme("object-rotate-right"), 0624 i18nc("Move mount to target", "Goto")); 0625 a->setEnabled(!mount->isParked()); 0626 connect(a, &QAction::triggered, 0627 [mount] { mount->Slew(SkyMap::Instance()->clickedPoint()); }); 0628 } 0629 if (mount->canSync()) 0630 { 0631 QAction *a = 0632 mountMenu->addAction(QIcon::fromTheme("media-record"), 0633 i18nc("Synchronize mount to target", "Sync")); 0634 a->setEnabled(!mount->isParked()); 0635 connect(a, &QAction::triggered, 0636 [mount] { mount->Sync(SkyMap::Instance()->clickedPoint()); }); 0637 } 0638 0639 mountMenu->addSeparator(); 0640 } 0641 0642 if (mount->canAbort()) 0643 { 0644 QAction *a = 0645 mountMenu->addAction(QIcon::fromTheme("process-stop"), i18n("Abort")); 0646 a->setEnabled(!mount->isParked()); 0647 connect(a, &QAction::triggered, [mount] { mount->abort(); }); 0648 mountMenu->addSeparator(); 0649 } 0650 0651 if (mount->canPark()) 0652 { 0653 QAction *park = 0654 mountMenu->addAction(QIcon::fromTheme("flag-red"), i18n("Park")); 0655 park->setEnabled(!mount->isParked()); 0656 connect(park, &QAction::triggered, [mount] { mount->park(); }); 0657 0658 QAction *unpark = 0659 mountMenu->addAction(QIcon::fromTheme("flag-green"), i18n("UnPark")); 0660 unpark->setEnabled(mount->isParked()); 0661 connect(unpark, &QAction::triggered, [mount] { mount->unpark(); }); 0662 0663 mountMenu->addSeparator(); 0664 } 0665 0666 const SkyObject *clickedObject = KStars::Instance()->map()->clickedObject(); 0667 if (clickedObject && clickedObject->type() == SkyObject::SATELLITE && 0668 (mount->canTrackSatellite())) 0669 { 0670 const Satellite *sat = dynamic_cast<const Satellite *>(clickedObject); 0671 const KStarsDateTime currentTime = KStarsData::Instance()->ut(); 0672 const KStarsDateTime currentTimePlusOne = currentTime.addSecs(60); 0673 QAction *a = 0674 mountMenu->addAction(QIcon::fromTheme("arrow"), i18n("Track satellite")); 0675 a->setEnabled(!mount->isParked()); 0676 connect(a, &QAction::triggered, 0677 [mount, sat, currentTime, currentTimePlusOne] 0678 { 0679 mount->setSatelliteTLEandTrack(sat->tle(), currentTime, 0680 currentTimePlusOne); 0681 }); 0682 mountMenu->addSeparator(); 0683 } 0684 0685 if (mount->canCustomPark()) 0686 { 0687 QAction *a = mountMenu->addAction(QIcon::fromTheme("go-jump-declaration"), 0688 i18n("Goto && Set As Parking Position")); 0689 a->setEnabled(!mount->isParked()); 0690 connect(a, &QAction::triggered, 0691 [mount] { mount->setCustomParking(); }); 0692 } 0693 0694 QAction *a = 0695 mountMenu->addAction(QIcon::fromTheme("edit-find"), i18n("Find Telescope")); 0696 connect(a, &QAction::triggered, 0697 [mount] { mount->find(); }); 0698 } 0699 #endif 0700 } 0701 0702 void KSPopupMenu::addFancyLabel(const QString &name, int deltaFontSize) 0703 { 0704 if (name.isEmpty()) 0705 return; 0706 QLabel *label = new QLabel("<b>" + name + "</b>", this); 0707 label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 0708 if (deltaFontSize != 0) 0709 { 0710 QFont font = label->font(); 0711 font.setPointSize(font.pointSize() + deltaFontSize); 0712 label->setFont(font); 0713 } 0714 QWidgetAction *act = new QWidgetAction(this); 0715 act->setDefaultWidget(label); 0716 addAction(act); 0717 } 0718 0719 void KSPopupMenu::slotViewInWI() 0720 { 0721 if (!KStars::Instance()->map()->clickedObject()) 0722 return; 0723 if (!KStars::Instance()->isWIVisible()) 0724 KStars::Instance()->slotToggleWIView(); 0725 KStars::Instance()->wiView()->inspectSkyObject( 0726 KStars::Instance()->map()->clickedObject()); 0727 }