File indexing completed on 2024-04-14 03:43:27

0001 /*
0002     SPDX-FileCopyrightText: 2003 Thomas Kabelmann <tk78@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "wutdialog.h"
0008 
0009 #include "kstars.h"
0010 #include "skymap.h"
0011 #include "dialogs/detaildialog.h"
0012 #include "dialogs/locationdialog.h"
0013 #include "dialogs/timedialog.h"
0014 #include "skyobjects/kssun.h"
0015 #include "skyobjects/ksmoon.h"
0016 #include "skycomponents/skymapcomposite.h"
0017 #include "tools/observinglist.h"
0018 #include "catalogsdb.h"
0019 #include "Options.h"
0020 
0021 WUTDialogUI::WUTDialogUI(QWidget *p) : QFrame(p)
0022 {
0023     setupUi(this);
0024 }
0025 
0026 WUTDialog::WUTDialog(QWidget *parent, bool _session, GeoLocation *_geo,
0027                      KStarsDateTime _lt)
0028     : QDialog(parent), session(_session), T0(_lt), geo(_geo)
0029 {
0030 #ifdef Q_OS_OSX
0031     setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
0032 #endif
0033     WUT = new WUTDialogUI(this);
0034 
0035     QVBoxLayout *mainLayout = new QVBoxLayout(this);
0036 
0037     mainLayout->addWidget(WUT);
0038 
0039     setWindowTitle(i18nc("@title:window", "What's up Tonight"));
0040 
0041     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
0042     mainLayout->addWidget(buttonBox);
0043     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0044 
0045     setModal(false);
0046 
0047     //If the Time is earlier than 6:00 am, assume the user wants the night of the previous date
0048     if (T0.time().hour() < 6)
0049         T0 = T0.addDays(-1);
0050 
0051     //Now, set time T0 to midnight (of the following day)
0052     T0.setTime(QTime(0, 0, 0));
0053     T0  = T0.addDays(1);
0054     UT0 = geo->LTtoUT(T0);
0055 
0056     //Set the Tomorrow date/time to Noon the following day
0057     Tomorrow   = T0.addSecs(12 * 3600);
0058     TomorrowUT = geo->LTtoUT(Tomorrow);
0059 
0060     //Set the Evening date/time to 6:00 pm
0061     Evening   = T0.addSecs(-6 * 3600);
0062     EveningUT = geo->LTtoUT(Evening);
0063 
0064     QString sGeo = geo->translatedName();
0065     if (!geo->translatedProvince().isEmpty())
0066         sGeo += ", " + geo->translatedProvince();
0067     sGeo += ", " + geo->translatedCountry();
0068     WUT->LocationLabel->setText(i18n("at %1", sGeo));
0069     WUT->DateLabel->setText(
0070         i18n("The night of %1", QLocale().toString(Evening.date(), QLocale::LongFormat)));
0071     m_Mag = 10.0;
0072     WUT->MagnitudeEdit->setValue(m_Mag);
0073     //WUT->MagnitudeEdit->setSliderEnabled( true );
0074     WUT->MagnitudeEdit->setSingleStep(0.100);
0075     initCategories();
0076 
0077     makeConnections();
0078 }
0079 
0080 void WUTDialog::makeConnections()
0081 {
0082     connect(WUT->DateButton, SIGNAL(clicked()), SLOT(slotChangeDate()));
0083     connect(WUT->LocationButton, SIGNAL(clicked()), SLOT(slotChangeLocation()));
0084     connect(WUT->CenterButton, SIGNAL(clicked()), SLOT(slotCenter()));
0085     connect(WUT->DetailButton, SIGNAL(clicked()), SLOT(slotDetails()));
0086     connect(WUT->ObslistButton, SIGNAL(clicked()), SLOT(slotObslist()));
0087     connect(WUT->CategoryListWidget, SIGNAL(currentTextChanged(QString)),
0088             SLOT(slotLoadList(QString)));
0089     connect(WUT->ObjectListWidget, SIGNAL(currentTextChanged(QString)),
0090             SLOT(slotDisplayObject(QString)));
0091     connect(WUT->EveningMorningBox, SIGNAL(activated(int)),
0092             SLOT(slotEveningMorning(int)));
0093     connect(WUT->MagnitudeEdit, SIGNAL(valueChanged(double)),
0094             SLOT(slotChangeMagnitude()));
0095 }
0096 
0097 void WUTDialog::initCategories()
0098 {
0099     m_Categories << i18n("Planets") << i18n("Stars") << i18n("Nebulae")
0100                  << i18n("Galaxies") << i18n("Star Clusters") << i18n("Constellations")
0101                  << i18n("Asteroids") << i18n("Comets");
0102 
0103     foreach (const QString &c, m_Categories)
0104         WUT->CategoryListWidget->addItem(c);
0105 
0106     WUT->CategoryListWidget->setCurrentRow(0);
0107 }
0108 
0109 void WUTDialog::init()
0110 {
0111     QString sRise, sSet, sDuration;
0112     float Dur;
0113     int hDur, mDur;
0114     KStarsData *data = KStarsData::Instance();
0115     // reset all lists
0116     foreach (const QString &c, m_Categories)
0117     {
0118         if (m_VisibleList.contains(c))
0119             visibleObjects(c).clear();
0120         else
0121             m_VisibleList[c] = QSet<const SkyObject *>();
0122 
0123         m_CategoryInitialized[c] = false;
0124     }
0125 
0126     // sun almanac information
0127     KSSun *oSun = dynamic_cast<KSSun *>(data->objectNamed(i18n("Sun")));
0128 
0129     Q_ASSERT(oSun);
0130 
0131     sunRiseTomorrow = oSun->riseSetTime(TomorrowUT, geo, true);
0132     sunSetToday     = oSun->riseSetTime(EveningUT, geo, false);
0133     sunRiseToday    = oSun->riseSetTime(EveningUT, geo, true);
0134 
0135     //check to see if Sun is circumpolar
0136     KSNumbers *num    = new KSNumbers(UT0.djd());
0137     KSNumbers *oldNum = new KSNumbers(data->ut().djd());
0138     CachingDms LST    = geo->GSTtoLST(T0.gst());
0139 
0140     oSun->updateCoords(num, true, geo->lat(), &LST, true);
0141     if (oSun->checkCircumpolar(geo->lat()))
0142     {
0143         if (oSun->alt().Degrees() > 0.0)
0144         {
0145             sRise     = i18n("circumpolar");
0146             sSet      = i18n("circumpolar");
0147             sDuration = "00:00";
0148             Dur = hDur = mDur = 0;
0149         }
0150         else
0151         {
0152             sRise     = i18n("does not rise");
0153             sSet      = i18n("does not rise");
0154             sDuration = "24:00";
0155             Dur = hDur = 24;
0156             mDur       = 0;
0157         }
0158     }
0159     else
0160     {
0161         //Round times to the nearest minute by adding 30 seconds to the time
0162         sRise = QLocale().toString(sunRiseTomorrow);
0163         sSet  = QLocale().toString(sunSetToday);
0164 
0165         Dur = 24.0 + (float)sunRiseTomorrow.hour() +
0166               (float)sunRiseTomorrow.minute() / 60.0 +
0167               (float)sunRiseTomorrow.second() / 3600.0 - (float)sunSetToday.hour() -
0168               (float)sunSetToday.minute() / 60.0 - (float)sunSetToday.second() / 3600.0;
0169         hDur = int(Dur);
0170         mDur = int(60.0 * (Dur - (float)hDur));
0171         QTime tDur(hDur, mDur);
0172         //sDuration = QLocale().toString(tDur);
0173         // Should always be in 24 hour format
0174         sDuration = tDur.toString("hh:mm");
0175     }
0176 
0177     WUT->SunSetLabel->setText(
0178         i18nc("Sunset at time %1 on date %2", "Sunset: %1 on %2", sSet,
0179               QLocale().toString(Evening.date(), QLocale::LongFormat)));
0180     WUT->SunRiseLabel->setText(
0181         i18nc("Sunrise at time %1 on date %2", "Sunrise: %1 on %2", sRise,
0182               QLocale().toString(Tomorrow.date(), QLocale::LongFormat)));
0183     if (Dur == 0)
0184         WUT->NightDurationLabel->setText(i18n("Night duration: %1", sDuration));
0185     else if (Dur > 1)
0186         WUT->NightDurationLabel->setText(i18n("Night duration: %1 hours", sDuration));
0187     else if (Dur == 1)
0188         WUT->NightDurationLabel->setText(i18n("Night duration: %1 hour", sDuration));
0189     else if (mDur > 1)
0190         WUT->NightDurationLabel->setText(i18n("Night duration: %1 minutes", sDuration));
0191     else if (mDur == 1)
0192         WUT->NightDurationLabel->setText(i18n("Night duration: %1 minute", sDuration));
0193 
0194     // moon almanac information
0195     KSMoon *oMoon = dynamic_cast<KSMoon *>(data->objectNamed(i18n("Moon")));
0196     moonRise      = oMoon->riseSetTime(UT0, geo, true);
0197     moonSet       = oMoon->riseSetTime(UT0, geo, false);
0198 
0199     //check to see if Moon is circumpolar
0200     oMoon->updateCoords(num, true, geo->lat(), &LST, true);
0201     if (oMoon->checkCircumpolar(geo->lat()))
0202     {
0203         if (oMoon->alt().Degrees() > 0.0)
0204         {
0205             sRise = i18n("circumpolar");
0206             sSet  = i18n("circumpolar");
0207         }
0208         else
0209         {
0210             sRise = i18n("does not rise");
0211             sSet  = i18n("does not rise");
0212         }
0213     }
0214     else
0215     {
0216         //Round times to the nearest minute by adding 30 seconds to the time
0217         sRise = QLocale().toString(moonRise.addSecs(30));
0218         sSet  = QLocale().toString(moonSet.addSecs(30));
0219     }
0220 
0221     WUT->MoonRiseLabel->setText(
0222         i18n("Moon rises at: %1 on %2", sRise,
0223              QLocale().toString(Evening.date(), QLocale::LongFormat)));
0224 
0225     // If the moon rises and sets on the same day, this will be valid [ Unless
0226     // the moon sets on the next day after staying on for over 24 hours ]
0227 
0228     if (moonSet > moonRise)
0229         WUT->MoonSetLabel->setText(
0230             i18n("Moon sets at: %1 on %2", sSet,
0231                  QLocale().toString(Evening.date(), QLocale::LongFormat)));
0232     else
0233         WUT->MoonSetLabel->setText(
0234             i18n("Moon sets at: %1 on %2", sSet,
0235                  QLocale().toString(Tomorrow.date(), QLocale::LongFormat)));
0236     oMoon->findPhase(nullptr);
0237     WUT->MoonIllumLabel->setText(oMoon->phaseName() +
0238                                  QString(" (%1%)").arg(int(100.0 * oMoon->illum())));
0239 
0240     //Restore Sun's and Moon's coordinates, and recompute Moon's original Phase
0241     oMoon->updateCoords(oldNum, true, geo->lat(), data->lst(), true);
0242     oSun->updateCoords(oldNum, true, geo->lat(), data->lst(), true);
0243     oMoon->findPhase(nullptr);
0244 
0245     if (WUT->CategoryListWidget->currentItem())
0246         slotLoadList(WUT->CategoryListWidget->currentItem()->text());
0247 
0248     delete num;
0249     delete oldNum;
0250 }
0251 
0252 QSet<const SkyObject *> &WUTDialog::visibleObjects(const QString &category)
0253 {
0254     return m_VisibleList[category];
0255 }
0256 
0257 const SkyObject * WUTDialog::findVisibleObject(const QString &name)
0258 {
0259     for (const auto &oneList : m_VisibleList)
0260     {
0261         for (const auto &oneObject : oneList)
0262         {
0263             if (oneObject->name() == name)
0264                 return oneObject;
0265         }
0266     }
0267 
0268     return nullptr;
0269 }
0270 
0271 bool WUTDialog::isCategoryInitialized(const QString &category)
0272 {
0273     return m_CategoryInitialized[category];
0274 }
0275 
0276 QVector<QPair<QString, const SkyObject *>> WUTDialog::load_dso(const QString &category,
0277                                         const std::vector<SkyObject::TYPE> &types)
0278 {
0279     CatalogsDB::DBManager db{ CatalogsDB::dso_db_path() };
0280     QVector<QPair<QString, const SkyObject *>> objects;
0281 
0282     auto &lst = m_CatalogObjects[category];
0283     lst.clear();
0284 
0285     for (const auto type : types)
0286     {
0287         lst.splice(lst.end(), db.get_objects(type, m_Mag));
0288     }
0289 
0290     objects.reserve(lst.size());
0291     for (const auto &obj : lst)
0292     {
0293         objects.push_back({ obj.name(), &obj });
0294     }
0295 
0296     return objects;
0297 }
0298 
0299 void WUTDialog::slotLoadList(const QString &c)
0300 {
0301     KStarsData *data = KStarsData::Instance();
0302     if (!m_VisibleList.contains(c))
0303         return;
0304 
0305     WUT->ObjectListWidget->clear();
0306     setCursor(QCursor(Qt::WaitCursor));
0307 
0308     const bool isDSO = c == m_Categories[2] || c == m_Categories[3] || c == m_Categories[4];
0309 
0310     if (!isCategoryInitialized(c))
0311     {
0312         if (c == m_Categories[0]) //Planets
0313         {
0314             foreach (const QString &name,
0315                      data->skyComposite()->objectNames(SkyObject::PLANET))
0316             {
0317                 SkyObject *o = data->skyComposite()->findByName(name);
0318 
0319                 if (o->mag() <= m_Mag && checkVisibility(o))
0320                     visibleObjects(c).insert(o);
0321             }
0322 
0323             m_CategoryInitialized[c] = true;
0324         }
0325 
0326         else if (c == m_Categories[1]) //Stars
0327         {
0328             QVector<QPair<QString, const SkyObject *>> starObjects;
0329             starObjects.append(data->skyComposite()->objectLists(SkyObject::STAR));
0330             starObjects.append(
0331                 data->skyComposite()->objectLists(SkyObject::CATALOG_STAR));
0332             starObjects.append(load_dso(c, { SkyObject::STAR, SkyObject::CATALOG_STAR }));
0333 
0334             for (const auto &object : starObjects)
0335             {
0336                 const SkyObject *o = object.second;
0337 
0338                 if (o->mag() <= m_Mag && checkVisibility(o))
0339                 {
0340                     visibleObjects(c).insert(o);
0341                 }
0342             }
0343             m_CategoryInitialized[c] = true;
0344         }
0345 
0346         else if (c == m_Categories[5]) //Constellations
0347         {
0348             foreach (SkyObject *o, data->skyComposite()->constellationNames())
0349                 if (checkVisibility(o))
0350                     visibleObjects(c).insert(o);
0351 
0352             m_CategoryInitialized[c] = true;
0353         }
0354 
0355         else if (c == m_Categories[6]) //Asteroids
0356         {
0357             foreach (SkyObject *o, data->skyComposite()->asteroids())
0358                 if (o->mag() <= m_Mag &&
0359                         o->name() != i18nc("Asteroid name (optional)", "Pluto") &&
0360                         checkVisibility(o))
0361                     visibleObjects(c).insert(o);
0362 
0363             m_CategoryInitialized[c] = true;
0364         }
0365 
0366         else if (c == m_Categories[7]) //Comets
0367         {
0368             foreach (SkyObject *o, data->skyComposite()->comets())
0369                 if (o->mag() <= m_Mag && checkVisibility(o))
0370                     visibleObjects(c).insert(o);
0371 
0372             m_CategoryInitialized[c] = true;
0373         }
0374 
0375         else //all deep-sky objects, need to split clusters, nebulae and galaxies
0376         {
0377             auto dsos{ load_dso(c,
0378                 {
0379                     SkyObject::OPEN_CLUSTER, SkyObject::GLOBULAR_CLUSTER,
0380                     SkyObject::GASEOUS_NEBULA, SkyObject::PLANETARY_NEBULA,
0381                     SkyObject::SUPERNOVA_REMNANT, SkyObject::SUPERNOVA,
0382                     SkyObject::GALAXY
0383                 }) };
0384 
0385             for (auto &dso : dsos)
0386             {
0387                 const SkyObject *o = dso.second;
0388                 if (checkVisibility(o) && o->mag() <= m_Mag)
0389                 {
0390                     switch (o->type())
0391                     {
0392                         case SkyObject::OPEN_CLUSTER: //fall through
0393                         case SkyObject::GLOBULAR_CLUSTER:
0394                             visibleObjects(m_Categories[4]).insert(o); //star clusters
0395                             break;
0396                         case SkyObject::GASEOUS_NEBULA:   //fall through
0397                         case SkyObject::PLANETARY_NEBULA: //fall through
0398                         case SkyObject::SUPERNOVA:        //fall through
0399                         case SkyObject::SUPERNOVA_REMNANT:
0400                             visibleObjects(m_Categories[2]).insert(o); //nebulae
0401                             break;
0402                         case SkyObject::GALAXY:
0403                             visibleObjects(m_Categories[3]).insert(o); //galaxies
0404                             break;
0405                     }
0406                 }
0407             }
0408 
0409             m_CategoryInitialized[m_Categories[2]] = true;
0410             m_CategoryInitialized[m_Categories[3]] = true;
0411             m_CategoryInitialized[m_Categories[4]] = true;
0412         }
0413     }
0414 
0415     //Now the category has been initialized, we can populate the list widget
0416     if (isDSO)
0417     {
0418         for (const auto &oneObject : visibleObjects(c))
0419             WUT->ObjectListWidget->addItem(oneObject->name());
0420     }
0421     else
0422     {
0423         for (const auto &oneObject : visibleObjects(c))
0424             WUT->ObjectListWidget->addItem(oneObject->longname());
0425     }
0426 
0427     setCursor(QCursor(Qt::ArrowCursor));
0428 
0429     // highlight first item
0430     if (WUT->ObjectListWidget->count())
0431     {
0432         WUT->ObjectListWidget->setCurrentRow(0);
0433         WUT->ObjectListWidget->setFocus();
0434     }
0435 }
0436 
0437 bool WUTDialog::checkVisibility(const SkyObject *o)
0438 {
0439     bool visible(false);
0440     double minAlt =
0441         6.0; //An object is considered 'visible' if it is above horizon during civil twilight.
0442 
0443     // reject objects that never rise
0444     if (o->checkCircumpolar(geo->lat()) == true && o->alt().Degrees() <= 0)
0445         return false;
0446 
0447     //Initial values for T1, T2 assume all night option of EveningMorningBox
0448     KStarsDateTime T1 = Evening;
0449     T1.setTime(sunSetToday);
0450     KStarsDateTime T2 = Tomorrow;
0451     T2.setTime(sunRiseTomorrow);
0452 
0453     //Check Evening/Morning only state:
0454     if (EveningFlag == 0) //Evening only
0455     {
0456         T2 = T0; //midnight
0457     }
0458     else if (EveningFlag == 1) //Morning only
0459     {
0460         T1 = T0; //midnight
0461     }
0462 
0463     for (KStarsDateTime test = T1; test < T2; test = test.addSecs(3600))
0464     {
0465         //Need LST of the test time, expressed as a dms object.
0466         KStarsDateTime ut = geo->LTtoUT(test);
0467         dms LST           = geo->GSTtoLST(ut.gst());
0468         SkyPoint sp       = o->recomputeCoords(ut, geo);
0469 
0470         //check altitude of object at this time.
0471         sp.EquatorialToHorizontal(&LST, geo->lat());
0472 
0473         if (sp.alt().Degrees() > minAlt)
0474         {
0475             visible = true;
0476             break;
0477         }
0478     }
0479 
0480     return visible;
0481 }
0482 
0483 void WUTDialog::slotDisplayObject(const QString &name)
0484 {
0485     QTime tRise, tSet, tTransit;
0486     QString sRise, sTransit, sSet;
0487 
0488     sRise    = "--:--";
0489     sTransit = "--:--";
0490     sSet     = "--:--";
0491     WUT->DetailButton->setEnabled(false);
0492 
0493     SkyObject *o = nullptr;
0494     if (name.isEmpty())
0495     {
0496         //no object selected
0497         WUT->ObjectBox->setTitle(i18n("No Object Selected"));
0498         o = nullptr;
0499     }
0500     else
0501     {
0502         o = KStarsData::Instance()->objectNamed(name);
0503 
0504         if (!o) //should never get here
0505         {
0506             WUT->ObjectBox->setTitle(i18n("Object Not Found"));
0507         }
0508     }
0509     if (o)
0510     {
0511         WUT->ObjectBox->setTitle(o->name());
0512 
0513         if (o->checkCircumpolar(geo->lat()))
0514         {
0515             if (o->alt().Degrees() > 0.0)
0516             {
0517                 sRise = i18n("circumpolar");
0518                 sSet  = i18n("circumpolar");
0519             }
0520             else
0521             {
0522                 sRise = i18n("does not rise");
0523                 sSet  = i18n("does not rise");
0524             }
0525         }
0526         else
0527         {
0528             tRise = o->riseSetTime(T0, geo, true);
0529             tSet  = o->riseSetTime(T0, geo, false);
0530 
0531             sRise = QString("%1:%2").arg(tRise.hour(), 2, 10, QChar('0')).arg(tRise.minute(), 2, 10, QChar('0'));
0532             sSet  = QString("%1:%2").arg(tSet.hour(), 2, 10, QChar('0')).arg(tSet.minute(), 2, 10, QChar('0'));
0533         }
0534 
0535         tTransit = o->transitTime(T0, geo);
0536         sTransit = QString("%1:%2").arg(tTransit.hour(), 2, 10, QChar('0')).arg(tTransit.minute(), 2, 10, QChar('0'));
0537 
0538         WUT->DetailButton->setEnabled(true);
0539     }
0540 
0541     WUT->ObjectRiseLabel->setText(i18n("Rises at: %1", sRise));
0542     WUT->ObjectTransitLabel->setText(i18n("Transits at: %1", sTransit));
0543     WUT->ObjectSetLabel->setText(i18n("Sets at: %1", sSet));
0544 }
0545 
0546 void WUTDialog::slotCenter()
0547 {
0548     KStars *kstars = KStars::Instance();
0549     SkyObject *o   = nullptr;
0550     // get selected item
0551     if (WUT->ObjectListWidget->currentItem() != nullptr)
0552     {
0553         o = kstars->data()->objectNamed(WUT->ObjectListWidget->currentItem()->text());
0554     }
0555     if (o != nullptr)
0556     {
0557         kstars->map()->setFocusPoint(o);
0558         kstars->map()->setFocusObject(o);
0559         kstars->map()->setDestination(*kstars->map()->focusPoint());
0560     }
0561 }
0562 
0563 void WUTDialog::slotDetails()
0564 {
0565     KStars *kstars = KStars::Instance();
0566     SkyObject *o   = nullptr;
0567     // get selected item
0568     if (WUT->ObjectListWidget->currentItem() != nullptr)
0569     {
0570         o = kstars->data()->objectNamed(WUT->ObjectListWidget->currentItem()->text());
0571     }
0572     if (o != nullptr)
0573     {
0574         QPointer<DetailDialog> detail =
0575             new DetailDialog(o, kstars->data()->ut(), geo, kstars);
0576         detail->exec();
0577         delete detail;
0578     }
0579 }
0580 void WUTDialog::slotObslist()
0581 {
0582     SkyObject *o = nullptr;
0583     // get selected item
0584     if (WUT->ObjectListWidget->currentItem() != nullptr)
0585     {
0586         o = KStarsData::Instance()->objectNamed(
0587                 WUT->ObjectListWidget->currentItem()->text());
0588     }
0589     if (o != nullptr)
0590     {
0591         KStarsData::Instance()->observingList()->slotAddObject(o, session);
0592     }
0593 }
0594 
0595 void WUTDialog::slotChangeDate()
0596 {
0597     // Set the time T0 to the evening of today. This will make life easier for the user, who most probably
0598     // wants to see what's up on the night of some date, rather than the night of the previous day
0599     T0.setTime(QTime(18, 0, 0)); // 6 PM
0600 
0601     QPointer<TimeDialog> td = new TimeDialog(T0, KStarsData::Instance()->geo(), this);
0602     if (td->exec() == QDialog::Accepted)
0603     {
0604         T0 = td->selectedDateTime();
0605 
0606         // If the time is set to 12 midnight, set it to 00:00:01, so that we don't have date interpretation problems
0607         if (T0.time() == QTime(0, 0, 0))
0608             T0.setTime(QTime(0, 0, 1));
0609 
0610         //If the Time is earlier than 6:00 am, assume the user wants the night of the previous date
0611         if (T0.time().hour() < 6)
0612             T0 = T0.addDays(-1);
0613 
0614         //Now, set time T0 to midnight (of the following day)
0615         T0.setTime(QTime(0, 0, 0));
0616         T0  = T0.addDays(1);
0617         UT0 = geo->LTtoUT(T0);
0618 
0619         //Set the Tomorrow date/time to Noon the following day
0620         Tomorrow   = T0.addSecs(12 * 3600);
0621         TomorrowUT = geo->LTtoUT(Tomorrow);
0622 
0623         //Set the Evening date/time to 6:00 pm
0624         Evening   = T0.addSecs(-6 * 3600);
0625         EveningUT = geo->LTtoUT(Evening);
0626 
0627         WUT->DateLabel->setText(i18n(
0628                                     "The night of %1", QLocale().toString(Evening.date(), QLocale::LongFormat)));
0629 
0630         init();
0631         slotLoadList(WUT->CategoryListWidget->currentItem()->text());
0632     }
0633     delete td;
0634 }
0635 
0636 void WUTDialog::slotChangeLocation()
0637 {
0638     QPointer<LocationDialog> ld = new LocationDialog(this);
0639     if (ld->exec() == QDialog::Accepted)
0640     {
0641         GeoLocation *newGeo = ld->selectedCity();
0642         if (newGeo)
0643         {
0644             geo        = newGeo;
0645             UT0        = geo->LTtoUT(T0);
0646             TomorrowUT = geo->LTtoUT(Tomorrow);
0647             EveningUT  = geo->LTtoUT(Evening);
0648 
0649             WUT->LocationLabel->setText(i18n("at %1", geo->fullName()));
0650 
0651             init();
0652             slotLoadList(WUT->CategoryListWidget->currentItem()->text());
0653         }
0654     }
0655     delete ld;
0656 }
0657 
0658 void WUTDialog::slotEveningMorning(int index)
0659 {
0660     if (EveningFlag != index)
0661     {
0662         EveningFlag = index;
0663         init();
0664         slotLoadList(WUT->CategoryListWidget->currentItem()->text());
0665     }
0666 }
0667 
0668 void WUTDialog::updateMag()
0669 {
0670     m_Mag = WUT->MagnitudeEdit->value();
0671     init();
0672     slotLoadList(WUT->CategoryListWidget->currentItem()->text());
0673 }
0674 
0675 void WUTDialog::slotChangeMagnitude()
0676 {
0677     if (timer)
0678     {
0679         timer->stop();
0680     }
0681     else
0682     {
0683         timer = new QTimer(this);
0684         timer->setSingleShot(true);
0685         connect(timer, SIGNAL(timeout()), this, SLOT(updateMag()));
0686     }
0687     timer->start(500);
0688 }
0689 
0690 void WUTDialog::showEvent(QShowEvent *event)
0691 {
0692     Q_UNUSED(event);
0693     QTimer::singleShot(0, this, SLOT(init()));
0694 };