KPublicTransport

journey.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 "journey.h"
8
9#include "identifier_p.h"
10#include "journeyutil_p.h"
11#include "json_p.h"
12#include "datatypes_p.h"
13#include "loadutil_p.h"
14#include "logging.h"
15#include "mergeutil_p.h"
16#include "notesutil_p.h"
17#include "platformutils_p.h"
18#include "rentalvehicle.h"
19#include "rentalvehicleutil_p.h"
20#include "stopover.h"
21
22#include <KLocalizedString>
23
24#include <QDebug>
25#include <QVariant>
26
27using namespace Qt::Literals::StringLiterals;
28using namespace KPublicTransport;
29
30namespace KPublicTransport {
31
32class JourneySectionPrivate : public QSharedData
33{
34public:
35 [[nodiscard]] bool isValidIndex(qsizetype idx) const;
36
37 JourneySection::Mode mode = JourneySection::Invalid;
38 QDateTime scheduledDepartureTime;
39 QDateTime expectedDepartureTime;
40 QDateTime scheduledArrivalTime;
41 QDateTime expectedArrivalTime;
42 Location from;
43 Location to;
44 Route route;
45 QString scheduledDeparturePlatform;
46 QString expectedDeparturePlatform;
47 QString scheduledArrivalPlatform;
48 QString expectedArrivalPlatform;
49 int distance = 0;
50 Disruption::Effect disruptionEffect = Disruption::NormalService;
51 QStringList notes;
52 std::vector<Stopover> intermediateStops;
53 int co2Emission = -1;
54 std::vector<LoadInfo> loadInformation;
55 RentalVehicle rentalVehicle;
56 Path path;
57 Vehicle departureVehicleLayout;
58 Platform departurePlatformLayout;
59 Vehicle arrivalVehicleLayout;
60 Platform arrivalPlatformLayout;
61 IndividualTransport individualTransport;
62 IdentifierSet ids;
63};
64
65class JourneyPrivate : public QSharedData
66{
67public:
68 std::vector<JourneySection> sections;
69};
70
71}
72
73KPUBLICTRANSPORT_MAKE_GADGET(JourneySection)
74KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, JourneySection::Mode, mode, setMode)
75KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, scheduledDepartureTime, setScheduledDepartureTime)
76KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, expectedDepartureTime, setExpectedDepartureTime)
77KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, scheduledArrivalTime, setScheduledArrivalTime)
78KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, expectedArrivalTime, setExpectedArrivalTime)
79KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Location, from, setFrom)
80KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Location, to, setTo)
81KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Route, route, setRoute)
82KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Disruption::Effect, disruptionEffect, setDisruptionEffect)
83KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QStringList, notes, setNotes)
84KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, RentalVehicle, rentalVehicle, setRentalVehicle)
85KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Path, path, setPath)
86KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Vehicle, departureVehicleLayout, setDepartureVehicleLayout)
87KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Platform, departurePlatformLayout, setDeparturePlatformLayout)
88KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Vehicle, arrivalVehicleLayout, setArrivalVehicleLayout)
89KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Platform, arrivalPlatformLayout, setArrivalPlatformLayout)
90KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, KPublicTransport::IndividualTransport, individualTransport, setIndividualTransport)
91
92bool JourneySectionPrivate::isValidIndex(qsizetype idx) const
93{
94 return idx >= 0 && idx <= (qsizetype)(intermediateStops.size()) + 1;
95}
96
98{
99 return d->expectedDepartureTime.isValid();
100}
101
103{
105 return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
106 }
107 return 0;
108}
109
111{
112 return d->expectedArrivalTime.isValid();
113}
114
116{
118 return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
119 }
120 return 0;
121}
122
123int JourneySection::duration() const
124{
125 return d->scheduledDepartureTime.secsTo(d->scheduledArrivalTime);
126}
127
128int JourneySection::distance() const
129{
130 if (d->mode == JourneySection::Waiting) {
131 return 0;
132 }
133
134 double dist = 0;
135 if (d->from.hasCoordinate() && d->to.hasCoordinate()) {
136 auto startLat = d->from.latitude();
137 auto startLon = d->from.longitude();
138
139 for (const auto &stop : d->intermediateStops) {
140 if (!stop.stopPoint().hasCoordinate()) {
141 continue;
142 }
143 dist += Location::distance(startLat, startLon, stop.stopPoint().latitude(), stop.stopPoint().longitude());
144 startLat = stop.stopPoint().latitude();
145 startLon = stop.stopPoint().longitude();
146 }
147
148 dist += Location::distance(startLat, startLon, d->to.latitude(), d->to.longitude());
149 }
150 dist = std::max<double>(dist, d->path.distance());
151 return std::max((int)std::round(dist), d->distance);
152}
153
154void JourneySection::setDistance(int value)
155{
156 d.detach();
157 d->distance = value;
158}
159
161{
162 return d->scheduledDeparturePlatform;
163}
164
165void JourneySection::setScheduledDeparturePlatform(const QString &platform)
166{
167 d.detach();
168 d->scheduledDeparturePlatform = PlatformUtils::normalizePlatform(platform);
169}
170
172{
173 return d->expectedDeparturePlatform;
174}
175
176void JourneySection::setExpectedDeparturePlatform(const QString &platform)
177{
178 d.detach();
179 d->expectedDeparturePlatform = PlatformUtils::normalizePlatform(platform);
180}
181
183{
184 return !d->expectedDeparturePlatform.isEmpty();
185}
186
188{
189 return PlatformUtils::platformChanged(d->scheduledDeparturePlatform, d->expectedDeparturePlatform);
190}
191
193{
194 return d->scheduledArrivalPlatform;
195}
196
197void JourneySection::setScheduledArrivalPlatform(const QString &platform)
198{
199 d.detach();
200 d->scheduledArrivalPlatform = PlatformUtils::normalizePlatform(platform);
201}
202
204{
205 return d->expectedArrivalPlatform;
206}
207
208void JourneySection::setExpectedArrivalPlatform(const QString &platform)
209{
210 d.detach();
211 d->expectedArrivalPlatform = PlatformUtils::normalizePlatform(platform);
212}
213
215{
216 return !d->expectedArrivalPlatform.isEmpty();
217}
218
220{
221 return PlatformUtils::platformChanged(d->scheduledArrivalPlatform, d->expectedArrivalPlatform);
222}
223
225{
226 const auto n = NotesUtil::normalizeNote(note);
227 const auto idx = NotesUtil::needsAdding(d->notes, n);
228 if (idx >= 0) {
229 d.detach();
230 NotesUtil::performAdd(d->notes, n, idx);
231 }
232}
233
234void JourneySection::addNotes(const QStringList &notes)
235{
236 for (const auto &n : notes) {
237 addNote(n);
238 }
239}
240
241const std::vector<Stopover>& JourneySection::intermediateStops() const
242{
243 return d->intermediateStops;
244}
245
247{
248 d.detach();
249 return std::move(d->intermediateStops);
250}
251
252void JourneySection::setIntermediateStops(std::vector<Stopover> &&stops)
253{
254 d.detach();
255 d->intermediateStops = std::move(stops);
256}
257
258QVariantList JourneySection::intermediateStopsVariant() const
259{
260 QVariantList l;
261 l.reserve(d->intermediateStops.size());
262 std::transform(d->intermediateStops.begin(), d->intermediateStops.end(), std::back_inserter(l), [](const auto &stop) { return QVariant::fromValue(stop); });
263 return l;
264}
265
267{
268 Stopover dep;
269 dep.setStopPoint(from());
270 dep.setRoute(route());
271 dep.setScheduledDepartureTime(scheduledDepartureTime());
272 dep.setExpectedDepartureTime(expectedDepartureTime());
273 dep.setScheduledPlatform(scheduledDeparturePlatform());
274 dep.setExpectedPlatform(expectedDeparturePlatform());
275 dep.addNotes(notes());
276 dep.setDisruptionEffect(disruptionEffect());
277 dep.setVehicleLayout(departureVehicleLayout());
278 dep.setPlatformLayout(departurePlatformLayout());
279 return dep;
280}
281
283{
284 setFrom(departure.stopPoint());
285 setScheduledDepartureTime(departure.scheduledDepartureTime());
286 setExpectedDepartureTime(departure.expectedDepartureTime());
287 setScheduledDeparturePlatform(departure.scheduledPlatform());
288 setExpectedDeparturePlatform(departure.expectedPlatform());
289 setDeparturePlatformLayout(departure.platformLayout());
290 setDepartureVehicleLayout(departure.vehicleLayout());
291 if (departure.disruptionEffect() == Disruption::NoService) {
292 setDisruptionEffect(departure.disruptionEffect());
293 }
294}
295
297{
298 Stopover arr;
299 arr.setStopPoint(to());
300 arr.setRoute(route());
301 arr.setScheduledArrivalTime(scheduledArrivalTime());
302 arr.setExpectedArrivalTime(expectedArrivalTime());
303 arr.setScheduledPlatform(scheduledArrivalPlatform());
304 arr.setExpectedPlatform(expectedArrivalPlatform());
305 arr.setDisruptionEffect(disruptionEffect());
306 arr.setVehicleLayout(arrivalVehicleLayout());
307 arr.setPlatformLayout(arrivalPlatformLayout());
308 return arr;
309}
310
312{
313 setTo(arrival.stopPoint());
314 setScheduledArrivalTime(arrival.scheduledArrivalTime());
315 setExpectedArrivalTime(arrival.expectedArrivalTime());
316 setScheduledArrivalPlatform(arrival.scheduledPlatform());
317 setExpectedArrivalPlatform(arrival.expectedPlatform());
318 setArrivalPlatformLayout(arrival.platformLayout());
319 setArrivalVehicleLayout(arrival.vehicleLayout());
320 if (arrival.disruptionEffect() == Disruption::NoService) {
321 setDisruptionEffect(arrival.disruptionEffect());
322 }
323}
324
325struct {
326 Line::Mode mode;
327 int gramPerKm;
328} static constexpr const emissionForModeMap[] = {
329 { Line::Air, 285 },
330 { Line::Boat, 245 },
331 { Line::Bus, 68 },
332 { Line::Coach, 68 },
333 { Line::Ferry, 245 },
334 // { Line::Funicular, -1 }, TODO
335 { Line::LocalTrain, 14 },
336 { Line::LongDistanceTrain, 14 },
337 { Line::Metro, 11 },
338 { Line::RailShuttle, 11 }, // assuming tram/rapid transit-like
339 { Line::RapidTransit, 11 },
340 { Line::Shuttle, 68 },
341 { Line::Taxi, 158 },
342 { Line::Train, 14 },
343 { Line::Tramway, 11 },
344 { Line::RideShare, 158 },
345 // { Line::AerialLift, -1 }, TODO
346};
347
348struct {
350 int gramPerKm;
351} static constexpr const emissionForIvModeMap[] = {
352 { IndividualTransport::Walk, 0 },
353 { IndividualTransport::Bike, 0 },
354 { IndividualTransport::Car, 158 }
355};
356
357struct {
359 int gramPerKm;
360} static constexpr const emissionForRvModeMap[] = {
362 // { RentalVehicle::Pedelec, -1 }, TODO
363 // { RentalVehicle::ElectricKickScooter, -1 }, TODO
364 // { RentalVehicle::ElectricMoped, -1 }, TODO
365 { RentalVehicle::Car, 158 },
366};
367
369{
370 if (d->co2Emission >= 0) {
371 return d->co2Emission;
372 }
373
374 switch (d->mode) {
375 case JourneySection::Invalid:
376 return -1;
377 case JourneySection::Walking:
378 case JourneySection::Transfer:
379 case JourneySection::Waiting:
380 return 0;
381 case JourneySection::PublicTransport:
382 {
383 const auto mode = route().line().mode();
384 for (const auto &map : emissionForModeMap) {
385 if (map.mode == mode) {
386 return (map.gramPerKm * distance()) / 1000;
387 }
388 }
389 qCDebug(Log) << "No CO2 emission estimate for mode" << mode;
390 return -1;
391 }
393 {
394 const auto mode = individualTransport().mode();
395 for (const auto &map :emissionForIvModeMap) {
396 if (map.mode == mode) {
397 return (map.gramPerKm *distance()) / 1000;
398 }
399 }
400 qCDebug(Log) << "No CO2 emission estimate for mode" << mode;
401 return -1;
402 }
404 {
405 const auto mode = rentalVehicle().type();
406 for (const auto &map :emissionForRvModeMap) {
407 if (map.mode == mode) {
408 return (map.gramPerKm *distance()) / 1000;
409 }
410 }
411 qCDebug(Log) << "No CO2 emission estimate for vehicle type" << mode;
412 return -1;
413 }
414 }
415
416 return -1;
417}
418
419void JourneySection::setCo2Emission(int value)
420{
421 d.detach();
422 d->co2Emission = value;
423}
424
425const std::vector<LoadInfo>& JourneySection::loadInformation() const
426{
427 return d->loadInformation;
428}
429
430std::vector<LoadInfo>&& JourneySection::takeLoadInformation()
431{
432 d.detach();
433 return std::move(d->loadInformation);
434}
435
436void JourneySection::setLoadInformation(std::vector<LoadInfo> &&loadInfo)
437{
438 d.detach();
439 d->loadInformation = std::move(loadInfo);
440}
441
442QList<LoadInfo> JourneySection::loadInformationList() const
443{
445 l.reserve((qsizetype)d->loadInformation.size());
446 std::copy(d->loadInformation.begin(), d->loadInformation.end(), std::back_inserter(l));
447 return l;
448}
449
450void JourneySection::setLoadInformationList(const QList<LoadInfo> &loadInfo)
451{
452 d->loadInformation.clear();
453 d->loadInformation.reserve(loadInfo.size());
454 std::copy(loadInfo.begin(), loadInfo.end(), std::back_inserter(d->loadInformation));
455}
456
457const std::vector<KPublicTransport::Feature>& JourneySection::features() const
458{
459 return d->departureVehicleLayout.features();
460}
461
462[[nodiscard]] std::vector<KPublicTransport::Feature>&& JourneySection::takeFeatures()
463{
464 return d->departureVehicleLayout.takeFeatures();
465}
466
467void JourneySection::setFeatures(std::vector<KPublicTransport::Feature> &&features)
468{
469 d.detach();
470 d->departureVehicleLayout.setFeatures(std::move(features));
471}
472
473QString JourneySection::iconName() const
474{
475 switch (d->mode) {
476 case JourneySection::Invalid:
477 return {};
478 case JourneySection::PublicTransport:
479 return d->route.line().iconName();
481 return d->rentalVehicle.vehicleTypeIconName();
483 return d->individualTransport.modeIconName();
484 case JourneySection::Transfer:
485 case JourneySection::Walking:
486 case JourneySection::Waiting:
487 break;
488 }
489
490 return modeIconName(d->mode);
491}
492
494{
495 switch (mode) {
496 case JourneySection::Invalid:
497 return {};
498 case JourneySection::PublicTransport:
499 return Line::modeIconName(Line::Train);
500 case JourneySection::Transfer:
501 return u"qrc:///org.kde.kpublictransport/assets/images/journey-mode-transfer.svg"_s;
502 case JourneySection::Walking:
503 return IndividualTransport::modeIconName(IndividualTransport::Walk);
504 case JourneySection::Waiting:
505 return u"qrc:///org.kde.kpublictransport/assets/images/journey-mode-wait.svg"_s;
509 return IndividualTransport::modeIconName(IndividualTransport::Bike);
510 }
511
512 return u"question"_s;
513}
514
516{
517 switch (mode()) {
518 case JourneySection::Invalid:
519 break;
520 case JourneySection::PublicTransport:
521 return route().line().name();
522 case JourneySection::Walking:
523 return i18nc("mode of individual transport", "Walk");
524 case JourneySection::Waiting:
525 return i18n("Wait");
526 case JourneySection::Transfer:
527 break; // ?
529 return rentalVehicle().label();
531 return individualTransport().label();
532 }
533
534 return {};
535}
536
538{
539 return std::accumulate(d->loadInformation.begin(), d->loadInformation.end(), Load::Unknown, [](auto l, const auto &info) {
540 return std::max(l, info.load());
541 });
542}
543
545{
546 return d->ids.identifier(identifierType);
547}
548
549bool JourneySection::hasIdentifier(QAnyStringView identifierType) const
550{
551 return d->ids.hasIdentifier(identifierType);
552}
553
554void JourneySection::setIdentifier(const QString &identifierType, const QString &id)
555{
556 d.detach();
557 d->ids.setIdentifier(identifierType, id);
558}
559
561{
562 return !d->ids.isEmpty();
563}
564
566{
567 if (!d->isValidIndex(idx)) {
568 return {};
569 }
570
571 if (idx == 0) {
572 return departure();
573 }
574 if (idx <= (qsizetype)d->intermediateStops.size()) {
575 return d->intermediateStops[idx - 1];
576 }
577 return arrival();
578}
579
580void JourneySection::setStopovver(qsizetype idx, const Stopover &stop)
581{
582 if (!d->isValidIndex(idx)) {
583 return;
584 }
585
586 if (idx == 0) {
588 } else if (idx <= (qsizetype)d->intermediateStops.size()) {
589 d.detach();
590 d->intermediateStops[idx - 1] = stop;
591 } else {
593 }
594}
595
597{
599 return 0;
600 }
601 if (const auto it = std::ranges::find_if(d->intermediateStops, [&stop](const auto &s) { return Stopover::isSame(s, stop); }); it != d->intermediateStops.end()) {
602 return std::distance(d->intermediateStops.begin(), it) + 1;
603 }
604 if (Stopover::isSame(arrival(), stop)) {
605 return (qsizetype)d->intermediateStops.size() + 1;
606 }
607 return -1;
608}
609
610JourneySection JourneySection::subsection(qsizetype begin, qsizetype end) const
611{
612 if (!d->isValidIndex(begin) || !d->isValidIndex(end) || end <= begin) {
613 return {};
614 }
615
616 auto partialTrip = *this;
617 if (begin > 0) {
618 partialTrip.setDeparture(stopover(begin));
619 }
620 if (end <= (qsizetype)d->intermediateStops.size()) {
621 partialTrip.setArrival(stopover(end));
622 }
623
624 const auto beginIt = d->intermediateStops.begin() + std::max<qsizetype>(0, begin);
625 const auto endIt = beginIt + std::max<qsizetype>(0, end - begin - 1);
626 partialTrip.setIntermediateStops({beginIt, endIt});
627
628 auto path = d->path;
629 auto pathSections = path.takeSections();
630
631 // find the closest points on the path to the departure/arrival locations
632 // we have to expect aribitrarly broken/imprecise data here...
633 qsizetype beginSection = -1, beginPoint = -1, endSection = -1, endPoint = -1;
634 double beginMinDist = std::numeric_limits<double>::max(), endMinDist = std::numeric_limits<double>::max();
635 for (std::size_t i = 0; i < pathSections.size(); ++i) {
636 const auto poly = pathSections[i].path();
637 for (qsizetype j = 0; j < poly.size(); ++j) {
638 const auto p = poly[j];
639 if (const auto d = Location::distance(p.y(), p.x(), partialTrip.from().latitude(), partialTrip.from().longitude()); d <beginMinDist) {
640 beginSection = (qsizetype)i;
641 beginPoint = j;
642 beginMinDist = d;
643 }
644 if (const auto d = Location::distance(p.y(), p.x(), partialTrip.to().latitude(), partialTrip.to().longitude()); d <endMinDist) {
645 endSection = (qsizetype)i;
646 endPoint = j;
647 endMinDist = d;
648 }
649 }
650 }
651
652 // if we found something, truncate path accordingly
653 if (std::tie(beginSection, beginPoint) < std::tie(endSection, endPoint)) {
654 // start cutting from the end, as otherwise the end indices become invalid!
655 pathSections.erase(pathSections.begin() + endSection + 1, pathSections.end());
656 pathSections.erase(pathSections.begin(), pathSections.begin() + beginSection);
657
658 auto poly = pathSections.back().path();
659 poly.erase(poly.begin() + endPoint + 1, poly.end());
660 pathSections.back().setPath(poly);
661
662 poly = pathSections.front().path();
663 poly.erase(poly.begin(), poly.begin() + beginPoint);
664 pathSections.front().setPath(poly);
665
666 path.setSections(std::move(pathSections));
667 partialTrip.setPath(path);
668 }
669
670 return partialTrip;
671}
672
674{
675 if (!from().hasCoordinate() || mode() != JourneySection::PublicTransport) {
676 return;
677 }
678 auto line = d->route.line();
679 line.applyMetaData(from(), download);
680 d->route.setLine(line);
681
682 // propagate to intermediate stops
683 for (auto &stop : d->intermediateStops) {
684 stop.setRoute(d->route);
685 }
686}
687
689{
690 if (lhs.d->mode != rhs.d->mode) {
691 return false;
692 }
693
695 return false;
696 }
697
698 switch (lhs.d->ids.compare(rhs.d->ids)) {
699 case IdentifierSet::NotEqual: return false;
700 case IdentifierSet::Equal: // same trip id can still mean diffierent departure/arrival stops
701 case IdentifierSet::NoIntersection: break;
702 }
703
704 // we have N criteria to compare here, with 3 possible results:
705 // - equal
706 // - similar-ish, unknwon, or at least not conflicting
707 // - conflicting
708 // A single conflict results in a negative result, at least N - 1 equal comparisons lead to
709 // in a positive result.
710 enum { Equal = 1, Compatible = 0, Conflict = -1000 };
711 int result = 0;
712
713 const auto depTimeDist = MergeUtil::distance(lhs.d->scheduledDepartureTime, rhs.d->scheduledDepartureTime);
714 result += depTimeDist < 60 ? Equal : depTimeDist <= 60 ? Compatible : Conflict;
715 const auto arrTimeDist = MergeUtil::distance(lhs.d->scheduledArrivalTime, rhs.d->scheduledArrivalTime);
716 result += arrTimeDist < 60 ? Equal : depTimeDist <= 60 ? Compatible : Conflict;
717
718 const auto sameFrom = Location::isSame(lhs.d->from, rhs.d->from);
719 const auto fromDist = Location::distance(lhs.from(), rhs.from());
720 result += sameFrom ? Equal : fromDist < 200 ? Compatible : Conflict;
721
722 const auto sameTo = Location::isSame(lhs.d->to, rhs.d->to);
723 const auto toDist = Location::distance(lhs.to(), rhs.to());
724 result += sameTo ? Equal : toDist < 200 ? Compatible : Conflict;
725
726 const auto sameRoute = Route::isSame(lhs.d->route, rhs.d->route);
727 const auto sameDir = Location::isSameName(lhs.d->route.direction(), rhs.d->route.direction());
728 const auto sameLine = Line::isSame(lhs.d->route.line(), rhs.d->route.line());
729 result += sameRoute ? Equal : (sameDir || sameLine) ? Compatible : Conflict;
730
732 result += lhs.scheduledDeparturePlatform() == rhs.scheduledDeparturePlatform() ? Equal : Conflict;
733 }
734
735 return result >= 4;
736}
737
739{
740 using namespace MergeUtil;
741 auto res = lhs;
742 res.d->ids.merge(rhs.d->ids);
743 res.setScheduledDepartureTime(mergeDateTimeEqual(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()));
744 res.setExpectedDepartureTime(mergeDateTimeMax(lhs.expectedDepartureTime(), rhs.expectedDepartureTime()));
745 res.setScheduledArrivalTime(mergeDateTimeMax(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()));
746 res.setExpectedArrivalTime(mergeDateTimeMax(lhs.expectedArrivalTime(), rhs.expectedArrivalTime()));
747
748 if (res.expectedDeparturePlatform().isEmpty()) {
749 res.setExpectedDeparturePlatform(rhs.expectedDeparturePlatform());
750 }
751 if (res.expectedArrivalPlatform().isEmpty()) {
752 res.setExpectedArrivalPlatform(rhs.expectedArrivalPlatform());
753 }
754 res.setFrom(Location::merge(lhs.from(), rhs.from()));
755 res.setTo(Location::merge(lhs.to(), rhs.to()));
756 res.setRoute(Route::merge(lhs.route(), rhs.route()));
757
758 res.setScheduledDeparturePlatform(mergeString(lhs.scheduledDeparturePlatform(), rhs.scheduledDeparturePlatform()));
759 res.setScheduledArrivalPlatform(mergeString(lhs.scheduledArrivalPlatform(), rhs.scheduledArrivalPlatform()));
760
761 res.setDisruptionEffect(std::max(lhs.disruptionEffect(), rhs.disruptionEffect()));
762 res.setNotes(NotesUtil::mergeNotes(lhs.notes(), rhs.notes()));
763 res.setDistance(std::max(lhs.d->distance, rhs.d->distance));
764
765 if (lhs.intermediateStops().size() == rhs.intermediateStops().size()) {
766 auto stops = res.takeIntermediateStops();
767 for (uint i = 0; i < stops.size(); ++i) {
768 stops[i] = Stopover::merge(stops[i], rhs.intermediateStops()[i]);
769 stops[i].setRoute(res.route());
770 }
771 res.setIntermediateStops(std::move(stops));
772 } else if (lhs.intermediateStops().empty() && !rhs.intermediateStops().empty()) {
773 res.setIntermediateStops(std::vector<Stopover>(rhs.intermediateStops()));
774 } else if (!lhs.intermediateStops().empty() && rhs.intermediateStops().empty()) {
775 res.setIntermediateStops(std::vector<Stopover>(lhs.intermediateStops()));
776 }
777
778 res.d->co2Emission = std::max(lhs.d->co2Emission, rhs.d->co2Emission);
779 res.d->loadInformation = LoadUtil::merge(lhs.d->loadInformation, rhs.d->loadInformation);
780 res.d->rentalVehicle = RentalVehicleUtil::merge(lhs.d->rentalVehicle, rhs.d->rentalVehicle);
781
782 res.d->path = lhs.d->path.sections().size() < rhs.d->path.sections().size() ? rhs.d->path : lhs.d->path;
783
784 res.d->departureVehicleLayout = Vehicle::merge(lhs.d->departureVehicleLayout, rhs.d->departureVehicleLayout);
785 res.d->departurePlatformLayout = Platform::merge(lhs.d->departurePlatformLayout, rhs.d->departurePlatformLayout);
786 res.d->arrivalVehicleLayout = Vehicle::merge(lhs.d->arrivalVehicleLayout, rhs.d->arrivalVehicleLayout);
787 res.d->arrivalPlatformLayout = Platform::merge(lhs.d->arrivalPlatformLayout, rhs.d->arrivalPlatformLayout);
788
789 return res;
790}
791
793{
794 auto obj = Json::toJson(section);
795 if (!section.d->ids.isEmpty()) {
796 obj.insert("identifiers"_L1, section.d->ids.toJson());
797 }
798 if (section.mode() != Waiting) {
799 const auto fromObj = Location::toJson(section.from());
800 if (!fromObj.empty()) {
801 obj.insert(QLatin1String("from"), fromObj);
802 }
803 const auto toObj = Location::toJson(section.to());
804 if (!toObj.empty()) {
805 obj.insert(QLatin1String("to"), toObj);
806 }
807 }
808 if (section.mode() == PublicTransport) {
809 const auto routeObj = Route::toJson(section.route());
810 if (!routeObj.empty()) {
811 obj.insert(QLatin1String("route"), routeObj);
812 }
813 if (!section.intermediateStops().empty()) {
814 obj.insert(QLatin1String("intermediateStops"), Stopover::toJson(section.intermediateStops()));
815 }
816 if (!section.loadInformation().empty()) {
817 obj.insert(QLatin1String("load"), LoadInfo::toJson(section.loadInformation()));
818 }
819 }
820 if (section.d->distance <= 0) {
821 obj.remove("distance"_L1);
822 }
823 if (section.d->co2Emission < 0) {
824 obj.remove(QLatin1String("co2Emission"));
825 }
826 if (section.rentalVehicle().type() != RentalVehicle::Unknown) {
827 obj.insert(QLatin1String("rentalVehicle"), RentalVehicle::toJson(section.rentalVehicle()));
828 }
829
830 if (!section.path().isEmpty()) {
831 obj.insert(QLatin1String("path"), Path::toJson(section.path()));
832 }
833
834 if (!section.departureVehicleLayout().isEmpty()) {
835 obj.insert(QLatin1String("departureVehicleLayout"), Vehicle::toJson(section.departureVehicleLayout()));
836 }
837 if (!section.departurePlatformLayout().isEmpty()) {
838 obj.insert(QLatin1String("departurePlatformLayout"), Platform::toJson(section.departurePlatformLayout()));
839 }
840 if (!section.arrivalVehicleLayout().isEmpty()) {
841 obj.insert(QLatin1String("arrivalVehicleLayout"), Vehicle::toJson(section.arrivalVehicleLayout()));
842 }
843 if (!section.arrivalPlatformLayout().isEmpty()) {
844 obj.insert(QLatin1String("arrivalPlatformLayout"), Platform::toJson(section.arrivalPlatformLayout()));
845 }
846
847 if (section.mode() == JourneySection::IndividualTransport) {
848 obj.insert(QLatin1String("individualTransport"), IndividualTransport::toJson(section.individualTransport()));
849 }
850
851 if (obj.size() <= 2) { // only the disruption and mode enums, ie. this is an empty object
852 return {};
853 }
854 return obj;
855}
856
857QJsonArray JourneySection::toJson(const std::vector<JourneySection> &sections)
858{
859 return Json::toJson(sections);
860}
861
863{
864 auto section = Json::fromJson<JourneySection>(obj);
865 section.d->ids.fromJson(obj.value("identifiers"_L1).toObject());
866 section.setFrom(Location::fromJson(obj.value(QLatin1String("from")).toObject()));
867 section.setTo(Location::fromJson(obj.value(QLatin1String("to")).toObject()));
868 section.setRoute(Route::fromJson(obj.value(QLatin1String("route")).toObject()));
869 section.setIntermediateStops(Stopover::fromJson(obj.value(QLatin1String("intermediateStops")).toArray()));
870 section.setLoadInformation(LoadInfo::fromJson(obj.value(QLatin1String("load")).toArray()));
871 section.setRentalVehicle(RentalVehicle::fromJson(obj.value(QLatin1String("rentalVehicle")).toObject()));
872 section.setPath(Path::fromJson(obj.value(QLatin1String("path")).toObject()));
873 section.setDepartureVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("departureVehicleLayout")).toObject()));
874 section.setDeparturePlatformLayout(Platform::fromJson(obj.value(QLatin1String("departurePlatformLayout")).toObject()));
875 section.setArrivalVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("arrivalVehicleLayout")).toObject()));
876 section.setArrivalPlatformLayout(Platform::fromJson(obj.value(QLatin1String("arrivalPlatformLayout")).toObject()));
877 section.setIndividualTransport(IndividualTransport::fromJson(obj.value(QLatin1String("individualTransport")).toObject()));
878 section.applyMetaData(false);
879 return section;
880}
881
882std::vector<JourneySection> JourneySection::fromJson(const QJsonArray &array)
883{
884 return Json::fromJson<JourneySection>(array);
885}
886
887
888KPUBLICTRANSPORT_MAKE_GADGET(Journey)
889
890const std::vector<JourneySection>& Journey::sections() const
891{
892 return d->sections;
893}
894
895std::vector<JourneySection>&& Journey::takeSections()
896{
897 d.detach();
898 return std::move(d->sections);
899}
900
901void Journey::setSections(std::vector<JourneySection> &&sections)
902{
903 d.detach();
904 d->sections = std::move(sections);
905}
906
907QList<JourneySection> Journey::sectionsList() const
908{
910 l.reserve((qsizetype)d->sections.size());
911 std::copy(d->sections.begin(), d->sections.end(), std::back_inserter(l));
912 return l;
913}
914
915void Journey::setSectionsList(const QList<JourneySection> &sections)
916{
917 d->sections.clear();
918 d->sections.reserve(sections.size());
919 std::copy(sections.begin(), sections.end(), std::back_inserter(d->sections));
920}
921
922QDateTime Journey::scheduledDepartureTime() const
923{
924 if (!d->sections.empty()) {
925 return d->sections.front().scheduledDepartureTime();
926 }
927 return {};
928}
929
931{
932 return d->sections.empty() ? false : d->sections.front().hasExpectedDepartureTime();
933}
934
935QDateTime Journey::expectedDepartureTime() const
936{
937 return d->sections.empty() ? QDateTime() : d->sections.front().expectedDepartureTime();
938}
939
940int Journey::departureDelay() const
941{
942 return d->sections.empty() ? 0 : d->sections.front().departureDelay();
943}
944
945QDateTime Journey::scheduledArrivalTime() const
946{
947 if (!d->sections.empty()) {
948 return d->sections.back().scheduledArrivalTime();
949 }
950 return {};
951}
952
954{
955 return d->sections.empty() ? false : d->sections.back().hasExpectedArrivalTime();
956}
957
958QDateTime Journey::expectedArrivalTime() const
959{
960 return d->sections.empty() ? QDateTime() : d->sections.back().expectedArrivalTime();
961}
962
963int Journey::arrivalDelay() const
964{
965 return d->sections.empty() ? 0 : d->sections.back().arrivalDelay();
966}
967
968int Journey::duration() const
969{
971}
972
973int Journey::numberOfChanges() const
974{
975 return std::max(0, static_cast<int>(std::count_if(d->sections.begin(), d->sections.end(), [](const auto &section) { return section.mode() == JourneySection::PublicTransport; }) - 1));
976}
977
979{
980 Disruption::Effect effect = Disruption::NormalService;
981 for (const auto &sec : d->sections) {
982 effect = std::max(effect, sec.disruptionEffect());
983 }
984 return effect;
985}
986
987int Journey::distance() const
988{
989 return std::accumulate(d->sections.begin(), d->sections.end(), 0, [](auto dist, const auto &jny) { return dist + jny.distance(); });
990}
991
992int Journey::co2Emission() const
993{
994 return std::accumulate(d->sections.begin(), d->sections.end(), 0, [](auto co2, const auto &jny) { return co2 + std::max(0, jny.co2Emission()); });
995}
996
998{
999 return std::accumulate(d->sections.begin(), d->sections.end(), Load::Unknown, [](auto l, const auto &jny) {
1000 return std::max(l, jny.maximumOccupancy());
1001 });
1002}
1003
1004void Journey::applyMetaData(bool download)
1005{
1006 for (auto &sec : d->sections) {
1007 sec.applyMetaData(download);
1008 }
1009}
1010
1011static bool isTransportSection(JourneySection::Mode mode)
1012{
1013 return mode == JourneySection::PublicTransport
1016}
1017
1018bool Journey::isSame(const Journey &lhs, const Journey &rhs)
1019{
1020 auto lIt = lhs.sections().begin();
1021 auto rIt = rhs.sections().begin();
1022
1023 while (lIt != lhs.sections().end() || rIt != rhs.sections().end()) {
1024 // ignore non-transport sections
1025 if (lIt != lhs.sections().end() && !isTransportSection((*lIt).mode())) {
1026 ++lIt;
1027 continue;
1028 }
1029 if (rIt != rhs.sections().end() && !isTransportSection((*rIt).mode())) {
1030 ++rIt;
1031 continue;
1032 }
1033
1034 if (lIt == lhs.sections().end() || rIt == rhs.sections().end()) {
1035 return false;
1036 }
1037
1038 if (!JourneySection::isSame(*lIt, *rIt)) {
1039 return false;
1040 }
1041
1042 ++lIt;
1043 ++rIt;
1044 }
1045
1046 Q_ASSERT(lIt == lhs.sections().end() && rIt == rhs.sections().end());
1047 return true;
1048}
1049
1050Journey Journey::merge(const Journey &lhs, const Journey &rhs)
1051{
1052 std::vector<JourneySection> sections;
1053 sections.reserve(lhs.sections().size() + rhs.sections().size());
1054 std::copy(lhs.sections().begin(), lhs.sections().end(), std::back_inserter(sections));
1055 std::copy(rhs.sections().begin(), rhs.sections().end(), std::back_inserter(sections));
1056 std::sort(sections.begin(), sections.end(), [](const auto &lSec, const auto &rSec) {
1057 if (MergeUtil::distance(lSec.scheduledDepartureTime(), rSec.scheduledDepartureTime()) == 0) {
1058 return lSec.mode() < rSec.mode();
1059 }
1060 return MergeUtil::isBefore(lSec.scheduledDepartureTime(), rSec.scheduledDepartureTime());
1061 });
1062
1063 for (auto it = sections.begin(); it != sections.end(); ++it) {
1064 const auto nextIt = it + 1;
1065 if (nextIt == sections.end()) {
1066 break;
1067 }
1068
1069 if (JourneySection::isSame(*it, *nextIt) || ((*it).mode() == (*nextIt).mode() && (*it).mode() != JourneySection::PublicTransport)) {
1070 *it = JourneySection::merge(*it, *nextIt);
1071 sections.erase(nextIt);
1072 }
1073 }
1074
1075 Journey res;
1076 res.setSections(std::move(sections));
1077 return res;
1078}
1079
1081{
1082 QJsonObject obj;
1083 obj.insert(QLatin1String("sections"), JourneySection::toJson(journey.sections()));
1084 return obj;
1085}
1086
1087QJsonArray Journey::toJson(const std::vector<Journey> &journeys)
1088{
1089 return Json::toJson(journeys);
1090}
1091
1093{
1094 Journey j;
1095 j.setSections(JourneySection::fromJson(obj.value(QLatin1String("sections")).toArray()));
1096 return j;
1097}
1098
1099std::vector<Journey> Journey::fromJson(const QJsonArray &array)
1100{
1101 return Json::fromJson<Journey>(array);
1102}
1103
1104#include "moc_journey.cpp"
Individual transport mode details for a journey section, and for specifying journey requests.
QString label
Label shortly describing this transport for display.
Mode
Mode of (individual) transportation.
static QJsonObject toJson(const IndividualTransport &it)
Serializes one object to JSON.
static IndividualTransport fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
QString modeIconName
Name of an icon to represent this transport mode.
A segment of a journey plan.
Definition journey.h:39
KPublicTransport::Path path
Movement path for this journey section.
Definition journey.h:148
void applyMetaData(bool download)
Augment line meta data.
Definition journey.cpp:673
bool arrivalPlatformChanged
true if we have real-time platform information and the platform changed.
Definition journey.h:112
QString scheduledDeparturePlatform
Planned departure platform.
Definition journey.h:97
static JourneySection merge(const JourneySection &lhs, const JourneySection &rhs)
Merge two instances.
Definition journey.cpp:738
Stopover stopover(qsizetype idx) const
Retrieve stopover at index idx.
Definition journey.cpp:565
qsizetype indexOfStopover(const Stopover &stop) const
Returns the index of stop in this journey section.
Definition journey.cpp:596
KPublicTransport::Load::Category maximumOccupancy
Maximum occpancy over all classes.
Definition journey.h:180
void setDeparture(const Stopover &departure)
Sets all departure properties from a given Stopover.
Definition journey.cpp:282
static bool isSame(const JourneySection &lhs, const JourneySection &rhs)
Checks if two instances refer to the same journey section (which does not necessarily mean they are e...
Definition journey.cpp:688
void setLoadInformation(std::vector< LoadInfo > &&loadInfo)
Set the vehicle load information for this journey section.
Definition journey.cpp:436
KPublicTransport::Location from
Departure location of this segment.
Definition journey.h:90
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition journey.h:78
QString expectedArrivalPlatform
Actual arrival platform, in case real-time information are available.
Definition journey.h:108
QString iconName
The best available icon to represent this journey section.
Definition journey.h:174
QList< KPublicTransport::LoadInfo > loadInformation
Vehicle load information for this journey section.
Definition journey.h:139
int departureDelay
Difference to schedule in minutes.
Definition journey.h:71
JourneySection subsection(qsizetype begin, qsizetype end) const
Returns the sub-journey starting from index begin until end (inclusive).
Definition journey.cpp:610
void setIntermediateStops(std::vector< Stopover > &&stops)
Set the intermediate stops.
Definition journey.cpp:252
QString label
Label shortly describing this transport for display.
Definition journey.h:177
static Q_INVOKABLE QString modeIconName(KPublicTransport::JourneySection::Mode mode)
Icon representing the journey section mode mode.
Definition journey.cpp:493
KPublicTransport::Platform arrivalPlatformLayout
Platform layout information at arrival.
Definition journey.h:160
int co2Emission
COâ‚‚ emission during this journey section, in gram.
Definition journey.h:134
KPublicTransport::RentalVehicle rentalVehicle
Information about a rental vehicle, for sections using one.
Definition journey.h:142
bool hasIdentifiers() const
Returns true if there is any identifier set at all.
Definition journey.cpp:560
QString identifier(QAnyStringView identifierType) const
Backend-specific journey section identifiers.
Definition journey.cpp:544
QStringList notes
General human-readable notes on this service, e.g.
Definition journey.h:117
void setArrival(const Stopover &arrival)
Sets all arrival properties from a given Stopover.
Definition journey.cpp:311
static QJsonObject toJson(const JourneySection &section)
Serializes one journey section to JSON.
Definition journey.cpp:792
QDateTime scheduledDepartureTime
Planned departure time.
Definition journey.h:63
bool hasExpectedArrivalPlatform
true if real-time platform information are available.
Definition journey.h:110
@ RentedVehicle
free floating or dock-based rental bike service, electric scooters, car sharing services,...
Definition journey.h:52
@ IndividualTransport
using your own vehicle (bike, car, etc).
Definition journey.h:53
KPublicTransport::Route route
Route to take on this segment.
Definition journey.h:94
KPublicTransport::Disruption::Effect disruptionEffect
Disruption effect on this section, if any.
Definition journey.h:115
KPublicTransport::Stopover departure
All departure information represented as Stopover object.
Definition journey.h:123
KPublicTransport::Vehicle arrivalVehicleLayout
Vehicle coach layout information at arrival.
Definition journey.h:158
QVariantList intermediateStops
Intermediate stops for consumption by QML.
Definition journey.h:120
KPublicTransport::Platform departurePlatformLayout
Platform layout information at departure.
Definition journey.h:153
void setStopovver(qsizetype idx, const Stopover &stop)
Set the stopover at index idx.
Definition journey.cpp:580
int arrivalDelay
Difference to schedule in minutes.
Definition journey.h:82
KPublicTransport::Location to
Arrival location of this segment.
Definition journey.h:92
std::vector< Stopover > && takeIntermediateStops()
Moves the intermediate stops out of this object.
Definition journey.cpp:246
bool hasExpectedDeparturePlatform
true if real-time platform information are available.
Definition journey.h:101
QString scheduledArrivalPlatform
Planned arrival platform.
Definition journey.h:106
bool hasExpectedDepartureTime
true if this has real-time data.
Definition journey.h:69
bool hasExpectedArrivalTime
true if this has real-time data.
Definition journey.h:80
QString expectedDeparturePlatform
Actual departure platform, in case real-time information are available.
Definition journey.h:99
static JourneySection fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition journey.cpp:862
std::vector< LoadInfo > && takeLoadInformation()
Moves the load information out of this object for modification.
Definition journey.cpp:430
KPublicTransport::Vehicle departureVehicleLayout
Vehicle coach layout information at departure.
Definition journey.h:151
std::vector< KPublicTransport::Feature > features
Features of the vehicle used on this section.
Definition journey.h:169
void addNote(const QString &note)
Adds a note.
Definition journey.cpp:224
int duration
Duration of the section in seconds.
Definition journey.h:85
Mode mode
Mode of transport for this section.
Definition journey.h:60
QDateTime scheduledArrivalTime
Planned arrival time.
Definition journey.h:74
KPublicTransport::IndividualTransport individualTransport
Individual transport details for sections using your own vehicle.
Definition journey.h:163
bool departurePlatformChanged
true if we have real-time platform information and the platform changed.
Definition journey.h:103
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition journey.h:67
KPublicTransport::Stopover arrival
All arrival information represented as Stopover object.
Definition journey.h:125
int distance
Distance of the section in meter.
Definition journey.h:87
A journey plan.
Definition journey.h:319
void applyMetaData(bool download)
Augment line meta data.
Definition journey.cpp:1004
KPublicTransport::Disruption::Effect disruptionEffect
Worst disruption effect of any of the journey sections.
Definition journey.h:350
static Journey fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition journey.cpp:1092
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition journey.h:330
QDateTime scheduledDepartureTime
Departure time of the journey, according to schedule.
Definition journey.h:324
static bool isSame(const Journey &lhs, const Journey &rhs)
Checks if two instances refer to the same journey (which does not necessarily mean they are exactly e...
Definition journey.cpp:1018
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition journey.h:341
int departureDelay
Difference to schedule in minutes.
Definition journey.h:332
int numberOfChanges
Number of changes on this journey.
Definition journey.h:348
void setSections(std::vector< JourneySection > &&sections)
Sets the journey sections.
Definition journey.cpp:901
KPublicTransport::Load::Category maximumOccupancy
Maximum occpancy in all journey sections, over all classes.
Definition journey.h:362
QList< KPublicTransport::JourneySection > sections
Journey sections for consumption by QML.
Definition journey.h:322
static QJsonObject toJson(const Journey &journey)
Serializes one journey object to JSON.
Definition journey.cpp:1080
bool hasExpectedDepartureTime
true if this has real-time data.
Definition journey.h:326
int duration
Duration of the entire journey in seconds.
Definition journey.h:346
QDateTime scheduledArrivalTime
Arrival time of the journey, according to schedule.
Definition journey.h:335
int distance
Total travelled distance of the entire journey in meter.
Definition journey.h:355
int arrivalDelay
Difference to schedule in minutes.
Definition journey.h:343
int co2Emission
Total CO2 emissions for the entire journey in gram.
Definition journey.h:359
std::vector< JourneySection > && takeSections()
Moves the journey sections out of this object.
Definition journey.cpp:895
static Journey merge(const Journey &lhs, const Journey &rhs)
Merge two instances.
Definition journey.cpp:1050
bool hasExpectedArrivalTime
true if this has real-time data.
Definition journey.h:337
KPublicTransport::Line::Mode mode
Type of transport.
Definition line.h:60
QString name
Name of the line.
Definition line.h:50
QString modeIconName
Generic icon for the line mode.
Definition line.h:93
Mode
Mode of transportation.
Definition line.h:27
@ RideShare
peer-to-peer ride sharing/car pooling
Definition line.h:44
@ RailShuttle
rail shuttle service within a complex, as e.g. found at or around airports
Definition line.h:38
@ Shuttle
shuttle bus/coach services, e.g. to/from an airport
Definition line.h:40
static bool isSame(const Line &lhs, const Line &rhs)
Checks if to instances refer to the same line (which does not necessarily mean they are exactly equal...
Definition line.cpp:167
static QJsonObject toJson(const LoadInfo &info)
Serializes one load information object to JSON.
Definition load.cpp:26
static LoadInfo fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition load.cpp:36
static Location fromJson(const QJsonObject &obj)
Deserialize a Location object from JSON.
Definition location.cpp:539
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition location.cpp:360
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition location.cpp:478
static double distance(double lat1, double lon1, double lat2, double lon2)
Compute the distance between two geo coordinates, in meters.
Definition location.cpp:458
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:407
static bool isSame(const Location &lhs, const Location &rhs)
Checks if to instances refer to the same location (which does not necessarily mean they are exactly e...
Definition location.cpp:312
A path followed by any kind of location change.
Definition path.h:113
bool isEmpty() const
Returns true if this is an empty/not-set path.
Definition path.cpp:143
static Path fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition path.cpp:187
static QJsonObject toJson(const Path &path)
Serializes one path object to JSON.
Definition path.cpp:180
std::vector< KPublicTransport::PathSection > sections
Access to path sections for QML.
Definition path.h:117
Information about the layout of a station platform.
Definition platform.h:45
static Platform fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition platform.cpp:113
bool isEmpty() const
Returns true if this object contains no information beyond default values.
Definition platform.cpp:66
static Platform merge(const Platform &lhs, const Platform &rhs)
Merge two platform instances.
Definition platform.cpp:93
static QJsonObject toJson(const Platform &platform)
Serializes one platform object to JSON.
Definition platform.cpp:99
An individual rental vehicle used on a JourneySection, ie.
QString label
Label shortly describing this transport for display.
@ Car
electrical- or combustion-powered car
@ ElectricKickScooter
"e scooter", electrically assisted kick scooters, not to be confused with motorcycle-like scooters
@ Bicycle
human-powered bicylce
static RentalVehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
static QJsonObject toJson(const RentalVehicle &vehicle)
Serializes one object to JSON.
VehicleType type
Vehicle type.
QString vehicleTypeIconName
Icon representing the vehicle type.
A route of a public transport line.
Definition line.h:148
QString direction
Direction of the route.
Definition line.h:157
static bool isSame(const Route &lhs, const Route &rhs)
Checks if to instances refer to the same route (which does not necessarily mean they are exactly equa...
Definition line.cpp:266
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition line.cpp:286
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition line.cpp:276
KPublicTransport::Line line
Line this route belongs to.
Definition line.h:151
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:299
Information about an arrival and/or departure of a vehicle at a stop area.
Definition stopover.h:26
static Stopover merge(const Stopover &lhs, const Stopover &rhs)
Merge two departure instances.
Definition stopover.cpp:212
static QJsonObject toJson(const Stopover &stopover)
Serializes one object to JSON.
Definition stopover.cpp:239
static bool isSame(const Stopover &lhs, const Stopover &rhs)
Checks if to instances refer to the same departure (which does not necessarily mean they are exactly ...
Definition stopover.cpp:182
static Stopover fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition stopover.cpp:271
Information about the vehicle used on a journey.
Definition vehicle.h:159
static QJsonObject toJson(const Vehicle &vehicle)
Serializes one vehicle object to JSON.
Definition vehicle.cpp:264
static Vehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition vehicle.cpp:281
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition vehicle.cpp:176
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition vehicle.cpp:240
void stop(Ekos::AlignState mode)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Effect
Disruption effects, numerical sorted so that higher values imply more severe disruptions.
Definition disruption.h:25
Category
Vehicle load categories.
Definition load.h:20
@ Unknown
no load information are available
Definition load.h:21
Query operations and data types for accessing realtime public transport information from online servi...
KGuiItem back(BidiMode useBidi=IgnoreRTL)
qint64 secsTo(const QDateTime &other) const const
iterator insert(QLatin1StringView key, const QJsonValue &value)
QJsonValue value(QLatin1StringView key) const const
QJsonObject toObject() const const
iterator begin()
void clear()
iterator end()
iterator erase(const_iterator begin, const_iterator end)
void reserve(qsizetype size)
qsizetype size() const const
bool isEmpty() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:47:40 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.