Warning, file /plasma/kdeplasma-addons/applets/weather/plugin/locationlistmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2009 Petri Damstén <damu@iki.fi> 0003 * SPDX-FileCopyrightText: 2016, 2018 Friedrich W. H. Kossebau <kossebau@kde.org> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "locationlistmodel.h" 0009 0010 #include <Plasma/DataContainer> 0011 0012 #include <KLocalizedString> 0013 0014 #include <QDebug> 0015 0016 WeatherValidator::WeatherValidator(Plasma::DataEngine *weatherDataengine, const QString &ionName, QObject *parent) 0017 : QObject(parent) 0018 , m_weatherDataEngine(weatherDataengine) 0019 , m_ionName(ionName) 0020 { 0021 } 0022 0023 WeatherValidator::~WeatherValidator() = default; 0024 0025 void WeatherValidator::validate(const QString &location) 0026 { 0027 const QString validationSource = m_ionName + QLatin1String("|validate|") + location; 0028 0029 m_weatherDataEngine->connectSource(validationSource, this); 0030 } 0031 0032 void WeatherValidator::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) 0033 { 0034 QMap<QString, QString> locationSources; 0035 0036 m_weatherDataEngine->disconnectSource(source, this); 0037 0038 const auto validationResult = data[QStringLiteral("validate")].toString().split(QLatin1Char('|')); 0039 0040 if (validationResult.size() < 2) { 0041 Q_EMIT error(i18n("Cannot find '%1' using %2.", source, m_ionName)); 0042 } else if (validationResult[1] == QLatin1String("valid") && validationResult.size() > 2) { 0043 const QString weatherSourcePrefix = validationResult[0] + QLatin1String("|weather|"); 0044 int i = 3; 0045 0046 const int lastFieldIndex = validationResult.size() - 1; 0047 while (i < lastFieldIndex) { 0048 if (validationResult[i] == QLatin1String("place")) { 0049 const QString &name = validationResult[i + 1]; 0050 QString locationSource; 0051 if (i + 2 < lastFieldIndex && validationResult[i + 2] == QLatin1String("extra")) { 0052 const QString &id = validationResult[i + 3]; 0053 locationSource = weatherSourcePrefix + name + QLatin1Char('|') + id; 0054 i += 4; 0055 } else { 0056 locationSource = weatherSourcePrefix + name; 0057 i += 2; 0058 } 0059 locationSources.insert(name, locationSource); 0060 } else { 0061 ++i; 0062 } 0063 } 0064 0065 } else if (validationResult[1] == QLatin1String("timeout")) { 0066 Q_EMIT error(i18n("Connection to %1 weather server timed out.", m_ionName)); 0067 } else { 0068 const QString searchTerm = validationResult.size() > 3 ? validationResult[3] : source; 0069 Q_EMIT error(i18n("Cannot find '%1' using %2.", searchTerm, m_ionName)); 0070 } 0071 0072 Q_EMIT finished(locationSources); 0073 } 0074 0075 LocationListModel::LocationListModel(QObject *parent) 0076 : QAbstractListModel(parent) 0077 , m_validatingInput(false) 0078 , m_checkedInCount(0) 0079 { 0080 } 0081 0082 QVariant LocationListModel::data(const QModelIndex &index, int role) const 0083 { 0084 if (!index.isValid() || index.row() >= m_locations.size()) { 0085 return QVariant(); 0086 } 0087 0088 switch (role) { 0089 case Qt::DisplayRole: 0090 return nameForListIndex(index.row()); 0091 } 0092 0093 return QVariant(); 0094 } 0095 0096 int LocationListModel::rowCount(const QModelIndex &index) const 0097 { 0098 if (!index.isValid()) { 0099 return m_locations.size(); 0100 } 0101 0102 return 0; 0103 } 0104 0105 bool LocationListModel::isValidatingInput() const 0106 { 0107 return m_validatingInput; 0108 } 0109 0110 QString LocationListModel::valueForListIndex(int listIndex) const 0111 { 0112 if (0 <= listIndex && listIndex < m_locations.count()) { 0113 return m_locations.at(listIndex).value; 0114 } 0115 0116 return QString(); 0117 } 0118 0119 QString LocationListModel::nameForListIndex(int listIndex) const 0120 { 0121 if (0 <= listIndex && listIndex < m_locations.count()) { 0122 const LocationItem &item = m_locations.at(listIndex); 0123 if (!item.weatherService.isEmpty()) { 0124 return i18nc("A weather station location and the weather service it comes from", 0125 "%1 (%2)", 0126 item.weatherStation, 0127 m_serviceCodeToDisplayName.value(item.weatherService, item.weatherService)); 0128 } 0129 } 0130 0131 return QString(); 0132 } 0133 0134 void LocationListModel::searchLocations(const QString &searchString, const QStringList &services) 0135 { 0136 m_checkedInCount = 0; 0137 0138 // reset current validators 0139 qDeleteAll(m_validators); 0140 m_validators.clear(); 0141 0142 m_searchString = searchString; 0143 0144 if (!m_validatingInput) { 0145 m_validatingInput = true; 0146 Q_EMIT validatingInputChanged(true); 0147 } 0148 0149 beginResetModel(); 0150 m_locations.clear(); 0151 endResetModel(); 0152 0153 if (searchString.isEmpty()) { 0154 completeSearch(); 0155 return; 0156 } 0157 0158 Plasma::DataEngine *dataengine = dataEngine(QStringLiteral("weather")); 0159 0160 const QVariantList plugins = dataengine->containerForSource(QStringLiteral("ions"))->data().values(); 0161 for (const QVariant &plugin : plugins) { 0162 const QStringList pluginInfo = plugin.toString().split(QLatin1Char('|')); 0163 if (pluginInfo.count() > 1) { 0164 const QString &ionId = pluginInfo[1]; 0165 if (!services.contains(ionId)) { 0166 continue; 0167 } 0168 0169 m_serviceCodeToDisplayName[pluginInfo[1]] = pluginInfo[0]; 0170 0171 // qDebug() << "ion: " << pluginInfo[0] << pluginInfo[1]; 0172 // d->ions.insert(pluginInfo[1], pluginInfo[0]); 0173 0174 auto *validator = new WeatherValidator(dataengine, ionId, this); 0175 connect(validator, &WeatherValidator::error, this, &LocationListModel::validatorError); 0176 connect(validator, &WeatherValidator::finished, this, &LocationListModel::addSources); 0177 0178 m_validators.append(validator); 0179 } 0180 } 0181 0182 for (auto *validator : std::as_const(m_validators)) { 0183 validator->validate(m_searchString); 0184 } 0185 } 0186 0187 void LocationListModel::validatorError(const QString &error) 0188 { 0189 qDebug() << error; 0190 } 0191 0192 void LocationListModel::addSources(const QMap<QString, QString> &sources) 0193 { 0194 QMapIterator<QString, QString> it(sources); 0195 0196 // TODO: be more elaborate and use beginInsertRows() & endInsertRows() 0197 beginResetModel(); 0198 0199 while (it.hasNext()) { 0200 it.next(); 0201 const QStringList list = it.value().split(QLatin1Char('|'), Qt::SkipEmptyParts); 0202 if (list.count() > 2) { 0203 qDebug() << list; 0204 m_locations.append(LocationItem(list[2], list[0], it.value())); 0205 } 0206 } 0207 0208 endResetModel(); 0209 0210 ++m_checkedInCount; 0211 if (m_checkedInCount >= m_validators.count()) { 0212 completeSearch(); 0213 } 0214 } 0215 0216 void LocationListModel::completeSearch() 0217 { 0218 m_validatingInput = false; 0219 const bool success = !m_locations.empty(); 0220 Q_EMIT locationSearchDone(success, m_searchString); 0221 Q_EMIT validatingInputChanged(false); 0222 } 0223 0224 void LocationListModel::clear() 0225 { 0226 beginResetModel(); 0227 m_locations.clear(); 0228 endResetModel(); 0229 0230 m_checkedInCount = 0; 0231 m_validatingInput = false; 0232 Q_EMIT validatingInputChanged(false); 0233 }