Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 602428f3 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

Semantic formatter: add support for bus reservations

Differential Revision: https://phabricator.kde.org/D11397
parent e130eb01
......@@ -30,7 +30,9 @@ using namespace KCalCore;
QDateTime CalendarHandler::startDateTime(const QVariant &reservation)
{
if (reservation.userType() == qMetaTypeId<FlightReservation>() || reservation.userType() == qMetaTypeId<TrainReservation>()) {
if (reservation.userType() == qMetaTypeId<FlightReservation>()
|| reservation.userType() == qMetaTypeId<TrainReservation>()
|| reservation.userType() == qMetaTypeId<BusReservation>()) {
const auto trip = JsonLdDocument::readProperty(reservation, "reservationFor");
return JsonLdDocument::readProperty(trip, "departureTime").toDateTime();
} else if (reservation.userType() == qMetaTypeId<LodgingReservation>()) {
......@@ -69,6 +71,8 @@ void CalendarHandler::fillEvent(const QVariant &reservation, const KCalCore::Eve
fillLodgingReservation(reservation, event);
} else if (typeId == qMetaTypeId<TrainReservation>()) {
fillTrainReservation(reservation, event);
} else if (typeId == qMetaTypeId<BusReservation>()) {
fillBusReservation(reservation, event);
}
const auto bookingRef = JsonLdDocument::readProperty(reservation, "reservationNumber").toString();
......@@ -138,20 +142,12 @@ void CalendarHandler::fillFlightReservation(const QVariant &reservation, const K
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 @@ void CalendarHandler::fillTrainReservation(const QVariant &reservation, const KC
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");
......
......@@ -42,7 +42,9 @@ public:
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);
};
......
......@@ -55,6 +55,11 @@ bool TrainStation::operator!=(const TrainStation &other) const
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 @@ QString TrainTrip::arrivalTimeLocalized() const
{
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);
}
......@@ -91,6 +91,14 @@ public:
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 @@ private:
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 @@ class TrainReservation : protected Reservation
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(Seat)
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
......
......@@ -38,6 +38,8 @@ void ExtractorPostprocessor::process(const QVector<QVariant> &data)
d = processReservation(d);
} else if (d.userType() == qMetaTypeId<LodgingReservation>()) {
d = processReservation(d);
} else if (d.userType() == qMetaTypeId<BusReservation>()) {
d = processReservation(d);
}
if (filterReservation(d)) {
......@@ -191,7 +193,9 @@ bool ExtractorPostprocessor::filterReservation(const QVariant &res) const
if (resFor.userType() == qMetaTypeId<Flight>()) {
return filterFlight(resFor);
} else if (resFor.userType() == qMetaTypeId<TrainTrip>()) {
return filterTrainTrip(resFor);
return filterTrainOrBusTrip(resFor);
} else if (resFor.userType() == qMetaTypeId<BusTrip>()) {
return filterTrainOrBusTrip(resFor);
}
if (res.userType() == qMetaTypeId<LodgingReservation>()) {
......@@ -223,16 +227,16 @@ bool ExtractorPostprocessor::filterAirport(const QVariant &airport) const
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();
}
......@@ -44,8 +44,8 @@ private:
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<QVariant> m_data;
};
......
......@@ -105,6 +105,9 @@ static QVariant createInstance(const QJsonObject &obj)
MAKE_FACTORY(TrainStation);
MAKE_FACTORY(TrainTrip);
MAKE_FACTORY(TrainReservation);
MAKE_FACTORY(BusStation);
MAKE_FACTORY(BusTrip);
MAKE_FACTORY(BusReservation);
return {};
}
......
......@@ -58,6 +58,9 @@ GRANTLEE_MAKE_GADGET(Ticket)
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 @@ SemanticRenderer::SemanticRenderer()
Grantlee::registerMetaType<TrainStation>();
Grantlee::registerMetaType<TrainTrip>();
Grantlee::registerMetaType<TrainReservation>();
Grantlee::registerMetaType<BusStation>();
Grantlee::registerMetaType<BusTrip>();
Grantlee::registerMetaType<BusReservation>();
}
bool SemanticRenderer::render(const MimeTreeParser::MessagePartPtr &msgPart, MessageViewer::HtmlWriter *htmlWriter, MessageViewer::RenderContext *context) const
......
......@@ -154,7 +154,7 @@ bool SemanticUrlHandler::handleContextMenuRequest(MimeTreeParser::Interface::Bod
addGoToMapAction(&menu, airport);
places.insert(iataCode);
}
} else if (r.userType() == qMetaTypeId<TrainReservation>()) {
} else if (r.userType() == qMetaTypeId<TrainReservation>() || r.userType() == qMetaTypeId<BusReservation>()) {
const auto trip = JsonLdDocument::readProperty(r, "reservationFor");
auto station = JsonLdDocument::readProperty(trip, "departureStation");
......
......@@ -4,5 +4,6 @@
<file alias="flightreservation.html">templates/flightreservation.html</file>
<file alias="lodgingreservation.html">templates/lodgingreservation.html</file>
<file alias="trainreservation.html">templates/trainreservation.html</file>
<file alias="busreservation.html">templates/busreservation.html</file>
</qresource>
</RCC>
<table style="width:100%;">
<tr>
<td style="font-size:120%; width:33;">
{{ item.reservationFor.departureStation.name }}
{% if item.reservationFor.departurePlatform %}
[{{ item.reservationFor.departurePlatform }}]
{% endif %}
</td>
<td style="font-size:120%; width:33%; text-align:center;">&rarr;</td>
<td style="font-size:120%; width:33%;">
{{ item.reservationFor.arrivalStation.name}}
{% if item.reservationFor.arrivalPlatform %}
[{{ item.reservationFor.arrivalPlatform }}]
{% endif %}
</td>
</tr>
<tr>
<td>{{ item.reservationFor.departureTimeLocalized }}</td>
<td style="white-space: nowrap; text-align:center;">
{% if item.reservationFor.busName and item.reservationiFor.busNumber %}
{{ item.reservationFor.busName }} <br> {{ item.reservationFor.busNumber }}
{% else %}
{{ item.reservationFor.busName }} {{ item.reservationFor.busNumber }}
{% endif %}
</td>
<td>{{ item.reservationFor.arrivalTimeLocalized }}</td>
</tr>
<tr><td colspan="3">
<div style="float:left">
{% if elem.ticketToken %}
<a href="x-kmail:/bodypart/0//semanticExpand?{{ forloop.counter0 }}">
{% if elem.state.expanded %}
<img src="{{ style.collapseIcon }}" style="margin-right: 4px;"/>
{% else %}
<img src="{{ style.expandIcon }}" style="margin-right: 4px;"/>
{% endif %}
</a>
{% endif %}
{% if item.reservedTicket.ticketedSeat.seatNumber %}
{% i18n "Seat: %1" item.reservedTicket.ticketedSeat.seatNumber %}
{% endif %}
</div>
<div style="float:right">
{% if item.url %}
<a href="{{ item.url }}"/>{% i18n "View" %}</a>
{% if item.modifyReservationUrl or item.cancelReservationUrl %}|{% endif %}
{% endif %}
{% if item.modifyReservationUrl %}
<a href="{{ item.modifyReservationUrl }}"/>{% i18n "Modify" %}</a>
{% if item.cancelReservationUrl %}|{% endif %}
{% endif %}
{% if item.cancelReservationUrl %}
<a href="{{ item.cancelReservationUrl }}"/>{% i18n "Cancel" %}</a>
{% endif %}
</div>
</td></tr>
</table>
{% if elem.state.expanded %}
<div style="text-align:center;">
<div style="background-color: #ffffff; display: inline-block; padding: 4px;">
<img src="{{ elem.ticketToken }}"/>
</div>
</div>
{% endif %}
......@@ -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 %}
......
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