KPublicTransport

line.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "line.h"
8#include "lineutil_p.h"
9#include "datatypes_p.h"
10#include "json_p.h"
11#include "mergeutil_p.h"
12#include "assetrepository_p.h"
13
14#include "knowledgedb/linemetadata.h"
15
16#include <QColor>
17#include <QDebug>
18#include <QUrl>
19
20using namespace Qt::Literals::StringLiterals;
21using namespace KPublicTransport;
22
23namespace KPublicTransport {
24class LinePrivate : public QSharedData {
25public:
26 Line::Mode mode = Line::Unknown;
27 QString modeString;
28 QString name;
29 QColor color;
30 QColor textColor;
31 LineMetaData metaData;
32 QString operatorName;
33};
34
35class RoutePrivate : public QSharedData {
36public:
37 Line line;
38 QString direction;
39 Location destination;
40 QString name;
41};
42
43}
44
45KPUBLICTRANSPORT_MAKE_GADGET(Line)
46KPUBLICTRANSPORT_MAKE_PROPERTY(Line, QString, name, setName)
47KPUBLICTRANSPORT_MAKE_PROPERTY(Line, QColor, textColor, setTextColor)
48KPUBLICTRANSPORT_MAKE_PROPERTY(Line, Line::Mode, mode, setMode)
49KPUBLICTRANSPORT_MAKE_PROPERTY(Line, QString, modeString, setModeString)
50KPUBLICTRANSPORT_MAKE_PROPERTY(Line, QString, operatorName, setOperatorName)
51
52QColor Line::color() const
53{
54 return d->metaData.color().isValid() ? d->metaData.color() : d->color;
55}
56
57void Line::setColor(const QColor &value)
58{
59 d.detach();
60 d->color = value;
61}
62
63bool Line::hasColor() const
64{
65 return d->color.isValid() || d->metaData.color().isValid();
66}
67
68bool Line::hasTextColor() const
69{
70 return d->textColor.isValid();
71}
72
73QString Line::logo() const
74{
75 return AssetRepository::localFile(d->metaData.logoUrl()).toString(QUrl::FullyEncoded);
76}
77
78bool Line::hasLogo() const
79{
80 return !logo().isEmpty();
81}
82
83QString Line::modeLogo() const
84{
85 return AssetRepository::localFile(d->metaData.modeLogoUrl()).toString(QUrl::FullyEncoded);
86}
87
88bool Line::hasModeLogo() const
89{
90 return !modeLogo().isEmpty();
91}
92
93QString Line::modeIconName() const
94{
95 return Line::modeIconName(mode());
96}
97
99{
100 // see https://invent.kde.org/frameworks/breeze-icons/-/issues/16
101 switch (mode) {
102 case Line::Unknown:
103 break;
104 case Line::Air:
105 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-flight.svg"_s;
106 case Line::Boat:
107 case Line::Ferry:
108 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-ferry.svg"_s;
109 case Line::Bus:
110 case Line::Shuttle:
111 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-bus.svg"_s;
112 case Line::Coach:
113 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-bus-longdistance.svg"_s;
114 case Line::Funicular:
115 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-funicular.svg"_s;
116 case Line::LocalTrain:
117 case Line::Train:
118 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-train.svg"_s;
119 case Line::LongDistanceTrain:
120 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-train-longdistance.svg"_s;
121 case Line::Metro:
122 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-subway.svg"_s;
124 case Line::RapidTransit:
125 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-rapidtransit.svg"_s;
126 case Line::Taxi:
127 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-taxi.svg"_s;
128 case Line::Tramway:
129 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-tram.svg"_s;
130 case Line::RideShare:
131 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-car.svg"_s;
132 case Line::AerialLift:
133 return u"qrc:///org.kde.kpublictransport/assets/images/transport-mode-aeriallift.svg"_s;
134 }
135
136 return u"question"_s;
137}
138
140{
141 switch (mode) {
142 case Line::Train:
143 case Line::Funicular:
144 case Line::LocalTrain:
145 case Line::LongDistanceTrain:
146 case Line::Metro:
148 case Line::RapidTransit:
149 case Line::Tramway:
150 return true;
151 default:
152 return false;
153 }
154}
155
156bool Line::isRailBound() const
157{
158 return modeIsRailBound(d->mode);
159}
160
162{
163 if (hasLogo()) {
164 return logo();
165 }
166 if (hasModeLogo()) {
167 return modeLogo();
168 }
169 return modeIconName();
170}
171
172bool Line::isSame(const Line &lhs, const Line &rhs)
173{
174 if (!LineUtil::isCompatibleMode(lhs.mode(), rhs.mode())) {
175 return false;
176 }
177
178 // ### not really the most efficient way of doing this...
179 using namespace LineUtil;
180 return isSameLineNameFuzzy(lhs.name(), rhs.name())
181 || isSameLineNameFuzzy(QString(lhs.modeString() + QLatin1Char(' ') + lhs.name()).trimmed(), rhs.name())
182 || isSameLineNameFuzzy(lhs.name(), QString(rhs.modeString() + QLatin1Char(' ') + rhs.name()).trimmed())
183 || isSameLineNameFuzzy(QString(lhs.modeString() + QLatin1Char(' ') + lhs.name()).trimmed(), QString(rhs.modeString() + QLatin1Char(' ') + rhs.name()).trimmed());
184}
185
186static QColor mergeColor(const QColor &lhs, const QColor &rhs)
187{
188 if (!lhs.isValid()) {
189 return rhs;
190 }
191 if (!rhs.isValid()) {
192 return lhs;
193 }
194
195 const auto lh = lhs.hue(), ls = lhs.saturation(), lv = lhs.value();
196 const auto rh = rhs.hue(), rs = rhs.saturation(), rv = rhs.value();
197 return std::tie(ls, lv, lh) < std::tie(rs, rv, rh) ? rhs : lhs;
198}
199
200Line Line::merge(const Line &lhs, const Line &rhs)
201{
202 Line l(lhs);
203
204 l.setModeString(MergeUtil::mergeString(lhs.modeString(), rhs.modeString()));
205 l.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
207 l.setName(QStringView(l.name()).mid(l.modeString().size()).trimmed().toString());
208 }
209
210 l.setColor(mergeColor(lhs.color(), rhs.color()));
211 if (!l.textColor().isValid() && rhs.textColor().isValid()) {
212 l.setTextColor(rhs.textColor());
213 }
214 if (l.mode() == Unknown || (l.mode() == Train && rhs.mode() != Unknown)) {
215 l.setMode(rhs.mode());
216 }
217
218 l.setOperatorName(MergeUtil::mergeString(lhs.operatorName(), rhs.operatorName()));
219 return l;
220}
221
222void Line::applyMetaData(const Location &location, bool download)
223{
224 if (name().isEmpty() || !location.hasCoordinate()) {
225 return;
226 }
227
228 d->metaData = LineMetaData::find(location.latitude(), location.longitude(), name(), mode());
229
230 if (download && AssetRepository::instance()) {
231 AssetRepository::instance()->download(d->metaData.logoUrl());
232 AssetRepository::instance()->download(d->metaData.modeLogoUrl());
233 }
234}
235
237{
238 auto obj = Json::toJson(l);
239 if (l.mode() == Unknown) {
240 obj.remove(QLatin1String("mode"));
241 }
242 return obj;
243}
244
246{
247 auto l = Json::fromJson<Line>(obj);
248 return l;
249}
250
251
252KPUBLICTRANSPORT_MAKE_GADGET(Route)
253KPUBLICTRANSPORT_MAKE_PROPERTY(Route, Line, line, setLine)
254KPUBLICTRANSPORT_MAKE_PROPERTY(Route, Location, destination, setDestination)
255KPUBLICTRANSPORT_MAKE_PROPERTY(Route, QString, name, setName)
256
258{
259 if (d->direction.isEmpty() && !d->destination.isEmpty()) {
260 return d->destination.name();
261 }
262 return d->direction;
263}
264
265void Route::setDirection(const QString &value)
266{
267 d.detach();
268 d->direction = value;
269}
270
271bool Route::isSame(const Route &lhs, const Route &rhs)
272{
273 const auto matchingDirection = (!lhs.destination().isEmpty() && !rhs.destination().isEmpty() && Location::isSame(lhs.destination(), rhs.destination()))
275
276 const auto matchingRouteName = lhs.name().size() < 3 || rhs.name().size() < 3 || lhs.name().endsWith(rhs.name()) || rhs.name().endsWith(lhs.name());
277
278 return matchingDirection && matchingRouteName && Line::isSame(lhs.line(), rhs.line());
279}
280
281Route Route::merge(const Route &lhs, const Route &rhs)
282{
283 Route r(lhs);
284 r.setLine(Line::merge(lhs.line(), rhs.line()));
285 r.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
286 r.setDirection(MergeUtil::mergeString(lhs.direction(), rhs.direction()));
287 r.setDestination(Location::merge(lhs.destination(), rhs.destination()));
288 return r;
289}
290
292{
293 auto obj = Json::toJson(r);
294 const auto lineObj = Line::toJson(r.line());
295 if (!lineObj.empty()) {
296 obj.insert(QLatin1String("line"), lineObj);
297 }
298 if (!r.destination().isEmpty()) {
299 obj.insert(QLatin1String("destination"), Location::toJson(r.destination()));
300 }
301 return obj;
302}
303
305{
306 auto r = Json::fromJson<Route>(obj);
307 r.setLine(Line::fromJson(obj.value(QLatin1String("line")).toObject()));
308 r.setDestination(Location::fromJson(obj.value(QLatin1String("destination")).toObject()));
309 return r;
310}
311
312#include "moc_line.cpp"
static LineMetaData find(double latitude, double longitude, const QString &name, Line::Mode mode)
Attempts to find information about a line with the given name and a stop at the given coordinates.
A public transport line.
Definition line.h:20
KPublicTransport::Line::Mode mode
Type of transport.
Definition line.h:60
bool hasTextColor
true if a text color is set.
Definition line.h:58
static Line fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:245
QString name
Name of the line.
Definition line.h:50
QString modeString
Human readable representation of the type of transport.
Definition line.h:65
bool hasLogo
true if the line has a logo.
Definition line.h:74
static Line merge(const Line &lhs, const Line &rhs)
Merge two Line instances.
Definition line.cpp:200
bool hasColor
true if a line color is set.
Definition line.h:54
QString operatorName
Name of the operator running this line.
Definition line.h:88
QColor color
Color of the line.
Definition line.h:52
QString modeIconName
Generic icon for the line mode.
Definition line.h:93
void applyMetaData(const Location &location, bool download)
Look up line meta data and apply what is found.
Definition line.cpp:222
QString logo
Path of a local file containing the line logo.
Definition line.h:72
QString iconName
The best available icon for this line.
Definition line.h:102
QColor textColor
Text color to use on top of the line color.
Definition line.h:56
QString modeLogo
Path of a local file containing the line mode logo.
Definition line.h:83
static QJsonObject toJson(const Line &l)
Serializes one object to JSON.
Definition line.cpp:236
Mode
Mode of transportation.
Definition line.h:27
@ RideShare
peer-to-peer ride sharing/car pooling
Definition line.h:44
@ RailShuttle
rail shuttle service within a complex, as e.g. found at or around airports
Definition line.h:38
@ Shuttle
shuttle bus/coach services, e.g. to/from an airport
Definition line.h:40
@ AerialLift
aerial cable cars, gondolas, etc
Definition line.h:45
bool hasModeLogo
true if the line has a mode logo.
Definition line.h:85
bool isRailBound
true if mode is bound to rail tracks.
Definition line.h:105
static bool modeIsRailBound(KPublicTransport::Line::Mode mode)
true if mode is bound to rail tracks.
Definition line.cpp:139
static bool isSame(const Line &lhs, const Line &rhs)
Checks if to instances refer to the same line (which does not necessarily mean they are exactly equal...
Definition line.cpp:172
static Location fromJson(const QJsonObject &obj)
Deserialize a Location object from JSON.
Definition location.cpp:539
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition location.cpp:360
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition location.cpp:478
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:407
bool isEmpty() const
Returns true if this is an default-constructed location object not specifying any location.
Definition location.cpp:121
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:312
A route of a public transport line.
Definition line.h:152
KPublicTransport::Location destination
Destination of the route.
Definition line.h:166
QString direction
Direction of the route.
Definition line.h:161
static bool isSame(const Route &lhs, const Route &rhs)
Checks if to instances refer to the same route (which does not necessarily mean they are exactly equa...
Definition line.cpp:271
QString name
Name of the route.
Definition line.h:174
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition line.cpp:291
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition line.cpp:281
KPublicTransport::Line line
Line this route belongs to.
Definition line.h:155
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:304
Query operations and data types for accessing realtime public transport information from online servi...
int hue() const const
bool isValid() const const
int saturation() const const
int value() const const
QJsonValue value(QLatin1StringView key) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString trimmed() const const
QStringView mid(qsizetype start, qsizetype length) const const
QString toString() const const
QStringView trimmed() const const
CaseInsensitive
FullyEncoded
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 11:47:05 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.