1 /***************************************************************************
2                              qgslayermetadata.h
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 #ifndef QGSLAYERMETADATA_H
19 #define QGSLAYERMETADATA_H
20 
21 #include "qgis_sip.h"
22 #include "qgis_core.h"
23 #include "qgscoordinatereferencesystem.h"
24 #include "qgsbox3d.h"
25 #include "qgsrange.h"
26 #include "qgsabstractmetadatabase.h"
27 
28 class QgsMapLayer;
29 
30 /**
31  * \ingroup core
32  * \class QgsLayerMetadata
33  * \brief A structured metadata store for a map layer.
34  *
35  * QgsLayerMetadata handles storage and management of the metadata
36  * for a QgsMapLayer. This class is an internal QGIS format with a common
37  * metadata structure, which allows for code to access the metadata properties for
38  * layers in a uniform way.
39  *
40  * The metadata store is designed to be compatible with the Dublin Core metadata
41  * specifications, and will be expanded to allow compatibility with ISO specifications
42  * in future releases. However, the QGIS internal schema does not represent a superset
43  * of all existing metadata schemas and accordingly conversion from specific
44  * metadata formats to QgsLayerMetadata may result in a loss of information.
45  *
46  * This class is designed to follow the specifications detailed in
47  * the schema definition available at resources/qgis-resource-metadata.xsd
48  * within the QGIS source code.
49  *
50  * Metadata can be validated through the use of QgsLayerMetadataValidator
51  * subclasses. E.g. validating against the native QGIS metadata schema can be performed
52  * using QgsNativeMetadataValidator.
53  *
54  * \since QGIS 3.0
55  */
56 class CORE_EXPORT QgsLayerMetadata : public QgsAbstractMetadataBase
57 {
58   public:
59 
60     /**
61      * Metadata spatial extent structure.
62      */
63     struct CORE_EXPORT SpatialExtent
64     {
65 
66       /**
67        * Coordinate reference system for spatial extent.
68        * The CRS should match the CRS defined in the QgsLayerMetadata CRS property.
69        * \see QgsLayerMetadata::crs()
70        * \see spatial
71        */
72       QgsCoordinateReferenceSystem extentCrs;
73 
74       /**
75        * Geospatial extent of the resource. X and Y coordinates are in the
76        * CRS defined by the metadata (see extentCrs).
77        *
78        * While the spatial extent can include a Z dimension, this is not
79        * compulsory.
80        * \see extentCrs
81        */
82       QgsBox3d bounds;
83 
84       bool operator==( const QgsLayerMetadata::SpatialExtent &other ) const;
85     };
86 
87     /**
88      * Metadata extent structure.
89      */
90     struct CORE_EXPORT Extent
91     {
92       public:
93 
94         /**
95          * Spatial extents of the resource.
96          * \see setSpatialExtents()
97          */
98         QList< QgsLayerMetadata::SpatialExtent > spatialExtents() const;
99 
100         /**
101          * Sets the spatial \a extents of the resource.
102          * \see spatialExtents()
103          */
104         void setSpatialExtents( const QList< QgsLayerMetadata::SpatialExtent > &extents );
105 
106         /**
107          * Temporal extents of the resource. Use QgsDateTimeRange::isInstant() to determine
108          * whether the temporal extent is a range or a single point in time.
109          * If QgsDateTimeRange::isInfinite() returns TRUE then the temporal extent
110          * is considered to be indeterminate and continuous.
111          * \see setTemporalExtents()
112          */
113         QList< QgsDateTimeRange > temporalExtents() const;
114 
115         /**
116          * Sets the temporal \a extents of the resource.
117          * \see temporalExtents()
118          */
119         void setTemporalExtents( const QList< QgsDateTimeRange > &extents );
120 
121         bool operator==( const QgsLayerMetadata::Extent &other ) const;
122 
123 #ifndef SIP_RUN
124       private:
125 
126         QList< QgsLayerMetadata::SpatialExtent > mSpatialExtents;
127         QList< QgsDateTimeRange > mTemporalExtents;
128 
129 #endif
130 
131     };
132 
133     /**
134      * Metadata constraint structure.
135      */
136     struct CORE_EXPORT Constraint
137     {
138 
139       /**
140        * Constructor for Constraint.
141        */
142       Constraint( const QString &constraint = QString(), const QString &type = QString() )
typeConstraint143         : type( type )
144         , constraint( constraint )
145       {}
146 
147       /**
148        * Constraint type. Standard values include 'access' and 'other', however any
149        * string can be used for the type.
150        */
151       QString type;
152 
153       /**
154        * Free-form constraint string.
155        */
156       QString constraint;
157 
158       bool operator==( const QgsLayerMetadata::Constraint &other ) const;
159 
160     };
161 
162     /**
163      * A list of constraints.
164      */
165     typedef QList< QgsLayerMetadata::Constraint > ConstraintList;
166 
167     /**
168      * Constructor for QgsLayerMetadata.
169      */
170     QgsLayerMetadata() = default;
171 
172     QgsLayerMetadata *clone() const override SIP_FACTORY;
173 
174     /**
175      * Returns any fees associated with using the resource.
176      * An empty string will be returned if no fees are set.
177      * \see setFees()
178      */
179     QString fees() const;
180 
181     /**
182      * Sets the \a fees associated with using the resource.
183      * Use an empty string if no fees are set.
184      * \see fees()
185      */
186     void setFees( const QString &fees );
187 
188     /**
189      * Returns a list of constraints associated with using the resource.
190      * \see setConstraints()
191      */
192     QgsLayerMetadata::ConstraintList constraints() const;
193 
194     /**
195      * Adds an individual constraint to the existing constraints.
196      * \see constraints()
197      * \see setConstraints()
198      */
199     void addConstraint( const QgsLayerMetadata::Constraint &constraint );
200 
201     /**
202      * Sets the list of \a constraints associated with using the resource.
203      * \see constraints()
204      */
205     void setConstraints( const QgsLayerMetadata::ConstraintList &constraints );
206 
207     /**
208      * Returns a list of attribution or copyright strings associated with the resource.
209      * \see setRights()
210      */
211     QStringList rights() const;
212 
213     /**
214      * Sets a list of \a rights (attribution or copyright strings) associated with the resource.
215      * \see rights()
216      */
217     void setRights( const QStringList &rights );
218 
219     /**
220      * Returns a list of licenses associated with the resource (examples: http://opendefinition.org/licenses/).
221      * \see setLicenses()
222      */
223     QStringList licenses() const;
224 
225     /**
226      * Sets a list of \a licenses associated with the resource.
227      * (examples: http://opendefinition.org/licenses/).
228      * \see licenses()
229      */
230     void setLicenses( const QStringList &licenses );
231 
232     /**
233      * Returns the character encoding of the data in the resource. An empty string will be returned if no encoding is set.
234      * \see setEncoding()
235      */
236     QString encoding() const;
237 
238     /**
239      * Sets the character \a encoding of the data in the resource. Use an empty string if no encoding is set.
240      * \see encoding()
241      */
242     void setEncoding( const QString &encoding );
243 
244     /**
245      * Returns the spatial and temporal extents associated with the resource.
246      * \see setExtent()
247      */
248     SIP_SKIP const QgsLayerMetadata::Extent &extent() const;
249 
250     /**
251      * Returns the spatial and temporal extents associated with the resource.
252      * \see setExtent()
253      */
254     QgsLayerMetadata::Extent &extent();
255 
256     /**
257      * Sets the spatial and temporal extents associated with the resource.
258      * \see setExtent()
259      */
260     void setExtent( const QgsLayerMetadata::Extent &extent );
261 
262     /**
263      * Returns the coordinate reference system described by the layer's metadata.
264      *
265      * Note that this has no link to QgsMapLayer::crs(). While in most cases these
266      * two systems are likely to be identical, it is possible to have a layer
267      * with a different CRS described by it's accompanying metadata versus the
268      * CRS which is actually used to display and manipulate the layer within QGIS.
269      * This may be the case when a layer has an incorrect CRS within its metadata
270      * and a user has manually overridden the layer's CRS within QGIS.
271      *
272      * The CRS described here should either match the CRS from the layer QgsMapLayer::crs()
273      * or the CRS from the data provider.
274      *
275      * This property should also match the CRS property used in the spatial extent.
276      *
277      * \see setCrs()
278      */
279     QgsCoordinateReferenceSystem crs() const;
280 
281     /**
282      * Sets the coordinate reference system for the layer's metadata.
283      *
284      * Note that this has no link to QgsMapLayer::setCrs(). Setting the layer's
285      * CRS via QgsMapLayer::setCrs() does not affect the layer's metadata CRS,
286      * and changing the CRS from the metadata will not change the layer's
287      * CRS or how it is projected within QGIS.
288      *
289      * While ideally these two systems are likely to be identical, it is possible to have a layer
290      * with a different CRS described by it's accompanying metadata versus the
291      * CRS which is actually used to display and manipulate the layer within QGIS.
292      * This may be the case when a layer has an incorrect CRS within its metadata
293      * and a user has manually overridden the layer's CRS within QGIS.
294      *
295      * The CRS described here should either match the CRS from the layer QgsMapLayer::crs()
296      * or the CRS from the data provider.
297      *
298      * This property should also match the CRS property used in the spatial extent.
299      *
300      * \see crs()
301      */
302     void setCrs( const QgsCoordinateReferenceSystem &crs );
303 
304     /**
305      * Saves the metadata to a \a layer's custom properties (see QgsMapLayer::setCustomProperty() ).
306      * \see readFromLayer()
307      */
308     void saveToLayer( QgsMapLayer *layer ) const;
309 
310     /**
311      * Reads the metadata state from a \a layer's custom properties (see QgsMapLayer::customProperty() ).
312      * \see saveToLayer()
313      */
314     void readFromLayer( const QgsMapLayer *layer );
315 
316     bool readMetadataXml( const QDomElement &metadataElement ) override;
317     bool writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const override;
318 
319     bool operator==( const QgsLayerMetadata &metadataOther ) const;
320 
321   private:
322 
323     /*
324      * IMPORTANT!!!!!!
325      *
326      * Do NOT add anything to this class without also updating the schema
327      * definition located at resources/qgis-resource-metadata.xsd
328      *
329      */
330 
331     QString mFees;
332     ConstraintList mConstraints;
333     QStringList mRights;
334     QStringList mLicenses;
335 
336     // IMPORTANT - look up before adding anything here!!
337 
338     QString mEncoding;
339     QgsCoordinateReferenceSystem mCrs;
340 
341     Extent mExtent;
342 
343     /*
344      * IMPORTANT!!!!!!
345      *
346      * Do NOT add anything to this class without also updating the schema
347      * definition located at resources/qgis-resource-metadata.xsd
348      *
349      */
350 
351 };
352 
353 Q_DECLARE_METATYPE( QgsLayerMetadata::ConstraintList )
354 Q_DECLARE_METATYPE( QgsLayerMetadata::Extent )
355 
356 #endif // QGSLAYERMETADATA_H
357