File indexing completed on 2025-02-16 04:40:29
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Ralf Habacker ralf.habacker@freenet.de 0003 * SPDX-FileCopyrightText: 2023 Thomas Baumgart <tbaumgart@kde.org> 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 * 0006 * This file is part of libalkimia. 0007 */ 0008 0009 #include "alkonlinequotesource.h" 0010 0011 #include "alkonlinequotesprofile.h" 0012 0013 #include "alkonlinequotesource_p.h" 0014 0015 /** 0016 * Key to identifying "Finance::Quote" sources 0017 */ 0018 static const char *fqName = "Finance::Quote"; 0019 0020 AlkOnlineQuoteSource::AlkOnlineQuoteSource() 0021 : d(new Private) 0022 { 0023 } 0024 0025 AlkOnlineQuoteSource::AlkOnlineQuoteSource(const AlkOnlineQuoteSource &other) 0026 : d(new Private(other.d)) 0027 { 0028 } 0029 0030 AlkOnlineQuoteSource &AlkOnlineQuoteSource::operator=(AlkOnlineQuoteSource other) 0031 { 0032 swap(*this, other); 0033 return *this; 0034 } 0035 0036 AlkOnlineQuoteSource::AlkOnlineQuoteSource(const QString& name, 0037 const QString& url, 0038 const QString& idRegex, 0039 const IdSelector idBy, 0040 const QString& priceRegex, 0041 const QString& dateRegex, 0042 const QString& dateFormat, 0043 DataFormat dataFormat) 0044 : d(new Private) 0045 { 0046 d->m_name = name; 0047 d->m_url = url; 0048 d->m_idRegex = idRegex; 0049 d->m_idSelector = idBy; 0050 d->m_priceRegex = priceRegex; 0051 d->m_dataFormat = dataFormat; 0052 d->m_dateRegex = dateRegex; 0053 d->m_dateFormat = dateFormat; 0054 d->m_isGHNSSource = false; 0055 } 0056 0057 AlkOnlineQuoteSource::AlkOnlineQuoteSource(const QString &name, AlkOnlineQuotesProfile *profile) 0058 : d(new Private) 0059 { 0060 if ((profile != nullptr) && (profile->type() == AlkOnlineQuotesProfile::Type::None) && (profile->defaultQuoteSources().contains(name))) { 0061 *this = profile->defaultQuoteSources()[name]; 0062 } else { 0063 d->m_profile = profile; 0064 d->m_name = name; 0065 read(); 0066 } 0067 } 0068 0069 AlkOnlineQuoteSource AlkOnlineQuoteSource::defaultCurrencyQuoteSource(const QString& name) 0070 { 0071 return AlkOnlineQuoteSource(name, 0072 "https://fx-rate.net/%1/%2", 0073 QString(), // idregexp 0074 AlkOnlineQuoteSource::Symbol, 0075 "Today\\s+=\\s+([^<]+)", 0076 ",\\s*(\\d+\\s*[a-zA-Z]{3}\\s*\\d{4})", 0077 "%d %m %y", 0078 HTML 0079 ); 0080 } 0081 0082 AlkOnlineQuoteSource::~AlkOnlineQuoteSource() 0083 { 0084 delete d; 0085 } 0086 0087 bool AlkOnlineQuoteSource::isEmpty() 0088 { 0089 return !isValid() && !d->m_url.isEmpty(); 0090 } 0091 0092 bool AlkOnlineQuoteSource::isValid() 0093 { 0094 return !d->m_name.isEmpty(); 0095 } 0096 0097 QString AlkOnlineQuoteSource::name() const 0098 { 0099 return d->m_name; 0100 } 0101 0102 QString AlkOnlineQuoteSource::url() const 0103 { 0104 return d->m_url; 0105 } 0106 0107 QString AlkOnlineQuoteSource::idRegex() const 0108 { 0109 return d->m_idRegex; 0110 } 0111 0112 AlkOnlineQuoteSource::IdSelector AlkOnlineQuoteSource::idSelector() const 0113 { 0114 return d->m_idSelector; 0115 } 0116 0117 QString AlkOnlineQuoteSource::priceRegex() const 0118 { 0119 return d->m_priceRegex; 0120 } 0121 0122 QString AlkOnlineQuoteSource::dateRegex() const 0123 { 0124 return d->m_dateRegex; 0125 } 0126 0127 AlkOnlineQuoteSource::DataFormat AlkOnlineQuoteSource::dataFormat() const 0128 { 0129 return d->m_dataFormat; 0130 } 0131 0132 QString AlkOnlineQuoteSource::dateFormat() const 0133 { 0134 return d->m_dateFormat; 0135 } 0136 0137 /** 0138 * Returns the name of the "Finance::Quote" source. 0139 * This function only makes sense if the current source 0140 * is of the specified type. 0141 * 0142 * @return "Finance::Quote" source name 0143 */ 0144 QString AlkOnlineQuoteSource::financeQuoteName() const 0145 { 0146 return d->m_name.section(' ', 1); 0147 } 0148 0149 void AlkOnlineQuoteSource::setName(const QString &name) 0150 { 0151 d->m_name = name; 0152 } 0153 0154 void AlkOnlineQuoteSource::setUrl(const QString &url) 0155 { 0156 d->m_url = url; 0157 } 0158 0159 void AlkOnlineQuoteSource::setPriceRegex(const QString &priceRegex) 0160 { 0161 d->m_priceRegex = priceRegex; 0162 } 0163 0164 void AlkOnlineQuoteSource::setIdRegex(const QString &idRegex) 0165 { 0166 d->m_idRegex = idRegex; 0167 } 0168 0169 void AlkOnlineQuoteSource::setIdSelector(AlkOnlineQuoteSource::IdSelector idSelector) 0170 { 0171 d->m_idSelector = idSelector; 0172 } 0173 0174 /** 0175 * Set regular expression for parsing dates 0176 * 0177 * An empty string as expression disables the extraction 0178 * of the date, which is sometimes necessary, for example 0179 * if the service does not provide a complete date. 0180 * 0181 * @param date regular expression 0182 */ 0183 void AlkOnlineQuoteSource::setDateRegex(const QString &dateRegex) 0184 { 0185 d->m_dateRegex = dateRegex; 0186 } 0187 0188 void AlkOnlineQuoteSource::setDataFormat(DataFormat dataFormat) 0189 { 0190 d->m_dataFormat = dataFormat; 0191 } 0192 0193 void AlkOnlineQuoteSource::setDateFormat(const QString &dateFormat) 0194 { 0195 d->m_dateFormat = dateFormat; 0196 } 0197 0198 void AlkOnlineQuoteSource::setGHNS(bool state) 0199 { 0200 d->m_storageChanged = d->m_isGHNSSource != state; 0201 d->m_isGHNSSource = state; 0202 } 0203 0204 bool AlkOnlineQuoteSource::isGHNS() const 0205 { 0206 return d->m_isGHNSSource; 0207 } 0208 0209 bool AlkOnlineQuoteSource::isReadOnly() const 0210 { 0211 return d->m_readOnly; 0212 } 0213 0214 /** 0215 * Checks whether the current source is of type "Finance::Quote" 0216 * 0217 * @return state 0218 */ 0219 bool AlkOnlineQuoteSource::isFinanceQuote() const 0220 { 0221 return d->m_name.contains(fqName); 0222 } 0223 0224 /** 0225 * Checks whether the specified source name is of type "Finance::Quote" 0226 * 0227 * @return state 0228 */ 0229 bool AlkOnlineQuoteSource::isFinanceQuote(const QString &name) 0230 { 0231 return name.contains(fqName); 0232 } 0233 0234 QString AlkOnlineQuoteSource::ghnsWriteFileName() const 0235 { 0236 return d->ghnsWriteFilePath(); 0237 } 0238 0239 void AlkOnlineQuoteSource::setProfile(AlkOnlineQuotesProfile *profile) 0240 { 0241 d->m_profile = profile; 0242 qDebug() << "using profile" << profile->name(); 0243 } 0244 0245 AlkOnlineQuotesProfile *AlkOnlineQuoteSource::profile() 0246 { 0247 return d->m_profile; 0248 } 0249 0250 AlkOnlineQuotesProfile *AlkOnlineQuoteSource::profile() const 0251 { 0252 return d->m_profile; 0253 } 0254 0255 bool AlkOnlineQuoteSource::read() 0256 { 0257 if (d->m_profile->hasGHNSSupport()) { 0258 if (d->readFromGHNSFile()) { 0259 return true; 0260 } 0261 } 0262 return d->read(); 0263 } 0264 0265 bool AlkOnlineQuoteSource::write() 0266 { 0267 bool result = false; 0268 // check if type has been changedd->isGHNS 0269 if (d->m_profile->hasGHNSSupport() && d->m_isGHNSSource) { 0270 result = d->writeToGHNSFile(); 0271 if (d->m_storageChanged) 0272 d->remove(); 0273 return result; 0274 } else { 0275 if (d->m_storageChanged && d->m_profile->quoteSources().contains(d->m_name)) 0276 d->m_name.append(".local"); 0277 result = d->write(); 0278 if (d->m_profile->hasGHNSSupport() && d->m_storageChanged) { 0279 d->removeGHNSFile(); 0280 } 0281 } 0282 d->m_storageChanged = false; 0283 return result; 0284 } 0285 0286 void AlkOnlineQuoteSource::rename(const QString &name) 0287 { 0288 if (d->m_profile->type() != AlkOnlineQuotesProfile::Type::None) { 0289 remove(); 0290 d->m_name = name; 0291 write(); 0292 } else 0293 d->m_name = name; 0294 } 0295 0296 void AlkOnlineQuoteSource::remove() 0297 { 0298 if (d->m_profile->hasGHNSSupport() && d->m_isGHNSSource) { 0299 d->removeGHNSFile(); 0300 } else if (d->m_profile->type() != AlkOnlineQuotesProfile::Type::None) { 0301 d->remove(); 0302 } 0303 } 0304 0305 const QString &AlkOnlineQuoteSource::defaultId() const 0306 { 0307 return d->m_defaultId; 0308 } 0309 0310 void AlkOnlineQuoteSource::setDefaultId(const QString &defaultId) 0311 { 0312 d->m_defaultId = defaultId; 0313 } 0314 0315 bool AlkOnlineQuoteSource::requiresTwoIdentifier() const 0316 { 0317 return url().contains("%2"); 0318 }