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