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.
tdeedu/kstars/kstars/detaildialog.cpp

1081 lines
34 KiB

/***************************************************************************
detaildialog.cpp - description
-------------------
begin : Sun May 5 2002
copyright : (C) 2002 by Jason Harris and Jasem Mutlaq
email : kstars@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 <tqstring.h>
#include <tqlayout.h> //still needed for secondary dialogs
#include <tqlineedit.h>
#include <tqimage.h>
#include <tqregexp.h>
#include <tdeapplication.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>
#include <kactivelabel.h>
#include <kpushbutton.h>
#include <tdelistview.h>
#include <klineedit.h>
#include "detaildialog.h"
//UI headers
#include "details_data.h"
#include "details_position.h"
#include "details_links.h"
#include "details_database.h"
#include "details_log.h"
#include "kstars.h"
#include "kstarsdata.h"
#include "kstarsdatetime.h"
#include "geolocation.h"
#include "ksutils.h"
#include "skymap.h"
#include "skyobject.h"
#include "starobject.h"
#include "deepskyobject.h"
#include "ksplanetbase.h"
#include "ksmoon.h"
#include "thumbnailpicker.h"
#include "indielement.h"
#include "indiproperty.h"
#include "indidevice.h"
#include "indimenu.h"
#include "devicemanager.h"
#include "indistd.h"
LogEdit::LogEdit( TQWidget *parent, const char *name ) : KTextEdit( parent, name )
{
setFrameStyle( TQFrame::StyledPanel );
setFrameShadow( TQFrame::Plain );
setLineWidth( 4 );
}
void LogEdit::focusOutEvent( TQFocusEvent *e ) {
emit focusOut();
TQWidget::focusOutEvent(e);
}
ClickLabel::ClickLabel( TQWidget *parent, const char *name ) : TQLabel( parent, name )
{}
DetailDialog::DetailDialog(SkyObject *o, const KStarsDateTime &ut, GeoLocation *geo,
TQWidget *parent, const char *name ) :
KDialogBase( KDialogBase::Tabbed, i18n( "Object Details" ), Close, Close, parent, name ) ,
selectedObject(o), ksw((KStars*)parent), Data(0), Pos(0), Links(0), Adv(0), Log(0)
{
//Modify color palette
setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Base ) );
setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Text ) );
//Create thumbnail image
Thumbnail = new TQPixmap( 200, 200 );
createGeneralTab();
createPositionTab( ut, geo );
createLinksTab();
createAdvancedTab();
createLogTab();
//Connections
connect( Data->ObsListButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( addToObservingList() ) );
connect( Data->CenterButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( centerMap() ) );
connect( Data->ScopeButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( centerTelescope() ) );
connect( Data->Image, TQT_SIGNAL( clicked() ), this, TQT_SLOT( updateThumbnail() ) );
}
void DetailDialog::createGeneralTab()
{
TQFrame *DataTab = addPage(i18n("General"));
Data = new DetailsDataUI( DataTab, "general_data_tab" );
//Modify colors
Data->Names->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Data->Names->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::HighlightedText ) );
Data->DataFrame->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Data->Type->setPalette( palette() );
Data->Constellation->setPalette( palette() );
Data->Mag->setPalette( palette() );
Data->Distance->setPalette( palette() );
Data->AngSize->setPalette( palette() );
Data->InLabel->setPalette( palette() );
Data->MagLabel->setPalette( palette() );
Data->DistanceLabel->setPalette( palette() );
Data->AngSizeLabel->setPalette( palette() );
//Show object thumbnail image
showThumbnail();
TQVBoxLayout *vlay = new TQVBoxLayout( DataTab, 0, 0 );
vlay->addWidget( Data );
//Fill in the data fields
//Contents depend on type of object
StarObject *s = 0L;
DeepSkyObject *dso = 0L;
KSPlanetBase *ps = 0L;
TQString pname(""), oname("");
switch ( selectedObject->type() ) {
case 0: //stars
s = (StarObject *)selectedObject;
Data->Names->setText( s->longname() );
Data->Type->setText( s->sptype() + " " + i18n("star") );
Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
TDEGlobal::locale()->formatNumber( s->mag(), 1 ) ) ); //show to tenths place
//distance
if ( s->distance() > 2000. || s->distance() < 0. ) // parallax < 0.5 mas
Data->Distance->setText( TQString(i18n("larger than 2000 parsecs", "> 2000 pc") ) );
else if ( s->distance() > 50.0 ) //show to nearest integer
Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
TQString::number( int( s->distance() + 0.5 ) ) ) );
else if ( s->distance() > 10.0 ) //show to tenths place
Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
TDEGlobal::locale()->formatNumber( s->distance(), 1 ) ) );
else //show to hundredths place
Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
TDEGlobal::locale()->formatNumber( s->distance(), 2 ) ) );
//Note multiplicity/variablility in angular size label
Data->AngSizeLabel->setText( "" );
Data->AngSize->setText( "" );
Data->AngSizeLabel->setFont( Data->AngSize->font() );
if ( s->isMultiple() && s->isVariable() ) {
Data->AngSizeLabel->setText( i18n( "the star is a multiple star", "multiple" ) + "," );
Data->AngSize->setText( i18n( "the star is a variable star", "variable" ) );
} else if ( s->isMultiple() )
Data->AngSizeLabel->setText( i18n( "the star is a multiple star", "multiple" ) );
else if ( s->isVariable() )
Data->AngSizeLabel->setText( i18n( "the star is a variable star", "variable" ) );
break; //end of stars case
case 9: //asteroids [fall through to planets]
case 10: //comets [fall through to planets]
case 2: //planets (including comets and asteroids)
ps = (KSPlanetBase *)selectedObject;
Data->Names->setText( ps->longname() );
//Type is "G5 star" for Sun
if ( ps->name() == "Sun" )
Data->Type->setText( i18n("G5 star") );
else
Data->Type->setText( ps->typeName() );
Data->Constellation->setText( ps->constellation( ksw->data()->csegmentList,
ksw->data()->cnameList ) );
//Magnitude: The moon displays illumination fraction instead
if ( selectedObject->name() == "Moon" ) {
Data->MagLabel->setText( i18n("Illumination:") );
Data->Mag->setText( TQString("%1 %").arg( int( ((KSMoon *)selectedObject)->illum()*100. ) ) );
} else {
Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
TDEGlobal::locale()->formatNumber( ps->mag(), 1 ) ) ); //show to tenths place
}
//Distance from Earth. The moon requires a unit conversion
if ( ps->name() == "Moon" ) {
Data->Distance->setText( i18n("distance in kilometers", "%1 km").arg(
TDEGlobal::locale()->formatNumber( ps->rearth()*AU_KM ) ) );
} else {
Data->Distance->setText( i18n("distance in Astronomical Units", "%1 AU").arg(
TDEGlobal::locale()->formatNumber( ps->rearth() ) ) );
}
//Angular size; moon and sun in arcmin, others in arcsec
if ( ps->angSize() ) {
if ( ps->name() == "Sun" || ps->name() == "Moon" )
Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg(
TDEGlobal::locale()->formatNumber( ps->angSize() ) ) );
else
Data->AngSize->setText( i18n("angular size in arcseconds", "%1 arcsec").arg(
TDEGlobal::locale()->formatNumber( ps->angSize()*60.0 ) ) );
} else {
Data->AngSize->setText( "--" );
}
break; //end of planets/comets/asteroids case
default: //deep-sky objects
dso = (DeepSkyObject *)selectedObject;
//Show all names recorded for the object
if ( ! dso->longname().isEmpty() && dso->longname() != dso->name() ) {
pname = dso->translatedLongName();
oname = dso->translatedName();
} else {
pname = dso->translatedName();
}
if ( ! dso->translatedName2().isEmpty() ) {
if ( oname.isEmpty() ) oname = dso->translatedName2();
else oname += ", " + dso->translatedName2();
}
if ( dso->ugc() != 0 ) {
if ( ! oname.isEmpty() ) oname += ", ";
oname += "UGC " + TQString("%1").arg( dso->ugc() );
}
if ( dso->pgc() != 0 ) {
if ( ! oname.isEmpty() ) oname += ", ";
oname += "PGC " + TQString("%1").arg( dso->pgc() );
}
if ( ! oname.isEmpty() ) pname += ", " + oname;
Data->Names->setText( pname );
Data->Type->setText( dso->typeName() );
if ( dso->mag() > 90.0 )
Data->Mag->setText( "--" );
else
Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
TDEGlobal::locale()->formatNumber( dso->mag(), 1 ) ) ); //show to tenths place
//No distances at this point...
Data->Distance->setText( "--" );
//Only show decimal place for small angular sizes
if ( dso->a() > 10.0 )
Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg(
int( dso->a() ) ) );
else if ( dso->a() )
Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg(
TDEGlobal::locale()->formatNumber( dso->a(), 1 ) ) );
else
Data->AngSize->setText( "--" );
break;
}
//Common to all types:
Data->Constellation->setText( selectedObject->constellation( ksw->data()->csegmentList,
ksw->data()->cnameList ) );
}
void DetailDialog::createPositionTab( const KStarsDateTime &ut, GeoLocation *geo ) {
TQFrame *PosTab = addPage( i18n("Position") );
Pos = new DetailsPositionUI( PosTab, "position_tab" );
//Modify colors
Pos->CoordTitle->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Pos->CoordTitle->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::HighlightedText ) );
Pos->CoordFrame->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Pos->RSTTitle->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Pos->RSTTitle->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::HighlightedText ) );
Pos->RSTFrame->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Pos->RA->setPalette( palette() );
Pos->Dec->setPalette( palette() );
Pos->Az->setPalette( palette() );
Pos->Alt->setPalette( palette() );
Pos->HA->setPalette( palette() );
Pos->Airmass->setPalette( palette() );
Pos->TimeRise->setPalette( palette() );
Pos->TimeTransit->setPalette( palette() );
Pos->TimeSet->setPalette( palette() );
Pos->AzRise->setPalette( palette() );
Pos->AltTransit->setPalette( palette() );
Pos->AzSet->setPalette( palette() );
Pos->RALabel->setPalette( palette() );
Pos->DecLabel->setPalette( palette() );
Pos->AzLabel->setPalette( palette() );
Pos->AltLabel->setPalette( palette() );
Pos->HALabel->setPalette( palette() );
Pos->AirmassLabel->setPalette( palette() );
Pos->TimeRiseLabel->setPalette( palette() );
Pos->TimeTransitLabel->setPalette( palette() );
Pos->TimeSetLabel->setPalette( palette() );
Pos->AzRiseLabel->setPalette( palette() );
Pos->AltTransitLabel->setPalette( palette() );
Pos->AzSetLabel->setPalette( palette() );
TQVBoxLayout *vlay = new TQVBoxLayout( PosTab, 0, 0 );
vlay->addWidget( Pos );
//Coordinates Section:
//Don't use TDELocale::formatNumber() for the epoch string,
//because we don't want a thousands-place separator!
TQString sEpoch = TQString::number( ut.epoch(), 'f', 1 );
//Replace the decimal point with localized decimal symbol
sEpoch.replace( ".", TDEGlobal::locale()->decimalSymbol() );
Pos->RALabel->setText( i18n( "RA (%1):" ).arg( sEpoch ) );
Pos->DecLabel->setText( i18n( "Dec (%1):" ).arg( sEpoch ) );
Pos->RA->setText( selectedObject->ra()->toHMSString() );
Pos->Dec->setText( selectedObject->dec()->toDMSString() );
Pos->Az->setText( selectedObject->az()->toDMSString() );
Pos->Alt->setText( selectedObject->alt()->toDMSString() );
//Hour Angle can be negative, but dms HMS expressions cannot.
//Here's a kludgy workaround:
dms lst = geo->GSTtoLST( ut.gst() );
dms ha( lst.Degrees() - selectedObject->ra()->Degrees() );
TQChar sgn('+');
if ( ha.Hours() > 12.0 ) {
ha.setH( 24.0 - ha.Hours() );
sgn = '-';
}
Pos->HA->setText( TQString("%1%2").arg(sgn).arg( ha.toHMSString() ) );
//Airmass is approximated as the secant of the zenith distance,
//equivalent to 1./sin(Alt). Beware of Inf at Alt=0!
if ( selectedObject->alt()->Degrees() > 0.0 )
Pos->Airmass->setText( TDEGlobal::locale()->formatNumber(
1./sin( selectedObject->alt()->radians() ), 2 ) );
else
Pos->Airmass->setText( "--" );
//Rise/Set/Transit Section:
//Prepare time/position variables
TQTime rt = selectedObject->riseSetTime( ut, geo, true ); //true = use rise time
dms raz = selectedObject->riseSetTimeAz( ut, geo, true ); //true = use rise time
//If transit time is before rise time, use transit time for tomorrow
TQTime tt = selectedObject->transitTime( ut, geo );
dms talt = selectedObject->transitAltitude( ut, geo );
if ( tt < rt ) {
tt = selectedObject->transitTime( ut.addDays( 1 ), geo );
talt = selectedObject->transitAltitude( ut.addDays( 1 ), geo );
}
//If set time is before rise time, use set time for tomorrow
TQTime st = selectedObject->riseSetTime( ut, geo, false ); //false = use set time
dms saz = selectedObject->riseSetTimeAz( ut, geo, false ); //false = use set time
if ( st < rt ) {
st = selectedObject->riseSetTime( ut.addDays( 1 ), geo, false ); //false = use set time
saz = selectedObject->riseSetTimeAz( ut.addDays( 1 ), geo, false ); //false = use set time
}
if ( rt.isValid() ) {
Pos->TimeRise->setText( TQString().sprintf( "%02d:%02d", rt.hour(), rt.minute() ) );
Pos->TimeSet->setText( TQString().sprintf( "%02d:%02d", st.hour(), st.minute() ) );
Pos->AzRise->setText( raz.toDMSString() );
Pos->AzSet->setText( saz.toDMSString() );
} else {
if ( selectedObject->alt()->Degrees() > 0.0 ) {
Pos->TimeRise->setText( i18n( "Circumpolar" ) );
Pos->TimeSet->setText( i18n( "Circumpolar" ) );
} else {
Pos->TimeRise->setText( i18n( "Never rises" ) );
Pos->TimeSet->setText( i18n( "Never rises" ) );
}
Pos->AzRise->setText( i18n( "Not Applicable", "N/A" ) );
Pos->AzSet->setText( i18n( "Not Applicable", "N/A" ) );
}
Pos->TimeTransit->setText( TQString().sprintf( "%02d:%02d", tt.hour(), tt.minute() ) );
Pos->AltTransit->setText( talt.toDMSString() );
}
void DetailDialog::createLinksTab()
{
// don't create a link tab for an unnamed star
if (selectedObject->name() == TQString("star"))
return;
TQFrame *LinksTab = addPage( i18n( "Links" ) );
Links = new DetailsLinksUI( LinksTab, "links_tab" );
//Modify colors
Links->InfoTitle->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Text ) );
Links->InfoTitle->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Base ) );
Links->ImagesTitle->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Text ) );
Links->ImagesTitle->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Base ) );
TQPalette p = palette();
p.setColor( TQPalette::Active, TQColorGroup::Dark, palette().color( TQPalette::Active, TQColorGroup::Highlight ) );
Links->InfoList->setPalette( p );
Links->ImagesList->setPalette( p );
TQVBoxLayout *vlay = new TQVBoxLayout( LinksTab, 0, 0 );
vlay->addWidget( Links );
TQStringList::Iterator itList = selectedObject->InfoList.begin();
TQStringList::Iterator itTitle = selectedObject->InfoTitle.begin();
TQStringList::Iterator itListEnd = selectedObject->InfoList.end();
for ( ; itList != itListEnd; ++itList ) {
Links->InfoList->insertItem(TQString(*itTitle));
itTitle++;
}
Links->InfoList->setSelected(0, true);
itList = selectedObject->ImageList.begin();
itTitle = selectedObject->ImageTitle.begin();
itListEnd = selectedObject->ImageList.end();
for ( ; itList != itListEnd; ++itList ) {
Links->ImagesList->insertItem(TQString(*itTitle));
itTitle++;
}
if (! Links->InfoList->count() && ! Links->ImagesList->count()) {
Links->EditLinkButton->setDisabled(true);
Links->RemoveLinkButton->setDisabled(true);
}
// Signals/Slots
connect( Links->ViewButton, TQT_SIGNAL(clicked()), this, TQT_SLOT( viewLink() ) );
connect( Links->AddLinkButton, TQT_SIGNAL(clicked()), ksw->map(), TQT_SLOT( addLink() ) );
connect( Links->EditLinkButton, TQT_SIGNAL(clicked()), this, TQT_SLOT( editLinkDialog() ) );
connect( Links->RemoveLinkButton, TQT_SIGNAL(clicked()), this, TQT_SLOT( removeLinkDialog() ) );
connect( Links->InfoList, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT( unselectImagesList() ) );
connect( Links->ImagesList, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT( unselectInfoList() ) );
connect( ksw->map(), TQT_SIGNAL(linkAdded()), this, TQT_SLOT( updateLists() ) );
}
void DetailDialog::createAdvancedTab()
{
// Don't create an adv tab for an unnamed star or if advinterface file failed loading
// We also don't need adv dialog for solar system objects.
if (selectedObject->name() == TQString("star") ||
ksw->data()->ADVtreeList.isEmpty() ||
selectedObject->type() == SkyObject::PLANET ||
selectedObject->type() == SkyObject::COMET ||
selectedObject->type() == SkyObject::ASTEROID )
return;
TQFrame *AdvancedTab = addPage(i18n("Advanced"));
Adv = new DetailsDatabaseUI( AdvancedTab, "database_tab" );
// Adv->setPaletteBackgroundColor( TQColor( "white" ) );
TQVBoxLayout *vlay = new TQVBoxLayout( AdvancedTab, 0, 0 );
vlay->addWidget( Adv );
treeIt = new TQPtrListIterator<ADVTreeData> (ksw->data()->ADVtreeList);
connect( Adv->ADVTree, TQT_SIGNAL(doubleClicked(TQListViewItem*)), this, TQT_SLOT(viewADVData()));
populateADVTree(NULL);
}
void DetailDialog::createLogTab()
{
//Don't create a a log tab for an unnamed star
if (selectedObject->name() == TQString("star"))
return;
// Log Tab
TQFrame *LogTab = addPage(i18n("Log"));
Log = new DetailsLogUI( LogTab, "log_tab" );
//Modify colors
Log->LogTitle->setPaletteBackgroundColor( palette().color( TQPalette::Active, TQColorGroup::Text ) );
Log->LogTitle->setPaletteForegroundColor( palette().color( TQPalette::Active, TQColorGroup::Base ) );
TQVBoxLayout *vlay = new TQVBoxLayout( LogTab, 0, 0 );
vlay->addWidget( Log );
if ( selectedObject->userLog.isEmpty() )
Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.").arg(selectedObject->translatedName()));
else
Log->UserLog->setText(selectedObject->userLog);
//Automatically save the log contents when the widget loses focus
connect( Log->UserLog, TQT_SIGNAL( focusOut() ), this, TQT_SLOT( saveLogData() ) );
}
void DetailDialog::unselectInfoList()
{
Links->InfoList->setSelected( Links->InfoList->currentItem(), false );
}
void DetailDialog::unselectImagesList()
{
Links->ImagesList->setSelected( Links->ImagesList->currentItem(), false );
}
void DetailDialog::viewLink()
{
TQString URL;
if ( Links->InfoList->currentItem() != -1 &&
Links->InfoList->isSelected( Links->InfoList->currentItem() ) )
URL = TQString( *selectedObject->InfoList.at( Links->InfoList->currentItem() ) );
else if ( Links->ImagesList->currentItem() != -1 )
URL = TQString( *selectedObject->ImageList.at( Links->ImagesList->currentItem() ) );
if (!URL.isEmpty())
kapp->invokeBrowser(URL);
}
void DetailDialog::updateLists()
{
Links->InfoList->clear();
Links->ImagesList->clear();
TQStringList::Iterator itList = selectedObject->InfoList.begin();
TQStringList::Iterator itTitle = selectedObject->InfoTitle.begin();
TQStringList::Iterator itListEnd = selectedObject->InfoList.end();
for ( ; itList != itListEnd; ++itList ) {
Links->InfoList->insertItem(TQString(*itTitle));
itTitle++;
}
Links->InfoList->setSelected(0, true);
itList = selectedObject->ImageList.begin();
itTitle = selectedObject->ImageTitle.begin();
itListEnd = selectedObject->ImageList.end();
for ( ; itList != itListEnd; ++itList ) {
Links->ImagesList->insertItem(TQString(*itTitle));
itTitle++;
}
}
void DetailDialog::editLinkDialog()
{
int type;
uint i;
TQString defaultURL , entry;
TQFile newFile;
KDialogBase editDialog(KDialogBase::Plain, i18n("Edit Link"), Ok|Cancel, Ok , this, "editlink", false);
TQFrame *editFrame = editDialog.plainPage();
editLinkURL = new TQLabel(i18n("URL:"), editFrame);
editLinkField = new TQLineEdit(editFrame, "lineedit");
editLinkField->setMinimumWidth(300);
editLinkField->home(false);
editLinkLayout = new TQHBoxLayout(editFrame, 6, 6, "editlinklayout");
editLinkLayout->addWidget(editLinkURL);
editLinkLayout->addWidget(editLinkField);
currentItemIndex = Links->InfoList->currentItem();
if (currentItemIndex != -1 && Links->InfoList->isSelected(currentItemIndex))
{
defaultURL = *selectedObject->InfoList.at(currentItemIndex);
editLinkField->setText(defaultURL);
type = 1;
currentItemTitle = Links->InfoList->currentText();
}
else if ( (currentItemIndex = Links->ImagesList->currentItem()) != -1)
{
defaultURL = *selectedObject->ImageList.at(currentItemIndex);
editLinkField->setText(defaultURL);
type = 0;
currentItemTitle = Links->ImagesList->currentText();
}
else return;
// If user presses cancel then return
if (!editDialog.exec() == TQDialog::Accepted)
return;
// if it wasn't edit, don't do anything
if (!editLinkField->edited())
return;
// Save the URL of the current item
currentItemURL = editLinkField->text();
entry = selectedObject->name() + ":" + currentItemTitle + ":" + currentItemURL;
//FIXME: usage of verifyUserData() is pretty unclear
//verifyUserData() returns false if currentItemTitle/currentItemURL
//are not found in the user's list already. If they are, then that
//item is removed.
switch (type)
{
case 0:
if (!verifyUserData(type))
return;
break;
case 1:
if (!verifyUserData(type))
return;
break;
}
// Open a new file with the same name and copy all data along with changes
newFile.setName(file.name());
newFile.open(IO_WriteOnly);
TQTextStream newStream(&newFile);
for (i=0; i<dataList.count(); i++)
{
newStream << dataList[i] << endl;
continue;
}
if (type==0)
{
*selectedObject->ImageTitle.at(currentItemIndex) = currentItemTitle;
*selectedObject->ImageList.at(currentItemIndex) = currentItemURL;
}
else
{
*selectedObject->InfoTitle.at(currentItemIndex) = currentItemTitle;
*selectedObject->InfoList.at(currentItemIndex) = currentItemURL;
}
newStream << entry << endl;
newFile.close();
file.close();
updateLists();
}
void DetailDialog::removeLinkDialog()
{
int type;
uint i;
TQString defaultURL, entry;
TQFile newFile;
currentItemIndex = Links->InfoList->currentItem();
if (currentItemIndex != -1 && Links->InfoList->isSelected(currentItemIndex))
{
defaultURL = *selectedObject->InfoList.at(currentItemIndex);
type = 1;
currentItemTitle = Links->InfoList->currentText();
}
else
{
currentItemIndex = Links->ImagesList->currentItem();
defaultURL = *selectedObject->ImageList.at(currentItemIndex);
type = 0;
currentItemTitle = Links->ImagesList->currentText();
}
if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 link?").arg(currentItemTitle), i18n("Delete Confirmation"),KStdGuiItem::del())!=KMessageBox::Continue)
return;
switch (type)
{
case 0:
if (!verifyUserData(type))
return;
selectedObject->ImageTitle.remove( selectedObject->ImageTitle.at(currentItemIndex));
selectedObject->ImageList.remove( selectedObject->ImageList.at(currentItemIndex));
break;
case 1:
if (!verifyUserData(type))
return;
selectedObject->InfoTitle.remove(selectedObject->InfoTitle.at(currentItemIndex));
selectedObject->InfoList.remove(selectedObject->InfoList.at(currentItemIndex));
break;
}
// Open a new file with the same name and copy all data along with changes
newFile.setName(file.name());
newFile.open(IO_WriteOnly);
TQTextStream newStream(&newFile);
for (i=0; i<dataList.count(); i++)
newStream << dataList[i] << endl;
newFile.close();
file.close();
updateLists();
}
bool DetailDialog::verifyUserData(int type)
{
TQString line, name, sub, title;
bool ObjectFound = false;
uint i;
switch (type)
{
case 0:
if (!readUserFile(type))
return false;
for (i=0; i<dataList.count(); i++)
{
line = dataList[i];
name = line.mid( 0, line.find(':') );
sub = line.mid( line.find(':')+1 );
title = sub.mid( 0, sub.find(':') );
if (name == selectedObject->name() && title == currentItemTitle)
{
ObjectFound = true;
dataList.remove(dataList.at(i));
break;
}
}
break;
case 1:
if (!readUserFile(type))
return false;
for (i=0; i<dataList.count(); i++)
{
line = dataList[i];
name = line.mid( 0, line.find(':') );
sub = line.mid( line.find(':')+1 );
title = sub.mid( 0, sub.find(':') );
if (name == selectedObject->name() && title == currentItemTitle)
{
ObjectFound = true;
dataList.remove(dataList.at(i));
break;
}
}
break;
}
return ObjectFound;
}
bool DetailDialog::readUserFile(int type)//, int sourceFileType)
{
switch (type)
{
case 0:
file.setName( locateLocal( "appdata", "image_url.dat" ) ); //determine filename
if ( !file.open( IO_ReadOnly) )
{
ksw->data()->initError("image_url.dat", false);
return false;
}
break;
case 1:
file.setName( locateLocal( "appdata", "info_url.dat" ) ); //determine filename
if ( !file.open( IO_ReadOnly) )
{
ksw->data()->initError("info_url.dat", false);
return false;
}
break;
}
// Must reset file
file.reset();
TQTextStream stream(&file);
dataList.clear();
// read all data into memory
while (!stream.eof())
dataList.append(stream.readLine());
return true;
}
void DetailDialog::populateADVTree(TQListViewItem *parent)
{
// list done
if (!treeIt->current())
return;
// if relative top level [KSLABEL]
if (treeIt->current()->Type == 0)
forkTree(parent);
while (treeIt->current())
{
if (treeIt->current()->Type == 0)
{
forkTree(parent);
continue;
}
else if (treeIt->current()->Type == 1)
break;
if (parent)
new TQListViewItem( parent, treeIt->current()->Name);
else
new TQListViewItem( Adv->ADVTree, treeIt->current()->Name);
++(*treeIt);
}
}
void DetailDialog::forkTree(TQListViewItem *parent)
{
TQListViewItem *current = 0;
if (parent)
current = new TQListViewItem(parent, treeIt->current()->Name);
else
current = new TQListViewItem(Adv->ADVTree, treeIt->current()->Name);
// we need to increment the iterator before and after populating the tree
++(*treeIt);
populateADVTree(current);
++(*treeIt);
}
void DetailDialog::viewADVData()
{
TQString link;
TQListViewItem * current = Adv->ADVTree->currentItem();
if (!current) return;
treeIt->toFirst();
while (treeIt->current())
{
if (treeIt->current()->Name == current->text(0))
{
if (treeIt->current()->Type == 2) break;
else return;
}
++(*treeIt);
}
link = treeIt->current()->Link;
link = parseADVData(link);
kapp->invokeBrowser(link);
}
TQString DetailDialog::parseADVData(TQString link)
{
TQString subLink;
int index;
if ( (index = link.find("KSOBJ")) != -1)
{
link.remove(index, 5);
link = link.insert(index, selectedObject->name());
}
if ( (index = link.find("KSRA")) != -1)
{
link.remove(index, 4);
subLink = TQString().sprintf("%02d%02d%02d", selectedObject->ra0()->hour(), selectedObject->ra0()->minute(), selectedObject->ra0()->second());
subLink = subLink.insert(2, "%20");
subLink = subLink.insert(7, "%20");
link = link.insert(index, subLink);
}
if ( (index = link.find("KSDEC")) != -1)
{
link.remove(index, 5);
if (selectedObject->dec()->degree() < 0)
{
subLink = TQString().sprintf("%03d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
subLink = subLink.insert(3, "%20");
subLink = subLink.insert(8, "%20");
}
else
{
subLink = TQString().sprintf("%02d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
subLink = subLink.insert(0, "%2B");
subLink = subLink.insert(5, "%20");
subLink = subLink.insert(10, "%20");
}
link = link.insert(index, subLink);
}
return link;
}
void DetailDialog::saveLogData() {
selectedObject->saveUserLog( Log->UserLog->text() );
}
void DetailDialog::addToObservingList() {
ksw->observingList()->slotAddObject( selectedObject );
}
void DetailDialog::centerMap() {
ksw->map()->setClickedObject( selectedObject );
ksw->map()->slotCenter();
}
void DetailDialog::centerTelescope()
{
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 = ksw->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 = selectedObject;
/* 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 (ksw->map()->clickedPoint()->ra(), ksw->map()->clickedPoint()->dec());
if (useJ2000)
sp.apparentCoord(ksw->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(*ksw->map()->clickedPoint()->az());
sp.setAlt(*ksw->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."));
}
void DetailDialog::showThumbnail() {
//No image if object is a star
if ( selectedObject->type() == SkyObject::STAR ||
selectedObject->type() == SkyObject::CATALOG_STAR ) {
Thumbnail->resize( Data->Image->width(), Data->Image->height() );
Thumbnail->fill( Data->paletteBackgroundColor() );
Data->Image->setPixmap( *Thumbnail );
return;
}
//Try to load the object's image from disk
//If no image found, load "no image" image
//If that isn't found, make it blank.
TQFile file;
TQString fname = "thumb-" + selectedObject->name().lower().replace( TQRegExp(" "), "" ) + ".png";
if ( KSUtils::openDataFile( file, fname ) ) {
file.close();
Thumbnail->load( file.name(), "PNG" );
} else if ( KSUtils::openDataFile( file, "noimage.png" ) ) {
file.close();
Thumbnail->load( file.name(), "PNG" );
} else {
Thumbnail->resize( Data->Image->width(), Data->Image->height() );
Thumbnail->fill( Data->paletteBackgroundColor() );
}
Data->Image->setPixmap( *Thumbnail );
}
void DetailDialog::updateThumbnail() {
ThumbnailPicker tp( selectedObject, *Thumbnail, this, "thumbnaileditor" );
if ( tp.exec() == TQDialog::Accepted ) {
TQString fname = locateLocal( "appdata", "thumb-"
+ selectedObject->name().lower().replace( TQRegExp(" "), "" ) + ".png" );
Data->Image->setPixmap( *(tp.image()) );
//If a real image was set, save it.
//If the image was unset, delete the old image on disk.
if ( tp.imageFound() ) {
Data->Image->pixmap()->save( fname, "PNG" );
*Thumbnail = *(Data->Image->pixmap());
} else {
TQFile f;
f.setName( fname );
f.remove();
}
}
}
#include "detaildialog.moc"