File indexing completed on 2025-01-19 09:45:58
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 "flagcomponent.h" 0008 0009 #include "ksfilereader.h" 0010 #include "kstarsdata.h" 0011 #include "Options.h" 0012 #ifdef KSTARS_LITE 0013 #include "skymaplite.h" 0014 #else 0015 #include "skymap.h" 0016 #endif 0017 #include "skypainter.h" 0018 #include "auxiliary/kspaths.h" 0019 #include "projections/projector.h" 0020 #include "skyobjects/skypoint.h" 0021 0022 #include <KLocalizedString> 0023 0024 #include <QDir> 0025 #include <QtMath> 0026 #include <QStandardPaths> 0027 0028 FlagComponent::FlagComponent(SkyComposite *parent) : PointListComponent(parent) 0029 { 0030 // Add the default flag images to available images list 0031 m_Names.append(i18n("No icon")); 0032 m_Images.append(QImage()); 0033 m_Names.append(i18n("Default")); 0034 m_Images.append(QImage(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "defaultflag.gif"))); 0035 0036 QDir appDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); 0037 appDir.setNameFilters(QStringList() << "flag*"); 0038 // Add all other images found in user appdata directory 0039 for (auto &item : appDir.entryList()) 0040 { 0041 QString path = appDir.absoluteFilePath(item); 0042 m_Images.append(QImage(path)); 0043 0044 QString fileName = item.replace(QRegExp("\\.[^.]*$"), QString()).replace(QRegExp("^flag"), QString()).replace('_', ' '); 0045 0046 m_Names.append(fileName); 0047 } 0048 0049 loadFromFile(); 0050 } 0051 0052 void FlagComponent::draw(SkyPainter *skyp) 0053 { 0054 // Return if flags must not be draw 0055 if (!selected()) 0056 return; 0057 0058 // Return if no images are available 0059 if (m_Names.size() < 1) 0060 return; 0061 0062 // Draw all flags 0063 skyp->drawFlags(); 0064 } 0065 0066 bool FlagComponent::selected() 0067 { 0068 return Options::showFlags(); 0069 } 0070 0071 void FlagComponent::loadFromFile() 0072 { 0073 bool imageFound = false; 0074 QList<QStringList> flagList; 0075 KStarsData::Instance()->userdb()->GetAllFlags(flagList); 0076 0077 for (auto &flagEntry : flagList) 0078 { 0079 // Read coordinates 0080 dms r(flagEntry.at(0)); 0081 dms d(flagEntry.at(1)); 0082 0083 m_EpochCoords.append(qMakePair(r.Degrees(), d.Degrees())); 0084 0085 std::shared_ptr<SkyPoint> flagPoint(new SkyPoint(r, d)); 0086 0087 // Convert to JNow 0088 toJ2000(flagPoint.get(), flagEntry.at(2)); 0089 0090 flagPoint->updateCoordsNow(KStarsData::Instance()->updateNum()); 0091 0092 pointList().append(std::move(flagPoint)); 0093 0094 // Read epoch 0095 m_Epoch.append(flagEntry.at(2)); 0096 0097 // Read image name 0098 QString str = flagEntry.at(3); 0099 str = str.replace('_', ' '); 0100 for (int i = 0; i < m_Names.size(); ++i) 0101 { 0102 if (str == m_Names.at(i)) 0103 { 0104 m_FlagImages.append(i); 0105 imageFound = true; 0106 } 0107 } 0108 0109 // If the image specified in db does not exist, 0110 // use the default one 0111 if (!imageFound) 0112 m_FlagImages.append(0); 0113 0114 imageFound = false; 0115 0116 // If there is no label, use an empty string, red color and continue. 0117 m_Labels.append(flagEntry.at(4)); 0118 0119 // color label 0120 0121 QRegExp rxLabelColor("^#[a-fA-F0-9]{6}$"); 0122 if (rxLabelColor.exactMatch(flagEntry.at(5))) 0123 { 0124 m_LabelColors.append(QColor(flagEntry.at(5))); 0125 } 0126 else 0127 { 0128 m_LabelColors.append(QColor("red")); 0129 } 0130 } 0131 } 0132 0133 void FlagComponent::saveToFile() 0134 { 0135 /* 0136 TODO: This is a really bad way of storing things. Adding one flag shouldn't 0137 involve writing a new file/table every time. Needs fixing. 0138 */ 0139 KStarsData::Instance()->userdb()->DeleteAllFlags(); 0140 0141 for (int i = 0; i < size(); ++i) 0142 { 0143 KStarsData::Instance()->userdb()->AddFlag(QString::number(epochCoords(i).first), 0144 QString::number(epochCoords(i).second), epoch(i), 0145 imageName(i).replace(' ', '_'), label(i), labelColor(i).name()); 0146 } 0147 } 0148 0149 void FlagComponent::add(const SkyPoint &flagPoint, QString epoch, QString image, QString label, QColor labelColor) 0150 { 0151 //JM 2015-02-21: Insert original coords in list and convert skypint to JNow 0152 // JM 2017-02-07: Discard above! We add RAW epoch coordinates to list. 0153 // If not J2000, we convert to J2000 0154 m_EpochCoords.append(qMakePair(flagPoint.ra().Degrees(), flagPoint.dec().Degrees())); 0155 0156 std::shared_ptr<SkyPoint> newFlagPoint(new SkyPoint(flagPoint.ra(), flagPoint.dec())); 0157 0158 toJ2000(newFlagPoint.get(), epoch); 0159 0160 newFlagPoint->updateCoordsNow(KStarsData::Instance()->updateNum()); 0161 0162 pointList().append(std::move(newFlagPoint)); 0163 m_Epoch.append(epoch); 0164 0165 for (int i = 0; i < m_Names.size(); i++) 0166 { 0167 if (image == m_Names.at(i)) 0168 m_FlagImages.append(i); 0169 } 0170 0171 m_Labels.append(label); 0172 m_LabelColors.append(labelColor); 0173 } 0174 0175 void FlagComponent::remove(int index) 0176 { 0177 // check if flag of required index exists 0178 if (index > pointList().size() - 1) 0179 { 0180 return; 0181 } 0182 0183 pointList().removeAt(index); 0184 m_EpochCoords.removeAt(index); 0185 m_Epoch.removeAt(index); 0186 m_FlagImages.removeAt(index); 0187 m_Labels.removeAt(index); 0188 m_LabelColors.removeAt(index); 0189 0190 // request SkyMap update 0191 #ifndef KSTARS_LITE 0192 SkyMap::Instance()->forceUpdate(); 0193 #endif 0194 } 0195 0196 void FlagComponent::updateFlag(int index, const SkyPoint &flagPoint, QString epoch, QString image, QString label, 0197 QColor labelColor) 0198 { 0199 if (index < 0 || index > pointList().size() - 1) 0200 return; 0201 0202 std::shared_ptr<SkyPoint> existingFlag = pointList().at(index); 0203 0204 existingFlag->setRA0(flagPoint.ra()); 0205 existingFlag->setDec0(flagPoint.dec()); 0206 0207 // If epoch not J2000, to convert to J2000 0208 toJ2000(existingFlag.get(), epoch); 0209 0210 existingFlag->updateCoordsNow(KStarsData::Instance()->updateNum()); 0211 0212 m_EpochCoords.replace(index, qMakePair(flagPoint.ra().Degrees(), flagPoint.dec().Degrees())); 0213 0214 m_Epoch.replace(index, epoch); 0215 0216 for (int i = 0; i < m_Names.size(); i++) 0217 { 0218 if (image == m_Names.at(i)) 0219 m_FlagImages.replace(index, i); 0220 } 0221 0222 m_Labels.replace(index, label); 0223 m_LabelColors.replace(index, labelColor); 0224 } 0225 0226 QStringList FlagComponent::getNames() 0227 { 0228 return m_Names; 0229 } 0230 0231 int FlagComponent::size() 0232 { 0233 return pointList().size(); 0234 } 0235 0236 QString FlagComponent::epoch(int index) 0237 { 0238 if (index > m_Epoch.size() - 1) 0239 { 0240 return QString(); 0241 } 0242 0243 return m_Epoch.at(index); 0244 } 0245 0246 QString FlagComponent::label(int index) 0247 { 0248 if (index > m_Labels.size() - 1) 0249 { 0250 return QString(); 0251 } 0252 0253 return m_Labels.at(index); 0254 } 0255 0256 QColor FlagComponent::labelColor(int index) 0257 { 0258 if (index > m_LabelColors.size() - 1) 0259 { 0260 return QColor(); 0261 } 0262 0263 return m_LabelColors.at(index); 0264 } 0265 0266 QImage FlagComponent::image(int index) 0267 { 0268 if (index > m_FlagImages.size() - 1) 0269 { 0270 return QImage(); 0271 } 0272 0273 if (m_FlagImages.at(index) > m_Images.size() - 1) 0274 { 0275 return QImage(); 0276 } 0277 0278 return m_Images.at(m_FlagImages.at(index)); 0279 } 0280 0281 QString FlagComponent::imageName(int index) 0282 { 0283 if (index > m_FlagImages.size() - 1) 0284 { 0285 return QString(); 0286 } 0287 0288 if (m_FlagImages.at(index) > m_Names.size() - 1) 0289 { 0290 return QString(); 0291 } 0292 0293 return m_Names.at(m_FlagImages.at(index)); 0294 } 0295 0296 QList<QImage> FlagComponent::imageList() 0297 { 0298 return m_Images; 0299 } 0300 0301 QList<int> FlagComponent::getFlagsNearPix(SkyPoint *point, int pixelRadius) 0302 { 0303 #ifdef KSTARS_LITE 0304 const Projector *proj = SkyMapLite::Instance()->projector(); 0305 #else 0306 const Projector *proj = SkyMap::Instance()->projector(); 0307 #endif 0308 QPointF pos = proj->toScreen(point); 0309 QList<int> retVal; 0310 int ptr = 0; 0311 0312 for (auto &cp : pointList()) 0313 { 0314 if (std::isnan(cp->ra().Degrees()) || std::isnan(cp->dec().Degrees())) 0315 continue; 0316 cp->EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat()); 0317 QPointF pos2 = proj->toScreen(cp.get()); 0318 int dx = (pos2 - pos).x(); 0319 int dy = (pos2 - pos).y(); 0320 0321 if (qSqrt(dx * dx + dy * dy) <= pixelRadius) 0322 { 0323 //point is inside pixelRadius circle 0324 retVal.append(ptr); 0325 } 0326 0327 ptr++; 0328 } 0329 0330 return retVal; 0331 } 0332 0333 QImage FlagComponent::imageList(int index) 0334 { 0335 if (index < 0 || index > m_Images.size() - 1) 0336 { 0337 return QImage(); 0338 } 0339 0340 return m_Images.at(index); 0341 } 0342 0343 void FlagComponent::toJ2000(SkyPoint *p, QString epoch) 0344 { 0345 KStarsDateTime dt; 0346 dt.setFromEpoch(epoch); 0347 0348 if (dt.djd() == J2000) 0349 return; 0350 0351 p->catalogueCoord(dt.djd()); 0352 0353 // Store J2000 coords in RA0, DEC0 0354 p->setRA0(p->ra()); 0355 p->setDec0(p->dec()); 0356 } 0357 0358 QPair<double, double> FlagComponent::epochCoords(int index) 0359 { 0360 if (index > m_FlagImages.size() - 1) 0361 { 0362 QPair<double, double> coord = qMakePair(0, 0); 0363 return coord; 0364 } 0365 0366 return m_EpochCoords.at(index); 0367 } 0368 0369 void FlagComponent::update(KSNumbers *num) 0370 { 0371 if (!selected()) 0372 return; 0373 KStarsData *data = KStarsData::Instance(); 0374 0375 for (auto &p : pointList()) 0376 { 0377 if (num) 0378 p->updateCoordsNow(num); 0379 0380 p->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0381 } 0382 }