File indexing completed on 2025-04-27 06:42:37
0001 /* 0002 SPDX-FileCopyrightText: 2011 Jérôme SONRIER <jsid@emor3j.fr.eu.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "opssatellites.h" 0008 0009 #include "kstars.h" 0010 #include "kstarsdata.h" 0011 #include "Options.h" 0012 #include "satellite.h" 0013 #include "skymapcomposite.h" 0014 #include "skycomponents/satellitescomponent.h" 0015 #include "skymap.h" 0016 0017 #include <QStandardItemModel> 0018 #include <QStatusBar> 0019 0020 static const char *satgroup_strings_context = "Satellite group name"; 0021 0022 SatelliteSortFilterProxyModel::SatelliteSortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) 0023 { 0024 } 0025 0026 bool SatelliteSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const 0027 { 0028 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); 0029 0030 if (sourceModel()->hasChildren(index)) 0031 { 0032 for (int i = 0; i < sourceModel()->rowCount(index); ++i) 0033 if (filterAcceptsRow(i, index)) 0034 return true; 0035 return false; 0036 } 0037 0038 return sourceModel()->data(index).toString().contains(filterRegExp()); 0039 } 0040 0041 OpsSatellites::OpsSatellites() : QFrame(KStars::Instance()) 0042 { 0043 setupUi(this); 0044 0045 m_ConfigDialog = KConfigDialog::exists("settings"); 0046 0047 //Set up the Table Views 0048 m_Model = new QStandardItemModel(0, 1, this); 0049 m_SortModel = new SatelliteSortFilterProxyModel(this); 0050 m_SortModel->setSourceModel(m_Model); 0051 SatListTreeView->setModel(m_SortModel); 0052 SatListTreeView->setEditTriggers(QTreeView::NoEditTriggers); 0053 SatListTreeView->setSortingEnabled(false); 0054 0055 // Populate satellites list 0056 updateListView(); 0057 0058 // Signals and slots connections 0059 connect(UpdateTLEButton, SIGNAL(clicked()), this, SLOT(slotUpdateTLEs())); 0060 connect(kcfg_ShowSatellites, SIGNAL(toggled(bool)), SLOT(slotShowSatellites(bool))); 0061 connect(m_ConfigDialog->button(QDialogButtonBox::Apply), SIGNAL(clicked()), SLOT(slotApply())); 0062 connect(m_ConfigDialog->button(QDialogButtonBox::Ok), SIGNAL(clicked()), SLOT(slotApply())); 0063 connect(m_ConfigDialog->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), SLOT(slotCancel())); 0064 connect(FilterEdit, SIGNAL(textChanged(QString)), this, SLOT(slotFilterReg(QString))); 0065 connect(m_Model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotItemChanged(QStandardItem*))); 0066 0067 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 0068 connect(satelliteButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonPressed), this, 0069 [&]() { isDirty = true; }); 0070 #else 0071 connect(satelliteButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::idPressed), this, 0072 [&]() { isDirty = true; }); 0073 #endif 0074 0075 isDirty = false; 0076 } 0077 0078 void OpsSatellites::slotUpdateTLEs() 0079 { 0080 // Save existing satellites 0081 saveSatellitesList(); 0082 0083 // Get new data files 0084 KStarsData::Instance()->skyComposite()->satellites()->updateTLEs(); 0085 0086 isDirty = true; 0087 0088 // Refresh satellites list 0089 updateListView(); 0090 } 0091 0092 void OpsSatellites::updateListView() 0093 { 0094 KStarsData *data = KStarsData::Instance(); 0095 0096 // Clear satellites list 0097 m_Model->clear(); 0098 SatListTreeView->reset(); 0099 0100 m_Model->setHorizontalHeaderLabels(QStringList(i18n("Satellite Name"))); 0101 0102 // Add each groups and satellites in the list 0103 foreach (SatelliteGroup *sat_group, data->skyComposite()->satellites()->groups()) 0104 { 0105 QStandardItem *group_item; 0106 QStandardItem *sat_item; 0107 bool all_sat_checked = true; 0108 bool all_sat_unchecked = true; 0109 0110 // Add the group 0111 group_item = new QStandardItem(i18nc(satgroup_strings_context, sat_group->name().toUtf8())); 0112 group_item->setCheckable(true); 0113 m_Model->appendRow(group_item); 0114 0115 // Add all satellites of the group 0116 for (int i = 0; i < sat_group->count(); ++i) 0117 { 0118 sat_item = new QStandardItem(sat_group->at(i)->name()); 0119 sat_item->setCheckable(true); 0120 if (Options::selectedSatellites().contains(sat_group->at(i)->name())) 0121 { 0122 sat_item->setCheckState(Qt::Checked); 0123 all_sat_unchecked = false; 0124 } 0125 else 0126 all_sat_checked = false; 0127 group_item->setChild(i, sat_item); 0128 } 0129 0130 // If all satellites of the group are selected, select the group 0131 if (all_sat_checked) 0132 group_item->setCheckState(Qt::Checked); 0133 else if (all_sat_unchecked) 0134 group_item->setCheckState(Qt::Unchecked); 0135 else 0136 group_item->setCheckState(Qt::PartiallyChecked); 0137 } 0138 } 0139 0140 void OpsSatellites::saveSatellitesList() 0141 { 0142 KStarsData *data = KStarsData::Instance(); 0143 QString sat_name; 0144 QStringList selected_satellites; 0145 QModelIndex group_index, sat_index; 0146 QStandardItem *group_item; 0147 QStandardItem *sat_item; 0148 0149 // Retrieve each satellite in the list and select it if checkbox is checked 0150 for (int i = 0; i < m_Model->rowCount(SatListTreeView->rootIndex()); ++i) 0151 { 0152 group_index = m_Model->index(i, 0, SatListTreeView->rootIndex()); 0153 group_item = m_Model->itemFromIndex(group_index); 0154 0155 for (int j = 0; j < m_Model->rowCount(group_item->index()); ++j) 0156 { 0157 sat_index = m_Model->index(j, 0, group_index); 0158 sat_item = m_Model->itemFromIndex(sat_index); 0159 sat_name = sat_item->data(0).toString(); 0160 0161 Satellite *sat = data->skyComposite()->satellites()->findSatellite(sat_name); 0162 if (sat) 0163 { 0164 if (sat_item->checkState() == Qt::Checked) 0165 { 0166 int rc = sat->updatePos(); 0167 // If position calculation fails, unselect it 0168 if (rc == 0) 0169 { 0170 sat->setSelected(true); 0171 selected_satellites.append(sat_name); 0172 } 0173 else 0174 { 0175 KStars::Instance()->statusBar()->showMessage( 0176 i18n("%1 position calculation error: %2.", sat->name(), sat->sgp4ErrorString(rc)), 0); 0177 sat->setSelected(false); 0178 sat_item->setCheckState(Qt::Unchecked); 0179 } 0180 } 0181 else 0182 { 0183 sat->setSelected(false); 0184 } 0185 } 0186 } 0187 } 0188 0189 Options::setSelectedSatellites(selected_satellites); 0190 } 0191 0192 void OpsSatellites::slotApply() 0193 { 0194 if (isDirty == false) 0195 return; 0196 0197 isDirty = false; 0198 0199 saveSatellitesList(); 0200 0201 // update time for all objects because they might be not initialized 0202 // it's needed when using horizontal coordinates 0203 KStars::Instance()->data()->setFullTimeUpdate(); 0204 KStars::Instance()->updateTime(); 0205 KStars::Instance()->map()->forceUpdate(); 0206 } 0207 0208 void OpsSatellites::slotCancel() 0209 { 0210 // Update satellites list 0211 updateListView(); 0212 } 0213 0214 void OpsSatellites::slotShowSatellites(bool on) 0215 { 0216 isDirty = true; 0217 kcfg_ShowVisibleSatellites->setEnabled(on); 0218 kcfg_ShowSatellitesLabels->setEnabled(on); 0219 kcfg_DrawSatellitesLikeStars->setEnabled(on); 0220 } 0221 0222 void OpsSatellites::slotFilterReg(const QString &filter) 0223 { 0224 m_SortModel->setFilterRegExp(QRegExp(filter, Qt::CaseInsensitive, QRegExp::RegExp)); 0225 m_SortModel->setFilterKeyColumn(-1); 0226 0227 isDirty = true; 0228 0229 // Expand all categories when the user use filter 0230 if (filter.length() > 0) 0231 SatListTreeView->expandAll(); 0232 else 0233 SatListTreeView->collapseAll(); 0234 } 0235 0236 void OpsSatellites::slotItemChanged(QStandardItem *item) 0237 { 0238 if (item->parent() == nullptr && !item->hasChildren()) 0239 { 0240 return; 0241 } 0242 0243 isDirty = true; 0244 0245 QModelIndex sat_index; 0246 QStandardItem *sat_item; 0247 0248 disconnect(m_Model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotItemChanged(QStandardItem*))); 0249 0250 // If a group has been (un)checked, (un)check all satellites of the group 0251 // else a satellite has been (un)checked, (un)check his group 0252 if (item->hasChildren()) 0253 { 0254 for (int i = 0; i < m_Model->rowCount(item->index()); ++i) 0255 { 0256 sat_index = m_Model->index(i, 0, item->index()); 0257 sat_item = m_Model->itemFromIndex(sat_index); 0258 0259 if (item->checkState() == Qt::Checked) 0260 sat_item->setCheckState(Qt::Checked); 0261 else 0262 sat_item->setCheckState(Qt::Unchecked); 0263 } 0264 } 0265 else 0266 { 0267 bool all_sat_checked = true; 0268 bool all_sat_unchecked = true; 0269 0270 for (int i = 0; i < item->parent()->model()->rowCount(item->parent()->index()); ++i) 0271 { 0272 sat_index = m_Model->index(i, 0, item->parent()->index()); 0273 sat_item = m_Model->itemFromIndex(sat_index); 0274 0275 if (sat_item->checkState() == Qt::Checked) 0276 all_sat_unchecked = false; 0277 else 0278 all_sat_checked = false; 0279 } 0280 0281 if (all_sat_checked) 0282 item->parent()->setCheckState(Qt::Checked); 0283 else if (all_sat_unchecked) 0284 item->parent()->setCheckState(Qt::Unchecked); 0285 else 0286 item->parent()->setCheckState(Qt::PartiallyChecked); 0287 } 0288 0289 connect(m_Model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotItemChanged(QStandardItem*))); 0290 }