QGIS API Documentation 4.1.0-Master (60fea48833c)
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"
34#include "qgssettings.h"
35#include "qgssqliteutils.h"
36
37#include <QFileInfo>
38#include <QString>
39
40#include "moc_qgscoordinatereferencesystemregistry.cpp"
41
42using namespace Qt::StringLiterals;
43
47
49
50QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> QgsCoordinateReferenceSystemRegistry::userCrsList() const
51{
52 QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> res;
53
54 //Setup connection to the existing custom CRS database:
56 //check the db is available
57 int result = database.open_v2( QgsApplication::qgisUserDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr );
58 if ( result != SQLITE_OK )
59 {
60 QgsDebugError( u"Can't open database: %1"_s.arg( database.errorMessage() ) );
61 return res;
62 }
63
64 const QString sql = u"select srs_id,description,parameters, wkt from tbl_srs"_s;
65 QgsDebugMsgLevel( u"Query to populate existing list:%1"_s.arg( sql ), 4 );
66 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
67 if ( result == SQLITE_OK )
68 {
70 while ( preparedStatement.step() == SQLITE_ROW )
71 {
72 UserCrsDetails details;
73 details.id = preparedStatement.columnAsText( 0 ).toLong();
74 details.name = preparedStatement.columnAsText( 1 );
75 details.proj = preparedStatement.columnAsText( 2 );
76 details.wkt = preparedStatement.columnAsText( 3 );
77
78 if ( !details.wkt.isEmpty() )
79 details.crs.createFromWkt( details.wkt );
80 else
81 details.crs.createFromProj( details.proj );
82
83 res << details;
84 }
85 }
86 return res;
87}
88
90{
91 if ( !crs.isValid() )
92 {
93 QgsDebugMsgLevel( u"Can't save an invalid CRS!"_s, 4 );
94 return -1;
95 }
96
97 QString mySql;
98
99 QString proj4String = crs.d->mProj4;
100 if ( proj4String.isEmpty() )
101 {
102 proj4String = crs.toProj();
103 }
104 const QString wktString = crs.toWkt( Qgis::CrsWktVariant::Preferred );
105
106 // ellipsoid acroynym column is incorrectly marked as not null in many crs database instances,
107 // hack around this by using an empty string instead
108 const QString quotedEllipsoidString = crs.ellipsoidAcronym().isNull() ? u"''"_s : QgsSqliteUtils::quotedString( crs.ellipsoidAcronym() );
109
110 //if this is the first record we need to ensure that its srs_id is 10000. For
111 //any rec after that sqlite3 will take care of the autonumbering
112 //this was done to support sqlite 3.0 as it does not yet support
113 //the autoinc related system tables.
114 if ( QgsCoordinateReferenceSystem::getRecordCount() == 0 )
115 {
116 mySql = "insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo,wkt) values ("
117 + QString::number( Qgis::USER_CRS_START_ID )
118 + ','
120 + ','
121 + ( !crs.d->mProjectionAcronym.isEmpty() ? QgsSqliteUtils::quotedString( crs.d->mProjectionAcronym ) : u"''"_s )
122 + ','
123 + quotedEllipsoidString
124 + ','
125 + ( !proj4String.isEmpty() ? QgsSqliteUtils::quotedString( proj4String ) : u"''"_s )
126 + ",0," // <-- is_geo shamelessly hard coded for now
127 + ( nativeFormat == Qgis::CrsDefinitionFormat::Wkt ? QgsSqliteUtils::quotedString( wktString ) : u"''"_s )
128 + ')';
129 }
130 else
131 {
132 mySql = "insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo,wkt) values ("
134 + ','
135 + ( !crs.d->mProjectionAcronym.isEmpty() ? QgsSqliteUtils::quotedString( crs.d->mProjectionAcronym ) : u"''"_s )
136 + ','
137 + quotedEllipsoidString
138 + ','
139 + ( !proj4String.isEmpty() ? QgsSqliteUtils::quotedString( proj4String ) : u"''"_s )
140 + ",0," // <-- is_geo shamelessly hard coded for now
141 + ( nativeFormat == Qgis::CrsDefinitionFormat::Wkt ? QgsSqliteUtils::quotedString( wktString ) : u"''"_s )
142 + ')';
143 }
146 //check the db is available
147 int myResult = database.open( QgsApplication::qgisUserDatabaseFilePath() );
148 if ( myResult != SQLITE_OK )
149 {
150 QgsDebugError( u"Can't open or create database %1: %2"_s.arg( QgsApplication::qgisUserDatabaseFilePath(), database.errorMessage() ) );
151 return false;
152 }
153 statement = database.prepare( mySql, myResult );
154
155 qint64 returnId = -1;
156 if ( myResult == SQLITE_OK && statement.step() == SQLITE_DONE )
157 {
158 QgsMessageLog::logMessage( QObject::tr( "Saved user CRS [%1]" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
159
160 returnId = sqlite3_last_insert_rowid( database.get() );
161 crs.d->mSrsId = returnId;
162 crs.d->mAuthId = u"USER:%1"_s.arg( returnId );
163 crs.d->mDescription = name;
164 }
165
166 if ( returnId != -1 )
167 {
168 // If we have a projection acronym not in the user db previously, add it.
169 // This is a must, or else we can't select it from the vw_srs table.
170 // Actually, add it always and let the SQL PRIMARY KEY remove duplicates.
171 insertProjection( crs.projectionAcronym() );
172 }
173
176
177 if ( returnId != -1 )
178 {
179 emit userCrsAdded( crs.d->mAuthId );
181 }
182
183 return returnId;
184}
185
187{
188 if ( !crs.isValid() )
189 {
190 QgsDebugMsgLevel( u"Can't save an invalid CRS!"_s, 4 );
191 return false;
192 }
193
194 const QString sql = "update tbl_srs set description="
196 + ",projection_acronym="
197 + ( !crs.projectionAcronym().isEmpty() ? QgsSqliteUtils::quotedString( crs.projectionAcronym() ) : u"''"_s )
198 + ",ellipsoid_acronym="
199 + ( !crs.ellipsoidAcronym().isEmpty() ? QgsSqliteUtils::quotedString( crs.ellipsoidAcronym() ) : u"''"_s )
200 + ",parameters="
201 + ( !crs.toProj().isEmpty() ? QgsSqliteUtils::quotedString( crs.toProj() ) : u"''"_s )
202 + ",is_geo=0" // <--shamelessly hard coded for now
203 + ",wkt="
205 + " where srs_id="
206 + QgsSqliteUtils::quotedString( QString::number( id ) );
207
209 //check the db is available
210 const int myResult = database.open( QgsApplication::qgisUserDatabaseFilePath() );
211 if ( myResult != SQLITE_OK )
212 {
213 QgsDebugError( u"Can't open or create database %1: %2"_s.arg( QgsApplication::qgisUserDatabaseFilePath(), database.errorMessage() ) );
214 return false;
215 }
216
217 bool res = true;
218 QString errorMessage;
219 if ( database.exec( sql, errorMessage ) != SQLITE_OK )
220 {
221 QgsMessageLog::logMessage( QObject::tr( "Error saving user CRS [%1]: %2" ).arg( crs.toProj(), errorMessage ), QObject::tr( "CRS" ) );
222 res = false;
223 }
224 else
225 {
226 const int changed = sqlite3_changes( database.get() );
227 if ( changed )
228 {
229 QgsMessageLog::logMessage( QObject::tr( "Saved user CRS [%1]" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
230 }
231 else
232 {
233 QgsMessageLog::logMessage( QObject::tr( "Error saving user CRS [%1]: No matching ID found in database" ).arg( crs.toProj() ), QObject::tr( "CRS" ) );
234 res = false;
235 }
236 }
237
238 if ( res )
239 {
240 // If we have a projection acronym not in the user db previously, add it.
241 // This is a must, or else we can't select it from the vw_srs table.
242 // Actually, add it always and let the SQL PRIMARY KEY remove duplicates.
243 insertProjection( crs.projectionAcronym() );
244 }
245
248
249 if ( res )
250 {
251 emit userCrsChanged( u"USER:%1"_s.arg( id ) );
253 }
254
255 return res;
256}
257
259{
261
262 const QString sql = "delete from tbl_srs where srs_id=" + QgsSqliteUtils::quotedString( QString::number( id ) );
263 QgsDebugMsgLevel( sql, 4 );
264 //check the db is available
265 int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
266 if ( result != SQLITE_OK )
267 {
268 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() ) );
269 return false;
270 }
271
272 bool res = true;
273 {
274 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
275 if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
276 {
277 QgsDebugError( u"failed to remove custom CRS from database: %1 [%2]"_s.arg( sql, database.errorMessage() ) );
278 res = false;
279 }
280 else
281 {
282 const int changed = sqlite3_changes( database.get() );
283 if ( changed )
284 {
285 QgsMessageLog::logMessage( QObject::tr( "Removed user CRS [%1]" ).arg( id ), QObject::tr( "CRS" ) );
286 }
287 else
288 {
289 QgsMessageLog::logMessage( QObject::tr( "Error removing user CRS [%1]: No matching ID found in database" ).arg( id ), QObject::tr( "CRS" ) );
290 res = false;
291 }
292 }
293 }
294
297
298 if ( res )
299 {
300 emit userCrsRemoved( id );
302 }
303
304 return res;
305}
306
307
308bool QgsCoordinateReferenceSystemRegistry::insertProjection( const QString &projectionAcronym )
309{
311 sqlite3_database_unique_ptr srsDatabase;
312 QString sql;
313 //check the db is available
314 int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
315 if ( result != SQLITE_OK )
316 {
317 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() ) );
318 return false;
319 }
320 int srsResult = srsDatabase.open( QgsApplication::srsDatabaseFilePath() );
321 if ( result != SQLITE_OK )
322 {
323 QgsDebugError( u"Can't open database %1 [%2]"_s.arg( QgsApplication::srsDatabaseFilePath(), srsDatabase.errorMessage() ) );
324 return false;
325 }
326
327 // Set up the query to retrieve the projection information needed to populate the PROJECTION list
328 const QString srsSql = "select acronym,name,notes,parameters from tbl_projection where acronym=" + QgsSqliteUtils::quotedString( projectionAcronym );
329
330 sqlite3_statement_unique_ptr srsPreparedStatement = srsDatabase.prepare( srsSql, srsResult );
331 if ( srsResult == SQLITE_OK )
332 {
333 if ( srsPreparedStatement.step() == SQLITE_ROW )
334 {
335 QgsDebugMsgLevel( u"Trying to insert projection"_s, 4 );
336 // We have the result from system srs.db. Now insert into user db.
337 sql = "insert into tbl_projection(acronym,name,notes,parameters) values ("
338 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 0 ) )
339 + ','
340 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 1 ) )
341 + ','
342 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 2 ) )
343 + ','
344 + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 3 ) )
345 + ')';
346 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
347 if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
348 {
349 QgsDebugError( u"Could not insert projection into database: %1 [%2]"_s.arg( sql, database.errorMessage() ) );
350 return false;
351 }
352 }
353 }
354 else
355 {
356 QgsDebugError( u"prepare failed: %1 [%2]"_s.arg( srsSql, srsDatabase.errorMessage() ) );
357 return false;
358 }
359
360 return true;
361}
362
363QMap<QString, QgsProjOperation> QgsCoordinateReferenceSystemRegistry::projOperations() const
364{
365 static std::once_flag initialized;
366 static QMap< QString, QgsProjOperation > sProjOperations;
367 std::call_once( initialized, [] {
368 const QgsScopedRuntimeProfile profile( QObject::tr( "Initialize PROJ operations" ) );
369
370 const PJ_OPERATIONS *operation = proj_list_operations();
371 while ( operation && operation->id )
372 {
373 QgsProjOperation value;
374 value.mValid = true;
375 value.mId = QString( operation->id );
376
377 const QString description( *operation->descr );
378 const QStringList descriptionParts = description.split( u"\n\t"_s );
379 value.mDescription = descriptionParts.value( 0 );
380 value.mDetails = descriptionParts.mid( 1 ).join( '\n' );
381
382 sProjOperations.insert( value.id(), value );
383
384 operation++;
385 }
386 } );
387
388 return sProjOperations;
389}
390
392{
393 static QList< QgsCelestialBody > sCelestialBodies;
394 static std::once_flag initialized;
395 std::call_once( initialized, [] {
396 QgsScopedRuntimeProfile profile( QObject::tr( "Initialize celestial bodies" ) );
397
398 PJ_CONTEXT *context = QgsProjContext::get();
399
400 int resultCount = 0;
401 PROJ_CELESTIAL_BODY_INFO **list = proj_get_celestial_body_list_from_database( context, nullptr, &resultCount );
402 sCelestialBodies.reserve( resultCount );
403 for ( int i = 0; i < resultCount; i++ )
404 {
405 const PROJ_CELESTIAL_BODY_INFO *info = list[i];
406 if ( !info )
407 break;
408
409 QgsCelestialBody body;
410 body.mValid = true;
411 body.mAuthority = QString( info->auth_name );
412 body.mName = QString( info->name );
413
414 sCelestialBodies << body;
415 }
416 proj_celestial_body_list_destroy( list );
417 } );
418
419 return sCelestialBodies;
420}
421
423{
424 static QSet< QString > sKnownAuthorities;
425 static std::once_flag initialized;
426 std::call_once( initialized, [] {
427 QgsScopedRuntimeProfile profile( QObject::tr( "Initialize authorities" ) );
428
429 PJ_CONTEXT *pjContext = QgsProjContext::get();
430 PROJ_STRING_LIST authorities = proj_get_authorities_from_database( pjContext );
431
432 for ( auto authIter = authorities; authIter && *authIter; ++authIter )
433 {
434 const QString authority( *authIter );
435 sKnownAuthorities.insert( authority.toLower() );
436 }
437
438 proj_string_list_destroy( authorities );
439 } );
440
441 return sKnownAuthorities;
442}
443
445{
446 QgsReadWriteLocker locker( mCrsDbRecordsLock, QgsReadWriteLocker::Read );
447 if ( mCrsDbRecordsPopulated )
448 return mCrsDbRecords;
449
451
452 const QString srsDatabaseFileName = QgsApplication::srsDatabaseFilePath();
453 if ( QFileInfo::exists( srsDatabaseFileName ) )
454 {
455 // open the database containing the spatial reference data, and do a one-time read
457 int result = database.open_v2( srsDatabaseFileName, SQLITE_OPEN_READONLY, nullptr );
458 if ( result == SQLITE_OK )
459 {
460 const QString sql = u"SELECT description, srs_id, auth_name, auth_id, projection_acronym, deprecated, srs_type FROM tbl_srs"_s;
461 sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
462 if ( result == SQLITE_OK )
463 {
464 while ( preparedStatement.step() == SQLITE_ROW )
465 {
466 QgsCrsDbRecord record;
467 record.description = preparedStatement.columnAsText( 0 );
468 record.srsId = preparedStatement.columnAsText( 1 );
469 record.authName = preparedStatement.columnAsText( 2 );
470 record.authId = preparedStatement.columnAsText( 3 );
471 record.projectionAcronym = preparedStatement.columnAsText( 4 );
472 record.deprecated = preparedStatement.columnAsText( 5 ).toInt();
473 record.type = qgsEnumKeyToValue( preparedStatement.columnAsText( 6 ), Qgis::CrsType::Unknown );
474 mCrsDbRecords.append( record );
475 }
476 }
477 }
478 }
479
480 mCrsDbRecordsPopulated = true;
481 return mCrsDbRecords;
482}
483
484QList<QgsCoordinateReferenceSystem> QgsCoordinateReferenceSystemRegistry::recentCrs()
485{
486 QList<QgsCoordinateReferenceSystem> res;
487
488 // Read settings from persistent storage
489 QgsSettings settings;
490 QStringList projectionsProj4 = settings.value( u"UI/recentProjectionsProj4"_s ).toStringList();
491 QStringList projectionsWkt = settings.value( u"UI/recentProjectionsWkt"_s ).toStringList();
492 QStringList projectionsAuthId = settings.value( u"UI/recentProjectionsAuthId"_s ).toStringList();
493 int max = std::max( projectionsAuthId.size(), std::max( projectionsProj4.size(), projectionsWkt.size() ) );
494 res.reserve( max );
495 for ( int i = 0; i < max; ++i )
496 {
497 const QString proj = projectionsProj4.value( i );
498 const QString wkt = projectionsWkt.value( i );
499 const QString authid = projectionsAuthId.value( i );
500
502 if ( !authid.isEmpty() )
503 crs = QgsCoordinateReferenceSystem( authid );
504 if ( !crs.isValid() && !wkt.isEmpty() )
505 crs.createFromWkt( wkt );
506 if ( !crs.isValid() && !proj.isEmpty() )
507 crs.createFromProj( wkt );
508
509 if ( crs.isValid() )
510 res << crs;
511 }
512 return res;
513}
514
516{
517 QgsSettings settings;
518 settings.remove( u"UI/recentProjectionsAuthId"_s );
519 settings.remove( u"UI/recentProjectionsWkt"_s );
520 settings.remove( u"UI/recentProjectionsProj4"_s );
521
522 emit recentCrsCleared();
523}
524
526{
527 // we only want saved and standard CRSes in the recent list
528 if ( crs.srsid() == 0 || !crs.isValid() )
529 return;
530
531 QList<QgsCoordinateReferenceSystem> recent = recentCrs();
532 recent.removeAll( crs );
533 recent.insert( 0, crs );
534
535 auto hasVertical = []( const QgsCoordinateReferenceSystem &crs ) {
536 switch ( crs.type() )
537 {
548 return false;
549
553 return true;
554 }
556 };
557 QList<QgsCoordinateReferenceSystem> recentSameType;
558 std::copy_if( recent.begin(), recent.end(), std::back_inserter( recentSameType ), [crs, &hasVertical]( const QgsCoordinateReferenceSystem &it ) { return hasVertical( it ) == hasVertical( crs ); } );
559
560 // trim to max 30 items of the same type
561 const QList<QgsCoordinateReferenceSystem> toTrim = recentSameType.mid( 30 );
562 for ( const QgsCoordinateReferenceSystem &crsTrimmed : toTrim )
563 {
564 recent.removeOne( crsTrimmed );
565 emit recentCrsRemoved( crsTrimmed );
566 }
567
568 QStringList authids;
569 authids.reserve( recent.size() );
570 QStringList proj;
571 proj.reserve( recent.size() );
572 QStringList wkt;
573 wkt.reserve( recent.size() );
574 for ( const QgsCoordinateReferenceSystem &c : std::as_const( recent ) )
575 {
576 authids << c.authid();
577 proj << c.toProj();
578 wkt << c.toWkt( Qgis::CrsWktVariant::Preferred );
579 }
580
581 QgsSettings settings;
582 settings.setValue( u"UI/recentProjectionsAuthId"_s, authids );
583 settings.setValue( u"UI/recentProjectionsWkt"_s, wkt );
584 settings.setValue( u"UI/recentProjectionsProj4"_s, proj );
585
586 emit recentCrsPushed( crs );
587}
588
590{
591 if ( crs.srsid() == 0 || !crs.isValid() )
592 return;
593
594 QList<QgsCoordinateReferenceSystem> recent = recentCrs();
595 recent.removeAll( crs );
596 QStringList authids;
597 authids.reserve( recent.size() );
598 QStringList proj;
599 proj.reserve( recent.size() );
600 QStringList wkt;
601 wkt.reserve( recent.size() );
602 for ( const QgsCoordinateReferenceSystem &c : std::as_const( recent ) )
603 {
604 authids << c.authid();
605 proj << c.toProj();
606 wkt << c.toWkt( Qgis::CrsWktVariant::Preferred );
607 }
608 QgsSettings settings;
609 settings.setValue( u"UI/recentProjectionsAuthId"_s, authids );
610 settings.setValue( u"UI/recentProjectionsWkt"_s, wkt );
611 settings.setValue( u"UI/recentProjectionsProj4"_s, proj );
612
613 emit recentCrsRemoved( crs );
614}
@ Vertical
Vertical CRS.
Definition qgis.h:2415
@ Temporal
Temporal CRS.
Definition qgis.h:2418
@ Compound
Compound (horizontal + vertical) CRS.
Definition qgis.h:2417
@ Projected
Projected CRS.
Definition qgis.h:2416
@ Other
Other type.
Definition qgis.h:2421
@ Bound
Bound CRS.
Definition qgis.h:2420
@ DerivedProjected
Derived projected CRS.
Definition qgis.h:2422
@ Unknown
Unknown type.
Definition qgis.h:2410
@ Engineering
Engineering CRS.
Definition qgis.h:2419
@ Geographic3d
3D geopraphic CRS
Definition qgis.h:2414
@ Geodetic
Geodetic CRS.
Definition qgis.h:2411
@ Geographic2d
2D geographic CRS
Definition qgis.h:2413
@ Geocentric
Geocentric CRS.
Definition qgis.h:2412
CrsDefinitionFormat
CRS definition formats.
Definition qgis.h:4008
@ Wkt
WKT format (always recommended over proj string format).
Definition qgis.h:4009
static const int USER_CRS_START_ID
Minimum ID number for a user-defined projection.
Definition qgis.h:6606
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2527
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.
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.
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.
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.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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:7176
#define BUILTIN_UNREACHABLE
Definition qgis.h:7540
struct pj_ctx PJ_CONTEXT
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59