KPublicTransport

locationquerymodel.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "locationquerymodel.h"
8#include "abstractquerymodel_p.h"
9#include "logging.h"
10#include "../datatypes/locationutil_p.h"
11
12#include <KPublicTransport/Attribution>
13#include <KPublicTransport/Location>
14#include <KPublicTransport/LocationReply>
15#include <KPublicTransport/Manager>
16
17#include <QDebug>
18
19using namespace KPublicTransport;
20
21namespace KPublicTransport {
22class LocationQueryModelPrivate : public AbstractQueryModelPrivate
23{
24public:
25 void doQuery() override;
26 void doClearResults() override;
27 void mergeResults(const std::vector<Location> &newLocations);
28 bool isFiltered(const Location &loc) const;
29
30 std::vector<Location> m_locations;
31
32 LocationRequest m_request;
33
34 Q_DECLARE_PUBLIC(LocationQueryModel)
35};
36}
37
38void LocationQueryModelPrivate::doQuery()
39{
41 if (!m_manager || !m_request.isValid()) {
42 return;
43 }
44
45 setLoading(true);
46 auto reply = m_manager->queryLocation(m_request);
47 monitorReply(reply);
49 mergeResults(reply->takeResult());
50 });
51}
52
53void LocationQueryModelPrivate::doClearResults()
54{
55 m_locations.clear();
56}
57
58bool LocationQueryModelPrivate::isFiltered(const Location &loc) const
59{
60 if (m_request.types() != Location::Place && loc.type() != Location::Place && (loc.type() & m_request.types()) == 0) {
61 return true;
62 }
63
64 if (m_request.hasCoordinate() && m_request.maximumDistance() > 0) {
65 return Location::distance(m_request.latitude(), m_request.longitude(), loc.latitude(), loc.longitude()) > m_request.maximumDistance();
66 }
67
68 return false;
69}
70
71void LocationQueryModelPrivate::mergeResults(const std::vector<Location> &newLocations)
72{
74
75 for (const auto &loc : newLocations) {
76 if (isFiltered(loc)) {
77 continue;
78 }
79
80 // lacking an actual useful ordering, we need to do a full search for merging
81 // LocationUtil::sortLessThan provides an order, but proximity there does not imply
82 // always all merge candidates are nearby unfortunately (e.g. in cases of native
83 // language vs. English spelling in case of name searches).
84 bool found = false;
85 for (auto it = m_locations.begin(); it != m_locations.end(); ++it) {
86 if (Location::isSame(*it, loc)) {
87 *it = Location::merge(loc, *it);
88 found = true;
89 const auto row = std::distance(m_locations.begin(), it);
90 const auto idx = q->index(row, 0);
91 Q_EMIT q->dataChanged(idx, idx);
92 break;
93 }
94 }
95 if (found) {
96 continue;
97 }
98
99 auto it = std::lower_bound(m_locations.begin(), m_locations.end(), loc, [this](const auto &lhs, const auto &rhs) {
100 return LocationUtil::sortLessThan(m_request, lhs, rhs);
101 });
102
103 const auto row = std::distance(m_locations.begin(), it);
104 q->beginInsertRows({}, row, row);
105 m_locations.insert(it, loc);
106 q->endInsertRows();
107 }
108}
109
110
111LocationQueryModel::LocationQueryModel(QObject* parent)
112 : AbstractQueryModel(new LocationQueryModelPrivate, parent)
113{
114}
115
116LocationQueryModel::~LocationQueryModel() = default;
117
119{
120 Q_D(const LocationQueryModel);
121 return d->m_request;
122}
123
124void LocationQueryModel::setRequest(const LocationRequest &req)
125{
127 d->m_request = req;
128 Q_EMIT requestChanged();
129 d->query();
130}
131
133{
134 Q_D(const LocationQueryModel);
135 return d->m_queryDelay.count();
136}
137
138void LocationQueryModel::setQueryDelay(int ms)
139{
141 if (d->m_queryDelay == std::chrono::milliseconds(ms)) {
142 return;
143 }
144
145 d->m_queryDelay = std::chrono::milliseconds(ms);
146 Q_EMIT queryDelayChanged();
147}
148
149int LocationQueryModel::rowCount(const QModelIndex &parent) const
150{
151 Q_D(const LocationQueryModel);
152 if (parent.isValid()) {
153 return 0;
154 }
155 return d->m_locations.size();
156}
157
158QVariant LocationQueryModel::data(const QModelIndex &index, int role) const
159{
160 Q_D(const LocationQueryModel);
161 if (!index.isValid()) {
162 return {};
163 }
164
165 switch (role) {
166 case Qt::DisplayRole:
167 return d->m_locations[index.row()].name();
168 case LocationRole:
169 return QVariant::fromValue(d->m_locations[index.row()]);
170 }
171
172 return {};
173}
174
175QHash<int, QByteArray> LocationQueryModel::roleNames() const
176{
178 r.insert(LocationRole, "location");
179 return r;
180}
181
182const std::vector<Location>& LocationQueryModel::locations() const
183{
184 Q_D(const LocationQueryModel);
185 return d->m_locations;
186}
187
188#include "moc_locationquerymodel.moc"
Common base class for query models, do not use directly.
Model representing location query results.
KPublicTransport::LocationRequest request
Specify the actual location query.
const std::vector< Location > & locations() const
The current model content.
int queryDelay
Delay in milliseconds until the query is actually performed.
Describes a location search.
bool isValid() const
Returns true if this is a valid request, that is it has enough parameters set to perform a query.
KPublicTransport::Location::Types types
The type of locations you are interested in.
bool hasCoordinate() const
Returns true if a valid geo coordinate has been set.
int maximumDistance
When searching by coordinate, the expected maximum distance of the results in meters.
@ Place
a location that isn't of any specific type
Definition location.h:35
static float distance(float lat1, float lon1, float lat2, float lon2)
Compute the distance between two geo coordinates, in meters.
Definition location.cpp:425
float latitude
Latitude of the location, in degree, NaN if unknown.
Definition location.h:52
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:369
float longitude
Longitude of the location, in degree, NaN if unknown.
Definition location.h:54
Type type
Location type.
Definition location.h:47
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:263
void updated()
Emitted whenever new results are available, even before the search has been completed.
Query operations and data types for accessing realtime public transport information from online servi...
virtual QHash< int, QByteArray > roleNames() const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isValid() const const
int row() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
DisplayRole
QVariant fromValue(T &&value)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:06 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.