KPublicTransport

locationquerymodel.cpp
1 /*
2  SPDX-FileCopyrightText: 2019 Volker Krause <[email protected]>
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 
19 using namespace KPublicTransport;
20 
21 namespace KPublicTransport {
22 class LocationQueryModelPrivate : public AbstractQueryModelPrivate
23 {
24 public:
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 
38 void LocationQueryModelPrivate::doQuery()
39 {
40  Q_Q(LocationQueryModel);
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 
53 void LocationQueryModelPrivate::doClearResults()
54 {
55  m_locations.clear();
56 }
57 
58 bool 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 
71 void LocationQueryModelPrivate::mergeResults(const std::vector<Location> &newLocations)
72 {
73  Q_Q(LocationQueryModel);
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 
111 LocationQueryModel::LocationQueryModel(QObject* parent)
112  : AbstractQueryModel(new LocationQueryModelPrivate, parent)
113 {
114 }
115 
116 LocationQueryModel::~LocationQueryModel() = default;
117 
118 LocationRequest LocationQueryModel::request() const
119 {
120  Q_D(const LocationQueryModel);
121  return d->m_request;
122 }
123 
124 void LocationQueryModel::setRequest(const LocationRequest &req)
125 {
126  Q_D(LocationQueryModel);
127  d->m_request = req;
128  Q_EMIT requestChanged();
129  d->query();
130 }
131 
132 int LocationQueryModel::rowCount(const QModelIndex &parent) const
133 {
134  Q_D(const LocationQueryModel);
135  if (parent.isValid()) {
136  return 0;
137  }
138  return d->m_locations.size();
139 }
140 
141 QVariant LocationQueryModel::data(const QModelIndex &index, int role) const
142 {
143  Q_D(const LocationQueryModel);
144  if (!index.isValid()) {
145  return {};
146  }
147 
148  switch (role) {
149  case Qt::DisplayRole:
150  return d->m_locations[index.row()].name();
151  case LocationRole:
152  return QVariant::fromValue(d->m_locations[index.row()]);
153  }
154 
155  return {};
156 }
157 
158 QHash<int, QByteArray> LocationQueryModel::roleNames() const
159 {
161  r.insert(LocationRole, "location");
162  return r;
163 }
164 
165 const std::vector<Location>& LocationQueryModel::locations() const
166 {
167  Q_D(const LocationQueryModel);
168  return d->m_locations;
169 }
170 
171 #include "moc_locationquerymodel.moc"
Query operations and data types for accessing realtime public transport information from online servi...
Definition: attribution.cpp:16
a location that isn&#39;t of any specific type
Definition: location.h:35
virtual QHash< int, QByteArray > roleNames() const const
Model representing location query results.
float latitude
Latitude of the location, in degree, NaN if unknown.
Definition: location.h:52
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:262
void updated()
Emitted whenever new results are available, even before the search has been completed.
bool isValid() const const
Definition: location.h:16
float longitude
Longitude of the location, in degree, NaN if unknown.
Definition: location.h:54
DisplayRole
int row() const const
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition: location.cpp:368
const std::vector< Location > & locations() const
The current model content.
QVariant fromValue(const T &value)
Describes a location search.
static float distance(float lat1, float lon1, float lat2, float lon2)
Compute the distance between two geo coordinates, in meters.
Definition: location.cpp:424
Common base class for query models, do not use directly.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:05:21 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.