File indexing completed on 2024-04-14 14:11:36
0001 /* 0002 SPDX-FileCopyrightText: 2018 Valentin Boettcher <valentin@boettcher.cf> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "eclipsetool.h" 0008 #include "ui_eclipsetool.h" 0009 #include "ksplanetbase.h" 0010 #include "kstarsdata.h" 0011 #include "geolocation.h" 0012 #include "dialogs/locationdialog.h" 0013 #include "kstars.h" 0014 #include "skymap.h" 0015 0016 #include <QtConcurrent> 0017 #include <QFileDialog> 0018 #include <QErrorMessage> 0019 #include <QMenu> 0020 0021 EclipseTool::EclipseTool(QWidget *parent) : 0022 QFrame(parent), 0023 ui(new Ui::EclipseTool) 0024 { 0025 ui->setupUi(this); 0026 0027 // set up the eclipse-partner selection 0028 ui->Obj1ComboBox->addItem(i18n("Earth Shadow"), KSPlanetBase::EARTH_SHADOW); 0029 ui->Obj2ComboBox->addItem(i18n("Moon"), KSPlanetBase::MOON); 0030 0031 KStarsData *kd = KStarsData::Instance(); 0032 KStarsDateTime dtStart(KStarsDateTime::currentDateTime()); 0033 KStarsDateTime dtStop(dtStart.djd() + 365.24l); // one year 0034 0035 m_geoLocation = kd->geo(); 0036 ui->LocationButton->setText(m_geoLocation->fullName()); 0037 0038 ui->startDate->setDateTime(dtStart); 0039 ui->stopDate->setDateTime(dtStop); 0040 0041 ui->ClearButton->setIcon(QIcon::fromTheme("edit-clear")); 0042 0043 // set up slots 0044 connect(ui->LocationButton, &QPushButton::clicked, this, &EclipseTool::slotLocation); 0045 connect(ui->ComputeButton, &QPushButton::clicked, this, [&, this]() { 0046 // switch to progress bar 0047 ui->computeStack->setCurrentIndex(1); 0048 0049 // reset progress 0050 ui->progressBar->setValue(0); 0051 0052 QtConcurrent::run(this, &EclipseTool::slotCompute); 0053 }); 0054 0055 connect(ui->ClearButton, &QPushButton::clicked, &m_model, &EclipseModel::reset); 0056 connect(ui->ExportButton, &QPushButton::clicked, &m_model, &EclipseModel::exportAsCsv); 0057 0058 // eclipse table 0059 ui->tableView->setModel(&m_model); 0060 ui->tableView->horizontalHeader()->setStretchLastSection(true); 0061 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); 0062 0063 // double click to view 0064 connect(ui->tableView, &QTableView::doubleClicked, this, [this](const QModelIndex &index){ 0065 slotView(m_model.getEvent(index.row())); 0066 }); 0067 0068 connect(ui->tableView, &QTableView::customContextMenuRequested, this, &EclipseTool::slotContextMenu); 0069 0070 ui->progressBar->setMinimum(0); 0071 ui->progressBar->setMaximum(100); 0072 } 0073 0074 EclipseTool::~EclipseTool() 0075 { 0076 delete ui; 0077 } 0078 0079 void EclipseTool::slotLocation() 0080 { 0081 QPointer<LocationDialog> ld(new LocationDialog(this)); 0082 if (ld->exec() == QDialog::Accepted && ld) 0083 { 0084 m_geoLocation = ld->selectedCity(); 0085 ui->LocationButton->setText(m_geoLocation->fullName()); 0086 } 0087 delete ld; 0088 } 0089 0090 // NOTE: This will need redesign some day. 0091 void EclipseTool::slotCompute() 0092 { 0093 EclipseHandler * handler; 0094 KStarsDateTime dtStart(ui->startDate->dateTime()); // start date 0095 KStarsDateTime dtStop(ui->stopDate->dateTime()); // stop date 0096 long double startJD = dtStart.djd(); // start julian day 0097 long double stopJD = dtStop.djd(); 0098 0099 if(ui->Obj1ComboBox->currentData().toInt() == KSPlanetBase::EARTH_SHADOW && ui->Obj2ComboBox->currentData().toInt() == KSPlanetBase::MOON){ 0100 handler = new LunarEclipseHandler(); 0101 } else 0102 return; 0103 0104 connect(handler, &EclipseHandler::signalEventFound, &m_model, &EclipseModel::slotAddEclipse); 0105 connect(handler, &EclipseHandler::signalProgress, ui->progressBar, &QProgressBar::setValue); 0106 connect(handler, &EclipseHandler::signalComputationFinished, this, &EclipseTool::slotFinished); 0107 0108 handler->setGeoLocation(m_geoLocation); 0109 0110 // let's go 0111 EclipseHandler::EclipseVector eclipses = handler->computeEclipses(startJD, stopJD); 0112 delete handler; 0113 } 0114 0115 void EclipseTool::slotFinished() 0116 { 0117 ui->computeStack->setCurrentIndex(0); 0118 } 0119 0120 void EclipseTool::slotContextMenu(QPoint pos) 0121 { 0122 int row = ui->tableView->indexAt(pos).row(); 0123 EclipseEvent_s event = m_model.getEvent(row); 0124 0125 QMenu * menu = new QMenu(this); 0126 QAction * view = new QAction(i18n("View in SkyMap"), menu); 0127 connect(view, &QAction::triggered, this, [=]{ 0128 slotView(event); 0129 }); 0130 menu->addAction(view); 0131 0132 if(event->hasDetails()){ 0133 QAction * details = new QAction(i18n("Show Details"), menu); 0134 connect(details, &QAction::triggered, this, [=] { 0135 event->slotShowDetails(); // call virtual 0136 }); 0137 menu->addAction(details); 0138 } 0139 0140 menu->popup(ui->tableView->viewport()->mapToGlobal(pos)); 0141 } 0142 0143 void EclipseTool::slotView(EclipseEvent_s event) 0144 { 0145 SkyMap * map = KStars::Instance()->map(); 0146 KStarsData * data = KStarsData::Instance(); 0147 KStarsDateTime dt; 0148 0149 dt.setDJD(event->getJD()); 0150 data->changeDateTime(dt); 0151 data->setLocation(event->getGeolocation()); 0152 0153 map->setClickedObject(event->getEclipsingObjectFromSkyComposite()); 0154 map->setClickedPoint(map->clickedObject()); 0155 map->slotCenter(); 0156 } 0157 0158 EclipseModel::EclipseModel(QObject *parent) : QAbstractTableModel (parent) 0159 { 0160 0161 } 0162 0163 int EclipseModel::rowCount(const QModelIndex &) const 0164 { 0165 return m_eclipses.length(); 0166 } 0167 0168 QVariant EclipseModel::data(const QModelIndex &index, int role) const 0169 { 0170 int row = index.row(); 0171 int col = index.column(); 0172 0173 if(role != Qt::DisplayRole) 0174 return QVariant(); 0175 0176 EclipseEvent * event = m_eclipses[row].get(); 0177 0178 switch(col) { 0179 case 0: /* Date */ { 0180 KStarsDateTime dt(event->getJD()); 0181 return dt.toString(Qt::ISODate); 0182 } 0183 case 1: // Eclipsing Obj 0184 return event->getEclipsingObjectName(); 0185 case 2: // Eclipsed Obj 0186 return event->getEclipsedObjectName(); 0187 case 3: /* Eclipse Type */ { 0188 switch(event->getType()) { 0189 case EclipseEvent::FULL: 0190 return QString(i18n("Full")); 0191 case EclipseEvent::PARTIAL: 0192 return QString(i18n("Partial")); 0193 } 0194 break; 0195 } 0196 case 4: // Extra Info 0197 return event->getExtraInfo(); 0198 } 0199 0200 return QVariant(); 0201 } 0202 0203 void EclipseModel::slotAddEclipse(EclipseEvent_s eclipse) 0204 { 0205 m_eclipses.append(eclipse); 0206 emit layoutChanged(); // there must be a better way 0207 } 0208 0209 void EclipseModel::exportAsCsv() 0210 { 0211 int i, j; 0212 QByteArray line; 0213 0214 QFileDialog dialog; 0215 dialog.setNameFilter(i18n("CSV Files (*.csv)")); 0216 dialog.setDefaultSuffix("csv"); 0217 dialog.setWindowTitle(i18nc("@title:window", "Export Eclipses")); 0218 0219 QString fname; 0220 if(dialog.exec()) 0221 fname = dialog.selectedFiles()[0]; 0222 else { 0223 QErrorMessage msg; 0224 msg.showMessage(i18n("Could not export.")); 0225 return; 0226 } 0227 0228 QFile file(fname); 0229 0230 file.open(QIODevice::WriteOnly | QIODevice::Text); 0231 0232 for (i = 0; i < rowCount(); ++i) 0233 { 0234 for (j = 0; j < columnCount(); ++j) 0235 { 0236 line.append(data(index(i, j), Qt::DisplayRole).toByteArray()); 0237 if (j < columnCount() - 1) 0238 line.append(";"); 0239 else 0240 line.append("\n"); 0241 } 0242 file.write(line); 0243 line.clear(); 0244 } 0245 0246 file.close(); 0247 } 0248 0249 QVariant EclipseModel::headerData(int section, Qt::Orientation orientation, int role) const 0250 { 0251 if (role == Qt::DisplayRole) 0252 { 0253 if (orientation == Qt::Horizontal) { 0254 switch (section) 0255 { 0256 case 0: 0257 return QString("Date"); 0258 case 1: 0259 return QString("Eclipsing Object"); 0260 case 2: 0261 return QString("Eclipsed Object"); 0262 case 3: 0263 return QString("Eclipse Type"); 0264 case 4: 0265 return QString("Extra Information"); 0266 } 0267 } 0268 } 0269 return QVariant(); 0270 } 0271 0272 void EclipseModel::reset() 0273 { 0274 emit beginResetModel(); 0275 emit endResetModel(); 0276 }