File indexing completed on 2024-05-05 07:43:42
0001 /* 0002 SPDX-FileCopyrightText: 2009 Jerome SONRIER <jsid@emor3j.fr.eu.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "flagmanager.h" 0008 0009 #include "config-kstars.h" 0010 0011 #include "kspaths.h" 0012 #include "ksnotification.h" 0013 #include "kstars.h" 0014 #include "kstars_debug.h" 0015 #include "kstarsdata.h" 0016 #include "Options.h" 0017 #include "skymap.h" 0018 #include "skycomponents/flagcomponent.h" 0019 #include "skycomponents/skymapcomposite.h" 0020 0021 #ifdef HAVE_INDI 0022 #include <basedevice.h> 0023 #include "indi/indilistener.h" 0024 #include "indi/indistd.h" 0025 #include "indi/indimount.h" 0026 #include "indi/driverinfo.h" 0027 #endif 0028 0029 #include <KMessageBox> 0030 0031 #include <QStandardItemModel> 0032 #include <QSortFilterProxyModel> 0033 0034 FlagManagerUI::FlagManagerUI(QWidget *p) : QFrame(p) 0035 { 0036 setupUi(this); 0037 } 0038 0039 FlagManager::FlagManager(QWidget *ks) : QDialog(ks) 0040 { 0041 #ifdef Q_OS_OSX 0042 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); 0043 #endif 0044 QList<QStandardItem *> itemList; 0045 QList<QImage> imageList; 0046 QStringList flagNames; 0047 int i; 0048 0049 ui = new FlagManagerUI(this); 0050 0051 setWindowTitle(i18nc("@title:window", "Flag Manager")); 0052 0053 QVBoxLayout *mainLayout = new QVBoxLayout; 0054 mainLayout->addWidget(ui); 0055 setLayout(mainLayout); 0056 0057 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); 0058 mainLayout->addWidget(buttonBox); 0059 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0060 0061 m_Ks = KStars::Instance(); 0062 0063 ui->hintLabel->setText(i18n("To add custom icons, just add images in %1. File names must begin with flag. " 0064 "For example, the file <i>flagSmall_red_cross.png</i> will be shown as <b>Small red " 0065 "cross</b> in the combo box.", 0066 KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))); 0067 //Set up the Table Views 0068 m_Model = new QStandardItemModel(0, 5, this); 0069 m_Model->setHorizontalHeaderLabels(QStringList() << i18nc("Right Ascension", "RA") << i18nc("Declination", "Dec") 0070 << i18n("Epoch") << i18n("Icon") << i18n("Label")); 0071 m_SortModel = new QSortFilterProxyModel(this); 0072 m_SortModel->setSourceModel(m_Model); 0073 m_SortModel->setDynamicSortFilter(true); 0074 ui->flagList->setModel(m_SortModel); 0075 ui->flagList->horizontalHeader()->setStretchLastSection(true); 0076 0077 ui->flagList->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 0078 0079 ui->saveButton->setEnabled(false); 0080 0081 ui->raBox->setUnits(dmsBox::HOURS); 0082 0083 //Fill the list 0084 imageList = m_Ks->data()->skyComposite()->flags()->imageList(); 0085 flagNames = m_Ks->data()->skyComposite()->flags()->getNames(); 0086 0087 FlagComponent *flags = m_Ks->data()->skyComposite()->flags(); 0088 QPixmap pixmap; 0089 0090 for (i = 0; i < m_Ks->data()->skyComposite()->flags()->size(); ++i) 0091 { 0092 QStandardItem *labelItem = new QStandardItem(flags->label(i)); 0093 labelItem->setForeground(QBrush(flags->labelColor(i))); 0094 0095 itemList << new QStandardItem(flags->pointList().at(i)->ra0().toHMSString()) 0096 << new QStandardItem(flags->pointList().at(i)->dec0().toDMSString()) 0097 << new QStandardItem(flags->epoch(i)) 0098 << new QStandardItem(QIcon(pixmap.fromImage(flags->image(i))), flags->imageName(i)) << labelItem; 0099 m_Model->appendRow(itemList); 0100 itemList.clear(); 0101 } 0102 0103 //Fill the combobox 0104 for (i = 0; i < imageList.size(); ++i) 0105 { 0106 ui->flagCombobox->addItem(QIcon(pixmap.fromImage(flags->imageList(i))), flagNames.at(i), flagNames.at(i)); 0107 } 0108 0109 //Connect buttons 0110 connect(ui->addButton, SIGNAL(clicked()), this, SLOT(slotAddFlag())); 0111 connect(ui->delButton, SIGNAL(clicked()), this, SLOT(slotDeleteFlag())); 0112 connect(ui->CenterButton, SIGNAL(clicked()), this, SLOT(slotCenterFlag())); 0113 connect(ui->ScopeButton, SIGNAL(clicked()), this, SLOT(slotCenterTelescope())); 0114 connect(ui->flagList, SIGNAL(clicked(QModelIndex)), this, SLOT(slotSetShownFlag(QModelIndex))); 0115 connect(ui->flagList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(slotCenterFlag())); 0116 0117 connect(ui->saveButton, SIGNAL(clicked()), this, SLOT(slotSaveChanges())); 0118 } 0119 0120 void FlagManager::setRaDec(const dms &ra, const dms &dec) 0121 { 0122 ui->raBox->show(ra); 0123 ui->decBox->show(dec); 0124 } 0125 0126 void FlagManager::clearFields() 0127 { 0128 ui->raBox->clear(); 0129 ui->decBox->clear(); 0130 0131 ui->epochBox->setText("2000.0"); 0132 ui->flagLabel->clear(); 0133 ui->flagLabel->setFocus(); 0134 0135 //disable "Save Changes" button 0136 ui->saveButton->setEnabled(false); 0137 0138 //unselect item from flagList 0139 ui->flagList->clearSelection(); 0140 } 0141 0142 void FlagManager::showFlag(int flagIdx) 0143 { 0144 if (flagIdx < 0 || flagIdx >= m_Model->rowCount()) 0145 { 0146 return; 0147 } 0148 0149 else 0150 { 0151 ui->raBox->setText(m_Model->data(m_Model->index(flagIdx, 0)).toString()); 0152 ui->decBox->setText(m_Model->data(m_Model->index(flagIdx, 1)).toString()); 0153 ui->epochBox->setText(m_Model->data(m_Model->index(flagIdx, 2)).toString()); 0154 0155 //ui->flagCombobox->setCurrentItem( m_Model->data( m_Model->index( flagIdx, 3) ).toString() ); 0156 ui->flagCombobox->setCurrentText(m_Model->data(m_Model->index(flagIdx, 3)).toString()); 0157 ui->flagLabel->setText(m_Model->data(m_Model->index(flagIdx, 4)).toString()); 0158 0159 QColor labelColor = m_Model->item(flagIdx, 4)->foreground().color(); 0160 ui->labelColorcombo->setColor(labelColor); 0161 } 0162 0163 ui->flagList->selectRow(flagIdx); 0164 ui->saveButton->setEnabled(true); 0165 } 0166 0167 bool FlagManager::validatePoint() 0168 { 0169 bool raOk(false), decOk(false); 0170 dms ra(ui->raBox->createDms(&raOk)); 0171 dms dec(ui->decBox->createDms(&decOk)); 0172 0173 QString message; 0174 0175 //check if ra & dec values were successfully converted 0176 if (!raOk || !decOk) 0177 { 0178 KSNotification::error(i18n("Invalid coordinates.")); 0179 return false; 0180 } 0181 0182 //make sure values are in valid range 0183 if (ra.Hours() < 0.0 || ra.Degrees() > 360.0) 0184 message = i18n("The Right Ascension value must be between 0.0 and 24.0."); 0185 if (dec.Degrees() < -90.0 || dec.Degrees() > 90.0) 0186 message += '\n' + i18n("The Declination value must be between -90.0 and 90.0."); 0187 if (!message.isEmpty()) 0188 { 0189 KSNotification::sorry(message, i18n("Invalid Coordinate Data")); 0190 return false; 0191 } 0192 0193 //all checks passed 0194 return true; 0195 } 0196 0197 void FlagManager::deleteFlagItem(int flagIdx) 0198 { 0199 if (flagIdx < m_Model->rowCount()) 0200 { 0201 m_Model->removeRow(flagIdx); 0202 } 0203 } 0204 0205 void FlagManager::slotAddFlag() 0206 { 0207 if (validatePoint() == false) 0208 return; 0209 0210 dms ra(ui->raBox->createDms()); 0211 dms dec(ui->decBox->createDms()); 0212 0213 insertFlag(true); 0214 0215 FlagComponent *flags = m_Ks->data()->skyComposite()->flags(); 0216 //Add flag in FlagComponent 0217 SkyPoint flagPoint(ra, dec); 0218 flags->add(flagPoint, ui->epochBox->text(), ui->flagCombobox->currentText(), ui->flagLabel->text(), 0219 ui->labelColorcombo->color()); 0220 0221 ui->flagList->selectRow(m_Model->rowCount() - 1); 0222 ui->saveButton->setEnabled(true); 0223 0224 flags->saveToFile(); 0225 0226 //Redraw map 0227 m_Ks->map()->forceUpdate(false); 0228 } 0229 0230 void FlagManager::slotDeleteFlag() 0231 { 0232 int flag = ui->flagList->currentIndex().row(); 0233 0234 //Remove from FlagComponent 0235 m_Ks->data()->skyComposite()->flags()->remove(flag); 0236 0237 //Remove from list 0238 m_Model->removeRow(flag); 0239 0240 //Clear form fields 0241 clearFields(); 0242 0243 //Remove from file 0244 m_Ks->data()->skyComposite()->flags()->saveToFile(); 0245 0246 //Redraw map 0247 m_Ks->map()->forceUpdate(false); 0248 } 0249 0250 void FlagManager::slotCenterFlag() 0251 { 0252 if (ui->flagList->currentIndex().isValid()) 0253 { 0254 m_Ks->map()->setClickedObject(nullptr); 0255 m_Ks->map()->setClickedPoint( 0256 m_Ks->data()->skyComposite()->flags()->pointList().at(ui->flagList->currentIndex().row()).get()); 0257 m_Ks->map()->slotCenter(); 0258 } 0259 } 0260 0261 void FlagManager::slotCenterTelescope() 0262 { 0263 #ifdef HAVE_INDI 0264 0265 if (INDIListener::Instance()->size() == 0) 0266 { 0267 KSNotification::sorry(i18n("No connected mounts found.")); 0268 return; 0269 } 0270 0271 for (auto oneDevice : INDIListener::devices()) 0272 { 0273 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)) 0274 continue; 0275 0276 if (oneDevice->isConnected() == false) 0277 { 0278 KSNotification::error( 0279 i18n("Telescope %1 is offline. Please connect and retry again.", oneDevice->getDeviceName())); 0280 return; 0281 } 0282 0283 auto mount = oneDevice->getMount(); 0284 if (!mount) 0285 continue; 0286 0287 mount->Slew(m_Ks->data()->skyComposite()->flags()->pointList().at(ui->flagList->currentIndex().row()).get()); 0288 0289 return; 0290 } 0291 0292 KSNotification::sorry(i18n("No connected mounts found.")); 0293 0294 #endif 0295 } 0296 0297 void FlagManager::slotSaveChanges() 0298 { 0299 int row = ui->flagList->currentIndex().row(); 0300 0301 if (validatePoint() == false) 0302 return; 0303 0304 insertFlag(false, row); 0305 0306 m_Ks->map()->forceUpdate(); 0307 0308 dms ra(ui->raBox->createDms()); 0309 dms dec(ui->decBox->createDms()); 0310 0311 SkyPoint flagPoint(ra, dec); 0312 0313 //Update FlagComponent 0314 m_Ks->data()->skyComposite()->flags()->updateFlag(row, flagPoint, ui->epochBox->text(), 0315 ui->flagCombobox->currentText(), ui->flagLabel->text(), 0316 ui->labelColorcombo->color()); 0317 0318 //Save changes to file 0319 m_Ks->data()->skyComposite()->flags()->saveToFile(); 0320 0321 ui->flagList->selectRow(row); 0322 } 0323 0324 void FlagManager::slotSetShownFlag(QModelIndex idx) 0325 { 0326 showFlag(idx.row()); 0327 } 0328 0329 void FlagManager::insertFlag(bool isNew, int row) 0330 { 0331 dms ra(ui->raBox->createDms()); 0332 dms dec(ui->decBox->createDms()); 0333 SkyPoint flagPoint(ra, dec); 0334 0335 // Add flag in the list 0336 QList<QStandardItem *> itemList; 0337 0338 QStandardItem *labelItem = new QStandardItem(ui->flagLabel->text()); 0339 labelItem->setForeground(QBrush(ui->labelColorcombo->color())); 0340 0341 FlagComponent *flags = m_Ks->data()->skyComposite()->flags(); 0342 0343 QPixmap pixmap; 0344 itemList << new QStandardItem(flagPoint.ra0().toHMSString()) << new QStandardItem(flagPoint.dec0().toDMSString()) 0345 << new QStandardItem(ui->epochBox->text()) 0346 << new QStandardItem(QIcon(pixmap.fromImage(flags->imageList(ui->flagCombobox->currentIndex()))), 0347 ui->flagCombobox->currentText()) 0348 << labelItem; 0349 0350 if (isNew) 0351 { 0352 m_Model->appendRow(itemList); 0353 } 0354 0355 else 0356 { 0357 for (int i = 0; i < m_Model->columnCount(); i++) 0358 { 0359 m_Model->setItem(row, i, itemList.at(i)); 0360 } 0361 } 0362 }