File indexing completed on 2025-04-20 12:49:29
0001 /* 0002 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "locationreply.h" 0008 #include "reply_p.h" 0009 #include "locationrequest.h" 0010 #include "datatypes/locationutil_p.h" 0011 #include "logging.h" 0012 #include "backends/abstractbackend.h" 0013 #include "backends/cache.h" 0014 0015 #include <KPublicTransport/Location> 0016 0017 #include <QDebug> 0018 0019 using namespace KPublicTransport; 0020 0021 namespace KPublicTransport { 0022 class LocationReplyPrivate: public ReplyPrivate { 0023 public: 0024 void finalizeResult() override; 0025 0026 LocationRequest request; 0027 std::vector<Location> locations; 0028 }; 0029 } 0030 0031 void LocationReplyPrivate::finalizeResult() 0032 { 0033 if (locations.empty()) { 0034 return; 0035 } 0036 error = Reply::NoError; 0037 errorMsg.clear(); 0038 0039 // merge all duplicates, as there is no natural order for name searches this is done in O(n²) for now 0040 for (auto it = locations.begin(); it != locations.end(); ++it) { 0041 for (auto mergeIt = it + 1; mergeIt != locations.end();) { 0042 if (Location::isSame(*it, *mergeIt)) { 0043 *it = Location::merge(*it, *mergeIt); 0044 mergeIt = locations.erase(mergeIt); 0045 } else { 0046 ++mergeIt; 0047 } 0048 } 0049 } 0050 0051 std::sort(locations.begin(), locations.end(), [this](const auto &lhs, const auto &rhs) { 0052 return LocationUtil::sortLessThan(request, lhs, rhs); 0053 }); 0054 } 0055 0056 LocationReply::LocationReply(const LocationRequest &req, QObject *parent) 0057 : Reply(new LocationReplyPrivate, parent) 0058 { 0059 Q_D(LocationReply); 0060 d->request = req; 0061 } 0062 0063 LocationReply::~LocationReply() = default; 0064 0065 LocationRequest LocationReply::request() const 0066 { 0067 Q_D(const LocationReply); 0068 return d->request; 0069 } 0070 0071 const std::vector<Location>& LocationReply::result() const 0072 { 0073 Q_D(const LocationReply); 0074 return d->locations; 0075 } 0076 0077 std::vector<Location>&& LocationReply::takeResult() 0078 { 0079 Q_D(LocationReply); 0080 return std::move(d->locations); 0081 } 0082 0083 void LocationReply::addResult(std::vector<Location> &&res) 0084 { 0085 Q_D(LocationReply); 0086 // remove implausible results 0087 for (auto it = res.begin(); it != res.end();) { 0088 // we sometimes seem to get bogus places in Antarctica 0089 if ((*it).hasCoordinate() && (*it).latitude() < -65.0) { 0090 qCDebug(Log) << "Dropping location in Antarctica" << (*it).name() << (*it).latitude() << (*it).longitude(); 0091 it = res.erase(it); 0092 continue; 0093 } 0094 ++it; 0095 } 0096 0097 if (!res.empty()) { 0098 if (d->locations.empty()) { 0099 d->locations = std::move(res); 0100 } else { 0101 d->locations.insert(d->locations.end(), res.begin(), res.end()); 0102 } 0103 d->emitUpdated(this); 0104 } 0105 0106 d->pendingOps--; 0107 d->emitFinishedIfDone(this); 0108 } 0109 0110 void LocationReply::addError(const AbstractBackend *backend, Reply::Error error, const QString &errorMsg) 0111 { 0112 if (error == Reply::NotFoundError) { 0113 Cache::addNegativeLocationCacheEntry(backend->backendId(), request().cacheKey()); 0114 } else { 0115 qCDebug(Log) << backend->backendId() << error << errorMsg; 0116 } 0117 Reply::addError(error, errorMsg); 0118 }