Marble

Placemark.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2011 Dennis Nienhüser <nienhueser@kde.org>
4//
5
6#include "Placemark.h"
7
8#ifdef HAVE_QT6_POSITIONING
9#include <GeoDataExtendedData.h>
10#include <QGeoAddress>
11#endif // HAVE_QT6_POSITIONING
12#include <QRegularExpression>
13
14#include "GeoDataDocument.h"
15#include <osm/OsmPlacemarkData.h>
16
17namespace Marble
18{
19
21 : QObject(parent)
22{
23 // nothing to do
24}
25
26void Placemark::setGeoDataPlacemark(const Marble::GeoDataPlacemark &placemark)
27{
28 m_placemark = placemark;
29 m_address = QString();
30 m_description = QString();
31 m_website = QString();
32 m_wikipedia = QString();
33 m_openingHours = QString();
34 m_wheelchairInfo = QString();
35 m_wifiAvailable = QString();
36 m_phone = QString();
37 updateTags();
38 updateRelations(placemark);
39 Q_EMIT coordinatesChanged();
40 Q_EMIT nameChanged();
41 Q_EMIT descriptionChanged();
42 Q_EMIT addressChanged();
43 Q_EMIT websiteChanged();
44 Q_EMIT wikipediaChanged();
45 Q_EMIT openingHoursChanged();
46 Q_EMIT wheelchairInfoChanged();
47 Q_EMIT wifiAvailabilityChanged();
48 Q_EMIT phoneChanged();
49 Q_EMIT tagsChanged();
50}
51
52Marble::GeoDataPlacemark &Placemark::placemark()
53{
54 return m_placemark;
55}
56
57const GeoDataPlacemark &Placemark::placemark() const
58{
59 return m_placemark;
60}
61
62QString Placemark::name() const
63{
64 return m_placemark.displayName();
65}
66
67QString Placemark::description() const
68{
69 if (m_description.isEmpty()) {
70 auto const category = m_placemark.visualCategory();
71 m_description = m_placemark.categoryName();
72
73 if (category == GeoDataPlacemark::AccomodationHotel || category == GeoDataPlacemark::FoodRestaurant) {
74 QString const stars = m_placemark.osmData().tagValue(QStringLiteral("stars"));
75 if (!stars.isEmpty()) {
76 bool hasStars;
77 int const numStars = QStringView{stars}.mid(0, 1).toInt(&hasStars);
78 if (hasStars) {
79 m_description += u' ' + QStringLiteral("★").repeated(numStars) + stars.mid(1);
80 } else {
81 addTagValue(m_description, QStringLiteral("stars"));
82 }
83 }
84 addFirstTagValueOf(m_description, QStringList() << QStringLiteral("brand") << QStringLiteral("operator"));
85 }
86
87 if ((category >= GeoDataPlacemark::AccomodationHostel && category <= GeoDataPlacemark::AccomodationGuestHouse)
88 || category == GeoDataPlacemark::HealthHospital) {
89 int const rooms = m_placemark.osmData().tagValue(QStringLiteral("rooms")).toInt();
90 if (rooms > 0) {
91 //~ singular %n room
92 //~ plural %n rooms
93 addTagValue(m_description, QStringLiteral("rooms"), tr("%n rooms", nullptr, rooms));
94 }
95 int const beds = m_placemark.osmData().tagValue(QStringLiteral("beds")).toInt();
96 if (beds > 0) {
97 //~ singular %n bed
98 //~ plural %n beds
99 addTagValue(m_description, QStringLiteral("beds"), tr("%n beds", nullptr, beds));
100 }
101 }
102
103 if (category == GeoDataPlacemark::TransportParking || category == GeoDataPlacemark::TransportBicycleParking
104 || category == GeoDataPlacemark::TransportMotorcycleParking) {
105 addTagValue(m_description, QStringLiteral("capacity"), tr("%1 parking spaces"));
106 addTagValue(m_description, QStringLiteral("maxstay"), tr("Maximum parking time %1"));
107 }
108
109 if (category >= GeoDataPlacemark::FoodBar && category <= GeoDataPlacemark::FoodRestaurant) {
110 if (category != GeoDataPlacemark::FoodRestaurant) {
111 addFirstTagValueOf(m_description, QStringList() << QStringLiteral("brand") << QStringLiteral("operator"));
112 } else {
113 // Do nothing, already added in stars section above
114 }
115 addTagValue(m_description, QStringLiteral("cuisine"));
116 addTagValue(m_description, QStringLiteral("brewery"));
117 addTagDescription(m_description, QStringLiteral("self_service"), QStringLiteral("yes"), QStringLiteral("Self Service"));
118 addTagDescription(m_description, QStringLiteral("takeaway"), QStringLiteral("yes"), QStringLiteral("Take Away"));
119 addTagDescription(m_description, QStringLiteral("outdoor_seating"), QStringLiteral("yes"), QStringLiteral("Outdoor Seating"));
120 addTagDescription(m_description, QStringLiteral("ice_cream"), QStringLiteral("yes"), QStringLiteral("Ice Cream"));
121 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("dedicated"), QStringLiteral("Smoking (dedicated)"));
122 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("yes"), QStringLiteral("Smoking allowed"));
123 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("separated"), QStringLiteral("Smoking (separated)"));
124 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("isolated"), QStringLiteral("Smoking (isolated)"));
125 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("no"), QStringLiteral("No smoking"));
126 addTagDescription(m_description, QStringLiteral("smoking"), QStringLiteral("outside"), QStringLiteral("Smoking (outside)"));
127 addTagDescription(m_description, QStringLiteral("smoking:outside"), QStringLiteral("yes"), QStringLiteral("Smoking (outside)"));
128 addTagDescription(m_description, QStringLiteral("smoking:outside"), QStringLiteral("separated"), QStringLiteral("Smoking (outside separated)"));
129 addTagDescription(m_description, QStringLiteral("smoking:outside"), QStringLiteral("no"), QStringLiteral("No smoking outside"));
130 } else if (category >= GeoDataPlacemark::ShopBeverages && category <= GeoDataPlacemark::Shop) {
131 addFirstTagValueOf(m_description, QStringList() << QStringLiteral("brand") << QStringLiteral("operator"));
132 addTagValue(m_description, QStringLiteral("clothes"));
133 addTagValue(m_description, QStringLiteral("designation"));
134 if (category == GeoDataPlacemark::ShopButcher) {
135 addTagValue(m_description, QStringLiteral("butcher"));
136 } else if (category == GeoDataPlacemark::ShopCopy) {
137 addTagDescription(m_description,
138 QStringLiteral("service:computer"),
139 QStringLiteral("yes"),
140 tr("Computers available", "A copy shop provides computers for customer use"));
141 addTagDescription(m_description,
142 QStringLiteral("service:computer"),
143 QStringLiteral("no"),
144 tr("No computers available", "A copy shop does not provide computers for customer use"));
145 addTagDescription(m_description,
146 QStringLiteral("service:copy"),
147 QStringLiteral("yes"),
148 tr("Photocopying service", "A copy shop provides photocopying service"));
149 addTagDescription(m_description,
150 QStringLiteral("service:copy"),
151 QStringLiteral("no"),
152 tr("No photocopying service", "A copy shop does not provide photocopying service"));
153 addTagDescription(m_description,
154 QStringLiteral("service:scan"),
155 QStringLiteral("yes"),
156 tr("Digital scanning", "A copy shop provides a service for scanning documents into digital files"));
157 addTagDescription(m_description,
158 QStringLiteral("service:scan"),
159 QStringLiteral("no"),
160 tr("No digital scanning", "A copy shop does not provide a service for scanning documents into digital files"));
161 addTagDescription(m_description,
162 QStringLiteral("service:fax"),
163 QStringLiteral("yes"),
164 tr("Fax service", "A copy shop provides a service to send documents through fax"));
165 addTagDescription(m_description,
166 QStringLiteral("service:fax"),
167 QStringLiteral("no"),
168 tr("No fax service", "A copy shop does not provide a service to send documents through fax"));
169 addTagDescription(m_description,
170 QStringLiteral("service:phone"),
171 QStringLiteral("yes"),
172 tr("Phone service", "A copy shop provides a paid service to make phone calls"));
173 addTagDescription(m_description,
174 QStringLiteral("service:phone"),
175 QStringLiteral("no"),
176 tr("No phone service", "A copy shop does not provide a paid service to make phone calls"));
177 addTagDescription(m_description,
178 QStringLiteral("service:print"),
179 QStringLiteral("yes"),
180 tr("Digital printing", "A copy shop provides services to print paper documents from digital files"));
181 addTagDescription(m_description,
182 QStringLiteral("service:print"),
183 QStringLiteral("no"),
184 tr("No digital printing", "A copy shop does not provide services to print paper documents from digital files"));
185 addTagDescription(m_description,
186 QStringLiteral("service:press"),
187 QStringLiteral("yes"),
188 tr("Press printing service", "A copy shop provides a professional service to print a large number of copies of a document"));
189 addTagDescription(
190 m_description,
191 QStringLiteral("service:press"),
192 QStringLiteral("no"),
193 tr("No press printing service", "A copy shop does not provide a professional service to print a large number of copies of a document"));
194 addTagDescription(m_description,
195 QStringLiteral("service:prepress"),
196 QStringLiteral("yes"),
197 tr("Press printing assistance", "A copy shop provides help with preparing special printing techniques"));
198 addTagDescription(m_description,
199 QStringLiteral("service:prepress"),
200 QStringLiteral("no"),
201 tr("No press printing assistance", "A copy shop does not provide help with preparing special printing techniques"));
202 addTagDescription(m_description,
203 QStringLiteral("service:self"),
204 QStringLiteral("yes"),
205 tr("Self service", "A copy shop provides individual copy machines for self-service"));
206 addTagDescription(m_description,
207 QStringLiteral("service:self"),
208 QStringLiteral("no"),
209 tr(" No self service", "A copy shop does not provide individual machines for self-service"));
210 } else if (category == GeoDataPlacemark::ShopDeli) {
211 addTagDescription(m_description, QStringLiteral("organic"), QStringLiteral("yes"), tr("Sells organic food", "A deli that sells organic food"));
212 addTagDescription(m_description,
213 QStringLiteral("organic"),
214 QStringLiteral("no"),
215 tr("Does not sell organic food", "A deli that does not sell organic food"));
216 addTagDescription(m_description,
217 QStringLiteral("organic"),
218 QStringLiteral("only"),
219 tr("Only sells organic food", "A deli that only sells organic food"));
220
221 addTagDescription(m_description,
222 QStringLiteral("diet:gluten_free"),
223 QStringLiteral("yes"),
224 tr("Sells gluten free food", "A deli that sells gluten free food"));
225 addTagDescription(m_description,
226 QStringLiteral("diet:gluten_free"),
227 QStringLiteral("no"),
228 tr("Does not sell gluten free food", "A deli that does not sell gluten free food"));
229 addTagDescription(m_description,
230 QStringLiteral("diet:gluten_free"),
231 QStringLiteral("only"),
232 tr("Only sells gluten free food", "A deli that only sells gluten free food"));
233
234 addTagDescription(m_description,
235 QStringLiteral("diet:lactose_free"),
236 QStringLiteral("yes"),
237 tr("Sells lactose free food", "A deli that sells lactose free food"));
238 addTagDescription(m_description,
239 QStringLiteral("diet:lactose_free"),
240 QStringLiteral("no"),
241 tr("Does not sell lactose free food", "A deli that does not sell lactose free food"));
242 addTagDescription(m_description,
243 QStringLiteral("diet:lactose_free"),
244 QStringLiteral("only"),
245 tr("Only sells lactose free food", "A deli that only sells lactose free food"));
246 } else if (category == GeoDataPlacemark::ShopTobacco) {
247 addTagDescription(m_description,
248 QStringLiteral("lottery"),
249 QStringLiteral("yes"),
250 tr("Sells lottery tickets", "A tobacco shop that also sells lottery tickets"));
251 addTagDescription(m_description,
252 QStringLiteral("stamps"),
253 QStringLiteral("yes"),
254 tr("Sells revenue stamps", "A tobacco shop that also sells revenue stamps"));
255 addTagDescription(m_description, QStringLiteral("salt"), QStringLiteral("yes"), tr("Sells salt", "A tobacco shop that also sells salt"));
256 }
257 } else if (category == GeoDataPlacemark::TransportBusStop) {
258 addTagValue(m_description, QStringLiteral("network"));
259 addTagValue(m_description, QStringLiteral("operator"));
260 addTagValue(m_description, QStringLiteral("ref"));
261 } else if (category == GeoDataPlacemark::TransportCarShare) {
262 addTagValue(m_description, QStringLiteral("network"));
263 addTagValue(m_description, QStringLiteral("operator"));
264 } else if (category == GeoDataPlacemark::TransportRentalBicycle || category == GeoDataPlacemark::TransportRentalCar
265 || category == GeoDataPlacemark::TransportRentalSki) {
266 addFirstTagValueOf(m_description, QStringList() << QStringLiteral("brand") << QStringLiteral("operator"));
267
268 } else if (category == GeoDataPlacemark::TransportFuel) {
269 addFirstTagValueOf(m_description, QStringList() << QStringLiteral("brand") << QStringLiteral("operator"));
270 addTagDescription(m_description, QStringLiteral("fuel:diesel"), QStringLiteral("yes"), tr("Diesel"));
271 addTagDescription(m_description, QStringLiteral("fuel:biodiesel"), QStringLiteral("yes"), tr("Biodiesel"));
272 addTagDescription(m_description, QStringLiteral("fuel:octane_91"), QStringLiteral("yes"), tr("Octane 91"));
273 addTagDescription(m_description, QStringLiteral("fuel:octane_95"), QStringLiteral("yes"), tr("Octane 95"));
274 addTagDescription(m_description, QStringLiteral("fuel:octane_98"), QStringLiteral("yes"), tr("Octane 98"));
275 addTagDescription(m_description, QStringLiteral("fuel:octane_100"), QStringLiteral("yes"), tr("Octane 100"));
276 addTagDescription(m_description, QStringLiteral("fuel:e10"), QStringLiteral("yes"), tr("E10"));
277 addTagDescription(m_description, QStringLiteral("fuel:lpg"), QStringLiteral("yes"), tr("LPG"));
278 } else if (category == GeoDataPlacemark::NaturalTree) {
279 addTagValue(m_description, QStringLiteral("species:en"));
280 addTagValue(m_description, QStringLiteral("genus:en"));
281 addTagValue(m_description, QStringLiteral("leaf_type"));
282 } else if (category == GeoDataPlacemark::NaturalCave) {
283 addTagValue(m_description, QStringLiteral("cave:ref"));
284 } else if (category == GeoDataPlacemark::AmenityRecycling) {
285 addTagDescription(m_description, QStringLiteral("recycling:batteries"), QStringLiteral("yes"), tr("Batteries"));
286 addTagDescription(m_description, QStringLiteral("recycling:clothes"), QStringLiteral("yes"), tr("Clothes"));
287 addTagDescription(m_description, QStringLiteral("recycling:glass"), QStringLiteral("yes"), tr("Glass"));
288 addTagDescription(m_description, QStringLiteral("recycling:glass_bottles"), QStringLiteral("yes"), tr("Glass bottles"));
289 addTagDescription(m_description, QStringLiteral("recycling:green_waste"), QStringLiteral("yes"), tr("Green waste"));
290 addTagDescription(m_description, QStringLiteral("recycling:garden_waste"), QStringLiteral("yes"), tr("Garden waste"));
291 addTagDescription(m_description, QStringLiteral("recycling:electrical_items"), QStringLiteral("yes"), tr("Electrical items"));
292 addTagDescription(m_description, QStringLiteral("recycling:metal"), QStringLiteral("yes"), tr("Metal"));
293 addTagDescription(m_description, QStringLiteral("recycling:mobile_phones"), QStringLiteral("yes"), tr("Mobile phones"));
294 addTagDescription(m_description, QStringLiteral("recycling:newspaper"), QStringLiteral("yes"), tr("Newspaper"));
295 addTagDescription(m_description, QStringLiteral("recycling:paint"), QStringLiteral("yes"), tr("Paint"));
296 addTagDescription(m_description, QStringLiteral("recycling:paper"), QStringLiteral("yes"), tr("Paper"));
297 addTagDescription(m_description, QStringLiteral("recycling:paper_packaging"), QStringLiteral("yes"), tr("Paper packaging"));
298 addTagDescription(m_description, QStringLiteral("recycling:PET"), QStringLiteral("yes"), tr("PET"));
299 addTagDescription(m_description, QStringLiteral("recycling:plastic"), QStringLiteral("yes"), tr("Plastic"));
300 addTagDescription(m_description, QStringLiteral("recycling:plastic_bags"), QStringLiteral("yes"), tr("Plastic bags"));
301 addTagDescription(m_description, QStringLiteral("recycling:plastic_bottles"), QStringLiteral("yes"), tr("Plastic bottles"));
302 addTagDescription(m_description, QStringLiteral("recycling:plastic_packaging"), QStringLiteral("yes"), tr("Plastic packaging"));
303 addTagDescription(m_description, QStringLiteral("recycling:polyester"), QStringLiteral("yes"), tr("Polyester"));
304 addTagDescription(m_description, QStringLiteral("recycling:tyres"), QStringLiteral("yes"), tr("Tyres"));
305 addTagDescription(m_description, QStringLiteral("recycling:waste"), QStringLiteral("yes"), tr("Waste"));
306 addTagDescription(m_description, QStringLiteral("recycling:white_goods"), QStringLiteral("yes"), tr("White goods"));
307 addTagDescription(m_description, QStringLiteral("recycling:wood"), QStringLiteral("yes"), tr("Wood"));
308 } else if (category == GeoDataPlacemark::NaturalVolcano) {
309 addTagDescription(m_description, QStringLiteral("volcano:status"), QStringLiteral("active"), tr("Active", "An active volcano"));
310 addTagDescription(m_description,
311 QStringLiteral("volcano:status"),
312 QStringLiteral("dormant"),
313 tr("Dormant", "A dormant volcano that will erupt at some point in the future."));
314 addTagDescription(m_description,
315 QStringLiteral("volcano:status"),
316 QStringLiteral("extinct"),
317 tr("Extinct", "A volcano considered extinct, it has not erupted within the last 10000 years and likely never will again."));
318 addTagDescription(m_description, QStringLiteral("volcano:type"), QStringLiteral("stratovolcano"), tr("Stratovolcano"));
319 addTagDescription(m_description, QStringLiteral("volcano:type"), QStringLiteral("shield"), tr("Shield volcano"));
320 addTagDescription(m_description, QStringLiteral("volcano:type"), QStringLiteral("scoria"), tr("Scoria cone", "A scoria cone volcano."));
321 } else if (category == GeoDataPlacemark::HealthDoctors) {
322 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("alternative"), tr("Alternative medicine"));
323 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("audiologist"), tr("Audiologist"));
324 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("blood_bank"), tr("Blood bank"));
325 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("blood_donation"), tr("Blood donation"));
326 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("centre"), tr("Medical center"));
327 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("clinic"), tr("Clinic"));
328 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("dentist"), tr("Dentist"));
329 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("doctor"), tr("Medical practitioner"));
330 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("hospital"), tr("Hospital"));
331 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("midwife"), tr("Midwife"));
332 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("optometrist"), tr("Optometrist"));
333 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("physiotherapist"), tr("Physiotherapist"));
334 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("podiatrist"), tr("Podiatrist"));
335 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("psychotherapist"), tr("Psychotherapist"));
336 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("rehabilitation"), tr("Rehabilitation"));
337 addTagDescription(m_description, QStringLiteral("healthcare"), QStringLiteral("speech_therapist"), tr("Speech therapist"));
338 addTagValue(m_description, QStringLiteral("healthcare:speciality"));
339 } else if (category == GeoDataPlacemark::AmenityBench) {
340 int const seats = m_placemark.osmData().tagValue(QStringLiteral("seats")).toInt();
341 if (seats > 0) {
342 //~ singular %n seat
343 //~ plural %n seats
344 addTagValue(m_description, QStringLiteral("seats"), tr("%n seats", "number of seats a bench provides", seats));
345 }
346 addTagValue(m_description, QStringLiteral("material"));
347 addTagDescription(m_description,
348 QStringLiteral("backrest"),
349 QStringLiteral("yes"),
350 tr("Has backrest", "A bench provides a backrest to lean against"));
351 addTagDescription(m_description,
352 QStringLiteral("backrest"),
353 QStringLiteral("no"),
354 tr("No backrest", "A bench provides no backrest to lean against"));
355 } else if (category == GeoDataPlacemark::AmenityWasteBasket) {
356 addTagValue(m_description, QStringLiteral("waste"));
357 } else if (category == GeoDataPlacemark::TransportSpeedCamera) {
358 addTagValue(m_description, QStringLiteral("maxspeed"), tr("%1 km/h"));
359 addTagValue(m_description, QStringLiteral("ref"));
360 } else if (category == GeoDataPlacemark::TransportParking) {
361 addTagDescription(m_description,
362 QStringLiteral("supervised"),
363 QStringLiteral("yes"),
364 tr("Is supervised", "Parking spaces are supervised by guards"));
365 addTagDescription(m_description,
366 QStringLiteral("supervised"),
367 QStringLiteral("no"),
368 tr("Not supervised", "Parking spaces are not supervised by guards"));
369
370 int const disabledSpaces = m_placemark.osmData().tagValue(QStringLiteral("capacity:disabled")).toInt();
371 if (disabledSpaces > 0) {
372 addTagValue(m_description, QStringLiteral("capacity:disabled"), tr("%1 disabled spaces", "Parking spaces"));
373 }
374 int const womenSpaces = m_placemark.osmData().tagValue(QStringLiteral("capacity:women")).toInt();
375 if (womenSpaces > 0) {
376 addTagValue(m_description, QStringLiteral("capacity:women"), tr("%1 women spaces", "Parking spaces"));
377 }
378 int const parentSpaces = m_placemark.osmData().tagValue(QStringLiteral("capacity:parent")).toInt();
379 if (parentSpaces > 0) {
380 addTagValue(m_description, QStringLiteral("capacity:parent"), tr("%1 parent and child spaces", "Parking spaces"));
381 }
382 int const electricChargers = m_placemark.osmData().tagValue(QStringLiteral("capacity:charging")).toInt();
383 if (electricChargers > 0) {
384 addTagValue(m_description, QStringLiteral("capacity:charging"), tr("%1 spaces with electric chargers", "Parking spaces"));
385 }
386 } else if (category == GeoDataPlacemark::TransportBicycleParking) {
387 addTagDescription(m_description,
388 QStringLiteral("surveillance"),
389 QStringLiteral("outdoor"),
390 tr("Has outdoor surveillance", "A parking space has outdoor surveillance"));
391 addTagDescription(m_description,
392 QStringLiteral("surveillance"),
393 QStringLiteral("indoor"),
394 tr("Has indoor surveillance", "A parking space has indoor surveillance"));
395 addTagDescription(m_description,
396 QStringLiteral("surveillance"),
397 QStringLiteral("public"),
398 tr("Has public surveillance", "A parking space has public surveillance"));
399 } else if (category == GeoDataPlacemark::TourismWildernessHut) {
400 addTagDescription(m_description, QStringLiteral("shower"), QStringLiteral("yes"), tr("Has shower", "A hut provides showers inside or aside"));
401 addTagDescription(m_description,
402 QStringLiteral("shower"),
403 QStringLiteral("no"),
404 tr("Has no shower", "A hut does not provide showers inside or aside"));
405 addTagDescription(m_description, QStringLiteral("mattress"), QStringLiteral("yes"), tr("Has mattress", "A hut provides mattress"));
406 addTagDescription(m_description, QStringLiteral("mattress"), QStringLiteral("no"), tr("Has no mattress", "A hut does not provide mattress"));
407 addTagDescription(m_description, QStringLiteral("drinking_water"), QStringLiteral("yes"), tr("Has water", "Water is available inside or aside"));
408 addTagDescription(m_description,
409 QStringLiteral("drinking_water"),
410 QStringLiteral("no"),
411 tr("Has no water", "Water is not available inside nor aside"));
412 addTagDescription(m_description, QStringLiteral("toilets"), QStringLiteral("yes"), tr("Has toilets", "A hut provides toilets"));
413 addTagDescription(m_description, QStringLiteral("toilets"), QStringLiteral("no"), tr("Has no toilets", "A hut does not provide toilets"));
414 addTagDescription(m_description, QStringLiteral("reservation"), QStringLiteral("yes"), tr("Reservation is possible"));
415 addTagDescription(m_description, QStringLiteral("reservation"), QStringLiteral("no"), tr("No reservation possible"));
416 addTagDescription(m_description, QStringLiteral("reservation"), QStringLiteral("required"), tr("Reservation is required"));
417 addTagDescription(m_description,
418 QStringLiteral("reservation"),
419 QStringLiteral("recommended"),
420 tr("Reservation is recommended", "You should make reservation"));
421 addTagDescription(m_description,
422 QStringLiteral("reservation"),
423 QStringLiteral("members_only"),
424 tr("Only for members", "Reservation is only possible for members of the organisation running the hut"));
425 } else if (category == GeoDataPlacemark::TourismArtwork) {
426 addTagValue(m_description, QStringLiteral("artist_name"), tr("By %1"));
427 } else if (category == GeoDataPlacemark::AmenityChargingStation) {
428 addTagValue(m_description, QStringLiteral("capacity"), tr("%1 vehicles"));
429 addTagValue(m_description, QStringLiteral("amperage"), tr("%1 ampere"));
430 addTagValue(m_description, QStringLiteral("voltage"), tr("%1 volt"));
431
432 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("cee_blue"), tr("%1 blue CEE sockets"));
433 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("cee_red_16a"), tr("%1 red CEE sockets (16 A)"));
434 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("cee_red_32a"), tr("%1 red CEE sockets (32 A)"));
435 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("cee_red_64a"), tr("%1 red CEE sockets (64 A)"));
436 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("cee_red_125a"), tr("%1 red CEE sockets (125 A)"));
437 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("nema_5_15"), tr("%1 NEMA-5-15P plugs"));
438 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("typeb"), tr("%1 NEMA-5-15P plugs"));
439 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("nema_5_20"), tr("%1 NEMA-5-20P plugs"));
440 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("nema_14_30"), tr("%1 NEMA 14-30 sockets"));
441 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("nema_14_50"), tr("%1 NEMA 14-50 sockets"));
442 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("schuko"), tr("%1 Schuko sockets"));
443 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("bs1363"), tr("%1 BS 1363 sockets"));
444 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("type1"), tr("%1 Type 1 plugs"));
445 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("type1_combo"), tr("%1 Type 1 combo plugs"));
446 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("type2"), tr("%1 Type 2 sockets"));
447 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("type2_combo"), tr("%1 Type 2 combo sockets"));
448 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("type3"), tr("%1 Type 3 sockets"));
449 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("chademo"), tr("%1 CHAdeMO plugs"));
450 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("magne_charge"), tr("%1 Magne Charge plugs"));
451 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("tesla_standard"), tr("%1 Tesla standard plugs"));
452 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("tesla_supercharger"), tr("%1 Tesla standard plugs (Supercharger)"));
453 addTagDescription(m_description, QStringLiteral("socket"), QStringLiteral("tesla_roadster"), tr("%1 Tesla roadster plugs"));
454 } else if (category == GeoDataPlacemark::AmenityCarWash) {
455 addTagValue(m_description, QStringLiteral("maxwidth"), tr("Maximum vehicle width: %1"));
456 addTagValue(m_description, QStringLiteral("maxheight"), tr("Maximum vehicle height: %1"));
457
458 addTagDescription(m_description, QStringLiteral("self_service"), QStringLiteral("yes"), tr("Self-service"));
459 addTagDescription(m_description, QStringLiteral("self_service"), QStringLiteral("no"), tr("No self-service"));
460 addTagDescription(m_description, QStringLiteral("automated"), QStringLiteral("yes"), tr("Automated"));
461 addTagDescription(m_description, QStringLiteral("automated"), QStringLiteral("no"), tr("Manual"));
462 } else if (category == GeoDataPlacemark::AmenitySocialFacility) {
463 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("group_home"), tr("Group home"));
464 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("nursing_home"), tr("Nursing home"));
465 addTagDescription(m_description,
466 QStringLiteral("social_facility"),
467 QStringLiteral("assisted_living"),
468 tr("Assisted living", "Like group home but for more independent people, e.g. who have flats"));
469 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("day_care"), tr("Nursing services on a daily basis"));
470 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("shelter"), tr("Shelter"));
471 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("ambulatory_care"), tr("Ambulatory care"));
472 addTagDescription(m_description, QStringLiteral("social_facility"), QStringLiteral("outreach"), tr("Social welfare services"));
473 addTagDescription(m_description,
474 QStringLiteral("social_facility"),
475 QStringLiteral("workshop"),
476 tr("Employment and workshops for offenders and people with disabilities"));
477 addTagDescription(m_description,
478 QStringLiteral("social_facility"),
479 QStringLiteral("food_bank"),
480 tr("Pre-packaged food for free or below market price"));
481 addTagDescription(m_description,
482 QStringLiteral("social_facility"),
483 QStringLiteral("soup_kitchen"),
484 tr("Prepared meals for free or below market price"));
485 addTagDescription(m_description,
486 QStringLiteral("social_facility"),
487 QStringLiteral("dairy_kitchen"),
488 tr("Free dairy food (subject to local regulations)"));
489
490 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("abused"), tr("For abused"));
491 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("child"), tr("For children"));
492 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("disabled"), tr("For people with physical disabilities"));
493 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("diseased"), tr("For those who suffer of a disease"));
494 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("drug_addicted"), tr("For drug-addicted"));
495 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("homeless"), tr("For homeless"));
496 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("juvenile"), tr("For juvenile"));
497 addTagDescription(m_description,
498 QStringLiteral("social_facility:for"),
499 QStringLiteral("mental_health"),
500 tr("For those with mental/psychological problems"));
501 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("migrant"), tr("For migrants"));
502 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("orphan"), tr("For orphans"));
503 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("senior"), tr("For elder people"));
504 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("underprivileged"), tr("For poor or disadvantaged people"));
505 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("unemployed"), tr("For unemployed"));
506 addTagDescription(m_description, QStringLiteral("social_facility:for"), QStringLiteral("victim"), tr("For victims of crimes"));
507 } else if (category == GeoDataPlacemark::HistoricMemorial) {
508 addTagValue(m_description, QStringLiteral("inscription"), tr("Inscription: %1"));
509 } else if (category >= GeoDataPlacemark::AerialwayCableCar && category <= GeoDataPlacemark::AerialwayGoods) {
510 addTagValue(m_description, QStringLiteral("occupancy"), tr("%1 places per carriage"));
511 addTagValue(m_description, QStringLiteral("capacity"), tr("%1 people per hour"));
512 addTagValue(m_description, QStringLiteral("duration"), tr("%1 minutes"));
513
514 addTagDescription(m_description,
515 QStringLiteral("bubble"),
516 QStringLiteral("yes"),
517 tr("Has weather protection", "A carriage is protected from the weather"));
518 addTagDescription(m_description,
519 QStringLiteral("bubble"),
520 QStringLiteral("no"),
521 tr("No weather protection", "A carriage is not protected from the weather"));
522 addTagDescription(m_description, QStringLiteral("heating"), QStringLiteral("yes"), tr("Is heated", "A carriage is heated"));
523 addTagDescription(m_description, QStringLiteral("heating"), QStringLiteral("no"), tr("Not heated", "A carriage is not heated"));
524 addTagDescription(m_description,
525 QStringLiteral("bicycle"),
526 QStringLiteral("yes"),
527 tr("Bicycle transportation possible", "Bicycles can be transported"));
528 addTagDescription(m_description,
529 QStringLiteral("bicycle"),
530 QStringLiteral("summer"),
531 tr("Bicycle transportation only in summer", "Bicycles can only be transported in summer"));
532 addTagDescription(m_description,
533 QStringLiteral("bicycle"),
534 QStringLiteral("no"),
535 tr("Bicycle transportation impossible", "Bicyles cannot be transported"));
536 } else if (category >= GeoDataPlacemark::PisteDownhill && category <= GeoDataPlacemark::PisteSkiJump) {
537 addTagDescription(m_description, QStringLiteral("lit"), QStringLiteral("yes"), tr("Lit at night"));
538 addTagDescription(m_description, QStringLiteral("piste:lit"), QStringLiteral("yes"), tr("Lit in winter"));
539 addTagDescription(m_description, QStringLiteral("gladed"), QStringLiteral("yes"), tr("Contains trees", "A ski piste with trees (gladed)"));
540 addTagDescription(m_description, QStringLiteral("patrolled"), QStringLiteral("no"), tr("Not patrolled"));
541
542 addTagDescription(m_description,
543 QStringLiteral("piste:grooming"),
544 QStringLiteral("classic"),
545 tr("Groomed for classic style nordic or downhill skiing"));
546 addTagDescription(m_description, QStringLiteral("piste:grooming"), QStringLiteral("mogul"), tr("Mogul piste"));
547 addTagDescription(m_description, QStringLiteral("piste:grooming"), QStringLiteral("skating"), tr("Groomed for free style or skating"));
548 addTagDescription(m_description,
549 QStringLiteral("piste:grooming"),
550 QStringLiteral("classic;skating"),
551 tr("Groomed for classic and free style skiing"));
552 addTagDescription(m_description,
553 QStringLiteral("piste:grooming"),
554 QStringLiteral("classic+skating"),
555 tr("Groomed for classic and free style skiing"));
556 addTagDescription(m_description, QStringLiteral("piste:grooming"), QStringLiteral("scooter"), tr("Groomed by a smaller snowmobile"));
557 addTagDescription(m_description, QStringLiteral("piste:grooming"), QStringLiteral("backcountry"), tr("Unmarked piste (backcountry touring)"));
558 }
559
560 if (category == GeoDataPlacemark::TransportBicycleParking || category == GeoDataPlacemark::TransportMotorcycleParking) {
561 addTagDescription(m_description, QStringLiteral("covered"), QStringLiteral("yes"), tr("Is covered", "A parking space is covered"));
562 addTagDescription(m_description, QStringLiteral("covered"), QStringLiteral("no"), tr("Not covered", "A parking space is not covered"));
563 }
564
565 if (category == GeoDataPlacemark::AmenityRecycling || category == GeoDataPlacemark::AmenityPostBox) {
566 addTagValue(m_description, QStringLiteral("collection_times"), tr("Collection times %1"), QStringLiteral(", "));
567 }
568
569 if (category == GeoDataPlacemark::AerialwayStation) {
570 addTagDescription(m_description, QStringLiteral("aerialway:access"), QStringLiteral("entry"), tr("Entry", "Entry station of an aerialway"));
571 addTagDescription(m_description, QStringLiteral("aerialway:access"), QStringLiteral("exit"), tr("Exit", "Exit station of an aerialway"));
572 addTagDescription(m_description,
573 QStringLiteral("aerialway:access"),
574 QStringLiteral("both"),
575 tr("Entry and exit", "Entry and exit station of an aerialway"));
576 addTagDescription(m_description,
577 QStringLiteral("aerialway:access"),
578 QStringLiteral("no"),
579 tr("No entry or exit", "Transit only station of an aerialway"));
580 addTagDescription(m_description,
581 QStringLiteral("aerialway:summer:access"),
582 QStringLiteral("entry"),
583 tr("Entry during summer", "Entry station of an aerialway during summer"));
584 addTagDescription(m_description,
585 QStringLiteral("aerialway:summer:access"),
586 QStringLiteral("exit"),
587 tr("Exit during summer", "Exit station of an aerialway during summer"));
588 addTagDescription(m_description,
589 QStringLiteral("aerialway:summer:access"),
590 QStringLiteral("both"),
591 tr("Entry and exit during summer", "Entry and exit station of an aerialway during summer"));
592 addTagDescription(m_description,
593 QStringLiteral("aerialway:summer:access"),
594 QStringLiteral("no"),
595 tr("No entry or exit during summer", "Transit only station of an aerialway during summer"));
596 }
597
598 if (category != GeoDataPlacemark::AerialwayStation) {
599 addTagValue(m_description, QStringLiteral("ele"), tr("Elevation: %1 m"));
600 }
601
602 addTagDescription(m_description, QStringLiteral("access"), QStringLiteral("customers"), tr("Customers only"));
603 addTagDescription(m_description,
604 QStringLiteral("access"),
605 QStringLiteral("yes"),
606 tr("Accessible by anyone", "The public has an official, legally-enshrined right of access; i.e., it's a right of way"));
607 addTagDescription(m_description,
608 QStringLiteral("access"),
609 QStringLiteral("private"),
610 tr("Private", "Only with permission of the owner on an individual basis."));
611 addTagDescription(m_description,
612 QStringLiteral("access"),
613 QStringLiteral("permissive"),
614 tr("Open to general traffic", "Open to general traffic but permission can be revoked by the owner"));
615 addTagDescription(m_description, QStringLiteral("access"), QStringLiteral("no"), tr("No access", "No access for the general public"));
616
617 addTagDescription(m_description, QStringLiteral("fee"), QStringLiteral("no"), tr("no fee"));
618 addTagValue(m_description, QStringLiteral("description"));
619 addTagValue(m_description, QStringLiteral("old_name"), tr("formerly <i>%1</i>"));
620
621 const int level = m_placemark.osmData().tagValue(QStringLiteral("level")).toInt();
622 if (level > 2) {
623 addTagValue(m_description, QStringLiteral("level"), tr("Floor %1", "Positive floor level"));
624 } else if (level < -2) {
625 addTagValue(m_description, QStringLiteral("level"), tr("Basement %1", "Negative floor level"));
626 } else {
627 addTagDescription(m_description, QStringLiteral("level"), QStringLiteral("2"), tr("Floor 2", "Floor level 2, two levels above ground level"));
628 addTagDescription(m_description, QStringLiteral("level"), QStringLiteral("1"), tr("Floor 1", "Floor level 1, one level above ground level"));
629 addTagDescription(m_description, QStringLiteral("level"), QStringLiteral("0"), tr("Ground floor", "Floor level 0"));
630 addTagDescription(m_description, QStringLiteral("level"), QStringLiteral("-1"), tr("Basement 1", "Floor level -1, one level below ground level"));
631 addTagDescription(m_description, QStringLiteral("level"), QStringLiteral("-2"), tr("Basement 2", "Floor level -2, two levels below ground level"));
632 }
633 }
634
635 return m_description;
636}
637
638QString Placemark::address() const
639{
640 if (m_address.isEmpty()) {
641 m_address = addressFromOsmData();
642 }
643 return m_address;
644}
645
646QString Placemark::website() const
647{
648 if (!m_website.isEmpty()) {
649 return m_website;
650 }
651 auto const tags = QStringList() << QStringLiteral("website") << QStringLiteral("contact:website") << QStringLiteral("facebook")
652 << QStringLiteral("contact:facebook") << QStringLiteral("url");
653 for (const QString &tag : tags) {
654 QString const value = m_placemark.osmData().tagValue(tag);
655 if (!value.isEmpty()) {
656 QUrl url = QUrl(value);
657 if (url.isValid()) {
658 if (url.scheme().isEmpty()) {
659 m_website = QStringLiteral("http://%1").arg(value);
660 } else {
661 m_website = value;
662 }
663 if (!m_website.isEmpty()) {
664 return m_website;
665 }
666 }
667 }
668 }
669
670 return m_website;
671}
672
673QString Placemark::wikipedia() const
674{
675 if (!m_wikipedia.isEmpty()) {
676 return m_wikipedia;
677 }
678
679 // TODO: also support "wikipedia:lang=page title" tags
680 const QString wikipedia = m_placemark.osmData().tagValue(QStringLiteral("wikipedia"));
681 if (!wikipedia.isEmpty()) {
682 // full URL?
683 if (wikipedia.startsWith(QLatin1StringView("http://")) || wikipedia.startsWith(QLatin1StringView("https://"))) {
684 m_wikipedia = wikipedia;
685 } else {
686 // match "(lang:)human readable title"
687 QRegularExpression re(QStringLiteral("^(?:([a-z]{2,}):)?(.*)$"));
688 QRegularExpressionMatch match = re.match(wikipedia);
689 QString lang = match.captured(1);
690 if (lang.isEmpty()) {
691 lang = QStringLiteral("en");
692 }
693 const QString title = QString::fromLatin1(QUrl::toPercentEncoding(match.captured(2)));
694
695 m_wikipedia = QLatin1StringView("https://") + lang + QLatin1StringView(".wikipedia.org/wiki/") + title;
696 }
697 }
698
699 return m_wikipedia;
700}
701
702QString Placemark::openingHours() const
703{
704 if (!m_openingHours.isEmpty()) {
705 return m_openingHours;
706 }
707
708 addTagValue(m_openingHours, QStringLiteral("opening_hours"));
709 return m_openingHours;
710}
711
712QString Placemark::coordinates() const
713{
715}
716
717QString Placemark::wheelchairInfo() const
718{
719 if (!m_wheelchairInfo.isEmpty())
720 return m_wheelchairInfo;
721
722 addTagDescription(m_wheelchairInfo, QStringLiteral("wheelchair"), QStringLiteral("yes"), tr("Wheelchair accessible"));
723 addTagDescription(m_wheelchairInfo, QStringLiteral("wheelchair"), QStringLiteral("no"), tr("Wheelchair inaccessible"));
724 addTagDescription(m_wheelchairInfo, QStringLiteral("wheelchair"), QStringLiteral("limited"), tr("Limited wheelchair accessibility"));
725 addTagDescription(m_wheelchairInfo, QStringLiteral("wheelchair"), QStringLiteral("designated"), tr("Designated wheelchair access"));
726
727 // Check if there is localized description
728 auto const &osmData = m_placemark.osmData();
729 QStringList const uiLanguages = QLocale::system().uiLanguages();
730 const QString tag = QLatin1StringView("wheelchair:description:");
731 for (const QString &uiLanguage : uiLanguages) {
732 for (auto tagIter = osmData.tagsBegin(), end = osmData.tagsEnd(); tagIter != end; ++tagIter) {
733 if (tagIter.key().startsWith(tag)) {
734 QString const tagLanguage = tagIter.key().mid(tag.length());
735 if (tagLanguage == uiLanguage) {
736 append(m_wheelchairInfo, tagIter.value());
737 return m_wheelchairInfo;
738 }
739 }
740 }
741 }
742
743 addTagValue(m_wheelchairInfo, QStringLiteral("wheelchair:description"));
744
745 return m_wheelchairInfo;
746}
747
748QString Placemark::wifiAvailable() const
749{
750 if (!m_wifiAvailable.isEmpty()) {
751 return m_wifiAvailable;
752 }
753
754 const auto &osmData = m_placemark.osmData();
755 addTagDescription(m_wifiAvailable,
756 QStringLiteral("internet_access"),
757 QStringLiteral("no"),
758 tr("No public Internet access", "This location does not provide public Internet access"));
759 addTagDescription(m_wifiAvailable,
760 QStringLiteral("internet_access"),
761 QStringLiteral("yes"),
762 tr("Public Internet access available", "This location provides an unknown type of public Internet access."));
763
764 if (osmData.containsTag(QStringLiteral("internet_access:fee"), QStringLiteral("yes"))) {
765 addTagDescription(m_wifiAvailable,
766 QStringLiteral("internet_access"),
767 QStringLiteral("wlan"),
768 tr("Charged public wifi available", "Public wireless Internet access is available here for a fee."));
769 } else if (osmData.containsTag(QStringLiteral("internet_access:fee"), QStringLiteral("no"))) {
770 addTagDescription(m_wifiAvailable,
771 QStringLiteral("internet_access"),
772 QStringLiteral("wlan"),
773 tr("Free public wifi available", "Public wireless Internet access is available here for no cost."));
774 } else {
775 addTagDescription(m_wifiAvailable,
776 QStringLiteral("internet_access"),
777 QStringLiteral("wlan"),
778 tr("Public wifi available", "Public wireless Internet access is available here."));
779 }
780
781 if (m_wifiAvailable.isEmpty()) {
782 addTagDescription(m_wifiAvailable, QStringLiteral("wifi"), QStringLiteral("no"), tr("No public wifi", "Public wifi is not available here."));
783 addTagDescription(m_wifiAvailable,
784 QStringLiteral("wifi"),
785 QStringLiteral("yes"),
786 tr("Public wifi available", "Public wireless Internet is available here."));
787 addTagDescription(m_wifiAvailable,
788 QStringLiteral("wifi"),
789 QStringLiteral("free"),
790 tr("Free public wifi available", "Public wireless Internet is available here for no cost."));
791 }
792
793 return m_wifiAvailable;
794}
795
796QString Placemark::phone() const
797{
798 if (!m_phone.isEmpty()) {
799 return m_phone;
800 }
801
802 addTagValue(m_phone, QStringLiteral("phone"));
803 return m_phone;
804}
805
806void Placemark::setName(const QString &name)
807{
808 if (m_placemark.displayName() == name) {
809 return;
810 }
811
812 m_placemark.setName(name);
813 Q_EMIT nameChanged();
814}
815
816RouteRelationModel *Placemark::routeRelationModel()
817{
818 return &m_relationModel;
819}
820
821double Placemark::longitude() const
822{
823 return m_placemark.coordinate().longitude(GeoDataCoordinates::Degree);
824}
825
826double Placemark::latitude() const
827{
828 return m_placemark.coordinate().latitude(GeoDataCoordinates::Degree);
829}
830
831const QStringList &Placemark::tags() const
832{
833 return m_tags;
834}
835
836bool Placemark::addTagValue(QString &target, const QString &key, const QString &format, const QString &separator) const
837{
838 auto const &osmData = m_placemark.osmData();
839 QString const value = osmData.tagValue(key);
840 if (!value.isEmpty()) {
841 QString description = format.isEmpty() ? value : format.arg(value);
842 description.replace(QLatin1Char(';'), separator);
843 append(target, description);
844 return true;
845 }
846 return false;
847}
848
849void Placemark::addFirstTagValueOf(QString &target, const QStringList &keys) const
850{
851 for (auto const &key : keys) {
852 if (addTagValue(target, key)) {
853 return;
854 }
855 }
856}
857
858void Placemark::addTagDescription(QString &target, const QString &key, const QString &value, const QString &description) const
859{
860 auto const &osmData = m_placemark.osmData();
861 if (osmData.containsTag(key, value)) {
862 append(target, description);
863 }
864}
865
866void Placemark::append(QString &target, const QString &value)
867{
868 if (!target.isEmpty()) {
869 target += QStringLiteral(" · "); // non-latin1
870 }
871 target += value;
872}
873
874QString Placemark::addressFromOsmData() const
875{
876#ifdef HAVE_QT6_POSITIONING
877 QGeoAddress address;
878 OsmPlacemarkData const data = m_placemark.osmData();
879 address.setCountry(data.tagValue(QStringLiteral("addr:country")));
880 address.setState(data.tagValue(QStringLiteral("addr:state")));
881 address.setCity(data.tagValue(QStringLiteral("addr:city")));
882 address.setDistrict(data.tagValue(QStringLiteral("district")));
883 address.setPostalCode(data.tagValue(QStringLiteral("addr:postcode")));
884 QString const street = data.tagValue(QStringLiteral("addr:street"));
885 QString const houseNumber = data.tagValue(QStringLiteral("addr:housenumber"));
886 address.setStreet(formatStreet(street, houseNumber));
887 return address.text().replace(QStringLiteral("<br/>"), QStringLiteral(", "));
888#else
889 return QString();
890#endif
891}
892
893QString Placemark::formatStreet(const QString &street, const QString &houseNumber)
894{
895 return houseNumber.isEmpty()
896 ? street
897 : tr("%1 %2", "House number (first argument) and street name (second argument) in an address").arg(houseNumber).arg(street).trimmed();
898}
899
900void Placemark::updateTags()
901{
902 m_tags.clear();
903 QString const tag = QStringLiteral("%1 = %2");
904 for (auto iter = m_placemark.osmData().tagsBegin(), end = m_placemark.osmData().tagsEnd(); iter != end; ++iter) {
905 m_tags << tag.arg(iter.key()).arg(iter.value());
906 }
907}
908
909void Placemark::updateRelations(const Marble::GeoDataPlacemark &placemark)
910{
911 if (const auto document = (placemark.parent() ? geodata_cast<GeoDataDocument>(placemark.parent()) : nullptr)) {
913 QSet<const GeoDataRelation *> relevantRelations;
914 QSet<qint64> placemarkIds;
915 auto const &osmData = placemark.osmData();
916 placemarkIds << osmData.oid();
917 bool searchRelations = true;
918 for (auto feature : document->featureList()) {
919 if (const auto relation = geodata_cast<GeoDataRelation>(feature)) {
920 allRelations << relation;
921 if (relation->memberIds().contains(osmData.oid())) {
922 relevantRelations << relation;
923 auto const isRoute = relation->osmData().tagValue(QStringLiteral("type")) == QStringLiteral("route");
924 searchRelations &= !isRoute;
925 }
926 }
927 }
928 if (searchRelations) {
929 for (auto feature : document->featureList()) {
930 if (const auto relation = geodata_cast<GeoDataRelation>(feature)) {
931 if (relevantRelations.contains(relation) && relation->osmData().containsTag(QStringLiteral("type"), QStringLiteral("public_transport"))
932 && relation->osmData().containsTag(QStringLiteral("public_transport"), QStringLiteral("stop_area"))) {
933 for (auto iter = relation->osmData().relationReferencesBegin(), end = relation->osmData().relationReferencesEnd(); iter != end;
934 ++iter) {
935 if (iter.value() == QStringLiteral("stop") || iter.value() == QStringLiteral("platform")) {
936 placemarkIds << iter.key().id;
937 }
938 }
939 }
940 }
941 }
942 }
943 for (auto relation : std::as_const(allRelations)) {
944 if (relation->containsAnyOf(placemarkIds)) {
945 relevantRelations << relation;
946 }
947 }
948 m_relationModel.setRelations(relevantRelations);
949 }
950}
951
952}
953
954#include "moc_Placemark.cpp"
@ Decimal
"Decimal" notation (base-10)
QString toString() const
return a string representation of the coordinate this is a convenience function which uses the defaul...
void setName(const QString &value)
Set a new name for this feature.
const GeoDataObject * parent() const
Provides the parent of the object in GeoDataContainers.
a class representing a point of interest on the map
GeoDataVisualCategory visualCategory() const
Return the symbol index of the placemark.
OsmPlacemarkData & osmData()
Quick, safe accessor to the placemark's OsmPlacemarkData stored within it's ExtendedData.
GeoDataCoordinates coordinate(const QDateTime &dateTime=QDateTime(), bool *iconAtCoordinates=nullptr) const
Return the coordinates of the placemark at time dateTime as a GeoDataCoordinates.
QString displayName() const
displays the name of a place in the locale language of the user
QHash< QString, QString >::const_iterator tagsBegin() const
iterators for the tags hash.
QString tagValue(const QString &key) const
tagValue returns the value of the tag that has key as key or an empty qstring if there is no such tag
Placemark(QObject *parent=nullptr)
Constructor.
Definition Placemark.cpp:20
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
PostalAddress address(const QVariant &location)
QStringView level(QStringView ifopt)
Category category(StandardShortcut id)
Binds a QML item to a specific geodetic location in screen coordinates.
T * geodata_cast(GeoDataObject *node)
Returns the given node cast to type T if the node was instantiated as type T; otherwise returns 0.
void clear()
QLocale system()
QStringList uiLanguages() const const
Q_EMITQ_EMIT
QString tr(const char *sourceText, const char *disambiguation, int n)
bool contains(const QSet< T > &other) const const
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString repeated(qsizetype times) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
int toInt(bool *ok, int base) const const
QString trimmed() const const
QStringView mid(qsizetype start, qsizetype length) const const
int toInt(bool *ok, int base) const const
bool isValid() const const
QString scheme() const const
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:04:13 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.