Commit f1d09b5a authored by Nicolas Fella's avatar Nicolas Fella
Browse files

Simplify day forecast code

Replace WeatherDay and WeatherDayListModel with using KWeatherCore types directly
parent db1dc359
Pipeline #73119 passed with stage
in 18 seconds
......@@ -12,8 +12,6 @@ set(kweather_SRCS
weatherlocation.cpp
weatherhourmodel.cpp
weatherhour.cpp
weatherdaymodel.cpp
weatherday.cpp
locationquerymodel.cpp
resources.qrc
)
......
......@@ -27,7 +27,6 @@
#include "kweathersettings.h"
#include "locationquerymodel.h"
#include "version.h"
#include "weatherdaymodel.h"
#include "weatherforecastmanager.h"
#include "weatherhourmodel.h"
#include "weatherlocation.h"
......@@ -76,10 +75,10 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
// register QML types
qmlRegisterType<WeatherLocation>("kweather", 1, 0, "WeatherLocation");
qmlRegisterType<WeatherDay>("kweather", 1, 0, "WeatherDay");
qmlRegisterType<WeatherHour>("kweather", 1, 0, "WeatherHour");
qmlRegisterType<WeatherHourListModel>("kweather", 1, 0, "WeatherHourListModel");
qmlRegisterType<WeatherDayListModel>("kweather", 1, 0, "WeatherDayListModel");
qRegisterMetaType<KWeatherCore::Sunrise>();
// load setup wizard if first launch
engine.load(QUrl(QStringLiteral("qrc:///qml/main.qml")));
......
......@@ -18,7 +18,7 @@ Kirigami.ScrollablePage {
property bool inView: false
property WeatherLocation weatherLocation
property WeatherDay currentDay: weatherLocation.dayListModel.get(dailyListView.currentIndex)
property var currentDay: dailyListView.currentItem.weather
property int maximumContentWidth: Kirigami.Units.gridUnit * 35
......@@ -164,9 +164,9 @@ Kirigami.ScrollablePage {
currentIndex: 0
model: weatherLocation.dayListModel
model: weatherLocation.dayForecasts
delegate: WeatherDayDelegate {
weather: dayItem
weather: modelData
textColor: weatherLocation.cardTextColor
}
......@@ -543,7 +543,7 @@ Kirigami.ScrollablePage {
color: weatherLocation.cardTextColor
}
Label {
text: currentDay == null ? "" : currentDay.sunrise
text: Qt.formatTime(currentDay.sunrise.sunRise, Locale.ShortFormat)
color: weatherLocation.cardTextColor
}
}
......@@ -566,7 +566,7 @@ Kirigami.ScrollablePage {
color: weatherLocation.cardTextColor
}
Label {
text: currentDay == null ? "" : currentDay.sunset
text: Qt.formatTime(currentDay.sunrise.sunSet, Locale.ShortFormat)
color: weatherLocation.cardTextColor
}
}
......@@ -588,7 +588,7 @@ Kirigami.ScrollablePage {
color: weatherLocation.cardTextColor
}
Label {
text: currentDay == null ? "" : currentDay.moonPhase
text: currentDay.sunrise.moonPhaseString
color: weatherLocation.cardTextColor
}
}
......
......@@ -19,8 +19,8 @@ Kirigami.ScrollablePage {
background: null // transparent, since there is a page behind
property WeatherLocation weatherLocation
property WeatherDay currentDay: weatherLocation.dayListModel.get(dailyListView.currentIndex)
property var currentDay: dailyListView.currentItem.weather
property bool inView: false
// swipe down to refresh
......@@ -125,9 +125,9 @@ Kirigami.ScrollablePage {
currentIndex: 0
model: weatherLocation.dayListModel
model: weatherLocation.dayForecasts
delegate: WeatherDayDelegate {
weather: dayItem
weather: modelData
textColor: Kirigami.Theme.textColor
}
......@@ -369,7 +369,7 @@ Kirigami.ScrollablePage {
text: i18n("Sunrise")
}
Label {
text: currentDay == null ? "" : currentDay.sunrise
text: Qt.formatTime(currentDay.sunrise.sunRise, Locale.ShortFormat)
}
}
}
......@@ -393,7 +393,7 @@ Kirigami.ScrollablePage {
text: i18n("Sunset")
}
Label {
text: currentDay == null ? "" : currentDay.sunset
text: Qt.formatTime(currentDay.sunrise.sunSet, Locale.ShortFormat)
}
}
}
......@@ -417,7 +417,7 @@ Kirigami.ScrollablePage {
text: i18n("Moon Phase")
}
Label {
text: currentDay == null ? "" : currentDay.moonPhase
text: currentDay.sunrise.moonPhaseString
}
}
}
......
......@@ -17,7 +17,7 @@ Rectangle {
implicitHeight: Kirigami.Units.gridUnit * 8
color: "transparent"
property WeatherDay weather
property var weather
property color textColor
MouseArea {
......
/*
* SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
* SPDX-FileCopyrightText: 2020 Devin Lin <espidev@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "weatherday.h"
#include "global.h"
#include "weatherdaymodel.h"
WeatherDay::WeatherDay(WeatherDayListModel *parent)
: QObject(parent)
{
if (parent)
connect(parent, &WeatherDayListModel::weatherRefresh, this, &WeatherDay::refreshDaysFromForecasts);
}
WeatherDay::WeatherDay(KWeatherCore::WeatherForecast ptr, int day, WeatherDayListModel *parent)
: QObject(parent)
, m_day(day)
, m_forecast(std::move(ptr))
{
if (parent)
connect(parent, &WeatherDayListModel::weatherRefresh, this, &WeatherDay::refreshDaysFromForecasts);
determineSunrise();
}
void WeatherDay::determineSunrise()
{
m_sunrise = day().sunrise().sunRise().toString(QStringLiteral("hh:mm ap"));
m_sunset = day().sunrise().sunSet().toString(QStringLiteral("hh:mm ap"));
if (day().sunrise().moonPhase() <= 5) {
m_moonPhase = "New Moon";
} else if (day().sunrise().moonPhase() <= 25) {
m_moonPhase = "Waxing Crescent";
} else if (day().sunrise().moonPhase() <= 45) {
m_moonPhase = "Waxing Gibbous";
} else if (day().sunrise().moonPhase() <= 55) {
m_moonPhase = "Full Moon";
} else if (day().sunrise().moonPhase() <= 75) {
m_moonPhase = "Waning Gibbous";
} else if (day().sunrise().moonPhase() <= 95) {
m_moonPhase = "Waning Crescent";
} else {
m_moonPhase = "New Moon";
}
}
void WeatherDay::refreshDaysFromForecasts(KWeatherCore::WeatherForecast ptr)
{
m_forecast = std::move(ptr);
determineSunrise();
Q_EMIT propertyChanged();
}
/*
* SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
* SPDX-FileCopyrightText: 2020 Devin Lin <espidev@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "global.h"
#include <KWeatherCore/WeatherForecast>
#include <QObject>
class WeatherDayListModel;
class WeatherDay : public QObject
{
Q_OBJECT
Q_PROPERTY(QString weatherDescription READ weatherDescription NOTIFY propertyChanged)
Q_PROPERTY(QString weatherIcon READ weatherIcon NOTIFY propertyChanged)
Q_PROPERTY(QDateTime date READ date NOTIFY propertyChanged)
Q_PROPERTY(QString maxTemp READ maxTemp NOTIFY propertyChanged)
Q_PROPERTY(QString minTemp READ minTemp NOTIFY propertyChanged)
Q_PROPERTY(qreal precipitation READ precipitation NOTIFY propertyChanged)
Q_PROPERTY(qreal uvIndex READ uvIndex NOTIFY propertyChanged)
Q_PROPERTY(qreal humidity READ humidity NOTIFY propertyChanged)
Q_PROPERTY(qreal pressure READ pressure NOTIFY propertyChanged)
Q_PROPERTY(QString sunrise READ sunrise NOTIFY propertyChanged)
Q_PROPERTY(QString sunset READ sunset NOTIFY propertyChanged)
Q_PROPERTY(QString moonPhase READ moonPhase NOTIFY propertyChanged)
public:
WeatherDay(WeatherDayListModel *parent = nullptr);
explicit WeatherDay(KWeatherCore::WeatherForecast ptr, int day, WeatherDayListModel *parent = nullptr);
const QString &weatherDescription() const
{
return day().weatherDescription();
}
const QString &weatherIcon() const
{
return day().weatherIcon();
}
QDateTime date() const
{
return day().dateTime();
}
QString maxTemp() const
{
return Kweather::tempConverter(day().maxTemp());
}
QString minTemp() const
{
return Kweather::tempConverter(day().minTemp());
}
qreal precipitation() const
{
return day().precipitation();
}
qreal uvIndex() const
{
return day().uvIndex();
}
qreal humidity() const
{
return day().humidity();
}
qreal pressure() const
{
return day().pressure();
}
const QString &sunrise() const
{
return m_sunrise;
}
const QString &sunset() const
{
return m_sunset;
}
const QString &moonPhase() const
{
return m_moonPhase;
}
public Q_SLOTS:
void refreshDaysFromForecasts(KWeatherCore::WeatherForecast ptr);
Q_SIGNALS:
void propertyChanged();
private:
const KWeatherCore::DailyWeatherForecast &day() const
{
return m_forecast.dailyWeatherForecast().at(m_day);
}
void determineSunrise();
QString m_sunrise;
QString m_sunset;
QString m_moonPhase;
int m_day = 0;
KWeatherCore::WeatherForecast m_forecast;
};
/*
* SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
* SPDX-FileCopyrightText: 2020 Devin Lin <espidev@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "weatherdaymodel.h"
#include "weatherlocation.h"
#include <QQmlEngine>
WeatherDayListModel::WeatherDayListModel(WeatherLocation *location)
: QAbstractListModel(location)
{
connect(location, &WeatherLocation::weatherRefresh, this, &WeatherDayListModel::refreshDaysFromForecasts);
}
int WeatherDayListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_weatherDays.size();
}
QVariant WeatherDayListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= static_cast<int>(m_weatherDays.size()) || index.row() < 0) {
return {};
}
if (role == Roles::DayItemRole) {
return QVariant::fromValue(m_weatherDays.at(index.row()));
}
return {};
}
QHash<int, QByteArray> WeatherDayListModel::roleNames() const
{
return {{Roles::DayItemRole, "dayItem"}};
}
WeatherDay *WeatherDayListModel::get(int index)
{
WeatherDay *ret = nullptr;
if (index < 0 || index >= static_cast<int>(m_forecasts.dailyWeatherForecast().size()))
return ret;
ret = m_weatherDays.at(index);
QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); // prevent segfaults from js garbage collecting
return ret;
}
void WeatherDayListModel::refreshDaysFromForecasts(KWeatherCore::WeatherForecast forecasts)
{
if (forecasts.dailyWeatherForecast().empty())
return;
m_forecasts = forecasts;
// skip outdated data
int skipped = 0;
auto date = QDate::currentDate();
while (forecasts.dailyWeatherForecast().at(skipped).date() < date)
skipped++;
if (forecasts.dailyWeatherForecast().size() - skipped > m_weatherDays.size()) {
beginInsertRows(QModelIndex(), m_weatherDays.size(), forecasts.dailyWeatherForecast().size() - 1 - skipped);
for (auto i = m_weatherDays.size(); i < forecasts.dailyWeatherForecast().size() - skipped; i++) {
auto weatherDay = new WeatherDay(forecasts, i, this);
QQmlEngine::setObjectOwnership(weatherDay, QQmlEngine::CppOwnership); // prevent segfaults from js garbage collecting
m_weatherDays.push_back(weatherDay);
}
endInsertRows();
} else if (forecasts.dailyWeatherForecast().size() - skipped < m_weatherDays.size()) {
beginRemoveRows(QModelIndex(), forecasts.dailyWeatherForecast().size() - skipped, m_weatherDays.size() - 1);
for (auto i = m_weatherDays.size() - forecasts.dailyWeatherForecast().size() + skipped; i > 0; i--) {
m_weatherDays.back()->deleteLater();
m_weatherDays.pop_back();
}
endRemoveRows();
}
Q_EMIT weatherRefresh(forecasts);
}
void WeatherDayListModel::updateUi()
{
Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_forecasts.dailyWeatherForecast().size() - 1, 0));
}
/*
* SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
* SPDX-FileCopyrightText: 2020 Devin Lin <espidev@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "weatherday.h"
#include <KWeatherCore/WeatherForecast>
#include <QAbstractListModel>
#include <QObject>
class WeatherLocation;
class WeatherDay;
class WeatherDayListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit WeatherDayListModel(WeatherLocation *location = nullptr);
enum Roles { DayItemRole = Qt::UserRole };
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE WeatherDay *get(int index);
Q_INVOKABLE void updateUi();
public Q_SLOTS:
void refreshDaysFromForecasts(KWeatherCore::WeatherForecast forecast);
Q_SIGNALS:
void weatherRefresh(KWeatherCore::WeatherForecast forecast);
private:
KWeatherCore::WeatherForecast m_forecasts;
std::vector<WeatherDay *> m_weatherDays;
};
......@@ -9,9 +9,7 @@
#include "global.h"
#include "kweathersettings.h"
#include "locationquerymodel.h"
#include "weatherdaymodel.h"
#include <QAbstractSeries>
#include <QDateTimeAxis>
#include <QDir>
#include <QFile>
#include <QJsonArray>
......@@ -24,7 +22,6 @@
WeatherLocation::WeatherLocation()
{
m_weatherDayListModel = new WeatherDayListModel(this);
m_weatherHourListModel = new WeatherHourListModel(this);
m_lastUpdated = QDateTime::currentDateTime();
this->m_timer = new QTimer(this);
......@@ -45,14 +42,12 @@ WeatherLocation::WeatherLocation(QString locationId,
, m_latitude(latitude)
, m_longitude(longitude)
{
m_weatherDayListModel = new WeatherDayListModel(this);
m_weatherHourListModel = new WeatherHourListModel(this);
this->m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &WeatherLocation::updateCurrentDateTime);
this->m_timer->start(60 - QDateTime::currentDateTime().currentMSecsSinceEpoch() % 60);
// prevent segfaults from js garbage collection
QQmlEngine::setObjectOwnership(m_weatherDayListModel, QQmlEngine::CppOwnership);
QQmlEngine::setObjectOwnership(m_weatherHourListModel, QQmlEngine::CppOwnership);
m_lastUpdated = forecast.createdTime();
......@@ -222,27 +217,34 @@ void WeatherLocation::initSeries(QtCharts::QAbstractSeries *series)
}
void WeatherLocation::updateSeries()
{
if (m_series && !m_forecast.dailyWeatherForecast().empty()) {
m_vector.clear();
m_vector.clear();
double minTemp = std::numeric_limits<double>::max(), maxTemp = std::numeric_limits<double>::min();
for (const auto &d : m_forecast.dailyWeatherForecast()) {
const auto dayMinTemp = Kweather::convertTemp(d.minTemp()), dayMaxTemp = Kweather::convertTemp(d.maxTemp());
const auto &dayForecasts = m_forecast.dailyWeatherForecast();
for (const KWeatherCore::DailyWeatherForecast &day : dayForecasts) {
m_dayForecasts << QVariant::fromValue(day);
m_vector.append(QPointF(d.date().startOfDay().toMSecsSinceEpoch(), dayMaxTemp));
minTemp = std::min<double>(dayMinTemp, minTemp);
maxTemp = std::max<double>(dayMaxTemp, maxTemp);
}
if (m_series) {
double minTemp = std::numeric_limits<double>::max(), maxTemp = std::numeric_limits<double>::min();
for (const auto &d : m_forecast.dailyWeatherForecast()) {
const auto dayMinTemp = Kweather::convertTemp(d.minTemp()), dayMaxTemp = Kweather::convertTemp(d.maxTemp());
// make enough room for the curve
m_maxTempLimit = maxTemp + 5;
m_minTempLimit = minTemp - 5;
m_vector.append(QPointF(d.date().startOfDay().toMSecsSinceEpoch(), dayMaxTemp));
minTemp = std::min<double>(dayMinTemp, minTemp);
maxTemp = std::max<double>(dayMaxTemp, maxTemp);
}
m_series->replace(m_vector);
if (m_axisX) {
m_axisX->setRange(m_forecast.dailyWeatherForecast().front().date().startOfDay(), m_forecast.dailyWeatherForecast().back().date().startOfDay());
// make enough room for the curve
m_maxTempLimit = maxTemp + 5;
m_minTempLimit = minTemp - 5;
m_series->replace(m_vector);
if (m_axisX) {
m_axisX->setRange(m_forecast.dailyWeatherForecast().front().date().startOfDay(), m_forecast.dailyWeatherForecast().back().date().startOfDay());
}
}
}
Q_EMIT dayForecastsChanged();
}
void WeatherLocation::initAxes(QObject *axisX, QObject *axisY)
{
......
......@@ -19,7 +19,6 @@
#include <QTimer>
#include <utility>
class WeatherDayListModel;
namespace QtCharts
{
class QAbstractSeries;
......@@ -35,7 +34,7 @@ class WeatherLocation : public QObject
Q_PROPERTY(QString lastUpdated READ lastUpdatedFormatted NOTIFY propertyChanged)
Q_PROPERTY(QString currentTime READ currentTimeFormatted NOTIFY currentTimeChanged)
Q_PROPERTY(QString currentDate READ currentDateFormatted NOTIFY currentDateChanged)
Q_PROPERTY(WeatherDayListModel *dayListModel READ weatherDayListModel NOTIFY propertyChanged)
Q_PROPERTY(QVariantList dayForecasts READ dayForecasts NOTIFY dayForecastsChanged)
Q_PROPERTY(WeatherHourListModel *hourListModel READ weatherHourListModel NOTIFY propertyChanged)
Q_PROPERTY(QString backgroundComponent READ backgroundComponent NOTIFY currentForecastChange)
......@@ -81,10 +80,6 @@ public:
{
return m_longitude;
}
WeatherDayListModel *weatherDayListModel() const
{
return m_weatherDayListModel;
}
WeatherHourListModel *weatherHourListModel() const
{
return m_weatherHourListModel;
......@@ -152,6 +147,10 @@ public:
{
return m_isDarkTheme;
}
QVariantList dayForecasts() const
{
return m_dayForecasts;
}
Q_INVOKABLE void initSeries(QtCharts::QAbstractSeries *series);
Q_INVOKABLE void initAxes(QObject *axisX, QObject *axisY);
......@@ -169,6 +168,7 @@ signals:
void stopLoadingIndicator();
void currentTimeChanged();
void currentDateChanged();
void dayForecastsChanged();
void chartListChanged();
private slots:
......@@ -205,6 +205,7 @@ private:
QTimer *m_timer;
float m_latitude, m_longitude;
WeatherDayListModel *m_weatherDayListModel = nullptr;
QVariantList m_dayForecasts;
WeatherHourListModel *m_weatherHourListModel = nullptr;
};
......@@ -6,7 +6,6 @@
*/
#include "weatherlocationmodel.h"
#include "weatherdaymodel.h"
#include "weatherlocation.h"
#include <KConfigCore/KConfigGroup>
......@@ -89,7 +88,6 @@ void WeatherLocationListModel::updateUi()
Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_locations.size() - 1, 0));
for (const auto &l : qAsConst(m_locations)) {
Q_EMIT l->propertyChanged();
l->weatherDayListModel()->updateUi();
l->weatherHourListModel()->updateUi();
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment