QGIS API Documentation 3.27.0-Master (1c05421486)
qgsxmlutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsxmlutils.cpp
3 ---------------------
4 begin : December 2013
5 copyright : (C) 2013 by Martin Dobias
6 email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgsxmlutils.h"
16
17#include <QDomElement>
18
19#include "qgslogger.h"
20#include "qgsrectangle.h"
21#include "qgsproperty.h"
22#include "qgssymbollayerutils.h"
25
27{
28 if ( "unknown" == element.text() )
29 {
31 }
32 else
33 {
36 }
37}
38
39QgsRectangle QgsXmlUtils::readRectangle( const QDomElement &element )
40{
41 QgsRectangle aoi;
42
43 const QDomNode xminNode = element.namedItem( QStringLiteral( "xmin" ) );
44 const QDomNode yminNode = element.namedItem( QStringLiteral( "ymin" ) );
45 const QDomNode xmaxNode = element.namedItem( QStringLiteral( "xmax" ) );
46 const QDomNode ymaxNode = element.namedItem( QStringLiteral( "ymax" ) );
47
48 QDomElement exElement = xminNode.toElement();
49 const double xmin = exElement.text().toDouble();
50 aoi.setXMinimum( xmin );
51
52 exElement = yminNode.toElement();
53 const double ymin = exElement.text().toDouble();
54 aoi.setYMinimum( ymin );
55
56 exElement = xmaxNode.toElement();
57 const double xmax = exElement.text().toDouble();
58 aoi.setXMaximum( xmax );
59
60 exElement = ymaxNode.toElement();
61 const double ymax = exElement.text().toDouble();
62 aoi.setYMaximum( ymax );
63
64 return aoi;
65}
66
67
68
69QDomElement QgsXmlUtils::writeMapUnits( QgsUnitTypes::DistanceUnit units, QDomDocument &doc )
70{
71 QString unitsString = QgsUnitTypes::encodeUnit( units );
72 // maintain compatibility with old projects
74 unitsString = QStringLiteral( "unknown" );
75
76 QDomElement unitsNode = doc.createElement( QStringLiteral( "units" ) );
77 unitsNode.appendChild( doc.createTextNode( unitsString ) );
78 return unitsNode;
79}
80
81QDomElement QgsXmlUtils::writeRectangle( const QgsRectangle &rect, QDomDocument &doc, const QString &elementName )
82{
83 QDomElement xMin = doc.createElement( QStringLiteral( "xmin" ) );
84 QDomElement yMin = doc.createElement( QStringLiteral( "ymin" ) );
85 QDomElement xMax = doc.createElement( QStringLiteral( "xmax" ) );
86 QDomElement yMax = doc.createElement( QStringLiteral( "ymax" ) );
87
88 const QDomText xMinText = doc.createTextNode( qgsDoubleToString( rect.xMinimum() ) );
89 const QDomText yMinText = doc.createTextNode( qgsDoubleToString( rect.yMinimum() ) );
90 const QDomText xMaxText = doc.createTextNode( qgsDoubleToString( rect.xMaximum() ) );
91 const QDomText yMaxText = doc.createTextNode( qgsDoubleToString( rect.yMaximum() ) );
92
93 xMin.appendChild( xMinText );
94 yMin.appendChild( yMinText );
95 xMax.appendChild( xMaxText );
96 yMax.appendChild( yMaxText );
97
98 QDomElement extentNode = doc.createElement( elementName );
99 extentNode.appendChild( xMin );
100 extentNode.appendChild( yMin );
101 extentNode.appendChild( xMax );
102 extentNode.appendChild( yMax );
103 return extentNode;
104}
105
106QDomElement QgsXmlUtils::writeVariant( const QVariant &value, QDomDocument &doc )
107{
108 QDomElement element = doc.createElement( QStringLiteral( "Option" ) );
109 switch ( value.type() )
110 {
111 case QVariant::Invalid:
112 {
113 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "invalid" ) );
114 break;
115 }
116
117 case QVariant::Map:
118 {
119 const QVariantMap map = value.toMap();
120
121 for ( auto option = map.constBegin(); option != map.constEnd(); ++option )
122 {
123 QDomElement optionElement = writeVariant( option.value(), doc );
124 optionElement.setAttribute( QStringLiteral( "name" ), option.key() );
125 element.appendChild( optionElement );
126 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Map" ) );
127 }
128 break;
129 }
130
131 case QVariant::List:
132 {
133 const QVariantList list = value.toList();
134
135 const auto constList = list;
136 for ( const QVariant &value : constList )
137 {
138 const QDomElement valueElement = writeVariant( value, doc );
139 element.appendChild( valueElement );
140 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "List" ) );
141 }
142 break;
143 }
144
145 case QVariant::StringList:
146 {
147 const QStringList list = value.toStringList();
148
149 const auto constList = list;
150 for ( const QString &value : constList )
151 {
152 const QDomElement valueElement = writeVariant( value, doc );
153 element.appendChild( valueElement );
154 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "StringList" ) );
155 }
156 break;
157 }
158
159 case QVariant::Int:
160 case QVariant::UInt:
161 case QVariant::Bool:
162 case QVariant::Double:
163 case QVariant::LongLong:
164 case QVariant::ULongLong:
165 case QVariant::String:
166 element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
167 element.setAttribute( QStringLiteral( "value" ), value.toString() );
168 break;
169
170 case QVariant::Char:
171 element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
172 element.setAttribute( QStringLiteral( "value" ), QgsVariantUtils::isNull( value ) ? QString() : QString( value.toChar() ) );
173 break;
174
175 case QVariant::Color:
176 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "color" ) );
177 element.setAttribute( QStringLiteral( "value" ), value.value< QColor >().isValid() ? QgsSymbolLayerUtils::encodeColor( value.value< QColor >() ) : QString() );
178 break;
179
180 case QVariant::DateTime:
181 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "datetime" ) );
182 element.setAttribute( QStringLiteral( "value" ), value.value< QDateTime >().isValid() ? value.toDateTime().toString( Qt::ISODate ) : QString() );
183 break;
184
185 case QVariant::Date:
186 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
187 element.setAttribute( QStringLiteral( "value" ), value.value< QDate >().isValid() ? value.toDate().toString( Qt::ISODate ) : QString() );
188 break;
189
190 case QVariant::Time:
191 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "time" ) );
192 element.setAttribute( QStringLiteral( "value" ), value.value< QTime >().isValid() ? value.toTime().toString( Qt::ISODate ) : QString() );
193 break;
194
195 case QVariant::UserType:
196 {
197 if ( value.userType() == QMetaType::type( "QgsProperty" ) )
198 {
199 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProperty" ) );
200 const QDomElement propertyElem = QgsXmlUtils::writeVariant( value.value< QgsProperty >().toVariant(), doc );
201 element.appendChild( propertyElem );
202 break;
203 }
204 else if ( value.userType() == QMetaType::type( "QgsCoordinateReferenceSystem" ) )
205 {
206 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsCoordinateReferenceSystem" ) );
208 crs.writeXml( element, doc );
209 break;
210 }
211 else if ( value.userType() == QMetaType::type( "QgsGeometry" ) )
212 {
213 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsGeometry" ) );
214 const QgsGeometry geom = value.value< QgsGeometry >();
215 element.setAttribute( QStringLiteral( "value" ), geom.asWkt() );
216 break;
217 }
218 else if ( value.userType() == QMetaType::type( "QgsProcessingOutputLayerDefinition" ) )
219 {
220 const QDomElement valueElement = writeVariant( value.value< QgsProcessingOutputLayerDefinition >().toVariant(), doc );
221 element.appendChild( valueElement );
222 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingOutputLayerDefinition" ) );
223 break;
224 }
225 else if ( value.userType() == QMetaType::type( "QgsProcessingFeatureSourceDefinition" ) )
226 {
227 const QDomElement valueElement = writeVariant( value.value< QgsProcessingFeatureSourceDefinition >().toVariant(), doc );
228 element.appendChild( valueElement );
229 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingFeatureSourceDefinition" ) );
230 break;
231 }
232 else if ( value.userType() == QMetaType::type( "QgsRemappingSinkDefinition" ) )
233 {
234 const QDomElement valueElement = writeVariant( value.value< QgsRemappingSinkDefinition >().toVariant(), doc );
235 element.appendChild( valueElement );
236 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsRemappingSinkDefinition" ) );
237 break;
238 }
239 Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported user variant type %1" ).arg( QMetaType::typeName( value.userType() ) ).toLocal8Bit() );
240 break;
241 }
242
243 default:
244 Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported variant type %1" ).arg( QVariant::typeToName( value.type() ) ).toLocal8Bit() );
245 break;
246 }
247
248 return element;
249}
250
251QVariant QgsXmlUtils::readVariant( const QDomElement &element )
252{
253 const QString type = element.attribute( QStringLiteral( "type" ) );
254
255 if ( type == QLatin1String( "invalid" ) )
256 {
257 return QVariant();
258 }
259 else if ( type == QLatin1String( "int" ) )
260 {
261 return element.attribute( QStringLiteral( "value" ) ).toInt();
262 }
263 else if ( type == QLatin1String( "uint" ) )
264 {
265 return element.attribute( QStringLiteral( "value" ) ).toUInt();
266 }
267 else if ( type == QLatin1String( "qlonglong" ) )
268 {
269 return element.attribute( QStringLiteral( "value" ) ).toLongLong();
270 }
271 else if ( type == QLatin1String( "qulonglong" ) )
272 {
273 return element.attribute( QStringLiteral( "value" ) ).toULongLong();
274 }
275 else if ( type == QLatin1String( "double" ) )
276 {
277 return element.attribute( QStringLiteral( "value" ) ).toDouble();
278 }
279 else if ( type == QLatin1String( "QString" ) )
280 {
281 return element.attribute( QStringLiteral( "value" ) );
282 }
283 else if ( type == QLatin1String( "QChar" ) )
284 {
285 const QString res = element.attribute( QStringLiteral( "value" ) );
286 return res.isEmpty() ? QChar() : res.at( 0 );
287 }
288 else if ( type == QLatin1String( "bool" ) )
289 {
290 return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" );
291 }
292 else if ( type == QLatin1String( "color" ) )
293 {
294 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QColor() : QgsSymbolLayerUtils::decodeColor( element.attribute( QStringLiteral( "value" ) ) );
295 }
296 else if ( type == QLatin1String( "datetime" ) )
297 {
298 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QDateTime() : QDateTime::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
299 }
300 else if ( type == QLatin1String( "date" ) )
301 {
302 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QDate() : QDate::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
303 }
304 else if ( type == QLatin1String( "time" ) )
305 {
306 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QTime() : QTime::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
307 }
308 else if ( type == QLatin1String( "Map" ) )
309 {
310 QVariantMap map;
311 const QDomNodeList options = element.childNodes();
312
313 for ( int i = 0; i < options.count(); ++i )
314 {
315 const QDomElement elem = options.at( i ).toElement();
316 if ( elem.tagName() == QLatin1String( "Option" ) )
317 map.insert( elem.attribute( QStringLiteral( "name" ) ), readVariant( elem ) );
318 }
319 return map;
320 }
321 else if ( type == QLatin1String( "List" ) )
322 {
323 QVariantList list;
324 const QDomNodeList values = element.childNodes();
325 for ( int i = 0; i < values.count(); ++i )
326 {
327 const QDomElement elem = values.at( i ).toElement();
328 list.append( readVariant( elem ) );
329 }
330 return list;
331 }
332 else if ( type == QLatin1String( "StringList" ) )
333 {
334 QStringList list;
335 const QDomNodeList values = element.childNodes();
336 for ( int i = 0; i < values.count(); ++i )
337 {
338 const QDomElement elem = values.at( i ).toElement();
339 list.append( readVariant( elem ).toString() );
340 }
341 return list;
342 }
343 else if ( type == QLatin1String( "QgsProperty" ) )
344 {
345 const QDomNodeList values = element.childNodes();
346 if ( values.isEmpty() )
347 return QVariant();
348
349 QgsProperty p;
350 if ( p.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ) ) )
351 return p;
352
353 return QVariant();
354 }
355 else if ( type == QLatin1String( "QgsCoordinateReferenceSystem" ) )
356 {
358 crs.readXml( element );
359 return crs;
360 }
361 else if ( type == QLatin1String( "QgsGeometry" ) )
362 {
363 return QgsGeometry::fromWkt( element.attribute( "value" ) );
364 }
365 else if ( type == QLatin1String( "QgsProcessingOutputLayerDefinition" ) )
366 {
368 const QDomNodeList values = element.childNodes();
369 if ( values.isEmpty() )
370 return QVariant();
371
372 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
373 return res;
374
375 return QVariant();
376 }
377 else if ( type == QLatin1String( "QgsProcessingFeatureSourceDefinition" ) )
378 {
380 const QDomNodeList values = element.childNodes();
381 if ( values.isEmpty() )
382 return QVariant();
383
384 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
385 return res;
386
387 return QVariant();
388 }
389 else if ( type == QLatin1String( "QgsRemappingSinkDefinition" ) )
390 {
392 const QDomNodeList values = element.childNodes();
393 if ( values.isEmpty() )
394 return QVariant();
395
396 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
397 return QVariant::fromValue( res );
398
399 return QVariant();
400 }
401 else
402 {
403 return QVariant();
404 }
405}
This class represents a coordinate reference system (CRS).
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QString asWkt(int precision=17) const
Exports the geometry to WKT.
Encapsulates settings relating to a feature source input to a processing algorithm.
bool loadVariant(const QVariantMap &map)
Loads this source definition from a QVariantMap, wrapped in a QVariant.
QVariant toVariant() const
Saves this source definition to a QVariantMap, wrapped in a QVariant.
Encapsulates settings relating to a feature sink or output raster layer for a processing algorithm.
bool loadVariant(const QVariantMap &map)
Loads this output layer definition from a QVariantMap, wrapped in a QVariant.
QVariant toVariant() const
Saves this output layer definition to a QVariantMap, wrapped in a QVariant.
A store for object properties.
Definition: qgsproperty.h:231
QVariant toVariant() const
Saves this property to a QVariantMap, wrapped in a QVariant.
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
Defines the parameters used to remap features when creating a QgsRemappingProxyFeatureSink.
QVariant toVariant() const
Saves this remapping definition to a QVariantMap, wrapped in a QVariant.
bool loadVariant(const QVariantMap &map)
Loads this remapping definition from a QVariantMap, wrapped in a QVariant.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:68
@ DistanceDegrees
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:75
@ DistanceUnknownUnit
Unknown distance unit.
Definition: qgsunittypes.h:78
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc, const QString &elementName=QStringLiteral("extent"))
Encodes a rectangle to a DOM element.
Definition: qgsxmlutils.cpp:81
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
static QDomElement writeMapUnits(QgsUnitTypes::DistanceUnit units, QDomDocument &doc)
Encodes a distance unit to a DOM element.
Definition: qgsxmlutils.cpp:69
static QgsUnitTypes::DistanceUnit readMapUnits(const QDomElement &element)
Decodes a distance unit from a DOM element.
Definition: qgsxmlutils.cpp:26
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:39
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2446
const QgsCoordinateReferenceSystem & crs
const QString & typeName