Warning, file /education/kstars/kstars/kstarsactions.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2002 Jason Harris <jharris@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // This file contains function definitions for Actions declared in kstars.h 0008 0009 #include "kstars.h" 0010 0011 #include "imageexporter.h" 0012 #include "kstarsdata.h" 0013 #include "kstars_debug.h" 0014 #include "ksnotification.h" 0015 #include "kswizard.h" 0016 #include "Options.h" 0017 #include "skymap.h" 0018 #include "texturemanager.h" 0019 #include "dialogs/exportimagedialog.h" 0020 #include "dialogs/finddialog.h" 0021 #include "dialogs/focusdialog.h" 0022 #include "dialogs/fovdialog.h" 0023 #include "dialogs/locationdialog.h" 0024 #include "dialogs/timedialog.h" 0025 #include "dialogs/catalogsdbui.h" 0026 #include "oal/execute.h" 0027 #include "oal/equipmentwriter.h" 0028 #include "oal/observeradd.h" 0029 #include "options/opsadvanced.h" 0030 #include "options/opscatalog.h" 0031 #include "options/opscolors.h" 0032 #include "options/opsguides.h" 0033 #include "options/opsterrain.h" 0034 #include "options/opsdeveloper.h" 0035 #include "options/opssatellites.h" 0036 #include "options/opssolarsystem.h" 0037 #include "options/opssupernovae.h" 0038 #include "printing/printingwizard.h" 0039 #include "projections/projector.h" 0040 #include "skycomponents/asteroidscomponent.h" 0041 #include "skycomponents/cometscomponent.h" 0042 #include "skycomponents/satellitescomponent.h" 0043 #include "skycomponents/skymapcomposite.h" 0044 #include "skycomponents/solarsystemcomposite.h" 0045 #include "skycomponents/supernovaecomponent.h" 0046 #include "skycomponents/catalogscomponent.h" 0047 #include "skycomponents/mosaiccomponent.h" 0048 #ifdef HAVE_INDI 0049 #include "skyobjects/mosaictiles.h" 0050 #endif 0051 #include "tools/altvstime.h" 0052 #include "tools/astrocalc.h" 0053 #include "tools/eyepiecefield.h" 0054 #include "tools/flagmanager.h" 0055 #include "tools/horizonmanager.h" 0056 #include "tools/observinglist.h" 0057 #include "tools/planetviewer.h" 0058 #include "tools/jmoontool.h" 0059 #include "tools/scriptbuilder.h" 0060 #include "tools/skycalendar.h" 0061 #include "tools/wutdialog.h" 0062 #include "tools/polarishourangle.h" 0063 #include "tools/whatsinteresting/wiequipsettings.h" 0064 #include "tools/whatsinteresting/wilpsettings.h" 0065 #include "tools/whatsinteresting/wiview.h" 0066 #include "hips/hipsmanager.h" 0067 #include "catalogsdb.h" 0068 #ifdef HAVE_INDI 0069 #include <basedevice.h> 0070 //#include "indi/telescopewizardprocess.h" 0071 #include "indi/opsindi.h" 0072 #include "indi/drivermanager.h" 0073 #include "indi/guimanager.h" 0074 #include "indi/indilistener.h" 0075 #endif 0076 0077 #ifdef HAVE_CFITSIO 0078 #include "fitsviewer/fitsviewer.h" 0079 #include "fitsviewer/opsfits.h" 0080 #ifdef HAVE_INDI 0081 #include "ekos/manager.h" 0082 #include "ekos/scheduler/framingassistantui.h" 0083 #include "ekos/opsekos.h" 0084 #endif 0085 #endif 0086 0087 #include "xplanet/opsxplanet.h" 0088 0089 #ifdef HAVE_NOTIFYCONFIG 0090 #include <KNotifyConfigWidget> 0091 #endif 0092 #include <KActionCollection> 0093 #include <KActionMenu> 0094 #include <KTipDialog> 0095 #include <KToggleAction> 0096 #include <kns3/downloaddialog.h> 0097 0098 #include <QQuickWindow> 0099 #include <QQuickView> 0100 0101 #ifdef _WIN32 0102 #include <windows.h> 0103 #undef interface 0104 #endif 0105 #include <sys/stat.h> 0106 0107 /** ViewToolBar Action. All of the viewToolBar buttons are connected to this slot. **/ 0108 0109 void KStars::slotViewToolBar() 0110 { 0111 KToggleAction *a = (KToggleAction *)sender(); 0112 KConfigDialog *kcd = KConfigDialog::exists("settings"); 0113 0114 if (a == actionCollection()->action("show_stars")) 0115 { 0116 Options::setShowStars(a->isChecked()); 0117 if (kcd) 0118 { 0119 opcatalog->kcfg_ShowStars->setChecked(a->isChecked()); 0120 } 0121 } 0122 else if (a == actionCollection()->action("show_deepsky")) 0123 { 0124 Options::setShowDeepSky(a->isChecked()); 0125 if (kcd) 0126 { 0127 opcatalog->kcfg_ShowDeepSky->setChecked(a->isChecked()); 0128 } 0129 } 0130 else if (a == actionCollection()->action("show_planets")) 0131 { 0132 Options::setShowSolarSystem(a->isChecked()); 0133 if (kcd) 0134 { 0135 opsolsys->kcfg_ShowSolarSystem->setChecked(a->isChecked()); 0136 } 0137 } 0138 else if (a == actionCollection()->action("show_clines")) 0139 { 0140 Options::setShowCLines(a->isChecked()); 0141 if (kcd) 0142 { 0143 opguides->kcfg_ShowCLines->setChecked(a->isChecked()); 0144 } 0145 } 0146 else if (a == actionCollection()->action("show_cnames")) 0147 { 0148 Options::setShowCNames(a->isChecked()); 0149 if (kcd) 0150 { 0151 opguides->kcfg_ShowCNames->setChecked(a->isChecked()); 0152 } 0153 } 0154 else if (a == actionCollection()->action("show_cbounds")) 0155 { 0156 Options::setShowCBounds(a->isChecked()); 0157 if (kcd) 0158 { 0159 opguides->kcfg_ShowCBounds->setChecked(a->isChecked()); 0160 } 0161 } 0162 else if (a == actionCollection()->action("show_constellationart")) 0163 { 0164 Options::setShowConstellationArt(a->isChecked()); 0165 if (kcd) 0166 { 0167 opguides->kcfg_ShowConstellationArt->setChecked(a->isChecked()); 0168 } 0169 } 0170 else if (a == actionCollection()->action("show_mw")) 0171 { 0172 Options::setShowMilkyWay(a->isChecked()); 0173 if (kcd) 0174 { 0175 opguides->kcfg_ShowMilkyWay->setChecked(a->isChecked()); 0176 } 0177 } 0178 else if (a == actionCollection()->action("show_equatorial_grid")) 0179 { 0180 // if autoSelectGrid is selected and the user clicked the 0181 // show_equatorial_grid button, he probably wants us to disable 0182 // the autoSelectGrid and display the equatorial grid. 0183 Options::setAutoSelectGrid(false); 0184 Options::setShowEquatorialGrid(a->isChecked()); 0185 if (kcd) 0186 { 0187 opguides->kcfg_ShowEquatorialGrid->setChecked(a->isChecked()); 0188 opguides->kcfg_AutoSelectGrid->setChecked(false); 0189 } 0190 } 0191 else if (a == actionCollection()->action("show_horizontal_grid")) 0192 { 0193 Options::setAutoSelectGrid(false); 0194 Options::setShowHorizontalGrid(a->isChecked()); 0195 if (kcd) 0196 { 0197 opguides->kcfg_ShowHorizontalGrid->setChecked(a->isChecked()); 0198 opguides->kcfg_AutoSelectGrid->setChecked(false); 0199 } 0200 } 0201 else if (a == actionCollection()->action("show_horizon")) 0202 { 0203 Options::setShowGround(a->isChecked()); 0204 if (!a->isChecked() && Options::useRefraction()) 0205 { 0206 QString caption = i18n("Refraction effects disabled"); 0207 QString message = i18n("When the horizon is switched off, refraction effects " 0208 "are temporarily disabled."); 0209 0210 KMessageBox::information(this, message, caption, "dag_refract_hide_ground"); 0211 } 0212 if (kcd) 0213 { 0214 opguides->kcfg_ShowGround->setChecked(a->isChecked()); 0215 } 0216 } 0217 else if (a == actionCollection()->action("show_flags")) 0218 { 0219 Options::setShowFlags(a->isChecked()); 0220 if (kcd) 0221 { 0222 opguides->kcfg_ShowFlags->setChecked(a->isChecked()); 0223 } 0224 } 0225 else if (a == actionCollection()->action("show_satellites")) 0226 { 0227 Options::setShowSatellites(a->isChecked()); 0228 if (kcd) 0229 { 0230 opssatellites->kcfg_ShowSatellites->setChecked(a->isChecked()); 0231 } 0232 } 0233 else if (a == actionCollection()->action("show_supernovae")) 0234 { 0235 Options::setShowSupernovae(a->isChecked()); 0236 if (kcd) 0237 { 0238 opssupernovae->kcfg_ShowSupernovae->setChecked(a->isChecked()); 0239 } 0240 } 0241 0242 // update time for all objects because they might be not initialized 0243 // it's needed when using horizontal coordinates 0244 data()->setFullTimeUpdate(); 0245 updateTime(); 0246 0247 map()->forceUpdate(); 0248 } 0249 0250 void KStars::slotINDIToolBar() 0251 { 0252 #ifdef HAVE_INDI 0253 KToggleAction *a = qobject_cast<KToggleAction *>(sender()); 0254 0255 if (a == actionCollection()->action("show_control_panel")) 0256 { 0257 if (a->isChecked()) 0258 { 0259 GUIManager::Instance()->raise(); 0260 GUIManager::Instance()->activateWindow(); 0261 GUIManager::Instance()->showNormal(); 0262 } 0263 else 0264 GUIManager::Instance()->hide(); 0265 } 0266 else if (a == actionCollection()->action("show_ekos")) 0267 { 0268 if (a->isChecked()) 0269 { 0270 Ekos::Manager::Instance()->raise(); 0271 Ekos::Manager::Instance()->activateWindow(); 0272 Ekos::Manager::Instance()->showNormal(); 0273 } 0274 else 0275 Ekos::Manager::Instance()->hide(); 0276 } 0277 else if (a == actionCollection()->action("lock_telescope")) 0278 { 0279 for (auto &oneDevice : INDIListener::devices()) 0280 { 0281 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0282 continue; 0283 0284 if (oneDevice->isConnected() == false) 0285 { 0286 KSNotification::error(i18n("Mount %1 is offline. Please connect and retry again.", oneDevice->getDeviceName())); 0287 return; 0288 } 0289 0290 auto mount = oneDevice->getMount(); 0291 if (!mount) 0292 continue; 0293 0294 if (a->isChecked()) 0295 mount->centerLock(); 0296 else 0297 mount->centerUnlock(); 0298 return; 0299 } 0300 0301 KSNotification::sorry(i18n("No connected mounts found.")); 0302 return; 0303 } 0304 else if (a == actionCollection()->action("show_fits_viewer")) 0305 { 0306 if (m_FITSViewers.isEmpty()) 0307 { 0308 a->setEnabled(false); 0309 return; 0310 } 0311 0312 if (a->isChecked()) 0313 { 0314 for (auto &view : m_FITSViewers) 0315 { 0316 if (view->getTabs().empty() == false) 0317 { 0318 view->raise(); 0319 view->activateWindow(); 0320 view->showNormal(); 0321 } 0322 } 0323 } 0324 else 0325 { 0326 for (auto &view : m_FITSViewers) 0327 { 0328 view->hide(); 0329 } 0330 } 0331 } 0332 else if (a == actionCollection()->action("show_mount_box")) 0333 { 0334 Ekos::Manager::Instance()->mountModule()->toggleMountToolBox(); 0335 } 0336 else if (a == actionCollection()->action("show_sensor_fov")) 0337 { 0338 Options::setShowSensorFOV(a->isChecked()); 0339 for (auto &oneFOV : data()->getTransientFOVs()) 0340 { 0341 if (oneFOV->objectName() == "sensor_fov") 0342 oneFOV->setProperty("visible", a->isChecked()); 0343 } 0344 } 0345 else if (a == actionCollection()->action("show_mosaic_panel")) 0346 { 0347 Options::setShowMosaicPanel(a->isChecked()); 0348 // TODO 0349 // If scheduler is not running, then we should also show the Mosaic Planner dialog. 0350 auto scheduler = Ekos::Manager::Instance()->schedulerModule(); 0351 if (a->isChecked() && scheduler && scheduler->status() != Ekos::SCHEDULER_RUNNING) 0352 { 0353 // Only create if we don't have an instance already 0354 if (findChild<Ekos::FramingAssistantUI *>("FramingAssistant") == nullptr) 0355 { 0356 Ekos::FramingAssistantUI *assistant = new Ekos::FramingAssistantUI(); 0357 assistant->setAttribute(Qt::WA_DeleteOnClose, true); 0358 assistant->show(); 0359 } 0360 } 0361 } 0362 0363 #endif 0364 } 0365 0366 void KStars::slotSetTelescopeEnabled(bool enable) 0367 { 0368 telescopeGroup->setEnabled(enable); 0369 if (enable == false) 0370 { 0371 for (QAction *a : telescopeGroup->actions()) 0372 { 0373 a->setChecked(false); 0374 } 0375 } 0376 } 0377 0378 void KStars::slotSetDomeEnabled(bool enable) 0379 { 0380 domeGroup->setEnabled(enable); 0381 if (enable == false) 0382 { 0383 for (QAction *a : domeGroup->actions()) 0384 { 0385 a->setChecked(false); 0386 } 0387 } 0388 } 0389 0390 /** Major Dialog Window Actions **/ 0391 0392 void KStars::slotCalculator() 0393 { 0394 if (!m_AstroCalc) 0395 m_AstroCalc = new AstroCalc(this); 0396 m_AstroCalc->show(); 0397 } 0398 0399 void KStars::slotWizard() 0400 { 0401 QPointer<KSWizard> wizard = new KSWizard(this); 0402 if (wizard->exec() == QDialog::Accepted) 0403 { 0404 Options::setRunStartupWizard(false); //don't run on startup next time 0405 if (wizard->geo()) 0406 updateLocationFromWizard(*(wizard->geo())); 0407 } 0408 } 0409 0410 void KStars::updateLocationFromWizard(const GeoLocation &geo) 0411 { 0412 data()->setLocation(geo); 0413 // adjust local time to keep UT the same. 0414 // create new LT without DST offset 0415 KStarsDateTime ltime = data()->geo()->UTtoLT(data()->ut()); 0416 0417 // reset timezonerule to compute next dst change 0418 data()->geo()->tzrule()->reset_with_ltime(ltime, data()->geo()->TZ0(), 0419 data()->isTimeRunningForward()); 0420 0421 // reset next dst change time 0422 data()->setNextDSTChange(data()->geo()->tzrule()->nextDSTChange()); 0423 0424 // reset local sideral time 0425 data()->syncLST(); 0426 0427 // Make sure Numbers, Moon, planets, and sky objects are updated immediately 0428 data()->setFullTimeUpdate(); 0429 0430 // If the sky is in Horizontal mode and not tracking, reset focus such that 0431 // Alt/Az remain constant. 0432 if (!Options::isTracking() && Options::useAltAz()) 0433 { 0434 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); 0435 } 0436 0437 // recalculate new times and objects 0438 data()->setSnapNextFocus(); 0439 updateTime(); 0440 } 0441 0442 void KStars::slotDownload() 0443 { 0444 KSNotification::event( 0445 QLatin1String("KnownIssue"), 0446 i18n("Due to a known issue in the kde frameworks, " 0447 "updating already downloaded items is currently not possible. <br> " 0448 "Please uninstall and reinstall them to update.")); 0449 0450 // 2017-07-04: Explicitly load kstars.knsrc from resources file 0451 auto dlg = std::make_unique<KNS3::DownloadDialog>(":/kconfig/kstars.knsrc", this); 0452 0453 if (!dlg) 0454 return; 0455 0456 dlg->exec(); 0457 0458 // Get the list of all the installed entries. 0459 const auto changed_entries = dlg->changedEntries(); 0460 0461 CatalogsDB::DBManager manager{ CatalogsDB::dso_db_path() }; 0462 for (const KNS3::Entry &entry : changed_entries) 0463 { 0464 if (entry.category() != "dso") 0465 continue; 0466 const auto id = entry.id().toInt(); 0467 0468 if (entry.status() == KNS3::Entry::Installed) 0469 for (const QString &name : entry.installedFiles()) 0470 { 0471 if (name.endsWith(CatalogsDB::db_file_extension)) 0472 { 0473 const auto meta{ CatalogsDB::read_catalog_meta_from_file(name) }; 0474 0475 if (!meta.first) 0476 { 0477 QMessageBox::critical( 0478 this, i18n("Error"), 0479 i18n("The catalog \"%1\" is corrupt.", entry.name())); 0480 continue; 0481 } 0482 0483 if (meta.second.id != id) 0484 { 0485 QMessageBox::critical( 0486 this, i18n("Error"), 0487 i18n("The catalog \"%1\" is corrupt.<br>Expected id=%2 but " 0488 "got id=%3", 0489 entry.name(), id, meta.second.id)); 0490 continue; 0491 } 0492 0493 const auto success{ manager.import_catalog(name, true) }; 0494 if (!success.first) 0495 QMessageBox::critical( 0496 this, i18n("Error"), 0497 i18n("Could not import the catalog \"%1\"<br>%2", 0498 entry.name(), success.second)); 0499 } 0500 } 0501 0502 if (entry.status() == KNS3::Entry::Deleted) 0503 { 0504 manager.remove_catalog(id); 0505 } 0506 } 0507 0508 TextureManager::discoverTextureDirs(); 0509 KStars::Instance()->data()->skyComposite()->reloadDeepSky(); 0510 KStars::Instance()->data()->setFullTimeUpdate(); 0511 KStars::Instance()->updateTime(); 0512 KStars::Instance()->map()->forceUpdate(); 0513 } 0514 0515 void KStars::slotAVT() 0516 { 0517 if (!m_AltVsTime) 0518 m_AltVsTime = new AltVsTime(this); 0519 m_AltVsTime->show(); 0520 } 0521 0522 void KStars::slotWUT() 0523 { 0524 if (!m_WUTDialog) 0525 m_WUTDialog = new WUTDialog(this); 0526 m_WUTDialog->show(); 0527 } 0528 0529 //FIXME Port to QML2 0530 //#if 0 0531 void KStars::slotWISettings() 0532 { 0533 if (!m_WIView) 0534 slotToggleWIView(); 0535 if (m_WIView && !m_wiDock->isVisible()) 0536 slotToggleWIView(); 0537 0538 if (KConfigDialog::showDialog("wisettings")) 0539 { 0540 m_WIEquipmentSettings->populateScopeListWidget(); 0541 return; 0542 } 0543 0544 KConfigDialog *dialog = new KConfigDialog(this, "wisettings", Options::self()); 0545 0546 connect(dialog, SIGNAL(settingsChanged(QString)), this, 0547 SLOT(slotApplyWIConfigChanges())); 0548 0549 m_WISettings = new WILPSettings(this); 0550 m_WIEquipmentSettings = new WIEquipSettings(); 0551 dialog->addPage(m_WISettings, i18n("Light Pollution Settings")); 0552 dialog->addPage(m_WIEquipmentSettings, 0553 i18n("Equipment Settings - Equipment Type and Parameters")); 0554 dialog->exec(); 0555 if (m_WIEquipmentSettings) 0556 m_WIEquipmentSettings->setAperture(); //Something isn't working with this! 0557 } 0558 0559 void KStars::slotToggleWIView() 0560 { 0561 if (KStars::Closing) 0562 return; 0563 0564 if (!m_WIView) 0565 { 0566 m_WIView = new WIView(nullptr); 0567 m_wiDock = new QDockWidget(this); 0568 m_wiDock->setStyleSheet("QDockWidget::title{background-color:black;}"); 0569 m_wiDock->setObjectName("What's Interesting"); 0570 m_wiDock->setAllowedAreas(Qt::RightDockWidgetArea); 0571 QWidget *container = QWidget::createWindowContainer(m_WIView->getWIBaseView()); 0572 m_wiDock->setWidget(container); 0573 m_wiDock->setMinimumWidth(400); 0574 addDockWidget(Qt::RightDockWidgetArea, m_wiDock); 0575 connect(m_wiDock, SIGNAL(visibilityChanged(bool)), 0576 actionCollection()->action("show_whatsinteresting"), 0577 SLOT(setChecked(bool))); 0578 m_wiDock->setVisible(true); 0579 } 0580 else 0581 { 0582 m_wiDock->setVisible(!m_wiDock->isVisible()); 0583 } 0584 } 0585 0586 void KStars::slotCalendar() 0587 { 0588 if (!m_SkyCalendar) 0589 m_SkyCalendar = new SkyCalendar(this); 0590 m_SkyCalendar->show(); 0591 } 0592 0593 void KStars::slotGlossary() 0594 { 0595 // GlossaryDialog *dlg = new GlossaryDialog( this, true ); 0596 // QString glossaryfile =data()->stdDirs->findResource( "data", "kstars/glossary.xml" ); 0597 // QUrl u = glossaryfile; 0598 // Glossary *g = new Glossary( u ); 0599 // g->setName( i18n( "Knowledge" ) ); 0600 // dlg->addGlossary( g ); 0601 // dlg->show(); 0602 } 0603 0604 void KStars::slotScriptBuilder() 0605 { 0606 if (!m_ScriptBuilder) 0607 m_ScriptBuilder = new ScriptBuilder(this); 0608 m_ScriptBuilder->show(); 0609 } 0610 0611 void KStars::slotSolarSystem() 0612 { 0613 if (!m_PlanetViewer) 0614 m_PlanetViewer = new PlanetViewer(this); 0615 m_PlanetViewer->show(); 0616 } 0617 0618 void KStars::slotJMoonTool() 0619 { 0620 if (!m_JMoonTool) 0621 m_JMoonTool = new JMoonTool(this); 0622 m_JMoonTool->show(); 0623 } 0624 0625 void KStars::slotMoonPhaseTool() 0626 { 0627 //FIXME Port to KF5 0628 //if( ! mpt ) mpt = new MoonPhaseTool( this ); 0629 //mpt->show(); 0630 } 0631 0632 void KStars::slotFlagManager() 0633 { 0634 if (!m_FlagManager) 0635 m_FlagManager = new FlagManager(this); 0636 m_FlagManager->show(); 0637 } 0638 0639 #if 0 0640 void KStars::slotTelescopeWizard() 0641 { 0642 #ifdef HAVE_INDI 0643 #ifndef Q_OS_WIN 0644 0645 QString indiServerDir = Options::indiServer(); 0646 0647 #ifdef Q_OS_OSX 0648 if (Options::indiServerIsInternal()) 0649 indiServerDir = QCoreApplication::applicationDirPath(); 0650 else 0651 indiServerDir = QFileInfo(Options::indiServer()).dir().path(); 0652 #endif 0653 0654 QStringList paths; 0655 paths << "/usr/bin" 0656 << "/usr/local/bin" << indiServerDir; 0657 0658 if (QStandardPaths::findExecutable("indiserver").isEmpty()) 0659 { 0660 if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) 0661 { 0662 KSNotification::error(i18n("Unable to find INDI server. Please make sure the package that provides " 0663 "the 'indiserver' binary is installed.")); 0664 return; 0665 } 0666 } 0667 #endif 0668 0669 QPointer<telescopeWizardProcess> twiz = new telescopeWizardProcess(this); 0670 twiz->exec(); 0671 delete twiz; 0672 #endif 0673 } 0674 #endif 0675 0676 void KStars::slotINDIPanel() 0677 { 0678 #ifdef HAVE_INDI 0679 #ifndef Q_OS_WIN 0680 0681 QString indiServerDir = Options::indiServer(); 0682 0683 #ifdef Q_OS_OSX 0684 if (Options::indiServerIsInternal()) 0685 indiServerDir = QCoreApplication::applicationDirPath(); 0686 else 0687 indiServerDir = QFileInfo(Options::indiServer()).dir().path(); 0688 #endif 0689 0690 QStringList paths; 0691 paths << "/usr/bin" 0692 << "/usr/local/bin" << indiServerDir; 0693 0694 if (QStandardPaths::findExecutable("indiserver").isEmpty()) 0695 { 0696 if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) 0697 { 0698 KSNotification::error(i18n( 0699 "Unable to find INDI server. Please make sure the package that provides " 0700 "the 'indiserver' binary is installed.")); 0701 return; 0702 } 0703 } 0704 #endif 0705 GUIManager::Instance()->updateStatus(true); 0706 #endif 0707 } 0708 0709 void KStars::slotINDIDriver() 0710 { 0711 #ifdef HAVE_INDI 0712 #ifndef Q_OS_WIN 0713 0714 if (KMessageBox::warningContinueCancel( 0715 nullptr, 0716 i18n("INDI Device Manager should only be used by advanced technical users. " 0717 "It cannot be used with Ekos. Do you still want to open INDI device " 0718 "manager?"), 0719 i18n("INDI Device Manager"), KStandardGuiItem::cont(), 0720 KStandardGuiItem::cancel(), 0721 "indi_device_manager_warning") == KMessageBox::Cancel) 0722 return; 0723 0724 QString indiServerDir = Options::indiServer(); 0725 0726 #ifdef Q_OS_OSX 0727 if (Options::indiServerIsInternal()) 0728 indiServerDir = QCoreApplication::applicationDirPath(); 0729 else 0730 indiServerDir = QFileInfo(Options::indiServer()).dir().path(); 0731 #endif 0732 0733 QStringList paths; 0734 paths << "/usr/bin" 0735 << "/usr/local/bin" << indiServerDir; 0736 0737 if (QStandardPaths::findExecutable("indiserver").isEmpty()) 0738 { 0739 if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) 0740 { 0741 KSNotification::error(i18n( 0742 "Unable to find INDI server. Please make sure the package that provides " 0743 "the 'indiserver' binary is installed.")); 0744 return; 0745 } 0746 } 0747 #endif 0748 0749 DriverManager::Instance()->raise(); 0750 DriverManager::Instance()->activateWindow(); 0751 DriverManager::Instance()->showNormal(); 0752 0753 #endif 0754 } 0755 0756 void KStars::slotEkos() 0757 { 0758 #ifdef HAVE_CFITSIO 0759 #ifdef HAVE_INDI 0760 0761 #ifndef Q_OS_WIN 0762 0763 QString indiServerDir = Options::indiServer(); 0764 0765 #ifdef Q_OS_OSX 0766 if (Options::indiServerIsInternal()) 0767 indiServerDir = QCoreApplication::applicationDirPath(); 0768 else 0769 indiServerDir = QFileInfo(Options::indiServer()).dir().path(); 0770 #endif 0771 0772 QStringList paths; 0773 paths << "/usr/bin" 0774 << "/usr/local/bin" << indiServerDir; 0775 0776 if (QStandardPaths::findExecutable("indiserver").isEmpty()) 0777 { 0778 if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) 0779 { 0780 KSNotification::error(i18n( 0781 "Unable to find INDI server. Please make sure the package that provides " 0782 "the 'indiserver' binary is installed.")); 0783 return; 0784 } 0785 } 0786 #endif 0787 0788 if (Ekos::Manager::Instance()->isVisible() && 0789 Ekos::Manager::Instance()->isActiveWindow()) 0790 { 0791 Ekos::Manager::Instance()->hide(); 0792 } 0793 else 0794 { 0795 Ekos::Manager::Instance()->raise(); 0796 Ekos::Manager::Instance()->activateWindow(); 0797 Ekos::Manager::Instance()->showNormal(); 0798 } 0799 0800 #endif 0801 #endif 0802 } 0803 0804 void KStars::slotINDITelescopeTrack() 0805 { 0806 #ifdef HAVE_INDI 0807 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0808 return; 0809 0810 for (auto &oneDevice : INDIListener::devices()) 0811 { 0812 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0813 continue; 0814 0815 auto mount = oneDevice->getMount(); 0816 if (!mount || mount->isConnected() == false) 0817 continue; 0818 0819 KToggleAction *a = qobject_cast<KToggleAction *>(sender()); 0820 0821 if (a != nullptr) 0822 { 0823 mount->setTrackEnabled(a->isChecked()); 0824 return; 0825 } 0826 } 0827 #endif 0828 } 0829 0830 void KStars::slotINDITelescopeSlew(bool focused_object) 0831 { 0832 #ifdef HAVE_INDI 0833 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0834 return; 0835 0836 for (auto &oneDevice : INDIListener::devices()) 0837 { 0838 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0839 continue; 0840 0841 auto mount = oneDevice->getMount(); 0842 if (!mount || mount->isConnected() == false) 0843 continue; 0844 if (focused_object) 0845 { 0846 if (m_SkyMap->focusObject() != nullptr) 0847 mount->Slew(m_SkyMap->focusObject()); 0848 } 0849 else 0850 mount->Slew(m_SkyMap->mousePoint()); 0851 0852 return; 0853 } 0854 #else 0855 Q_UNUSED(focused_object) 0856 #endif 0857 } 0858 0859 void KStars::slotINDITelescopeSlewMousePointer() 0860 { 0861 #ifdef HAVE_INDI 0862 slotINDITelescopeSlew(false); 0863 #endif 0864 } 0865 0866 void KStars::slotINDITelescopeSync(bool focused_object) 0867 { 0868 #ifdef HAVE_INDI 0869 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0870 return; 0871 0872 for (auto &oneDevice : INDIListener::devices()) 0873 { 0874 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0875 continue; 0876 0877 auto mount = oneDevice->getMount(); 0878 if (!mount || mount->isConnected() == false) 0879 continue; 0880 0881 if (focused_object) 0882 { 0883 if (m_SkyMap->focusObject() != nullptr) 0884 mount->Sync(m_SkyMap->focusObject()); 0885 } 0886 else 0887 mount->Sync(m_SkyMap->mousePoint()); 0888 0889 return; 0890 } 0891 #else 0892 Q_UNUSED(focused_object) 0893 #endif 0894 } 0895 0896 void KStars::slotINDITelescopeSyncMousePointer() 0897 { 0898 #ifdef HAVE_INDI 0899 slotINDITelescopeSync(false); 0900 #endif 0901 } 0902 0903 void KStars::slotINDITelescopeAbort() 0904 { 0905 #ifdef HAVE_INDI 0906 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0907 return; 0908 0909 for (auto &oneDevice : INDIListener::devices()) 0910 { 0911 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0912 continue; 0913 0914 auto mount = oneDevice->getMount(); 0915 if (!mount || mount->isConnected() == false) 0916 continue; 0917 0918 mount->abort(); 0919 return; 0920 } 0921 #endif 0922 } 0923 0924 void KStars::slotINDITelescopePark() 0925 { 0926 #ifdef HAVE_INDI 0927 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0928 return; 0929 0930 for (auto &oneDevice : INDIListener::devices()) 0931 { 0932 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0933 continue; 0934 0935 auto mount = oneDevice->getMount(); 0936 if (!mount || mount->isConnected() == false || mount->canPark() == false) 0937 continue; 0938 0939 mount->park(); 0940 return; 0941 } 0942 #endif 0943 } 0944 0945 void KStars::slotINDITelescopeUnpark() 0946 { 0947 #ifdef HAVE_INDI 0948 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0949 return; 0950 0951 for (auto &oneDevice : INDIListener::devices()) 0952 { 0953 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0954 continue; 0955 0956 auto mount = oneDevice->getMount(); 0957 if (!mount || mount->isConnected() == false || mount->canPark() == false) 0958 continue; 0959 0960 mount->unpark(); 0961 return; 0962 } 0963 #endif 0964 } 0965 0966 void KStars::slotINDIDomePark() 0967 { 0968 #ifdef HAVE_INDI 0969 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0970 return; 0971 0972 for (auto &oneDevice : INDIListener::devices()) 0973 { 0974 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)) 0975 continue; 0976 0977 auto dome = oneDevice->getDome(); 0978 if (!dome || dome->isConnected() == false) 0979 continue; 0980 if (dome->canPark()) 0981 { 0982 dome->park(); 0983 return; 0984 } 0985 } 0986 #endif 0987 } 0988 0989 void KStars::slotINDIDomeUnpark() 0990 { 0991 #ifdef HAVE_INDI 0992 if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) 0993 return; 0994 0995 for (auto &oneDevice : INDIListener::devices()) 0996 { 0997 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)) 0998 continue; 0999 1000 auto dome = oneDevice->getDome(); 1001 if (!dome || dome->isConnected() == false) 1002 continue; 1003 if (dome->canPark()) 1004 { 1005 dome->unpark(); 1006 return; 1007 } 1008 } 1009 #endif 1010 } 1011 1012 void KStars::slotGeoLocator() 1013 { 1014 QPointer<LocationDialog> locationdialog = new LocationDialog(this); 1015 if (locationdialog->exec() == QDialog::Accepted) 1016 { 1017 GeoLocation *newLocation = locationdialog->selectedCity(); 1018 if (newLocation) 1019 { 1020 // set new location in options 1021 data()->setLocation(*newLocation); 1022 1023 // adjust local time to keep UT the same. 1024 // create new LT without DST offset 1025 KStarsDateTime ltime = newLocation->UTtoLT(data()->ut()); 1026 1027 // reset timezonerule to compute next dst change 1028 newLocation->tzrule()->reset_with_ltime(ltime, newLocation->TZ0(), 1029 data()->isTimeRunningForward()); 1030 1031 // reset next dst change time 1032 data()->setNextDSTChange(newLocation->tzrule()->nextDSTChange()); 1033 1034 // reset local sideral time 1035 data()->syncLST(); 1036 1037 // Make sure Numbers, Moon, planets, and sky objects are updated immediately 1038 data()->setFullTimeUpdate(); 1039 1040 // If the sky is in Horizontal mode and not tracking, reset focus such that 1041 // Alt/Az remain constant. 1042 if (!Options::isTracking() && Options::useAltAz()) 1043 { 1044 map()->focus()->HorizontalToEquatorial(data()->lst(), 1045 data()->geo()->lat()); 1046 } 1047 1048 // recalculate new times and objects 1049 data()->setSnapNextFocus(); 1050 updateTime(); 1051 } 1052 } 1053 delete locationdialog; 1054 } 1055 1056 void KStars::slotViewOps() 1057 { 1058 // An instance of your dialog could be already created and could be cached, 1059 // in which case you want to display the cached dialog instead of creating 1060 // another one 1061 auto ops = prepareOps(); 1062 ops->show(); 1063 // Bring to the front. 1064 ops->raise(); // for MacOS 1065 ops->activateWindow(); // for Windows 1066 } 1067 1068 KConfigDialog *KStars::prepareOps() 1069 { 1070 KConfigDialog *dialog = KConfigDialog::exists("settings"); 1071 if (nullptr != dialog) 1072 return dialog; 1073 1074 // KConfigDialog didn't find an instance of this dialog, so lets create it : 1075 dialog = new KConfigDialog(this, "settings", Options::self()); 1076 1077 // For some reason the dialog does not resize to contents 1078 // so we set initial 'resonable' size here. Any better way to do this? 1079 dialog->resize(800, 600); 1080 #ifdef Q_OS_OSX 1081 dialog->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); 1082 #endif 1083 1084 connect(dialog, SIGNAL(settingsChanged(QString)), this, 1085 SLOT(slotApplyConfigChanges())); 1086 1087 opcatalog = new OpsCatalog(); 1088 opguides = new OpsGuides(); 1089 opterrain = new OpsTerrain(); 1090 opsdeveloper = new OpsDeveloper(); 1091 opsolsys = new OpsSolarSystem(); 1092 opssatellites = new OpsSatellites(); 1093 opssupernovae = new OpsSupernovae(); 1094 opcolors = new OpsColors(); 1095 opadvanced = new OpsAdvanced(); 1096 1097 KPageWidgetItem *page; 1098 1099 page = dialog->addPage(opcatalog, i18n("Catalogs"), "kstars_catalog"); 1100 page->setIcon(QIcon::fromTheme("kstars_catalog")); 1101 1102 page = dialog->addPage(opsolsys, i18n("Solar System"), "kstars_solarsystem"); 1103 page->setIcon(QIcon::fromTheme("kstars_solarsystem")); 1104 1105 page = dialog->addPage(opssatellites, i18n("Satellites"), "kstars_satellites"); 1106 page->setIcon(QIcon::fromTheme("kstars_satellites")); 1107 1108 page = dialog->addPage(opssupernovae, i18n("Supernovae"), "kstars_supernovae"); 1109 page->setIcon(QIcon::fromTheme("kstars_supernovae")); 1110 1111 page = dialog->addPage(opguides, i18n("Guides"), "kstars_guides"); 1112 page->setIcon(QIcon::fromTheme("kstars_guides")); 1113 1114 page = dialog->addPage(opterrain, i18n("Terrain"), "kstars_terrain"); 1115 page->setIcon(QIcon::fromTheme("kstars_terrain", QIcon(":/icons/kstars_terrain.png"))); 1116 1117 1118 page = dialog->addPage(opcolors, i18n("Colors"), "kstars_colors"); 1119 page->setIcon(QIcon::fromTheme("kstars_colors")); 1120 1121 #ifdef HAVE_CFITSIO 1122 opsfits = new OpsFITS(); 1123 page = dialog->addPage(opsfits, i18n("FITS"), "kstars_fitsviewer"); 1124 page->setIcon(QIcon::fromTheme("kstars_fitsviewer")); 1125 #endif 1126 1127 #ifdef HAVE_INDI 1128 opsindi = new OpsINDI(); 1129 page = dialog->addPage(opsindi, i18n("INDI"), "kstars_indi"); 1130 page->setIcon(QIcon::fromTheme("kstars_indi")); 1131 #ifdef HAVE_CFITSIO 1132 opsekos = new OpsEkos(); 1133 KPageWidgetItem *ekosOption = dialog->addPage(opsekos, i18n("Ekos"), "kstars_ekos"); 1134 ekosOption->setIcon(QIcon::fromTheme("kstars_ekos")); 1135 if (Ekos::Manager::Instance()) 1136 Ekos::Manager::Instance()->setOptionsWidget(ekosOption, opsekos); 1137 #endif 1138 1139 #endif 1140 1141 opsxplanet = new OpsXplanet(this); 1142 page = dialog->addPage(opsxplanet, i18n("Xplanet"), "kstars_xplanet"); 1143 page->setIcon(QIcon::fromTheme("kstars_xplanet")); 1144 1145 page = dialog->addPage(opadvanced, i18n("Advanced"), "kstars_advanced"); 1146 page->setIcon(QIcon::fromTheme("kstars_advanced")); 1147 1148 page = dialog->addPage(opsdeveloper, i18n("Developer"), "kstars_developer"); 1149 page->setIcon(QIcon::fromTheme("kstars_developer", QIcon(":/icons/kstars_developer.png"))); 1150 1151 #ifdef Q_OS_OSX // This is because KHelpClient doesn't seem to be working right on MacOS 1152 dialog->button(QDialogButtonBox::Help)->disconnect(); 1153 connect(dialog->button(QDialogButtonBox::Help), &QPushButton::clicked, this, []() 1154 { 1155 KStars::Instance()->appHelpActivated(); 1156 }); 1157 #endif 1158 1159 return dialog; 1160 } 1161 1162 void KStars::syncOps() 1163 { 1164 opterrain->syncOptions(); 1165 actionCollection()->action("toggle_terrain") 1166 ->setText(Options::showTerrain() ? i18n("Hide Terrain") : i18n("Show Terrain")); 1167 } 1168 1169 void KStars::slotApplyConfigChanges() 1170 { 1171 Options::self()->save(); 1172 1173 applyConfig(); 1174 1175 //data()->setFullTimeUpdate(); 1176 //map()->forceUpdate(); 1177 } 1178 1179 void KStars::slotApplyWIConfigChanges() 1180 { 1181 Options::self()->save(); 1182 applyConfig(); 1183 m_WIView->updateObservingConditions(); 1184 m_WIView->onReloadIconClicked(); 1185 } 1186 1187 void KStars::slotSetTime() 1188 { 1189 QPointer<TimeDialog> timedialog = new TimeDialog(data()->lt(), data()->geo(), this); 1190 1191 if (timedialog->exec() == QDialog::Accepted) 1192 { 1193 data()->changeDateTime(data()->geo()->LTtoUT(timedialog->selectedDateTime())); 1194 1195 if (Options::useAltAz()) 1196 { 1197 if (map()->focusObject()) 1198 { 1199 map()->focusObject()->EquatorialToHorizontal(data()->lst(), 1200 data()->geo()->lat()); 1201 map()->setFocus(map()->focusObject()); 1202 } 1203 else 1204 map()->focus()->HorizontalToEquatorial(data()->lst(), 1205 data()->geo()->lat()); 1206 } 1207 1208 map()->forceUpdateNow(); 1209 1210 //If focusObject has a Planet Trail, clear it and start anew. 1211 KSPlanetBase *planet = dynamic_cast<KSPlanetBase *>(map()->focusObject()); 1212 if (planet && planet->hasTrail()) 1213 { 1214 planet->clearTrail(); 1215 planet->addToTrail(); 1216 } 1217 } 1218 delete timedialog; 1219 } 1220 1221 //Set Time to CPU clock 1222 void KStars::slotSetTimeToNow() 1223 { 1224 data()->changeDateTime(KStarsDateTime::currentDateTimeUtc()); 1225 1226 if (Options::useAltAz()) 1227 { 1228 if (map()->focusObject()) 1229 { 1230 map()->focusObject()->EquatorialToHorizontal(data()->lst(), 1231 data()->geo()->lat()); 1232 map()->setFocus(map()->focusObject()); 1233 } 1234 else 1235 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); 1236 } 1237 1238 map()->forceUpdateNow(); 1239 1240 //If focusObject has a Planet Trail, clear it and start anew. 1241 KSPlanetBase *planet = dynamic_cast<KSPlanetBase *>(map()->focusObject()); 1242 if (planet && planet->hasTrail()) 1243 { 1244 planet->clearTrail(); 1245 planet->addToTrail(); 1246 } 1247 } 1248 1249 void KStars::slotFind() 1250 { 1251 //clearCachedFindDialog(); 1252 SkyObject *targetObject = nullptr; 1253 if (FindDialog::Instance()->exec() == QDialog::Accepted && 1254 (targetObject = FindDialog::Instance()->targetObject())) 1255 { 1256 map()->setClickedObject(targetObject); 1257 map()->setClickedPoint(map()->clickedObject()); 1258 map()->slotCenter(); 1259 } 1260 1261 // check if data has changed while dialog was open 1262 //if (DialogIsObsolete) 1263 // clearCachedFindDialog(); 1264 } 1265 1266 void KStars::slotOpenFITS() 1267 { 1268 #ifdef HAVE_CFITSIO 1269 1270 static QUrl path = QUrl::fromLocalFile(QDir::homePath()); 1271 QUrl fileURL = 1272 QFileDialog::getOpenFileUrl(KStars::Instance(), i18nc("@title:window", "Open Image"), path, 1273 "Images (*.fits *.fits.fz *.fit *.fts " 1274 "*.jpg *.jpeg *.png *.gif *.bmp " 1275 "*.cr2 *.cr3 *.crw *.nef *.raf *.dng *.arw *.orf)"); 1276 if (fileURL.isEmpty()) 1277 return; 1278 1279 // Remember last directory 1280 path.setUrl(fileURL.url(QUrl::RemoveFilename)); 1281 1282 QPointer<FITSViewer> fv = createFITSViewer(); 1283 connect(fv, &FITSViewer::failed, [ &, fv](const QString & errorMessage) 1284 { 1285 KSNotification::error(errorMessage, i18n("Open FITS"), 10); 1286 fv->close(); 1287 }); 1288 1289 fv->loadFile(fileURL, FITS_NORMAL, FITS_NONE, QString()); 1290 #endif 1291 } 1292 1293 void KStars::slotExportImage() 1294 { 1295 //TODO Check this 1296 //For remote files, this returns 1297 //QFileInfo::absolutePath: QFileInfo::absolutePath: Constructed with empty filename 1298 //As of 2014-07-19 1299 //QUrl fileURL = KFileDialog::getSaveUrl( QDir::homePath(), "image/png image/jpeg image/gif image/x-portable-pixmap image/bmp image/svg+xml" ); 1300 QUrl fileURL = 1301 QFileDialog::getSaveFileUrl(KStars::Instance(), i18nc("@title:window", "Export Image"), QUrl(), 1302 "Images (*.png *.jpeg *.gif *.bmp *.svg)"); 1303 1304 //User cancelled file selection dialog - abort image export 1305 if (fileURL.isEmpty()) 1306 { 1307 return; 1308 } 1309 1310 //Warn user if file exists! 1311 if (QFile::exists(fileURL.toLocalFile())) 1312 { 1313 int r = KMessageBox::warningContinueCancel( 1314 parentWidget(), 1315 i18n("A file named \"%1\" already exists. Overwrite it?", fileURL.fileName()), 1316 i18n("Overwrite File?"), KStandardGuiItem::overwrite()); 1317 if (r == KMessageBox::Cancel) 1318 return; 1319 } 1320 1321 // execute image export dialog 1322 1323 // Note: We don't let ExportImageDialog create its own ImageExporter because we want legend settings etc to be remembered between UI use and DBus scripting interface use. 1324 //if ( !m_ImageExporter ) 1325 //m_ImageExporter = new ImageExporter( this ); 1326 1327 if (!m_ExportImageDialog) 1328 { 1329 m_ExportImageDialog = new ExportImageDialog( 1330 fileURL.toLocalFile(), QSize(map()->width(), map()->height()), 1331 KStarsData::Instance()->imageExporter()); 1332 } 1333 else 1334 { 1335 m_ExportImageDialog->setOutputUrl(fileURL.toLocalFile()); 1336 m_ExportImageDialog->setOutputSize(QSize(map()->width(), map()->height())); 1337 } 1338 1339 m_ExportImageDialog->show(); 1340 } 1341 1342 void KStars::slotRunScript() 1343 { 1344 QUrl fileURL = QFileDialog::getOpenFileUrl( 1345 KStars::Instance(), QString(), QUrl(QDir::homePath()), 1346 "*.kstars|" + 1347 i18nc("Filter by file type: KStars Scripts.", "KStars Scripts (*.kstars)")); 1348 QFile f; 1349 //QString fname; 1350 1351 if (fileURL.isValid()) 1352 { 1353 if (fileURL.isLocalFile() == false) 1354 { 1355 KSNotification::sorry(i18n("Executing remote scripts is not supported.")); 1356 return; 1357 } 1358 1359 f.setFileName(fileURL.toLocalFile()); 1360 1361 if (!f.open(QIODevice::ReadOnly)) 1362 { 1363 QString message = i18n("Could not open file %1", f.fileName()); 1364 KSNotification::sorry(message, i18n("Could Not Open File")); 1365 return; 1366 } 1367 1368 QTextStream istream(&f); 1369 QString line; 1370 bool fileOK(true); 1371 1372 while (!istream.atEnd()) 1373 { 1374 line = istream.readLine(); 1375 if (line.at(0) != '#' && line.left(9) != "dbus-send") 1376 { 1377 fileOK = false; 1378 break; 1379 } 1380 } 1381 1382 if (!fileOK) 1383 { 1384 int answer; 1385 answer = KMessageBox::warningContinueCancel( 1386 nullptr, 1387 i18n( 1388 "The selected script contains unrecognized elements, " 1389 "indicating that it was not created using the KStars script builder. " 1390 "This script may not function properly, and it may even contain " 1391 "malicious code. " 1392 "Would you like to execute it anyway?"), 1393 i18n("Script Validation Failed"), KGuiItem(i18n("Run Nevertheless")), 1394 KStandardGuiItem::cancel(), "daExecuteScript"); 1395 if (answer == KMessageBox::Cancel) 1396 return; 1397 } 1398 1399 //Add statusbar message that script is running 1400 statusBar()->showMessage(i18n("Running script: %1", fileURL.fileName())); 1401 1402 // 2017-09-19: Jasem 1403 // FIXME This is a hack and does not work on non-Linux systems 1404 // The Script Builder should generate files that can run cross-platform 1405 QProcess p; 1406 QStringList arguments; 1407 p.start(f.fileName(), arguments); 1408 if (!p.waitForStarted()) 1409 return; 1410 1411 while (!p.waitForFinished(10)) 1412 { 1413 qApp->processEvents(); //otherwise tempfile may get deleted before script completes. 1414 if (p.state() != QProcess::Running) 1415 break; 1416 } 1417 1418 statusBar()->showMessage(i18n("Script finished."), 0); 1419 } 1420 } 1421 1422 void KStars::slotPrint() 1423 { 1424 bool switchColors(false); 1425 1426 //Suggest Chart color scheme 1427 if (data()->colorScheme()->colorNamed("SkyColor") != QColor(255, 255, 255)) 1428 { 1429 QString message = 1430 i18n("You can save printer ink by using the \"Star Chart\" " 1431 "color scheme, which uses a white background. Would you like to " 1432 "temporarily switch to the Star Chart color scheme for printing?"); 1433 1434 int answer = KMessageBox::questionYesNoCancel( 1435 nullptr, message, i18n("Switch to Star Chart Colors?"), 1436 KGuiItem(i18n("Switch Color Scheme")), KGuiItem(i18n("Do Not Switch")), 1437 KStandardGuiItem::cancel(), "askAgainPrintColors"); 1438 1439 if (answer == KMessageBox::Cancel) 1440 return; 1441 if (answer == KMessageBox::Yes) 1442 switchColors = true; 1443 } 1444 1445 printImage(true, switchColors); 1446 } 1447 1448 void KStars::slotPrintingWizard() 1449 { 1450 if (m_PrintingWizard) 1451 { 1452 delete m_PrintingWizard; 1453 } 1454 1455 m_PrintingWizard = new PrintingWizard(this); 1456 m_PrintingWizard->show(); 1457 } 1458 1459 void KStars::slotToggleTimer() 1460 { 1461 if (data()->clock()->isActive()) 1462 { 1463 data()->clock()->stop(); 1464 updateTime(); 1465 } 1466 else 1467 { 1468 if (fabs(data()->clock()->scale()) > Options::slewTimeScale()) 1469 data()->clock()->setManualMode(true); 1470 data()->clock()->start(); 1471 if (data()->clock()->isManualMode()) 1472 map()->forceUpdate(); 1473 } 1474 1475 // Update clock state in options 1476 Options::setRunClock(data()->clock()->isActive()); 1477 } 1478 1479 void KStars::slotStepForward() 1480 { 1481 if (data()->clock()->isActive()) 1482 data()->clock()->stop(); 1483 data()->clock()->manualTick(true); 1484 map()->forceUpdate(); 1485 } 1486 1487 void KStars::slotStepBackward() 1488 { 1489 if (data()->clock()->isActive()) 1490 data()->clock()->stop(); 1491 data()->clock()->manualTick(true, true); 1492 map()->forceUpdate(); 1493 } 1494 1495 //Pointing 1496 void KStars::slotPointFocus() 1497 { 1498 // In the following cases, we set slewing=true in order to disengage tracking 1499 map()->stopTracking(); 1500 1501 if (sender() == actionCollection()->action("zenith")) 1502 map()->setDestinationAltAz(dms(90.0), map()->focus()->az(), 1503 Options::useRefraction()); 1504 else if (sender() == actionCollection()->action("north")) 1505 map()->setDestinationAltAz(dms(15.0), dms(0.0001), Options::useRefraction()); 1506 else if (sender() == actionCollection()->action("east")) 1507 map()->setDestinationAltAz(dms(15.0), dms(90.0), Options::useRefraction()); 1508 else if (sender() == actionCollection()->action("south")) 1509 map()->setDestinationAltAz(dms(15.0), dms(180.0), Options::useRefraction()); 1510 else if (sender() == actionCollection()->action("west")) 1511 map()->setDestinationAltAz(dms(15.0), dms(270.0), Options::useRefraction()); 1512 } 1513 1514 void KStars::slotTrack() 1515 { 1516 if (Options::isTracking()) 1517 { 1518 Options::setIsTracking(false); 1519 actionCollection()->action("track_object")->setText(i18n("Engage &Tracking")); 1520 actionCollection() 1521 ->action("track_object") 1522 ->setIcon(QIcon::fromTheme("document-decrypt")); 1523 1524 KSPlanetBase *planet = dynamic_cast<KSPlanetBase *>(map()->focusObject()); 1525 if (planet && data()->temporaryTrail) 1526 { 1527 planet->clearTrail(); 1528 data()->temporaryTrail = false; 1529 } 1530 1531 map()->setClickedObject(nullptr); 1532 map()->setFocusObject(nullptr); //no longer tracking focusObject 1533 map()->setFocusPoint(nullptr); 1534 } 1535 else 1536 { 1537 map()->setClickedPoint(map()->focus()); 1538 map()->setClickedObject(nullptr); 1539 map()->setFocusObject(nullptr); //no longer tracking focusObject 1540 map()->setFocusPoint(map()->clickedPoint()); 1541 Options::setIsTracking(true); 1542 actionCollection()->action("track_object")->setText(i18n("Stop &Tracking")); 1543 actionCollection() 1544 ->action("track_object") 1545 ->setIcon(QIcon::fromTheme("document-encrypt")); 1546 } 1547 1548 map()->forceUpdate(); 1549 } 1550 1551 void KStars::slotManualFocus() 1552 { 1553 QPointer<FocusDialog> focusDialog = new FocusDialog(); 1554 1555 // JM 2019-09-04: Should default to RA/DE always 1556 // if (Options::useAltAz()) 1557 // focusDialog->activateAzAltPage(); 1558 1559 if (focusDialog->exec() == QDialog::Accepted) 1560 { 1561 //If the requested position is very near the pole, we need to point first 1562 //to an intermediate location just below the pole in order to get the longitudinal 1563 //position (RA/Az) right. 1564 1565 // Do not access (RA0, Dec0) of focusDialog->point() as it can be of unknown epoch. 1566 // (RA, Dec) should be synced to JNow 1567 // -- asimha (2020-07-06) 1568 double realAlt(focusDialog->point()->alt().Degrees()); 1569 double realDec(focusDialog->point()->dec().Degrees()); 1570 if (Options::useAltAz() && realAlt > 89.0) 1571 { 1572 focusDialog->point()->setAlt(89.0); 1573 focusDialog->point()->HorizontalToEquatorial(data()->lst(), 1574 data()->geo()->lat()); 1575 } 1576 if (!Options::useAltAz() && realDec > 89.0) 1577 { 1578 focusDialog->point()->setDec(89.0); 1579 focusDialog->point()->EquatorialToHorizontal(data()->lst(), 1580 data()->geo()->lat()); 1581 } 1582 1583 map()->setClickedPoint(focusDialog->point()); 1584 1585 if (Options::isTracking()) 1586 slotTrack(); 1587 1588 map()->slotCenter(); 1589 1590 //The slew takes some time to complete, and this often causes the final focus point to be slightly 1591 //offset from the user's requested coordinates (because EquatorialToHorizontal() is called 1592 //throughout the process, which depends on the sidereal time). So we now "polish" the final 1593 //position by resetting the final focus to the focusDialog point. 1594 // 1595 //Also, if the requested position was within 1 degree of the coordinate pole, this will 1596 //automatically correct the final pointing from the intermediate offset position to the final position 1597 data()->setSnapNextFocus(); 1598 if (Options::useAltAz()) 1599 { 1600 // N.B. We have applied unrefract() in focusDialog 1601 map()->setDestinationAltAz(focusDialog->point()->alt(), 1602 focusDialog->point()->az(), false); 1603 } 1604 else 1605 { 1606 map()->setDestination(focusDialog->point()->ra(), 1607 focusDialog->point()->dec()); 1608 } 1609 1610 //Now, if the requested point was near a pole, we need to reset the Alt/Dec of the focus. 1611 if (Options::useAltAz() && realAlt > 89.0) 1612 map()->focus()->setAlt(realAlt); 1613 if (!Options::useAltAz() && realDec > 89.0) 1614 map()->focus()->setDec(realAlt); 1615 1616 //Don't track if we set Alt/Az coordinates. This way, Alt/Az remain constant. 1617 if (focusDialog->usedAltAz()) 1618 map()->stopTracking(); 1619 } 1620 delete focusDialog; 1621 } 1622 1623 void KStars::slotZoomChanged() 1624 { 1625 // Enable/disable actions 1626 actionCollection()->action("zoom_out")->setEnabled(Options::zoomFactor() > MINZOOM); 1627 actionCollection()->action("zoom_in")->setEnabled(Options::zoomFactor() < MAXZOOM); 1628 // Update status bar 1629 map() 1630 ->setupProjector(); // this needs to be run redundantly, so that the FOV returned below is up-to-date. 1631 float fov = map()->projector()->fov(); 1632 KLocalizedString fovi18nstring = 1633 ki18nc("approximate field of view", "Approximate FOV: %1 degrees"); 1634 if (fov < 1.0) 1635 { 1636 fov = fov * 60.0; 1637 fovi18nstring = 1638 ki18nc("approximate field of view", "Approximate FOV: %1 arcminutes"); 1639 } 1640 if (fov < 1.0) 1641 { 1642 fov = fov * 60.0; 1643 fovi18nstring = 1644 ki18nc("approximate field of view", "Approximate FOV: %1 arcseconds"); 1645 } 1646 QString fovstring = fovi18nstring.subs(QString::number(fov, 'f', 1)).toString(); 1647 1648 statusBar()->showMessage(fovstring, 0); 1649 } 1650 1651 void KStars::slotSetZoom() 1652 { 1653 bool ok; 1654 double currentAngle = map()->width() / (Options::zoomFactor() * dms::DegToRad); 1655 double minAngle = map()->width() / (MAXZOOM * dms::DegToRad); 1656 double maxAngle = map()->width() / (MINZOOM * dms::DegToRad); 1657 1658 double angSize = QInputDialog::getDouble( 1659 nullptr, 1660 i18nc("The user should enter an angle for the field-of-view of the display", 1661 "Enter Desired Field-of-View Angle"), 1662 i18n("Enter a field-of-view angle in degrees: "), currentAngle, minAngle, 1663 maxAngle, 1, &ok); 1664 1665 if (ok) 1666 { 1667 map()->setZoomFactor(map()->width() / (angSize * dms::DegToRad)); 1668 } 1669 } 1670 1671 void KStars::slotCoordSys() 1672 { 1673 if (Options::useAltAz()) 1674 { 1675 Options::setUseAltAz(false); 1676 if (Options::useRefraction()) 1677 { 1678 if (map()->focusObject()) //simply update focus to focusObject's position 1679 map()->setFocus(map()->focusObject()); 1680 else //need to recompute focus for unrefracted position 1681 { 1682 // FIXME: Changed focus()->alt() to be unrefracted by convention; is this still necessary? -- asimha 2020/07/05 1683 map()->setFocusAltAz(map()->focus()->alt(), map()->focus()->az()); 1684 map()->focus()->HorizontalToEquatorial(data()->lst(), 1685 data()->geo()->lat()); 1686 } 1687 } 1688 actionCollection() 1689 ->action("coordsys") 1690 ->setText(i18n("Switch to Horizonal View (Horizontal &Coordinates)")); 1691 } 1692 else 1693 { 1694 Options::setUseAltAz(true); 1695 if (Options::useRefraction()) 1696 { 1697 // FIXME: Changed focus()->alt() to be unrefracted by convention; is this still necessary? -- asimha 2020/07/05 1698 map()->setFocusAltAz(map()->focus()->alt(), map()->focus()->az()); 1699 } 1700 actionCollection() 1701 ->action("coordsys") 1702 ->setText(i18n("Switch to Star Globe View (Equatorial &Coordinates)")); 1703 } 1704 map()->forceUpdate(); 1705 } 1706 1707 void KStars::slotMapProjection() 1708 { 1709 if (sender() == actionCollection()->action("project_lambert")) 1710 Options::setProjection(Projector::Lambert); 1711 if (sender() == actionCollection()->action("project_azequidistant")) 1712 Options::setProjection(Projector::AzimuthalEquidistant); 1713 if (sender() == actionCollection()->action("project_orthographic")) 1714 Options::setProjection(Projector::Orthographic); 1715 if (sender() == actionCollection()->action("project_equirectangular")) 1716 Options::setProjection(Projector::Equirectangular); 1717 if (sender() == actionCollection()->action("project_stereographic")) 1718 Options::setProjection(Projector::Stereographic); 1719 if (sender() == actionCollection()->action("project_gnomonic")) 1720 Options::setProjection(Projector::Gnomonic); 1721 1722 //DEBUG 1723 qCDebug(KSTARS) << "Projection system: " << Options::projection(); 1724 1725 m_SkyMap->forceUpdate(); 1726 } 1727 1728 //Settings Menu: 1729 void KStars::slotColorScheme() 1730 { 1731 loadColorScheme(sender()->objectName()); 1732 } 1733 1734 void KStars::slotTargetSymbol(bool flag) 1735 { 1736 qDebug() << Q_FUNC_INFO << QString("slotTargetSymbol: %1 %2").arg(sender()->objectName()).arg(flag); 1737 1738 QStringList names = Options::fOVNames(); 1739 if (flag) 1740 { 1741 // Add FOV to list 1742 names.append(sender()->objectName()); 1743 } 1744 else 1745 { 1746 // Remove FOV from list 1747 int ix = names.indexOf(sender()->objectName()); 1748 if (ix >= 0) 1749 names.removeAt(ix); 1750 } 1751 Options::setFOVNames(names); 1752 1753 // Sync visibleFOVs with fovNames 1754 data()->syncFOV(); 1755 1756 map()->forceUpdate(); 1757 } 1758 1759 void KStars::slotHIPSSource() 1760 { 1761 QAction *selectedAction = qobject_cast<QAction *>(sender()); 1762 Q_ASSERT(selectedAction != nullptr); 1763 1764 QString selectedSource = selectedAction->text().remove('&'); 1765 1766 // selectedSource could be translated, while we need to send only Latin "None" 1767 // to Hips manager. 1768 if (selectedSource == i18n("None")) 1769 HIPSManager::Instance()->setCurrentSource("None"); 1770 else 1771 HIPSManager::Instance()->setCurrentSource(selectedSource); 1772 1773 map()->forceUpdate(); 1774 } 1775 1776 void KStars::slotFOVEdit() 1777 { 1778 QPointer<FOVDialog> fovdlg = new FOVDialog(this); 1779 if (fovdlg->exec() == QDialog::Accepted) 1780 { 1781 FOVManager::save(); 1782 repopulateFOV(); 1783 } 1784 delete fovdlg; 1785 } 1786 1787 void KStars::slotObsList() 1788 { 1789 m_KStarsData->observingList()->show(); 1790 } 1791 1792 void KStars::slotEquipmentWriter() 1793 { 1794 QPointer<EquipmentWriter> equipmentdlg = new EquipmentWriter(); 1795 equipmentdlg->loadEquipment(); 1796 equipmentdlg->exec(); 1797 delete equipmentdlg; 1798 } 1799 1800 void KStars::slotObserverManager() 1801 { 1802 QPointer<ObserverAdd> m_observerAdd = new ObserverAdd(); 1803 m_observerAdd->exec(); 1804 delete m_observerAdd; 1805 } 1806 1807 void KStars::slotHorizonManager() 1808 { 1809 if (!m_HorizonManager) 1810 { 1811 m_HorizonManager = new HorizonManager(this); 1812 connect(m_SkyMap, SIGNAL(positionClicked(SkyPoint *)), m_HorizonManager, 1813 SLOT(addSkyPoint(SkyPoint *))); 1814 } 1815 1816 m_HorizonManager->show(); 1817 } 1818 1819 void KStars::slotEyepieceView(SkyPoint *sp, const QString &imagePath) 1820 { 1821 if (!m_EyepieceView) 1822 m_EyepieceView = new EyepieceField(this); 1823 1824 // FIXME: Move FOV choice into the Eyepiece View tool itself. 1825 bool ok = true; 1826 const FOV *fov = nullptr; 1827 if (!data()->getAvailableFOVs().isEmpty()) 1828 { 1829 // Ask the user to choose from a list of available FOVs. 1830 //int index; 1831 const FOV *f; 1832 QMap<QString, const FOV *> nameToFovMap; 1833 foreach (f, data()->getAvailableFOVs()) 1834 { 1835 nameToFovMap.insert(f->name(), f); 1836 } 1837 nameToFovMap.insert(i18n("Attempt to determine from image"), nullptr); 1838 fov = nameToFovMap[QInputDialog::getItem( 1839 this, i18n("Eyepiece View: Choose a field-of-view"), 1840 i18n("FOV to render eyepiece view for:"), nameToFovMap.keys(), 0, false, 1841 &ok)]; 1842 } 1843 if (ok) 1844 m_EyepieceView->showEyepieceField(sp, fov, imagePath); 1845 } 1846 1847 void KStars::slotExecute() 1848 { 1849 KStarsData::Instance()->executeSession()->init(); 1850 KStarsData::Instance()->executeSession()->show(); 1851 } 1852 1853 void KStars::slotPolarisHourAngle() 1854 { 1855 QPointer<PolarisHourAngle> pHourAngle = new PolarisHourAngle(this); 1856 pHourAngle->exec(); 1857 } 1858 1859 //Help Menu 1860 void KStars::slotTipOfDay() 1861 { 1862 KTipDialog::showTip(this, "kstars/tips", true); 1863 } 1864 1865 // Toggle to and from full screen mode 1866 void KStars::slotFullScreen() 1867 { 1868 if (topLevelWidget()->isFullScreen()) 1869 { 1870 topLevelWidget()->setWindowState(topLevelWidget()->windowState() & 1871 ~Qt::WindowFullScreen); // reset 1872 } 1873 else 1874 { 1875 topLevelWidget()->setWindowState(topLevelWidget()->windowState() | 1876 Qt::WindowFullScreen); // set 1877 } 1878 } 1879 1880 // Toggle to and from full screen mode 1881 void KStars::slotTerrain() 1882 { 1883 Options::setShowTerrain(!Options::showTerrain()); 1884 actionCollection()->action("toggle_terrain") 1885 ->setText(Options::showTerrain() ? i18n("Hide Terrain") : i18n("Show Terrain")); 1886 KStars::Instance()->map()->forceUpdate(); 1887 } 1888 1889 void KStars::slotClearAllTrails() 1890 { 1891 //Exclude object with temporary trail 1892 SkyObject *exOb(nullptr); 1893 if (map()->focusObject() && map()->focusObject()->isSolarSystem() && 1894 data()->temporaryTrail) 1895 { 1896 exOb = map()->focusObject(); 1897 } 1898 1899 TrailObject::clearTrailsExcept(exOb); 1900 1901 map()->forceUpdate(); 1902 } 1903 1904 //toggle display of GUI Items on/off 1905 void KStars::slotShowGUIItem(bool show) 1906 { 1907 //Toolbars 1908 if (sender() == actionCollection()->action("show_statusBar")) 1909 { 1910 Options::setShowStatusBar(show); 1911 statusBar()->setVisible(show); 1912 } 1913 1914 if (sender() == actionCollection()->action("show_sbAzAlt")) 1915 { 1916 Options::setShowAltAzField(show); 1917 AltAzField.setHidden(!show); 1918 } 1919 1920 if (sender() == actionCollection()->action("show_sbRADec")) 1921 { 1922 Options::setShowRADecField(show); 1923 RADecField.setHidden(!show); 1924 } 1925 1926 if (sender() == actionCollection()->action("show_sbJ2000RADec")) 1927 { 1928 Options::setShowJ2000RADecField(show); 1929 J2000RADecField.setHidden(!show); 1930 } 1931 } 1932 void KStars::addColorMenuItem(QString name, const QString &actionName) 1933 { 1934 KToggleAction *kta = actionCollection()->add<KToggleAction>(actionName); 1935 const QString filename = QString(actionName).mid(3) + ".colors"; 1936 kta->setText(name); 1937 kta->setObjectName(filename); 1938 kta->setActionGroup(cschemeGroup); 1939 1940 colorActionMenu->addAction(kta); 1941 1942 KConfigGroup cg = KSharedConfig::openConfig()->group("Colors"); 1943 if (actionName.mid(3) == 1944 cg.readEntry("ColorSchemeFile", "moonless-night.colors").remove(".colors")) 1945 { 1946 kta->setChecked(true); 1947 } 1948 1949 //use mid(3) to exclude the leading "cs_" prefix from the action name 1950 data()->add_color_scheme(filename, name.replace("&", "")); 1951 connect(kta, SIGNAL(toggled(bool)), this, SLOT(slotColorScheme())); 1952 } 1953 1954 void KStars::removeColorMenuItem(const QString &actionName) 1955 { 1956 qCDebug(KSTARS) << "removing " << actionName; 1957 colorActionMenu->removeAction(actionCollection()->action(actionName)); 1958 } 1959 1960 void KStars::slotAboutToQuit() 1961 { 1962 if (m_SkyMap == nullptr) 1963 return; 1964 1965 #ifdef HAVE_INDI 1966 DriverManager::Instance()->disconnectClients(); 1967 INDIListener::Instance()->disconnect(); 1968 GUIManager::Instance()->disconnect(); 1969 #endif 1970 1971 // Delete skymap. This required to run destructors and save 1972 // current state in the option. 1973 delete m_SkyMap; 1974 m_SkyMap = nullptr; 1975 1976 //Store Window geometry in Options object 1977 Options::setWindowWidth(width()); 1978 Options::setWindowHeight(height()); 1979 1980 //explicitly save the colorscheme data to the config file 1981 data()->colorScheme()->saveToConfig(); 1982 1983 //synch the config file with the Config object 1984 writeConfig(); 1985 1986 //Terminate Child Processes if on OS X 1987 #ifdef Q_OS_OSX 1988 QProcess *quit = new QProcess(this); 1989 quit->start("killall kdeinit5"); 1990 quit->waitForFinished(1000); 1991 quit->start("killall klauncher"); 1992 quit->waitForFinished(1000); 1993 quit->start("killall kioslave"); 1994 quit->waitForFinished(1000); 1995 quit->start("killall kio_http_cache_cleaner"); 1996 quit->waitForFinished(1000); 1997 delete quit; 1998 #endif 1999 } 2000 2001 void KStars::slotShowPositionBar(SkyPoint *p) 2002 { 2003 if (Options::showAltAzField()) 2004 { 2005 dms a = p->alt(); 2006 if (Options::useAltAz()) 2007 a = p->altRefracted(); 2008 QString s = 2009 QString("%1, %2").arg(p->az().toDMSString(true), //true: force +/- symbol 2010 a.toDMSString(true)); //true: force +/- symbol 2011 //statusBar()->changeItem( s, 1 ); 2012 AltAzField.setText(s); 2013 } 2014 if (Options::showRADecField()) 2015 { 2016 KStarsDateTime lastUpdate; 2017 lastUpdate.setDJD(KStarsData::Instance()->updateNum()->getJD()); 2018 QString sEpoch = QString::number(lastUpdate.epoch(), 'f', 1); 2019 QString s = QString("%1, %2 (J%3)") 2020 .arg(p->ra().toHMSString(), p->dec().toDMSString(true), 2021 sEpoch); //true: force +/- symbol 2022 //statusBar()->changeItem( s, 2 ); 2023 RADecField.setText(s); 2024 } 2025 2026 if (Options::showJ2000RADecField()) 2027 { 2028 SkyPoint p0; 2029 //p0 = p->deprecess(KStarsData::Instance()->updateNum()); // deprecess to update RA0/Dec0 from RA/Dec 2030 p0 = p->catalogueCoord(KStarsData::Instance()->updateNum()->julianDay()); 2031 QString s = QString("%1, %2 (J2000)") 2032 .arg(p0.ra().toHMSString(), 2033 p0.dec().toDMSString(true)); //true: force +/- symbol 2034 //statusBar()->changeItem( s, 2 ); 2035 J2000RADecField.setText(s); 2036 } 2037 } 2038 2039 void KStars::slotUpdateComets(bool isAutoUpdate) 2040 { 2041 data()->skyComposite()->solarSystemComposite()->cometsComponent()->updateDataFile( 2042 isAutoUpdate); 2043 } 2044 2045 void KStars::slotUpdateAsteroids(bool isAutoUpdate) 2046 { 2047 data()->skyComposite()->solarSystemComposite()->asteroidsComponent()->updateDataFile( 2048 isAutoUpdate); 2049 } 2050 2051 void KStars::slotUpdateSupernovae() 2052 { 2053 data()->skyComposite()->supernovaeComponent()->slotTriggerDataFileUpdate(); 2054 } 2055 2056 void KStars::slotUpdateSatellites() 2057 { 2058 data()->skyComposite()->satellites()->updateTLEs(); 2059 } 2060 2061 void KStars::slotConfigureNotifications() 2062 { 2063 #ifdef HAVE_NOTIFYCONFIG 2064 KNotifyConfigWidget::configure(this); 2065 #endif 2066 } 2067 void KStars::slotDSOCatalogGUI() 2068 { 2069 auto *ui = new CatalogsDBUI{ this, CatalogsDB::dso_db_path() }; 2070 ui->show(); 2071 connect(ui, &QDialog::finished, this, [&](const auto) 2072 { 2073 KStars::Instance()->data()->skyComposite()->catalogsComponent()->dropCache(); 2074 }); 2075 }