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