QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgslayermetadata.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayermetadata.cpp
3  --------------------
4  begin : April 2017
5  copyright : (C) 2017 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslayermetadata.h"
19 #include "qgsmaplayer.h"
20 
22 {
23  return new QgsLayerMetadata( *this );
24 }
25 
26 QString QgsLayerMetadata::fees() const
27 {
28  return mFees;
29 }
30 
31 void QgsLayerMetadata::setFees( const QString &fees )
32 {
33  mFees = fees;
34 }
35 
37 {
38  mConstraints << constraint;
39 }
40 
41 QList<QgsLayerMetadata::Constraint> QgsLayerMetadata::constraints() const
42 {
43  return mConstraints;
44 }
45 
46 void QgsLayerMetadata::setConstraints( const QList<Constraint> &constraints )
47 {
48  mConstraints = constraints;
49 }
50 
51 QStringList QgsLayerMetadata::rights() const
52 {
53  return mRights;
54 }
55 
56 void QgsLayerMetadata::setRights( const QStringList &rights )
57 {
58  mRights = rights;
59 }
60 
61 QStringList QgsLayerMetadata::licenses() const
62 {
63  return mLicenses;
64 }
65 
66 void QgsLayerMetadata::setLicenses( const QStringList &licenses )
67 {
68  mLicenses = licenses;
69 }
70 
72 {
73  return mEncoding;
74 }
75 
76 void QgsLayerMetadata::setEncoding( const QString &encoding )
77 {
78  mEncoding = encoding;
79 }
80 
82 {
83  return mCrs;
84 }
85 
87 {
88  mCrs = crs;
89 }
90 
92 {
93  layer->setCustomProperty( QStringLiteral( "metadata/identifier" ), mIdentifier );
94  layer->setCustomProperty( QStringLiteral( "metadata/parentIdentifier" ), mParentIdentifier );
95  layer->setCustomProperty( QStringLiteral( "metadata/language" ), mLanguage );
96  layer->setCustomProperty( QStringLiteral( "metadata/type" ), mType );
97  layer->setCustomProperty( QStringLiteral( "metadata/title" ), mTitle );
98  layer->setCustomProperty( QStringLiteral( "metadata/extent" ), QVariant::fromValue( mExtent ) );
99  layer->setCustomProperty( QStringLiteral( "metadata/abstract" ), mAbstract );
100  layer->setCustomProperty( QStringLiteral( "metadata/fees" ), mFees );
101  layer->setCustomProperty( QStringLiteral( "metadata/rights" ), mRights );
102  layer->setCustomProperty( QStringLiteral( "metadata/licenses" ), mLicenses );
103  layer->setCustomProperty( QStringLiteral( "metadata/history" ), mHistory );
104  layer->setCustomProperty( QStringLiteral( "metadata/encoding" ), mEncoding );
105  layer->setCustomProperty( QStringLiteral( "metadata/crs" ), mCrs.authid() );
106  layer->setCustomProperty( QStringLiteral( "metadata/constraints" ), QVariant::fromValue( mConstraints ) );
107  layer->setCustomProperty( QStringLiteral( "metadata/keywords" ), QVariant::fromValue( mKeywords ) );
108  layer->setCustomProperty( QStringLiteral( "metadata/contacts" ), QVariant::fromValue( mContacts ) );
109  layer->setCustomProperty( QStringLiteral( "metadata/links" ), QVariant::fromValue( mLinks ) );
110 }
111 
113 {
114  mIdentifier = layer->customProperty( QStringLiteral( "metadata/identifier" ) ).toString();
115  mParentIdentifier = layer->customProperty( QStringLiteral( "metadata/parentIdentifier" ) ).toString();
116  mLanguage = layer->customProperty( QStringLiteral( "metadata/language" ) ).toString();
117  mType = layer->customProperty( QStringLiteral( "metadata/type" ) ).toString();
118  mTitle = layer->customProperty( QStringLiteral( "metadata/title" ) ).toString();
119  mAbstract = layer->customProperty( QStringLiteral( "metadata/abstract" ) ).toString();
120  mFees = layer->customProperty( QStringLiteral( "metadata/fees" ) ).toString();
121  mRights = layer->customProperty( QStringLiteral( "metadata/rights" ) ).toStringList();
122  mLicenses = layer->customProperty( QStringLiteral( "metadata/licenses" ) ).toStringList();
123  mHistory = layer->customProperty( QStringLiteral( "metadata/history" ) ).toStringList();
124  mEncoding = layer->customProperty( QStringLiteral( "metadata/encoding" ) ).toString();
125  QString crsAuthId = layer->customProperty( QStringLiteral( "metadata/crs" ) ).toString();
127  mExtent = layer->customProperty( QStringLiteral( "metadata/extent" ) ).value<Extent>();
128  mConstraints = layer->customProperty( QStringLiteral( "metadata/constraints" ) ).value<ConstraintList>();
129  mKeywords = layer->customProperty( QStringLiteral( "metadata/keywords" ) ).value<QgsAbstractMetadataBase::KeywordMap>();
130  mContacts = layer->customProperty( QStringLiteral( "metadata/contacts" ) ).value<QgsAbstractMetadataBase::ContactList>();
131  mLinks = layer->customProperty( QStringLiteral( "metadata/links" ) ).value<QgsAbstractMetadataBase::LinkList>();
132 }
133 
134 bool QgsLayerMetadata::readMetadataXml( const QDomElement &metadataElement )
135 {
136  QgsAbstractMetadataBase::readMetadataXml( metadataElement );
137 
138  QDomNode mnl;
139  QDomElement mne;
140 
141  // set fees
142  mnl = metadataElement.namedItem( QStringLiteral( "fees" ) );
143  mFees = mnl.toElement().text();
144 
145  // constraints
146  QDomNodeList constraintsList = metadataElement.elementsByTagName( QStringLiteral( "constraints" ) );
147  mConstraints.clear();
148  for ( int i = 0; i < constraintsList.size(); i++ )
149  {
150  mnl = constraintsList.at( i );
151  mne = mnl.toElement();
152  addConstraint( QgsLayerMetadata::Constraint( mne.text(), mne.attribute( QStringLiteral( "type" ) ) ) );
153  }
154 
155  // rights
156  QDomNodeList rightsNodeList = metadataElement.elementsByTagName( QStringLiteral( "rights" ) );
157  QStringList rightsList;
158  for ( int i = 0; i < rightsNodeList.size(); i++ )
159  {
160  mnl = rightsNodeList.at( i );
161  mne = mnl.toElement();
162  rightsList.append( mne.text() );
163  }
164  setRights( rightsList );
165 
166  // licenses
167  QDomNodeList licensesNodeList = metadataElement.elementsByTagName( QStringLiteral( "license" ) );
168  QStringList licensesList;
169  for ( int i = 0; i < licensesNodeList.size(); i++ )
170  {
171  mnl = licensesNodeList.at( i );
172  mne = mnl.toElement();
173  licensesList.append( mne.text() );
174  }
175  setLicenses( licensesList );
176 
177  // encoding
178  mnl = metadataElement.namedItem( QStringLiteral( "encoding" ) );
179  mEncoding = mnl.toElement().text();
180 
181  // crs
182  mnl = metadataElement.namedItem( QStringLiteral( "crs" ) );
183  if ( !mCrs.readXml( mnl ) )
185 
186  // extent
187  mnl = metadataElement.namedItem( QStringLiteral( "extent" ) );
188  QgsLayerMetadata::Extent metadataExtent;
189 
190  // spatial extent
191  QDomNodeList spatialList = mnl.toElement().elementsByTagName( QStringLiteral( "spatial" ) );
192  QList< QgsLayerMetadata::SpatialExtent > metadataSpatialExtents;
193  for ( int i = 0; i < spatialList.size(); i++ )
194  {
195  mnl = spatialList.at( i );
196  mne = mnl.toElement();
198  se.extentCrs = QgsCoordinateReferenceSystem( mne.attribute( QStringLiteral( "crs" ) ) );
199  se.bounds = QgsBox3d();
200  se.bounds.setXMinimum( mne.attribute( QStringLiteral( "minx" ) ).toDouble() );
201  se.bounds.setYMinimum( mne.attribute( QStringLiteral( "miny" ) ).toDouble() );
202  se.bounds.setZMinimum( mne.attribute( QStringLiteral( "minz" ) ).toDouble() );
203  se.bounds.setXMaximum( mne.attribute( QStringLiteral( "maxx" ) ).toDouble() );
204  se.bounds.setYMaximum( mne.attribute( QStringLiteral( "maxy" ) ).toDouble() );
205  se.bounds.setZMaximum( mne.attribute( QStringLiteral( "maxz" ) ).toDouble() );
206  metadataSpatialExtents.append( se );
207  }
208  metadataExtent.setSpatialExtents( metadataSpatialExtents );
209 
210  // temporal extent
211  mnl = metadataElement.namedItem( QStringLiteral( "extent" ) );
212  QDomNodeList temporalList = mnl.toElement().elementsByTagName( QStringLiteral( "temporal" ) );
213  QList<QgsDateTimeRange> metadataDates;
214  for ( int j = 0; j < temporalList.size(); j++ )
215  {
216  mnl = temporalList.at( j );
217  QDomNodeList instantList = mnl.toElement().elementsByTagName( QStringLiteral( "instant" ) );
218  for ( int i = 0; i < instantList.size(); i++ )
219  {
220  mnl = instantList.at( i );
221  QDateTime d = QDateTime().fromString( mnl.toElement().text(), Qt::ISODate );
222  QgsDateTimeRange date = QgsDateTimeRange( d, d );
223  metadataDates << date;
224  }
225  QDomNodeList periodList = mnl.toElement().elementsByTagName( QStringLiteral( "period" ) );
226  for ( int i = 0; i < periodList.size(); i++ )
227  {
228  QDomNode begin = periodList.at( i ).namedItem( QStringLiteral( "start" ) );
229  QDomNode end = periodList.at( i ).namedItem( QStringLiteral( "end" ) );
230  QDateTime beginDate = QDateTime().fromString( begin.toElement().text(), Qt::ISODate );
231  QDateTime endDate = QDateTime().fromString( end.toElement().text(), Qt::ISODate );
232  QgsDateTimeRange date = QgsDateTimeRange( beginDate, endDate );
233  metadataDates << date;
234  }
235  }
236  metadataExtent.setTemporalExtents( metadataDates );
237  setExtent( metadataExtent );
238 
239  return true;
240 }
241 
242 bool QgsLayerMetadata::writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const
243 {
244  QgsAbstractMetadataBase::writeMetadataXml( metadataElement, document );
245 
246  // fees
247  QDomElement fees = document.createElement( QStringLiteral( "fees" ) );
248  QDomText feesText = document.createTextNode( mFees );
249  fees.appendChild( feesText );
250  metadataElement.appendChild( fees );
251 
252  // constraints
253  for ( const QgsLayerMetadata::Constraint &constraint : mConstraints )
254  {
255  QDomElement constraintElement = document.createElement( QStringLiteral( "constraints" ) );
256  constraintElement.setAttribute( QStringLiteral( "type" ), constraint.type );
257  QDomText constraintText = document.createTextNode( constraint.constraint );
258  constraintElement.appendChild( constraintText );
259  metadataElement.appendChild( constraintElement );
260  }
261 
262  // rights
263  for ( const QString &right : mRights )
264  {
265  QDomElement rightElement = document.createElement( QStringLiteral( "rights" ) );
266  QDomText rightText = document.createTextNode( right );
267  rightElement.appendChild( rightText );
268  metadataElement.appendChild( rightElement );
269  }
270 
271  // license
272  for ( const QString &license : mLicenses )
273  {
274  QDomElement licenseElement = document.createElement( QStringLiteral( "license" ) );
275  QDomText licenseText = document.createTextNode( license );
276  licenseElement.appendChild( licenseText );
277  metadataElement.appendChild( licenseElement );
278  }
279 
280  // encoding
281  QDomElement encoding = document.createElement( QStringLiteral( "encoding" ) );
282  QDomText encodingText = document.createTextNode( mEncoding );
283  encoding.appendChild( encodingText );
284  metadataElement.appendChild( encoding );
285 
286  // crs
287  QDomElement crsElement = document.createElement( QStringLiteral( "crs" ) );
288  mCrs.writeXml( crsElement, document );
289  metadataElement.appendChild( crsElement );
290 
291  // extent
292  QDomElement extentElement = document.createElement( QStringLiteral( "extent" ) );
293 
294  // spatial extents
295  const QList< QgsLayerMetadata::SpatialExtent > sExtents = extent().spatialExtents();
296  for ( const QgsLayerMetadata::SpatialExtent &spatialExtent : sExtents )
297  {
298  QDomElement spatialElement = document.createElement( QStringLiteral( "spatial" ) );
299  // Dimensions fixed in the XSD
300  spatialElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) );
301  spatialElement.setAttribute( QStringLiteral( "crs" ), spatialExtent.extentCrs.authid() );
302  spatialElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( spatialExtent.bounds.xMinimum() ) );
303  spatialElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( spatialExtent.bounds.yMinimum() ) );
304  spatialElement.setAttribute( QStringLiteral( "minz" ), qgsDoubleToString( spatialExtent.bounds.zMinimum() ) );
305  spatialElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( spatialExtent.bounds.xMaximum() ) );
306  spatialElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( spatialExtent.bounds.yMaximum() ) );
307  spatialElement.setAttribute( QStringLiteral( "maxz" ), qgsDoubleToString( spatialExtent.bounds.zMaximum() ) );
308  extentElement.appendChild( spatialElement );
309  }
310 
311  // temporal extents
312  const QList< QgsDateTimeRange > tExtents = extent().temporalExtents();
313  for ( const QgsDateTimeRange &temporalExtent : tExtents )
314  {
315  QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
316  if ( temporalExtent.isInstant() )
317  {
318  QDomElement instantElement = document.createElement( QStringLiteral( "instant" ) );
319  QDomText instantText = document.createTextNode( temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
320  instantElement.appendChild( instantText );
321  temporalElement.appendChild( instantElement );
322  }
323  else
324  {
325  QDomElement periodElement = document.createElement( QStringLiteral( "period" ) );
326  QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
327  QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
328  QDomText startText = document.createTextNode( temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
329  QDomText endText = document.createTextNode( temporalExtent.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
330  startElement.appendChild( startText );
331  endElement.appendChild( endText );
332  periodElement.appendChild( startElement );
333  periodElement.appendChild( endElement );
334  temporalElement.appendChild( periodElement );
335  }
336  extentElement.appendChild( temporalElement );
337  }
338 
339  metadataElement.appendChild( extentElement );
340 
341  return true;
342 }
343 
345 {
347 
348  if ( const QgsLayerMetadata *otherLayerMetadata = dynamic_cast< const QgsLayerMetadata * >( other ) )
349  {
350  if ( !otherLayerMetadata->fees().isEmpty() )
351  mFees = otherLayerMetadata->fees();
352 
353  if ( !otherLayerMetadata->constraints().isEmpty() )
354  mConstraints = otherLayerMetadata->constraints();
355 
356  if ( !otherLayerMetadata->rights().isEmpty() )
357  mRights = otherLayerMetadata->rights();
358 
359  if ( !otherLayerMetadata->licenses().isEmpty() )
360  mLicenses = otherLayerMetadata->licenses();
361 
362  if ( !otherLayerMetadata->encoding().isEmpty() )
363  mEncoding = otherLayerMetadata->encoding();
364 
365  if ( otherLayerMetadata->crs().isValid() )
366  mCrs = otherLayerMetadata->crs();
367 
368  if ( !otherLayerMetadata->extent().spatialExtents().isEmpty() )
369  mExtent.setSpatialExtents( otherLayerMetadata->extent().spatialExtents() );
370 
371  if ( !otherLayerMetadata->extent().temporalExtents().isEmpty() )
372  mExtent.setTemporalExtents( otherLayerMetadata->extent().temporalExtents() );
373  }
374 }
375 
377 {
378  return mExtent;
379 }
380 
382 {
383  return mExtent;
384 }
385 
386 void QgsLayerMetadata::setExtent( const Extent &extent )
387 {
388  mExtent = extent;
389 }
390 
391 QList<QgsLayerMetadata::SpatialExtent> QgsLayerMetadata::Extent::spatialExtents() const
392 {
393  return mSpatialExtents;
394 }
395 
396 void QgsLayerMetadata::Extent::setSpatialExtents( const QList<QgsLayerMetadata::SpatialExtent> &spatialExtents )
397 {
398  mSpatialExtents = spatialExtents;
399 }
400 
401 QList<QgsDateTimeRange> QgsLayerMetadata::Extent::temporalExtents() const
402 {
403  return mTemporalExtents;
404 }
405 
406 void QgsLayerMetadata::Extent::setTemporalExtents( const QList<QgsDateTimeRange> &temporalExtents )
407 {
408  mTemporalExtents = temporalExtents;
409 }
410 
412 {
413  return mSpatialExtents == other.mSpatialExtents && mTemporalExtents == other.mTemporalExtents;
414 }
415 
417 {
418  return equals( other ) &&
419  mFees == other.mFees &&
420  mConstraints == other.mConstraints &&
421  mRights == other.mRights &&
422  mLicenses == other.mLicenses &&
423  mEncoding == other.mEncoding &&
424  mCrs == other.mCrs &&
425  mExtent == other.mExtent;
426 }
427 
429 {
430  return extentCrs == other.extentCrs &&
431  bounds == other.bounds;
432 }
433 
435 {
436  return type == other.type && constraint == other.constraint;
437 }
An abstract base class for metadata stores.
QgsAbstractMetadataBase::ContactList mContacts
virtual bool writeMetadataXml(QDomElement &metadataElement, QDomDocument &document) const
Stores state in a DOM node.
virtual void combine(const QgsAbstractMetadataBase *other)
Combines the metadata from this object with the metadata from an other object.
QgsAbstractMetadataBase::KeywordMap mKeywords
Keywords map.
bool equals(const QgsAbstractMetadataBase &other) const
Tests whether the common metadata fields in this object are equal to other.
virtual bool readMetadataXml(const QDomElement &metadataElement)
Sets state from DOM document.
QgsAbstractMetadataBase::LinkList mLinks
QString type() const
Returns the nature of the resource.
A 3-dimensional box composed of x, y, z coordinates.
Definition: qgsbox3d.h:39
void setXMaximum(double x) SIP_HOLDGIL
Sets the maximum x value.
Definition: qgsbox3d.cpp:44
void setYMaximum(double y) SIP_HOLDGIL
Sets the maximum y value.
Definition: qgsbox3d.cpp:54
void setZMinimum(double z) SIP_HOLDGIL
Sets the minimum z value.
Definition: qgsbox3d.cpp:59
void setZMaximum(double z) SIP_HOLDGIL
Sets the maximum z value.
Definition: qgsbox3d.cpp:64
void setYMinimum(double y) SIP_HOLDGIL
Sets the minimum y value.
Definition: qgsbox3d.cpp:49
void setXMinimum(double x) SIP_HOLDGIL
Sets the minimum x value.
Definition: qgsbox3d.cpp:39
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
QString authid() const
Returns the authority identifier for the CRS.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
A structured metadata store for a map layer.
void addConstraint(const QgsLayerMetadata::Constraint &constraint)
Adds an individual constraint to the existing constraints.
const QgsLayerMetadata::Extent & extent() const
Returns the spatial and temporal extents associated with the resource.
void setConstraints(const QgsLayerMetadata::ConstraintList &constraints)
Sets the list of constraints associated with using the resource.
QgsLayerMetadata()=default
Constructor for QgsLayerMetadata.
void setFees(const QString &fees)
Sets the fees associated with using the resource.
void setLicenses(const QStringList &licenses)
Sets a list of licenses associated with the resource.
bool operator==(const QgsLayerMetadata &metadataOther) const
QgsLayerMetadata::ConstraintList constraints() const
Returns a list of constraints associated with using the resource.
void setRights(const QStringList &rights)
Sets a list of rights (attribution or copyright strings) associated with the resource.
QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system described by the layer's metadata.
void setEncoding(const QString &encoding)
Sets the character encoding of the data in the resource.
QString encoding() const
Returns the character encoding of the data in the resource.
void combine(const QgsAbstractMetadataBase *other) override
Combines the metadata from this object with the metadata from an other object.
QStringList licenses() const
Returns a list of licenses associated with the resource (examples: http://opendefinition....
bool readMetadataXml(const QDomElement &metadataElement) override
Sets state from DOM document.
void readFromLayer(const QgsMapLayer *layer)
Reads the metadata state from a layer's custom properties (see QgsMapLayer::customProperty() ).
void saveToLayer(QgsMapLayer *layer) const
Saves the metadata to a layer's custom properties (see QgsMapLayer::setCustomProperty() ).
QStringList rights() const
Returns a list of attribution or copyright strings associated with the resource.
QgsLayerMetadata * clone() const override
Clones the metadata object.
void setExtent(const QgsLayerMetadata::Extent &extent)
Sets the spatial and temporal extents associated with the resource.
bool writeMetadataXml(QDomElement &metadataElement, QDomDocument &document) const override
Stores state in a DOM node.
QString fees() const
Returns any fees associated with using the resource.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the coordinate reference system for the layer's metadata.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:550
const QgsCoordinateReferenceSystem & crs
Metadata constraint structure.
bool operator==(const QgsLayerMetadata::Constraint &other) const
QString constraint
Free-form constraint string.
QString type
Constraint type.
Metadata extent structure.
QList< QgsLayerMetadata::SpatialExtent > spatialExtents() const
Spatial extents of the resource.
void setSpatialExtents(const QList< QgsLayerMetadata::SpatialExtent > &extents)
Sets the spatial extents of the resource.
bool operator==(const QgsLayerMetadata::Extent &other) const
void setTemporalExtents(const QList< QgsDateTimeRange > &extents)
Sets the temporal extents of the resource.
QList< QgsDateTimeRange > temporalExtents() const
Temporal extents of the resource.
Metadata spatial extent structure.
QgsCoordinateReferenceSystem extentCrs
Coordinate reference system for spatial extent.
bool operator==(const QgsLayerMetadata::SpatialExtent &other) const
QgsBox3d bounds
Geospatial extent of the resource.