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