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