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/tools/wutdialog.cpp

445 lines
14 KiB

/***************************************************************************
wutdialog.cpp - Trinity Desktop Planetarium
-------------------
begin : Die Feb 25 2003
copyright : (C) 2003 by Thomas Kabelmann
email : tk78@gmx.de
***************************************************************************/
/***************************************************************************
* *
* 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 "wutdialog.h"
#include "wutdialogui.h"
#include "kstars.h"
#include "kstarsdata.h"
#include "skymap.h"
#include "ksnumbers.h"
#include "skyobjectname.h"
#include "objectnamelist.h"
#include "simclock.h"
#include "detaildialog.h"
#include "locationdialog.h"
#include "timedialog.h"
#include "kssun.h"
#include "ksmoon.h"
#include <kcombobox.h>
#include <klocale.h>
#include <klistbox.h>
#include <kpushbutton.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqframe.h>
#include <tqtabbar.h>
#include <tqtimer.h>
#include <tqcursor.h>
WUTDialog::WUTDialog(KStars *ks) :
KDialogBase (KDialogBase::Plain, i18n("What's up Tonight"), Close, Close, (TQWidget*)ks),
kstars(ks), EveningFlag(0) {
TQFrame *page = plainPage();
setMainWidget(page);
TQVBoxLayout *vlay = new TQVBoxLayout( page, 0, spacingHint() );
WUT = new WUTDialogUI( page );
vlay->addWidget( WUT );
objectList = &(ks->data()->ObjNames);
// objectList->setLanguage( Options::useLatinConstellNames() );
//initialize location and date to current KStars settings:
geo = kstars->geo();
T0 = kstars->data()->lt();
//If the Time is earlier than 6:00 am, assume the user wants the night of the previous date
if ( T0.time().hour() < 6 )
T0 = T0.addDays( -1 );
//Now, set time T0 to midnight (of the following day)
T0.setTime( TQTime( 0, 0, 0 ) );
T0 = T0.addDays( 1 );
UT0 = geo->LTtoUT( T0 );
//Set the Tomorrow date/time to Noon the following day
Tomorrow = T0.addSecs( 12*3600 );
TomorrowUT = geo->LTtoUT( Tomorrow );
//Set the Evening date/time to 6:00 pm
Evening = T0.addSecs( -6*3600 );
EveningUT = geo->LTtoUT( Evening );
TQString sGeo = geo->translatedName();
if ( ! geo->translatedProvince().isEmpty() ) sGeo += ", " + geo->translatedProvince();
sGeo += ", " + geo->translatedCountry();
WUT->LocationLabel->setText( i18n( "at %1" ).arg( sGeo ) );
WUT->DateLabel->setText( i18n( "The night of %1" ).arg( Evening.date().toString( Qt::LocalDate ) ) );
initCategories();
makeConnections();
TQTimer::singleShot(0, this, TQT_SLOT(init()));
}
WUTDialog::~WUTDialog(){
}
void WUTDialog::makeConnections() {
connect( WUT->DateButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotChangeDate() ) );
connect( WUT->LocationButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotChangeLocation() ) );
connect( WUT->CenterButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotCenter() ) );
connect( WUT->DetailButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotDetails() ) );
connect( WUT->CategoryListBox, TQT_SIGNAL( highlighted(int) ), TQT_SLOT( slotLoadList(int) ) );
connect( WUT->ObjectListBox, TQT_SIGNAL( selectionChanged(TQListBoxItem*) ),
TQT_SLOT( slotDisplayObject(TQListBoxItem*) ) );
connect( WUT->EveningMorningBox, TQT_SIGNAL( activated(int) ), TQT_SLOT( slotEveningMorning(int) ) );
}
void WUTDialog::initCategories() {
WUT->CategoryListBox->insertItem( i18n( "Planets" ) );
WUT->CategoryListBox->insertItem( i18n( "Comets" ) );
WUT->CategoryListBox->insertItem( i18n( "Asteroids" ) );
WUT->CategoryListBox->insertItem( i18n( "Stars" ) );
WUT->CategoryListBox->insertItem( i18n( "Constellations" ) );
WUT->CategoryListBox->insertItem( i18n( "Star Clusters" ) );
WUT->CategoryListBox->insertItem( i18n( "Nebulae" ) );
WUT->CategoryListBox->insertItem( i18n( "Galaxies" ) );
WUT->CategoryListBox->setSelected(0, true);
}
void WUTDialog::init() {
TQString sRise, sSet, sDuration;
// reset all lists
for (int i=0; i<NCATEGORY; i++) {
lists.visibleList[i].clear();
lists.initialized[i] = false;
}
// sun almanac information
KSSun *oSun = (KSSun*) kstars->data()->PCat->planetSun();
sunRiseTomorrow = oSun->riseSetTime( TomorrowUT, geo, true );
sunSetToday = oSun->riseSetTime( EveningUT, geo, false );
sunRiseToday = oSun->riseSetTime( EveningUT, geo, true );
//check to see if Sun is circumpolar
KSNumbers *num = new KSNumbers( UT0.djd() );
KSNumbers *oldNum = new KSNumbers( kstars->data()->ut().djd() );
dms LST = geo->GSTtoLST( T0.gst() );
oSun->updateCoords( num, true, geo->lat(), &LST );
if ( oSun->checkCircumpolar( geo->lat() ) ) {
if ( oSun->alt()->Degrees() > 0.0 ) {
sRise = i18n( "circumpolar" );
sSet = i18n( "circumpolar" );
sDuration = "00:00";
} else {
sRise = i18n( "does not rise" );
sSet = i18n( "does not rise" );
sDuration = "24:00";
}
} else {
//Round times to the nearest minute by adding 30 seconds to the time
sRise = sunRiseTomorrow.addSecs(30).toString("hh:mm");
sSet = sunSetToday.addSecs(30).toString("hh:mm");
float Dur = 24.0 + (float)sunRiseTomorrow.hour()
+ (float)sunRiseTomorrow.minute()/60.0
+ (float)sunRiseTomorrow.second()/3600.0
- (float)sunSetToday.hour()
- (float)sunSetToday.minute()/60.0
- (float)sunSetToday.second()/3600.0;
int hDur = int(Dur);
int mDur = int(60.0*(Dur - (float)hDur));
sDuration = TQString().sprintf( "%02d:%02d", hDur, mDur );
}
WUT->SunSetLabel->setText( i18n( "Sunset: %1" ).arg(sSet) );
WUT->SunRiseLabel->setText( i18n( "Sunrise: %1" ).arg(sRise) );
WUT->NightDurationLabel->setText( i18n( "Night duration: %1 hours" ).arg( sDuration ) );
// moon almanac information
KSMoon *oMoon = (KSMoon*) kstars->data()->Moon;
moonRise = oMoon->riseSetTime( UT0, geo, true );
moonSet = oMoon->riseSetTime( UT0, geo, false );
//check to see if Moon is circumpolar
oMoon->updateCoords( num, true, geo->lat(), &LST );
if ( oMoon->checkCircumpolar( geo->lat() ) ) {
if ( oMoon->alt()->Degrees() > 0.0 ) {
sRise = i18n( "circumpolar" );
sSet = i18n( "circumpolar" );
} else {
sRise = i18n( "does not rise" );
sSet = i18n( "does not rise" );
}
} else {
//Round times to the nearest minute by adding 30 seconds to the time
sRise = moonRise.addSecs(30).toString("hh:mm");
sSet = moonSet.addSecs(30).toString("hh:mm");
}
WUT->MoonRiseLabel->setText( i18n( "Moon rises at: %1" ).arg( sRise ) );
WUT->MoonSetLabel->setText( i18n( "Moon sets at: %1" ).arg( sSet ) );
oMoon->findPhase( oSun );
WUT->MoonIllumLabel->setText( oMoon->phaseName() + TQString( " (%1%)" ).arg(
int(100.0*oMoon->illum() ) ) );
//Restore Sun's and Moon's coordinates, and recompute Moon's original Phase
oMoon->updateCoords( oldNum, true, geo->lat(), kstars->LST() );
oSun->updateCoords( oldNum, true, geo->lat(), kstars->LST() );
oMoon->findPhase( oSun );
splitObjectList();
// load first list
slotLoadList(0);
delete num;
delete oldNum;
}
void WUTDialog::splitObjectList() {
// don't append objects which are never visible
for (SkyObjectName *oname=objectList->first(); oname; oname=objectList->next()) {
bool visible = true;
SkyObject *o = oname->skyObject();
// is object circumpolar or never visible
if (o->checkCircumpolar(geo->lat()) == true) {
// never visible
if (o->alt()->Degrees() <= 0) visible = false;
}
if (visible == true) appendToList(oname);
}
}
void WUTDialog::appendToList(SkyObjectName *o) {
// split into several lists
switch (o->skyObject()->type()) {
//case SkyObject::CATALOG_STAR : //Omitting CATALOG_STARs from list
case SkyObject::PLANET : lists.visibleList[0].append(o); break;
case SkyObject::COMET : lists.visibleList[1].append(o); break;
case SkyObject::ASTEROID : lists.visibleList[2].append(o); break;
case SkyObject::STAR : lists.visibleList[3].append(o); break;
case SkyObject::CONSTELLATION : lists.visibleList[4].append(o); break;
case SkyObject::OPEN_CLUSTER :
case SkyObject::GLOBULAR_CLUSTER : lists.visibleList[5].append(o); break;
case SkyObject::GASEOUS_NEBULA :
case SkyObject::PLANETARY_NEBULA :
case SkyObject::SUPERNOVA_REMNANT : lists.visibleList[6].append(o); break;
case SkyObject::GALAXY : lists.visibleList[7].append(o); break;
}
}
void WUTDialog::slotLoadList(int i) {
WUT->ObjectListBox->clear();
setCursor(TQCursor(TQt::WaitCursor));
TQPtrList <SkyObjectName> invisibleList;
for (SkyObjectName *oname=lists.visibleList[i].first(); oname; oname=lists.visibleList[i].next()) {
bool visible = true;
if (lists.initialized[i] == false) {
if (i == 0) { //planets, sun and moon
if (oname->skyObject()->name() == "Sun" ) visible = false; // don't ever display the sun
else visible = checkVisibility(oname);
}
if (visible == false) {
// collect all invisible objects
invisibleList.append(oname);
}
}
// append to listbox
if (visible == true) new SkyObjectNameListItem(WUT->ObjectListBox, oname);
}
// remove all invisible objects from list
if (invisibleList.isEmpty() == false) {
for (SkyObjectName *o=invisibleList.first(); o; o=invisibleList.next()) {
lists.visibleList[i].removeRef(o);
}
}
setCursor(TQCursor(TQt::ArrowCursor));
lists.initialized[i] = true;
// highlight first item
if ( WUT->ObjectListBox->count() ) {
WUT->ObjectListBox->setSelected(0, true);
WUT->ObjectListBox->setFocus();
}
}
bool WUTDialog::checkVisibility(SkyObjectName *oname) {
bool visible( false );
double minAlt = 6.0; //An object is considered 'visible' if it is above horizon during civil twilight.
//Initial values for T1, T2 assume all night option of EveningMorningBox
KStarsDateTime T1 = Evening;
T1.setTime( sunSetToday );
KStarsDateTime T2 = Tomorrow;
T2.setTime( sunRiseTomorrow );
//Check Evening/Morning only state:
if ( EveningFlag==0 ) { //Evening only
T2 = T0; //midnight
} else if ( EveningFlag==1 ) { //Morning only
T1 = T0; //midnight
}
for ( KStarsDateTime test = T1; test < T2; test = test.addSecs(3600) ) {
//Need LST of the test time, expressed as a dms object.
KStarsDateTime ut = geo->LTtoUT( test );
dms LST = geo->GSTtoLST( ut.gst() );
SkyPoint sp = oname->skyObject()->recomputeCoords( ut, geo );
//check altitude of object at this time.
sp.EquatorialToHorizontal( &LST, geo->lat() );
if ( sp.alt()->Degrees() > minAlt ) {
visible = true;
break;
}
}
return visible;
}
void WUTDialog::slotDisplayObject(TQListBoxItem *item) {
TQTime tRise, tSet, tTransit;
TQString sRise, sTransit, sSet;
if ( item==0 ) { //no object selected
WUT->ObjectBox->setTitle( i18n( "No Object Selected" ) );
sRise = "--:--";
sTransit = "--:--";
sSet = "--:--";
WUT->DetailButton->setEnabled( false );
} else {
SkyObject *o = ((SkyObjectNameListItem*)item)->objName()->skyObject();
WUT->ObjectBox->setTitle( o->name() );
if ( o->checkCircumpolar( geo->lat() ) ) {
if ( o->alt()->Degrees() > 0.0 ) {
sRise = i18n( "circumpolar" );
sSet = i18n( "circumpolar" );
} else {
sRise = i18n( "does not rise" );
sSet = i18n( "does not rise" );
}
} else {
tRise = o->riseSetTime( T0, geo, true );
tSet = o->riseSetTime( T0, geo, false );
// if ( tSet < tRise )
// tSet = o->riseSetTime( JDTomorrow, geo, false );
sRise = TQString().sprintf( "%02d:%02d", tRise.hour(), tRise.minute() );
sSet = TQString().sprintf( "%02d:%02d", tSet.hour(), tSet.minute() );
}
tTransit = o->transitTime( T0, geo );
// if ( tTransit < tRise )
// tTransit = o->transitTime( JDTomorrow, geo );
sTransit = TQString().sprintf( "%02d:%02d", tTransit.hour(), tTransit.minute() );
WUT->DetailButton->setEnabled( true );
}
WUT->ObjectRiseLabel->setText( i18n( "Rises at: %1" ).arg( sRise ) );
WUT->ObjectTransitLabel->setText( i18n( "Transits at: %1" ).arg( sTransit ) );
WUT->ObjectSetLabel->setText( i18n( "Sets at: %1" ).arg( sSet ) );
}
void WUTDialog::slotCenter() {
SkyObject *o = 0;
// get selected item
if (WUT->ObjectListBox->selectedItem() != 0) {
o = ((SkyObjectNameListItem*)WUT->ObjectListBox->selectedItem())->objName()->skyObject();
}
if (o != 0) {
kstars->map()->setFocusPoint( o );
kstars->map()->setFocusObject( o );
kstars->map()->setDestination( kstars->map()->focusPoint() );
}
}
void WUTDialog::slotDetails() {
SkyObject *o = 0;
// get selected item
if (WUT->ObjectListBox->selectedItem() != 0) {
o = ((SkyObjectNameListItem*)WUT->ObjectListBox->selectedItem())->objName()->skyObject();
}
if (o != 0) {
DetailDialog detail(o, kstars->data()->LTime, geo, kstars);
detail.exec();
}
}
void WUTDialog::slotChangeDate() {
TimeDialog td( T0, this );
if ( td.exec() == TQDialog::Accepted ) {
T0 = td.selectedDateTime();
//If the Time is earlier than 6:00 am, assume the user wants the night of the previous date
if ( T0.time().hour() < 6 )
T0 = T0.addDays( -1 );
//Now, set time T0 to midnight (of the following day)
T0.setTime( TQTime( 0, 0, 0 ) );
T0 = T0.addDays( 1 );
UT0 = geo->LTtoUT( T0 );
//Set the Tomorrow date/time to Noon the following day
Tomorrow = T0.addSecs( 12*3600 );
TomorrowUT = geo->LTtoUT( Tomorrow );
//Set the Evening date/time to 6:00 pm
Evening = T0.addSecs( -6*3600 );
EveningUT = geo->LTtoUT( Evening );
WUT->DateLabel->setText( i18n( "The night of %1" ).arg( Evening.date().toString() ) );
int i = WUT->CategoryListBox->currentItem();
init();
slotLoadList( i );
}
}
void WUTDialog::slotChangeLocation() {
LocationDialog ld( kstars );
if ( ld.exec() == TQDialog::Accepted ) {
GeoLocation *newGeo = ld.selectedCity();
if ( newGeo ) {
geo = newGeo;
UT0 = geo->LTtoUT( T0 );
TomorrowUT = geo->LTtoUT( Tomorrow );
EveningUT = geo->LTtoUT( Evening );
WUT->LocationLabel->setText( i18n( "at %1" ).arg( geo->fullName() ) );
int i = WUT->CategoryListBox->currentItem();
init();
slotLoadList( i );
}
}
}
void WUTDialog::slotEveningMorning( int index ) {
if ( EveningFlag != index ) {
EveningFlag = index;
// splitObjectList();
// slotLoadList( WUT->CategoryListBox->currentItem() );
int i = WUT->CategoryListBox->currentItem();
init();
slotLoadList( i );
}
}
#include "wutdialog.moc"