diff --git a/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.h b/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.h --- a/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.h +++ b/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.h @@ -42,7 +42,9 @@ private: static void fillFlightReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event); + static void fillTripReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event); static void fillTrainReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event); + static void fillBusReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event); static void fillLodgingReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event); static void fillGeoPosition(const QVariant &place, const KCalCore::Event::Ptr &event); }; diff --git a/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.cpp b/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/calendarhandler.cpp @@ -30,7 +30,9 @@ QDateTime CalendarHandler::startDateTime(const QVariant &reservation) { - if (reservation.userType() == qMetaTypeId() || reservation.userType() == qMetaTypeId()) { + if (reservation.userType() == qMetaTypeId() + || reservation.userType() == qMetaTypeId() + || reservation.userType() == qMetaTypeId()) { const auto trip = JsonLdDocument::readProperty(reservation, "reservationFor"); return JsonLdDocument::readProperty(trip, "departureTime").toDateTime(); } else if (reservation.userType() == qMetaTypeId()) { @@ -69,6 +71,8 @@ fillLodgingReservation(reservation, event); } else if (typeId == qMetaTypeId()) { fillTrainReservation(reservation, event); + } else if (typeId == qMetaTypeId()) { + fillBusReservation(reservation, event); } const auto bookingRef = JsonLdDocument::readProperty(reservation, "reservationNumber").toString(); @@ -138,20 +142,12 @@ event->setDescription(desc.join(QLatin1Char('\n'))); } -void CalendarHandler::fillTrainReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event) +void CalendarHandler::fillTripReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event) { const auto trip = JsonLdDocument::readProperty(reservation, "reservationFor"); const auto depStation = JsonLdDocument::readProperty(trip, "departureStation"); const auto arrStation = JsonLdDocument::readProperty(trip, "arrivalStation"); - if (trip.isNull() || depStation.isNull() || arrStation.isNull()) { - return; - } - event->setSummary(i18n("Train %1 from %2 to %3", - JsonLdDocument::readProperty(trip, "trainNumber").toString(), - JsonLdDocument::readProperty(depStation, "name").toString(), - JsonLdDocument::readProperty(arrStation, "name").toString() - )); event->setLocation(JsonLdDocument::readProperty(depStation, "name").toString()); fillGeoPosition(depStation, event); event->setDtStart(JsonLdDocument::readProperty(trip, "departureTime").toDateTime()); @@ -184,6 +180,40 @@ event->setDescription(desc.join(QLatin1Char('\n'))); } +void CalendarHandler::fillTrainReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event) +{ + const auto trip = JsonLdDocument::readProperty(reservation, "reservationFor"); + const auto depStation = JsonLdDocument::readProperty(trip, "departureStation"); + const auto arrStation = JsonLdDocument::readProperty(trip, "arrivalStation"); + if (trip.isNull() || depStation.isNull() || arrStation.isNull()) { + return; + } + + event->setSummary(i18n("Train %1 from %2 to %3", + JsonLdDocument::readProperty(trip, "trainNumber").toString(), + JsonLdDocument::readProperty(depStation, "name").toString(), + JsonLdDocument::readProperty(arrStation, "name").toString() + )); + fillTripReservation(reservation, event); +} + +void CalendarHandler::fillBusReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event) +{ + const auto trip = JsonLdDocument::readProperty(reservation, "reservationFor"); + const auto depStation = JsonLdDocument::readProperty(trip, "departureStation"); + const auto arrStation = JsonLdDocument::readProperty(trip, "arrivalStation"); + if (trip.isNull() || depStation.isNull() || arrStation.isNull()) { + return; + } + + event->setSummary(i18n("Bus %1 from %2 to %3", + JsonLdDocument::readProperty(trip, "busNumber").toString(), + JsonLdDocument::readProperty(depStation, "name").toString(), + JsonLdDocument::readProperty(arrStation, "name").toString() + )); + fillTripReservation(reservation, event); +} + void CalendarHandler::fillLodgingReservation(const QVariant &reservation, const KCalCore::Event::Ptr &event) { const auto lodgingBusiness = JsonLdDocument::readProperty(reservation, "reservationFor"); diff --git a/plugins/messageviewer/bodypartformatter/semantic/datatypes.h b/plugins/messageviewer/bodypartformatter/semantic/datatypes.h --- a/plugins/messageviewer/bodypartformatter/semantic/datatypes.h +++ b/plugins/messageviewer/bodypartformatter/semantic/datatypes.h @@ -91,6 +91,14 @@ bool operator!=(const TrainStation &other) const; }; +class BusStation : protected Place +{ + SEMANTIC_GADGET + SEMANTIC_PROPERTY(QString, name) +public: + bool operator!=(const BusStation &other) const; +}; + /** * @see https://schema.org/Flight * @see https://developers.google.com/gmail/markup/reference/flight-reservation @@ -144,6 +152,26 @@ QString arrivalTimeLocalized() const; }; +class BusTrip +{ + SEMANTIC_GADGET + SEMANTIC_PROPERTY(QString, arrivalPlatform) + SEMANTIC_PROPERTY(BusStation, arrivalStation) + SEMANTIC_PROPERTY(QDateTime, arrivalTime) + SEMANTIC_PROPERTY(QString, departurePlatform) + SEMANTIC_PROPERTY(BusStation, departureStation) + SEMANTIC_PROPERTY(QDateTime, departureTime) + SEMANTIC_PROPERTY(QString, busName) + SEMANTIC_PROPERTY(QString, busNumber) + + Q_PROPERTY(QString departureTimeLocalized READ departureTimeLocalized STORED false CONSTANT) + Q_PROPERTY(QString arrivalTimeLocalized READ arrivalTimeLocalized STORED false CONSTANT) + +private: + QString departureTimeLocalized() const; + QString arrivalTimeLocalized() const; +}; + class Seat { SEMANTIC_GADGET @@ -205,6 +233,11 @@ SEMANTIC_GADGET }; +class BusReservation : protected Reservation +{ + SEMANTIC_GADGET +}; + Q_DECLARE_METATYPE(GeoCoordinates) Q_DECLARE_METATYPE(Airport) Q_DECLARE_METATYPE(Airline) @@ -217,6 +250,10 @@ Q_DECLARE_METATYPE(Ticket) Q_DECLARE_METATYPE(TrainStation) Q_DECLARE_METATYPE(TrainTrip) +Q_DECLARE_METATYPE(TrainReservation) +Q_DECLARE_METATYPE(BusStation) +Q_DECLARE_METATYPE(BusTrip) +Q_DECLARE_METATYPE(BusReservation) #undef SEMANTIC_GADGET diff --git a/plugins/messageviewer/bodypartformatter/semantic/datatypes.cpp b/plugins/messageviewer/bodypartformatter/semantic/datatypes.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/datatypes.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/datatypes.cpp @@ -55,6 +55,11 @@ return m_name != other.m_name; } +bool BusStation::operator!=(const BusStation &other) const +{ + return m_name != other.m_name; +} + static QString localizedDateTime(const QDateTime &dt) { auto s = QLocale().toString(dt, QLocale::ShortFormat); @@ -102,3 +107,13 @@ { return QLocale().toString(m_arrivalTime, QLocale::ShortFormat); } + +QString BusTrip::departureTimeLocalized() const +{ + return QLocale().toString(m_departureTime, QLocale::ShortFormat); +} + +QString BusTrip::arrivalTimeLocalized() const +{ + return QLocale().toString(m_arrivalTime, QLocale::ShortFormat); +} diff --git a/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.h b/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.h --- a/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.h +++ b/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.h @@ -44,8 +44,8 @@ bool filterLodgingReservation(const QVariant &res) const; bool filterFlight(const QVariant &flight) const; bool filterAirport(const QVariant &airport) const; - bool filterTrainTrip(const QVariant &trip) const; - bool filterTrainStation(const QVariant &station) const; + bool filterTrainOrBusTrip(const QVariant &trip) const; + bool filterTrainOrBusStation(const QVariant &station) const; QVector m_data; }; diff --git a/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.cpp b/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/extractorpostprocessor.cpp @@ -38,6 +38,8 @@ d = processReservation(d); } else if (d.userType() == qMetaTypeId()) { d = processReservation(d); + } else if (d.userType() == qMetaTypeId()) { + d = processReservation(d); } if (filterReservation(d)) { @@ -191,7 +193,9 @@ if (resFor.userType() == qMetaTypeId()) { return filterFlight(resFor); } else if (resFor.userType() == qMetaTypeId()) { - return filterTrainTrip(resFor); + return filterTrainOrBusTrip(resFor); + } else if (resFor.userType() == qMetaTypeId()) { + return filterTrainOrBusTrip(resFor); } if (res.userType() == qMetaTypeId()) { @@ -223,16 +227,16 @@ return !iataCode.isEmpty() || !name.isEmpty(); } -bool ExtractorPostprocessor::filterTrainTrip(const QVariant &trip) const +bool ExtractorPostprocessor::filterTrainOrBusTrip(const QVariant &trip) const { const auto depDt = JsonLdDocument::readProperty(trip, "departureTime").toDateTime(); const auto arrDt = JsonLdDocument::readProperty(trip, "arrivalTime").toDateTime(); - return filterAirport(JsonLdDocument::readProperty(trip, "departureStation")) - && filterAirport(JsonLdDocument::readProperty(trip, "arrivalStation")) + return filterTrainOrBusStation(JsonLdDocument::readProperty(trip, "departureStation")) + && filterTrainOrBusStation(JsonLdDocument::readProperty(trip, "arrivalStation")) && depDt.isValid() && arrDt.isValid(); } -bool ExtractorPostprocessor::filterTrainStation(const QVariant &station) const +bool ExtractorPostprocessor::filterTrainOrBusStation(const QVariant &station) const { return !JsonLdDocument::readProperty(station, "name").toString().isEmpty(); } diff --git a/plugins/messageviewer/bodypartformatter/semantic/jsonlddocument.cpp b/plugins/messageviewer/bodypartformatter/semantic/jsonlddocument.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/jsonlddocument.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/jsonlddocument.cpp @@ -105,6 +105,9 @@ MAKE_FACTORY(TrainStation); MAKE_FACTORY(TrainTrip); MAKE_FACTORY(TrainReservation); + MAKE_FACTORY(BusStation); + MAKE_FACTORY(BusTrip); + MAKE_FACTORY(BusReservation); return {}; } diff --git a/plugins/messageviewer/bodypartformatter/semantic/semanticrenderer.cpp b/plugins/messageviewer/bodypartformatter/semantic/semanticrenderer.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/semanticrenderer.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/semanticrenderer.cpp @@ -58,6 +58,9 @@ GRANTLEE_MAKE_GADGET(TrainStation) GRANTLEE_MAKE_GADGET(TrainTrip) GRANTLEE_MAKE_GADGET(TrainReservation) +GRANTLEE_MAKE_GADGET(BusStation) +GRANTLEE_MAKE_GADGET(BusTrip) +GRANTLEE_MAKE_GADGET(BusReservation) SemanticRenderer::SemanticRenderer() { @@ -73,6 +76,9 @@ Grantlee::registerMetaType(); Grantlee::registerMetaType(); Grantlee::registerMetaType(); + Grantlee::registerMetaType(); + Grantlee::registerMetaType(); + Grantlee::registerMetaType(); } bool SemanticRenderer::render(const MimeTreeParser::MessagePartPtr &msgPart, MessageViewer::HtmlWriter *htmlWriter, MessageViewer::RenderContext *context) const diff --git a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp @@ -154,7 +154,7 @@ addGoToMapAction(&menu, airport); places.insert(iataCode); } - } else if (r.userType() == qMetaTypeId()) { + } else if (r.userType() == qMetaTypeId() || r.userType() == qMetaTypeId()) { const auto trip = JsonLdDocument::readProperty(r, "reservationFor"); auto station = JsonLdDocument::readProperty(trip, "departureStation"); diff --git a/plugins/messageviewer/bodypartformatter/semantic/templates.qrc b/plugins/messageviewer/bodypartformatter/semantic/templates.qrc --- a/plugins/messageviewer/bodypartformatter/semantic/templates.qrc +++ b/plugins/messageviewer/bodypartformatter/semantic/templates.qrc @@ -4,5 +4,6 @@ templates/flightreservation.html templates/lodgingreservation.html templates/trainreservation.html + templates/busreservation.html diff --git a/plugins/messageviewer/bodypartformatter/semantic/templates/busreservation.html b/plugins/messageviewer/bodypartformatter/semantic/templates/busreservation.html new file mode 100644 --- /dev/null +++ b/plugins/messageviewer/bodypartformatter/semantic/templates/busreservation.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + +
+ {{ item.reservationFor.departureStation.name }} + {% if item.reservationFor.departurePlatform %} + [{{ item.reservationFor.departurePlatform }}] + {% endif %} + + {{ item.reservationFor.arrivalStation.name}} + {% if item.reservationFor.arrivalPlatform %} + [{{ item.reservationFor.arrivalPlatform }}] + {% endif %} +
{{ item.reservationFor.departureTimeLocalized }} + {% if item.reservationFor.busName and item.reservationiFor.busNumber %} + {{ item.reservationFor.busName }}
{{ item.reservationFor.busNumber }} + {% else %} + {{ item.reservationFor.busName }} {{ item.reservationFor.busNumber }} + {% endif %} +
{{ item.reservationFor.arrivalTimeLocalized }}
+
+ {% if elem.ticketToken %} + + {% if elem.state.expanded %} + + {% else %} + + {% endif %} + + {% endif %} + + {% if item.reservedTicket.ticketedSeat.seatNumber %} + {% i18n "Seat: %1" item.reservedTicket.ticketedSeat.seatNumber %} + {% endif %} +
+ +
+ {% if item.url %} + {% i18n "View" %} + {% if item.modifyReservationUrl or item.cancelReservationUrl %}|{% endif %} + {% endif %} + + {% if item.modifyReservationUrl %} + {% i18n "Modify" %} + {% if item.cancelReservationUrl %}|{% endif %} + {% endif %} + + {% if item.cancelReservationUrl %} + {% i18n "Cancel" %} + {% endif %} +
+ +
+ +{% if elem.state.expanded %} +
+
+ +
+
+{% endif %} diff --git a/plugins/messageviewer/bodypartformatter/semantic/templates/semantic.html b/plugins/messageviewer/bodypartformatter/semantic/templates/semantic.html --- a/plugins/messageviewer/bodypartformatter/semantic/templates/semantic.html +++ b/plugins/messageviewer/bodypartformatter/semantic/templates/semantic.html @@ -10,6 +10,8 @@ {% include ":/org.kde.messageviewer/semantic/lodgingreservation.html" %} {% elif item.className == "TrainReservation" %} {% include ":/org.kde.messageviewer/semantic/trainreservation.html" %} + {% elif item.className == "BusReservation" %} + {% include ":/org.kde.messageviewer/semantic/busreservation.html" %} {% endif %} {% if not forloop.last %}