QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgsrectangle.h"
20#include "qgsproperty.h"
21#include "qgscolorutils.h"
24#include "qgsunittypes.h"
25
26Qgis::DistanceUnit QgsXmlUtils::readMapUnits( const QDomElement &element )
27{
28 if ( "unknown" == element.text() )
29 {
31 }
32 else
33 {
34 const Qgis::DistanceUnit unit = QgsUnitTypes::decodeDistanceUnit( element.text() );
36 }
37}
38
39QgsBox3D QgsXmlUtils::readBox3D( const QDomElement &element )
40{
41 QgsBox3D aoi;
42
43 const double xmin = element.attribute( QStringLiteral( "xmin" ) ).toDouble();
44 aoi.setXMinimum( xmin );
45
46 const double ymin = element.attribute( QStringLiteral( "ymin" ) ).toDouble();
47 aoi.setYMinimum( ymin );
48
49 const double zmin = element.attribute( QStringLiteral( "zmin" ) ).toDouble();
50 aoi.setZMinimum( zmin );
51
52 const double xmax = element.attribute( QStringLiteral( "xmax" ) ).toDouble();
53 aoi.setXMaximum( xmax );
54
55 const double ymax = element.attribute( QStringLiteral( "ymax" ) ).toDouble();
56 aoi.setYMaximum( ymax );
57
58 const double zmax = element.attribute( QStringLiteral( "zmax" ) ).toDouble();
59 aoi.setZMaximum( zmax );
60
61 return aoi;
62}
63
64QgsRectangle QgsXmlUtils::readRectangle( const QDomElement &element )
65{
66 QgsRectangle aoi;
67
68 const QDomNode xminNode = element.namedItem( QStringLiteral( "xmin" ) );
69 const QDomNode yminNode = element.namedItem( QStringLiteral( "ymin" ) );
70 const QDomNode xmaxNode = element.namedItem( QStringLiteral( "xmax" ) );
71 const QDomNode ymaxNode = element.namedItem( QStringLiteral( "ymax" ) );
72
73 QDomElement exElement = xminNode.toElement();
74 const double xmin = exElement.text().toDouble();
75 aoi.setXMinimum( xmin );
76
77 exElement = yminNode.toElement();
78 const double ymin = exElement.text().toDouble();
79 aoi.setYMinimum( ymin );
80
81 exElement = xmaxNode.toElement();
82 const double xmax = exElement.text().toDouble();
83 aoi.setXMaximum( xmax );
84
85 exElement = ymaxNode.toElement();
86 const double ymax = exElement.text().toDouble();
87 aoi.setYMaximum( ymax );
88
89 return aoi;
90}
91
92
93
94QDomElement QgsXmlUtils::writeMapUnits( Qgis::DistanceUnit units, QDomDocument &doc )
95{
96 QString unitsString = QgsUnitTypes::encodeUnit( units );
97 // maintain compatibility with old projects
98 if ( units == Qgis::DistanceUnit::Unknown )
99 unitsString = QStringLiteral( "unknown" );
100
101 QDomElement unitsNode = doc.createElement( QStringLiteral( "units" ) );
102 unitsNode.appendChild( doc.createTextNode( unitsString ) );
103 return unitsNode;
104}
105
106QDomElement QgsXmlUtils::writeBox3D( const QgsBox3D &box, QDomDocument &doc, const QString &elementName )
107{
108 QDomElement elemExtent3D = doc.createElement( elementName );
109 elemExtent3D.setAttribute( QStringLiteral( "xMin" ), box.xMinimum() );
110 elemExtent3D.setAttribute( QStringLiteral( "yMin" ), box.yMinimum() );
111 elemExtent3D.setAttribute( QStringLiteral( "zMin" ), box.zMinimum() );
112 elemExtent3D.setAttribute( QStringLiteral( "xMax" ), box.xMaximum() );
113 elemExtent3D.setAttribute( QStringLiteral( "yMax" ), box.yMaximum() );
114 elemExtent3D.setAttribute( QStringLiteral( "zMax" ), box.zMaximum() );
115
116 return elemExtent3D;
117}
118
119QDomElement QgsXmlUtils::writeRectangle( const QgsRectangle &rect, QDomDocument &doc, const QString &elementName )
120{
121 QDomElement xMin = doc.createElement( QStringLiteral( "xmin" ) );
122 QDomElement yMin = doc.createElement( QStringLiteral( "ymin" ) );
123 QDomElement xMax = doc.createElement( QStringLiteral( "xmax" ) );
124 QDomElement yMax = doc.createElement( QStringLiteral( "ymax" ) );
125
126 const QDomText xMinText = doc.createTextNode( qgsDoubleToString( rect.xMinimum() ) );
127 const QDomText yMinText = doc.createTextNode( qgsDoubleToString( rect.yMinimum() ) );
128 const QDomText xMaxText = doc.createTextNode( qgsDoubleToString( rect.xMaximum() ) );
129 const QDomText yMaxText = doc.createTextNode( qgsDoubleToString( rect.yMaximum() ) );
130
131 xMin.appendChild( xMinText );
132 yMin.appendChild( yMinText );
133 xMax.appendChild( xMaxText );
134 yMax.appendChild( yMaxText );
135
136 QDomElement extentNode = doc.createElement( elementName );
137 extentNode.appendChild( xMin );
138 extentNode.appendChild( yMin );
139 extentNode.appendChild( xMax );
140 extentNode.appendChild( yMax );
141 return extentNode;
142}
143
144QDomElement QgsXmlUtils::writeVariant( const QVariant &value, QDomDocument &doc )
145{
146 QDomElement element = doc.createElement( QStringLiteral( "Option" ) );
147 switch ( value.type() )
148 {
149 case QVariant::Invalid:
150 {
151 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "invalid" ) );
152 break;
153 }
154
155 case QVariant::Map:
156 {
157 const QVariantMap map = value.toMap();
158
159 for ( auto option = map.constBegin(); option != map.constEnd(); ++option )
160 {
161 QDomElement optionElement = writeVariant( option.value(), doc );
162 optionElement.setAttribute( QStringLiteral( "name" ), option.key() );
163 element.appendChild( optionElement );
164 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Map" ) );
165 }
166 break;
167 }
168
169 case QVariant::List:
170 {
171 const QVariantList list = value.toList();
172
173 const auto constList = list;
174 for ( const QVariant &value : constList )
175 {
176 const QDomElement valueElement = writeVariant( value, doc );
177 element.appendChild( valueElement );
178 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "List" ) );
179 }
180 break;
181 }
182
183 case QVariant::StringList:
184 {
185 const QStringList list = value.toStringList();
186
187 const auto constList = list;
188 for ( const QString &value : constList )
189 {
190 const QDomElement valueElement = writeVariant( value, doc );
191 element.appendChild( valueElement );
192 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "StringList" ) );
193 }
194 break;
195 }
196
197 case QVariant::Int:
198 case QVariant::UInt:
199 case QVariant::Bool:
200 case QVariant::Double:
201 case QVariant::LongLong:
202 case QVariant::ULongLong:
203 case QVariant::String:
204 element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
205 element.setAttribute( QStringLiteral( "value" ), value.toString() );
206 break;
207
208 case QVariant::Char:
209 element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
210 element.setAttribute( QStringLiteral( "value" ), QgsVariantUtils::isNull( value ) ? QString() : QString( value.toChar() ) );
211 break;
212
213 case QVariant::Color:
214 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "color" ) );
215 element.setAttribute( QStringLiteral( "value" ), value.value< QColor >().isValid() ? QgsColorUtils::colorToString( value.value< QColor >() ) : QString() );
216 break;
217
218 case QVariant::DateTime:
219 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "datetime" ) );
220 element.setAttribute( QStringLiteral( "value" ), value.value< QDateTime >().isValid() ? value.toDateTime().toString( Qt::ISODate ) : QString() );
221 break;
222
223 case QVariant::Date:
224 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
225 element.setAttribute( QStringLiteral( "value" ), value.value< QDate >().isValid() ? value.toDate().toString( Qt::ISODate ) : QString() );
226 break;
227
228 case QVariant::Time:
229 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "time" ) );
230 element.setAttribute( QStringLiteral( "value" ), value.value< QTime >().isValid() ? value.toTime().toString( Qt::ISODate ) : QString() );
231 break;
232
233 case QVariant::UserType:
234 {
235 if ( value.userType() == QMetaType::type( "QgsProperty" ) )
236 {
237 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProperty" ) );
238 const QDomElement propertyElem = QgsXmlUtils::writeVariant( value.value< QgsProperty >().toVariant(), doc );
239 element.appendChild( propertyElem );
240 break;
241 }
242 else if ( value.userType() == QMetaType::type( "QgsCoordinateReferenceSystem" ) )
243 {
244 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsCoordinateReferenceSystem" ) );
246 crs.writeXml( element, doc );
247 break;
248 }
249 else if ( value.userType() == QMetaType::type( "QgsGeometry" ) )
250 {
251 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsGeometry" ) );
252 const QgsGeometry geom = value.value< QgsGeometry >();
253 element.setAttribute( QStringLiteral( "value" ), geom.asWkt() );
254 break;
255 }
256 else if ( value.userType() == QMetaType::type( "QgsProcessingOutputLayerDefinition" ) )
257 {
258 const QDomElement valueElement = writeVariant( value.value< QgsProcessingOutputLayerDefinition >().toVariant(), doc );
259 element.appendChild( valueElement );
260 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingOutputLayerDefinition" ) );
261 break;
262 }
263 else if ( value.userType() == QMetaType::type( "QgsProcessingFeatureSourceDefinition" ) )
264 {
265 const QDomElement valueElement = writeVariant( value.value< QgsProcessingFeatureSourceDefinition >().toVariant(), doc );
266 element.appendChild( valueElement );
267 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProcessingFeatureSourceDefinition" ) );
268 break;
269 }
270 else if ( value.userType() == QMetaType::type( "QgsRemappingSinkDefinition" ) )
271 {
272 const QDomElement valueElement = writeVariant( value.value< QgsRemappingSinkDefinition >().toVariant(), doc );
273 element.appendChild( valueElement );
274 element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsRemappingSinkDefinition" ) );
275 break;
276 }
277 Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported user variant type %1" ).arg( QMetaType::typeName( value.userType() ) ).toLocal8Bit() );
278 break;
279 }
280
281 default:
282 Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported variant type %1" ).arg( QVariant::typeToName( value.type() ) ).toLocal8Bit() );
283 break;
284 }
285
286 return element;
287}
288
289QVariant QgsXmlUtils::readVariant( const QDomElement &element )
290{
291 const QString type = element.attribute( QStringLiteral( "type" ) );
292
293 if ( type == QLatin1String( "invalid" ) )
294 {
295 return QVariant();
296 }
297 else if ( type == QLatin1String( "int" ) )
298 {
299 return element.attribute( QStringLiteral( "value" ) ).toInt();
300 }
301 else if ( type == QLatin1String( "uint" ) )
302 {
303 return element.attribute( QStringLiteral( "value" ) ).toUInt();
304 }
305 else if ( type == QLatin1String( "qlonglong" ) )
306 {
307 return element.attribute( QStringLiteral( "value" ) ).toLongLong();
308 }
309 else if ( type == QLatin1String( "qulonglong" ) )
310 {
311 return element.attribute( QStringLiteral( "value" ) ).toULongLong();
312 }
313 else if ( type == QLatin1String( "double" ) )
314 {
315 return element.attribute( QStringLiteral( "value" ) ).toDouble();
316 }
317 else if ( type == QLatin1String( "QString" ) )
318 {
319 const QString res = element.attribute( QStringLiteral( "value" ) );
320 return res.isEmpty() ? QVariant() : res;
321 }
322 else if ( type == QLatin1String( "QChar" ) )
323 {
324 const QString res = element.attribute( QStringLiteral( "value" ) );
325 return res.isEmpty() ? QVariant() : res.at( 0 );
326 }
327 else if ( type == QLatin1String( "bool" ) )
328 {
329 return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" );
330 }
331 else if ( type == QLatin1String( "color" ) )
332 {
333 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QVariant() : QgsColorUtils::colorFromString( element.attribute( QStringLiteral( "value" ) ) );
334 }
335 else if ( type == QLatin1String( "datetime" ) )
336 {
337 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QVariant() : QDateTime::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
338 }
339 else if ( type == QLatin1String( "date" ) )
340 {
341 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QVariant() : QDate::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
342 }
343 else if ( type == QLatin1String( "time" ) )
344 {
345 return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QVariant() : QTime::fromString( element.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
346 }
347 else if ( type == QLatin1String( "Map" ) )
348 {
349 QVariantMap map;
350 const QDomNodeList options = element.childNodes();
351
352 for ( int i = 0; i < options.count(); ++i )
353 {
354 const QDomElement elem = options.at( i ).toElement();
355 if ( elem.tagName() == QLatin1String( "Option" ) )
356 map.insert( elem.attribute( QStringLiteral( "name" ) ), readVariant( elem ) );
357 }
358 return map;
359 }
360 else if ( type == QLatin1String( "List" ) )
361 {
362 QVariantList list;
363 const QDomNodeList values = element.childNodes();
364 for ( int i = 0; i < values.count(); ++i )
365 {
366 const QDomElement elem = values.at( i ).toElement();
367 list.append( readVariant( elem ) );
368 }
369 return list;
370 }
371 else if ( type == QLatin1String( "StringList" ) )
372 {
373 QStringList list;
374 const QDomNodeList values = element.childNodes();
375 for ( int i = 0; i < values.count(); ++i )
376 {
377 const QDomElement elem = values.at( i ).toElement();
378 list.append( readVariant( elem ).toString() );
379 }
380 return list;
381 }
382 else if ( type == QLatin1String( "QgsProperty" ) )
383 {
384 const QDomNodeList values = element.childNodes();
385 if ( values.isEmpty() )
386 return QVariant();
387
388 QgsProperty p;
389 if ( p.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ) ) )
390 return p;
391
392 return QVariant();
393 }
394 else if ( type == QLatin1String( "QgsCoordinateReferenceSystem" ) )
395 {
397 crs.readXml( element );
398 return crs.isValid() ? crs : QVariant();
399 }
400 else if ( type == QLatin1String( "QgsGeometry" ) )
401 {
402 const QgsGeometry g = QgsGeometry::fromWkt( element.attribute( "value" ) );
403 return !g.isNull() ? g : QVariant();
404 }
405 else if ( type == QLatin1String( "QgsProcessingOutputLayerDefinition" ) )
406 {
408 const QDomNodeList values = element.childNodes();
409 if ( values.isEmpty() )
410 return QVariant();
411
412 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
413 return res;
414
415 return QVariant();
416 }
417 else if ( type == QLatin1String( "QgsProcessingFeatureSourceDefinition" ) )
418 {
420 const QDomNodeList values = element.childNodes();
421 if ( values.isEmpty() )
422 return QVariant();
423
424 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
425 return res;
426
427 return QVariant();
428 }
429 else if ( type == QLatin1String( "QgsRemappingSinkDefinition" ) )
430 {
432 const QDomNodeList values = element.childNodes();
433 if ( values.isEmpty() )
434 return QVariant();
435
436 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
437 return QVariant::fromValue( res );
438
439 return QVariant();
440 }
441 else
442 {
443 return QVariant();
444 }
445}
DistanceUnit
Units of distance.
Definition: qgis.h:4124
@ Unknown
Unknown distance unit.
@ Degrees
Degrees, for planar geographic CRS distance measurements.
A 3-dimensional box composed of x, y, z coordinates.
Definition: qgsbox3d.h:43
double yMaximum() const
Returns the maximum y value.
Definition: qgsbox3d.h:197
void setZMinimum(double z)
Sets the minimum z value.
Definition: qgsbox3d.cpp:76
void setYMaximum(double y)
Sets the maximum y value.
Definition: qgsbox3d.cpp:71
void setZMaximum(double z)
Sets the maximum z value.
Definition: qgsbox3d.cpp:81
double xMinimum() const
Returns the minimum x value.
Definition: qgsbox3d.h:162
double zMaximum() const
Returns the maximum z value.
Definition: qgsbox3d.h:225
double xMaximum() const
Returns the maximum x value.
Definition: qgsbox3d.h:169
void setXMaximum(double x)
Sets the maximum x value.
Definition: qgsbox3d.cpp:61
void setYMinimum(double y)
Sets the minimum y value.
Definition: qgsbox3d.cpp:66
double zMinimum() const
Returns the minimum z value.
Definition: qgsbox3d.h:218
double yMinimum() const
Returns the minimum y value.
Definition: qgsbox3d.h:190
void setXMinimum(double x)
Sets the minimum x value.
Definition: qgsbox3d.cpp:56
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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:162
Q_GADGET bool isNull
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:228
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 xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:201
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:159
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:211
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:149
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:196
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:206
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:164
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:154
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 Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE Qgis::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QDomElement writeBox3D(const QgsBox3D &box, QDomDocument &doc, const QString &elementName=QStringLiteral("extent3D"))
Encodes a 3D box to a DOM element.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QgsBox3D readBox3D(const QDomElement &element)
Decodes a DOM element to a 3D box.
Definition: qgsxmlutils.cpp:39
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc, const QString &elementName=QStringLiteral("extent"))
Encodes a rectangle to a DOM element.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
static Qgis::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:64
static QDomElement writeMapUnits(Qgis::DistanceUnit units, QDomDocument &doc)
Encodes a distance unit to a DOM element.
Definition: qgsxmlutils.cpp:94
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:5124
const QgsCoordinateReferenceSystem & crs
const QString & typeName