File indexing completed on 2024-04-28 04:41:39

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 }