diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -set(PIM_VERSION "5.9.43") +set(PIM_VERSION "5.9.44") project(KItinerary VERSION ${PIM_VERSION}) set(KF5_VERSION "5.48.0") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,7 @@ datatypes/ticket.cpp datatypes/traintrip.cpp datatypes/visit.cpp + datatypes/rentalcar.cpp jsapi/barcode.cpp jsapi/context.cpp @@ -119,6 +120,7 @@ Flight Organization Reservation + RentalCar Person Place Ticket diff --git a/src/calendarhandler.cpp b/src/calendarhandler.cpp --- a/src/calendarhandler.cpp +++ b/src/calendarhandler.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,7 @@ static void fillEventReservation(const QVector &reservations, const KCalCore::Event::Ptr &event); static void fillGeoPosition(const QVariant &place, const KCalCore::Event::Ptr &event); static void fillFoodReservation(const FoodEstablishmentReservation &reservation, const KCalCore::Event::Ptr &event); +static void fillRentalCarReservation(const RentalCarReservation &reservation, const KCalCore::Event::Ptr &event); #endif @@ -129,6 +131,8 @@ fillEventReservation(reservations, event); } else if (JsonLd::isA(reservation)) { fillFoodReservation(reservation.value(), event); + } else if (JsonLd::isA(reservation)) { + fillRentalCarReservation(reservation.value(), event); } else { return; } @@ -373,4 +377,45 @@ reservation.underName().value().name())); } + +static void fillRentalCarReservation(const RentalCarReservation &reservation, const KCalCore::Event::Ptr &event) +{ + const auto rentalCalPickup = reservation.pickUpLocation(); + const auto addressPickUp = rentalCalPickup.address(); + const auto rentalCar = reservation.reservationFor().value(); + event->setSummary(i18n("Rental Car reservation: %1", rentalCar.name())); +#ifdef HAVE_KCONTACTS + event->setLocation(i18nc(", , ", "%1, %2 %3, %4", + addressPickUp.streetAddress(), addressPickUp.postalCode(), + addressPickUp.addressLocality(), KContacts::Address::ISOtoCountry(addressPickUp.addressCountry()))); +#endif + fillGeoPosition(rentalCalPickup, event); + + event->setDtStart(reservation.pickupTime()); + event->setDtEnd(reservation.dropoffTime()); + event->setAllDay(true); + event->setTransparency(KCalCore::Event::Transparent); + event->setSummary(i18n("Rent car reservation: %1", rentalCar.name())); + + const QString pickUpAddress = i18nc(", , ", "%1, %2 %3, %4", + addressPickUp.streetAddress(), addressPickUp.postalCode(), + addressPickUp.addressLocality(), KContacts::Address::ISOtoCountry(addressPickUp.addressCountry())); + + const auto rentalCalDropOff = reservation.dropOffLocation(); + const auto addressDropOff = rentalCalDropOff.address(); + + + const QString dropAddress = i18nc(", , ", "%1, %2 %3, %4", + addressDropOff.streetAddress(), addressDropOff.postalCode(), + addressDropOff.addressLocality(), KContacts::Address::ISOtoCountry(addressDropOff.addressCountry())); + + const QString description = i18n("Reservation reference: %1\nUnder name: %2\nPickUp location: %3\nDropoff Location: %4", + reservation.reservationNumber(), + reservation.underName().value().name(), + pickUpAddress, + dropAddress); + + event->setDescription(description); +} + #endif diff --git a/src/datatypes/rentalcar.h b/src/datatypes/rentalcar.h new file mode 100644 --- /dev/null +++ b/src/datatypes/rentalcar.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2018 Laurent Montel + + 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 . +*/ + +#ifndef KITINERARY_RENTALCAR_H +#define KITINERARY_RENTALCAR_H + +#include "kitinerary_export.h" +#include "datatypes.h" + +namespace KItinerary { + +class RentalCarPrivate; + +/** An event. + * @see https://developers.google.com/gmail/markup/reference/event-reservation + */ +class KITINERARY_EXPORT RentalCar +{ + KITINERARY_GADGET(RentalCar) + KITINERARY_PROPERTY(QString, name, setName) + KITINERARY_PROPERTY(QString, model, setModel) + //Add more info : brand/rentalcompany +private: + QExplicitlySharedDataPointer d; +}; + +} + +Q_DECLARE_METATYPE(KItinerary::RentalCar) + +#endif // KITINERARY_RENTALCAR_H diff --git a/src/datatypes/rentalcar.cpp b/src/datatypes/rentalcar.cpp new file mode 100644 --- /dev/null +++ b/src/datatypes/rentalcar.cpp @@ -0,0 +1,40 @@ +/* + Copyright (C) 2018 Laurent Montel + + 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 . +*/ + +#include "rentalcar.h" +#include "datatypes_p.h" + +#include +#include + +using namespace KItinerary; + +namespace KItinerary { + +class RentalCarPrivate: public QSharedData { + +public: + QString name; + QString model; +}; + +KITINERARY_MAKE_SIMPLE_CLASS(RentalCar) +KITINERARY_MAKE_PROPERTY(RentalCar, QString, name, setName) +KITINERARY_MAKE_PROPERTY(RentalCar, QString, model, setModel) +} + +#include "moc_rentalcar.cpp" diff --git a/src/extractorpostprocessor.cpp b/src/extractorpostprocessor.cpp --- a/src/extractorpostprocessor.cpp +++ b/src/extractorpostprocessor.cpp @@ -77,6 +77,7 @@ FoodEstablishmentReservation processFoodEstablishmentReservation(FoodEstablishmentReservation res) const; TouristAttractionVisit processTouristAttractionVisit(TouristAttractionVisit visit) const; EventReservation processEventReservation(EventReservation res) const; + RentalCarReservation processRentalCarReservation(RentalCarReservation res) const; Event processEvent(Event event) const; template T processReservation(T res) const; @@ -125,6 +126,8 @@ elem = d->processBusReservation(elem.value()); } else if (JsonLd::isA(elem)) { elem = d->processEventReservation(elem.value()); + } else if (JsonLd::isA(elem)) { + elem = d->processRentalCarReservation(elem.value()); } d->mergeOrAppend(elem); @@ -392,6 +395,13 @@ return processReservation(res); } +RentalCarReservation ExtractorPostprocessorPrivate::processRentalCarReservation(RentalCarReservation res) const +{ + res.setPickUpLocation(processPlace(res.pickUpLocation())); + res.setDropOffLocation(processPlace(res.dropOffLocation())); + return processReservation(res); +} + FoodEstablishmentReservation ExtractorPostprocessorPrivate::processFoodEstablishmentReservation(FoodEstablishmentReservation res) const { res.setReservationFor(processPlace(res.reservationFor().value())); diff --git a/src/jsonlddocument.cpp b/src/jsonlddocument.cpp --- a/src/jsonlddocument.cpp +++ b/src/jsonlddocument.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,7 @@ MAKE_FACTORY(FoodEstablishment); MAKE_FACTORY(FoodEstablishmentReservation); MAKE_FACTORY(RentalCarReservation); + MAKE_FACTORY(RentalCar); MAKE_FACTORY(GeoCoordinates); MAKE_FACTORY(LodgingBusiness); MAKE_FACTORY(LodgingReservation); diff --git a/src/mergeutil.cpp b/src/mergeutil.cpp --- a/src/mergeutil.cpp +++ b/src/mergeutil.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ static bool isSameTouristAttractionVisit(const TouristAttractionVisit &lhs, const TouristAttractionVisit &rhs); static bool isSameTouristAttraction(const TouristAttraction &lhs, const TouristAttraction &rhs); static bool isSameEvent(const Event &lhs, const Event &rhs); +static bool isSameRentalCar(const RentalCar &lhs, const RentalCar &rhs); bool MergeUtil::isSame(const QVariant& lhs, const QVariant& rhs) { @@ -138,14 +140,29 @@ if (lhsRes.reservationNumber() != rhsRes.reservationNumber()) { return false; } - return isSame(lhsRes.reservationFor(), rhsRes.reservationFor()) && lhsRes.checkinTime().date() == rhsRes.checkinTime().date();; + return isSame(lhsRes.reservationFor(), rhsRes.reservationFor()) && lhsRes.checkinTime().date() == rhsRes.checkinTime().date(); } if (JsonLd::isA(lhs)) { const auto lhsHotel = lhs.value(); const auto rhsHotel = rhs.value(); return isSameLodingBusiness(lhsHotel, rhsHotel); } + // Rental Car + if (JsonLd::isA(lhs)) { + const auto lhsRes = lhs.value(); + const auto rhsRes = rhs.value(); + if (lhsRes.reservationNumber() != rhsRes.reservationNumber()) { + return false; + } + return isSame(lhsRes.reservationFor(), rhsRes.reservationFor()) && lhsRes.pickupTime().date() == rhsRes.pickupTime().date(); + } + if (JsonLd::isA(lhs)) { + const auto lhsEv = lhs.value(); + const auto rhsEv = rhs.value(); + return isSameRentalCar(lhsEv, rhsEv); + } + // restaurant reservation: same restaurant, same booking ref, same day if (JsonLd::isA(lhs)) { const auto lhsRes = lhs.value(); @@ -285,3 +302,8 @@ return equalAndPresent(lhs.name(), rhs.name()) && equalAndPresent(lhs.startDate(), rhs.startDate()); } + +static bool isSameRentalCar(const RentalCar &lhs, const RentalCar &rhs) +{ + return lhs.name() == rhs.name(); +} diff --git a/src/sortutil.cpp b/src/sortutil.cpp --- a/src/sortutil.cpp +++ b/src/sortutil.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,9 @@ if (JsonLd::isA(res)) { return res.value().startTime(); } + if (JsonLd::isA(res)) { + return res.value().pickupTime(); + } if (JsonLd::isA(res)) { const auto hotel = res.value(); // hotel checkin/checkout is always considered the first/last thing of the day @@ -88,6 +92,10 @@ } return endTime; } + if (JsonLd::isA(res)) { + return res.value().dropoffTime(); + } + if (JsonLd::isA(res)) { const auto hotel = res.value(); // hotel checkin/checkout is always considered the first/last thing of the day