File indexing completed on 2025-01-05 03:59:23
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2015 Marius-Valeriu Stanciu <stanciumarius94@gmail.com> 0004 // 0005 0006 #ifndef MARBLE_OSMPLACEMARKDATA_H 0007 #define MARBLE_OSMPLACEMARKDATA_H 0008 0009 // Qt 0010 #include <QHash> 0011 #include <QMetaType> 0012 #include <QString> 0013 #include <QScopedPointer> 0014 #include <QSharedPointer> 0015 0016 0017 // Marble 0018 #include "GeoDataCoordinates.h" 0019 #include "GeoDocument.h" 0020 #include "digikam_export.h" 0021 0022 class QXmlStreamAttributes; 0023 0024 namespace Marble 0025 { 0026 0027 /** Type of OSM element. */ 0028 enum class OsmType { 0029 Node, 0030 Way, 0031 Relation 0032 }; 0033 0034 /** Identifier for an OSM element. 0035 * @note OSM uses distinct id spaces for all its three basic element types, so just the numeric id 0036 * on its own doesn't identify an element without knowing its type. 0037 */ 0038 struct OsmIdentifier { 0039 inline OsmIdentifier() = default; 0040 inline OsmIdentifier(qint64 _id, OsmType _type) : id(_id), type(_type) {} 0041 0042 qint64 id = 0; 0043 OsmType type = OsmType::Way; 0044 0045 inline bool operator==(OsmIdentifier other) const { return id == other.id && type == other.type; } 0046 }; 0047 0048 /** Forward declaration */ 0049 class OsmPlacemarkDataHashRef; 0050 0051 /** 0052 * This class is used to encapsulate the osm data fields kept within a placemark's extendedData. 0053 * It stores OSM server generated data: id, version, changeset, uid, visible, user, timestamp; 0054 * It also stores a hash map of \<tags\> ( key-value mappings ) and a hash map of component osm 0055 * placemarks @see m_nodeReferences @see m_memberReferences 0056 * 0057 * The usual workflow with osmData goes as follows: 0058 * 0059 * Parsing stage: 0060 * The OsmParser parses tags (they have server-generated attributes), creates new placemarks and 0061 * assigns them new OsmPlacemarkData objects with all the needed information. 0062 * 0063 * Editing stage: 0064 * While editing placemarks that have OsmPlacemarkData, all relevant changes reflect on the 0065 * OsmPlacemarkData object as well, so as not to uncorrelate data from the actual placemarks. 0066 * 0067 * Writing stage: 0068 * The OsmObjectManager assigns OsmPlacemarkData objects to placemarks that do not have it 0069 * ( these are usually newly created placemarks within the editor, or placemarks loaded from 0070 * ".kml" files ). Placemarks that already have it, are simply written as-is. 0071 */ 0072 class DIGIKAM_EXPORT OsmPlacemarkData: public GeoNode 0073 { 0074 0075 public: 0076 0077 OsmPlacemarkData(); 0078 virtual ~OsmPlacemarkData(); 0079 0080 qint64 id() const; 0081 qint64 oid() const; 0082 QString version() const; 0083 QString changeset() const; 0084 QString uid() const; 0085 QString isVisible() const; 0086 QString user() const; 0087 QString timestamp() const; 0088 QString action() const; 0089 const char* nodeType() const override; 0090 0091 void setId( qint64 id ); 0092 void setVersion( const QString& version ); 0093 void setChangeset( const QString& changeset ); 0094 void setUid( const QString& uid ); 0095 void setVisible( const QString& visible ); 0096 void setUser( const QString& user ); 0097 void setTimestamp( const QString& timestamp ); 0098 void setAction( const QString& action ); 0099 0100 /** 0101 * @brief tagValue returns the value of the tag that has @p key as key 0102 * or an empty qstring if there is no such tag 0103 */ 0104 QString tagValue( const QString &key ) const; 0105 0106 /** 0107 * @brief addTag this function inserts a string key=value mapping, 0108 * equivalent to the \<tag k="@p key" v="@p value"\> osm core data 0109 * element 0110 */ 0111 void addTag( const QString& key, const QString& value ); 0112 0113 /** 0114 * @brief removeTag removes the tag from the tag hash 0115 */ 0116 void removeTag( const QString& key ); 0117 0118 /** 0119 * @brief containsTag returns true if the tag hash contains an entry with 0120 * the @p key as key and @p value as value 0121 */ 0122 bool containsTag( const QString& key, const QString& value ) const; 0123 0124 /** 0125 * @brief containsTagKey returns true if the tag hash contains an entry with 0126 * the @p key as key 0127 */ 0128 bool containsTagKey( const QString& key ) const; 0129 0130 /** 0131 * @brief tagValue returns a pointer to the tag that has @p key as key 0132 * or the end iterator if there is no such tag 0133 */ 0134 QHash<QString, QString>::const_iterator findTag(const QString &key) const; 0135 0136 /** 0137 * @brief iterators for the tags hash. 0138 */ 0139 QHash< QString, QString >::const_iterator tagsBegin() const; 0140 QHash< QString, QString >::const_iterator tagsEnd() const; 0141 0142 /** 0143 * @brief this function returns the osmData associated with a nd 0144 */ 0145 OsmPlacemarkData &nodeReference( const GeoDataCoordinates& coordinates ); 0146 OsmPlacemarkData nodeReference( const GeoDataCoordinates& coordinates ) const; 0147 0148 /** 0149 * @brief addRef this function inserts a GeoDataCoordinates = OsmPlacemarkData 0150 * mapping into the reference hash, equivalent to the \<member ref="@p key" \> 0151 * osm core data element 0152 */ 0153 void addNodeReference( const GeoDataCoordinates& key, const OsmPlacemarkData &value ); 0154 void removeNodeReference( const GeoDataCoordinates& key ); 0155 bool containsNodeReference( const GeoDataCoordinates& key ) const; 0156 0157 /** 0158 * @brief changeNodeReference is a convenience function that allows the quick change of 0159 * a node hash entry. This is generally used to update the osm data in case 0160 * nodes are being moved in the editor. 0161 */ 0162 void changeNodeReference( const GeoDataCoordinates& oldKey, const GeoDataCoordinates &newKey ); 0163 0164 /** 0165 * @brief this function returns the osmData associated with a member boundary's index 0166 * -1 represents the outer boundary of a polygon, and 0,1,2... the inner boundaries, 0167 * in the order provided by polygon->innerBoundaries(); 0168 */ 0169 OsmPlacemarkData &memberReference( int key ); 0170 OsmPlacemarkData memberReference( int key ) const; 0171 0172 /** 0173 * @brief addRef this function inserts a int = OsmplacemarkData 0174 * mapping into the reference hash, equivalent to the osm \<nd ref="@p boundary of index @key" \> 0175 * core data element 0176 * @see m_memberReferences 0177 */ 0178 void addMemberReference( int key, const OsmPlacemarkData &value ); 0179 void removeMemberReference( int key ); 0180 bool containsMemberReference( int key ) const; 0181 0182 /** 0183 * @brief addRelation calling this makes the osm placemark a member of the relation 0184 * with @p id as id, while having the role @p role 0185 */ 0186 void addRelation( qint64 id, OsmType type, const QString &role ); 0187 void removeRelation( qint64 id ); 0188 bool containsRelation( qint64 id ) const; 0189 0190 QHash< OsmIdentifier, QString >::const_iterator relationReferencesBegin() const; 0191 QHash< OsmIdentifier, QString >::const_iterator relationReferencesEnd() const; 0192 0193 /** 0194 * @brief isNull returns false if the osmData is loaded from a source 0195 * or true if its just default constructed 0196 */ 0197 bool isNull() const; 0198 0199 /** 0200 * @brief isEmpty returns true if no attribute other than the id has been set 0201 */ 0202 bool isEmpty() const; 0203 0204 /** 0205 * @brief fromParserAttributes is a convenience function that parses all osm-related 0206 * arguments of a tag 0207 * @return an OsmPlacemarkData object containing all the necessary data 0208 */ 0209 static OsmPlacemarkData fromParserAttributes( const QXmlStreamAttributes &attributes ); 0210 0211 /** 0212 * Return the insternal instance of the hash-table functions container. 0213 */ 0214 OsmPlacemarkDataHashRef* hRef() const; 0215 0216 private: 0217 0218 qint64 m_id; 0219 QHash<QString, QString> m_tags; 0220 0221 /** 0222 * @brief m_relationReferences is used to store the relations the placemark is part of 0223 * and the role it has within them. 0224 * Eg. an entry ( "123", "stop" ) means that the parent placemark is a member of 0225 * the relation with id "123", while having the "stop" role 0226 */ 0227 QHash<OsmIdentifier, QString> m_relationReferences; 0228 0229 /** 0230 * Store the insternal instance of the hash-table functions container. 0231 */ 0232 QSharedPointer<OsmPlacemarkDataHashRef> m_href; 0233 }; 0234 0235 /** 0236 * Container to host hash-table functions with OsmPlacemarkData as values. 0237 * This container is necessary with Qt 6.6 under MSVC 2022 as compiler refuse to build 0238 * a QHash of a not fully defined class as value. 0239 * 0240 * E:\dk\x64-windows\include\Qt6\QtCore/qhash.h(76,7): error C2079: 'QHashPrivate::Node<Key,T>::value' uses undefined class 'Marble::OsmPlacemarkData' [C:\Users\gilles\Documents\marble\build.vcpkg\src\lib\marble\marblewidget.vcxproj] 0241 * with 0242 * [ 0243 * Key=Marble::GeoDataCoordinates, 0244 * T=Marble::OsmPlacemarkData 0245 * ] 0246 * E:\dk\x64-windows\include\Qt6\QtCore/qhash.h(858,1): message : see reference to class template instantiation 'QHashPrivate::Node<Key,T>' being compiled [C:\Users\gilles\Documents\marble\build.vcpkg\src\lib\marble\marblewidget.vcxproj] 0247 * with 0248 * [ 0249 * Key=Marble::GeoDataCoordinates, 0250 * T=Marble::OsmPlacemarkData 0251 * ] 0252 * 0253 */ 0254 class DIGIKAM_EXPORT OsmPlacemarkDataHashRef 0255 { 0256 public: 0257 0258 OsmPlacemarkDataHashRef(); 0259 0260 /** 0261 * @brief iterators for the reference hashes. 0262 */ 0263 QHash< GeoDataCoordinates, OsmPlacemarkData > & nodeReferences(); 0264 QHash< GeoDataCoordinates, OsmPlacemarkData >::const_iterator nodeReferencesBegin() const; 0265 QHash< GeoDataCoordinates, OsmPlacemarkData >::const_iterator nodeReferencesEnd() const; 0266 0267 QHash< int, OsmPlacemarkData > & memberReferences(); 0268 QHash< int, OsmPlacemarkData >::const_iterator memberReferencesBegin() const; 0269 QHash< int, OsmPlacemarkData >::const_iterator memberReferencesEnd() const; 0270 0271 /** 0272 * @brief m_ndRefs is used to store a way's component nodes 0273 * ( It is empty for other placemark types ) 0274 */ 0275 QHash< GeoDataCoordinates, OsmPlacemarkData > m_nodeReferences; 0276 0277 /** 0278 * @brief m_memberRefs is used to store a polygon's member boundaries 0279 * the key represents the index of the boundary within the polygon geometry: 0280 * -1 represents the outerBoundary, and 0,1,2... its innerBoundaries, in the 0281 * order provided by polygon->innerBoundaries() 0282 */ 0283 QHash<int, OsmPlacemarkData> m_memberReferences; 0284 }; 0285 0286 } 0287 0288 // Makes qvariant_cast possible for OsmPlacemarkData objects 0289 Q_DECLARE_METATYPE( Marble::OsmPlacemarkData ) 0290 0291 #endif