File indexing completed on 2024-04-21 03:58:32
0001 /* 0002 * SPDX-FileCopyrightText: 2007-2009 Petri Damstén <damu@iki.fi> 0003 * SPDX-FileCopyrightText: 2014 John Layt <jlayt@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "unitcategory.h" 0009 #include "unit_p.h" 0010 #include "unitcategory_p.h" 0011 0012 #include <KLocalizedString> 0013 0014 #include <QNetworkReply> 0015 0016 #include <QNetworkAccessManager> 0017 #include <QStandardPaths> 0018 0019 namespace KUnitConversion 0020 { 0021 UnitCategoryPrivate::UnitCategoryPrivate() 0022 : m_id(InvalidCategory) 0023 { 0024 } 0025 0026 UnitCategoryPrivate::UnitCategoryPrivate(CategoryId id, const QString &name, const QString &description) 0027 : m_id(id) 0028 , m_name(name) 0029 , m_description(description) 0030 { 0031 } 0032 0033 UnitCategoryPrivate::~UnitCategoryPrivate() 0034 { 0035 } 0036 0037 UnitCategoryPrivate *UnitCategoryPrivate::clone() 0038 { 0039 return new UnitCategoryPrivate(*this); 0040 } 0041 0042 bool UnitCategoryPrivate::operator==(const UnitCategoryPrivate &other) const 0043 { 0044 return (m_id == other.m_id); 0045 } 0046 0047 bool UnitCategoryPrivate::operator!=(const UnitCategoryPrivate &other) const 0048 { 0049 return !(*this == other); 0050 } 0051 0052 QNetworkAccessManager *UnitCategoryPrivate::nam() 0053 { 0054 static std::unique_ptr<QNetworkAccessManager> s_nam; 0055 if (!s_nam) { 0056 s_nam = std::make_unique<QNetworkAccessManager>(); 0057 s_nam->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); 0058 s_nam->setStrictTransportSecurityEnabled(true); 0059 s_nam->enableStrictTransportSecurityStore(true, QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/org.kde.unitconversion/hsts/")); 0060 } 0061 return s_nam.get(); 0062 } 0063 0064 Value UnitCategoryPrivate::convert(const Value &value, const Unit &toUnit) 0065 { 0066 qreal v = value.unit().toDefault(value.number()); 0067 return Value(toUnit.fromDefault(v), toUnit); 0068 } 0069 0070 UnitCategory::UnitCategory() 0071 : d(nullptr) 0072 { 0073 } 0074 0075 UnitCategory::UnitCategory(UnitCategoryPrivate *dd) 0076 : d(dd) 0077 { 0078 } 0079 0080 UnitCategory::UnitCategory(const UnitCategory &other) 0081 : d(other.d) 0082 { 0083 } 0084 0085 UnitCategory::~UnitCategory() 0086 { 0087 } 0088 0089 UnitCategory &UnitCategory::operator=(const UnitCategory &other) 0090 { 0091 d = other.d; 0092 return *this; 0093 } 0094 0095 UnitCategory &UnitCategory::operator=(UnitCategory &&other) 0096 { 0097 d.swap(other.d); 0098 return *this; 0099 } 0100 0101 bool UnitCategory::operator==(const UnitCategory &other) const 0102 { 0103 if (d && other.d) { 0104 return (*d == *other.d); 0105 } else { 0106 return (d == other.d); 0107 } 0108 } 0109 0110 bool UnitCategory::operator!=(const UnitCategory &other) const 0111 { 0112 if (d && other.d) { 0113 return (*d != *other.d); 0114 } else { 0115 return (d != other.d); 0116 } 0117 } 0118 0119 bool UnitCategory::isNull() const 0120 { 0121 return !d; 0122 } 0123 0124 CategoryId UnitCategory::id() const 0125 { 0126 if (d) { 0127 return d->m_id; 0128 } 0129 return InvalidCategory; 0130 } 0131 0132 QList<Unit> UnitCategory::units() const 0133 { 0134 if (d) { 0135 return d->m_units; 0136 } 0137 return QList<Unit>(); 0138 } 0139 0140 QList<Unit> UnitCategory::mostCommonUnits() const 0141 { 0142 if (d) { 0143 return d->m_mostCommonUnits; 0144 } 0145 return QList<Unit>(); 0146 } 0147 0148 QStringList UnitCategory::allUnits() const 0149 { 0150 if (d) { 0151 return d->m_unitMap.keys(); 0152 } 0153 return QStringList(); 0154 } 0155 0156 bool UnitCategory::hasUnit(const QString &unit) const 0157 { 0158 if (d) { 0159 return d->m_unitMap.contains(unit); 0160 } 0161 return false; 0162 } 0163 0164 Value UnitCategory::convert(const Value &value, const QString &toUnit) const 0165 { 0166 if (d && (toUnit.isEmpty() || d->m_unitMap.contains(toUnit)) && value.unit().isValid()) { 0167 Unit to = toUnit.isEmpty() ? defaultUnit() : d->m_unitMap[toUnit]; 0168 return convert(value, to); 0169 } 0170 return Value(); 0171 } 0172 0173 Value UnitCategory::convert(const Value &value, UnitId toUnit) const 0174 { 0175 if (d && d->m_idMap.contains(toUnit) && value.unit().isValid()) { 0176 return convert(value, d->m_idMap[toUnit]); 0177 } 0178 return Value(); 0179 } 0180 0181 Value UnitCategory::convert(const Value &value, const Unit &toUnit) const 0182 { 0183 if (d && !toUnit.isNull()) { 0184 return d->convert(value, toUnit); 0185 } 0186 return Value(); 0187 } 0188 0189 Unit UnitCategory::unit(const QString &s) const 0190 { 0191 if (d) { 0192 return d->m_unitMap.value(s); 0193 } 0194 return Unit(); 0195 } 0196 0197 Unit UnitCategory::unit(UnitId unitId) const 0198 { 0199 if (d && d->m_idMap.contains(unitId)) { 0200 return d->m_idMap[unitId]; 0201 } 0202 return Unit(); 0203 } 0204 0205 QString UnitCategory::name() const 0206 { 0207 if (d) { 0208 return d->m_name; 0209 } 0210 return QString(); 0211 } 0212 0213 Unit UnitCategory::defaultUnit() const 0214 { 0215 if (d) { 0216 return d->m_defaultUnit; 0217 } 0218 return Unit(); 0219 } 0220 0221 QString UnitCategory::description() const 0222 { 0223 if (d) { 0224 return d->m_description; 0225 } 0226 return QString(); 0227 } 0228 0229 void UnitCategoryPrivate::addDefaultUnit(const Unit &unit) 0230 { 0231 addCommonUnit(unit); 0232 m_defaultUnit = unit; 0233 } 0234 0235 void UnitCategoryPrivate::addCommonUnit(const Unit &unit) 0236 { 0237 addUnit(unit); 0238 m_mostCommonUnits.append(unit); 0239 } 0240 0241 void UnitCategoryPrivate::addUnit(const Unit &unit) 0242 { 0243 // ### this is emulating a weak_ptr to break a reference cycle between Unit and UnitCategory 0244 // ### even without that, this is slicing the polymorphic part of UnitCategory 0245 // this only works by chance as apart from the ctors those parts contain no logic or data it seems 0246 unit.d->m_category = this; 0247 const QStringList list = unit.d->m_matchString.split(QLatin1Char(';'), Qt::SkipEmptyParts); 0248 Q_ASSERT_X(!list.isEmpty(), 0249 "UnitCategoryPrivate::addUnit", 0250 QLatin1String("Empty match string for unit symbol: '%1' '%2' - fix translation?").arg(unit.symbol(), unit.description()).toUtf8().constData()); 0251 0252 for (const QString &name : list) { 0253 m_unitMap[name] = unit; 0254 } 0255 m_idMap[unit.id()] = unit; 0256 m_units.append(unit); 0257 } 0258 0259 bool UnitCategory::hasOnlineConversionTable() const 0260 { 0261 return d->hasOnlineConversionTable(); 0262 } 0263 0264 UpdateJob* UnitCategory::syncConversionTable(std::chrono::seconds updateSkipPeriod) 0265 { 0266 return d->syncConversionTable(updateSkipPeriod); 0267 } 0268 0269 0270 UpdateJob::UpdateJob(QNetworkReply *reply) 0271 : d(reply) 0272 { 0273 connect(d, &QNetworkReply::finished, this, &UpdateJob::finished); 0274 connect(d, &QNetworkReply::finished, this, &QObject::deleteLater); 0275 } 0276 0277 UpdateJob::~UpdateJob() = default; 0278 0279 } 0280 0281 #include "moc_unitcategory.cpp"