Commit 95e93d48 authored by Volker Krause's avatar Volker Krause
Browse files

Add support for top-level schema.org Ticket elements

Those are shown in the programs & passes page.
parent 62ca9bdd
Pipeline #185516 passed with stage
in 1 minute and 27 seconds
{
"@context": "http://schema.org",
"@type": "Ticket",
"issuedBy": {
"@type": "Organization",
"identifier": "uic:0080"
},
"name": "9-Euro-Ticket",
"ticketNumber": "XXX007",
"ticketToken": "aztec:<ticket-barcode-omitted>",
"ticketedSeat": {
"@type": "Seat",
"seatingType": "2"
},
"underName": {
"@type": "Person",
"name": "Dr Konqui"
}
}
......@@ -8,6 +8,7 @@
#include <KItinerary/JsonLdDocument>
#include <KItinerary/ProgramMembership>
#include <KItinerary/Ticket>
#include <qtest.h>
#include <QAbstractItemModelTester>
......@@ -38,8 +39,9 @@ private Q_SLOTS:
QCOMPARE(mgr.rowCount(), 0);
// test import
QVERIFY(mgr.import(JsonLdDocument::fromJsonSingular(QJsonDocument::fromJson(Test::readFile(QStringLiteral(SOURCE_DIR "/data/bahncard.json"))).object())));
QCOMPARE(mgr.rowCount(), 1);
QVERIFY(mgr.import(JsonLdDocument::fromJsonSingular(QJsonDocument::fromJson(Test::readFile(QStringLiteral(SOURCE_DIR "/data/bahncard.json"))).object()), QStringLiteral("1")));
QVERIFY(mgr.import(JsonLdDocument::fromJsonSingular(QJsonDocument::fromJson(Test::readFile(QStringLiteral(SOURCE_DIR "/data/9euroticket.json"))).object()), QStringLiteral("2")));
QCOMPARE(mgr.rowCount(), 2);
// retrieval
auto idx = mgr.index(0, 0);
......@@ -53,6 +55,19 @@ private Q_SLOTS:
QCOMPARE(idx.data(PassManager::NameRole).toString(), QLatin1String("BahnCard 25 (2. Kl.) (BC25)"));
QVERIFY(!mgr.pass(passId).isNull());
idx = mgr.index(1, 0);
const auto passId2 = idx.data(PassManager::PassIdRole).toString();
QVERIFY(!passId2.isEmpty());
const auto ticket = idx.data(PassManager::PassRole);
QVERIFY(!ticket.isNull());
QVERIFY(JsonLd::isA<Ticket>(ticket));
QCOMPARE(idx.data(PassManager::PassTypeRole).toInt(), PassManager::Ticket);
QVERIFY(!idx.data(PassManager::PassDataRole).toByteArray().isEmpty());
QCOMPARE(idx.data(PassManager::NameRole).toString(), QLatin1String("9-Euro-Ticket"));
QVERIFY(!mgr.pass(passId2).isNull());
mgr.remove(passId2);
QCOMPARE(mgr.rowCount(), 1);
{
// test persistence
PassManager mgr2;
......
......@@ -20,6 +20,10 @@ Kirigami.ScrollablePage {
id: pkpassComponent
App.GenericPkPassPage {}
}
Component {
id: ticketComponent
App.TicketPage {}
}
Models.DelegateChooser {
id: chooser
......@@ -53,6 +57,16 @@ Kirigami.ScrollablePage {
onClicked: applicationWindow().pageStack.push(pkpassComponent, { passId: pkPassId, pass: pkPass, genericPassId: model.passId });
}
}
Models.DelegateChoice {
roleValue: PassManager.Ticket
Kirigami.BasicListItem {
highlighted: false
icon: "bookmarks"
text: model.pass.name
subtitle: model.pass.underName.name
onClicked: applicationWindow().pageStack.push(ticketComponent, { ticket: model.pass, passId: model.passId })
}
}
}
KSortFilterProxyModel {
......
/*
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 as QQC2
import org.kde.kirigami 2.19 as Kirigami
import org.kde.kitinerary 1.0
import org.kde.itinerary 1.0
import "." as App
Kirigami.ScrollablePage {
id: root
title: i18n("Ticket")
property var passId
property var ticket
BarcodeScanModeController {
id: scanModeController
page: root
}
Kirigami.OverlaySheet {
id: deleteWarningSheet
header: Kirigami.Heading {
text: i18n("Delete Ticket")
}
QQC2.Label {
text: i18n("Do you really want to delete this ticket?")
wrapMode: Text.WordWrap
}
footer: RowLayout {
QQC2.Button {
Layout.alignment: Qt.AlignHCenter
text: i18n("Delete")
icon.name: "edit-delete"
onClicked: {
PassManager.remove(passId)
applicationWindow().pageStack.pop();
}
}
}
}
actions.main: Kirigami.Action {
icon.name: "view-barcode-qr"
text: i18n("Barcode Scan Mode")
onTriggered: scanModeController.toggle()
visible: barcodeContainer.visible
checkable: true
checked: scanModeController.enabled
}
actions.contextualActions: [
Kirigami.Action {
icon.name: "edit-delete"
text: i18n("Delete")
onTriggered: deleteWarningSheet.open()
}
]
ColumnLayout {
width: parent.width
QQC2.Label {
Layout.fillWidth: true
text: root.ticket.name
horizontalAlignment: Qt.AlignHCenter
font.bold: true
}
App.BarcodeContainer {
id: barcodeContainer
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
barcodeType: root.ticket.ticketTokenType
barcodeContent: root.ticket.ticketTokenData
onDoubleClicked: scanModeController.toggle()
}
Kirigami.FormLayout {
Layout.fillWidth: true
Kirigami.Separator {
Kirigami.FormData.label: i18n("Ticket")
Kirigami.FormData.isSection: true
visible: nameLabel.visible || numberLabel.visible || classLabel.visible
}
QQC2.Label {
id: nameLabel
Kirigami.FormData.label: i18n("Name:")
text: ticket.underName.name
visible: ticket.underName.name !== ""
}
QQC2.Label {
id: numberLabel
Kirigami.FormData.label: i18n("Number:")
text: ticket.ticketNumber
visible: ticket.ticketNumber !== ""
}
QQC2.Label {
id: classLabel
Kirigami.FormData.label: i18n("Class:")
text: ticket.ticketedSeat.seatingType
visible: ticket.ticketedSeat.seatingType !== ""
}
}
}
}
......@@ -10,6 +10,7 @@
#include <KItinerary/ExtractorPostprocessor>
#include <KItinerary/JsonLdDocument>
#include <KItinerary/ProgramMembership>
#include <KItinerary/Ticket>
#include <QDirIterator>
#include <QJsonDocument>
......@@ -43,7 +44,7 @@ int PassManager::rowCount(const QModelIndex &parent) const
bool PassManager::import(const QVariant &pass, const QString &id)
{
if (JsonLd::isA<KItinerary::ProgramMembership>(pass) || JsonLd::isA<GenericPkPass>(pass)) {
if (JsonLd::isA<KItinerary::ProgramMembership>(pass) || JsonLd::isA<GenericPkPass>(pass) || JsonLd::isA<KItinerary::Ticket>(pass)) {
Entry entry;
entry.id = id.isEmpty() ? QUuid::createUuid().toString() : id;
entry.data = pass;
......@@ -149,6 +150,9 @@ QVariant PassManager::data(const QModelIndex &index, int role) const
if (JsonLd::isA<GenericPkPass>(entry.data)) {
return PkPass;
}
if (JsonLd::isA<KItinerary::Ticket>(entry.data)) {
return Ticket;
}
return {};
case PassDataRole:
return rawData(entry);
......@@ -160,6 +164,9 @@ QVariant PassManager::data(const QModelIndex &index, int role) const
if (JsonLd::isA<GenericPkPass>(entry.data)) {
return entry.data.value<GenericPkPass>().name();
}
if (JsonLd::isA<KItinerary::Ticket>(entry.data)) {
return entry.data.value<KItinerary::Ticket>().name();
}
return {};
}
......
......@@ -29,7 +29,8 @@ public:
enum PassType {
ProgramMembership,
PkPass
PkPass,
Ticket,
};
Q_ENUM(PassType)
......
......@@ -73,6 +73,7 @@
<file>StatisticsDelegate.qml</file>
<file>StatisticsPage.qml</file>
<file>StopPickerPage.qml</file>
<file>TicketPage.qml</file>
<file>TicketTokenDelegate.qml</file>
<file>TimeInput.qml</file>
<file>TimelineDelegate.qml</file>
......
Supports Markdown
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