diff --git a/src/app/TrainPage.qml b/src/app/TrainPage.qml index fc02ea1..ef30535 100644 --- a/src/app/TrainPage.qml +++ b/src/app/TrainPage.qml @@ -1,218 +1,219 @@ /* Copyright (C) 2018 Volker Krause 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 . */ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.1 as QQC2 import org.kde.kirigami 2.4 as Kirigami import org.kde.kpublictransport 1.0 as KPublicTransport import org.kde.kitinerary 1.0 import org.kde.itinerary 1.0 import "." as App App.DetailsPage { id: root title: i18n("Train Ticket") editor: Component { App.TrainEditor { batchId: root.batchId } } Component { id: alternativePage App.JourneyQueryPage { controller: root.controller } } Component { id: vehicleLayoutPage App.VehicleLayoutPage { publicTransportManager: root.controller.liveDataManager.publicTransportManager departure: root.departure + selectedVehicleSection: root.reservation.reservedTicket.ticketedSeat.seatSection } } Component { id: alternativeAction Kirigami.Action { text: i18n("Alternatives") iconName: "clock" onTriggered: { applicationWindow().pageStack.push(alternativePage); } } } Component { id: vehicleLayoutAction Kirigami.Action { text: i18n("Vehicle Layout") iconName: "view-list-symbolic" enabled: departure && departure.route.line.mode == KPublicTransport.Line.LongDistanceTrain onTriggered: { applicationWindow().pageStack.push(vehicleLayoutPage); } } } Component.onCompleted: { actions.contextualActions.push(alternativeAction.createObject(root)); actions.contextualActions.push(vehicleLayoutAction.createObject(root)); } ColumnLayout { width: parent.width QQC2.Label { Layout.fillWidth: true text: reservationFor.trainName + " " + reservationFor.trainNumber horizontalAlignment: Qt.AlignHCenter font.bold: true } // ticket barcode App.TicketTokenDelegate { resIds: _reservationManager.reservationsForBatch(root.batchId) onCurrentReservationIdChanged: { if (!currentReservationId) return; root.currentReservationId = currentReservationId; } } Kirigami.FormLayout { Layout.fillWidth: true // departure data Kirigami.Separator { Kirigami.FormData.isSection: true Kirigami.FormData.label: i18n("Departure") } RowLayout { Kirigami.FormData.label: i18n("Time:") QQC2.Label { text: Localizer.formatDateTime(reservationFor, "departureTime") } QQC2.Label { text: (departure.departureDelay >= 0 ? "+" : "") + departure.departureDelay color: (departure.departureDelay > 1) ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor visible: departure.hasExpectedDepartureTime } } QQC2.Label { Kirigami.FormData.label: i18n("Station:") text: reservationFor.departureStation.name } App.PlaceDelegate { place: reservationFor.departureStation controller: root.controller isRangeBegin: true } RowLayout { Kirigami.FormData.label: i18n("Platform:") QQC2.Label { text: departure.hasExpectedPlatform ? departure.expectedPlatform : reservationFor.departurePlatform color: departure.platformChanged ? Kirigami.Theme.negativeTextColor : departure.hasExpectedPlatform ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.textColor; } QQC2.Label { text: i18n("(was: %1)", reservationFor.departurePlatform) visible: departure.platformChanged && reservationFor.departurePlatform != "" } } // arrival data Kirigami.Separator { Kirigami.FormData.isSection: true Kirigami.FormData.label: i18n("Arrival") } RowLayout { Kirigami.FormData.label: i18n("Arrival time:") QQC2.Label { text: Localizer.formatDateTime(reservationFor, "arrivalTime") } QQC2.Label { text: (arrival.arrivalDelay >= 0 ? "+" : "") + arrival.arrivalDelay color: (arrival.arrivalDelay > 1) ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor visible: arrival.hasExpectedArrivalTime } } QQC2.Label { Kirigami.FormData.label: i18n("Station:") text: reservationFor.arrivalStation.name } App.PlaceDelegate { place: reservationFor.arrivalStation controller: root.controller isRangeEnd: true } RowLayout { Kirigami.FormData.label: i18n("Platform:") QQC2.Label { text: arrival.hasExpectedPlatform ? arrival.expectedPlatform : reservationFor.arrivalPlatform color: arrival.platformChanged ? Kirigami.Theme.negativeTextColor : arrival.hasExpectedPlatform ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.textColor; } QQC2.Label { text: i18n("(was: %1)", reservationFor.arrivalPlatform) visible: arrival.platformChanged && reservationFor.arrivalPlatform != "" } } // seat reservation Kirigami.Separator { Kirigami.FormData.label: i18n("Seat") Kirigami.FormData.isSection: true visible: reservation.reservedTicket.ticketedSeat.seatNumber != "" || reservation.reservedTicket.ticketedSeat.seatSection != "" || reservation.reservedTicket.ticketedSeat.seatingType != "" } QQC2.Label { Kirigami.FormData.label: i18n("Coach:") text: reservation.reservedTicket.ticketedSeat.seatSection visible: reservation.reservedTicket.ticketedSeat.seatSection != "" } QQC2.Label { Kirigami.FormData.label: i18n("Seat:") text: reservation.reservedTicket.ticketedSeat.seatNumber visible: reservation.reservedTicket.ticketedSeat.seatNumber != "" } QQC2.Label { Kirigami.FormData.label: i18n("Class:") text: reservation.reservedTicket.ticketedSeat.seatingType visible: reservation.reservedTicket.ticketedSeat.seatingType != "" } // booking details Kirigami.Separator { Kirigami.FormData.label: i18n("Booking") Kirigami.FormData.isSection: true } QQC2.Label { Kirigami.FormData.label: i18n("Reference:") text: reservation.reservationNumber } QQC2.Label { Kirigami.FormData.label: i18n("Under name:") text: reservation.underName.name } } } } diff --git a/src/app/VehicleLayoutPage.qml b/src/app/VehicleLayoutPage.qml index c499c50..9a43257 100644 --- a/src/app/VehicleLayoutPage.qml +++ b/src/app/VehicleLayoutPage.qml @@ -1,196 +1,202 @@ /* Copyright (C) 2019 Volker Krause 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 . */ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.1 as QQC2 import org.kde.kirigami 2.4 as Kirigami import org.kde.kpublictransport 1.0 as KPublicTransport import org.kde.kpublictransport.ui 1.0 import org.kde.itinerary 1.0 Kirigami.Page { id: root title: i18n("Vehicle Layout") property alias publicTransportManager: vehicleModel.manager property var departure + property string selectedVehicleSection onDepartureChanged: vehicleModel.request.departure = root.departure; KPublicTransport.VehicleLayoutQueryModel { id: vehicleModel } + function colorMix(bg, fg, alpha) + { + return Qt.tint(bg, Qt.rgba(fg.r, fg.g, fg.b, alpha)); + } + ColumnLayout { id: contentLayout anchors.fill: parent QQC2.Label { text: vehicleModel.departure.stopPoint.name + " - " + vehicleModel.departure.route.line.name + " - " + Localizer.formatDateTime(vehicleModel.departure, "scheduledDepartureTime") } QQC2.Label { text: i18n("Platform: %1", vehicleModel.platform.name) } Flickable { id: vehicleView property real fullLength: 1600 // full length of the platform display property real sectionWidth: 48 clip: true contentHeight: fullLength Layout.fillWidth: true Layout.fillHeight: true QQC2.ScrollBar.vertical: QQC2.ScrollBar {} Repeater { Layout.fillWidth: true; model: vehicleModel.platform.sections delegate: Item { property var section: modelData width: parent.width y: section.begin * vehicleView.fullLength height: section.end * vehicleView.fullLength - y Kirigami.Separator { visible: index == 0 anchors { top: parent.top; left: parent.left; right: parent.right } } QQC2.Label { anchors.centerIn: parent text: section.name } Kirigami.Separator { anchors { bottom: parent.bottom; left: parent.left; right: parent.right } } } } Kirigami.Icon { visible: vehicleModel.vehicle.direction != KPublicTransport.Vehicle.UnknownDirection source: { if (vehicleModel.vehicle.direction == KPublicTransport.Vehicle.Forward) return "go-up"; if (vehicleModel.vehicle.direction == KPublicTransport.Vehicle.Backward) return "go-down" return ""; } width: Kirigami.Units.iconSizes.small height: width x: vehicleView.sectionWidth / 2 - width / 2 y: vehicleModel.vehicle.platformPositionBegin * vehicleView.fullLength - height - Kirigami.Units.largeSpacing } Repeater { id: vehicleRepeater Layout.fillWidth: true model: vehicleModel delegate: VehicleSectionItem { section: model.vehicleSection y: section.platformPositionBegin * vehicleView.fullLength height: section.platformPositionEnd * vehicleView.fullLength - y width: vehicleView.sectionWidth textColor: Kirigami.Theme.textColor - firstClassBackground: Kirigami.Theme.positiveTextColor - secondClassBackground: Kirigami.Theme.focusColor - inaccessibleBackground: Kirigami.Theme.disabledTextColor - restaurantBackground: Kirigami.Theme.neutralTextColor + firstClassBackground: colorMix(Kirigami.Theme.backgroundColor, Kirigami.Theme.positiveTextColor, section.name == root.selectedVehicleSection ? 1 : 0.25) + secondClassBackground: colorMix(Kirigami.Theme.backgroundColor, Kirigami.Theme.focusColor, section.name == root.selectedVehicleSection ? 1 : 0.25) + inaccessibleBackground: colorMix(Kirigami.Theme.backgroundColor, Kirigami.Theme.disabledTextColor, section.name == root.selectedVehicleSection ? 1 : 0.25) + restaurantBackground: colorMix(Kirigami.Theme.backgroundColor, Kirigami.Theme.neutralTextColor, section.name == root.selectedVehicleSection ? 1 : 0.25) QQC2.Label { anchors.centerIn: parent text: section.name } ColumnLayout { anchors.verticalCenter: parent.verticalCenter anchors.left: parent.right anchors.leftMargin: Kirigami.Units.largeSpacing spacing: Kirigami.Units.smallSpacing RowLayout { spacing: Kirigami.Units.smallSpacing Repeater { model: section.featureList QQC2.Label { text: { switch (modelData) { case KPublicTransport.VehicleSection.AirConditioning: return "❄️"; case KPublicTransport.VehicleSection.Restaurant: return "🍴"; case KPublicTransport.VehicleSection.ToddlerArea: return "👶"; case KPublicTransport.VehicleSection.WheelchairAccessible: return "♿"; case KPublicTransport.VehicleSection.SilentArea: return "🔇"; case KPublicTransport.VehicleSection.BikeStorage: return "🚲"; } } } } } QQC2.Label { visible: section.classes != KPublicTransport.VehicleSection.UnknownClass text: { if (section.classes == KPublicTransport.VehicleSection.FirstClass) return i18n("First class"); if (section.classes == KPublicTransport.VehicleSection.SecondClass) return i18n("Second class"); if (section.classes == (KPublicTransport.VehicleSection.FirstClass | KPublicTransport.VehicleSection.SecondClass)) return i18n("First/second class"); return i18n("Unknown class"); } } } } } Kirigami.Icon { visible: vehicleModel.vehicle.direction != KPublicTransport.Vehicle.UnknownDirection source: { if (vehicleModel.vehicle.direction == KPublicTransport.Vehicle.Forward) return "go-up"; if (vehicleModel.vehicle.direction == KPublicTransport.Vehicle.Backward) return "go-down" return ""; } width: Kirigami.Units.iconSizes.small height: width x: vehicleView.sectionWidth / 2 - width / 2 y: vehicleModel.vehicle.platformPositionEnd * vehicleView.fullLength + Kirigami.Units.largeSpacing } } } QQC2.BusyIndicator { anchors.centerIn: contentLayout running: vehicleModel.loading } QQC2.Label { anchors.centerIn: contentLayout width: parent.width text: vehicleModel.errorMessage color: Kirigami.Theme.negativeTextColor wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter } QQC2.Label { anchors.centerIn: contentLayout width: parent.width visible: vehicleModel.errorMessage === "" && !vehicleModel.loading && vehicleRepeater.count === 0 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter text: i18n("No vehicle layout information available.") } }