Commit 664e29ad authored by Volker Krause's avatar Volker Krause

Show weather forecast and power plug infos in the trip group summary

parent c71366e0
......@@ -6,6 +6,7 @@ ecm_add_test(applicationcontrollertest.cpp LINK_LIBRARIES Qt5::Test itinerary)
ecm_add_test(tripgrouptest.cpp LINK_LIBRARIES Qt5::Test itinerary)
ecm_add_test(timelinemodeltest.cpp modelverificationpoint.cpp TEST_NAME timelinemodeltest LINK_LIBRARIES Qt5::Test itinerary)
ecm_add_test(tripgroupproxytest.cpp modelverificationpoint.cpp TEST_NAME tripgroupproxytest LINK_LIBRARIES Qt5::Test itinerary)
ecm_add_test(tripgroupinfoprovidertest.cpp TEST_NAME tripgroupinfoprovidertest LINK_LIBRARIES Qt5::Test itinerary)
ecm_add_test(weathertest.cpp LINK_LIBRARIES Qt5::Test itinerary-weather)
target_include_directories(weathertest PRIVATE ${CMAKE_BINARY_DIR})
/*
Copyright (C) 2019 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <countryinformation.h>
#include <reservationmanager.h>
#include <tripgroup.h>
#include <tripgroupmanager.h>
#include <tripgroupinfoprovider.h>
#include <weatherforecast.h>
#include <weatherforecastmanager.h>
#include <QtTest/qtest.h>
#include <QSignalSpy>
#include <QStandardPaths>
class TripGroupInfoProviderTest : public QObject
{
Q_OBJECT
private:
void clearReservations(ReservationManager *mgr)
{
const auto batches = mgr->batches(); // copy, as this is getting modified in the process
for (const auto &id : batches) {
mgr->removeBatch(id);
}
QCOMPARE(mgr->batches().size(), 0);
}
QByteArray readFile(const QString &fn)
{
QFile f(fn);
f.open(QFile::ReadOnly);
return f.readAll();
}
private Q_SLOTS:
void initTestCase()
{
qputenv("TZ", "UTC");
QStandardPaths::setTestModeEnabled(true);
}
void testInfoProvider()
{
ReservationManager resMgr;
clearReservations(&resMgr);
TripGroupManager::clear();
TripGroupManager mgr;
mgr.setReservationManager(&resMgr);
WeatherForecastManager fcMgr;
fcMgr.setTestModeEnabled(true);
resMgr.importReservation(readFile(QLatin1String(SOURCE_DIR "/../tests/randa2017.json")));
QCOMPARE(mgr.tripGroups().size(), 1);
TripGroupInfoProvider provider;
provider.setReservationManager(&resMgr);
provider.setWeatherForecastManager(&fcMgr);
QVERIFY(!provider.weatherForecast({}).isValid());
const auto fc = provider.weatherForecast(mgr.tripGroup(mgr.tripGroups().at(0)));
QVERIFY(fc.isValid());
QCOMPARE(fc.minimumTemperature(), 7.78147f);
QCOMPARE(fc.maximumTemperature(), 47.4647f);
const auto countries = provider.countryInformation(mgr.tripGroup(mgr.tripGroups().at(0)), QStringLiteral("DE"));
QCOMPARE(countries.size(), 1);
const auto country = countries.at(0).value<CountryInformation>();
QCOMPARE(country.isoCode(), QStringLiteral("CH"));
QCOMPARE(country.powerPlugCompatibility(), CountryInformation::PartiallyCompatible);
}
};
QTEST_GUILESS_MAIN(TripGroupInfoProviderTest)
#include "tripgroupinfoprovidertest.moc"
......@@ -11,6 +11,7 @@ set(itinerary_srcs
reservationmanager.cpp
timelinemodel.cpp
tripgroup.cpp
tripgroupinfoprovider.cpp
tripgroupmanager.cpp
tripgroupproxymodel.cpp
)
......
......@@ -27,6 +27,8 @@ Kirigami.AbstractCard {
property var tripGroupId;
property var rangeType;
property var weatherForecast: _tripGroupInfoProvider.weatherForecast(tripGroup)
id: root
showClickFeedback: true
topPadding: rangeType == TimelineModel.RangeEnd ? 0 : Kirigami.Units.largeSpacing
......@@ -66,7 +68,7 @@ Kirigami.AbstractCard {
}
}
contentItem: RowLayout {
contentItem: ColumnLayout {
id: contentLayout
visible: root.rangeType != TimelineModel.RangeEnd
......@@ -76,6 +78,39 @@ Kirigami.AbstractCard {
Localizer.formatDateTime(root.tripGroup, "beginDateTime"))
}
RowLayout {
visible: weatherForecast.valid
Kirigami.Icon {
source: weatherForecast.symbolIconName
width: Kirigami.Units.iconSizes.small
height: width
}
QQC2.Label {
text: i18n("%1°C / %2°C", weatherForecast.minimumTemperature, weatherForecast.maximumTemperature)
}
}
Repeater {
model: _tripGroupInfoProvider.countryInformation(tripGroup, _settings.homeCountryIsoCode)
QQC2.Label {
text: {
if (modelData.powerPlugCompatibility == CountryInformation.PartiallyCompatible) {
if (modelData.powerPlugTypes == "")
return i18n("%1: some incompatible power sockets (%2)", Localizer.countryName(modelData.isoCode), modelData.powerSocketTypes);
else
return i18n("%1: some incompatible power plugs (%2)", Localizer.countryName(modelData.isoCode), modelData.powerPlugTypes);
} else {
return i18n("%1: no compatible power plugs (%2)", Localizer.countryName(modelData.isoCode), modelData.powerSocketTypes);
}
}
color: modelData.powerPlugCompatibility == CountryInformation.PartiallyCompatible ? Kirigami.Theme.neutralTextColor : Kirigami.Theme.negativeTextColor
wrapMode: Text.WordWrap
}
}
Component.onCompleted: {
// hide content entirely in the header-only end elements
parent.visible = contentLayout.visible
......
......@@ -31,6 +31,7 @@
#include "reservationmanager.h"
#include "settings.h"
#include "tickettokenmodel.h"
#include "tripgroupinfoprovider.h"
#include "tripgroupmanager.h"
#include "tripgroupproxymodel.h"
#include "util.h"
......@@ -189,6 +190,10 @@ int main(int argc, char **argv)
TripGroupProxyModel tripGroupProxy;
tripGroupProxy.setSourceModel(&timelineModel);
TripGroupInfoProvider tripGroupInfoProvider;
tripGroupInfoProvider.setReservationManager(&resMgr);
tripGroupInfoProvider.setWeatherForecastManager(&weatherForecastMgr);
qmlRegisterUncreatableType<KPkPass::Barcode>("org.kde.pkpass", 1, 0, "Barcode", {});
qmlRegisterUncreatableType<KPkPass::Field>("org.kde.pkpass", 1, 0, "Field", {});
qmlRegisterUncreatableType<KPkPass::Pass>("org.kde.pkpass", 1, 0, "Pass", {});
......@@ -226,6 +231,7 @@ int main(int argc, char **argv)
engine.rootContext()->setContextProperty(QStringLiteral("_lockManager"), &lockManager);
engine.rootContext()->setContextProperty(QStringLiteral("_liveDataManager"), &liveDataMgr);
engine.rootContext()->setContextProperty(QStringLiteral("_journeyQueryModel"), &journeyQueryModel);
engine.rootContext()->setContextProperty(QStringLiteral("_tripGroupInfoProvider"), QVariant::fromValue(tripGroupInfoProvider));
engine.load(QStringLiteral("qrc:/main.qml"));
handlePositionalArguments(&appController, parser.positionalArguments());
......
/*
Copyright (C) 2019 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "tripgroupinfoprovider.h"
#include "countryinformation.h"
#include "reservationmanager.h"
#include "tripgroup.h"
#include <weatherforecast.h>
#include <weatherforecastmanager.h>
#include <KItinerary/LocationUtil>
#include <KItinerary/Place>
#include <KItinerary/SortUtil>
#include <QDateTime>
#include <QDebug>
using namespace KItinerary;
TripGroupInfoProvider::TripGroupInfoProvider() = default;
TripGroupInfoProvider::~TripGroupInfoProvider() = default;
void TripGroupInfoProvider::setReservationManager(ReservationManager *resMgr)
{
m_resMgr = resMgr;
}
void TripGroupInfoProvider::setWeatherForecastManager(WeatherForecastManager *mgr)
{
m_weatherMgr = mgr;
}
WeatherForecast TripGroupInfoProvider::weatherForecast(const TripGroup &group) const
{
WeatherForecast fc;
const auto elems = group.elements();
QVariant startRes;
for (const auto &resId : elems) {
const auto res = m_resMgr->reservation(resId);
if (!LocationUtil::isLocationChange(res)) {
continue;
}
if (startRes.isValid()) {
const auto geo = LocationUtil::geo(LocationUtil::arrivalLocation(startRes));
const auto startDt = SortUtil::endtDateTime(startRes);
const auto endDt = SortUtil::startDateTime(res);
if (geo.isValid() && startDt.isValid() && endDt.isValid()) {
const auto newFc = m_weatherMgr->forecast(geo.latitude(), geo.longitude(), startDt, endDt);
if (!fc.isValid() && newFc.isValid()) {
fc.setDateTime(startDt);
fc.setRange(std::numeric_limits<int>::max()); // always consider the sub-range forecast during merging
}
fc.merge(newFc);
}
}
startRes = res;
}
return fc;
}
QVariantList TripGroupInfoProvider::countryInformation(const TripGroup &group, const QString &homeCountryIsoCode) const
{
QVariantList l;
const auto elems = group.elements();
for (const auto &resId : elems) {
const auto res = m_resMgr->reservation(resId);
if (!LocationUtil::isLocationChange(res)) {
continue;
}
const auto destCountry = LocationUtil::address(LocationUtil::arrivalLocation(res)).addressCountry();
if (destCountry.isEmpty() || destCountry == homeCountryIsoCode) {
continue;
}
if (std::any_of(l.constBegin(), l.constEnd(), [destCountry](const QVariant &v) { return v.value<CountryInformation>().isoCode() == destCountry; })) {
continue;
}
CountryInformation info;
info.setIsoCode(homeCountryIsoCode);
info.setIsoCode(destCountry);
if (info.powerPlugCompatibility() != CountryInformation::FullyCompatible) {
l.push_back(QVariant::fromValue(info));
}
}
return l;
}
#include "moc_tripgroupinfoprovider.cpp"
/*
Copyright (C) 2019 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef TRIPGROUPINFOPROVIDER_H
#define TRIPGROUPINFOPROVIDER_H
#include <QMetaType>
class ReservationManager;
class TripGroup;
class WeatherForecast;
class WeatherForecastManager;
/** Provides the information shown in the trip group delegate. */
class TripGroupInfoProvider
{
Q_GADGET
public:
TripGroupInfoProvider();
~TripGroupInfoProvider();
void setReservationManager(ReservationManager *resMgr);
void setWeatherForecastManager(WeatherForecastManager *mgr);
Q_INVOKABLE WeatherForecast weatherForecast(const TripGroup &group) const;
Q_INVOKABLE QVariantList countryInformation(const TripGroup &group, const QString &homeCountryIsoCode) const;
private:
ReservationManager *m_resMgr = nullptr;
WeatherForecastManager *m_weatherMgr = nullptr;
};
Q_DECLARE_METATYPE(TripGroupInfoProvider)
#endif // TRIPGROUPINFOPROVIDER_H
......@@ -108,9 +108,14 @@ WeatherForecast WeatherForecastManager::forecast(float latitude, float longitude
return fc;
}
auto beginDt = std::max(begin, QDateTime::currentDateTimeUtc());
const auto now = QDateTime::currentDateTimeUtc();
if (end < now) {
return {};
}
auto beginDt = std::max(begin, now);
roundToHour(beginDt);
auto endDt = std::max(end, QDateTime::currentDateTimeUtc());
auto endDt = std::max(end, now);
roundToHour(endDt);
if (!beginDt.isValid() || !endDt.isValid() || beginDt > endDt) {
return {};
......
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