summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/kstarsactions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/kstarsactions.cpp')
-rw-r--r--kstars/kstars/kstarsactions.cpp1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/kstars/kstars/kstarsactions.cpp b/kstars/kstars/kstarsactions.cpp
new file mode 100644
index 00000000..b31e616c
--- /dev/null
+++ b/kstars/kstars/kstarsactions.cpp
@@ -0,0 +1,1039 @@
+/***************************************************************************
+ kstarsactions.cpp - K Desktop Planetarium
+ -------------------
+ begin : Mon Feb 25 2002
+ copyright : (C) 2002 by Jason Harris
+ email : jharris@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+//needed in slotRunScript() for chmod() syscall (remote script downloaded to temp file)
+#include <sys/stat.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <klineedit.h>
+#include <kshortcut.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <ktip.h>
+#include <kstandarddirs.h>
+#include <kconfigdialog.h>
+#include <kfiledialog.h>
+#include <kinputdialog.h>
+#include <kpopupmenu.h>
+#include <kstatusbar.h>
+#include <kprocess.h>
+#include <qcheckbox.h>
+#include <qdir.h>
+#include <kdeversion.h>
+//FIXME GLSOSSARY (uncomment these when content is added)
+//#include <libkdeedu/kdeeduui/kdeeduglossary.h>
+
+#include "opscatalog.h"
+#include "opsguides.h"
+#include "opssolarsystem.h"
+#include "opscolors.h"
+#include "opsadvanced.h"
+
+#include "Options.h"
+#include "kstars.h"
+#include "kstarsdata.h"
+#include "kstarsdatetime.h"
+#include "skymap.h"
+#include "skyobject.h"
+#include "skyobjectname.h"
+#include "ksplanetbase.h"
+#include "ksasteroid.h"
+#include "kscomet.h"
+#include "ksmoon.h"
+#include "simclock.h"
+#include "infoboxes.h"
+#include "toggleaction.h"
+#include "timedialog.h"
+#include "locationdialog.h"
+#include "finddialog.h"
+#include "focusdialog.h"
+#include "fovdialog.h"
+#include "kswizard.h"
+#include "tools/lcgenerator.h"
+#include "tools/astrocalc.h"
+#include "tools/altvstime.h"
+#include "tools/wutdialog.h"
+#include "tools/scriptbuilder.h"
+#include "tools/planetviewer.h"
+#include "tools/jmoontool.h"
+#include "devmanager.h"
+#include "indimenu.h"
+#include "indidriver.h"
+#include "indifitsconf.h"
+#include "telescopewizardprocess.h"
+#include "telescopeprop.h"
+#include "fitsviewer.h"
+
+#if ( KDE_IS_VERSION( 3, 2, 90 ) )
+#include "ksnewstuff.h"
+#endif // KDE >= 3.2.90
+#include "imagesequence.h"
+
+//This file contains function definitions for Actions declared in kstars.h
+
+/** ViewToolBar Action. All of the viewToolBar buttons are connected to this slot. **/
+
+void KStars::slotViewToolBar() {
+
+ if ( sender()->name() == QString( "show_stars" ) ) {
+ Options::setShowStars( !Options::showStars() );
+ } else if ( sender()->name() == QString( "show_deepsky" ) ) {
+ Options::setShowDeepSky( ! Options::showDeepSky() );
+ } else if ( sender()->name() == QString( "show_planets" ) ) {
+ Options::setShowPlanets( ! Options::showPlanets() );
+ } else if ( sender()->name() == QString( "show_clines" ) ) {
+ Options::setShowCLines( !Options::showCLines() );
+ } else if ( sender()->name() == QString( "show_cnames" ) ) {
+ Options::setShowCNames( !Options::showCNames() );
+ } else if ( sender()->name() == QString( "show_cbounds" ) ) {
+ Options::setShowCBounds( !Options::showCBounds() );
+ } else if ( sender()->name() == QString( "show_mw" ) ) {
+ Options::setShowMilkyWay( !Options::showMilkyWay() );
+ } else if ( sender()->name() == QString( "show_grid" ) ) {
+ Options::setShowGrid( !Options::showGrid() );
+ } else if ( sender()->name() == QString( "show_horizon" ) ) {
+ Options::setShowGround( !Options::showGround() );
+ }
+
+ // update time for all objects because they might be not initialized
+ // it's needed when using horizontal coordinates
+ data()->setFullTimeUpdate();
+ updateTime();
+
+ map()->forceUpdate();
+}
+
+/** Major Dialog Window Actions **/
+
+void KStars::slotCalculator() {
+ AstroCalc astrocalc (this);
+ astrocalc.exec();
+}
+
+void KStars::slotWizard() {
+ KSWizard wizard(this);
+ if ( wizard.exec() == QDialog::Accepted ) {
+ Options::setRunStartupWizard( false ); //don't run on startup next time
+
+ data()->setLocation( wizard.geo() );
+
+ // reset infoboxes
+ infoBoxes()->geoChanged( geo() );
+
+ // adjust local time to keep UT the same.
+ // create new LT without DST offset
+ KStarsDateTime ltime = geo()->UTtoLT( data()->ut() );
+
+ // reset timezonerule to compute next dst change
+ geo()->tzrule()->reset_with_ltime( ltime, geo()->TZ0(), data()->isTimeRunningForward() );
+
+ // reset next dst change time
+ data()->setNextDSTChange( geo()->tzrule()->nextDSTChange() );
+
+ // reset local sideral time
+ data()->syncLST();
+
+ // Make sure Numbers, Moon, planets, and sky objects are updated immediately
+ data()->setFullTimeUpdate();
+
+ // If the sky is in Horizontal mode and not tracking, reset focus such that
+ // Alt/Az remain constant.
+ if ( data()->useDefaultOptions ) {
+ SkyPoint newPoint;
+ newPoint.setAz( Options::focusRA() );
+ newPoint.setAlt( Options::focusDec() + 0.0001 );
+ newPoint.HorizontalToEquatorial( LST(), geo()->lat() );
+ map()->setDestination( &newPoint );
+ } else if ( ! Options::isTracking() && Options::useAltAz() ) {
+ map()->focus()->HorizontalToEquatorial( LST(), geo()->lat() );
+ }
+
+ // recalculate new times and objects
+ data()->setSnapNextFocus();
+ updateTime();
+ }
+}
+
+void KStars::slotDownload() {
+#if ( KDE_IS_VERSION( 3, 2, 90 ) )
+ if (!kns) kns = new KSNewStuff( this );
+ kns->download();
+#endif //KDE >= 3.2.90
+}
+
+void KStars::slotLCGenerator() {
+ if (AAVSODialog == NULL)
+ AAVSODialog = new LCGenerator(this);
+
+ AAVSODialog->show();
+}
+
+void KStars::slotAVT() {
+ AltVsTime * avt = new AltVsTime(this);
+ avt->show();
+}
+
+void KStars::slotWUT() {
+ WUTDialog dialog(this);
+ dialog.exec();
+}
+
+//FIXME GLOSSARY
+// void KStars::slotGlossary(){
+// GlossaryDialog *dlg = new GlossaryDialog( true, this, "glossary" );
+// QString glossaryfile =data()->stdDirs->findResource( "data", "kstars/glossary.xml" );
+// KURL u = glossaryfile;
+// Glossary *g = Glossary::readFromXML( u );
+// g->setName( i18n( "Knowledge" ) );
+// dlg->addGlossary( g );
+// dlg->show();
+// }
+
+void KStars::slotScriptBuilder() {
+ ScriptBuilder sb(this);
+ sb.exec();
+}
+
+void KStars::slotSolarSystem() {
+ PlanetViewer pv(this);
+ pv.exec();
+}
+
+void KStars::slotJMoonTool() {
+ JMoonTool jmt(this);
+ jmt.exec();
+}
+
+void KStars::slotImageSequence()
+{
+ if (indiseq == NULL)
+ indiseq = new imagesequence(this);
+
+ if (indiseq->updateStatus())
+ indiseq->show();
+}
+
+void KStars::slotTelescopeWizard()
+{
+ telescopeWizardProcess twiz(this);
+ twiz.exec();
+}
+
+void KStars::slotTelescopeProperties()
+{
+ telescopeProp scopeProp(this);
+ scopeProp.exec();
+}
+
+void KStars::slotINDIPanel() {
+
+ if (indimenu == NULL)
+ indimenu = new INDIMenu(this);
+
+ indimenu->updateStatus();
+}
+
+void KStars::slotINDIDriver() {
+ if (indidriver == NULL)
+ indidriver = new INDIDriver(this);
+ indidriver->show();
+}
+
+void KStars::slotINDIConf() {
+
+ INDIFITSConf indioptions(this);
+
+ indioptions.loadOptions();
+ /*QStringList filterList;
+
+
+ indiconf.timeCheck->setChecked( Options::indiAutoTime() );
+ indiconf.GeoCheck->setChecked( Options::indiAutoGeo() );
+ indiconf.crosshairCheck->setChecked( Options::indiCrosshairs() );
+ indiconf.messagesCheck->setChecked ( Options::indiMessages() );
+ indiconf.fitsAutoDisplayCheck->setChecked( Options::indiFITSDisplay() );
+ indiconf.telPort_IN->setText ( Options::indiTelescopePort());
+ indiconf.vidPort_IN->setText ( Options::indiVideoPort());
+
+ if (Options::fitsSaveDirectory().isEmpty())
+ {
+ indiconf.fitsDIR_IN->setText (QDir:: homeDirPath());
+ Options::setFitsSaveDirectory( indiconf.fitsDIR_IN->text());
+ }
+ else
+ indiconf.fitsDIR_IN->setText ( Options::fitsSaveDirectory());
+
+ if (Options::filterAlias().empty())
+ {
+ filterList << "0" << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8"
+ << "9";
+ indiconf.filterCombo->insertStringList(filterList);
+ }*/
+
+ if (indioptions.exec() == QDialog::Accepted)
+ {
+ /*Options::setIndiAutoTime( indiconf.timeCheck->isChecked() );
+ Options::setIndiAutoGeo( indiconf.GeoCheck->isChecked() );
+ Options::setIndiCrosshairs( indiconf.crosshairCheck->isChecked() );
+ Options::setIndiMessages( indiconf.messagesCheck->isChecked() );
+ Options::setIndiFITSDisplay (indiconf.fitsAutoDisplayCheck->isChecked());
+ Options::setIndiTelescopePort ( indiconf.telPort_IN->text());
+ Options::setIndiVideoPort( indiconf.vidPort_IN->text());
+ Options::setFitsSaveDirectory( indiconf.fitsDIR_IN->text());*/
+ indioptions.saveOptions();
+
+ map()->forceUpdateNow();
+ }
+}
+
+void KStars::slotGeoLocator() {
+ LocationDialog locationdialog (this);
+ if ( locationdialog.exec() == QDialog::Accepted ) {
+ GeoLocation *newLocation = locationdialog.selectedCity();
+ if ( newLocation ) {
+ // set new location in options
+ data()->setLocation( *newLocation );
+
+ // reset infoboxes
+ infoBoxes()->geoChanged( newLocation );
+
+ // adjust local time to keep UT the same.
+ // create new LT without DST offset
+ KStarsDateTime ltime = newLocation->UTtoLT( data()->ut() );
+
+ // reset timezonerule to compute next dst change
+ newLocation->tzrule()->reset_with_ltime( ltime, newLocation->TZ0(), data()->isTimeRunningForward() );
+
+ // reset next dst change time
+ data()->setNextDSTChange( newLocation->tzrule()->nextDSTChange() );
+
+ // reset local sideral time
+ data()->syncLST();
+
+ // Make sure Numbers, Moon, planets, and sky objects are updated immediately
+ data()->setFullTimeUpdate();
+
+ // If the sky is in Horizontal mode and not tracking, reset focus such that
+ // Alt/Az remain constant.
+ if ( ! Options::isTracking() && Options::useAltAz() ) {
+ map()->focus()->HorizontalToEquatorial( LST(), geo()->lat() );
+ }
+
+ // recalculate new times and objects
+ data()->setSnapNextFocus();
+ updateTime();
+ }
+ }
+}
+
+void KStars::slotViewOps() {
+ KStandardDirs stdDirs;
+
+ //An instance of your dialog could be already created and could be cached,
+ //in which case you want to display the cached dialog instead of creating
+ //another one
+ if ( KConfigDialog::showDialog( "settings" ) ) return;
+
+ //KConfigDialog didn't find an instance of this dialog, so lets create it :
+ KConfigDialog* dialog = new KConfigDialog( this, "settings",
+ Options::self() );
+
+ connect( dialog, SIGNAL( applyClicked() ), this, SLOT( slotApplySettings() ) );
+ connect( dialog, SIGNAL( okClicked() ), this, SLOT( slotApplySettings() ) );
+
+ OpsCatalog *opcatalog = new OpsCatalog( this, "catalogs" );
+ OpsGuides *opguides = new OpsGuides( this, "guides" );
+ OpsSolarSystem *opsolsys = new OpsSolarSystem( this, "solarsystem" );
+ OpsColors *opcolors = new OpsColors( this, "colors" );
+ OpsAdvanced *opadvanced = new OpsAdvanced( this, "advanced" );
+
+ dialog->addPage(opcatalog, i18n("Catalogs"), "kstars_catalog");
+ dialog->addPage(opsolsys, i18n("Solar System"), "kstars_solarsystem");
+ dialog->addPage(opguides, i18n("Guides"), "kstars_guides");
+ dialog->addPage(opcolors, i18n("Colors"), "kstars_colors");
+ dialog->addPage(opadvanced, i18n("Advanced"), "kstars_advanced");
+
+ dialog->show();
+}
+
+void KStars::slotApplyConfigChanges() {
+ Options::writeConfig();
+ applyConfig();
+ data()->setFullTimeUpdate();
+ map()->forceUpdate();
+}
+
+void KStars::slotSetTime() {
+ TimeDialog timedialog ( data()->lt(), this );
+
+ if ( timedialog.exec() == QDialog::Accepted ) {
+ data()->changeDateTime( geo()->LTtoUT( timedialog.selectedDateTime() ) );
+
+ if ( Options::useAltAz() ) {
+ map()->focus()->HorizontalToEquatorial( LST(), geo()->lat() );
+ }
+
+ //If focusObject has a Planet Trail, clear it and start anew.
+ if ( map()->focusObject() && map()->focusObject()->isSolarSystem() &&
+ ((KSPlanetBase*)map()->focusObject())->hasTrail() ) {
+ ((KSPlanetBase*)map()->focusObject())->clearTrail();
+ ((KSPlanetBase*)map()->focusObject())->addToTrail();
+ }
+ }
+}
+
+void KStars::slotFind() {
+ clearCachedFindDialog();
+ if ( !findDialog ) { // create new dialog if no dialog is existing
+ findDialog = new FindDialog( this );
+ }
+
+ if ( !findDialog ) kdWarning() << i18n( "KStars::slotFind() - Not enough memory for dialog" ) << endl;
+
+ if ( findDialog->exec() == QDialog::Accepted && findDialog->currentItem() ) {
+ map()->setClickedObject( findDialog->currentItem()->objName()->skyObject() );
+ map()->setClickedPoint( map()->clickedObject() );
+ map()->slotCenter();
+ }
+
+ // check if data has changed while dialog was open
+ if ( DialogIsObsolete ) clearCachedFindDialog();
+}
+
+/** Menu Slots **/
+
+//File
+void KStars::newWindow() {
+ new KStars(true);
+}
+
+void KStars::closeWindow() {
+ // since QT 3.1 close() just emits lastWindowClosed if the window is not hidden
+ show();
+ close();
+}
+
+void KStars::slotOpenFITS()
+{
+
+ KURL fileURL = KFileDialog::getOpenURL( QDir::homeDirPath(), "*.fits *.fit *.fts|Flexible Image Transport System");
+
+ if (fileURL.isEmpty())
+ return;
+
+ FITSViewer * fv = new FITSViewer(&fileURL, this);
+ fv->show();
+
+}
+
+void KStars::slotExportImage() {
+ KURL fileURL = KFileDialog::getSaveURL( QDir::homeDirPath(), "image/png image/jpeg image/gif image/x-portable-pixmap image/x-bmp" );
+
+ //Warn user if file exists!
+ if (QFile::exists(fileURL.path()))
+ {
+ int r=KMessageBox::warningContinueCancel(static_cast<QWidget *>(parent()),
+ i18n( "A file named \"%1\" already exists. "
+ "Overwrite it?" ).arg(fileURL.fileName()),
+ i18n( "Overwrite File?" ),
+ i18n( "&Overwrite" ) );
+
+ if(r==KMessageBox::Cancel) return;
+ }
+
+ exportImage( fileURL.url(), map()->width(), map()->height() );
+}
+
+void KStars::slotRunScript() {
+ KURL fileURL = KFileDialog::getOpenURL( QDir::homeDirPath(), "*.kstars|KStars Scripts (*.kstars)" );
+ QFile f;
+ QString fname;
+
+ if ( fileURL.isValid() ) {
+ if ( ! fileURL.isLocalFile() ) {
+ //Warn the user about executing remote code.
+ QString message = i18n( "Warning: You are about to execute a remote shell script on your machine. " );
+ message += i18n( "If you absolutely trust the source of this script, press Continue to execute the script; " );
+ message += i18n( "to save the file without executing it, press Save; " );
+ message += i18n( "to cancel the download, press Cancel. " );
+
+ int result = KMessageBox::warningYesNoCancel( 0, message, i18n( "Really Execute Remote Script?" ),
+ KStdGuiItem::cont(), KStdGuiItem::save() );
+
+ if ( result == KMessageBox::Cancel ) return;
+ if ( result == KMessageBox::No ) { //save file
+ KURL saveURL = KFileDialog::getSaveURL( QDir::homeDirPath(), "*.kstars|KStars Scripts (*.kstars)" );
+ KTempFile tmpfile;
+ tmpfile.setAutoDelete(true);
+
+ while ( ! saveURL.isValid() ) {
+ message = i18n( "Save location is invalid. Try another location?" );
+ if ( KMessageBox::warningYesNo( 0, message, i18n( "Invalid Save Location" ), i18n("Try Another"), i18n("Do Not Try") ) == KMessageBox::No ) return;
+ saveURL = KFileDialog::getSaveURL( QDir::homeDirPath(), "*.kstars|KStars Scripts (*.kstars)" );
+ }
+
+ if ( saveURL.isLocalFile() ) {
+ fname = saveURL.path();
+ } else {
+ fname = tmpfile.name();
+ }
+
+ if( KIO::NetAccess::download( fileURL, fname, this ) ) {
+ chmod( fname.ascii(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH ); //make it executable
+
+ if ( tmpfile.name() == fname ) { //upload to remote location
+ if ( ! KIO::NetAccess::upload( tmpfile.name(), fileURL, this ) ) {
+ QString message = i18n( "Could not upload image to remote location: %1" ).arg( fileURL.prettyURL() );
+ KMessageBox::sorry( 0, message, i18n( "Could not upload file" ) );
+ }
+ }
+ } else {
+ KMessageBox::sorry( 0, i18n( "Could not download the file." ), i18n( "Download Error" ) );
+ }
+
+ return;
+ }
+ }
+
+ //Damn the torpedos and full speed ahead, we're executing the script!
+ KTempFile tmpfile;
+ tmpfile.setAutoDelete(true);
+
+ if ( ! fileURL.isLocalFile() ) {
+ fname = tmpfile.name();
+ if( KIO::NetAccess::download( fileURL, fname, this ) ) {
+ chmod( fname.ascii(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH );
+ f.setName( fname );
+ }
+ } else {
+ f.setName( fileURL.path() );
+ }
+
+ if ( !f.open( IO_ReadOnly) ) {
+ QString message = i18n( "Could not open file %1" ).arg( f.name() );
+ KMessageBox::sorry( 0, message, i18n( "Could Not Open File" ) );
+ return;
+ }
+
+ // Before we run the script, make sure that it's safe. Each line must either begin with "#"
+ // or begin with "dcop $KSTARS". Otherwise, the line must be equal to one of the following:
+ // "KSTARS=`dcopfind -a 'kstars*'`"; "MAIN=KStarsInterface"; or "CLOCK=clock#1"
+ QTextStream istream(&f);
+ QString line;
+ bool fileOK( true );
+
+ while ( ! istream.eof() ) {
+ line = istream.readLine();
+ if ( line.left(1) != "#" && line.left(12) != "dcop $KSTARS"
+ && line.stripWhiteSpace() != "KSTARS=`dcopfind -a 'kstars*'`"
+ && line.stripWhiteSpace() != "MAIN=KStarsInterface"
+ && line.stripWhiteSpace() != "CLOCK=clock#1" ) {
+ fileOK = false;
+ break;
+ }
+ }
+
+ if ( ! fileOK ) {
+ int answer;
+ answer = KMessageBox::warningContinueCancel( 0, i18n( "The selected script contains unrecognized elements,"
+ "indicating that it was not created using the KStars script builder. "
+ "This script may not function properly, and it may even contain malicious code. "
+ "Would you like to execute it anyway?" ),
+ i18n( "Script Validation Failed" ), i18n("Run Nevertheless"), "daExecuteScript" );
+ if ( answer == KMessageBox::Cancel ) return;
+ }
+
+ //FIXME STRINGS FREEZE
+ //Add statusbar message that script is running
+ //ks->statusBar()->changeItem( i18n( "Running script: %1" ).arg( fileURL.fileName() ), 0 );
+
+ KProcess p;
+ p << f.name();
+ p.start( KProcess::DontCare );
+
+ while ( p.isRunning() ) kapp->processEvents( 50 ); //otherwise tempfile may get deleted before script completes.
+ }
+}
+
+void KStars::slotPrint() {
+ bool switchColors(false);
+
+ //Suggest Chart color scheme
+ if ( data()->colorScheme()->colorNamed( "SkyColor" ) != "#FFFFFF" ) {
+ QString message = i18n( "You can save printer ink by using the \"Star Chart\" "
+ "color scheme, which uses a white background. Would you like to "
+ "temporarily switch to the Star Chart color scheme for printing?" );
+
+ int answer;
+ answer = KMessageBox::questionYesNoCancel( 0, message, i18n( "Switch to Star Chart Colors?" ),
+ i18n("Switch Color Scheme"), i18n("Do Not Switch"), "askAgainPrintColors" );
+
+ if ( answer == KMessageBox::Cancel ) return;
+ if ( answer == KMessageBox::Yes ) switchColors = true;
+ }
+
+ printImage( true, switchColors );
+}
+
+//Set Time to CPU clock
+void KStars::slotSetTimeToNow() {
+ data()->changeDateTime( geo()->LTtoUT( KStarsDateTime::currentDateTime() ) );
+
+ if ( Options::useAltAz() ) {
+ map()->focus()->HorizontalToEquatorial( LST(), geo()->lat() );
+ }
+
+ //If focusObject has a Planet Trail, clear it and start anew.
+ if ( map()->focusObject() && map()->focusObject()->isSolarSystem() &&
+ ((KSPlanetBase*)map()->focusObject())->hasTrail() ) {
+ ((KSPlanetBase*)map()->focusObject())->clearTrail();
+ ((KSPlanetBase*)map()->focusObject())->addToTrail();
+ }
+}
+
+void KStars::slotToggleTimer() {
+ if ( data()->clock()->isActive() ) {
+ data()->clock()->stop();
+ updateTime();
+ } else {
+ if ( fabs( data()->clock()->scale() ) > Options::slewTimeScale() )
+ data()->clock()->setManualMode( true );
+ data()->clock()->start();
+ if ( data()->clock()->isManualMode() ) map()->forceUpdate();
+ }
+}
+
+//Focus
+void KStars::slotPointFocus() {
+ QString sentFrom( sender()->name() );
+
+ if ( sentFrom == "zenith" )
+ map()->invokeKey( KKey( "Z" ).keyCodeQt() );
+ else if ( sentFrom == "north" )
+ map()->invokeKey( KKey( "N" ).keyCodeQt() );
+ else if ( sentFrom == "east" )
+ map()->invokeKey( KKey( "E" ).keyCodeQt() );
+ else if ( sentFrom == "south" )
+ map()->invokeKey( KKey( "S" ).keyCodeQt() );
+ else if ( sentFrom == "west" )
+ map()->invokeKey( KKey( "W" ).keyCodeQt() );
+}
+
+void KStars::slotTrack() {
+ if ( Options::isTracking() ) {
+ Options::setIsTracking( false );
+ actionCollection()->action("track_object")->setText( i18n( "Engage &Tracking" ) );
+ actionCollection()->action("track_object")->setIconSet( BarIcon( "decrypted" ) );
+ if ( map()->focusObject() && map()->focusObject()->isSolarSystem() && data()->temporaryTrail ) {
+ ((KSPlanetBase*)map()->focusObject())->clearTrail();
+ data()->temporaryTrail = false;
+ }
+
+ map()->setClickedObject( NULL );
+ map()->setFocusObject( NULL );//no longer tracking focusObject
+ map()->setFocusPoint( NULL );
+ } else {
+ map()->setClickedPoint( map()->focus() );
+ map()->setClickedObject( NULL );
+ map()->setFocusObject( NULL );//no longer tracking focusObject
+ map()->setFocusPoint( map()->clickedPoint() );
+ Options::setIsTracking( true );
+ actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) );
+ actionCollection()->action("track_object")->setIconSet( BarIcon( "encrypted" ) );
+ }
+
+ map()->forceUpdate();
+}
+
+void KStars::slotManualFocus() {
+ FocusDialog focusDialog( this ); // = new FocusDialog( this );
+ if ( Options::useAltAz() ) focusDialog.activateAzAltPage();
+
+ if ( focusDialog.exec() == QDialog::Accepted ) {
+ //If the requested position is very near the pole, we need to point first
+ //to an intermediate location just below the pole in order to get the longitudinal
+ //position (RA/Az) right.
+ double realAlt( focusDialog.point()->alt()->Degrees() );
+ double realDec( focusDialog.point()->dec()->Degrees() );
+ if ( Options::useAltAz() && realAlt > 89.0 ) {
+ focusDialog.point()->setAlt( 89.0 );
+ }
+ if ( ! Options::useAltAz() && realDec > 89.0 ) {
+ focusDialog.point()->setDec( 89.0 );
+ }
+
+ //Do we need to convert Az/Alt to RA/Dec?
+ if ( focusDialog.usedAltAz() )
+ focusDialog.point()->HorizontalToEquatorial( LST(), geo()->lat() );
+
+ //Do we need to convert RA/Dec to Alt/Az?
+ if ( ! focusDialog.usedAltAz() )
+ focusDialog.point()->EquatorialToHorizontal( LST(), geo()->lat() );
+
+ map()->setClickedPoint( focusDialog.point() );
+ if ( Options::isTracking() ) slotTrack();
+
+ map()->slotCenter();
+
+ //The slew takes some time to complete, and this often causes the final focus point to be slightly
+ //offset from the user's requested coordinates (because EquatorialToHorizontal() is called
+ //throughout the process, which depends on the sidereal time). So we now "polish" the final
+ //position by resetting the final focus to the focusDialog point.
+ //
+ //Also, if the requested position was within 1 degree of the coordinate pole, this will
+ //automatically correct the final pointing from the intermediate offset position to the final position
+ if ( Options::useAltAz() ) {
+ data()->setSnapNextFocus();
+ map()->setDestinationAltAz( focusDialog.point()->alt()->Degrees(), focusDialog.point()->az()->Degrees() );
+ } else {
+ data()->setSnapNextFocus();
+ map()->setDestination( focusDialog.point()->ra()->Hours(), focusDialog.point()->dec()->Degrees() );
+ }
+
+ //Now, if the requested point was near a pole, we need to reset the Alt/Dec of the focus.
+ if ( Options::useAltAz() && realAlt > 89.0 ) map()->focus()->setAlt( realAlt );
+ if ( ! Options::useAltAz() && realDec > 89.0 ) map()->focus()->setDec( realAlt );
+
+ //Don't track if we set Alt/Az coordinates. This way, Alt/Az remain constant.
+ if ( focusDialog.usedAltAz() ) map()->stopTracking();
+ }
+}
+
+//View Menu
+void KStars::slotZoomIn() {
+ actionCollection()->action("zoom_out")->setEnabled (true);
+ if ( Options::zoomFactor() < MAXZOOM )
+ Options::setZoomFactor( Options::zoomFactor()*DZOOM );
+
+ if ( Options::zoomFactor() >= MAXZOOM ) {
+ Options::setZoomFactor( MAXZOOM );
+ actionCollection()->action("zoom_in")->setEnabled (false);
+ }
+
+ map()->forceUpdate();
+}
+
+void KStars::slotZoomOut() {
+ actionCollection()->action("zoom_in")->setEnabled (true);
+ if ( Options::zoomFactor() > MINZOOM )
+ Options::setZoomFactor( Options::zoomFactor()/DZOOM );
+
+ if ( Options::zoomFactor() <= MINZOOM ) {
+ Options::setZoomFactor( MINZOOM );
+ actionCollection()->action("zoom_out")->setEnabled (false);
+ }
+
+ map()->forceUpdate();
+}
+
+void KStars::slotDefaultZoom() {
+ Options::setZoomFactor( DEFAULTZOOM );
+ map()->forceUpdate();
+
+ if ( Options::zoomFactor() > MINZOOM )
+ actionCollection()->action("zoom_out")->setEnabled (true);
+ if ( Options::zoomFactor() < MAXZOOM )
+ actionCollection()->action("zoom_in")->setEnabled (true);
+}
+
+void KStars::slotSetZoom() {
+ bool ok( false );
+ double currentAngle = map()->width() / ( Options::zoomFactor() * dms::DegToRad );
+ double angSize = currentAngle;
+ double minAngle = map()->width() / ( MAXZOOM * dms::DegToRad );
+ double maxAngle = map()->width() / ( MINZOOM * dms::DegToRad );
+
+ angSize = KInputDialog::getDouble( i18n( "The user should enter an angle for the field-of-view of the display",
+ "Enter Desired Field-of-View Angle" ), i18n( "Enter a field-of-view angle in degrees: " ),
+ currentAngle, minAngle, maxAngle, 0.1, 1, &ok );
+
+ if ( ok ) {
+ Options::setZoomFactor( map()->width() / ( angSize * dms::DegToRad ) );
+
+ if ( Options::zoomFactor() <= MINZOOM ) {
+ Options::setZoomFactor( MINZOOM );
+ actionCollection()->action("zoom_out")->setEnabled( false );
+ } else {
+ actionCollection()->action("zoom_out")->setEnabled( true );
+ }
+
+ if ( Options::zoomFactor() >= MAXZOOM ) {
+ Options::setZoomFactor( MAXZOOM );
+ actionCollection()->action("zoom_in")->setEnabled( false );
+ } else {
+ actionCollection()->action("zoom_in")->setEnabled( true );
+ }
+
+ map()->forceUpdate();
+ }
+}
+
+void KStars::slotCoordSys() {
+ if ( Options::useAltAz() ) {
+ Options::setUseAltAz( false );
+ if ( Options::useRefraction() ) {
+ if ( map()->focusObject() ) //simply update focus to focusObject's position
+ map()->setFocus( map()->focusObject() );
+ else { //need to recompute focus for unrefracted position
+ map()->setFocusAltAz( map()->refract( map()->focus()->alt(), false ).Degrees(),
+ map()->focus()->az()->Degrees() );
+ map()->focus()->HorizontalToEquatorial( data()->lst(), geo()->lat() );
+ }
+ }
+ actCoordSys->turnOn();
+ } else {
+ Options::setUseAltAz( true );
+ if ( Options::useRefraction() ) {
+ map()->setFocusAltAz( map()->refract( map()->focus()->alt(), true ).Degrees(),
+ map()->focus()->az()->Degrees() );
+ }
+ actCoordSys->turnOff();
+ }
+ map()->forceUpdate();
+}
+
+//Settings Menu:
+void KStars::slotColorScheme() {
+ //use mid(3) to exclude the leading "cs_" prefix from the action name
+ QString filename = QString( sender()->name() ).mid(3) + ".colors";
+ loadColorScheme( filename );
+}
+
+void KStars::slotTargetSymbol() {
+ QString symbolName( sender()->name() );
+ FOV f( symbolName ); //read data from fov.dat
+
+ Options::setFOVName( f.name() );
+ Options::setFOVSize( f.size() );
+ Options::setFOVShape( f.shape() );
+ Options::setFOVColor( f.color() );
+ data()->fovSymbol.setName( Options::fOVName() );
+ data()->fovSymbol.setSize( Options::fOVSize() );
+ data()->fovSymbol.setShape( Options::fOVShape() );
+ data()->fovSymbol.setColor( Options::fOVColor().name() );
+
+//Careful!! If the user selects a small FOV (like HST), this basically crashes kstars :(
+// //set ZoomLevel to match the FOV symbol
+// zoom( (double)(map()->width()) * 60.0 / ( 2.0 * dms::DegToRad * data()->fovSymbol.size() ) );
+
+ map()->forceUpdate();
+}
+
+void KStars::slotFOVEdit() {
+ FOVDialog fovdlg( this );
+ if ( fovdlg.exec() == QDialog::Accepted ) {
+ //replace existing fov.dat with data from the FOVDialog
+ QFile f;
+ f.setName( locateLocal( "appdata", "fov.dat" ) );
+
+ //rebuild fov.dat if FOVList is empty
+ if ( fovdlg.FOVList.isEmpty() ) {
+ f.remove();
+ initFOV();
+ } else {
+ if ( ! f.open( IO_WriteOnly ) ) {
+ kdDebug() << i18n( "Could not open fov.dat for writing." ) << endl;
+ } else {
+ QTextStream ostream(&f);
+
+ for ( FOV *fov = fovdlg.FOVList.first(); fov; fov = fovdlg.FOVList.next() )
+ ostream << fov->name() << ":" << fov->size()
+ << ":" << QString("%1").arg( fov->shape() ) << ":" << fov->color() << endl;
+
+ f.close();
+ }
+ }
+
+ //repopulate FOV menu with items from new fov.dat
+ fovActionMenu->popupMenu()->clear();
+
+ if ( f.open( IO_ReadOnly ) ) {
+ QTextStream stream( &f );
+ while ( !stream.eof() ) {
+ QString line = stream.readLine();
+ QStringList fields = QStringList::split( ":", line );
+
+ if ( fields.count() == 4 ) {
+ QString nm = fields[0].stripWhiteSpace();
+ KToggleAction *kta = new KToggleAction( nm, 0, this, SLOT( slotTargetSymbol() ),
+ actionCollection(), nm.utf8() );
+ kta->setExclusiveGroup( "fovsymbol" );
+ fovActionMenu->insert( kta );
+ }
+ }
+ } else {
+ kdDebug() << i18n( "Could not open file: %1" ).arg( f.name() ) << endl;
+ }
+
+ fovActionMenu->popupMenu()->insertSeparator();
+ fovActionMenu->insert( new KAction( i18n( "Edit FOV Symbols..." ), 0, this,
+ SLOT( slotFOVEdit() ), actionCollection(), "edit_fov" ) );
+
+ //set FOV to whatever was highlighted in FOV dialog
+ if ( fovdlg.FOVList.count() > 0 ) {
+ Options::setFOVName( fovdlg.FOVList.at( fovdlg.currentItem() )->name() );
+ data()->fovSymbol.setName( Options::fOVName() );
+ data()->fovSymbol.setSize( Options::fOVSize() );
+ data()->fovSymbol.setShape( Options::fOVShape() );
+ data()->fovSymbol.setColor( Options::fOVColor().name() );
+ }
+
+//Careful!! If the user selects a small FOV (like HST), this basically crashes kstars :(
+// //set ZoomLevel to match the FOV symbol
+// zoom( (double)(map()->width()) * 60.0 / ( 2.0 * dms::DegToRad * data()->fovSymbol.size() ) );
+ }
+}
+
+void KStars::slotObsList() {
+ obsList->show();
+}
+
+//Help Menu
+void KStars::slotTipOfDay() {
+ KTipDialog::showTip("kstars/tips", true);
+}
+
+// Toggle to and from full screen mode
+void KStars::slotFullScreen()
+{
+ if ( topLevelWidget()->isFullScreen() ) {
+ topLevelWidget()->showNormal();
+ }
+ else {
+ topLevelWidget()->showFullScreen();
+ }
+}
+
+void KStars::slotClearAllTrails() {
+ //Exclude object with temporary trail
+ SkyObject *exOb( NULL );
+ if ( map()->focusObject() && map()->focusObject()->isSolarSystem() && data()->temporaryTrail ) {
+ exOb = map()->focusObject();
+ }
+
+ //Major bodies
+ if ( !( exOb && exOb->name() == "Moon" ) ) data()->Moon->clearTrail();
+ if ( !( exOb && exOb->name() == "Sun" ) ) data()->PCat->findByName("Sun")->clearTrail();
+ if ( !( exOb && exOb->name() == "Mercury" ) ) data()->PCat->findByName("Mercury")->clearTrail();
+ if ( !( exOb && exOb->name() == "Venus" ) ) data()->PCat->findByName("Venus")->clearTrail();
+ if ( !( exOb && exOb->name() == "Mars" ) ) data()->PCat->findByName("Mars")->clearTrail();
+ if ( !( exOb && exOb->name() == "Jupiter" ) ) data()->PCat->findByName("Jupiter")->clearTrail();
+ if ( !( exOb && exOb->name() == "Saturn" ) ) data()->PCat->findByName("Saturn")->clearTrail();
+ if ( !( exOb && exOb->name() == "Uranus" ) ) data()->PCat->findByName("Uranus")->clearTrail();
+ if ( !( exOb && exOb->name() == "Neptune" ) ) data()->PCat->findByName("Neptune")->clearTrail();
+ if ( !( exOb && exOb->name() == "Pluto" ) ) data()->PCat->findByName("Pluto")->clearTrail();
+
+ //Asteroids
+ for ( KSAsteroid *ast = data()->asteroidList.first(); ast; ast = data()->asteroidList.next() )
+ if ( !( exOb && exOb->name() == ast->name() ) ) ast->clearTrail();
+
+ //Comets
+ for ( KSComet *com = data()->cometList.first(); com; com = data()->cometList.next() )
+ if ( !( exOb && exOb->name() == com->name() ) ) com->clearTrail();
+
+ map()->forceUpdate();
+}
+
+//toggle display of GUI Items on/off
+void KStars::slotShowGUIItem( bool show ) {
+//Toolbars
+ if ( sender()->name() == QString( "show_mainToolBar" ) ) {
+ Options::setShowMainToolBar( show );
+ if ( show ) toolBar( "mainToolBar" )->show();
+ else toolBar( "mainToolBar" )->hide();
+ }
+ if ( sender()->name() == QString( "show_viewToolBar" ) ) {
+ Options::setShowViewToolBar( show );
+ if ( show ) toolBar( "viewToolBar" )->show();
+ else toolBar( "viewToolBar" )->hide();
+ }
+
+ if ( sender()->name() == QString( "show_statusBar" ) ) {
+ Options::setShowStatusBar( show );
+ if ( show ) statusBar()->show();
+ else statusBar()->hide();
+ }
+
+ if ( sender()->name() == QString( "show_sbAzAlt" ) ) {
+ Options::setShowAltAzField( show );
+ if ( show ) {
+ //To preserve the order (AzAlt before RADec), we have to remove
+ //the RADec field and then add both back.
+ if ( Options::showRADecField() ) statusBar()->removeItem( 2 );
+
+ QString s = "000d 00m 00s, +00d 00\' 00\""; //only need this to set the width
+ statusBar()->insertFixedItem( s, 1, true );
+ statusBar()->setItemAlignment( 1, AlignRight | AlignVCenter );
+ statusBar()->changeItem( "", 1 );
+
+ if ( Options::showRADecField() ) {
+ statusBar()->insertFixedItem( s, 2, true );
+ statusBar()->setItemAlignment( 2, AlignRight | AlignVCenter );
+ statusBar()->changeItem( "", 2 );
+ }
+ } else {
+ statusBar()->removeItem( 1 );
+ }
+ }
+
+ if ( sender()->name() == QString( "show_sbRADec" ) ) {
+ Options::setShowRADecField( show );
+ if ( show ) {
+ QString s = "000d 00m 00s, +00d 00\' 00\""; //only need this to set the width
+ statusBar()->insertFixedItem( s, 2, true );
+ statusBar()->setItemAlignment( 2, AlignRight | AlignVCenter );
+ statusBar()->changeItem( "", 2 );
+ } else {
+ statusBar()->removeItem( 2 );
+ }
+ }
+
+//InfoBoxes: we only change options here; these are also connected to slots in
+//InfoBoxes that actually toggle the display.
+ if ( sender()->name() == QString( "show_boxes" ) )
+ Options::setShowInfoBoxes( show );
+ if ( sender()->name() == QString( "show_time_box" ) )
+ Options::setShowTimeBox( show );
+ if ( sender()->name() == QString( "show_location_box" ) )
+ Options::setShowGeoBox( show );
+ if ( sender()->name() == QString( "show_focus_box" ) )
+ Options::setShowFocusBox( show );
+}
+
+void KStars::addColorMenuItem( QString name, QString actionName ) {
+ colorActionMenu->insert( new KAction( name, 0,
+ this, SLOT( slotColorScheme() ), actionCollection(), actionName.local8Bit() ) );
+}
+
+void KStars::removeColorMenuItem( QString actionName ) {
+ kdDebug() << "removing " << actionName << endl;
+ colorActionMenu->remove( actionCollection()->action( actionName.local8Bit() ) );
+}
+
+void KStars::establishINDI()
+{
+ if (indimenu == NULL)
+ indimenu = new INDIMenu(this);
+
+ if (indidriver == NULL)
+ indidriver = new INDIDriver(this);
+}
+