File indexing completed on 2024-04-28 15:11:24
0001 /* 0002 SPDX-FileCopyrightText: 2012 Samikshan Bairagya <samikshan@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "skyobjitem.h" 0008 0009 #include "catalogobject.h" 0010 #include "ksfilereader.h" 0011 #include "kspaths.h" 0012 #include "ksplanetbase.h" 0013 #include "kstarsdata.h" 0014 #include "ksutils.h" 0015 0016 #include <QDirIterator> 0017 0018 SkyObjItem::SkyObjItem(SkyObject *so) 0019 : m_Name(so->name()), m_LongName(so->longname()), m_TypeName(so->typeName()), m_So(so) 0020 { 0021 switch (so->type()) 0022 { 0023 case SkyObject::PLANET: 0024 case SkyObject::MOON: 0025 m_Type = Planet; 0026 break; 0027 case SkyObject::STAR: 0028 case SkyObject::CATALOG_STAR: 0029 case SkyObject::MULT_STAR: 0030 m_Type = Star; 0031 break; 0032 case SkyObject::CONSTELLATION: 0033 case SkyObject::ASTERISM: 0034 m_Type = Constellation; 0035 break; 0036 case SkyObject::GALAXY: 0037 m_Type = Galaxy; 0038 break; 0039 case SkyObject::OPEN_CLUSTER: 0040 case SkyObject::GLOBULAR_CLUSTER: 0041 case SkyObject::GALAXY_CLUSTER: 0042 m_Type = Cluster; 0043 break; 0044 case SkyObject::PLANETARY_NEBULA: 0045 case SkyObject::SUPERNOVA_REMNANT: 0046 case SkyObject::GASEOUS_NEBULA: 0047 case SkyObject::DARK_NEBULA: 0048 m_Type = Nebula; 0049 break; 0050 case SkyObject::SUPERNOVA: 0051 m_Type = Supernova; 0052 } 0053 0054 setPosition(m_So); 0055 } 0056 0057 QVariant SkyObjItem::data(int role) 0058 { 0059 switch (role) 0060 { 0061 case DispNameRole: 0062 return getDescName(); 0063 case DispImageRole: 0064 return getImageURL(true); 0065 case DispSummaryRole: 0066 return getSummary(true); 0067 case CategoryRole: 0068 return getType(); 0069 case CategoryNameRole: 0070 return getTypeName(); 0071 default: 0072 return QVariant(); 0073 } 0074 } 0075 0076 ///Moved to skyobjlistmodel.cpp 0077 /* 0078 QHash<int, QByteArray> SkyObjItem::roleNames() const 0079 { 0080 QHash<int, QByteArray> roles; 0081 roles[DispNameRole] = "dispName"; 0082 roles[CategoryRole] = "type"; 0083 roles[CategoryNameRole] = "typeName"; 0084 return roles; 0085 } 0086 */ 0087 0088 void SkyObjItem::setPosition(SkyObject *so) 0089 { 0090 double altitude; 0091 dms azimuth; 0092 if (so->type() == SkyObject::SATELLITE) 0093 { 0094 altitude = so->alt().Degrees(); 0095 azimuth = so->az(); 0096 } 0097 else 0098 { 0099 KStarsData *data = KStarsData::Instance(); 0100 KStarsDateTime ut = data->geo()->LTtoUT( 0101 KStarsDateTime(QDateTime::currentDateTime().toLocalTime())); 0102 SkyPoint sp = so->recomputeCoords(ut, data->geo()); 0103 0104 //check altitude of object at this time. 0105 sp.EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0106 altitude = sp.alt().Degrees(); 0107 azimuth = sp.az(); 0108 } 0109 0110 double rounded_altitude = (int)(altitude / 5.0) * 5.0; 0111 0112 if (rounded_altitude <= 0) 0113 m_Position = "<span style='color:red'>" + 0114 xi18n("NOT VISIBLE: About %1 degrees below the %2 horizon", 0115 -rounded_altitude, KSUtils::toDirectionString(azimuth)) + 0116 "</span>"; 0117 else 0118 m_Position = "<span style='color:yellow'>" + 0119 xi18n("Now visible: About %1 degrees above the %2 horizon", 0120 rounded_altitude, KSUtils::toDirectionString(azimuth)) + 0121 "</span>"; 0122 } 0123 0124 QString findImage(const QString &prefix, const SkyObject &obj, const QString &suffix) 0125 { 0126 static const auto base = 0127 KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation); 0128 QDirIterator search( 0129 base, 0130 QStringList() << prefix + obj.name().toLower().remove(' ').remove('/') + suffix, 0131 QDir::Files, QDirIterator::Subdirectories); 0132 0133 return search.hasNext() ? QUrl::fromLocalFile(search.next()).url() : ""; 0134 } 0135 QString SkyObjItem::getImageURL(bool preferThumb) const 0136 { 0137 const auto &thumbURL = findImage("thumb-", *m_So, ".png"); 0138 0139 const auto &fullSizeURL = findImage("image-", *m_So, ".png"); 0140 const auto &wikiImageURL = 0141 QUrl::fromLocalFile(KSPaths::locate(QStandardPaths::AppLocalDataLocation, 0142 "descriptions/wikiImage-" + 0143 m_So->name().toLower().remove(' ') + 0144 ".png")) 0145 .url(); 0146 QString XPlanetURL = 0147 QUrl::fromLocalFile(KSPaths::locate(QStandardPaths::AppLocalDataLocation, 0148 "xplanet/" + m_So->name() + ".png")) 0149 .url(); 0150 0151 //First try to return the preferred file 0152 if (!thumbURL.isEmpty() && preferThumb) 0153 return thumbURL; 0154 if (!fullSizeURL.isEmpty() && (!preferThumb)) 0155 return fullSizeURL; 0156 0157 //If that fails, try to return the large image first, then the thumb, and then if it is a planet, the xplanet image. Finally if all else fails, the wiki image. 0158 QString fname = fullSizeURL; 0159 0160 if (fname.isEmpty()) 0161 { 0162 fname = thumbURL; 0163 } 0164 if (fname.isEmpty() && m_Type == Planet) 0165 { 0166 fname = XPlanetURL; 0167 } 0168 if (fname.isEmpty()) 0169 { 0170 fname = wikiImageURL; 0171 } 0172 return fname; 0173 } 0174 0175 QString SkyObjItem::getSummary(bool includeDescription) const 0176 { 0177 if (includeDescription) 0178 { 0179 QString description = loadObjectDescription(); 0180 if(description.indexOf(".") > 0) //This will shorten the description in the list to just a sentence, whereas in the larger space of the Object Information Summary, it is a full paragraph. 0181 return m_So->typeName() + "<BR>" + getRADE() + "<BR>" + getAltAz() + "<BR><BR>" + description.left(description.indexOf(".") + 1); 0182 else 0183 return m_So->typeName() + "<BR>" + getRADE() + "<BR>" + getAltAz() + "<BR><BR>" + description; 0184 } 0185 else 0186 return m_So->typeName() + "<BR>" + getRADE() + "<BR>" + getAltAz(); 0187 } 0188 0189 QString SkyObjItem::getSurfaceBrightness() const 0190 { 0191 /** Surface Brightness is applicable only for extended light sources like 0192 * Deep-Sky Objects. Here we use the formula SB = m + log10(a*b/4) 0193 * where m is the magnitude of the sky-object. a and b are the major and minor 0194 * axis lengths of the objects respectively in arcminutes. SB is the surface 0195 * brightness obtained in mag * arcminutes^-2 0196 */ 0197 0198 auto *dso = dynamic_cast<CatalogObject*>(m_So); 0199 float SB = m_So->mag(); 0200 0201 if (dso != nullptr) 0202 SB += 2.5 * log10(dso->a() * dso->b() / 4); 0203 0204 switch (getType()) 0205 { 0206 case Galaxy: 0207 case Nebula: 0208 return QLocale().toString(SB, 'f', 2) + "<BR> (mag/arcmin^2)"; 0209 default: 0210 return QString(" --"); // Not applicable for other sky-objects 0211 } 0212 } 0213 0214 QString SkyObjItem::getSize() const 0215 { 0216 switch (getType()) 0217 { 0218 case Galaxy: 0219 case Cluster: 0220 case Nebula: 0221 return QLocale().toString(((CatalogObject *)m_So)->a(), 'f', 2) + "\""; 0222 case Planet: 0223 return QLocale().toString(((KSPlanetBase *)m_So)->angSize(), 'f', 2) + "\""; 0224 default: 0225 return QString(" --"); 0226 } 0227 } 0228 0229 inline QString SkyObjItem::loadObjectDescription() const 0230 { 0231 QFile file; 0232 QString fname = "description-" + getName().toLower().remove(' ') + ".html"; 0233 //determine filename in local user KDE directory tree. 0234 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("descriptions/" + fname)); 0235 0236 if (file.exists()) 0237 { 0238 if (file.open(QIODevice::ReadOnly)) 0239 { 0240 QTextStream in(&file); 0241 QString line; 0242 line = in.readLine(); //This should only read the description since the source is on the next line 0243 file.close(); 0244 return line; 0245 } 0246 } 0247 return getTypeName(); 0248 } 0249 0250 QString SkyObjItem::getRADE() const 0251 { 0252 return "RA: " + m_So->ra().toHMSString() + "<BR>DE: " + m_So->dec().toDMSString(); 0253 } 0254 0255 QString SkyObjItem::getAltAz() const 0256 { 0257 return "Alt: " + QString::number(m_So->alt().Degrees(), 'f', 2) + 0258 ", Az: " + QString::number(m_So->az().Degrees(), 'f', 2); 0259 } 0260 0261 float SkyObjItem::getMagnitude() const 0262 { 0263 return m_So->mag(); 0264 }