• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

detaildialog.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           detaildialog.cpp  -  description
00003                              -------------------
00004     begin                : Sun May 5 2002
00005     copyright            : (C) 2002 by Jason Harris and Jasem Mutlaq
00006     email                : kstars@30doradus.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <qstring.h>
00019 #include <qlayout.h> //still needed for secondary dialogs
00020 #include <qlineedit.h>
00021 #include <qimage.h>
00022 #include <qregexp.h>
00023 
00024 #include <kapplication.h>
00025 #include <kstandarddirs.h>
00026 #include <kmessagebox.h>
00027 #include <kactivelabel.h>
00028 #include <kpushbutton.h>
00029 #include <klistview.h>
00030 #include <klineedit.h>
00031 
00032 #include "detaildialog.h"
00033 //UI headers
00034 #include "details_data.h"
00035 #include "details_position.h"
00036 #include "details_links.h"
00037 #include "details_database.h"
00038 #include "details_log.h"
00039 
00040 #include "kstars.h"
00041 #include "kstarsdata.h"
00042 #include "kstarsdatetime.h"
00043 #include "geolocation.h"
00044 #include "ksutils.h"
00045 #include "skymap.h"
00046 #include "skyobject.h"
00047 #include "starobject.h"
00048 #include "deepskyobject.h"
00049 #include "ksplanetbase.h"
00050 #include "ksmoon.h"
00051 #include "thumbnailpicker.h"
00052 
00053 #include "indielement.h"
00054 #include "indiproperty.h"
00055 #include "indidevice.h"
00056 #include "indimenu.h"
00057 #include "devicemanager.h"
00058 #include "indistd.h"
00059 
00060 LogEdit::LogEdit( QWidget *parent, const char *name ) : KTextEdit( parent, name ) 
00061 {
00062     setFrameStyle( QFrame::StyledPanel );
00063     setFrameShadow( QFrame::Plain );
00064     setLineWidth( 4 );
00065 }
00066 
00067 void LogEdit::focusOutEvent( QFocusEvent *e ) {
00068     emit focusOut();
00069     QWidget::focusOutEvent(e);
00070 }
00071 
00072 ClickLabel::ClickLabel( QWidget *parent, const char *name ) : QLabel( parent, name ) 
00073 {}
00074 
00075 DetailDialog::DetailDialog(SkyObject *o, const KStarsDateTime &ut, GeoLocation *geo, 
00076         QWidget *parent, const char *name ) : 
00077         KDialogBase( KDialogBase::Tabbed, i18n( "Object Details" ), Close, Close, parent, name ) ,
00078         selectedObject(o), ksw((KStars*)parent), Data(0), Pos(0), Links(0), Adv(0), Log(0)
00079 {
00080     //Modify color palette
00081     setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Base ) );
00082     setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Text ) );
00083 
00084     //Create thumbnail image
00085     Thumbnail = new QPixmap( 200, 200 );
00086 
00087     createGeneralTab();
00088     createPositionTab( ut, geo );
00089     createLinksTab();
00090     createAdvancedTab();
00091     createLogTab();
00092 
00093     //Connections
00094     connect( Data->ObsListButton, SIGNAL( clicked() ), this, SLOT( addToObservingList() ) );
00095     connect( Data->CenterButton, SIGNAL( clicked() ), this, SLOT( centerMap() ) );
00096     connect( Data->ScopeButton, SIGNAL( clicked() ), this, SLOT( centerTelescope() ) );
00097     connect( Data->Image, SIGNAL( clicked() ), this, SLOT( updateThumbnail() ) );
00098 }
00099 
00100 void DetailDialog::createGeneralTab()
00101 {
00102     QFrame *DataTab = addPage(i18n("General"));
00103     Data = new DetailsDataUI( DataTab, "general_data_tab" );
00104  
00105     //Modify colors
00106     Data->Names->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00107     Data->Names->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::HighlightedText ) );
00108     Data->DataFrame->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00109     Data->Type->setPalette( palette() );
00110     Data->Constellation->setPalette( palette() );
00111     Data->Mag->setPalette( palette() );
00112     Data->Distance->setPalette( palette() );
00113     Data->AngSize->setPalette( palette() );
00114     Data->InLabel->setPalette( palette() );
00115     Data->MagLabel->setPalette( palette() );
00116     Data->DistanceLabel->setPalette( palette() );
00117     Data->AngSizeLabel->setPalette( palette() );
00118 
00119     //Show object thumbnail image
00120     showThumbnail();
00121 
00122     QVBoxLayout *vlay = new QVBoxLayout( DataTab, 0, 0 );
00123     vlay->addWidget( Data );
00124 
00125     //Fill in the data fields
00126     //Contents depend on type of object
00127     StarObject *s = 0L;
00128     DeepSkyObject *dso = 0L;
00129     KSPlanetBase *ps = 0L;
00130     QString pname(""), oname("");
00131 
00132     switch ( selectedObject->type() ) {
00133     case 0: //stars
00134         s = (StarObject *)selectedObject;
00135 
00136         Data->Names->setText( s->longname() );
00137         Data->Type->setText( s->sptype() + " " + i18n("star") );
00138         Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
00139                 KGlobal::locale()->formatNumber( s->mag(), 1 ) ) );  //show to tenths place
00140 
00141         //distance
00142         if ( s->distance() > 2000. || s->distance() < 0. )  // parallax < 0.5 mas 
00143             Data->Distance->setText( QString(i18n("larger than 2000 parsecs", "> 2000 pc") ) );
00144         else if ( s->distance() > 50.0 ) //show to nearest integer
00145             Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
00146                     QString::number( int( s->distance() + 0.5 ) ) ) );
00147         else if ( s->distance() > 10.0 ) //show to tenths place
00148             Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
00149                     KGlobal::locale()->formatNumber( s->distance(), 1 ) ) );
00150         else //show to hundredths place
00151             Data->Distance->setText( i18n( "number in parsecs", "%1 pc" ).arg(
00152                     KGlobal::locale()->formatNumber( s->distance(), 2 ) ) );
00153 
00154         //Note multiplicity/variablility in angular size label
00155         Data->AngSizeLabel->setText( "" );
00156         Data->AngSize->setText( "" );
00157         Data->AngSizeLabel->setFont( Data->AngSize->font() );
00158         if ( s->isMultiple() && s->isVariable() ) {
00159             Data->AngSizeLabel->setText( i18n( "the star is a multiple star", "multiple" ) + "," );
00160             Data->AngSize->setText( i18n( "the star is a variable star", "variable" ) );
00161         } else if ( s->isMultiple() ) 
00162             Data->AngSizeLabel->setText( i18n( "the star is a multiple star", "multiple" ) );
00163         else if ( s->isVariable() ) 
00164             Data->AngSizeLabel->setText( i18n( "the star is a variable star", "variable" ) );
00165         
00166         break; //end of stars case
00167 
00168     case 9:  //asteroids [fall through to planets]
00169     case 10: //comets [fall through to planets]
00170     case 2:  //planets (including comets and asteroids)
00171         ps = (KSPlanetBase *)selectedObject;
00172         
00173         Data->Names->setText( ps->longname() );
00174         //Type is "G5 star" for Sun
00175         if ( ps->name() == "Sun" )
00176             Data->Type->setText( i18n("G5 star") );
00177         else
00178             Data->Type->setText( ps->typeName() );
00179 
00180         Data->Constellation->setText( ps->constellation( ksw->data()->csegmentList, 
00181                                                                     ksw->data()->cnameList ) );
00182 
00183         //Magnitude: The moon displays illumination fraction instead
00184         if ( selectedObject->name() == "Moon" ) {
00185             Data->MagLabel->setText( i18n("Illumination:") );
00186             Data->Mag->setText( QString("%1 %").arg( int( ((KSMoon *)selectedObject)->illum()*100. ) ) );
00187         } else {
00188             Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
00189                     KGlobal::locale()->formatNumber( ps->mag(), 1 ) ) );  //show to tenths place
00190         }
00191 
00192         //Distance from Earth.  The moon requires a unit conversion
00193         if ( ps->name() == "Moon" ) {
00194             Data->Distance->setText( i18n("distance in kilometers", "%1 km").arg( 
00195                         KGlobal::locale()->formatNumber( ps->rearth()*AU_KM ) ) );
00196         } else {
00197             Data->Distance->setText( i18n("distance in Astronomical Units", "%1 AU").arg( 
00198                         KGlobal::locale()->formatNumber( ps->rearth() ) ) );
00199         }
00200 
00201         //Angular size; moon and sun in arcmin, others in arcsec
00202         if ( ps->angSize() ) {
00203             if ( ps->name() == "Sun" || ps->name() == "Moon" ) 
00204                 Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg( 
00205                             KGlobal::locale()->formatNumber( ps->angSize() ) ) );
00206             else
00207                 Data->AngSize->setText( i18n("angular size in arcseconds", "%1 arcsec").arg( 
00208                             KGlobal::locale()->formatNumber( ps->angSize()*60.0 ) ) );
00209         } else {
00210             Data->AngSize->setText( "--" );
00211         }
00212 
00213         break; //end of planets/comets/asteroids case
00214 
00215     default: //deep-sky objects
00216         dso = (DeepSkyObject *)selectedObject;
00217 
00218         //Show all names recorded for the object
00219         if ( ! dso->longname().isEmpty() && dso->longname() != dso->name() ) {
00220             pname = dso->translatedLongName();
00221             oname = dso->translatedName();
00222         } else {
00223             pname = dso->translatedName();
00224         }
00225 
00226         if ( ! dso->translatedName2().isEmpty() ) {
00227             if ( oname.isEmpty() ) oname = dso->translatedName2();
00228             else oname += ", " + dso->translatedName2();
00229         }
00230 
00231         if ( dso->ugc() != 0 ) {
00232             if ( ! oname.isEmpty() ) oname += ", ";
00233             oname += "UGC " + QString("%1").arg( dso->ugc() );
00234         }
00235         if ( dso->pgc() != 0 ) {
00236             if ( ! oname.isEmpty() ) oname += ", ";
00237             oname += "PGC " + QString("%1").arg( dso->pgc() );
00238         }
00239         
00240         if ( ! oname.isEmpty() ) pname += ", " + oname;
00241         Data->Names->setText( pname );
00242 
00243         Data->Type->setText( dso->typeName() );
00244 
00245         if ( dso->mag() > 90.0 )
00246             Data->Mag->setText( "--" );
00247         else
00248             Data->Mag->setText( i18n( "number in magnitudes", "%1 mag" ).arg(
00249                     KGlobal::locale()->formatNumber( dso->mag(), 1 ) ) );  //show to tenths place
00250 
00251         //No distances at this point...
00252         Data->Distance->setText( "--" );
00253 
00254         //Only show decimal place for small angular sizes
00255         if ( dso->a() > 10.0 ) 
00256             Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg( 
00257                     int( dso->a() ) ) );
00258         else if ( dso->a() ) 
00259             Data->AngSize->setText( i18n("angular size in arcminutes", "%1 arcmin").arg( 
00260                     KGlobal::locale()->formatNumber( dso->a(), 1 ) ) );
00261         else 
00262             Data->AngSize->setText( "--" );
00263         
00264         break;
00265     }
00266 
00267     //Common to all types:
00268     Data->Constellation->setText( selectedObject->constellation( ksw->data()->csegmentList, 
00269                         ksw->data()->cnameList ) );
00270 }
00271 
00272 void DetailDialog::createPositionTab( const KStarsDateTime &ut, GeoLocation *geo ) {
00273     QFrame *PosTab = addPage( i18n("Position") );
00274     Pos = new DetailsPositionUI( PosTab, "position_tab" );
00275 
00276     //Modify colors
00277     Pos->CoordTitle->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00278     Pos->CoordTitle->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::HighlightedText ) );
00279     Pos->CoordFrame->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00280     Pos->RSTTitle->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00281     Pos->RSTTitle->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::HighlightedText ) );
00282     Pos->RSTFrame->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Highlight ) );
00283     Pos->RA->setPalette( palette() );
00284     Pos->Dec->setPalette( palette() );
00285     Pos->Az->setPalette( palette() );
00286     Pos->Alt->setPalette( palette() );
00287     Pos->HA->setPalette( palette() );
00288     Pos->Airmass->setPalette( palette() );
00289     Pos->TimeRise->setPalette( palette() );
00290     Pos->TimeTransit->setPalette( palette() );
00291     Pos->TimeSet->setPalette( palette() );
00292     Pos->AzRise->setPalette( palette() );
00293     Pos->AltTransit->setPalette( palette() );
00294     Pos->AzSet->setPalette( palette() );
00295     Pos->RALabel->setPalette( palette() );
00296     Pos->DecLabel->setPalette( palette() );
00297     Pos->AzLabel->setPalette( palette() );
00298     Pos->AltLabel->setPalette( palette() );
00299     Pos->HALabel->setPalette( palette() );
00300     Pos->AirmassLabel->setPalette( palette() );
00301     Pos->TimeRiseLabel->setPalette( palette() );
00302     Pos->TimeTransitLabel->setPalette( palette() );
00303     Pos->TimeSetLabel->setPalette( palette() );
00304     Pos->AzRiseLabel->setPalette( palette() );
00305     Pos->AltTransitLabel->setPalette( palette() );
00306     Pos->AzSetLabel->setPalette( palette() );
00307 
00308     QVBoxLayout *vlay = new QVBoxLayout( PosTab, 0, 0 );
00309     vlay->addWidget( Pos );
00310     
00311     //Coordinates Section:
00312     //Don't use KLocale::formatNumber() for the epoch string,
00313     //because we don't want a thousands-place separator!
00314     QString sEpoch = QString::number( ut.epoch(), 'f', 1 );
00315     //Replace the decimal point with localized decimal symbol
00316     sEpoch.replace( ".", KGlobal::locale()->decimalSymbol() );
00317 
00318     Pos->RALabel->setText( i18n( "RA (%1):" ).arg( sEpoch ) );
00319     Pos->DecLabel->setText( i18n( "Dec (%1):" ).arg( sEpoch ) );
00320     Pos->RA->setText( selectedObject->ra()->toHMSString() );
00321     Pos->Dec->setText( selectedObject->dec()->toDMSString() );
00322     Pos->Az->setText( selectedObject->az()->toDMSString() );
00323     Pos->Alt->setText( selectedObject->alt()->toDMSString() );
00324 
00325     //Hour Angle can be negative, but dms HMS expressions cannot.
00326     //Here's a kludgy workaround:
00327     dms lst = geo->GSTtoLST( ut.gst() );
00328     dms ha( lst.Degrees() - selectedObject->ra()->Degrees() );
00329     QChar sgn('+');
00330     if ( ha.Hours() > 12.0 ) {
00331         ha.setH( 24.0 - ha.Hours() );
00332         sgn = '-';
00333     }
00334     Pos->HA->setText( QString("%1%2").arg(sgn).arg( ha.toHMSString() ) );
00335 
00336     //Airmass is approximated as the secant of the zenith distance,
00337     //equivalent to 1./sin(Alt).  Beware of Inf at Alt=0!
00338     if ( selectedObject->alt()->Degrees() > 0.0 ) 
00339         Pos->Airmass->setText( KGlobal::locale()->formatNumber( 
00340                 1./sin( selectedObject->alt()->radians() ), 2 ) );
00341     else 
00342         Pos->Airmass->setText( "--" );
00343 
00344     //Rise/Set/Transit Section:
00345 
00346     //Prepare time/position variables
00347     QTime rt = selectedObject->riseSetTime( ut, geo, true ); //true = use rise time
00348     dms raz = selectedObject->riseSetTimeAz( ut, geo, true ); //true = use rise time
00349 
00350     //If transit time is before rise time, use transit time for tomorrow
00351     QTime tt = selectedObject->transitTime( ut, geo );
00352     dms talt = selectedObject->transitAltitude( ut, geo );
00353     if ( tt < rt ) {
00354         tt = selectedObject->transitTime( ut.addDays( 1 ), geo );
00355         talt = selectedObject->transitAltitude( ut.addDays( 1 ), geo );
00356     }
00357 
00358     //If set time is before rise time, use set time for tomorrow
00359     QTime st = selectedObject->riseSetTime(  ut, geo, false ); //false = use set time
00360     dms saz = selectedObject->riseSetTimeAz( ut, geo, false ); //false = use set time
00361     if ( st < rt ) {
00362         st = selectedObject->riseSetTime( ut.addDays( 1 ), geo, false ); //false = use set time
00363         saz = selectedObject->riseSetTimeAz( ut.addDays( 1 ), geo, false ); //false = use set time
00364     }
00365 
00366     if ( rt.isValid() ) {
00367         Pos->TimeRise->setText( QString().sprintf( "%02d:%02d", rt.hour(), rt.minute() ) );
00368         Pos->TimeSet->setText( QString().sprintf( "%02d:%02d", st.hour(), st.minute() ) );
00369         Pos->AzRise->setText( raz.toDMSString() );
00370         Pos->AzSet->setText( saz.toDMSString() );
00371     } else {
00372         if ( selectedObject->alt()->Degrees() > 0.0 ) {
00373             Pos->TimeRise->setText( i18n( "Circumpolar" ) );
00374             Pos->TimeSet->setText( i18n( "Circumpolar" ) );
00375         } else {
00376             Pos->TimeRise->setText( i18n( "Never rises" ) );
00377             Pos->TimeSet->setText( i18n( "Never rises" ) );
00378         }
00379 
00380         Pos->AzRise->setText( i18n( "Not Applicable", "N/A" ) );
00381         Pos->AzSet->setText( i18n( "Not Applicable", "N/A" ) );
00382     }
00383 
00384     Pos->TimeTransit->setText( QString().sprintf( "%02d:%02d", tt.hour(), tt.minute() ) );
00385     Pos->AltTransit->setText( talt.toDMSString() );
00386 }
00387 
00388 void DetailDialog::createLinksTab()
00389 {
00390     // don't create a link tab for an unnamed star
00391     if (selectedObject->name() == QString("star"))
00392         return;
00393 
00394     QFrame *LinksTab = addPage( i18n( "Links" ) );
00395     Links = new DetailsLinksUI( LinksTab, "links_tab" );
00396 
00397     //Modify colors
00398     Links->InfoTitle->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Text ) );
00399     Links->InfoTitle->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Base ) );
00400     Links->ImagesTitle->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Text ) );
00401     Links->ImagesTitle->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Base ) );
00402 
00403     QPalette p = palette();
00404     p.setColor( QPalette::Active, QColorGroup::Dark, palette().color( QPalette::Active, QColorGroup::Highlight ) );
00405     Links->InfoList->setPalette( p );
00406     Links->ImagesList->setPalette( p );
00407 
00408     QVBoxLayout *vlay = new QVBoxLayout( LinksTab, 0, 0 );
00409     vlay->addWidget( Links );
00410 
00411     QStringList::Iterator itList = selectedObject->InfoList.begin();
00412     QStringList::Iterator itTitle = selectedObject->InfoTitle.begin();
00413     QStringList::Iterator itListEnd = selectedObject->InfoList.end();
00414 
00415     for ( ; itList != itListEnd; ++itList ) {
00416         Links->InfoList->insertItem(QString(*itTitle));
00417         itTitle++;
00418     }
00419 
00420     Links->InfoList->setSelected(0, true);
00421 
00422     itList  = selectedObject->ImageList.begin();
00423     itTitle = selectedObject->ImageTitle.begin();
00424     itListEnd  = selectedObject->ImageList.end();
00425 
00426     for ( ; itList != itListEnd; ++itList ) {
00427         Links->ImagesList->insertItem(QString(*itTitle));
00428         itTitle++;
00429     }
00430 
00431     if (! Links->InfoList->count() && ! Links->ImagesList->count()) {
00432         Links->EditLinkButton->setDisabled(true);
00433         Links->RemoveLinkButton->setDisabled(true);
00434     }
00435 
00436     // Signals/Slots
00437     connect( Links->ViewButton, SIGNAL(clicked()), this, SLOT( viewLink() ) );
00438     connect( Links->AddLinkButton, SIGNAL(clicked()), ksw->map(), SLOT( addLink() ) );
00439     connect( Links->EditLinkButton, SIGNAL(clicked()), this, SLOT( editLinkDialog() ) );
00440     connect( Links->RemoveLinkButton, SIGNAL(clicked()), this, SLOT( removeLinkDialog() ) );
00441     connect( Links->InfoList, SIGNAL(highlighted(int)), this, SLOT( unselectImagesList() ) );
00442     connect( Links->ImagesList, SIGNAL(highlighted(int)), this, SLOT( unselectInfoList() ) );
00443     connect( ksw->map(), SIGNAL(linkAdded()), this, SLOT( updateLists() ) );
00444 }
00445 
00446 void DetailDialog::createAdvancedTab()
00447 {
00448     // Don't create an adv tab for an unnamed star or if advinterface file failed loading
00449     // We also don't need adv dialog for solar system objects.
00450    if (selectedObject->name() == QString("star") || 
00451                 ksw->data()->ADVtreeList.isEmpty() || 
00452                 selectedObject->type() == SkyObject::PLANET || 
00453                 selectedObject->type() == SkyObject::COMET || 
00454                 selectedObject->type() == SkyObject::ASTEROID )
00455         return;
00456 
00457     QFrame *AdvancedTab = addPage(i18n("Advanced"));
00458     Adv = new DetailsDatabaseUI( AdvancedTab, "database_tab" );
00459 //  Adv->setPaletteBackgroundColor( QColor( "white" ) );
00460     QVBoxLayout *vlay = new QVBoxLayout( AdvancedTab, 0, 0 );
00461     vlay->addWidget( Adv );
00462 
00463     treeIt = new QPtrListIterator<ADVTreeData> (ksw->data()->ADVtreeList);
00464     connect( Adv->ADVTree, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(viewADVData()));
00465 
00466     populateADVTree(NULL);
00467 }
00468 
00469 void DetailDialog::createLogTab()
00470 {
00471     //Don't create a a log tab for an unnamed star
00472     if (selectedObject->name() == QString("star"))
00473         return;
00474 
00475     // Log Tab
00476     QFrame *LogTab = addPage(i18n("Log"));
00477     Log = new DetailsLogUI( LogTab, "log_tab" );
00478 
00479     //Modify colors
00480     Log->LogTitle->setPaletteBackgroundColor( palette().color( QPalette::Active, QColorGroup::Text ) );
00481     Log->LogTitle->setPaletteForegroundColor( palette().color( QPalette::Active, QColorGroup::Base ) );
00482 
00483     QVBoxLayout *vlay = new QVBoxLayout( LogTab, 0, 0 );
00484     vlay->addWidget( Log );
00485 
00486     if ( selectedObject->userLog.isEmpty() )
00487         Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.").arg(selectedObject->translatedName()));
00488     else
00489         Log->UserLog->setText(selectedObject->userLog);
00490 
00491     //Automatically save the log contents when the widget loses focus
00492     connect( Log->UserLog, SIGNAL( focusOut() ), this, SLOT( saveLogData() ) );
00493 }
00494 
00495 
00496 void DetailDialog::unselectInfoList()
00497 {
00498     Links->InfoList->setSelected( Links->InfoList->currentItem(), false );
00499 }
00500 
00501 void DetailDialog::unselectImagesList()
00502 {
00503     Links->ImagesList->setSelected( Links->ImagesList->currentItem(), false );
00504 }
00505 
00506 void DetailDialog::viewLink()
00507 {
00508     QString URL;
00509 
00510     if ( Links->InfoList->currentItem() != -1 && 
00511             Links->InfoList->isSelected( Links->InfoList->currentItem() ) )
00512         URL = QString( *selectedObject->InfoList.at( Links->InfoList->currentItem() ) );
00513     else if ( Links->ImagesList->currentItem() != -1 )
00514         URL = QString( *selectedObject->ImageList.at( Links->ImagesList->currentItem() ) );
00515 
00516     if (!URL.isEmpty())
00517         kapp->invokeBrowser(URL);
00518 }
00519 
00520 void DetailDialog::updateLists()
00521 {
00522     Links->InfoList->clear();
00523     Links->ImagesList->clear();
00524     
00525     QStringList::Iterator itList = selectedObject->InfoList.begin();
00526     QStringList::Iterator itTitle = selectedObject->InfoTitle.begin();
00527     QStringList::Iterator itListEnd = selectedObject->InfoList.end();
00528     
00529     for ( ; itList != itListEnd; ++itList ) {
00530         Links->InfoList->insertItem(QString(*itTitle));
00531         itTitle++;
00532     }
00533 
00534     Links->InfoList->setSelected(0, true);
00535     itList  = selectedObject->ImageList.begin();
00536     itTitle = selectedObject->ImageTitle.begin();
00537     itListEnd = selectedObject->ImageList.end();
00538 
00539     for ( ; itList != itListEnd; ++itList ) {
00540         Links->ImagesList->insertItem(QString(*itTitle));
00541         itTitle++;
00542     }
00543 }
00544 
00545 void DetailDialog::editLinkDialog()
00546 {
00547     int type;
00548     uint i;
00549     QString defaultURL , entry;
00550     QFile newFile;
00551     
00552     KDialogBase editDialog(KDialogBase::Plain, i18n("Edit Link"), Ok|Cancel, Ok , this, "editlink", false);
00553     QFrame *editFrame = editDialog.plainPage();
00554     
00555     editLinkURL = new QLabel(i18n("URL:"), editFrame);
00556     editLinkField = new QLineEdit(editFrame, "lineedit");
00557     editLinkField->setMinimumWidth(300);
00558     editLinkField->home(false);
00559     editLinkLayout = new QHBoxLayout(editFrame, 6, 6, "editlinklayout");
00560     editLinkLayout->addWidget(editLinkURL);
00561     editLinkLayout->addWidget(editLinkField);
00562     
00563     currentItemIndex = Links->InfoList->currentItem();
00564     
00565     if (currentItemIndex != -1 && Links->InfoList->isSelected(currentItemIndex))
00566     {
00567         defaultURL = *selectedObject->InfoList.at(currentItemIndex);
00568         editLinkField->setText(defaultURL);
00569         type = 1;
00570         currentItemTitle = Links->InfoList->currentText();
00571     }
00572     else if ( (currentItemIndex = Links->ImagesList->currentItem()) != -1)
00573     {
00574         defaultURL = *selectedObject->ImageList.at(currentItemIndex);
00575         editLinkField->setText(defaultURL);
00576         type = 0;
00577         currentItemTitle = Links->ImagesList->currentText();
00578     }
00579     else return;
00580 
00581     // If user presses cancel then return
00582     if (!editDialog.exec() == QDialog::Accepted)
00583         return;
00584     // if it wasn't edit, don't do anything
00585     if (!editLinkField->edited())
00586         return;
00587 
00588     // Save the URL of the current item
00589     currentItemURL =  editLinkField->text();
00590     entry = selectedObject->name() + ":" + currentItemTitle + ":" + currentItemURL;
00591 
00592     //FIXME: usage of verifyUserData() is pretty unclear
00593     //verifyUserData() returns false if currentItemTitle/currentItemURL 
00594     //are not found in the user's list already.  If they are, then that 
00595     //item is removed.
00596     switch (type)
00597     {
00598         case 0:
00599             if (!verifyUserData(type))
00600                 return;
00601                 break;
00602         case 1:
00603             if (!verifyUserData(type))
00604                 return;
00605                 break;
00606     }
00607 
00608     // Open a new file with the same name and copy all data along with changes
00609     newFile.setName(file.name());
00610     newFile.open(IO_WriteOnly);
00611 
00612     QTextStream newStream(&newFile);
00613 
00614     for (i=0; i<dataList.count(); i++)
00615     {
00616         newStream << dataList[i] << endl;
00617         continue;
00618     }
00619 
00620     if (type==0)
00621     {
00622         *selectedObject->ImageTitle.at(currentItemIndex) = currentItemTitle;
00623         *selectedObject->ImageList.at(currentItemIndex) = currentItemURL;
00624     }
00625     else
00626     {
00627         *selectedObject->InfoTitle.at(currentItemIndex) = currentItemTitle;
00628         *selectedObject->InfoList.at(currentItemIndex) = currentItemURL;
00629     }
00630 
00631     newStream << entry << endl;
00632 
00633     newFile.close();
00634     file.close();
00635     updateLists();
00636 }
00637 
00638 void DetailDialog::removeLinkDialog()
00639 {
00640     int type;
00641     uint i;
00642     QString defaultURL, entry;
00643     QFile newFile;
00644     
00645     currentItemIndex = Links->InfoList->currentItem();
00646     
00647     if (currentItemIndex != -1 && Links->InfoList->isSelected(currentItemIndex))
00648     {
00649         defaultURL = *selectedObject->InfoList.at(currentItemIndex);
00650         type = 1;
00651         currentItemTitle = Links->InfoList->currentText();
00652     }
00653     else
00654     {
00655         currentItemIndex = Links->ImagesList->currentItem();
00656         defaultURL = *selectedObject->ImageList.at(currentItemIndex);
00657         type = 0;
00658         currentItemTitle = Links->ImagesList->currentText();
00659     }
00660 
00661     if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 link?").arg(currentItemTitle), i18n("Delete Confirmation"),KStdGuiItem::del())!=KMessageBox::Continue)
00662         return;
00663 
00664     switch (type)
00665     {
00666         case 0:
00667             if (!verifyUserData(type))
00668                 return;
00669             selectedObject->ImageTitle.remove( selectedObject->ImageTitle.at(currentItemIndex));
00670             selectedObject->ImageList.remove( selectedObject->ImageList.at(currentItemIndex));
00671             break;
00672 
00673         case 1:
00674             if (!verifyUserData(type))
00675                 return;
00676             selectedObject->InfoTitle.remove(selectedObject->InfoTitle.at(currentItemIndex));
00677             selectedObject->InfoList.remove(selectedObject->InfoList.at(currentItemIndex));
00678             break;
00679     }
00680 
00681     // Open a new file with the same name and copy all data along with changes
00682     newFile.setName(file.name());
00683     newFile.open(IO_WriteOnly);
00684 
00685     QTextStream newStream(&newFile);
00686 
00687     for (i=0; i<dataList.count(); i++)
00688         newStream << dataList[i] << endl;
00689 
00690     newFile.close();
00691     file.close();
00692     updateLists();
00693 }
00694 
00695 bool DetailDialog::verifyUserData(int type)
00696 {
00697     QString line, name, sub, title;
00698     bool ObjectFound = false;
00699     uint i;
00700     
00701     switch (type)
00702     {
00703         case 0:
00704             if (!readUserFile(type))
00705                 return false;
00706             for (i=0; i<dataList.count(); i++)
00707             {
00708                 line = dataList[i];
00709                 name = line.mid( 0, line.find(':') );
00710                 sub = line.mid( line.find(':')+1 );
00711                 title = sub.mid( 0, sub.find(':') );
00712                 if (name == selectedObject->name() && title == currentItemTitle)
00713                 {
00714                     ObjectFound = true;
00715                     dataList.remove(dataList.at(i));
00716                     break;
00717                 }
00718             }
00719             break;
00720         case 1:
00721             if (!readUserFile(type))
00722                 return false;
00723             for (i=0; i<dataList.count(); i++)
00724             {
00725                 line = dataList[i];
00726                 name = line.mid( 0, line.find(':') );
00727                 sub = line.mid( line.find(':')+1 );
00728                 title = sub.mid( 0, sub.find(':') );
00729                 if (name == selectedObject->name() && title == currentItemTitle)
00730                 {
00731                     ObjectFound = true;
00732                     dataList.remove(dataList.at(i));
00733                     break;
00734                 }
00735             }
00736             break;
00737     }
00738     return ObjectFound;
00739 }
00740 
00741 bool DetailDialog::readUserFile(int type)//, int sourceFileType)
00742 {
00743     switch (type)
00744     {
00745         case 0:
00746             file.setName( locateLocal( "appdata", "image_url.dat" ) ); //determine filename
00747             if ( !file.open( IO_ReadOnly) )
00748             {
00749                 ksw->data()->initError("image_url.dat", false);
00750                 return false;
00751             }
00752             break;
00753 
00754         case 1:
00755             file.setName( locateLocal( "appdata", "info_url.dat" ) );  //determine filename
00756             if ( !file.open( IO_ReadOnly) )
00757             {
00758                 ksw->data()->initError("info_url.dat", false);
00759                 return false;
00760             }
00761             break;
00762     }
00763 
00764     // Must reset file
00765     file.reset();
00766     QTextStream stream(&file);
00767 
00768     dataList.clear();
00769     
00770     // read all data into memory
00771     while (!stream.eof())
00772         dataList.append(stream.readLine());
00773 
00774     return true;
00775 }
00776 
00777 void DetailDialog::populateADVTree(QListViewItem *parent)
00778 {
00779     // list done
00780     if (!treeIt->current())
00781         return;
00782 
00783     // if relative top level [KSLABEL]
00784     if (treeIt->current()->Type == 0)
00785         forkTree(parent);
00786 
00787     while (treeIt->current())
00788     {
00789         if (treeIt->current()->Type == 0)
00790         {
00791             forkTree(parent);
00792             continue;
00793         }
00794         else if (treeIt->current()->Type == 1)
00795             break;
00796 
00797         if (parent)
00798             new QListViewItem( parent, treeIt->current()->Name);
00799         else
00800             new QListViewItem( Adv->ADVTree, treeIt->current()->Name);
00801 
00802         ++(*treeIt);
00803     }
00804 }
00805 
00806 void DetailDialog::forkTree(QListViewItem *parent)
00807 {
00808     QListViewItem *current = 0;
00809     if (parent)
00810         current = new QListViewItem(parent, treeIt->current()->Name);
00811     else
00812         current = new QListViewItem(Adv->ADVTree, treeIt->current()->Name);
00813 
00814     // we need to increment the iterator before and after populating the tree
00815     ++(*treeIt);
00816     populateADVTree(current);
00817     ++(*treeIt);
00818 }
00819 
00820 void  DetailDialog::viewADVData()
00821 {
00822     QString link;
00823     QListViewItem * current = Adv->ADVTree->currentItem();
00824 
00825     if (!current)  return;
00826 
00827     treeIt->toFirst();
00828     while (treeIt->current())
00829     {
00830         if (treeIt->current()->Name == current->text(0))
00831         {
00832             if (treeIt->current()->Type == 2)  break;
00833             else return;
00834         }
00835         ++(*treeIt);
00836     }
00837 
00838     link = treeIt->current()->Link;
00839     link = parseADVData(link);
00840     kapp->invokeBrowser(link);
00841 }
00842 
00843 QString DetailDialog::parseADVData(QString link)
00844 {
00845     QString subLink;
00846     int index;
00847     
00848     if ( (index = link.find("KSOBJ")) != -1)
00849     {
00850         link.remove(index, 5);
00851         link = link.insert(index, selectedObject->name());
00852     }
00853 
00854     if ( (index = link.find("KSRA")) != -1)
00855     {
00856         link.remove(index, 4);
00857         subLink = QString().sprintf("%02d%02d%02d", selectedObject->ra0()->hour(), selectedObject->ra0()->minute(), selectedObject->ra0()->second());
00858         subLink = subLink.insert(2, "%20");
00859         subLink = subLink.insert(7, "%20");
00860 
00861         link = link.insert(index, subLink);
00862     }
00863     if ( (index = link.find("KSDEC")) != -1)
00864     {
00865         link.remove(index, 5);
00866         if (selectedObject->dec()->degree() < 0)
00867         {
00868             subLink = QString().sprintf("%03d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
00869             subLink = subLink.insert(3, "%20");
00870             subLink = subLink.insert(8, "%20");
00871         }
00872         else
00873         {
00874             subLink = QString().sprintf("%02d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
00875             subLink = subLink.insert(0, "%2B");
00876             subLink = subLink.insert(5, "%20");
00877             subLink = subLink.insert(10, "%20");
00878         }
00879         link = link.insert(index, subLink);
00880     }
00881 
00882     return link;
00883 }
00884 
00885 void DetailDialog::saveLogData() {
00886   selectedObject->saveUserLog( Log->UserLog->text() );
00887 }
00888 
00889 void DetailDialog::addToObservingList() {
00890     ksw->observingList()->slotAddObject( selectedObject );
00891 }
00892 
00893 void DetailDialog::centerMap() {
00894     ksw->map()->setClickedObject( selectedObject );
00895     ksw->map()->slotCenter();
00896 }
00897 
00898 void DetailDialog::centerTelescope()
00899 {
00900 
00901   INDI_D *indidev(NULL);
00902   INDI_P *prop(NULL), *onset(NULL);
00903   INDI_E *RAEle(NULL), *DecEle(NULL), *AzEle(NULL), *AltEle(NULL), *ConnectEle(NULL), *nameEle(NULL);
00904   bool useJ2000( false);
00905   int selectedCoord(0);
00906   SkyPoint sp;
00907   
00908   // Find the first device with EQUATORIAL_EOD_COORD or EQUATORIAL_COORD and with SLEW element
00909   // i.e. the first telescope we find!
00910   
00911   INDIMenu *imenu = ksw->getINDIMenu();
00912 
00913   
00914   for (unsigned int i=0; i < imenu->mgr.count() ; i++)
00915   {
00916     for (unsigned int j=0; j < imenu->mgr.at(i)->indi_dev.count(); j++)
00917     {
00918        indidev = imenu->mgr.at(i)->indi_dev.at(j);
00919        indidev->stdDev->currentObject = NULL;
00920        prop = indidev->findProp("EQUATORIAL_EOD_COORD");
00921         if (prop == NULL)
00922     {
00923           prop = indidev->findProp("EQUATORIAL_COORD");
00924           if (prop == NULL)
00925                   {
00926                     prop = indidev->findProp("HORIZONTAL_COORD");
00927                     if (prop == NULL)
00928                 continue;
00929                     else
00930                         selectedCoord = 1;      /* Select horizontal */
00931                   }
00932           else
00933                 useJ2000 = true;
00934     }
00935 
00936        ConnectEle = indidev->findElem("CONNECT");
00937        if (!ConnectEle) continue;
00938        
00939        if (ConnectEle->state == PS_OFF)
00940        {
00941      KMessageBox::error(0, i18n("Telescope %1 is offline. Please connect and retry again.").arg(indidev->label));
00942      return;
00943        }
00944 
00945         switch (selectedCoord)
00946         {
00947           // Equatorial
00948           case 0:
00949            if (prop->perm == PP_RO) continue;
00950            RAEle  = prop->findElement("RA");
00951            if (!RAEle) continue;
00952        DecEle = prop->findElement("DEC");
00953        if (!DecEle) continue;
00954            break;
00955 
00956          // Horizontal
00957          case 1:
00958           if (prop->perm == PP_RO) continue;
00959           AzEle = prop->findElement("AZ");
00960           if (!AzEle) continue;
00961           AltEle = prop->findElement("ALT");
00962           if (!AltEle) continue;
00963           break;
00964         }
00965    
00966         onset = indidev->findProp("ON_COORD_SET");
00967         if (!onset) continue;
00968        
00969         onset->activateSwitch("SLEW");
00970 
00971         indidev->stdDev->currentObject = selectedObject;
00972 
00973       /* Send object name if available */
00974       if (indidev->stdDev->currentObject)
00975          {
00976              nameEle = indidev->findElem("OBJECT_NAME");
00977              if (nameEle && nameEle->pp->perm != PP_RO)
00978              {
00979                  nameEle->write_w->setText(indidev->stdDev->currentObject->name());
00980                  nameEle->pp->newText();
00981              }
00982           }
00983 
00984        switch (selectedCoord)
00985        {
00986          case 0:
00987             if (indidev->stdDev->currentObject)
00988         sp.set (indidev->stdDev->currentObject->ra(), indidev->stdDev->currentObject->dec());
00989             else
00990                 sp.set (ksw->map()->clickedPoint()->ra(), ksw->map()->clickedPoint()->dec());
00991 
00992          if (useJ2000)
00993         sp.apparentCoord(ksw->data()->ut().djd(), (long double) J2000);
00994 
00995            RAEle->write_w->setText(QString("%1:%2:%3").arg(sp.ra()->hour()).arg(sp.ra()->minute()).arg(sp.ra()->second()));
00996        DecEle->write_w->setText(QString("%1:%2:%3").arg(sp.dec()->degree()).arg(sp.dec()->arcmin()).arg(sp.dec()->arcsec()));
00997 
00998           break;
00999 
01000        case 1:
01001          if (indidev->stdDev->currentObject)
01002          {
01003            sp.setAz(*indidev->stdDev->currentObject->az());
01004            sp.setAlt(*indidev->stdDev->currentObject->alt());
01005          }
01006          else
01007          {
01008            sp.setAz(*ksw->map()->clickedPoint()->az());
01009            sp.setAlt(*ksw->map()->clickedPoint()->alt());
01010          }
01011 
01012           AzEle->write_w->setText(QString("%1:%2:%3").arg(sp.az()->degree()).arg(sp.az()->arcmin()).arg(sp.az()->arcsec()));
01013           AltEle->write_w->setText(QString("%1:%2:%3").arg(sp.alt()->degree()).arg(sp.alt()->arcmin()).arg(sp.alt()->arcsec()));
01014 
01015          break;
01016        }
01017 
01018        prop->newText();
01019        
01020        return;
01021     }
01022   }
01023        
01024   // We didn't find any telescopes
01025   KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));
01026     
01027 }
01028 
01029 void DetailDialog::showThumbnail() {
01030     //No image if object is a star
01031     if ( selectedObject->type() == SkyObject::STAR || 
01032             selectedObject->type() == SkyObject::CATALOG_STAR ) {
01033         Thumbnail->resize( Data->Image->width(), Data->Image->height() );
01034         Thumbnail->fill( Data->paletteBackgroundColor() );
01035         Data->Image->setPixmap( *Thumbnail );
01036         return;
01037     }
01038 
01039     //Try to load the object's image from disk
01040     //If no image found, load "no image" image
01041     //If that isn't found, make it blank.
01042     QFile file;
01043     QString fname = "thumb-" + selectedObject->name().lower().replace( QRegExp(" "), "" ) + ".png";
01044     if ( KSUtils::openDataFile( file, fname ) ) {
01045         file.close();
01046         Thumbnail->load( file.name(), "PNG" );
01047     } else if ( KSUtils::openDataFile( file, "noimage.png" ) ) {
01048         file.close();
01049         Thumbnail->load( file.name(), "PNG" );
01050     } else {
01051         Thumbnail->resize( Data->Image->width(), Data->Image->height() );
01052         Thumbnail->fill( Data->paletteBackgroundColor() );
01053     }
01054 
01055     Data->Image->setPixmap( *Thumbnail );
01056 }
01057 
01058 void DetailDialog::updateThumbnail() {
01059     ThumbnailPicker tp( selectedObject, *Thumbnail, this, "thumbnaileditor" );
01060     
01061     if ( tp.exec() == QDialog::Accepted ) {
01062         QString fname = locateLocal( "appdata", "thumb-" 
01063                 + selectedObject->name().lower().replace( QRegExp(" "), "" ) + ".png" );
01064 
01065         Data->Image->setPixmap( *(tp.image()) );
01066 
01067         //If a real image was set, save it.
01068         //If the image was unset, delete the old image on disk.
01069         if ( tp.imageFound() ) {
01070             Data->Image->pixmap()->save( fname, "PNG" );
01071             *Thumbnail = *(Data->Image->pixmap());
01072         } else {
01073             QFile f;
01074             f.setName( fname );
01075             f.remove();
01076         }
01077     }
01078 }
01079 
01080 #include "detaildialog.moc"

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal