File indexing completed on 2024-12-08 07:19:12
0001 /* 0002 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "stopoverrequest.h" 0008 #include "requestcontext_p.h" 0009 #include "datatypes/datatypes_p.h" 0010 #include "datatypes/json_p.h" 0011 #include "datatypes/locationutil_p.h" 0012 0013 #include <KPublicTransport/Location> 0014 0015 #include <QCryptographicHash> 0016 #include <QDateTime> 0017 #include <QMetaEnum> 0018 #include <QSharedData> 0019 0020 using namespace KPublicTransport; 0021 0022 enum { DepartureCacheTimeResolution = 60 }; // in seconds 0023 0024 namespace KPublicTransport { 0025 class StopoverRequestPrivate : public QSharedData { 0026 public: 0027 Location stop; 0028 QDateTime dateTime; 0029 StopoverRequest::Mode mode = StopoverRequest::QueryDeparture; 0030 std::vector<RequestContext> contexts; 0031 QStringList backendIds; 0032 std::vector<Line::Mode> lineModes; 0033 bool downloadAssets = false; 0034 int maximumResults = 12; 0035 }; 0036 } 0037 0038 KPUBLICTRANSPORT_MAKE_GADGET(StopoverRequest) 0039 KPUBLICTRANSPORT_MAKE_PROPERTY(StopoverRequest, Location, stop, setStop) 0040 KPUBLICTRANSPORT_MAKE_PROPERTY(StopoverRequest, StopoverRequest::Mode, mode, setMode) 0041 KPUBLICTRANSPORT_MAKE_PROPERTY(StopoverRequest, bool, downloadAssets, setDownloadAssets) 0042 KPUBLICTRANSPORT_MAKE_PROPERTY(StopoverRequest, int, maximumResults, setMaximumResults) 0043 0044 StopoverRequest::StopoverRequest(const Location &stop) 0045 : d(new StopoverRequestPrivate) 0046 { 0047 d->stop = stop; 0048 } 0049 0050 bool StopoverRequest::isValid() const 0051 { 0052 return !d->stop.isEmpty(); 0053 } 0054 0055 QDateTime StopoverRequest::dateTime() const 0056 { 0057 if (!d->dateTime.isValid()) { 0058 d->dateTime = QDateTime::currentDateTime(); 0059 } 0060 return d->dateTime; 0061 } 0062 0063 void StopoverRequest::setDateTime(const QDateTime &dt) 0064 { 0065 d.detach(); 0066 d->dateTime = dt; 0067 } 0068 0069 const std::vector<Line::Mode>& StopoverRequest::lineModes() const 0070 { 0071 return d->lineModes; 0072 } 0073 0074 void StopoverRequest::setLineModes(std::vector<Line::Mode> &&lineModes) 0075 { 0076 d.detach(); 0077 d->lineModes = std::move(lineModes); 0078 std::sort(d->lineModes.begin(), d->lineModes.end()); 0079 d->lineModes.erase(std::unique(d->lineModes.begin(), d->lineModes.end()), d->lineModes.end()); 0080 } 0081 0082 QVariantList StopoverRequest::lineModesVariant() const 0083 { 0084 QVariantList l; 0085 l.reserve(d->lineModes.size()); 0086 std::transform(d->lineModes.begin(), d->lineModes.end(), std::back_inserter(l), [](const Line::Mode &value) { 0087 return QVariant::fromValue<Line::Mode>(value); 0088 }); 0089 return l; 0090 } 0091 0092 void StopoverRequest::setLineModesVariant(const QVariantList &lineModes) 0093 { 0094 auto l = std::move(d->lineModes); 0095 l.clear(); 0096 l.reserve(lineModes.size()); 0097 std::transform(lineModes.begin(), lineModes.end(), std::back_inserter(l), [](const auto &mode) { return static_cast<Line::Mode>(mode.toInt()); }); 0098 setLineModes(std::move(l)); 0099 } 0100 0101 RequestContext StopoverRequest::context(const AbstractBackend *backend) const 0102 { 0103 const auto it = std::lower_bound(d->contexts.begin(), d->contexts.end(), backend); 0104 if (it != d->contexts.end() && (*it).backend == backend) { 0105 return *it; 0106 } 0107 0108 RequestContext context; 0109 context.backend = backend; 0110 return context; 0111 } 0112 0113 const std::vector<RequestContext>& StopoverRequest::contexts() const 0114 { 0115 return d->contexts; 0116 } 0117 0118 void StopoverRequest::setContext(const AbstractBackend *backend, RequestContext &&context) 0119 { 0120 d.detach(); 0121 const auto it = std::lower_bound(d->contexts.begin(), d->contexts.end(), backend); 0122 if (it != d->contexts.end() && (*it).backend == backend) { 0123 (*it) = std::move(context); 0124 } else { 0125 d->contexts.insert(it, std::move(context)); 0126 } 0127 } 0128 0129 void StopoverRequest::purgeLoops(const StopoverRequest &baseRequest) 0130 { 0131 RequestContext::purgeLoops(d->contexts, baseRequest.contexts()); 0132 } 0133 0134 QJsonObject StopoverRequest::toJson(const StopoverRequest &req) 0135 { 0136 auto obj = Json::toJson(req); 0137 obj.insert(QLatin1String("stop"), Location::toJson(req.stop())); 0138 return obj; 0139 } 0140 0141 QStringList StopoverRequest::backendIds() const 0142 { 0143 return d->backendIds; 0144 } 0145 0146 void StopoverRequest::setBackendIds(const QStringList &backendIds) 0147 { 0148 d.detach(); 0149 d->backendIds = backendIds; 0150 } 0151 0152 QString StopoverRequest::cacheKey() const 0153 { 0154 QCryptographicHash hash(QCryptographicHash::Sha1); 0155 hash.addData(QByteArray::number(d->dateTime.toSecsSinceEpoch() / DepartureCacheTimeResolution)); 0156 hash.addData(LocationUtil::cacheKey(d->stop).toUtf8()); 0157 hash.addData(d->mode == StopoverRequest::QueryArrival ? "A" : "D"); 0158 0159 hash.addData("MODES"); 0160 for (const auto &mode : d->lineModes) { 0161 hash.addData(QMetaEnum::fromType<Line::Mode>().valueToKey(mode)); 0162 } 0163 0164 return QString::fromUtf8(hash.result().toHex()); 0165 } 0166 0167 #include "moc_stopoverrequest.cpp"