QGIS API Documentation 3.99.0-Master (a8882ad4560)
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
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( u"xmin"_s ).toDouble();
44 aoi.setXMinimum( xmin );
45
46 const double ymin = element.attribute( u"ymin"_s ).toDouble();
47 aoi.setYMinimum( ymin );
48
49 const double zmin = element.attribute( u"zmin"_s ).toDouble();
50 aoi.setZMinimum( zmin );
51
52 const double xmax = element.attribute( u"xmax"_s ).toDouble();
53 aoi.setXMaximum( xmax );
54
55 const double ymax = element.attribute( u"ymax"_s ).toDouble();
56 aoi.setYMaximum( ymax );
57
58 const double zmax = element.attribute( u"zmax"_s ).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( u"xmin"_s );
69 const QDomNode yminNode = element.namedItem( u"ymin"_s );
70 const QDomNode xmaxNode = element.namedItem( u"xmax"_s );
71 const QDomNode ymaxNode = element.namedItem( u"ymax"_s );
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 = u"unknown"_s;
100
101 QDomElement unitsNode = doc.createElement( u"units"_s );
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( u"xMin"_s, box.xMinimum() );
110 elemExtent3D.setAttribute( u"yMin"_s, box.yMinimum() );
111 elemExtent3D.setAttribute( u"zMin"_s, box.zMinimum() );
112 elemExtent3D.setAttribute( u"xMax"_s, box.xMaximum() );
113 elemExtent3D.setAttribute( u"yMax"_s, box.yMaximum() );
114 elemExtent3D.setAttribute( u"zMax"_s, 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( u"xmin"_s );
122 QDomElement yMin = doc.createElement( u"ymin"_s );
123 QDomElement xMax = doc.createElement( u"xmax"_s );
124 QDomElement yMax = doc.createElement( u"ymax"_s );
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( u"Option"_s );
147 switch ( value.userType() )
148 {
149 case QMetaType::Type::UnknownType:
150 {
151 element.setAttribute( u"type"_s, u"invalid"_s );
152 break;
153 }
154
155 case QMetaType::Type::QVariantMap:
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( u"name"_s, option.key() );
163 element.appendChild( optionElement );
164 element.setAttribute( u"type"_s, u"Map"_s );
165 }
166 break;
167 }
168
169 case QMetaType::Type::QVariantList:
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( u"type"_s, u"List"_s );
179 }
180 break;
181 }
182
183 case QMetaType::Type::QStringList:
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( u"type"_s, u"StringList"_s );
193 }
194 break;
195 }
196
197 case QMetaType::Type::QRect:
198 {
199 element.setAttribute( u"type"_s, "QRect" );
200
201 const QRect rect = value.toRect();
202 element.setAttribute( u"x"_s, rect.x() );
203 element.setAttribute( u"y"_s, rect.y() );
204 element.setAttribute( u"width"_s, rect.width() );
205 element.setAttribute( u"height"_s, rect.height() );
206 break;
207 }
208
209 case QMetaType::Type::Int:
210 case QMetaType::Type::UInt:
211 case QMetaType::Type::Bool:
212 case QMetaType::Type::Double:
213 case QMetaType::Type::LongLong:
214 case QMetaType::Type::ULongLong:
215 case QMetaType::Type::QString:
216 element.setAttribute( u"type"_s, QVariant::typeToName( static_cast<QMetaType::Type>( value.userType() ) ) );
217 element.setAttribute( u"value"_s, value.toString() );
218 break;
219
220 case QMetaType::Type::QChar:
221 element.setAttribute( u"type"_s, QVariant::typeToName( static_cast<QMetaType::Type>( value.userType() ) ) );
222 element.setAttribute( u"value"_s, QgsVariantUtils::isNull( value ) ? QString() : QString( value.toChar() ) );
223 break;
224
225 case QMetaType::Type::QColor:
226 element.setAttribute( u"type"_s, u"color"_s );
227 element.setAttribute( u"value"_s, value.value< QColor >().isValid() ? QgsColorUtils::colorToString( value.value< QColor >() ) : QString() );
228 break;
229
230 case QMetaType::Type::QDateTime:
231 element.setAttribute( u"type"_s, u"datetime"_s );
232 element.setAttribute( u"value"_s, value.value< QDateTime >().isValid() ? value.toDateTime().toString( Qt::ISODate ) : QString() );
233 break;
234
235 case QMetaType::Type::QDate:
236 element.setAttribute( u"type"_s, u"date"_s );
237 element.setAttribute( u"value"_s, value.value< QDate >().isValid() ? value.toDate().toString( Qt::ISODate ) : QString() );
238 break;
239
240 case QMetaType::Type::QTime:
241 element.setAttribute( u"type"_s, u"time"_s );
242 element.setAttribute( u"value"_s, value.value< QTime >().isValid() ? value.toTime().toString( Qt::ISODate ) : QString() );
243 break;
244
245 default:
246
247 if ( value.userType() == qMetaTypeId<QgsProperty>() )
248 {
249 element.setAttribute( u"type"_s, u"QgsProperty"_s );
250 const QDomElement propertyElem = QgsXmlUtils::writeVariant( value.value< QgsProperty >().toVariant(), doc );
251 element.appendChild( propertyElem );
252 break;
253 }
254 else if ( value.userType() == qMetaTypeId<QgsCoordinateReferenceSystem>() )
255 {
256 element.setAttribute( u"type"_s, u"QgsCoordinateReferenceSystem"_s );
258 crs.writeXml( element, doc );
259 break;
260 }
261 else if ( value.userType() == qMetaTypeId< QgsGeometry>() )
262 {
263 element.setAttribute( u"type"_s, u"QgsGeometry"_s );
264 const QgsGeometry geom = value.value< QgsGeometry >();
265 element.setAttribute( u"value"_s, geom.asWkt() );
266 break;
267 }
268 else if ( value.userType() == qMetaTypeId<QgsProcessingOutputLayerDefinition>() )
269 {
270 const QDomElement valueElement = writeVariant( value.value< QgsProcessingOutputLayerDefinition >().toVariant(), doc );
271 element.appendChild( valueElement );
272 element.setAttribute( u"type"_s, u"QgsProcessingOutputLayerDefinition"_s );
273 break;
274 }
275 else if ( value.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
276 {
277 const QDomElement valueElement = writeVariant( value.value< QgsProcessingFeatureSourceDefinition >().toVariant(), doc );
278 element.appendChild( valueElement );
279 element.setAttribute( u"type"_s, u"QgsProcessingFeatureSourceDefinition"_s );
280 break;
281 }
282 else if ( value.userType() == qMetaTypeId<QgsRemappingSinkDefinition>() )
283 {
284 const QDomElement valueElement = writeVariant( value.value< QgsRemappingSinkDefinition >().toVariant(), doc );
285 element.appendChild( valueElement );
286 element.setAttribute( u"type"_s, u"QgsRemappingSinkDefinition"_s );
287 break;
288 }
289 else
290 {
291 Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", u"unsupported %1variant type %2"_s
292 .arg( value.userType() >= QMetaType::Type::User ? "user " : QString() ).arg( value.metaType().name() ).toLocal8Bit() );
293 }
294 break;
295 }
296
297 return element;
298}
299
300QVariant QgsXmlUtils::readVariant( const QDomElement &element )
301{
302 const QString type = element.attribute( u"type"_s );
303
304 if ( type == "invalid"_L1 )
305 {
306 return QVariant();
307 }
308 else if ( type == "int"_L1 )
309 {
310 return element.attribute( u"value"_s ).toInt();
311 }
312 else if ( type == "uint"_L1 )
313 {
314 return element.attribute( u"value"_s ).toUInt();
315 }
316 else if ( type == "qlonglong"_L1 )
317 {
318 return element.attribute( u"value"_s ).toLongLong();
319 }
320 else if ( type == "qulonglong"_L1 )
321 {
322 return element.attribute( u"value"_s ).toULongLong();
323 }
324 else if ( type == "double"_L1 )
325 {
326 return element.attribute( u"value"_s ).toDouble();
327 }
328 else if ( type == "QString"_L1 )
329 {
330 const QString res = element.attribute( u"value"_s );
331 return res.isEmpty() ? QVariant() : res;
332 }
333 else if ( type == "QChar"_L1 )
334 {
335 const QString res = element.attribute( u"value"_s );
336 return res.isEmpty() ? QVariant() : res.at( 0 );
337 }
338 else if ( type == "bool"_L1 )
339 {
340 return element.attribute( u"value"_s ) == "true"_L1;
341 }
342 else if ( type == "color"_L1 )
343 {
344 return element.attribute( u"value"_s ).isEmpty() ? QVariant() : QgsColorUtils::colorFromString( element.attribute( u"value"_s ) );
345 }
346 else if ( type == "datetime"_L1 )
347 {
348 return element.attribute( u"value"_s ).isEmpty() ? QVariant() : QDateTime::fromString( element.attribute( u"value"_s ), Qt::ISODate );
349 }
350 else if ( type == "date"_L1 )
351 {
352 return element.attribute( u"value"_s ).isEmpty() ? QVariant() : QDate::fromString( element.attribute( u"value"_s ), Qt::ISODate );
353 }
354 else if ( type == "time"_L1 )
355 {
356 return element.attribute( u"value"_s ).isEmpty() ? QVariant() : QTime::fromString( element.attribute( u"value"_s ), Qt::ISODate );
357 }
358 else if ( type == "Map"_L1 )
359 {
360 QVariantMap map;
361 const QDomNodeList options = element.childNodes();
362
363 for ( int i = 0; i < options.count(); ++i )
364 {
365 const QDomElement elem = options.at( i ).toElement();
366 if ( elem.tagName() == "Option"_L1 )
367 map.insert( elem.attribute( u"name"_s ), readVariant( elem ) );
368 }
369 return map;
370 }
371 else if ( type == "List"_L1 )
372 {
373 QVariantList 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 ) );
379 }
380 return list;
381 }
382 else if ( type == "StringList"_L1 )
383 {
384 QStringList list;
385 const QDomNodeList values = element.childNodes();
386 for ( int i = 0; i < values.count(); ++i )
387 {
388 const QDomElement elem = values.at( i ).toElement();
389 list.append( readVariant( elem ).toString() );
390 }
391 return list;
392 }
393 else if ( type == "QRect"_L1 )
394 {
395 const int x = element.attribute( "x" ).toInt();
396 const int y = element.attribute( "y" ).toInt();
397 const int width = element.attribute( "width" ).toInt();
398 const int height = element.attribute( "height" ).toInt();
399
400 return QRect( x, y, width, height );
401 }
402 else if ( type == "QgsProperty"_L1 )
403 {
404 const QDomNodeList values = element.childNodes();
405 if ( values.isEmpty() )
406 return QVariant();
407
408 QgsProperty p;
409 if ( p.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ) ) )
410 return p;
411
412 return QVariant();
413 }
414 else if ( type == "QgsCoordinateReferenceSystem"_L1 )
415 {
417 crs.readXml( element );
418 return crs.isValid() ? crs : QVariant();
419 }
420 else if ( type == "QgsGeometry"_L1 )
421 {
422 const QgsGeometry g = QgsGeometry::fromWkt( element.attribute( "value" ) );
423 return !g.isNull() ? g : QVariant();
424 }
425 else if ( type == "QgsProcessingOutputLayerDefinition"_L1 )
426 {
428 const QDomNodeList values = element.childNodes();
429 if ( values.isEmpty() )
430 return QVariant();
431
432 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
433 return res;
434
435 return QVariant();
436 }
437 else if ( type == "QgsProcessingFeatureSourceDefinition"_L1 )
438 {
440 const QDomNodeList values = element.childNodes();
441 if ( values.isEmpty() )
442 return QVariant();
443
444 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
445 return res;
446
447 return QVariant();
448 }
449 else if ( type == "QgsRemappingSinkDefinition"_L1 )
450 {
452 const QDomNodeList values = element.childNodes();
453 if ( values.isEmpty() )
454 return QVariant();
455
456 if ( res.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ).toMap() ) )
457 return QVariant::fromValue( res );
458
459 return QVariant();
460 }
461 else
462 {
463 return QVariant();
464 }
465}
DistanceUnit
Units of distance.
Definition qgis.h:5073
@ Unknown
Unknown distance unit.
Definition qgis.h:5123
@ Degrees
Degrees, for planar geographic CRS distance measurements.
Definition qgis.h:5080
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:42
double yMaximum() const
Returns the maximum y value.
Definition qgsbox3d.h:230
void setZMinimum(double z)
Sets the minimum z value.
Definition qgsbox3d.cpp:90
void setYMaximum(double y)
Sets the maximum y value.
Definition qgsbox3d.cpp:85
void setZMaximum(double z)
Sets the maximum z value.
Definition qgsbox3d.cpp:95
double xMinimum() const
Returns the minimum x value.
Definition qgsbox3d.h:195
double zMaximum() const
Returns the maximum z value.
Definition qgsbox3d.h:258
double xMaximum() const
Returns the maximum x value.
Definition qgsbox3d.h:202
void setXMaximum(double x)
Sets the maximum x value.
Definition qgsbox3d.cpp:75
void setYMinimum(double y)
Sets the minimum y value.
Definition qgsbox3d.cpp:80
double zMinimum() const
Returns the minimum z value.
Definition qgsbox3d.h:251
double yMinimum() const
Returns the minimum y value.
Definition qgsbox3d.h:223
void setXMinimum(double x)
Sets the minimum x value.
Definition qgsbox3d.cpp:70
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:6805