KItinerary

sortutil.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "sortutil.h"
8
9#include <KItinerary/BoatTrip>
10#include <KItinerary/BusTrip>
11#include <KItinerary/Event>
12#include <KItinerary/Flight>
13#include <KItinerary/MergeUtil>
14#include <KItinerary/Person>
15#include <KItinerary/Place>
16#include <KItinerary/RentalCar>
17#include <KItinerary/Reservation>
18#include <KItinerary/Ticket>
19#include <KItinerary/TrainTrip>
20#include <KItinerary/Visit>
21
22#include "knowledgedb/airportdb.h"
23
24#include <QDateTime>
25#include <QTimeZone>
26
27using namespace KItinerary;
28
30{
31 // reservation types
33 return elem.value<FoodEstablishmentReservation>().startTime();
34 }
36 const auto hotel = elem.value<LodgingReservation>();
37 // hotel checkin/checkout is always considered the first/last thing of the day
38 auto dt = QDateTime(hotel.checkinTime().date(), QTime(23, 59, 59));
39 if (hotel.checkinTime().timeSpec() == Qt::TimeZone) {
40 dt.setTimeZone(hotel.checkinTime().timeZone());
41 }
42 return dt;
43 }
45 return elem.value<RentalCarReservation>().pickupTime();
46 }
48 return elem.value<TaxiReservation>().pickupTime();
49 }
51 const auto res = JsonLd::convert<Reservation>(elem).reservationFor();
52 return startDateTime(res);
53 }
55 return elem.value<TouristAttractionVisit>().arrivalTime();
56 }
57
58 // "reservationFor" types
59 if (JsonLd::isA<Flight>(elem)) {
60 const auto flight = elem.value<Flight>();
61 if (flight.departureTime().isValid()) {
62 return flight.departureTime();
63 }
64 if (flight.boardingTime().isValid()) {
65 return flight.boardingTime();
66 }
67 QDateTime dt(flight.departureDay(), QTime(23, 59, 59));
68 dt.setTimeZone(KnowledgeDb::timezoneForAirport(KnowledgeDb::IataCode{flight.departureAirport().iataCode()}));
69 return dt;
70 }
71 if (JsonLd::isA<TrainTrip>(elem)) {
72 const auto trip = elem.value<TrainTrip>();
73 if (trip.departureTime().isValid()) {
74 return trip.departureTime();
75 }
76 return QDateTime(trip.departureDay(), QTime(23, 59, 59));
77 }
78 if (JsonLd::isA<BusTrip>(elem)) {
79 return elem.value<BusTrip>().departureTime();
80 }
81 if (JsonLd::isA<BoatTrip>(elem)) {
82 return elem.value<BoatTrip>().departureTime();
83 }
84 if (JsonLd::isA<Event>(elem)) {
85 return elem.value<Event>().startDate();
86 }
87
88 return {};
89}
90
92{
93 // reservation types
95 auto endTime = elem.value<FoodEstablishmentReservation>().endTime();
96 if (!endTime.isValid()) {
97 endTime = QDateTime(elem.value<FoodEstablishmentReservation>().startTime().date(), QTime(23, 59, 59));
98 }
99 return endTime;
100 }
102 return elem.value<RentalCarReservation>().dropoffTime();
103 }
105 const auto hotel = elem.value<LodgingReservation>();
106 // hotel checkin/checkout is always considered the first/last thing of the day
107 auto dt = QDateTime(hotel.checkoutTime().date(), QTime(0, 0, 0));
108 if (hotel.checkoutTime().timeSpec() == Qt::TimeZone) {
109 dt.setTimeZone(hotel.checkoutTime().timeZone());
110 }
111 return dt;
112 }
114 const auto res = JsonLd::convert<Reservation>(elem).reservationFor();
115 return endDateTime(res);
116 }
118 return elem.value<TouristAttractionVisit>().departureTime();
119 }
120
121 // "reservationFor" types
122 if (JsonLd::isA<Event>(elem)) {
123 return elem.value<Event>().endDate();
124 }
125 if (JsonLd::isA<Flight>(elem)) {
126 const auto flight = elem.value<Flight>();
127 if (flight.arrivalTime().isValid()) {
128 return flight.arrivalTime();
129 }
130 QDateTime dt(flight.departureDay(), QTime(23, 59, 59));
131 dt.setTimeZone(KnowledgeDb::timezoneForAirport(KnowledgeDb::IataCode{flight.arrivalAirport().iataCode()}));
132 return dt;
133 }
134 if (JsonLd::isA<TrainTrip>(elem)) {
135 const auto trip = elem.value<TrainTrip>();
136 if (trip.arrivalTime().isValid()) {
137 return trip.arrivalTime();
138 }
139 return QDateTime(trip.departureDay(), QTime(23, 59, 59));
140 }
141 if (JsonLd::isA<BusTrip>(elem)) {
142 return elem.value<BusTrip>().arrivalTime();
143 }
144 if (JsonLd::isA<BoatTrip>(elem)) {
145 return elem.value<BoatTrip>().arrivalTime();
146 }
147
148 return {};
149}
150
151bool SortUtil::isBefore(const QVariant &lhs, const QVariant &rhs)
152{
153 if (startDateTime(lhs) == startDateTime(rhs) && lhs.userType() == rhs.userType() && JsonLd::canConvert<Reservation>(lhs)) {
154 // sort by end date if available next, e.g. for overlapping hotel bookings
155 const auto lhsEndDt = endDateTime(lhs);
156 const auto rhsEndDt = endDateTime(rhs);
157 if (JsonLd::isA<LodgingReservation>(lhs) && lhsEndDt.isValid() && rhsEndDt.isValid() && lhsEndDt != rhsEndDt) {
158 return lhsEndDt < rhsEndDt;
159 }
160
161 // for multi-traveler reservations, sort by traveler name to achieve a stable result
162 const auto lhsRes = JsonLd::convert<Reservation>(lhs);
163 const auto rhsRes = JsonLd::convert<Reservation>(rhs);
164 if (!lhsRes.underName().isNull() && !rhsRes.underName().isNull() && MergeUtil::isSame(lhsRes.reservationFor(), rhsRes.reservationFor())) {
165 const auto lhsUN = lhsRes.underName().value<Person>();
166 const auto rhsUN = rhsRes.underName().value<Person>();
167
168 // for multi-ticket reservations for the same person, sort by ticket name
169 if (lhsUN.name() == rhsUN.name()) {
170 const auto lhsTicket = lhsRes.reservedTicket().value<Ticket>();
171 const auto rhsTicket = rhsRes.reservedTicket().value<Ticket>();
172 return lhsTicket.name() < rhsTicket.name();
173 }
174 return lhsUN.name() < rhsUN.name();
175 }
176 }
177 return startDateTime(lhs) < startDateTime(rhs);
178}
179
181{
183 return hasStartTime(JsonLd::convert<Reservation>(elem).reservationFor());
184 }
185 if (JsonLd::isA<TrainTrip>(elem)) {
186 return elem.value<TrainTrip>().departureTime().isValid();
187 }
188 if (JsonLd::isA<Flight>(elem)) {
189 return elem.value<Flight>().departureTime().isValid();
190 }
191
192 return SortUtil::startDateTime(elem).isValid();
193}
194
196{
198 return hasEndTime(JsonLd::convert<Reservation>(elem).reservationFor());
199 }
200 if (JsonLd::isA<TrainTrip>(elem)) {
201 return elem.value<TrainTrip>().arrivalTime().isValid();
202 }
203 if (JsonLd::isA<Flight>(elem)) {
204 return elem.value<Flight>().arrivalTime().isValid();
205 }
206
207 return SortUtil::endDateTime(elem).isValid();
208}
A boat or ferry trip.
Definition boattrip.h:23
A bus trip.
Definition bustrip.h:22
An event.
Definition event.h:21
A flight.
Definition flight.h:25
A hotel reservation.
Definition reservation.h:77
static bool isSame(const QVariant &lhs, const QVariant &rhs)
Checks if two Reservation or Trip values refer to the same booking element.
A person.
Definition person.h:20
A Rental Car reservation.
A Taxi reservation.
A booked ticket.
Definition ticket.h:41
A train trip.
Definition traintrip.h:24
bool canConvert(const QVariant &value)
Checks if the given value can be up-cast to T.
Definition datatypes.h:31
QTimeZone timezoneForAirport(IataCode iataCode)
Returns the timezone the airport with IATA code iataCode is in.
Definition airportdb.cpp:40
QDateTime startDateTime(const QVariant &elem)
Returns the (start) time associated with the given element.
Definition sortutil.cpp:29
bool isBefore(const QVariant &lhs, const QVariant &rhs)
Sorting function for top-level reservation/visit/event elements.
Definition sortutil.cpp:151
bool hasStartTime(const QVariant &elem)
Returns whether the given element has a start time.
Definition sortutil.cpp:180
bool hasEndTime(const QVariant &elem)
Returns whether the given element has an end time.
Definition sortutil.cpp:195
QDateTime endDateTime(const QVariant &res)
Returns the (end) time associated with the given element.
Definition sortutil.cpp:91
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
QDate date() const const
bool isValid() const const
void setTimeZone(const QTimeZone &toZone)
TimeZone
int userType() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.