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 const auto platform = m_stopover.platformLayout();
80 for (const auto &sec : platform.sections()) {
81 if (sec.name() == startSection) {
82 interpolatePlatformPositionsFromSectionName(vehicleSections.begin(), vehicleSections.end());
83 break;
84 } else if (sec.name() == endSection) {
85 interpolatePlatformPositionsFromSectionName(vehicleSections.rbegin(), vehicleSections.rend());
86 break;
87 }
88 }
89
90 vehicle.setSections(std::move(vehicleSections));
91 m_stopover.setVehicleLayout(std::move(vehicle));
92}
93
94template<typename Iter>
95void VehicleLayoutQueryModelPrivate::interpolatePlatformPositionsFromSectionName(Iter begin, Iter end)
96{
97 auto rangeBegin = begin, rangeEnd = begin;
98 float minLength = 1.0;
99 while (rangeBegin != end) {
100 while (rangeEnd != end && (*rangeBegin).platformSectionName() == (*rangeEnd).platformSectionName()) {
101 ++rangeEnd;
102 }
103
104 const auto platformIt = std::find_if(m_stopover.platformLayout().sections().begin(), m_stopover.platformLayout().sections().end(), [&rangeBegin](const auto &p) {
105 return p.name() == (*rangeBegin).platformSectionName();
106 });
107 if (platformIt == m_stopover.platformLayout().sections().end()) {
108 qWarning() << "Failed to find platform section" << (*rangeBegin).platformSectionName();
109 return;
110 }
111
112 auto l = ((*platformIt).end() - (*platformIt).begin()) / std::distance(rangeBegin, rangeEnd);
113 minLength = std::min(minLength, l);
114
115 if (rangeEnd == end) { // trailing coaches, don't scale them to the full section
116 l = minLength;
117 }
118
119 auto pos = (*platformIt).begin();
120 for (auto it = rangeBegin; it != rangeEnd; ++it) {
121 (*it).setPlatformPositionBegin(pos);
122 (*it).setPlatformPositionEnd(pos + l);
123 pos += l;
124 }
125
126 rangeBegin = rangeEnd;
127 }
128
129 // fix-up leading coaches to not fill up the entire platform section
130 rangeEnd = std::find_if(begin, end, [&begin](const auto &p) {
131 return p.platformSectionName() != (*begin).platformSectionName();
132 });
133 auto pos = (*std::prev(rangeEnd)).platformPositionEnd() - std::distance(begin, rangeEnd) * minLength;
134 for (auto it = begin; it != rangeEnd; ++it) {
135 (*it).setPlatformPositionBegin(pos);
136 (*it).setPlatformPositionEnd(pos + minLength);
137 pos += minLength;
138 }
139}
140
141
142VehicleLayoutQueryModel::VehicleLayoutQueryModel(QObject* parent)
143 : AbstractQueryModel(new VehicleLayoutQueryModelPrivate, parent)
144{
145}
146
147VehicleLayoutQueryModel::~VehicleLayoutQueryModel() = default;
148
149VehicleLayoutRequest VehicleLayoutQueryModel::request() const
150{
152 return d->m_request;
153}
154
155void VehicleLayoutQueryModel::setRequest(const VehicleLayoutRequest &req)
156{
158 d->m_request = req;
159 Q_EMIT requestChanged();
160 d->query();
161}
162
164{
165 return stopover().vehicleLayout();
166}
167
169{
170 return stopover().platformLayout();
171}
172
174{
176 return d->m_stopover;
177}
178
179int VehicleLayoutQueryModel::rowCount(const QModelIndex &parent) const
180{
182 if (parent.isValid()) {
183 return 0;
184 }
185 return d->m_stopover.vehicleLayout().sections().size();
186}
187
188QVariant VehicleLayoutQueryModel::data(const QModelIndex &index, int role) const
189{
191 if (!index.isValid()) {
192 return {};
193 }
194
195 switch (role) {
196 case VehicleSectionRole:
197 return QVariant::fromValue(d->m_stopover.vehicleLayout().sections()[index.row()]);
198 }
199
200 return {};
201}
202
203QHash<int, QByteArray> VehicleLayoutQueryModel::roleNames() const
204{
206 r.insert(VehicleSectionRole, "vehicleSection");
207 return r;
208}
209
210#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
void setSections(std::vector< PlatformSection > &&sections)
Sets the platform sections.
Definition platform.cpp:82
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:159
bool hasPlatformPositions() const
Checks whether all vehicle sections have platform positions set.
Definition vehicle.cpp:294
bool hasPlatformSectionNames() const
Check whether all vehicle sections have platform section names set.
Definition vehicle.cpp:299
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition vehicle.cpp:176
std::vector< VehicleSection > && takeSections()
Moves the vehicle sections out of this object.
Definition vehicle.cpp:186
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 Sat Dec 21 2024 16:59:57 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.