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.
1081 lines
34 KiB
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"
|