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