QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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"
23 
25 {
26  if ( "unknown" == element.text() )
27  {
29  }
30  else
31  {
34  }
35 }
36 
37 QgsRectangle QgsXmlUtils::readRectangle( const QDomElement &element )
38 {
39  QgsRectangle aoi;
40 
41  QDomNode xminNode = element.namedItem( QStringLiteral( "xmin" ) );
42  QDomNode yminNode = element.namedItem( QStringLiteral( "ymin" ) );
43  QDomNode xmaxNode = element.namedItem( QStringLiteral( "xmax" ) );
44  QDomNode ymaxNode = element.namedItem( QStringLiteral( "ymax" ) );
45 
46  QDomElement exElement = xminNode.toElement();
47  double xmin = exElement.text().toDouble();
48  aoi.setXMinimum( xmin );
49 
50  exElement = yminNode.toElement();
51  double ymin = exElement.text().toDouble();
52  aoi.setYMinimum( ymin );
53 
54  exElement = xmaxNode.toElement();
55  double xmax = exElement.text().toDouble();
56  aoi.setXMaximum( xmax );
57 
58  exElement = ymaxNode.toElement();
59  double ymax = exElement.text().toDouble();
60  aoi.setYMaximum( ymax );
61 
62  return aoi;
63 }
64 
65 
66 
67 QDomElement QgsXmlUtils::writeMapUnits( QgsUnitTypes::DistanceUnit units, QDomDocument &doc )
68 {
69  QString unitsString = QgsUnitTypes::encodeUnit( units );
70  // maintain compatibility with old projects
71  if ( units == QgsUnitTypes::DistanceUnknownUnit )
72  unitsString = QStringLiteral( "unknown" );
73 
74  QDomElement unitsNode = doc.createElement( QStringLiteral( "units" ) );
75  unitsNode.appendChild( doc.createTextNode( unitsString ) );
76  return unitsNode;
77 }
78 
79 QDomElement QgsXmlUtils::writeRectangle( const QgsRectangle &rect, QDomDocument &doc )
80 {
81  QDomElement xMin = doc.createElement( QStringLiteral( "xmin" ) );
82  QDomElement yMin = doc.createElement( QStringLiteral( "ymin" ) );
83  QDomElement xMax = doc.createElement( QStringLiteral( "xmax" ) );
84  QDomElement yMax = doc.createElement( QStringLiteral( "ymax" ) );
85 
86  QDomText xMinText = doc.createTextNode( qgsDoubleToString( rect.xMinimum() ) );
87  QDomText yMinText = doc.createTextNode( qgsDoubleToString( rect.yMinimum() ) );
88  QDomText xMaxText = doc.createTextNode( qgsDoubleToString( rect.xMaximum() ) );
89  QDomText yMaxText = doc.createTextNode( qgsDoubleToString( rect.yMaximum() ) );
90 
91  xMin.appendChild( xMinText );
92  yMin.appendChild( yMinText );
93  xMax.appendChild( xMaxText );
94  yMax.appendChild( yMaxText );
95 
96  QDomElement extentNode = doc.createElement( QStringLiteral( "extent" ) );
97  extentNode.appendChild( xMin );
98  extentNode.appendChild( yMin );
99  extentNode.appendChild( xMax );
100  extentNode.appendChild( yMax );
101  return extentNode;
102 }
103 
104 QDomElement QgsXmlUtils::writeVariant( const QVariant &value, QDomDocument &doc )
105 {
106  QDomElement element = doc.createElement( QStringLiteral( "Option" ) );
107  switch ( value.type() )
108  {
109  case QVariant::Invalid:
110  {
111  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "invalid" ) );
112  break;
113  }
114 
115  case QVariant::Map:
116  {
117  QVariantMap map = value.toMap();
118 
119  for ( auto option = map.constBegin(); option != map.constEnd(); ++option )
120  {
121  QDomElement optionElement = writeVariant( option.value(), doc );
122  optionElement.setAttribute( QStringLiteral( "name" ), option.key() );
123  element.appendChild( optionElement );
124  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Map" ) );
125  }
126  break;
127  }
128 
129  case QVariant::List:
130  {
131  QVariantList list = value.toList();
132 
133  const auto constList = list;
134  for ( const QVariant &value : constList )
135  {
136  QDomElement valueElement = writeVariant( value, doc );
137  element.appendChild( valueElement );
138  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "List" ) );
139  }
140  break;
141  }
142 
143  case QVariant::StringList:
144  {
145  QStringList list = value.toStringList();
146 
147  const auto constList = list;
148  for ( const QString &value : constList )
149  {
150  QDomElement valueElement = writeVariant( value, doc );
151  element.appendChild( valueElement );
152  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "StringList" ) );
153  }
154  break;
155  }
156 
157  case QVariant::Int:
158  case QVariant::UInt:
159  case QVariant::Bool:
160  case QVariant::Double:
161  case QVariant::LongLong:
162  case QVariant::ULongLong:
163  case QVariant::String:
164  element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
165  element.setAttribute( QStringLiteral( "value" ), value.toString() );
166  break;
167 
168  case QVariant::Char:
169  element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) );
170  element.setAttribute( QStringLiteral( "value" ), value.isNull() ? QString() : value.toString() );
171  break;
172 
173  case QVariant::Color:
174  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "color" ) );
175  element.setAttribute( QStringLiteral( "value" ), value.value< QColor >().isValid() ? QgsSymbolLayerUtils::encodeColor( value.value< QColor >() ) : QString() );
176  break;
177 
178  case QVariant::UserType:
179  {
180  if ( value.canConvert< QgsProperty >() )
181  {
182  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsProperty" ) );
183  const QDomElement propertyElem = QgsXmlUtils::writeVariant( value.value< QgsProperty >().toVariant(), doc );
184  element.appendChild( propertyElem );
185  break;
186  }
187  else if ( value.canConvert< QgsCoordinateReferenceSystem >() )
188  {
189  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsCoordinateReferenceSystem" ) );
191  crs.writeXml( element, doc );
192  break;
193  }
194  else if ( value.canConvert< QgsGeometry >() )
195  {
196  element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "QgsGeometry" ) );
197  const QgsGeometry geom = value.value< QgsGeometry >();
198  element.setAttribute( QStringLiteral( "value" ), geom.asWkt() );
199  break;
200  }
202  }
203 
204  default:
205  Q_ASSERT_X( false, "QgsXmlUtils::writeVariant", QStringLiteral( "unsupported variant type %1" ).arg( QVariant::typeToName( value.type() ) ).toLocal8Bit() );
206  break;
207  }
208 
209  return element;
210 }
211 
212 QVariant QgsXmlUtils::readVariant( const QDomElement &element )
213 {
214  QString type = element.attribute( QStringLiteral( "type" ) );
215 
216  if ( type == QLatin1String( "invalid" ) )
217  {
218  return QVariant();
219  }
220  else if ( type == QLatin1String( "int" ) )
221  {
222  return element.attribute( QStringLiteral( "value" ) ).toInt();
223  }
224  else if ( type == QLatin1String( "uint" ) )
225  {
226  return element.attribute( QStringLiteral( "value" ) ).toUInt();
227  }
228  else if ( type == QLatin1String( "qlonglong" ) )
229  {
230  return element.attribute( QStringLiteral( "value" ) ).toLongLong();
231  }
232  else if ( type == QLatin1String( "qulonglong" ) )
233  {
234  return element.attribute( QStringLiteral( "value" ) ).toULongLong();
235  }
236  else if ( type == QLatin1String( "double" ) )
237  {
238  return element.attribute( QStringLiteral( "value" ) ).toDouble();
239  }
240  else if ( type == QLatin1String( "QString" ) )
241  {
242  return element.attribute( QStringLiteral( "value" ) );
243  }
244  else if ( type == QLatin1String( "QChar" ) )
245  {
246  const QString res = element.attribute( QStringLiteral( "value" ) );
247  return res.isEmpty() ? QChar() : res.at( 0 );
248  }
249  else if ( type == QLatin1String( "bool" ) )
250  {
251  return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" );
252  }
253  else if ( type == QLatin1String( "color" ) )
254  {
255  return element.attribute( QStringLiteral( "value" ) ).isEmpty() ? QColor() : QgsSymbolLayerUtils::decodeColor( element.attribute( QStringLiteral( "value" ) ) );
256  }
257  else if ( type == QLatin1String( "Map" ) )
258  {
259  QVariantMap map;
260  QDomNodeList options = element.childNodes();
261 
262  for ( int i = 0; i < options.count(); ++i )
263  {
264  QDomElement elem = options.at( i ).toElement();
265  if ( elem.tagName() == QLatin1String( "Option" ) )
266  map.insert( elem.attribute( QStringLiteral( "name" ) ), readVariant( elem ) );
267  }
268  return map;
269  }
270  else if ( type == QLatin1String( "List" ) )
271  {
272  QVariantList list;
273  QDomNodeList values = element.childNodes();
274  for ( int i = 0; i < values.count(); ++i )
275  {
276  QDomElement elem = values.at( i ).toElement();
277  list.append( readVariant( elem ) );
278  }
279  return list;
280  }
281  else if ( type == QLatin1String( "StringList" ) )
282  {
283  QStringList list;
284  QDomNodeList values = element.childNodes();
285  for ( int i = 0; i < values.count(); ++i )
286  {
287  QDomElement elem = values.at( i ).toElement();
288  list.append( readVariant( elem ).toString() );
289  }
290  return list;
291  }
292  else if ( type == QLatin1String( "QgsProperty" ) )
293  {
294  const QDomNodeList values = element.childNodes();
295  if ( values.isEmpty() )
296  return QVariant();
297 
298  QgsProperty p;
299  if ( p.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ) ) )
300  return p;
301 
302  return QVariant();
303  }
304  else if ( type == QLatin1String( "QgsCoordinateReferenceSystem" ) )
305  {
307  crs.readXml( element );
308  return crs;
309  }
310  else if ( type == QLatin1String( "QgsGeometry" ) )
311  {
312  return QgsGeometry::fromWkt( element.attribute( "value" ) );
313  }
314  else
315  {
316  return QVariant();
317  }
318 }
A rectangle specified with double values.
Definition: qgsrectangle.h:41
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:135
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc)
Definition: qgsxmlutils.cpp:79
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
static Q_INVOKABLE QgsUnitTypes::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
const QgsCoordinateReferenceSystem & crs
static QString encodeColor(const QColor &color)
QVariant toVariant() const
Saves this property to a QVariantMap, wrapped in a QVariant.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
#define FALLTHROUGH
Definition: qgis.h:763
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
static QgsUnitTypes::DistanceUnit readMapUnits(const QDomElement &element)
Decodes a distance unit from a DOM element.
Definition: qgsxmlutils.cpp:24
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:275
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:140
static QDomElement writeMapUnits(QgsUnitTypes::DistanceUnit units, QDomDocument &doc)
Encodes a distance unit to a DOM element.
Definition: qgsxmlutils.cpp:67
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:74
A store for object properties.
Definition: qgsproperty.h:229
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QString asWkt(int precision=17) const
Exports the geometry to WKT.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:66
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
Unknown distance unit.
Definition: qgsunittypes.h:77
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:145
This class represents a coordinate reference system (CRS).
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:37
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:130
static QColor decodeColor(const QString &str)