QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgscoordinatereferencesystemregistry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscoordinatereferencesystemregistry.cpp
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
19
20#include <mutex>
21#include <proj.h>
22#include <sqlite3.h>
23
24#include "qgsapplication.h"
25#include "qgscelestialbody.h"
28#include "qgsexception.h"
29#include "qgslogger.h"
30#include "qgsmessagelog.h"
31#include "qgsprojoperation.h"
32#include "qgsprojutils.h"
33#include "qgsruntimeprofiler.h"
35#include "qgssettingstree.h"
36#include "qgssqliteutils.h"
37
38#include <QFileInfo>
39#include <QString>
40
41#include "moc_qgscoordinatereferencesystemregistry.cpp"
42
43using namespace Qt::StringLiterals;
44
46 = new QgsSettingsEntryStringList( u"recent-projections-auth-id"_s, QgsSettingsTree::sTreeCrs, QStringList(), u"Authority identifiers (e.g. \"EPSG:4326\") of the most recently used coordinate reference systems."_s );
48 = new QgsSettingsEntryStringList( u"recent-projections-wkt"_s, QgsSettingsTree::sTreeCrs, QStringList(), u"WKT definitions of the most recently used coordinate reference systems, kept in sync with the corresponding authority identifier list."_s );
50 = new QgsSettingsEntryStringList( u"recent-projections-proj4"_s, QgsSettingsTree::sTreeCrs, QStringList(), u"PROJ.4 strings of the most recently used coordinate reference systems, kept in sync with the corresponding authority identifier list."_s );
51
55
57
58QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> QgsCoordinateReferenceSystemRegistry::userCrsList() const
59{
60 QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> res;
61
62 //Setup connection to the existing custom CRS database:
64 //check the db is available
65 int result = database.open_v2( QgsApplication::qgisUserDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr );
66 if ( result != SQLITE_OK )
67 {
68 QgsDebugError( u"Can't open database: %1"_s.arg( database.errorMessage() ) );
69 return res;
70 }
71
72 const QString sql = u"select srs_id,description,parameters, wkt from tbl_srs"_s;
73 QgsDebugMsgLevel( u"Query to populate existing list:%1"_s.arg( sql ), 4 );
74 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
75 if ( result == SQLITE_OK )
76 {
78 while ( preparedStatement.step() == SQLITE_ROW )
79 {
80 UserCrsDetails details;
81 details.id = preparedStatement.columnAsText( 0 ).toLong();
82 details.name = preparedStatement.columnAsText( 1 );
83 details.proj = preparedStatement.columnAsText( 2 );
84 details.wkt = preparedStatement.columnAsText( 3 );
85
86 if ( !details.wkt.isEmpty() )
87 details.crs.createFromWkt( details.wkt );
88 else
89 details.crs.createFromProj( details.proj );
90
91 res << details;
92 }
93 }
94 return res;
95}
96
98{
99 if ( !crs.isValid() )
100 {
101 QgsDebugMsgLevel( u"Can't save an invalid CRS!"_s, 4 );
102 return -1;
103 }
104
105 QString mySql;
106
107 QString proj4String = crs.d->mProj4;
108 if ( proj4String.isEmpty() )
109 {
110 proj4String = crs.toProj();
111 }
112 const QString wktString = crs.toWkt( Qgis::CrsWktVariant::Preferred );
113
114 // ellipsoid acroynym column is incorrectly marked as not null in many crs database instances,
115 // hack around this by using an empty string instead
116 const QString quotedEllipsoidString = crs.ellipsoidAcronym().isNull() ? u"''"_s : QgsSqliteUtils::quotedString( crs.ellipsoidAcronym() );
117
118 //if this is the first record we need to ensure that its srs_id is 10000. For
119 //any rec after that sqlite3 will take care of the autonumbering
120 //this was done to support sqlite 3.0 as it does not yet support
121 //the autoinc related system tables.
122 if ( QgsCoordinateReferenceSystem::getRecordCount() == 0 )
123 {
124 mySql = "insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo,wkt) values ("
125 + QString::number( Qgis::USER_CRS_START_ID )
126 + ','
128 + ','
129 + ( !crs.d->mProjectionAcronym.isEmpty() ? QgsSqliteUtils::quotedString( crs.d->mProjectionAcronym ) : u"''"_s )
130 + ','
131 + quotedEllipsoidString
132 + ','
133 + ( !proj4String.isEmpty() ? QgsSqliteUtils::quotedString( proj4String ) : u"''"_s )
134 + ",0," // <-- is_geo shamelessly hard coded for now
135 + ( nativeFormat == Qgis::CrsDefinitionFormat::Wkt ? QgsSqliteUtils::quotedString( wktString ) : u"''"_s )
136 + ')';
137 }
138 else
139 {
140 mySql = "insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo,wkt) values ("
142 + ','
143 + ( !crs.d->mProjectionAcronym.isEmpty() ? QgsSqliteUtils::quotedString( crs.d->mProjectionAcronym ) : u"''"_s )
144 + ','
145 + quotedEllipsoidString
146 + ','
147 + ( !proj4String.isEmpty() ? QgsSqliteUtils::quotedString( proj4String ) : u"''"_s )
148 + ",0," // <-- is_geo shamelessly hard coded for now
149 + ( nativeFormat == Qgis::CrsDefinitionFormat::Wkt ? QgsSqliteUtils::quotedString( wktString ) : u"''"_s )
150 + ')';
151 }
154 //check the db is available
155 int myResult = database.open( QgsApplication::qgisUserDatabaseFilePath() );
156 if ( myResult != SQLITE_OK )
157 {
158 QgsDebugError( u"Can't open or create database %1: %2"_s.arg( QgsApplication::qgisUserDatabaseFilePath(), database.errorMessage() ) );
159 return false;
160 }
161 statement = database.prepare( mySql, myResult );
162
163 qint64 returnId = -1;
164 if ( myResult == SQLITE_OK && statement.step() == SQLITE_DONE )
165 {
166 QgsMessageLog::logMessage( QObject::tr( "Saved user CRS [%1]" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
167
168 returnId = sqlite3_last_insert_rowid( database.get() );
169 crs.d->mSrsId = returnId;
170 crs.d->mAuthId = u"USER:%1"_s.arg( returnId );
171 crs.d->mDescription = name;
172 }
173
174 if ( returnId != -1 )
175 {
176 // If we have a projection acronym not in the user db previously, add it.
177 // This is a must, or else we can't select it from the vw_srs table.
178 // Actually, add it always and let the SQL PRIMARY KEY remove duplicates.
179 insertProjection( crs.projectionAcronym() );
180 }
181
184
185 if ( returnId != -1 )
186 {
187 emit userCrsAdded( crs.d->mAuthId );
189 }
190
191 return returnId;
192}
193
195{
196 if ( !crs.isValid() )
197 {
198 QgsDebugMsgLevel( u"Can't save an invalid CRS!"_s, 4 );
199 return false;
200 }
201
202 const QString sql = "update tbl_srs set description="
204 + ",projection_acronym="
205 + ( !crs.projectionAcronym().isEmpty() ? QgsSqliteUtils::quotedString( crs.projectionAcronym() ) : u"''"_s )
206 + ",ellipsoid_acronym="
207 + ( !crs.ellipsoidAcronym().isEmpty() ? QgsSqliteUtils::quotedString( crs.ellipsoidAcronym() ) : u"''"_s )
208 + ",parameters="
209 + ( !crs.toProj().isEmpty() ? QgsSqliteUtils::quotedString( crs.toProj() ) : u"''"_s )
210 + ",is_geo=0" // <--shamelessly hard coded for now
211 + ",wkt="
213 + " where srs_id="
214 + QgsSqliteUtils::quotedString( QString::number( id ) );
215
217 //check the db is available
218 const int myResult = database.open( QgsApplication::qgisUserDatabaseFilePath() );
219 if ( myResult != SQLITE_OK )
220 {
221 QgsDebugError( u"Can't open or create database %1: %2"_s.arg( QgsApplication::qgisUserDatabaseFilePath(), database.errorMessage() ) );
222 return false;
223 }
224
225 bool res = true;
226 QString errorMessage;
227 if ( database.exec( sql, errorMessage ) != SQLITE_OK )
228 {
229 QgsMessageLog::logMessage( QObject::tr( "Error saving user CRS [%1]: %2" ).arg( crs.toProj(), errorMessage ), QObject::tr( "CRS" ) );
230 res = false;
231 }
232 else
233 {
234 const int changed = sqlite3_changes( database.get() );
235 if ( changed )
236 {
237 QgsMessageLog::logMessage( QObject::tr( "Saved user CRS [%1]" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
238 }
239 else
240 {
241 QgsMessageLog::logMessage( QObject::tr( "Error saving user CRS [%1]: No matching ID found in database" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
242 res = false;
243 }
244 }
245
246 if ( res )
247 {
248 // If we have a projection acronym not in the user db previously, add it.
249 // This is a must, or else we can't select it from the vw_srs table.
250 // Actually, add it always and let the SQL PRIMARY KEY remove duplicates.
251 insertProjection( crs.projectionAcronym() );
252 }
253
256
257 if ( res )
258 {
259 emit userCrsChanged( u"USER:%1"_s.arg( id ) );
261 }
262
263 return res;
264}
265
267{
269
270 const QString sql = "delete from tbl_srs where srs_id=" + QgsSqliteUtils::quotedString( QString::number( id ) );
271 QgsDebugMsgLevel( sql, 4 );
272 //check the db is available
273 int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
274 if ( result != SQLITE_OK )
275 {
276 QgsDebugError( u"Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) "_s.arg( database.errorMessage(), QgsApplication::qgisUserDatabaseFilePath() ) );
277 return false;
278 }
279
280 bool res = true;
281 {
282 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
283 if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
284 {
285 QgsDebugError( u"failed to remove custom CRS from database: %1 [%2]"_s.arg( sql, database.errorMessage() ) );
286 res = false;
287 }
288 else
289 {
290 const int changed = sqlite3_changes( database.get() );
291 if ( changed )
292 {
293 QgsMessageLog::logMessage( QObject::tr( "Removed user CRS [%1]" ).arg( id ), QObject::tr( "CRS" ) );
294 }
295 else
296 {
297 QgsMessageLog::logMessage( QObject::tr( "Error removing user CRS [%1]: No matching ID found in database" ).arg( id ), QObject::tr( "CRS" ) );
298 res = false;
299 }
300 }
301 }
302
305
306 if ( res )
307 {
308 emit userCrsRemoved( id );
310 }
311
312 return res;
313}
314
315
316bool QgsCoordinateReferenceSystemRegistry::insertProjection( const QString &projectionAcronym )
317{
319 sqlite3_database_unique_ptr srsDatabase;
320 QString sql;
321 //check the db is available
322 int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
323 if ( result != SQLITE_OK )
324 {
325 QgsDebugError( u"Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) "_s.arg( database.errorMessage(), QgsApplication::qgisUserDatabaseFilePath() ) );
326 return false;
327 }
328 int srsResult = srsDatabase.open( QgsApplication::srsDatabaseFilePath() );
329 if ( result != SQLITE_OK )
330 {
331 QgsDebugError( u"Can't open database %1 [%2]"_s.arg( QgsApplication::srsDatabaseFilePath(), srsDatabase.errorMessage() ) );
332 return false;
333 }
334
335 // Set up the query to retrieve the projection information needed to populate the PROJECTION list
336 const QString srsSql = "select acronym,name,notes,parameters from tbl_projection where acronym=" + QgsSqliteUtils::quotedString( projectionAcronym );
337
338 sqlite3_statement_unique_ptr srsPreparedStatement = srsDatabase.prepare( srsSql, srsResult );
339 if ( srsResult == SQLITE_OK )
340 {
341 if ( srsPreparedStatement.step() == SQLITE_ROW )
342 {
343 QgsDebugMsgLevel( u"Trying to insert projection"_s, 4 );
344 // We have the result from system srs.db. Now insert into user db.
345 sql = "insert into tbl_projection(acronym,name,notes,parameters) values ("
346 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 0 ) )
347 + ','
348 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 1 ) )
349 + ','
350 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 2 ) )
351 + ','
352 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 3 ) )
353 + ')';
354 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
355 if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
356 {
357 QgsDebugError( u"Could not insert projection into database: %1 [%2]"_s.arg( sql, database.errorMessage() ) );
358 return false;
359 }
360 }
361 }
362 else
363 {
364 QgsDebugError( u"prepare failed: %1 [%2]"_s.arg( srsSql, srsDatabase.errorMessage() ) );
365 return false;
366 }
367
368 return true;
369}
370
371QMap<QString, QgsProjOperation> QgsCoordinateReferenceSystemRegistry::projOperations() const
372{
373 static std::once_flag initialized;
374 static QMap< QString, QgsProjOperation > sProjOperations;
375 std::call_once( initialized, [] {
376 const QgsScopedRuntimeProfile profile( QObject::tr( "Initialize PROJ operations" ) );
377
378 const PJ_OPERATIONS *operation = proj_list_operations();
379 while ( operation && operation->id )
380 {
381 QgsProjOperation value;
382 value.mValid = true;
383 value.mId = QString( operation->id );
384
385 const QString description( *operation->descr );
386 const QStringList descriptionParts = description.split( u"\n\t"_s );
387 value.mDescription = descriptionParts.value( 0 );
388 value.mDetails = descriptionParts.mid( 1 ).join( '\n' );
389
390 sProjOperations.insert( value.id(), value );
391
392 operation++;
393 }
394 } );
395
396 return sProjOperations;
397}
398
400{
401 static QList< QgsCelestialBody > sCelestialBodies;
402 static std::once_flag initialized;
403 std::call_once( initialized, [] {
404 QgsScopedRuntimeProfile profile( QObject::tr( "Initialize celestial bodies" ) );
405
406 PJ_CONTEXT *context = QgsProjContext::get();
407
408 int resultCount = 0;
409 PROJ_CELESTIAL_BODY_INFO **list = proj_get_celestial_body_list_from_database( context, nullptr, &resultCount );
410 sCelestialBodies.reserve( resultCount );
411 for ( int i = 0; i < resultCount; i++ )
412 {
413 const PROJ_CELESTIAL_BODY_INFO *info = list[i];
414 if ( !info )
415 break;
416
417 QgsCelestialBody body;
418 body.mValid = true;
419 body.mAuthority = QString( info->auth_name );
420 body.mName = QString( info->name );
421
422 sCelestialBodies << body;
423 }
424 proj_celestial_body_list_destroy( list );
425 } );
426
427 return sCelestialBodies;
428}
429
431{
432 static QSet< QString > sKnownAuthorities;
433 static std::once_flag initialized;
434 std::call_once( initialized, [] {
435 QgsScopedRuntimeProfile profile( QObject::tr( "Initialize authorities" ) );
436
437 PJ_CONTEXT *pjContext = QgsProjContext::get();
438 PROJ_STRING_LIST authorities = proj_get_authorities_from_database( pjContext );
439
440 for ( auto authIter = authorities; authIter && *authIter; ++authIter )
441 {
442 const QString authority( *authIter );
443 sKnownAuthorities.insert( authority.toLower() );
444 }
445
446 proj_string_list_destroy( authorities );
447 } );
448
449 return sKnownAuthorities;
450}
451
453{
454 QgsReadWriteLocker locker( mCrsDbRecordsLock, QgsReadWriteLocker::Read );
455 if ( mCrsDbRecordsPopulated )
456 return mCrsDbRecords;
457
459
460 const QString srsDatabaseFileName = QgsApplication::srsDatabaseFilePath();
461 if ( QFileInfo::exists( srsDatabaseFileName ) )
462 {
463 // open the database containing the spatial reference data, and do a one-time read
465 int result = database.open_v2( srsDatabaseFileName, SQLITE_OPEN_READONLY, nullptr );
466 if ( result == SQLITE_OK )
467 {
468 const QString sql = u"SELECT description, srs_id, auth_name, auth_id, projection_acronym, deprecated, srs_type FROM tbl_srs"_s;
469 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
470 if ( result == SQLITE_OK )
471 {
472 while ( preparedStatement.step() == SQLITE_ROW )
473 {
474 QgsCrsDbRecord record;
475 record.description = preparedStatement.columnAsText( 0 );
476 record.srsId = preparedStatement.columnAsText( 1 );
477 record.authName = preparedStatement.columnAsText( 2 );
478 record.authId = preparedStatement.columnAsText( 3 );
479 record.projectionAcronym = preparedStatement.columnAsText( 4 );
480 record.deprecated = preparedStatement.columnAsText( 5 ).toInt();
481 record.type = qgsEnumKeyToValue( preparedStatement.columnAsText( 6 ), Qgis::CrsType::Unknown );
482 mCrsDbRecords.append( record );
483 }
484 }
485 }
486 }
487
488 mCrsDbRecordsPopulated = true;
489 return mCrsDbRecords;
490}
491
492QList<QgsCoordinateReferenceSystem> QgsCoordinateReferenceSystemRegistry::recentCrs()
493{
494 QList<QgsCoordinateReferenceSystem> res;
495
496 // Read settings from persistent storage
497 QStringList projectionsProj4 = settingsRecentProjectionsProj4->value();
498 QStringList projectionsWkt = settingsRecentProjectionsWkt->value();
499 QStringList projectionsAuthId = settingsRecentProjectionsAuthId->value();
500 int max = std::max( projectionsAuthId.size(), std::max( projectionsProj4.size(), projectionsWkt.size() ) );
501 res.reserve( max );
502 for ( int i = 0; i < max; ++i )
503 {
504 const QString proj = projectionsProj4.value( i );
505 const QString wkt = projectionsWkt.value( i );
506 const QString authid = projectionsAuthId.value( i );
507
509 if ( !authid.isEmpty() )
510 crs = QgsCoordinateReferenceSystem( authid );
511 if ( !crs.isValid() && !wkt.isEmpty() )
512 crs.createFromWkt( wkt );
513 if ( !crs.isValid() && !proj.isEmpty() )
514 crs.createFromProj( wkt );
515
516 if ( crs.isValid() )
517 res << crs;
518 }
519 return res;
520}
521
530
532{
533 // we only want saved and standard CRSes in the recent list
534 if ( crs.srsid() == 0 || !crs.isValid() )
535 return;
536
537 QList<QgsCoordinateReferenceSystem> recent = recentCrs();
538 recent.removeAll( crs );
539 recent.insert( 0, crs );
540
541 auto hasVertical = []( const QgsCoordinateReferenceSystem &crs ) {
542 switch ( crs.type() )
543 {
554 return false;
555
559 return true;
560 }
562 };
563 QList<QgsCoordinateReferenceSystem> recentSameType;
564 std::copy_if( recent.begin(), recent.end(), std::back_inserter( recentSameType ), [crs, &hasVertical]( const QgsCoordinateReferenceSystem &it ) { return hasVertical( it ) == hasVertical( crs ); } );
565
566 // trim to max 30 items of the same type
567 const QList<QgsCoordinateReferenceSystem> toTrim = recentSameType.mid( 30 );
568 for ( const QgsCoordinateReferenceSystem &crsTrimmed : toTrim )
569 {
570 recent.removeOne( crsTrimmed );
571 emit recentCrsRemoved( crsTrimmed );
572 }
573
574 QStringList authids;
575 authids.reserve( recent.size() );
576 QStringList proj;
577 proj.reserve( recent.size() );
578 QStringList wkt;
579 wkt.reserve( recent.size() );
580 for ( const QgsCoordinateReferenceSystem &c : std::as_const( recent ) )
581 {
582 authids << c.authid();
583 proj << c.toProj();
584 wkt << c.toWkt( Qgis::CrsWktVariant::Preferred );
585 }
586
587 settingsRecentProjectionsAuthId->setValue( authids );
588 settingsRecentProjectionsWkt->setValue( wkt );
589 settingsRecentProjectionsProj4->setValue( proj );
590
591 emit recentCrsPushed( crs );
592}
593
595{
596 if ( crs.srsid() == 0 || !crs.isValid() )
597 return;
598
599 QList<QgsCoordinateReferenceSystem> recent = recentCrs();
600 recent.removeAll( crs );
601 QStringList authids;
602 authids.reserve( recent.size() );
603 QStringList proj;
604 proj.reserve( recent.size() );
605 QStringList wkt;
606 wkt.reserve( recent.size() );
607 for ( const QgsCoordinateReferenceSystem &c : std::as_const( recent ) )
608 {
609 authids << c.authid();
610 proj << c.toProj();
611 wkt << c.toWkt( Qgis::CrsWktVariant::Preferred );
612 }
613 settingsRecentProjectionsAuthId->setValue( authids );
614 settingsRecentProjectionsWkt->setValue( wkt );
615 settingsRecentProjectionsProj4->setValue( proj );
616
617 emit recentCrsRemoved( crs );
618}
@ Vertical
Vertical CRS.
Definition qgis.h:2468
@ Temporal
Temporal CRS.
Definition qgis.h:2471
@ Compound
Compound (horizontal + vertical) CRS.
Definition qgis.h:2470
@ Projected
Projected CRS.
Definition qgis.h:2469
@ Other
Other type.
Definition qgis.h:2474
@ Bound
Bound CRS.
Definition qgis.h:2473
@ DerivedProjected
Derived projected CRS.
Definition qgis.h:2475
@ Unknown
Unknown type.
Definition qgis.h:2463
@ Engineering
Engineering CRS.
Definition qgis.h:2472
@ Geographic3d
3D geopraphic CRS
Definition qgis.h:2467
@ Geodetic
Geodetic CRS.
Definition qgis.h:2464
@ Geographic2d
2D geographic CRS
Definition qgis.h:2466
@ Geocentric
Geocentric CRS.
Definition qgis.h:2465
CrsDefinitionFormat
CRS definition formats.
Definition qgis.h:4075
@ Wkt
WKT format (always recommended over proj string format).
Definition qgis.h:4076
static const int USER_CRS_START_ID
Minimum ID number for a user-defined projection.
Definition qgis.h:6762
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2580
static QString qgisUserDatabaseFilePath()
Returns the path to the user qgis.db file.
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
Contains information about a celestial body.
QgsCoordinateReferenceSystem crs
QgsCoordinateReferenceSystem object representing the user-defined CRS.
QList< QgsCrsDbRecord > crsDbRecords() const
Returns the list of records from the QGIS srs db.
static const QgsSettingsEntryStringList * settingsRecentProjectionsProj4
void userCrsAdded(const QString &id)
Emitted whenever a new user CRS definition is added.
void recentCrsRemoved(const QgsCoordinateReferenceSystem &crs)
Emitted when a recently used CRS has been removed from the recent CRS list.
void userCrsChanged(const QString &id)
Emitted whenever an existing user CRS definition is changed.
void recentCrsCleared()
Emitted when the list of recently used CRS has been cleared.
void recentCrsPushed(const QgsCoordinateReferenceSystem &crs)
Emitted when a recently used CRS has been pushed to the top of the recent CRS list.
QList< QgsCelestialBody > celestialBodies() const
Returns a list of all known celestial bodies.
void userCrsRemoved(long id)
Emitted when the user CRS with matching id is removed from the database.
void crsDefinitionsChanged()
Emitted whenever an operation has caused any of the known CRS definitions (including user-defined CRS...
bool updateUserCrs(long id, const QgsCoordinateReferenceSystem &crs, const QString &name, Qgis::CrsDefinitionFormat nativeFormat=Qgis::CrsDefinitionFormat::Wkt)
Updates the definition of the existing user CRS with matching id.
QgsCoordinateReferenceSystemRegistry(QObject *parent=nullptr)
Constructor for QgsCoordinateReferenceSystemRegistry, with the specified parent object.
void removeRecent(const QgsCoordinateReferenceSystem &crs)
Removes a CRS from the list of recently used CRS.
static const QgsSettingsEntryStringList * settingsRecentProjectionsWkt
long addUserCrs(const QgsCoordinateReferenceSystem &crs, const QString &name, Qgis::CrsDefinitionFormat nativeFormat=Qgis::CrsDefinitionFormat::Wkt)
Adds a new crs definition as a custom ("USER") CRS.
QSet< QString > authorities() const
Returns a list of all known authorities.
static const QgsSettingsEntryStringList * settingsRecentProjectionsAuthId
bool removeUserCrs(long id)
Removes the existing user CRS with matching id.
void clearRecent()
Cleans the list of recently used CRS.
QList< QgsCoordinateReferenceSystemRegistry::UserCrsDetails > userCrsList() const
Returns a list containing the details of all registered custom (user-defined) CRSes.
QList< QgsCoordinateReferenceSystem > recentCrs()
Returns a list of recently used CRS.
void pushRecent(const QgsCoordinateReferenceSystem &crs)
Pushes a recently used CRS to the top of the recent CRS list.
QMap< QString, QgsProjOperation > projOperations() const
Returns a map of all valid PROJ operations.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromWkt(const QString &wkt)
Sets this CRS using a WKT definition.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
QString projectionAcronym() const
Returns the projection acronym for the projection used by the CRS.
bool createFromProj(const QString &projString, bool identify=true)
Sets this CRS by passing it a PROJ style formatted string.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used to initialize QgsCoordinateReferenceSystem objects.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
long srsid() const
Returns the internal CRS ID, if available.
Qgis::CrsType type() const
Returns the type of the CRS.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used to initialize QgsCoordinateTransform objects.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
Contains information about a PROJ operation.
QString id() const
ID of operation.
A convenience class that simplifies locking and unlocking QReadWriteLocks.
@ Write
Lock for write.
void changeMode(Mode mode)
Change the mode of the lock to mode.
Scoped object for logging of the runtime for a single operation or group of operations.
A string list settings entry.
static QgsSettingsTreeNode * sTreeCrs
static QString quotedString(const QString &value)
Returns a quoted string value, surround by ' characters and with special characters correctly escaped...
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
int open(const QString &path)
Opens the database at the specified file path.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7335
#define BUILTIN_UNREACHABLE
Definition qgis.h:7714
struct pj_ctx PJ_CONTEXT
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59