1 /***************************************************************************
2                              qgscoordinatereferencesystemregistry.h
3                              -------------------
4     begin                : January 2021
5     copyright            : (C) 2021 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 QGSCOORDINATEREFERENCESYSTEMREGISTRY_H
19 #define QGSCOORDINATEREFERENCESYSTEMREGISTRY_H
20 
21 #include <QObject>
22 #include <QMap>
23 #include "qgscoordinatereferencesystem.h"
24 
25 class QgsCelestialBody;
26 class QgsProjOperation;
27 
28 /**
29  * \class QgsCoordinateReferenceSystemRegistry
30  * \ingroup core
31  * \brief A registry for known coordinate reference system (CRS) definitions, including
32  * any user-defined CRSes.
33  *
34  * QgsCoordinateReferenceSystemRegistry is not usually directly created, but rather accessed through
35  * QgsApplication::coordinateReferenceSystemRegistry().
36  *
37  * \since QGIS 3.18
38  */
39 class CORE_EXPORT QgsCoordinateReferenceSystemRegistry : public QObject
40 {
41     Q_OBJECT
42   public:
43 
44     /**
45      * Constructor for QgsCoordinateReferenceSystemRegistry, with the specified \a parent object.
46      */
47     explicit QgsCoordinateReferenceSystemRegistry( QObject *parent = nullptr );
48 
49     ~QgsCoordinateReferenceSystemRegistry();
50 
51     /**
52      * \brief Contains details of a custom (user defined) CRS.
53      * \ingroup core
54      * \since QGIS 3.18
55      */
56     class UserCrsDetails
57     {
58       public:
59 
60         //! CRS ID
61         long id = -1;
62 
63         //! CRS name (or description)
64         QString name;
65 
66         //! PROJ string definition of CRS
67         QString proj;
68 
69         /**
70          * WKT definition of CRS. This will be empty for custom CRSes
71          * which were defined using a PROJ string only.
72          */
73         QString wkt;
74 
75         //! QgsCoordinateReferenceSystem object representing the user-defined CRS.
76         QgsCoordinateReferenceSystem crs;
77     };
78 
79     /**
80      * Returns a list containing the details of all registered
81      * custom (user-defined) CRSes.
82      */
83     QList< QgsCoordinateReferenceSystemRegistry::UserCrsDetails > userCrsList() const;
84 
85     /**
86      * Adds a new \a crs definition as a custom ("USER") CRS.
87      *
88      * Returns the new CRS srsid(), or -1 if the CRS could not be saved.
89      *
90      * The \a nativeFormat argument specifies the format to use when saving the CRS
91      * definition. FormatWkt is recommended as it is a lossless format.
92      *
93      * \warning Not all CRS definitions can be represented as a Proj string, so
94      * take care when using the FormatProj option.
95      *
96      * \see updateUserCrs()
97      * \see userCrsAdded()
98      */
99     long addUserCrs( const QgsCoordinateReferenceSystem &crs, const QString &name, QgsCoordinateReferenceSystem::Format nativeFormat = QgsCoordinateReferenceSystem::FormatWkt );
100 
101     /**
102      * Updates the definition of the existing user CRS with matching \a id.
103      *
104      * The \a crs argument specifies a CRS with the desired new definition.
105      *
106      * Returns FALSE if the new CRS definition could not be saved.
107      *
108      * The \a nativeFormat argument specifies the format to use when saving the CRS
109      * definition. FormatWkt is recommended as it is a lossless format.
110      *
111      * \warning Not all CRS definitions can be represented as a Proj string, so
112      * take care when using the FormatProj option.
113      *
114      * \see addUserCrs()
115      * \see userCrsChanged()
116      */
117     bool updateUserCrs( long id, const QgsCoordinateReferenceSystem &crs, const QString &name, QgsCoordinateReferenceSystem::Format nativeFormat = QgsCoordinateReferenceSystem::FormatWkt );
118 
119     /**
120      * Removes the existing user CRS with matching \a id.
121      *
122      * Returns FALSE if the CRS could not be removed.
123      *
124      * \see userCrsRemoved()
125      */
126     bool removeUserCrs( long id );
127 
128     /**
129      * Returns a map of all valid PROJ operations.
130      *
131      * The map keys correspond to PROJ operation IDs.
132      *
133      * \since QGIS 3.20
134      */
135     QMap< QString, QgsProjOperation > projOperations() const;
136 
137     /**
138      * Returns a list of all known celestial bodies.
139      *
140      * \warning This method requires PROJ 8.1 or later
141      *
142      * \throws QgsNotSupportedException on QGIS builds based on PROJ 8.0 or earlier.
143      *
144      * \since QGIS 3.20
145      */
146     QList< QgsCelestialBody > celestialBodies() const;
147 
148   signals:
149 
150     /**
151      * Emitted whenever an existing user CRS definition is changed.
152      *
153      * The \a id argument specifies the ID of the user CRS which has been changed.
154      *
155      * Objects which store QgsCoordinateReferenceSystem members should connect to this signal
156      * and update any stored CRS definitions to ensure that they always use the current
157      * definition of any user defined CRSes.
158      *
159      * \see crsDefinitionsChanged()
160      * \see userCrsAdded()
161      */
162     void userCrsChanged( const QString &id );
163 
164     /**
165      * Emitted whenever a new user CRS definition is added.
166      *
167      * The \a id argument specifies the ID of the user CRS which has been changed.
168      *
169      * \see userCrsChanged()
170      * \see crsDefinitionsChanged()
171      */
172     void userCrsAdded( const QString &id );
173 
174     /**
175      * Emitted when the user CRS with matching \a id is removed
176      * from the database.
177      *
178      * \see removeUserCrs()
179      */
180     void userCrsRemoved( long id );
181 
182     /**
183      * Emitted whenever an operation has caused any of the known CRS definitions (including
184      * user-defined CRS) to change.
185      */
186     void crsDefinitionsChanged();
187 
188   private:
189 
190     bool insertProjection( const QString &projectionAcronym );
191 
192     mutable QList< QgsCelestialBody > mCelestialBodies;
193     mutable QMap< QString, QgsProjOperation > mProjOperations;
194 
195 };
196 
197 
198 #endif // QGSCOORDINATEREFERENCESYSTEMREGISTRY_H
199