File indexing completed on 2024-05-19 05:55:49
0001 // SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com> 0002 // SPDX-FileCopyrightText: 2020-2022 Devin Lin <espidev@gmail.com> 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include "weatherlocationlistmodel.h" 0006 0007 #include <QJsonArray> 0008 #include <QQmlEngine> 0009 0010 #include <KConfigGroup> 0011 #include <KSharedConfig> 0012 0013 #include <KWeatherCore/LocationQueryReply> 0014 0015 #include "global.h" 0016 #include "kweathersettings.h" 0017 #include "weatherlocation.h" 0018 0019 WeatherLocationListModel::WeatherLocationListModel(QObject *parent) 0020 : QAbstractListModel{parent} 0021 { 0022 load(); 0023 } 0024 0025 WeatherLocationListModel *WeatherLocationListModel::create(QQmlEngine *, QJSEngine *) 0026 { 0027 QQmlEngine::setObjectOwnership(inst(), QQmlEngine::CppOwnership); 0028 return inst(); 0029 } 0030 0031 WeatherLocationListModel *WeatherLocationListModel::inst() 0032 { 0033 static WeatherLocationListModel *singleton = new WeatherLocationListModel; 0034 return singleton; 0035 } 0036 0037 void WeatherLocationListModel::load() 0038 { 0039 beginResetModel(); 0040 0041 // load locations from kconfig 0042 auto config = KWeatherSettings::self()->config()->group(KWeather::WEATHER_LOCATIONS_CFG_GROUP); 0043 auto locations = config.groupList(); 0044 for (const auto &location : locations) { 0045 auto location_ptr = WeatherLocation::load(location); 0046 if (location_ptr) 0047 m_locations.push_back(location_ptr); 0048 } 0049 0050 // sort locations by index, correcting any issues with the stored index 0051 0052 QList<WeatherLocation *> sorted, unsorted; 0053 for (int i = 0; i < (int)m_locations.size(); ++i) { 0054 sorted.push_back(nullptr); 0055 } 0056 0057 // loop through the initial locations and fill in the indicies in sorted 0058 for (auto loc : m_locations) { 0059 auto index = loc->index(); 0060 0061 if (index < 0 || index >= (int)sorted.size() || sorted[index] != nullptr) { 0062 unsorted.push_back(loc); 0063 } else { 0064 sorted[index] = loc; 0065 } 0066 } 0067 // add unsorted locations in positions unfilled 0068 for (auto loc : unsorted) { 0069 for (int i = 0; i < (int)sorted.size(); ++i) { 0070 if (!sorted[i]) { 0071 sorted[i] = loc; 0072 break; 0073 } 0074 } 0075 } 0076 // move into original array 0077 for (int i = 0; i < (int)m_locations.size(); ++i) { 0078 m_locations[i] = sorted[i]; 0079 } 0080 0081 Q_EMIT locationsChanged(); 0082 endResetModel(); 0083 } 0084 0085 void WeatherLocationListModel::saveOrder() 0086 { 0087 auto i{0}; 0088 for (auto loc : m_locations) { 0089 loc->saveOrder(i); 0090 i++; 0091 } 0092 } 0093 0094 int WeatherLocationListModel::count() const 0095 { 0096 return m_locations.size(); 0097 } 0098 0099 int WeatherLocationListModel::rowCount(const QModelIndex &parent) const 0100 { 0101 if (parent.isValid()) { 0102 return 0; 0103 } 0104 return m_locations.size(); 0105 } 0106 0107 QVariant WeatherLocationListModel::data(const QModelIndex &index, int role) const 0108 { 0109 if (!checkIndex(index)) { 0110 return QVariant(); 0111 } 0112 if (role != LocationRole) { 0113 return QVariant(); 0114 } 0115 0116 auto *location = m_locations[index.row()]; 0117 return location ? QVariant::fromValue(location) : QVariant(); 0118 } 0119 0120 QHash<int, QByteArray> WeatherLocationListModel::roleNames() const 0121 { 0122 return {{LocationRole, "location"}}; 0123 } 0124 0125 void WeatherLocationListModel::insert(int index, WeatherLocation *weatherLocation) 0126 { 0127 if ((index < 0) || (index > static_cast<int>(m_locations.size()))) { 0128 return; 0129 } 0130 0131 beginInsertRows(QModelIndex(), index, index); 0132 0133 QQmlEngine::setObjectOwnership(weatherLocation, QQmlEngine::CppOwnership); 0134 m_locations.insert(m_locations.begin() + index, weatherLocation); 0135 0136 Q_EMIT locationsChanged(); 0137 endInsertRows(); 0138 0139 saveOrder(); 0140 weatherLocation->save(); 0141 } 0142 0143 void WeatherLocationListModel::remove(int index) 0144 { 0145 if ((index < 0) || (index >= static_cast<int>(m_locations.size()))) { 0146 return; 0147 } 0148 0149 beginRemoveRows(QModelIndex(), index, index); 0150 0151 auto location = m_locations.at(index); 0152 m_locations.erase(m_locations.begin() + index); 0153 location->deleteConfig(); 0154 location->deleteLater(); 0155 0156 Q_EMIT locationsChanged(); 0157 endRemoveRows(); 0158 0159 saveOrder(); 0160 } 0161 0162 void WeatherLocationListModel::move(int oldIndex, int newIndex) 0163 { 0164 int locationsSize = m_locations.size(); 0165 if (oldIndex < 0 || oldIndex >= locationsSize || newIndex < 0 || newIndex >= locationsSize) { 0166 return; 0167 } 0168 if (newIndex > oldIndex) { 0169 ++newIndex; 0170 } 0171 0172 beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex); 0173 if (newIndex > oldIndex) { 0174 auto *location = m_locations.at(oldIndex); 0175 m_locations.insert(newIndex, location); 0176 m_locations.takeAt(oldIndex); 0177 } else { 0178 auto *location = m_locations.takeAt(oldIndex); 0179 m_locations.insert(newIndex, location); 0180 } 0181 endMoveRows(); 0182 Q_EMIT locationsChanged(); 0183 0184 saveOrder(); 0185 } 0186 0187 void WeatherLocationListModel::addLocation(const KWeatherCore::LocationQueryResult &ret) 0188 { 0189 const auto &locId = ret.geonameId(); 0190 const auto &locName = ret.toponymName(); 0191 auto lat = ret.latitude(); 0192 auto lon = ret.longitude(); 0193 0194 // add location 0195 auto *location = new WeatherLocation(locId, locName, QString(), lat, lon); 0196 0197 insert(m_locations.size(), location); 0198 } 0199 0200 void WeatherLocationListModel::requestCurrentLocation() 0201 { 0202 static KWeatherCore::LocationQuery *geoPtr = nullptr; 0203 if (!geoPtr) { 0204 geoPtr = new KWeatherCore::LocationQuery(this); 0205 } 0206 0207 auto reply = geoPtr->locate(); 0208 connect(reply, &KWeatherCore::LocationQueryReply::finished, this, [reply, this]() { 0209 reply->deleteLater(); 0210 if (reply->error() != KWeatherCore::LocationQueryReply::NoError) { 0211 Q_EMIT networkErrorCreatingDefault(); 0212 } else { 0213 addCurrentLocation(reply->result().at(0)); 0214 } 0215 }); 0216 } 0217 0218 void WeatherLocationListModel::addCurrentLocation(const KWeatherCore::LocationQueryResult &ret) 0219 { 0220 auto location = new WeatherLocation(ret.geonameId(), ret.toponymName(), QString(), ret.latitude(), ret.longitude()); 0221 0222 insert(0, location); 0223 Q_EMIT successfullyCreatedDefault(); 0224 } 0225 0226 QList<WeatherLocation *> &WeatherLocationListModel::locations() 0227 { 0228 return m_locations; 0229 } 0230 0231 #include "moc_weatherlocationlistmodel.cpp"