You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
741 lines
23 KiB
741 lines
23 KiB
/***************************************************************************
|
|
observinglist.cpp - Trinity Desktop Planetarium
|
|
-------------------
|
|
begin : 29 Nov 2004
|
|
copyright : (C) 2004 by Jeff Woods, Jason Harris
|
|
email : jcwoods@bellsouth.net, 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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <tqfile.h>
|
|
#include <tqdir.h>
|
|
#include <tqlabel.h>
|
|
#include <tqlayout.h>
|
|
#include <tqstringlist.h>
|
|
#include <tqwidgetstack.h>
|
|
#include <tdelistview.h>
|
|
#include <kpushbutton.h>
|
|
#include <kstatusbar.h>
|
|
#include <ktextedit.h>
|
|
#include <kinputdialog.h>
|
|
#include <kicontheme.h>
|
|
#include <kiconloader.h>
|
|
#include <tdeio/netaccess.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdefiledialog.h>
|
|
#include <tdetempfile.h>
|
|
#include <klineedit.h>
|
|
|
|
#include "observinglist.h"
|
|
#include "observinglistui.h"
|
|
#include "obslistwizard.h"
|
|
#include "kstars.h"
|
|
#include "kstarsdata.h"
|
|
#include "skyobject.h"
|
|
#include "starobject.h"
|
|
#include "skymap.h"
|
|
#include "detaildialog.h"
|
|
#include "tools/altvstime.h"
|
|
|
|
#include "indimenu.h"
|
|
#include "indielement.h"
|
|
#include "indiproperty.h"
|
|
#include "indidevice.h"
|
|
#include "devicemanager.h"
|
|
#include "indistd.h"
|
|
|
|
ObservingList::ObservingList( KStars *_ks, TQWidget* parent )
|
|
: KDialogBase( KDialogBase::Plain, i18n( "Observing List" ),
|
|
Close, Close, parent, "observinglist", false ), ks( _ks ), LogObject(0), oCurrent(0),
|
|
noNameStars(0), isModified(false), bIsLarge(true)
|
|
{
|
|
TQFrame *page = plainPage();
|
|
TQVBoxLayout *vlay = new TQVBoxLayout( page, 0, 0 );
|
|
ui = new ObservingListUI( page );
|
|
vlay->addWidget( ui );
|
|
|
|
//FIXME: enable MiniButton when I figure out how to resize the window correctly
|
|
ui->MiniButton->hide();
|
|
|
|
//Connections
|
|
connect( this, TQT_SIGNAL( closeClicked() ), this, TQT_SLOT( slotClose() ) );
|
|
connect( ui->TableStack, TQT_SIGNAL( aboutToShow( TQWidget* ) ),
|
|
this, TQT_SLOT( slotPrepTable( TQWidget* ) ) );
|
|
connect( ui->FullTable, TQT_SIGNAL( selectionChanged() ),
|
|
this, TQT_SLOT( slotNewSelection() ) );
|
|
connect( ui->TinyTable, TQT_SIGNAL( selectionChanged() ),
|
|
this, TQT_SLOT( slotNewSelection() ) );
|
|
connect( ui->FullTable, TQT_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint&, int) ),
|
|
this, TQT_SLOT( slotCenterObject() ) );
|
|
connect( ui->TinyTable, TQT_SIGNAL( doubleClicked( TQListBoxItem* ) ),
|
|
this, TQT_SLOT( slotCenterObject() ) );
|
|
connect( ui->RemoveButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotRemoveObjects() ) );
|
|
connect( ui->CenterButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotCenterObject() ) );
|
|
connect( ui->ScopeButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotSlewToObject() ) );
|
|
connect( ui->DetailsButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotDetails() ) );
|
|
connect( ui->AVTButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotAVT() ) );
|
|
|
|
connect( ui->OpenButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotOpenList() ) );
|
|
connect( ui->SaveButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotSaveList() ) );
|
|
connect( ui->SaveAsButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotSaveListAs() ) );
|
|
connect( ui->WizardButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( slotWizard() ) );
|
|
|
|
//FIXME: enable MiniButton
|
|
// connect( ui->MiniButton, TQT_SIGNAL( clicked() ),
|
|
// this, TQT_SLOT( slotToggleSize() ) );
|
|
|
|
obsList.setAutoDelete( false ); //do NOT delete removed pointers!
|
|
|
|
//Add icons to Push Buttons
|
|
TDEIconLoader *icons = TDEGlobal::iconLoader();
|
|
ui->OpenButton->setPixmap( icons->loadIcon( "document-open", TDEIcon::Toolbar ) );
|
|
ui->SaveButton->setPixmap( icons->loadIcon( "document-save", TDEIcon::Toolbar ) );
|
|
ui->SaveAsButton->setPixmap( icons->loadIcon( "document-save-as", TDEIcon::Toolbar ) );
|
|
ui->WizardButton->setPixmap( icons->loadIcon( "wizard", TDEIcon::Toolbar ) );
|
|
ui->MiniButton->setPixmap( icons->loadIcon( "view-restore", TDEIcon::Toolbar ) );
|
|
|
|
ui->CenterButton->setEnabled( false );
|
|
ui->ScopeButton->setEnabled( false );
|
|
ui->DetailsButton->setEnabled( false );
|
|
ui->AVTButton->setEnabled( false );
|
|
ui->RemoveButton->setEnabled( false );
|
|
ui->NotesLabel->setEnabled( false );
|
|
ui->NotesEdit->setEnabled( false );
|
|
}
|
|
|
|
bool ObservingList::contains( const SkyObject *q ) {
|
|
for ( SkyObject* o = obsList.first(); o; o = obsList.next() ) {
|
|
if ( o == q ) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//SLOTS
|
|
void ObservingList::slotPrepTable( TQWidget *tab ) {
|
|
if ( tab == ui->FullTable ) {
|
|
} else {
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotAddObject( SkyObject *obj ) {
|
|
if ( ! obj ) obj = ks->map()->clickedObject();
|
|
|
|
//First, make sure object is not already in the list
|
|
for ( SkyObject *o = obsList.first(); o; o = obsList.next() ) {
|
|
if ( obj == o ) {
|
|
//FIXME STRINGS FREEZE
|
|
//ks->statusBar()->changeItem( i18n( "%1 is already in the observing list." ).arg( obj->name() ), 0 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//Insert object in obsList
|
|
obsList.append( obj );
|
|
if ( ! isModified ) isModified = true;
|
|
|
|
//Insert object entry in FullTable and TinyTable
|
|
TQString smag("--");
|
|
if ( obj->mag() < 90.0 ) smag = TQString::number( obj->mag(), 'g', 2 );
|
|
new TDEListViewItem( ui->FullTable, obj->translatedName(),
|
|
obj->ra()->toHMSString(),
|
|
obj->dec()->toDMSString(),
|
|
smag,
|
|
obj->typeName() );
|
|
ui->TinyTable->insertItem( obj->translatedName() );
|
|
|
|
//Note addition in statusbar
|
|
ks->statusBar()->changeItem( i18n( "Added %1 to observing list." ).arg( obj->name() ), 0 );
|
|
}
|
|
|
|
void ObservingList::slotRemoveObject( SkyObject *o ) {
|
|
if ( !o )
|
|
o = ks->map()->clickedObject();
|
|
|
|
obsList.remove(o);
|
|
if ( ! isModified ) isModified = true;
|
|
|
|
if ( o == LogObject )
|
|
saveCurrentUserLog();
|
|
|
|
//Remove entry from FullTable
|
|
bool objectFound = false;
|
|
TQListViewItemIterator it( ui->FullTable );
|
|
while ( it.current() ) {
|
|
TQListViewItem *item = it.current();
|
|
|
|
//If the object is named "star" then match coordinates instead of name
|
|
if ( o->translatedName() == i18n( "star" ) ) {
|
|
if ( item->text(1) == o->ra()->toHMSString()
|
|
&& item->text(2) == o->dec()->toDMSString() ) {
|
|
delete item;
|
|
objectFound = true;
|
|
break;
|
|
}
|
|
} else if ( item->text( 0 ) == o->translatedName() ) {
|
|
delete item;
|
|
objectFound = true;
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
if ( ! objectFound ) {
|
|
kdDebug() << i18n( "Cannot remove Object %1; not found in table." ).arg(o->translatedName()) << endl;
|
|
} else {
|
|
//Remove object from TinyTable
|
|
for ( uint i=0; i < ui->TinyTable->count(); i++ ) {
|
|
if ( o->translatedName() == ui->TinyTable->text(i) ) {
|
|
ui->TinyTable->removeItem(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotRemoveObjects() {
|
|
if ( SelectedObjects.count() == 0) return;
|
|
|
|
for ( SkyObject *o = SelectedObjects.first(); o; o = SelectedObjects.next() )
|
|
slotRemoveObject( o );
|
|
|
|
slotNewSelection();
|
|
}
|
|
|
|
void ObservingList::slotNewSelection() {
|
|
//If the TinyTable is visible, we need to sync the selection in the FullTable
|
|
if ( sender() == ui->TinyTable ) syncTableSelection();
|
|
|
|
//Construct list of selected objects
|
|
SelectedObjects.clear();
|
|
TQListViewItemIterator it( ui->FullTable, TQListViewItemIterator::Selected ); //loop over selected items
|
|
while ( it.current() ) {
|
|
for ( SkyObject *o = obsList.first(); o; o = obsList.next() ) {
|
|
if ( it.current()->text(0) == i18n("star") ) {
|
|
if ( it.current()->text(1) == o->ra()->toHMSString()
|
|
&& it.current()->text(2) == o->dec()->toDMSString() ) {
|
|
SelectedObjects.append(o);
|
|
break;
|
|
}
|
|
} else if ( o->translatedName() == it.current()->text(0) ) {
|
|
SelectedObjects.append( o );
|
|
break;
|
|
}
|
|
}
|
|
it++;
|
|
}
|
|
|
|
//Enable widgets when one object selected
|
|
if ( SelectedObjects.count() == 1 ) {
|
|
TQString newName( SelectedObjects.first()->translatedName() );
|
|
TQString oldName( obsList.current()->translatedName() );
|
|
|
|
//Enable buttons
|
|
ui->CenterButton->setEnabled( true );
|
|
ui->ScopeButton->setEnabled( true );
|
|
ui->DetailsButton->setEnabled( true );
|
|
ui->AVTButton->setEnabled( true );
|
|
ui->RemoveButton->setEnabled( true );
|
|
|
|
//Find the selected object in the obsList,
|
|
//then break the loop. Now obsList.current()
|
|
//points to the new selected object (until now it was the previous object)
|
|
bool found( false );
|
|
for ( SkyObject* o = obsList.first(); o; o = obsList.next() ) {
|
|
if ( o->translatedName() == newName ) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! found ) {
|
|
kdDebug() << i18n( "Object %1 not found in obsList." ).arg( newName ) << endl;
|
|
} else if ( newName != i18n( "star" ) ) {
|
|
//Display the object's current user notes in the NotesEdit
|
|
//First, save the last object's user log to disk, if necessary
|
|
saveCurrentUserLog();
|
|
|
|
//set LogObject to the new selected object
|
|
LogObject = obsList.current();
|
|
|
|
ui->NotesLabel->setEnabled( true );
|
|
ui->NotesEdit->setEnabled( true );
|
|
|
|
ui->NotesLabel->setText( i18n( "observing notes for %1:" ).arg( LogObject->translatedName() ) );
|
|
if ( LogObject->userLog.isEmpty() ) {
|
|
ui->NotesEdit->setText( i18n("Record here observation logs and/or data on %1.").arg( LogObject->translatedName() ) );
|
|
} else {
|
|
ui->NotesEdit->setText( LogObject->userLog );
|
|
}
|
|
} else { //selected object is named "star"
|
|
//clear the log text box
|
|
saveCurrentUserLog();
|
|
ui->NotesLabel->setEnabled( false );
|
|
ui->NotesEdit->setEnabled( false );
|
|
}
|
|
|
|
//This shouldn't be necessary. For some reason, obsList.current()
|
|
//is valid here, but in subsequent functions (such as slotCenterObject)
|
|
//called *right after* this one, obsList.current()==NULL. No idea why.
|
|
oCurrent = obsList.current();
|
|
|
|
} else if ( SelectedObjects.count() == 0 ) {
|
|
//Disable buttons
|
|
ui->CenterButton->setEnabled( false );
|
|
ui->ScopeButton->setEnabled( false );
|
|
ui->DetailsButton->setEnabled( false );
|
|
ui->AVTButton->setEnabled( false );
|
|
ui->RemoveButton->setEnabled( false );
|
|
ui->NotesLabel->setEnabled( false );
|
|
ui->NotesEdit->setEnabled( false );
|
|
oCurrent = 0;
|
|
|
|
//Clear the user log text box.
|
|
saveCurrentUserLog();
|
|
} else { //more than one object selected.
|
|
ui->CenterButton->setEnabled( false );
|
|
ui->ScopeButton->setEnabled( false );
|
|
ui->DetailsButton->setEnabled( false );
|
|
ui->AVTButton->setEnabled( true );
|
|
ui->RemoveButton->setEnabled( true );
|
|
ui->NotesLabel->setEnabled( false );
|
|
ui->NotesEdit->setEnabled( false );
|
|
oCurrent = 0;
|
|
|
|
//Clear the user log text box.
|
|
saveCurrentUserLog();
|
|
}
|
|
|
|
}
|
|
|
|
void ObservingList::slotCenterObject() {
|
|
if ( oCurrent ) {
|
|
ks->map()->setClickedObject( oCurrent );
|
|
ks->map()->setClickedPoint( oCurrent );
|
|
ks->map()->slotCenter();
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotSlewToObject()
|
|
{
|
|
|
|
INDI_D *indidev(NULL);
|
|
INDI_P *prop(NULL), *onset(NULL);
|
|
INDI_E *RAEle(NULL), *DecEle(NULL), *AzEle(NULL), *AltEle(NULL), *ConnectEle(NULL), *nameEle(NULL);
|
|
bool useJ2000( false);
|
|
int selectedCoord(0);
|
|
SkyPoint sp;
|
|
|
|
// Find the first device with EQUATORIAL_EOD_COORD or EQUATORIAL_COORD and with SLEW element
|
|
// i.e. the first telescope we find!
|
|
|
|
INDIMenu *imenu = ks->getINDIMenu();
|
|
|
|
|
|
for (unsigned int i=0; i < imenu->mgr.count() ; i++)
|
|
{
|
|
for (unsigned int j=0; j < imenu->mgr.at(i)->indi_dev.count(); j++)
|
|
{
|
|
indidev = imenu->mgr.at(i)->indi_dev.at(j);
|
|
indidev->stdDev->currentObject = NULL;
|
|
prop = indidev->findProp("EQUATORIAL_EOD_COORD");
|
|
if (prop == NULL)
|
|
{
|
|
prop = indidev->findProp("EQUATORIAL_COORD");
|
|
if (prop == NULL)
|
|
{
|
|
prop = indidev->findProp("HORIZONTAL_COORD");
|
|
if (prop == NULL)
|
|
continue;
|
|
else
|
|
selectedCoord = 1; /* Select horizontal */
|
|
}
|
|
else
|
|
useJ2000 = true;
|
|
}
|
|
|
|
ConnectEle = indidev->findElem("CONNECT");
|
|
if (!ConnectEle) continue;
|
|
|
|
if (ConnectEle->state == PS_OFF)
|
|
{
|
|
KMessageBox::error(0, i18n("Telescope %1 is offline. Please connect and retry again.").arg(indidev->label));
|
|
return;
|
|
}
|
|
|
|
switch (selectedCoord)
|
|
{
|
|
// Equatorial
|
|
case 0:
|
|
if (prop->perm == PP_RO) continue;
|
|
RAEle = prop->findElement("RA");
|
|
if (!RAEle) continue;
|
|
DecEle = prop->findElement("DEC");
|
|
if (!DecEle) continue;
|
|
break;
|
|
|
|
// Horizontal
|
|
case 1:
|
|
if (prop->perm == PP_RO) continue;
|
|
AzEle = prop->findElement("AZ");
|
|
if (!AzEle) continue;
|
|
AltEle = prop->findElement("ALT");
|
|
if (!AltEle) continue;
|
|
break;
|
|
}
|
|
|
|
onset = indidev->findProp("ON_COORD_SET");
|
|
if (!onset) continue;
|
|
|
|
onset->activateSwitch("SLEW");
|
|
|
|
indidev->stdDev->currentObject = oCurrent;
|
|
|
|
/* Send object name if available */
|
|
if (indidev->stdDev->currentObject)
|
|
{
|
|
nameEle = indidev->findElem("OBJECT_NAME");
|
|
if (nameEle && nameEle->pp->perm != PP_RO)
|
|
{
|
|
nameEle->write_w->setText(indidev->stdDev->currentObject->name());
|
|
nameEle->pp->newText();
|
|
}
|
|
}
|
|
|
|
switch (selectedCoord)
|
|
{
|
|
case 0:
|
|
if (indidev->stdDev->currentObject)
|
|
sp.set (indidev->stdDev->currentObject->ra(), indidev->stdDev->currentObject->dec());
|
|
else
|
|
sp.set (ks->map()->clickedPoint()->ra(), ks->map()->clickedPoint()->dec());
|
|
|
|
if (useJ2000)
|
|
sp.apparentCoord(ks->data()->ut().djd(), (long double) J2000);
|
|
|
|
RAEle->write_w->setText(TQString("%1:%2:%3").arg(sp.ra()->hour()).arg(sp.ra()->minute()).arg(sp.ra()->second()));
|
|
DecEle->write_w->setText(TQString("%1:%2:%3").arg(sp.dec()->degree()).arg(sp.dec()->arcmin()).arg(sp.dec()->arcsec()));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
if (indidev->stdDev->currentObject)
|
|
{
|
|
sp.setAz(*indidev->stdDev->currentObject->az());
|
|
sp.setAlt(*indidev->stdDev->currentObject->alt());
|
|
}
|
|
else
|
|
{
|
|
sp.setAz(*ks->map()->clickedPoint()->az());
|
|
sp.setAlt(*ks->map()->clickedPoint()->alt());
|
|
}
|
|
|
|
AzEle->write_w->setText(TQString("%1:%2:%3").arg(sp.az()->degree()).arg(sp.az()->arcmin()).arg(sp.az()->arcsec()));
|
|
AltEle->write_w->setText(TQString("%1:%2:%3").arg(sp.alt()->degree()).arg(sp.alt()->arcmin()).arg(sp.alt()->arcsec()));
|
|
|
|
break;
|
|
}
|
|
|
|
prop->newText();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// We didn't find any telescopes
|
|
KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));
|
|
|
|
}
|
|
|
|
//FIXME: This will open multiple Detail windows for each object;
|
|
//Should have one window whose target object changes with selection
|
|
void ObservingList::slotDetails() {
|
|
if ( oCurrent ) {
|
|
DetailDialog dd( oCurrent, ks->data()->lt(), ks->geo(), ks );
|
|
dd.exec();
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotAVT() {
|
|
if ( SelectedObjects.count() ) {
|
|
AltVsTime avt( ks );
|
|
for ( SkyObject *o = SelectedObjects.first(); o; o = SelectedObjects.next() ) {
|
|
avt.processObject( o );
|
|
}
|
|
|
|
avt.exec();
|
|
}
|
|
}
|
|
|
|
//FIXME: On close, we will need to close any open Details/AVT windows
|
|
void ObservingList::slotClose() {
|
|
//Save the current User log text
|
|
if ( oCurrent && ! ui->NotesEdit->text().isEmpty() && ui->NotesEdit->text()
|
|
!= i18n("Record here observation logs and/or data on %1.").arg( oCurrent->name()) ) {
|
|
oCurrent->saveUserLog( ui->NotesEdit->text() );
|
|
}
|
|
|
|
hide();
|
|
}
|
|
|
|
void ObservingList::saveCurrentUserLog() {
|
|
if ( ! ui->NotesEdit->text().isEmpty() &&
|
|
ui->NotesEdit->text() !=
|
|
i18n("Record here observation logs and/or data on %1.").arg( LogObject->translatedName() ) ) {
|
|
LogObject->saveUserLog( ui->NotesEdit->text() );
|
|
|
|
ui->NotesEdit->clear();
|
|
ui->NotesLabel->setText( i18n( "Observing notes for object:" ) );
|
|
LogObject = NULL;
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotOpenList() {
|
|
KURL fileURL = KFileDialog::getOpenURL( TQDir::homeDirPath(), "*.obslist|KStars Observing List (*.obslist)" );
|
|
TQFile f;
|
|
|
|
if ( fileURL.isValid() ) {
|
|
if ( ! fileURL.isLocalFile() ) {
|
|
//Save remote list to a temporary local file
|
|
KTempFile tmpfile;
|
|
tmpfile.setAutoDelete(true);
|
|
FileName = tmpfile.name();
|
|
if( TDEIO::NetAccess::download( fileURL, FileName, this ) )
|
|
f.setName( FileName );
|
|
|
|
} else {
|
|
FileName = fileURL.path();
|
|
f.setName( FileName );
|
|
}
|
|
|
|
if ( !f.open( IO_ReadOnly) ) {
|
|
TQString message = i18n( "Could not open file %1" ).arg( f.name() );
|
|
KMessageBox::sorry( 0, message, i18n( "Could Not Open File" ) );
|
|
return;
|
|
}
|
|
|
|
saveCurrentList();
|
|
//First line is the name of the list. The rest of the file should
|
|
//be object names, one per line.
|
|
TQTextStream istream(&f);
|
|
TQString line;
|
|
ListName = istream.readLine();
|
|
|
|
while ( ! istream.eof() ) {
|
|
line = istream.readLine();
|
|
//DEBUG
|
|
kdDebug() << line << endl;
|
|
|
|
//If the object is named "star", add it by coordinates
|
|
SkyObject *o = 0;
|
|
if ( line.startsWith( "star" ) ) {
|
|
TQStringList fields = TQStringList::split( " ", line );
|
|
//DEBUG
|
|
kdDebug() << fields << endl;
|
|
|
|
double ra = dms::fromString( fields[1], false ).Degrees(); //false = hours
|
|
double dc = dms::fromString( fields[2], true ).Degrees(); //true = degrees
|
|
|
|
//Identify the star with these coordinates
|
|
double rmax = 1.;
|
|
for ( uint i=0; i < ks->data()->starList.count(); ++i ) {
|
|
SkyObject *s = (SkyObject*)(ks->data()->starList.at(i));
|
|
double dra = fabs( ra - s->ra()->Degrees() );
|
|
double ddc = fabs( dc - s->dec()->Degrees() );
|
|
if ( dra < rmax && ddc < rmax ) {
|
|
o = s;
|
|
rmax = sqrt( dra*dra + ddc*ddc );
|
|
}
|
|
}
|
|
} else {
|
|
o = ks->data()->objectNamed( line );
|
|
}
|
|
|
|
if ( o ) slotAddObject( o );
|
|
}
|
|
|
|
//Newly-opened list should not trigger isModified flag
|
|
isModified = false;
|
|
|
|
f.close();
|
|
|
|
} else if ( fileURL.path() != "" ) {
|
|
TQString message = i18n( "The specified file is invalid. Try another file?" );
|
|
if ( KMessageBox::warningYesNo( this, message, i18n("Invalid File"), i18n("Try Another"), i18n("Do Not Try") ) == KMessageBox::Yes ) {
|
|
slotOpenList();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObservingList::saveCurrentList() {
|
|
//Before loading a new list, do we need to save the current one?
|
|
//Assume that if the list is empty, then there's no need to save
|
|
if ( obsList.count() ) {
|
|
if ( isModified ) {
|
|
TQString message = i18n( "Do you want to save the current list before opening a new list?" );
|
|
if ( KMessageBox::questionYesNo( this, message,
|
|
i18n( "Save Current List?" ), KStdGuiItem::save(), KStdGuiItem::discard() ) == KMessageBox::Yes )
|
|
slotSaveList();
|
|
}
|
|
|
|
//If we ever allow merging the loaded list with
|
|
//the existing one, that code would go here
|
|
obsList.clear();
|
|
ui->FullTable->clear();
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotSaveListAs() {
|
|
bool ok(false);
|
|
ListName = KInputDialog::getText( i18n( "Enter List Name" ),
|
|
i18n( "List name:" ), "", &ok );
|
|
|
|
if ( ok ) {
|
|
KURL fileURL = KFileDialog::getSaveURL( TQDir::homeDirPath(), "*.obslist|KStars Observing List (*.obslist)" );
|
|
|
|
if ( fileURL.isValid() )
|
|
FileName = fileURL.path();
|
|
|
|
slotSaveList();
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotSaveList() {
|
|
if ( ListName.isEmpty() || FileName.isEmpty() ) {
|
|
slotSaveListAs();
|
|
return;
|
|
}
|
|
|
|
TQFile f( FileName );
|
|
if ( !f.open( IO_WriteOnly) ) {
|
|
TQString message = i18n( "Could not open file %1. Try a different filename?" ).arg( f.name() );
|
|
|
|
if ( KMessageBox::warningYesNo( 0, message, i18n( "Could Not Open File" ), i18n("Try Different"), i18n("Do Not Try") ) == KMessageBox::Yes ) {
|
|
FileName == "";
|
|
slotSaveList();
|
|
}
|
|
return;
|
|
}
|
|
|
|
TQTextStream ostream(&f);
|
|
ostream << ListName << endl;
|
|
|
|
//Save objects to the list using their name. If it's a star with a genetive name
|
|
//(i.e., "sigma orionis"), save the name with ascii characters, not greek letters.
|
|
//If it's an unnamed star, save "star" and the star's coordinates.
|
|
for ( SkyObject* o = obsList.first(); o; o = obsList.next() ) {
|
|
if ( o->name() == "star" ) {
|
|
ostream << o->name() << " " << o->ra()->Hours() << " " << o->dec()->Degrees() << endl;
|
|
} else if ( o->type() == SkyObject::STAR ) {
|
|
StarObject *s = (StarObject*)o;
|
|
|
|
if ( s->name() == s->gname() ) {
|
|
ostream << s->gname( false ) << endl;
|
|
} else {
|
|
ostream << o->name() << endl;
|
|
}
|
|
} else {
|
|
ostream << o->name() << endl;
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
isModified = false;
|
|
}
|
|
|
|
void ObservingList::slotWizard() {
|
|
ObsListWizard wizard( ks );
|
|
if ( wizard.exec() == TQDialog::Accepted ) {
|
|
//Make sure current list is saved
|
|
saveCurrentList();
|
|
|
|
for ( SkyObject *o = wizard.obsList().first(); o; o = wizard.obsList().next() ) {
|
|
slotAddObject( o );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObservingList::slotToggleSize() {
|
|
if ( isLarge() ) {
|
|
ui->MiniButton->setPixmap( TDEGlobal::iconLoader()->loadIcon( "view-fullscreen", TDEIcon::Toolbar ) );
|
|
|
|
//switch widget stack to show TinyTable
|
|
ui->TableStack->raiseWidget( ui->TinyTable );
|
|
|
|
//Abbreviate text on each button
|
|
ui->CenterButton->setText( i18n( "First letter in 'Center'", "C" ) );
|
|
ui->ScopeButton->setText( i18n( "First letter in 'Scope'", "S" ) );
|
|
ui->DetailsButton->setText( i18n( "First letter in 'Details'", "D" ) );
|
|
ui->AVTButton->setText( i18n( "First letter in 'Alt vs Time'", "A" ) );
|
|
ui->RemoveButton->setText( i18n( "First letter in 'Remove'", "R" ) );
|
|
|
|
//Hide Observing notes
|
|
ui->NotesLabel->hide();
|
|
ui->NotesEdit->hide();
|
|
|
|
syncTableSelection( false ); //sync TinyTable with FullTable
|
|
adjustSize();
|
|
bIsLarge = false;
|
|
|
|
} else {
|
|
ui->MiniButton->setPixmap( TDEGlobal::iconLoader()->loadIcon( "view-restore", TDEIcon::Toolbar ) );
|
|
|
|
//switch widget stack to show FullTable
|
|
ui->TableStack->raiseWidget( ui->FullTable );
|
|
|
|
//Expand text on each button
|
|
ui->CenterButton->setText( i18n( "Center" ) );
|
|
ui->ScopeButton->setText( i18n( "Scope" ) );
|
|
ui->DetailsButton->setText( i18n( "Details" ) );
|
|
ui->AVTButton->setText( i18n( "Alt vs Time" ) );
|
|
ui->RemoveButton->setText( i18n( "Remove" ) );
|
|
|
|
//Show Observing notes
|
|
ui->NotesLabel->show();
|
|
ui->NotesEdit->show();
|
|
|
|
syncTableSelection( true ); //sync FullTable with TinyTable
|
|
adjustSize();
|
|
bIsLarge = true;
|
|
}
|
|
}
|
|
|
|
void ObservingList::syncTableSelection( bool syncFullTable ) {
|
|
if ( syncFullTable ) {
|
|
int i=0;
|
|
TQListViewItem *it = ui->FullTable->firstChild();
|
|
while ( it ) {
|
|
it->setSelected( ui->TinyTable->isSelected( i++ ) );
|
|
it->nextSibling();
|
|
}
|
|
} else {
|
|
int i=0;
|
|
TQListViewItem *it = ui->FullTable->firstChild();
|
|
while ( it ) {
|
|
ui->TinyTable->setSelected( i++, it->isSelected() );
|
|
it->nextSibling();
|
|
}
|
|
}
|
|
}
|
|
|
|
#include "observinglist.moc"
|