Marble

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

KDE's Doxygen guidelines are available online.