File indexing completed on 2024-12-08 07:19:12
0001 /* 0002 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "vehiclelayoutreply.h" 0008 #include "reply_p.h" 0009 #include "vehiclelayoutrequest.h" 0010 #include "logging.h" 0011 #include "backends/abstractbackend.h" 0012 #include "backends/cache.h" 0013 0014 #include <KPublicTransport/Platform> 0015 #include <KPublicTransport/Stopover> 0016 #include <KPublicTransport/Vehicle> 0017 0018 #include <QDebug> 0019 0020 using namespace KPublicTransport; 0021 0022 namespace KPublicTransport { 0023 class VehicleLayoutReplyPrivate: public ReplyPrivate { 0024 public: 0025 void finalizeResult() override {} 0026 0027 VehicleLayoutRequest request; 0028 Stopover stopover; 0029 }; 0030 } 0031 0032 VehicleLayoutReply::VehicleLayoutReply(const VehicleLayoutRequest &req, QObject *parent) 0033 : Reply(new VehicleLayoutReplyPrivate, parent) 0034 { 0035 Q_D(VehicleLayoutReply); 0036 d->request = req; 0037 d->stopover = req.stopover(); 0038 } 0039 0040 VehicleLayoutReply::~VehicleLayoutReply() = default; 0041 0042 VehicleLayoutRequest VehicleLayoutReply::request() const 0043 { 0044 Q_D(const VehicleLayoutReply); 0045 return d->request; 0046 } 0047 0048 Stopover VehicleLayoutReply::stopover() const 0049 { 0050 Q_D(const VehicleLayoutReply); 0051 return d->stopover; 0052 } 0053 0054 static bool isOneSidedCar(VehicleSection::Type type) 0055 { 0056 return type == VehicleSection::PowerCar || type == VehicleSection::ControlCar; 0057 } 0058 0059 void VehicleLayoutReply::addResult(const Stopover &stopover) 0060 { 0061 Q_D(VehicleLayoutReply); 0062 d->stopover = Stopover::merge(d->stopover, stopover); 0063 0064 if (!d->stopover.vehicleLayout().sections().empty()) { 0065 // normalize section order 0066 auto vehicle = d->stopover.vehicleLayout(); 0067 auto sections = vehicle.takeSections(); 0068 std::sort(sections.begin(), sections.end(), [](const auto &lhs, const auto &rhs) { 0069 return lhs.platformPositionBegin() < rhs.platformPositionBegin(); 0070 }); 0071 0072 // we have no connections at the ends 0073 sections.front().setConnectedSides(sections.front().connectedSides() & ~VehicleSection::Front); 0074 sections.back().setConnectedSides(sections.back().connectedSides() & ~VehicleSection::Back); 0075 0076 // if the leading car in driving direction is a PassengerCar, turn it into a ControlCar 0077 if (vehicle.direction() == Vehicle::Forward && sections.front().type() == VehicleSection::PassengerCar) { 0078 sections.front().setType(VehicleSection::ControlCar); 0079 } else if (vehicle.direction() == Vehicle::Backward && sections.back().type() == VehicleSection::PassengerCar) { 0080 sections.back().setType(VehicleSection::ControlCar); 0081 } 0082 0083 for (auto it = sections.begin(); it != sections.end(); ++it) { 0084 // engines and power cars have no connections either 0085 if ((*it).type() == VehicleSection::Engine) { 0086 (*it).setConnectedSides(VehicleSection::NoSide); 0087 } 0088 0089 if (it == sections.begin()) { 0090 continue; 0091 } 0092 0093 // connect control cars in the middle of the train to the correct side 0094 // only do that when two cars back isn't a control car either, ie. the preceeding car 0095 // actually has a connection to the front. Otherwise trains consisting of e.g. 4 consecutive 0096 // control cars get layouted wrongly. 0097 if (isOneSidedCar((*(it - 1)).type()) && isOneSidedCar((*it).type()) && ((*(it - 1)).connectedSides() & VehicleSection::Front)) { 0098 (*it).setConnectedSides((*it).connectedSides() & ~VehicleSection::Front); 0099 } 0100 0101 // make sure connections are symmetric 0102 if (((*(it - 1)).connectedSides() & VehicleSection::Back) == 0) { 0103 (*it).setConnectedSides((*it).connectedSides() & ~VehicleSection::Front); 0104 } 0105 if (((*it).connectedSides() & VehicleSection::Front) == 0) { 0106 (*(it - 1)).setConnectedSides((*(it - 1)).connectedSides() & ~VehicleSection::Back); 0107 } 0108 } 0109 0110 vehicle.setSections(std::move(sections)); 0111 d->stopover.setVehicleLayout(std::move(vehicle)); 0112 } 0113 0114 d->pendingOps--; 0115 d->emitFinishedIfDone(this); 0116 } 0117 0118 void VehicleLayoutReply::addError(const AbstractBackend *backend, Reply::Error error, const QString &errorMsg) 0119 { 0120 if (error == Reply::NotFoundError) { 0121 // TODO add negative cache entry 0122 } else { 0123 qCDebug(Log) << backend->backendId() << error << errorMsg; 0124 } 0125 Reply::addError(error, errorMsg); 0126 }