Commit 9d21179b authored by Volker Krause's avatar Volker Krause
Browse files

Properly format date/time values

Since timezones matter for us (we want local times at the destination, not
times in our current timezone), we can't pass date/time values through QML,
as the timezone gets lost in the conversion to JS Date. So we need to do
the property read as part as the formatting function.
parent 689cae22
...@@ -19,6 +19,7 @@ import QtQuick 2.5 ...@@ -19,6 +19,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2 import QtQuick.Controls 2.1 as QQC2
import org.kde.kirigami 2.0 as Kirigami import org.kde.kirigami 2.0 as Kirigami
import org.kde.itinerary 1.0
import "." as App import "." as App
App.TimelineDelegate { App.TimelineDelegate {
...@@ -49,7 +50,7 @@ App.TimelineDelegate { ...@@ -49,7 +50,7 @@ App.TimelineDelegate {
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label { QQC2.Label {
text: reservation.reservationFor.departureTimeLocalized text: Localizer.formatTime(reservation.reservationFor, "departureTime")
color: Kirigami.Theme.complementaryTextColor color: Kirigami.Theme.complementaryTextColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale
} }
...@@ -66,7 +67,7 @@ App.TimelineDelegate { ...@@ -66,7 +67,7 @@ App.TimelineDelegate {
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label { QQC2.Label {
text: qsTr("To: %1 ") text: qsTr("To: %1")
.arg(reservation.reservationFor.arrivalStation.name) .arg(reservation.reservationFor.arrivalStation.name)
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
} }
...@@ -74,7 +75,10 @@ App.TimelineDelegate { ...@@ -74,7 +75,10 @@ App.TimelineDelegate {
place: reservation.reservationFor.arrivalStation place: reservation.reservationFor.arrivalStation
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label {
text: qsTr("Arrival: %1").arg(Localizer.formatDateTime(reservation.reservationFor, "arrivalTime"))
color: Kirigami.Theme.textColor
}
} }
} }
......
...@@ -19,6 +19,7 @@ target_link_libraries(itinerary PUBLIC ...@@ -19,6 +19,7 @@ target_link_libraries(itinerary PUBLIC
add_executable(itinerary-app add_executable(itinerary-app
main.cpp main.cpp
applicationcontroller.cpp applicationcontroller.cpp
localizer.cpp
pkpassimageprovider.cpp pkpassimageprovider.cpp
qml.qrc qml.qrc
) )
......
...@@ -19,6 +19,7 @@ import QtQuick 2.5 ...@@ -19,6 +19,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2 import QtQuick.Controls 2.1 as QQC2
import org.kde.kirigami 2.0 as Kirigami import org.kde.kirigami 2.0 as Kirigami
import org.kde.itinerary 1.0
import "." as App import "." as App
App.TimelineDelegate { App.TimelineDelegate {
...@@ -51,7 +52,9 @@ App.TimelineDelegate { ...@@ -51,7 +52,9 @@ App.TimelineDelegate {
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label { QQC2.Label {
text: reservation.reservationFor.boardingTimeLocalized text: isNaN(reservation.reservationFor.boardingTime.getTime()) ?
Localizer.formatTime(reservation.reservationFor, "departureTime") :
Localizer.formatTime(reservation.reservationFor, "boardingTime")
color: Kirigami.Theme.complementaryTextColor color: Kirigami.Theme.complementaryTextColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale
} }
...@@ -61,7 +64,7 @@ App.TimelineDelegate { ...@@ -61,7 +64,7 @@ App.TimelineDelegate {
QQC2.Label { QQC2.Label {
text: qsTr("Departure from %1: %2") text: qsTr("Departure from %1: %2")
.arg(reservation.reservationFor.departureAirport.name) .arg(reservation.reservationFor.departureAirport.name)
.arg(reservation.reservationFor.departureTimeLocalized) .arg(Localizer.formatTime(reservation.reservationFor, "departureTime"))
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
Layout.maximumWidth: root.width Layout.maximumWidth: root.width
...@@ -81,7 +84,7 @@ App.TimelineDelegate { ...@@ -81,7 +84,7 @@ App.TimelineDelegate {
QQC2.Label { QQC2.Label {
text: qsTr("Arrival at %1: %2") text: qsTr("Arrival at %1: %2")
.arg(reservation.reservationFor.arrivalAirport.name) .arg(reservation.reservationFor.arrivalAirport.name)
.arg(reservation.reservationFor.arrivalTimeLocalized) .arg(Localizer.formatDateTime(reservation.reservationFor, "arrivalTime"))
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
Layout.maximumWidth: root.width Layout.maximumWidth: root.width
......
...@@ -19,6 +19,7 @@ import QtQuick 2.5 ...@@ -19,6 +19,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2 import QtQuick.Controls 2.1 as QQC2
import org.kde.kirigami 2.0 as Kirigami import org.kde.kirigami 2.0 as Kirigami
import org.kde.itinerary 1.0
import "." as App import "." as App
App.TimelineDelegate { App.TimelineDelegate {
...@@ -55,12 +56,12 @@ App.TimelineDelegate { ...@@ -55,12 +56,12 @@ App.TimelineDelegate {
} }
QQC2.Label { QQC2.Label {
text: qsTr("Check-in time: %1") text: qsTr("Check-in time: %1")
.arg(reservation.checkinTime) .arg(Localizer.formatTime(reservation, "checkinTime"))
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
} }
QQC2.Label { QQC2.Label {
text: qsTr("Check-out time: %1") text: qsTr("Check-out time: %1")
.arg(reservation.checkoutTime) .arg(Localizer.formatDateTime(reservation, "checkoutTime"))
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
} }
......
...@@ -19,6 +19,7 @@ import QtQuick 2.5 ...@@ -19,6 +19,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2 import QtQuick.Controls 2.1 as QQC2
import org.kde.kirigami 2.0 as Kirigami import org.kde.kirigami 2.0 as Kirigami
import org.kde.itinerary 1.0
import "." as App import "." as App
App.TimelineDelegate { App.TimelineDelegate {
...@@ -47,7 +48,7 @@ App.TimelineDelegate { ...@@ -47,7 +48,7 @@ App.TimelineDelegate {
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label { QQC2.Label {
text: reservation.startTime text: Localizer.formatTime(reservation, "startTime")
color: Kirigami.Theme.complementaryTextColor color: Kirigami.Theme.complementaryTextColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale
} }
...@@ -65,7 +66,7 @@ App.TimelineDelegate { ...@@ -65,7 +66,7 @@ App.TimelineDelegate {
} }
QQC2.Label { QQC2.Label {
text: qsTr("End: %1") text: qsTr("End: %1")
.arg(reservation.endTime) .arg(Localizer.formatTime(reservation, "endTime"))
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
} }
......
...@@ -19,6 +19,7 @@ import QtQuick 2.5 ...@@ -19,6 +19,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2 import QtQuick.Controls 2.1 as QQC2
import org.kde.kirigami 2.0 as Kirigami import org.kde.kirigami 2.0 as Kirigami
import org.kde.itinerary 1.0
import "." as App import "." as App
App.TimelineDelegate { App.TimelineDelegate {
...@@ -49,7 +50,7 @@ App.TimelineDelegate { ...@@ -49,7 +50,7 @@ App.TimelineDelegate {
Layout.fillWidth: true Layout.fillWidth: true
} }
QQC2.Label { QQC2.Label {
text: reservation.reservationFor.departureTimeLocalized text: Localizer.formatTime(reservation.reservationFor, "departureTime")
color: Kirigami.Theme.complementaryTextColor color: Kirigami.Theme.complementaryTextColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale
} }
...@@ -73,6 +74,11 @@ App.TimelineDelegate { ...@@ -73,6 +74,11 @@ App.TimelineDelegate {
.arg(reservation.reservationFor.arrivalPlatform) .arg(reservation.reservationFor.arrivalPlatform)
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
} }
QQC2.Label {
text: qsTr("Arrival time: %1")
.arg(Localizer.formatDateTime(reservation.reservationFor, "arrivalTime"))
color: Kirigami.Theme.textColor
}
App.PlaceDelegate { App.PlaceDelegate {
place: reservation.reservationFor.arrivalStation place: reservation.reservationFor.arrivalStation
Layout.fillWidth: true Layout.fillWidth: true
......
/*
Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#include "localizer.h"
#include <KItinerary/JsonLdDocument>
#include <QDateTime>
#include <QLocale>
#include <QTimeZone>
using namespace KItinerary;
Localizer::Localizer(QObject *parent)
: QObject(parent)
{
}
Localizer::~Localizer() = default;
static bool needsTimeZone(const QDateTime &dt)
{
if (dt.timeSpec() == Qt::TimeZone && dt.timeZone().abbreviation(dt) != QTimeZone::systemTimeZone().abbreviation(dt)) {
return true;
} else if (dt.timeSpec() == Qt::OffsetFromUTC && dt.timeZone().offsetFromUtc(dt) != dt.offsetFromUtc()) {
return true;
}
return false;
}
QString Localizer::formatTime(const QVariant &obj, const QString &propertyName) const
{
const auto dt = JsonLdDocument::readProperty(obj, propertyName.toUtf8().constData()).value<QDateTime>();
if (!dt.isValid()) {
return {};
}
auto s = QLocale().toString(dt.time(), QLocale::ShortFormat);
if (needsTimeZone(dt)) {
s += QLatin1Char(' ') + dt.timeZone().abbreviation(dt);
}
return s;
}
QString Localizer::formatDateTime(const QVariant& obj, const QString& propertyName) const
{
const auto dt = JsonLdDocument::readProperty(obj, propertyName.toUtf8().constData()).value<QDateTime>();
if (!dt.isValid()) {
return {};
}
auto s = QLocale().toString(dt, QLocale::ShortFormat);
if (needsTimeZone(dt)) {
s += QLatin1Char(' ') + dt.timeZone().abbreviation(dt);
}
return s;
}
/*
Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
*/
#ifndef LOCALIZER_H
#define LOCALIZER_H
#include <QObject>
class QVariant;
/** Date/time localization utilities.
* Works around JS losing timezone information, ie. we need
* to do this without passing the date/time values through JS.
*/
class Localizer : public QObject
{
Q_OBJECT
public:
explicit Localizer(QObject *parent = nullptr);
~Localizer();
Q_INVOKABLE QString formatTime(const QVariant &obj, const QString &propertyName) const;
Q_INVOKABLE QString formatDateTime(const QVariant &obj, const QString &propertyName) const;
};
#endif // LOCALIZER_H
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "logging.h" #include "logging.h"
#include "applicationcontroller.h" #include "applicationcontroller.h"
#include "localizer.h"
#include "pkpassmanager.h" #include "pkpassmanager.h"
#include "timelinemodel.h" #include "timelinemodel.h"
#include "pkpassimageprovider.h" #include "pkpassimageprovider.h"
...@@ -108,6 +109,9 @@ int main(int argc, char **argv) ...@@ -108,6 +109,9 @@ int main(int argc, char **argv)
qmlRegisterUncreatableType<KPkPass::Field>("org.kde.pkpass", 1, 0, "Field", {}); qmlRegisterUncreatableType<KPkPass::Field>("org.kde.pkpass", 1, 0, "Field", {});
qmlRegisterUncreatableType<TimelineModel>("org.kde.itinerary", 1, 0, "TimelineModel", {}); qmlRegisterUncreatableType<TimelineModel>("org.kde.itinerary", 1, 0, "TimelineModel", {});
qmlRegisterSingletonType<Localizer>("org.kde.itinerary", 1, 0, "Localizer", [](QQmlEngine*, QJSEngine*) -> QObject*{
return new Localizer;
});
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
engine.addImageProvider(QStringLiteral("org.kde.pkpass"), new PkPassImageProvider(&passMgr)); engine.addImageProvider(QStringLiteral("org.kde.pkpass"), new PkPassImageProvider(&passMgr));
......
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