File indexing completed on 2025-01-05 03:58:59

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2004-2007 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 // SPDX-FileCopyrightText: 2008-2009 Patrick Spendrin <ps_ml@gmx.de>
0006 //
0007 
0008 
0009 // Own
0010 #include "GeoDataPlacemark.h"
0011 
0012 // Private
0013 #include "GeoDataPlacemark_p.h"
0014 
0015 // Qt
0016 #include <QDataStream>
0017 #include <QString>
0018 #include <QXmlStreamWriter>
0019 
0020 #include <klocalizedstring.h>
0021 
0022 #include "GeoDataMultiGeometry.h"
0023 #include "GeoDataLatLonAltBox.h"
0024 #include "GeoDataData.h"
0025 #include "OsmPlacemarkData.h"
0026 #include "GeoDataTrack.h"
0027 #include "GeoDataModel.h"
0028 
0029 #include "digikam_debug.h"
0030 
0031 namespace Marble
0032 {
0033 
0034 const OsmPlacemarkData GeoDataPlacemarkPrivate::s_nullOsmPlacemarkData = OsmPlacemarkData();
0035 const GeoDataPlacemarkExtendedData GeoDataPlacemarkPrivate::s_nullPlacemarkExtendedData = GeoDataPlacemarkExtendedData();
0036 
0037 GeoDataPlacemark::GeoDataPlacemark()
0038     : GeoDataFeature( new GeoDataPlacemarkPrivate )
0039 {
0040     Q_D(GeoDataPlacemark);
0041     d->m_geometry->setParent(this);
0042 }
0043 
0044 
0045 GeoDataPlacemark::GeoDataPlacemark( const GeoDataPlacemark& other )
0046     : GeoDataFeature(other, new GeoDataPlacemarkPrivate(*other.d_func()))
0047 {
0048     Q_D(GeoDataPlacemark);
0049     if (d->m_geometry) {
0050         d->m_geometry->setParent(this);
0051     }
0052 }
0053 
0054 GeoDataPlacemark::GeoDataPlacemark( const QString& name )
0055     : GeoDataFeature( new GeoDataPlacemarkPrivate )
0056 {
0057     Q_D(GeoDataPlacemark);
0058     d->m_name = name;
0059     d->m_geometry->setParent(this);
0060 }
0061 
0062 GeoDataPlacemark::~GeoDataPlacemark()
0063 {
0064     // nothing to do
0065 }
0066 
0067 GeoDataPlacemark &GeoDataPlacemark::operator=( const GeoDataPlacemark &other )
0068 {
0069     if (this != &other) {
0070         Q_D(GeoDataPlacemark);
0071         *d = *other.d_func();
0072         if (d->m_geometry) {
0073             d->m_geometry->setParent(this);
0074         }
0075     }
0076 
0077     return *this;
0078 }
0079 
0080 bool GeoDataPlacemark::operator==( const GeoDataPlacemark& other ) const
0081 {
0082     Q_D(const GeoDataPlacemark);
0083     const GeoDataPlacemarkPrivate* const other_d = other.d_func();
0084     if (!equals(other) ||
0085         d->m_population != other_d->m_population) {
0086         return false;
0087     }
0088 
0089     if ((d->m_placemarkExtendedData && !other_d->m_placemarkExtendedData) &&
0090         (*d->m_placemarkExtendedData != GeoDataPlacemarkExtendedData())) {
0091         return false;
0092     }
0093 
0094     if ((!d->m_placemarkExtendedData && other_d->m_placemarkExtendedData) &&
0095         (GeoDataPlacemarkExtendedData() != *other_d->m_placemarkExtendedData)) {
0096         return false;
0097     }
0098 
0099     if (d->m_placemarkExtendedData && other_d->m_placemarkExtendedData &&
0100             !(*d->m_placemarkExtendedData == *other_d->m_placemarkExtendedData)) {
0101         return false;
0102     }
0103 
0104     if (!d->m_geometry && !other_d->m_geometry) {
0105         return true;
0106     }
0107     if ((!d->m_geometry && other_d->m_geometry) ||
0108         (d->m_geometry && !other_d->m_geometry)) {
0109         return false;
0110     }
0111 
0112     if (*d->m_geometry != *other_d->m_geometry) {
0113         return false;
0114     }
0115 
0116     return true;
0117 }
0118 
0119 bool GeoDataPlacemark::operator!=( const GeoDataPlacemark& other ) const
0120 {
0121     return !this->operator==( other );
0122 }
0123 
0124 const char* GeoDataPlacemark::nodeType() const
0125 {
0126     return GeoDataTypes::GeoDataPlacemarkType;
0127 }
0128 
0129 
0130 GeoDataFeature * GeoDataPlacemark::clone() const
0131 {
0132     return new GeoDataPlacemark(*this);
0133 }
0134 
0135 
0136 GeoDataPlacemark::GeoDataVisualCategory GeoDataPlacemark::visualCategory() const
0137 {
0138     Q_D(const GeoDataPlacemark);
0139     return d->m_visualCategory;
0140 }
0141 
0142 void GeoDataPlacemark::setVisualCategory(GeoDataPlacemark::GeoDataVisualCategory index)
0143 {
0144     Q_D(GeoDataPlacemark);
0145     d->m_visualCategory = index;
0146 }
0147 
0148 GeoDataGeometry* GeoDataPlacemark::geometry()
0149 {
0150     Q_D(GeoDataPlacemark);
0151     return d->m_geometry;
0152 }
0153 
0154 const GeoDataGeometry* GeoDataPlacemark::geometry() const
0155 {
0156     Q_D(const GeoDataPlacemark);
0157     return d->m_geometry;
0158 }
0159 
0160 const OsmPlacemarkData& GeoDataPlacemark::osmData() const
0161 {
0162     Q_D(const GeoDataPlacemark);
0163     return d->osmPlacemarkData();
0164 }
0165 
0166 void GeoDataPlacemark::setOsmData( const OsmPlacemarkData &osmData )
0167 {
0168     Q_D(GeoDataPlacemark);
0169     d->osmPlacemarkData() = osmData;
0170 }
0171 
0172 OsmPlacemarkData& GeoDataPlacemark::osmData()
0173 {
0174     Q_D(GeoDataPlacemark);
0175     return d->osmPlacemarkData();
0176 }
0177 
0178 bool GeoDataPlacemark::hasOsmData() const
0179 {
0180     Q_D(const GeoDataPlacemark);
0181     return d->m_osmPlacemarkData != nullptr;
0182 }
0183 
0184 void GeoDataPlacemark::clearOsmData()
0185 {
0186     Q_D(GeoDataPlacemark);
0187     delete d->m_osmPlacemarkData;
0188     d->m_osmPlacemarkData = nullptr;
0189 }
0190 
0191 const GeoDataLookAt *GeoDataPlacemark::lookAt() const
0192 {
0193     return dynamic_cast<const GeoDataLookAt*>( abstractView() );
0194 }
0195 
0196 GeoDataLookAt *GeoDataPlacemark::lookAt()
0197 {
0198     return dynamic_cast<GeoDataLookAt*>( abstractView() );
0199 }
0200 
0201 bool GeoDataPlacemark::placemarkLayoutOrderCompare(const GeoDataPlacemark *left, const GeoDataPlacemark *right)
0202 {
0203     const GeoDataPlacemarkPrivate * const left_d = left->d_func();
0204     const GeoDataPlacemarkPrivate * const right_d = right->d_func();
0205 
0206     if (left_d->m_zoomLevel != right_d->m_zoomLevel) {
0207         return (left_d->m_zoomLevel < right_d->m_zoomLevel); // lower zoom level comes first
0208     }
0209 
0210     if (left_d->m_popularity != right_d->m_popularity) {
0211         return (left_d->m_popularity > right_d->m_popularity); // higher popularity comes first
0212     }
0213 
0214     return left < right; // lower pointer value comes first
0215 }
0216 
0217 GeoDataCoordinates GeoDataPlacemark::coordinate( const QDateTime &dateTime, bool *iconAtCoordinates ) const
0218 {
0219     Q_D(const GeoDataPlacemark);
0220     bool hasIcon = false;
0221     GeoDataCoordinates coord;
0222 
0223     if (d->m_geometry) {
0224         // Beware: comparison between pointers, not strings.
0225         if (geodata_cast<GeoDataPoint>(d->m_geometry)
0226                 || geodata_cast<GeoDataPolygon>(d->m_geometry)
0227                 || geodata_cast<GeoDataLinearRing>(d->m_geometry)) {
0228             hasIcon = true;
0229             coord = d->m_geometry->latLonAltBox().center();
0230         } else if (const auto multiGeometry = geodata_cast<GeoDataMultiGeometry>(d->m_geometry)) {
0231             QVector<GeoDataGeometry*>::ConstIterator it = multiGeometry->constBegin();
0232             QVector<GeoDataGeometry*>::ConstIterator end = multiGeometry->constEnd();
0233             for ( ; it != end; ++it ) {
0234                 if (geodata_cast<GeoDataPoint>(*it)
0235                         || geodata_cast<GeoDataPolygon>(*it)
0236                         || geodata_cast<GeoDataLinearRing>(*it)) {
0237                     hasIcon = true;
0238                     break;
0239                 }
0240             }
0241 
0242             coord = d->m_geometry->latLonAltBox().center();
0243         } else if (const auto track = geodata_cast<GeoDataTrack>(d->m_geometry)) {
0244             hasIcon = track->size() != 0 && track->firstWhen() <= dateTime;
0245             coord = track->coordinatesAt( dateTime );
0246         } else if (const auto lineString = geodata_cast<GeoDataLineString>(d->m_geometry)) {
0247             auto const size = lineString->size();
0248             if (size == 0) {
0249                 return GeoDataCoordinates();
0250             } else if (size < 3) {
0251                 // Approximate center if there are just two coordinates
0252                 return lineString->latLonAltBox().center();
0253             } else {
0254                 return lineString->at(size / 2);
0255             }
0256         } else {
0257             coord = d->m_geometry->latLonAltBox().center();
0258         }
0259     }
0260 
0261     if ( iconAtCoordinates != nullptr ) {
0262         *iconAtCoordinates = hasIcon;
0263     }
0264     return coord;
0265 }
0266 
0267 void GeoDataPlacemark::coordinate( qreal& lon, qreal& lat, qreal& alt ) const
0268 {
0269     coordinate().geoCoordinates( lon, lat, alt );
0270 }
0271 
0272 void GeoDataPlacemark::setCoordinate( qreal lon, qreal lat, qreal alt, GeoDataPoint::Unit _unit)
0273 {
0274     setGeometry( new GeoDataPoint(lon, lat, alt, _unit ) );
0275 }
0276 
0277 void GeoDataPlacemark::setCoordinate( const GeoDataCoordinates &point )
0278 {
0279     setGeometry ( new GeoDataPoint( point ) );
0280 }
0281 
0282 void GeoDataPlacemark::setGeometry( GeoDataGeometry *entry )
0283 {
0284     Q_D(GeoDataPlacemark);
0285     delete d->m_geometry;
0286     d->m_geometry = entry;
0287     d->m_geometry->setParent(this);
0288 }
0289 
0290 
0291 QString GeoDataPlacemark::displayName() const
0292 {
0293     if (hasOsmData()) {
0294         OsmPlacemarkData const &data = osmData();
0295         QStringList const uiLanguages = QLocale::system().uiLanguages();
0296         for (const QString &uiLanguage: uiLanguages) {
0297             for (auto tagIter = data.tagsBegin(), end = data.tagsEnd(); tagIter != end; ++tagIter) {
0298                 if (tagIter.key().startsWith(QLatin1String("name:"))) {
0299                     QString const tagLanguage = tagIter.key().mid(5);
0300                     if (tagLanguage == uiLanguage) {
0301                         return tagIter.value();
0302                     }
0303                 }
0304             }
0305         }
0306     }
0307 
0308     return name();
0309 }
0310 
0311 QString GeoDataPlacemark::categoryName() const
0312 {
0313     Q_D(const GeoDataPlacemark);
0314     switch (d->m_visualCategory) {
0315     case Valley: return i18n("Valley");
0316     case OtherTerrain: return i18n("Terrain");
0317     case Crater: return i18n("Crater");
0318     case Mare: return i18n("Sea");
0319     case MannedLandingSite: return i18n("Manned Landing Site");
0320     case RoboticRover: return i18n("Robotic Rover");
0321     case UnmannedSoftLandingSite: return i18n("Unmanned Soft Landing Site");
0322     case UnmannedHardLandingSite: return i18n("Unmanned Hard Landing Site");
0323     case Mons: return i18n("Mountain");
0324     case SmallCity: return i18n("City");
0325     case SmallCountyCapital: return i18n("County Capital");
0326     case SmallStateCapital: return i18n("State Capital");
0327     case SmallNationCapital: return i18n("Nation Capital");
0328     case MediumCity: return i18n("City");
0329     case MediumCountyCapital: return i18n("County Capital");
0330     case MediumStateCapital: return i18n("State Capital");
0331     case MediumNationCapital: return i18n("Nation Capital");
0332     case BigCity: return i18n("City");
0333     case BigCountyCapital: return i18n("County Capital");
0334     case BigStateCapital: return i18n("State Capital");
0335     case BigNationCapital: return i18n("Nation Capital");
0336     case LargeCity: return i18n("City");
0337     case LargeCountyCapital: return i18n("County Capital");
0338     case LargeStateCapital: return i18n("State Capital");
0339     case LargeNationCapital: return i18n("Nation Capital");
0340     case Nation: return i18n("Nation");
0341     case Mountain: return i18n("Mountain");
0342     case Volcano: return i18n("Volcano");
0343     case Continent: return i18n("Continent");
0344     case Ocean: return i18n("Ocean");
0345     case GeographicPole: return i18n("Geographic Pole");
0346     case MagneticPole: return i18n("Magnetic Pole");
0347     case ShipWreck: return i18n("Ship Wreck");
0348     case AirPort: return i18n("Air Port");
0349     case Observatory: return i18n("Observatory");
0350     case MilitaryDangerArea: return i18n("Military Danger Area");
0351     case OsmSite: return i18n("OSM Site");
0352     case Coordinate: return i18n("Coordinate");
0353     case Satellite: return i18n("Satellite");
0354 
0355     // OpenStreetMap categories
0356     case PlaceCity: return i18n("City");
0357     case PlaceCityCapital: return i18n("City Capital");
0358     case PlaceCityNationalCapital: return i18n("National Capital");
0359     case PlaceSuburb: return i18n("Suburb");
0360     case PlaceHamlet: return i18n("Hamlet");
0361     case PlaceLocality: return i18n("Locality");
0362     case PlaceTown: return i18n("Town");
0363     case PlaceTownCapital: return i18n("Town Capital");
0364     case PlaceTownNationalCapital: return i18n("National Capital");
0365     case PlaceVillage: return i18n("Village");
0366     case PlaceVillageCapital: return i18n("Village Capital");
0367     case PlaceVillageNationalCapital: return i18n("National Capital");
0368     case NaturalWater: return i18n("Water");
0369     case NaturalReef: return i18n("Reef");
0370     case NaturalWood: return i18n("Wood");
0371     case NaturalBeach: return i18n("Beach");
0372     case NaturalWetland: return i18n("Wetland");
0373     case NaturalGlacier: return i18n("Glacier");
0374     case NaturalIceShelf: return i18n("Ice Shelf");
0375     case NaturalScrub: return i18n("Scrub");
0376     case NaturalCliff: return i18n("Cliff");
0377     case NaturalHeath: return i18n("Heath");
0378     case HighwayTrafficSignals: return i18n("Traffic Signals");
0379     case HighwayElevator: return i18n("Elevator");
0380     case HighwaySteps: return i18n("Steps");
0381     case HighwayUnknown: return i18n("Unknown Road");
0382     case HighwayPath: return i18n("Path");
0383     case HighwayFootway: return i18n("Footway");
0384     case HighwayTrack: return i18n("Track");
0385     case HighwayPedestrian: return i18n("Footway");
0386     case HighwayCycleway: return i18n("Cycleway");
0387     case HighwayService: return i18n("Service Road");
0388     case HighwayRoad: return i18n("Road");
0389     case HighwayResidential: return i18n("Residential Road");
0390     case HighwayLivingStreet: return i18n("Living Street");
0391     case HighwayUnclassified: return i18n("Unclassified Road");
0392     case HighwayTertiaryLink: return i18n("Tertiary Link Road");
0393     case HighwayTertiary: return i18n("Tertiary Road");
0394     case HighwaySecondaryLink: return i18n("Secondary Link Road");
0395     case HighwaySecondary: return i18n("Secondary Road");
0396     case HighwayPrimaryLink: return i18n("Primary Link Road");
0397     case HighwayPrimary: return i18n("Primary Road");
0398     case HighwayRaceway: return i18n("Raceway");
0399     case HighwayTrunkLink: return i18n("Trunk Link Road");
0400     case HighwayTrunk: return i18n("Trunk Road");
0401     case HighwayMotorwayLink: return i18n("Motorway Link Road");
0402     case HighwayMotorway: return i18n("Motorway");
0403     case HighwayCorridor: return i18n("Corridor");
0404     case Building: return i18n("Building");
0405     case AccomodationCamping: return i18n("Camping");
0406     case AccomodationHostel: return i18n("Hostel");
0407     case AccomodationHotel: return i18n("Hotel");
0408     case AccomodationMotel: return i18n("Motel");
0409     case AccomodationYouthHostel: return i18n("Youth Hostel");
0410     case AccomodationGuestHouse: return i18n("Guest House");
0411     case AmenityLibrary: return i18n("Library");
0412     case AmenityKindergarten: return i18n("Kindergarten");
0413     case EducationCollege: return i18n("College");
0414     case EducationSchool: return i18n("School");
0415     case EducationUniversity: return i18n("University");
0416     case FoodBar: return i18n("Bar");
0417     case FoodBiergarten: return i18n("Biergarten");
0418     case FoodCafe: return i18n("Cafe");
0419     case FoodFastFood: return i18n("Fast Food");
0420     case FoodPub: return i18n("Pub");
0421     case FoodRestaurant: return i18n("Restaurant");
0422     case HealthDentist: return i18n("Dentist");
0423     case HealthDoctors: return i18n("Doctors");
0424     case HealthHospital: return i18n("Hospital");
0425     case HealthPharmacy: return i18n("Pharmacy");
0426     case HealthVeterinary: return i18n("Veterinary");
0427     case MoneyAtm: return i18n("ATM");
0428     case MoneyBank: return i18n("Bank");
0429     case HistoricArchaeologicalSite: return i18n("Archaeological Site");
0430     case AmenityEmbassy: return i18n("Embassy");
0431     case AmenityEmergencyPhone: return i18n("Emergency Phone");
0432     case AmenityMountainRescue: return i18n("Mountain Rescue");
0433     case LeisureWaterPark: return i18n("Water Park");
0434     case AmenityCommunityCentre: return i18n("Community Centre");
0435     case AmenityFountain: return i18n("Fountain");
0436     case AmenityNightClub: return i18n("Night Club");
0437     case AmenityBench: return i18n("Bench");
0438     case AmenityCourtHouse: return i18n("Court House");
0439     case AmenityFireStation: return i18n("Fire Station");
0440     case AmenityHuntingStand: return i18n("Hunting Stand");
0441     case AmenityPolice: return i18n("Police");
0442     case AmenityPostBox: return i18n("Post Box");
0443     case AmenityPostOffice: return i18n("Post Office");
0444     case AmenityPrison: return i18n("Prison");
0445     case AmenityRecycling: return i18n("Recycling");
0446     case AmenityShelter: return i18n("Shelter");
0447     case AmenityTelephone: return i18n("Telephone");
0448     case AmenityToilets: return i18n("Toilets");
0449     case AmenityTownHall: return i18n("Town Hall");
0450     case AmenityWasteBasket: return i18n("Waste Basket");
0451     case AmenityDrinkingWater: return i18n("Drinking Water");
0452     case AmenityGraveyard: return i18n("Graveyard");
0453     case AmenityChargingStation: return i18n("Charging Station");
0454     case AmenityCarWash: return i18n("Car Wash");
0455     case AmenitySocialFacility: return i18n("Social Facility");
0456     case BarrierCityWall: return i18n("City Wall");
0457     case BarrierGate: return i18n("Gate");
0458     case BarrierLiftGate: return i18n("Lift Gate");
0459     case BarrierWall: return i18n("Wall");
0460     case NaturalVolcano: return i18n("Volcano");
0461     case NaturalPeak: return i18n("Peak");
0462     case NaturalTree: return i18n("Tree");
0463     case NaturalCave: return i18n("Cave Entrance");
0464     case ShopBeverages: return i18n("Beverages");
0465     case ShopHifi: return i18n("Hifi");
0466     case ShopSupermarket: return i18n("Supermarket");
0467     case ShopAlcohol: return i18n("Liquor Store");
0468     case ShopBakery: return i18n("Bakery");
0469     case ShopButcher: return i18n("Butcher");
0470     case ShopConfectionery: return i18n("Confectionery");
0471     case ShopConvenience: return i18n("Convenience Shop");
0472     case ShopGreengrocer: return i18n("Greengrocer");
0473     case ShopSeafood: return i18n("Seafood Shop");
0474     case ShopDepartmentStore: return i18n("Department Store");
0475     case ShopKiosk: return i18n("Kiosk");
0476     case ShopBag: return i18n("Bag Shop");
0477     case ShopClothes: return i18n("Clothes Shop");
0478     case ShopFashion: return i18n("Fashion Shop");
0479     case ShopJewelry: return i18n("Jewelry Shop");
0480     case ShopShoes: return i18n("Shoe Shop");
0481     case ShopVarietyStore: return i18n("Variety Store");
0482     case ShopBeauty: return i18n("Beauty Services");
0483     case ShopChemist: return i18n("Chemist");
0484     case ShopCosmetics: return i18n("Cosmetics");
0485     case ShopHairdresser: return i18n("Hairdresser");
0486     case ShopOptician: return i18n("Optician");
0487     case ShopPerfumery: return i18n("Perfumery");
0488     case ShopDoitYourself: return i18n("Hardware Store");
0489     case ShopFlorist: return i18n("Florist");
0490     case ShopHardware: return i18n("Hardware Store");
0491     case ShopFurniture: return i18n("Furniture Store");
0492     case ShopElectronics: return i18n("Electronics Shop");
0493     case ShopMobilePhone: return i18n("Mobile Phone Shop");
0494     case ShopBicycle: return i18n("Bicycle Shop");
0495     case ShopCar: return i18n("Car Dealer");
0496     case ShopCarRepair: return i18n("Car Repair Shop");
0497     case ShopCarParts: return i18n("Car Parts");
0498     case ShopMotorcycle: return i18n("Motorcycle Shop");
0499     case ShopOutdoor: return i18n("Outdoor Shop");
0500     case ShopSports: return i18n("Sports Shop");
0501     case ShopCopy: return i18n("Printing Services");
0502     case ShopArt: return i18n("Art Shop");
0503     case ShopMusicalInstrument: return i18n("Musical Instrument Shop");
0504     case ShopPhoto: return i18n("Photo Shop");
0505     case ShopBook: return i18n("Bookshop");
0506     case ShopGift: return i18n("Gift Shop");
0507     case ShopStationery: return i18n("Stationery");
0508     case ShopLaundry: return i18n("Laundry");
0509     case ShopPet: return i18n("Pet Shop");
0510     case ShopToys: return i18n("Toy Store");
0511     case ShopTravelAgency: return i18n("Travel Agency");
0512     case ShopDeli: return i18n("Deli");
0513     case ShopTobacco: return i18n("Tobacco Shop");
0514     case ShopTea: return i18n("Tea Shop");
0515     case ShopComputer: return i18n("Computer Shop");
0516     case ShopGardenCentre: return i18n("Garden Centre");
0517     case Shop: return i18n("Shop");
0518     case ManmadeBridge: return i18n("Bridge");
0519     case ManmadeLighthouse: return i18n("Lighthouse");
0520     case ManmadePier: return i18n("Pier");
0521     case ManmadeWaterTower: return i18n("Water Tower");
0522     case ManmadeWindMill: return i18n("Wind Mill");
0523     case ManmadeCommunicationsTower: return i18n("Communications Tower");
0524     case TourismAttraction: return i18n("Tourist Attraction");
0525     case TourismArtwork: return i18n("Artwork");
0526     case HistoricCastle: return i18n("Castle");
0527     case AmenityCinema: return i18n("Cinema");
0528     case TourismInformation: return i18n("Information");
0529     case HistoricMonument: return i18n("Monument");
0530     case TourismMuseum: return i18n("Museum");
0531     case HistoricRuins: return i18n("Ruin");
0532     case AmenityTheatre: return i18n("Theatre");
0533     case TourismThemePark: return i18n("Theme Park");
0534     case TourismViewPoint: return i18n("View Point");
0535     case TourismZoo: return i18n("Zoo");
0536     case TourismAlpineHut: return i18n("Alpine Hut");
0537     case TourismWildernessHut: return i18n("Wilderness Hut");
0538     case HistoricMemorial: return i18n("Memorial");
0539     case TransportAerodrome: return i18n("Aerodrome");
0540     case TransportHelipad: return i18n("Helipad");
0541     case TransportAirportGate: return i18n("Airport Gate");
0542     case TransportAirportRunway: return i18n("Airport Runway");
0543     case TransportAirportApron: return i18n("Airport Apron");
0544     case TransportAirportTaxiway: return i18n("Airport Taxiway");
0545     case TransportAirportTerminal: return i18n("Airport Terminal");
0546     case TransportBusStation: return i18n("Bus Station");
0547     case TransportBusStop: return i18n("Bus Stop");
0548     case TransportCarShare: return i18n("Car Sharing");
0549     case TransportFuel: return i18n("Gas Station");
0550     case TransportParking: return i18n("Parking");
0551     case TransportParkingSpace: return i18n("Parking Space");
0552     case TransportPlatform: return i18n("Platform");
0553     case TransportRentalBicycle: return i18n("Bicycle Rental");
0554     case TransportRentalCar: return i18n("Car Rental");
0555     case TransportRentalSki: return i18n("Ski Rental");
0556     case TransportTaxiRank: return i18n("Taxi Rank");
0557     case TransportTrainStation: return i18n("Train Station");
0558     case TransportTramStop: return i18n("Tram Stop");
0559     case TransportBicycleParking: return i18n("Bicycle Parking");
0560     case TransportMotorcycleParking: return i18n("Motorcycle Parking");
0561     case TransportSubwayEntrance: return i18n("Subway Entrance");
0562     case TransportSpeedCamera: return i18n("Speed Camera");
0563     case ReligionPlaceOfWorship: return i18n("Place Of Worship");
0564     case ReligionBahai: return i18n("Bahai");
0565     case ReligionBuddhist: return i18n("Buddhist");
0566     case ReligionChristian: return i18n("Christian");
0567     case ReligionMuslim: return i18n("Muslim");
0568     case ReligionHindu: return i18n("Hindu");
0569     case ReligionJain: return i18n("Jain");
0570     case ReligionJewish: return i18n("Jewish");
0571     case ReligionShinto: return i18n("Shinto");
0572     case ReligionSikh: return i18n("Sikh");
0573     case ReligionTaoist: return i18n("Taoist");
0574     case LeisureGolfCourse: return i18n("Golf Course");
0575     case LeisureMarina: return i18n("Marina");
0576     case LeisurePark: return i18n("Park");
0577     case LeisurePlayground: return i18n("Playground");
0578     case LeisurePitch: return i18n("Pitch");
0579     case LeisureSportsCentre: return i18n("Sports Centre");
0580     case LeisureStadium: return i18n("Stadium");
0581     case LeisureTrack: return i18n("Track");
0582     case LeisureSwimmingPool: return i18n("Swimming Pool");
0583     case LeisureMinigolfCourse: return i18n("Miniature Golf Course");
0584     case LanduseAllotments: return i18n("Allotments");
0585     case LanduseBasin: return i18n("Basin");
0586     case LanduseCemetery: return i18n("Cemetery");
0587     case LanduseCommercial: return i18n("Commercial");
0588     case LanduseConstruction: return i18n("Construction");
0589     case LanduseFarmland: return i18n("Farmland");
0590     case LanduseFarmyard: return i18n("Farmyard");
0591     case LanduseGarages: return i18n("Garages");
0592     case LanduseGrass: return i18n("Grass");
0593     case LanduseIndustrial: return i18n("Industrial");
0594     case LanduseLandfill: return i18n("Landfill");
0595     case LanduseMeadow: return i18n("Meadow");
0596     case LanduseMilitary: return i18n("Military");
0597     case LanduseQuarry: return i18n("Quarry");
0598     case LanduseRailway: return i18n("Railway");
0599     case LanduseReservoir: return i18n("Reservoir");
0600     case LanduseResidential: return i18n("Residential");
0601     case LanduseRetail: return i18n("Retail");
0602     case LanduseOrchard: return i18n("Orchard");
0603     case LanduseVineyard: return i18n("Vineyard");
0604     case RailwayRail: return i18n("Rail");
0605     case RailwayNarrowGauge: return i18n("Narrow Gauge");
0606     case RailwayTram: return i18n("Tram");
0607     case RailwayLightRail: return i18n("Light Rail");
0608     case RailwayAbandoned: return i18n("Abandoned Railway");
0609     case RailwaySubway: return i18n("Subway");
0610     case RailwayPreserved: return i18n("Preserved Railway");
0611     case RailwayMiniature: return i18n("Miniature Railway");
0612     case RailwayConstruction: return i18n("Railway Construction");
0613     case RailwayMonorail: return i18n("Monorail");
0614     case RailwayFunicular: return i18n("Funicular Railway");
0615     case PowerTower: return i18n("Power Tower");
0616     case AerialwayStation:  return i18n("Aerialway Station");
0617     case AerialwayPylon: return i18nc("A pylon supporting the aerialway cable e.g. on a ski lift", "Pylon");
0618     case AerialwayCableCar: return i18n("Cable Car");
0619     case AerialwayGondola: return i18n("Gondola");
0620     case AerialwayChairLift: return i18n("Chair Lift");
0621     case AerialwayMixedLift: return i18n("Mixed Lift");
0622     case AerialwayDragLift: return i18n("Drag Lift");
0623     case AerialwayTBar: return i18n("T-Bar");
0624     case AerialwayJBar: return i18n("J-Bar");
0625     case AerialwayPlatter: return i18n("Platter");
0626     case AerialwayRopeTow: return i18n("Rope Tow");
0627     case AerialwayMagicCarpet: return i18n("Magic Carpet");
0628     case AerialwayZipLine: return i18n("Zip Line");
0629     case AerialwayGoods: return i18n("Goods");
0630     case PisteDownhill: return i18n("Downhill Piste");
0631     case PisteNordic: return i18n("Nordic Piste");
0632     case PisteSkitour: return i18n("Skitour");
0633     case PisteSled: return i18n("Sled Piste");
0634     case PisteHike: return i18n("Winter Hike");
0635     case PisteSleigh: return i18n("Sleigh Piste");
0636     case PisteIceSkate: return i18n("Ice Skate");
0637     case PisteSnowPark: return i18n("Snow Park");
0638     case PistePlayground: return i18n("Ski Playground");
0639     case PisteSkiJump: return i18n("Ski Jump");
0640     case AdminLevel1: return i18n("Admin Boundary (Level 1)");
0641     case AdminLevel2: return i18n("Admin Boundary (Level 2)");
0642     case AdminLevel3: return i18n("Admin Boundary (Level 3)");
0643     case AdminLevel4: return i18n("Admin Boundary (Level 4)");
0644     case AdminLevel5: return i18n("Admin Boundary (Level 5)");
0645     case AdminLevel6: return i18n("Admin Boundary (Level 6)");
0646     case AdminLevel7: return i18n("Admin Boundary (Level 7)");
0647     case AdminLevel8: return i18n("Admin Boundary (Level 8)");
0648     case AdminLevel9: return i18n("Admin Boundary (Level 9)");
0649     case AdminLevel10: return i18n("Admin Boundary (Level 10)");
0650     case AdminLevel11: return i18n("Admin Boundary (Level 11)");
0651     case BoundaryMaritime: return i18n("Boundary (Maritime)");
0652     case Landmass: return i18n("Land Mass");
0653     case UrbanArea: return i18n("Urban Area");
0654     case InternationalDateLine: return i18n("International Date Line");
0655     case Bathymetry: return i18n("Bathymetry");
0656     case WaterwayCanal: return i18n("Canal");
0657     case WaterwayDrain: return i18n("Drain");
0658     case WaterwayDitch: return i18n("Ditch");
0659     case WaterwayStream: return i18n("Stream");
0660     case WaterwayRiver: return i18n("River");
0661     case WaterwayWeir: return i18n("Weir");
0662     case CrossingSignals: return i18n("Crosswalk");
0663     case CrossingIsland: return i18n("Crosswalk");
0664     case CrossingZebra: return i18n("Crosswalk");
0665     case CrossingRailway: return i18n("Railway Crossing");
0666     case IndoorDoor: return i18n("Door");
0667     case IndoorWall: return i18n("Wall");
0668     case IndoorRoom: return i18n("Room");
0669 
0670     case Default:
0671     case Unknown:
0672     case None:
0673     case LastIndex: return QString();
0674     }
0675 
0676     return QString();
0677 }
0678 
0679 qreal GeoDataPlacemark::area() const
0680 {
0681     Q_D(const GeoDataPlacemark);
0682     return d->m_placemarkExtendedData ? d->m_placemarkExtendedData->m_area : -1.0;
0683 }
0684 
0685 void GeoDataPlacemark::setArea( qreal area )
0686 {
0687     if (area == -1.0 && !d_func()->m_placemarkExtendedData) {
0688         return; // nothing to do
0689     }
0690 
0691     Q_D(GeoDataPlacemark);
0692     d->placemarkExtendedData().m_area = area;
0693 }
0694 
0695 qint64 GeoDataPlacemark::population() const
0696 {
0697     Q_D(const GeoDataPlacemark);
0698     return d->m_population;
0699 }
0700 
0701 void GeoDataPlacemark::setPopulation( qint64 population )
0702 {
0703     Q_D(GeoDataPlacemark);
0704     d->m_population = population;
0705 }
0706 
0707 const QString GeoDataPlacemark::state() const
0708 {
0709     Q_D(const GeoDataPlacemark);
0710     return d->m_placemarkExtendedData ? d->m_placemarkExtendedData->m_state : QString();
0711 }
0712 
0713 void GeoDataPlacemark::setState( const QString &state )
0714 {
0715     if (state.isEmpty() && !d_func()->m_placemarkExtendedData) {
0716         return; // nothing to do
0717     }
0718 
0719     Q_D(GeoDataPlacemark);
0720     d->placemarkExtendedData().m_state = state;
0721 }
0722 
0723 const QString GeoDataPlacemark::countryCode() const
0724 {
0725     Q_D(const GeoDataPlacemark);
0726     return d->m_placemarkExtendedData ? d->m_placemarkExtendedData->m_countrycode : QString();
0727 }
0728 
0729 void GeoDataPlacemark::setCountryCode( const QString &countrycode )
0730 {
0731     if (countrycode.isEmpty() && !d_func()->m_placemarkExtendedData) {
0732         return; // nothing to do
0733     }
0734 
0735     Q_D(GeoDataPlacemark);
0736     d->placemarkExtendedData().m_countrycode = countrycode;
0737 }
0738 
0739 bool GeoDataPlacemark::isBalloonVisible() const
0740 {
0741     Q_D(const GeoDataPlacemark);
0742     return d->m_placemarkExtendedData ? d->m_placemarkExtendedData->m_isBalloonVisible : false;
0743 }
0744 
0745 void GeoDataPlacemark::setBalloonVisible( bool visible )
0746 {
0747     if (!visible && !d_func()->m_placemarkExtendedData) {
0748         return; // nothing to do
0749     }
0750 
0751     Q_D(GeoDataPlacemark);
0752     d->placemarkExtendedData().m_isBalloonVisible = visible;
0753 }
0754 
0755 void GeoDataPlacemark::pack( QDataStream& stream ) const
0756 {
0757     Q_D(const GeoDataPlacemark);
0758     GeoDataFeature::pack( stream );
0759 
0760     stream << d->placemarkExtendedData().m_countrycode;
0761     stream << d->placemarkExtendedData().m_area;
0762     stream << d->m_population;
0763     if (d->m_geometry) {
0764         stream << d->m_geometry->geometryId();
0765         d->m_geometry->pack( stream );
0766     }
0767     else
0768     {
0769         stream << InvalidGeometryId;
0770     }
0771 }
0772 
0773 QXmlStreamWriter& GeoDataPlacemark::pack( QXmlStreamWriter& stream ) const
0774 {
0775     stream.writeStartElement( QLatin1String("placemark") );
0776 
0777     stream.writeEndElement();
0778     return stream;
0779 }
0780 
0781 QXmlStreamWriter& GeoDataPlacemark::operator <<( QXmlStreamWriter& stream ) const
0782 {
0783     pack( stream );
0784     return stream;
0785 }
0786 
0787 void GeoDataPlacemark::unpack( QDataStream& stream )
0788 {
0789     Q_D(GeoDataPlacemark);
0790     GeoDataFeature::unpack( stream );
0791 
0792     stream >> d->placemarkExtendedData().m_countrycode;
0793     stream >> d->placemarkExtendedData().m_area;
0794     stream >> d->m_population;
0795     int geometryId;
0796     stream >> geometryId;
0797     GeoDataGeometry *geometry = nullptr;
0798     switch( geometryId ) {
0799         case InvalidGeometryId:
0800             break;
0801         case GeoDataPointId:
0802             {
0803             GeoDataPoint* point = new GeoDataPoint;
0804             point->unpack( stream );
0805             geometry = point;
0806             }
0807             break;
0808         case GeoDataLineStringId:
0809             {
0810             GeoDataLineString* lineString = new GeoDataLineString;
0811             lineString->unpack( stream );
0812             geometry = lineString;
0813             }
0814             break;
0815         case GeoDataLinearRingId:
0816             {
0817             GeoDataLinearRing* linearRing = new GeoDataLinearRing;
0818             linearRing->unpack( stream );
0819             geometry = linearRing;
0820             }
0821             break;
0822         case GeoDataPolygonId:
0823             {
0824             GeoDataPolygon* polygon = new GeoDataPolygon;
0825             polygon->unpack( stream );
0826             geometry = polygon;
0827             }
0828             break;
0829         case GeoDataMultiGeometryId:
0830             {
0831             GeoDataMultiGeometry* multiGeometry = new GeoDataMultiGeometry;
0832             multiGeometry->unpack( stream );
0833             geometry = multiGeometry;
0834             }
0835             break;
0836         case GeoDataModelId:
0837             break;
0838         default: break;
0839     };
0840     if (geometry) {
0841        delete d->m_geometry;
0842        d->m_geometry = geometry;
0843        d->m_geometry->setParent(this);
0844     }
0845 }
0846 
0847 }