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
84{
85 return AssetRepository::localFile(d->metaData.modeLogoUrl()).toString(QUrl::FullyEncoded);
86}
87
88bool Line::hasModeLogo() const
89{
90 return !modeLogo().isEmpty();
91}
92
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
157{
158 if (hasLogo()) {
159 return logo();
160 }
161 if (hasModeLogo()) {
162 return modeLogo();
163 }
164 return modeIconName();
165}
166
167bool Line::isSame(const Line &lhs, const Line &rhs)
168{
169 if (!LineUtil::isCompatibleMode(lhs.mode(), rhs.mode())) {
170 return false;
171 }
172
173 // ### not really the most efficient way of doing this...
174 using namespace LineUtil;
175 return isSameLineNameFuzzy(lhs.name(), rhs.name())
176 || isSameLineNameFuzzy(QString(lhs.modeString() + QLatin1Char(' ') + lhs.name()).trimmed(), rhs.name())
177 || isSameLineNameFuzzy(lhs.name(), QString(rhs.modeString() + QLatin1Char(' ') + rhs.name()).trimmed())
178 || isSameLineNameFuzzy(QString(lhs.modeString() + QLatin1Char(' ') + lhs.name()).trimmed(), QString(rhs.modeString() + QLatin1Char(' ') + rhs.name()).trimmed());
179}
180
181static QColor mergeColor(const QColor &lhs, const QColor &rhs)
182{
183 if (!lhs.isValid()) {
184 return rhs;
185 }
186 if (!rhs.isValid()) {
187 return lhs;
188 }
189
190 const auto lh = lhs.hue(), ls = lhs.saturation(), lv = lhs.value();
191 const auto rh = rhs.hue(), rs = rhs.saturation(), rv = rhs.value();
192 return std::tie(ls, lv, lh) < std::tie(rs, rv, rh) ? rhs : lhs;
193}
194
195Line Line::merge(const Line &lhs, const Line &rhs)
196{
197 Line l(lhs);
198
199 l.setModeString(MergeUtil::mergeString(lhs.modeString(), rhs.modeString()));
200 l.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
202 l.setName(QStringView(l.name()).mid(l.modeString().size()).trimmed().toString());
203 }
204
205 l.setColor(mergeColor(lhs.color(), rhs.color()));
206 if (!l.textColor().isValid() && rhs.textColor().isValid()) {
207 l.setTextColor(rhs.textColor());
208 }
209 if (l.mode() == Unknown || (l.mode() == Train && rhs.mode() != Unknown)) {
210 l.setMode(rhs.mode());
211 }
212
213 l.setOperatorName(MergeUtil::mergeString(lhs.operatorName(), rhs.operatorName()));
214 return l;
215}
216
217void Line::applyMetaData(const Location &location, bool download)
218{
219 if (name().isEmpty() || !location.hasCoordinate()) {
220 return;
221 }
222
223 d->metaData = LineMetaData::find(location.latitude(), location.longitude(), name(), mode());
224
225 if (download && AssetRepository::instance()) {
226 AssetRepository::instance()->download(d->metaData.logoUrl());
227 AssetRepository::instance()->download(d->metaData.modeLogoUrl());
228 }
229}
230
232{
233 auto obj = Json::toJson(l);
234 if (l.mode() == Unknown) {
235 obj.remove(QLatin1String("mode"));
236 }
237 return obj;
238}
239
241{
242 auto l = Json::fromJson<Line>(obj);
243 return l;
244}
245
246
247KPUBLICTRANSPORT_MAKE_GADGET(Route)
248KPUBLICTRANSPORT_MAKE_PROPERTY(Route, Line, line, setLine)
249KPUBLICTRANSPORT_MAKE_PROPERTY(Route, Location, destination, setDestination)
250KPUBLICTRANSPORT_MAKE_PROPERTY(Route, QString, name, setName)
251
253{
254 if (d->direction.isEmpty() && !d->destination.isEmpty()) {
255 return d->destination.name();
256 }
257 return d->direction;
258}
259
260void Route::setDirection(const QString &value)
261{
262 d.detach();
263 d->direction = value;
264}
265
266bool Route::isSame(const Route &lhs, const Route &rhs)
267{
268 const auto matchingDirection = (!lhs.destination().isEmpty() && !rhs.destination().isEmpty() && Location::isSame(lhs.destination(), rhs.destination()))
270
271 const auto matchingRouteName = lhs.name().size() < 3 || rhs.name().size() < 3 || lhs.name().endsWith(rhs.name()) || rhs.name().endsWith(lhs.name());
272
273 return matchingDirection && matchingRouteName && Line::isSame(lhs.line(), rhs.line());
274}
275
276Route Route::merge(const Route &lhs, const Route &rhs)
277{
278 Route r(lhs);
279 r.setLine(Line::merge(lhs.line(), rhs.line()));
280 r.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
281 r.setDirection(MergeUtil::mergeString(lhs.direction(), rhs.direction()));
282 r.setDestination(Location::merge(lhs.destination(), rhs.destination()));
283 return r;
284}
285
287{
288 auto obj = Json::toJson(r);
289 const auto lineObj = Line::toJson(r.line());
290 if (!lineObj.empty()) {
291 obj.insert(QLatin1String("line"), lineObj);
292 }
293 if (!r.destination().isEmpty()) {
294 obj.insert(QLatin1String("destination"), Location::toJson(r.destination()));
295 }
296 return obj;
297}
298
300{
301 auto r = Json::fromJson<Route>(obj);
302 r.setLine(Line::fromJson(obj.value(QLatin1String("line")).toObject()));
303 r.setDestination(Location::fromJson(obj.value(QLatin1String("destination")).toObject()));
304 return r;
305}
306
307#include "moc_line.cpp"
Static information about a public transport line.
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:240
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:195
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:217
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:231
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
static bool modeIsRailBound(KPublicTransport::Line::Mode mode)
true if mode is bounds 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:167
static Location fromJson(const QJsonObject &obj)
Deserialize a Location object from JSON.
Definition location.cpp:559
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition location.cpp:370
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition location.cpp:494
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:417
bool isEmpty() const
Returns true if this is an default-constructed location object not specifying any location.
Definition location.cpp:120
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:311
A route of a public transport line.
Definition line.h:148
KPublicTransport::Location destination
Destination of the route.
Definition line.h:162
QString direction
Direction of the route.
Definition line.h:157
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:266
QString name
Name of the route.
Definition line.h:170
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition line.cpp:286
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition line.cpp:276
KPublicTransport::Line line
Line this route belongs to.
Definition line.h:151
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:299
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-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:07:52 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.