KPublicTransport

vehiclelayoutquerymodel.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 "vehiclelayoutquerymodel.h"
8#include "abstractquerymodel_p.h"
9
10#include <KPublicTransport/Attribution>
11#include <KPublicTransport/VehicleLayoutReply>
12#include <KPublicTransport/Manager>
13
14#include <QDebug>
15
16using namespace KPublicTransport;
17
18namespace KPublicTransport {
19class VehicleLayoutQueryModelPrivate : public AbstractQueryModelPrivate
20{
21public:
22 void doQuery() override;
23 void doClearResults() override;
24
25 void interpolatePlatformPositionsFromSectionName();
26 template <typename Iter>
27 void interpolatePlatformPositionsFromSectionName(Iter begin, Iter end);
28
29 VehicleLayoutRequest m_request;
30 Stopover m_stopover;
31
32 Q_DECLARE_PUBLIC(VehicleLayoutQueryModel)
33};
34}
35
36void VehicleLayoutQueryModelPrivate::doQuery()
37{
39 if (!m_manager || !m_request.isValid()) {
40 return;
41 }
42
43 // if the request already contains useful information, let's use those already
44 q->beginResetModel();
45 m_stopover = m_request.stopover();
46 q->endResetModel();
47 Q_EMIT q->contentChanged();
48
49 setLoading(true);
50 auto reply = m_manager->queryVehicleLayout(m_request);
51 monitorReply(reply);
54 q->beginResetModel();
55 m_stopover = reply->stopover();
56 if (!m_stopover.platformLayout().isEmpty() && !m_stopover.vehicleLayout().isEmpty()
57 && !m_stopover.vehicleLayout().hasPlatformPositions() && m_stopover.vehicleLayout().hasPlatformSectionNames()) {
58 interpolatePlatformPositionsFromSectionName();
59 }
60 q->endResetModel();
61 Q_EMIT q->contentChanged();
62 });
63}
64
65void VehicleLayoutQueryModelPrivate::doClearResults()
66{
67 m_stopover = {};
69 Q_EMIT q->contentChanged();
70}
71
72void VehicleLayoutQueryModelPrivate::interpolatePlatformPositionsFromSectionName()
73{
74 auto vehicle = m_stopover.vehicleLayout();
75 auto vehicleSections = vehicle.takeSections();
76 const auto startSection = vehicleSections.front().platformSectionName();
77 const auto endSection = vehicleSections.back().platformSectionName();
78
79 for (const auto &sec : m_stopover.platformLayout().sections()) {
80 if (sec.name() == startSection) {
81 interpolatePlatformPositionsFromSectionName(vehicleSections.begin(), vehicleSections.end());
82 break;
83 } else if (sec.name() == endSection) {
84 interpolatePlatformPositionsFromSectionName(vehicleSections.rbegin(), vehicleSections.rend());
85 break;
86 }
87 }
88
89 vehicle.setSections(std::move(vehicleSections));
90 m_stopover.setVehicleLayout(std::move(vehicle));
91}
92
93template<typename Iter>
94void VehicleLayoutQueryModelPrivate::interpolatePlatformPositionsFromSectionName(Iter begin, Iter end)
95{
96 auto rangeBegin = begin, rangeEnd = begin;
97 float minLength = 1.0;
98 while (rangeBegin != end) {
99 while (rangeEnd != end && (*rangeBegin).platformSectionName() == (*rangeEnd).platformSectionName()) {
100 ++rangeEnd;
101 }
102
103 const auto platformIt = std::find_if(m_stopover.platformLayout().sections().begin(), m_stopover.platformLayout().sections().end(), [&rangeBegin](const auto &p) {
104 return p.name() == (*rangeBegin).platformSectionName();
105 });
106 if (platformIt == m_stopover.platformLayout().sections().end()) {
107 qWarning() << "Failed to find platform section" << (*rangeBegin).platformSectionName();
108 return;
109 }
110
111 auto l = ((*platformIt).end() - (*platformIt).begin()) / std::distance(rangeBegin, rangeEnd);
112 minLength = std::min(minLength, l);
113
114 if (rangeEnd == end) { // trailing coaches, don't scale them to the full section
115 l = minLength;
116 }
117
118 auto pos = (*platformIt).begin();
119 for (auto it = rangeBegin; it != rangeEnd; ++it) {
120 (*it).setPlatformPositionBegin(pos);
121 (*it).setPlatformPositionEnd(pos + l);
122 pos += l;
123 }
124
125 rangeBegin = rangeEnd;
126 }
127
128 // fix-up leading coaches to not fill up the entire platform section
129 rangeEnd = std::find_if(begin, end, [&begin](const auto &p) {
130 return p.platformSectionName() != (*begin).platformSectionName();
131 });
132 auto pos = (*std::prev(rangeEnd)).platformPositionEnd() - std::distance(begin, rangeEnd) * minLength;
133 for (auto it = begin; it != rangeEnd; ++it) {
134 (*it).setPlatformPositionBegin(pos);
135 (*it).setPlatformPositionEnd(pos + minLength);
136 pos += minLength;
137 }
138}
139
140
141VehicleLayoutQueryModel::VehicleLayoutQueryModel(QObject* parent)
142 : AbstractQueryModel(new VehicleLayoutQueryModelPrivate, parent)
143{
144}
145
146VehicleLayoutQueryModel::~VehicleLayoutQueryModel() = default;
147
148VehicleLayoutRequest VehicleLayoutQueryModel::request() const
149{
151 return d->m_request;
152}
153
154void VehicleLayoutQueryModel::setRequest(const VehicleLayoutRequest &req)
155{
157 d->m_request = req;
158 Q_EMIT requestChanged();
159 d->query();
160}
161
163{
164 return stopover().vehicleLayout();
165}
166
168{
169 return stopover().platformLayout();
170}
171
173{
175 return d->m_stopover;
176}
177
178int VehicleLayoutQueryModel::rowCount(const QModelIndex &parent) const
179{
181 if (parent.isValid()) {
182 return 0;
183 }
184 return d->m_stopover.vehicleLayout().sections().size();
185}
186
187QVariant VehicleLayoutQueryModel::data(const QModelIndex &index, int role) const
188{
190 if (!index.isValid()) {
191 return {};
192 }
193
194 switch (role) {
195 case VehicleSectionRole:
196 return QVariant::fromValue(d->m_stopover.vehicleLayout().sections()[index.row()]);
197 }
198
199 return {};
200}
201
202QHash<int, QByteArray> VehicleLayoutQueryModel::roleNames() const
203{
205 r.insert(VehicleSectionRole, "vehicleSection");
206 return r;
207}
208
209#include "moc_vehiclelayoutquerymodel.moc"
Common base class for query models, do not use directly.
Information about the layout of a station platform.
Definition platform.h:45
bool isEmpty() const
Returns true if this object contains no information beyond default values.
Definition platform.cpp:66
QVariantList sections
Platform sections for consumption by QML.
Definition platform.h:62
void finished()
Emitted whenever the corresponding search has been completed.
Information about an arrival and/or departure of a vehicle at a stop area.
Definition stopover.h:26
KPublicTransport::Vehicle vehicleLayout
Vehicle coach layout information at this stopover.
Definition stopover.h:77
KPublicTransport::Platform platformLayout
Platform layout information.
Definition stopover.h:79
Model for retrieving vehicle and platform layout query results.
KPublicTransport::Vehicle vehicle
The vehicle for which this model shows its sections.
KPublicTransport::Stopover stopover
The departure this vehicle layout belongs to.
KPublicTransport::Platform platform
The platform this vehicle is departing from.
Describes a query for vehicle layout information.
bool isValid() const
Returns true if this is a valid request, that is it has enough parameters set to perform a query.
KPublicTransport::Stopover stopover
The stopover vehicle and platform layout information are requested for.
Information about the vehicle used on a journey.
Definition vehicle.h:144
bool hasPlatformPositions() const
Checks whether all vehicle sections have platform positions set.
Definition vehicle.cpp:230
bool hasPlatformSectionNames() const
Check whether all vehicle sections have platform section names set.
Definition vehicle.cpp:235
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition vehicle.cpp:118
std::vector< VehicleSection > && takeSections()
Moves the vehicle sections out of this object.
Definition vehicle.cpp:128
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
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.