Skip to content

Commit

Permalink
Add a new QgsCoordinateReferenceSystemRegistry singleton attached
Browse files Browse the repository at this point in the history
to QgsApplication

In the long term all methods for retrieving available CRS details
should be moved here (instead of being scattered all over the place,
as they are now). But for now the logic for saving and updating
user CRS definitions has been moved here only.

The initial motivation is to create a central place where objects
can connect to in order to listen for when a user makes changes
to their custom projections.

Refs #40704
  • Loading branch information
nyalldawson committed Jan 27, 2021
1 parent 064825b commit 1499250
Show file tree
Hide file tree
Showing 15 changed files with 642 additions and 116 deletions.
8 changes: 8 additions & 0 deletions python/core/auto_generated/qgsapplication.sip.in
Expand Up @@ -694,6 +694,14 @@ Returns the application's data item provider registry, which keeps a list of dat
providers that may add items to the browser tree.

.. versionadded:: 3.0
%End

static QgsCoordinateReferenceSystemRegistry *coordinateReferenceSystemRegistry() /KeepReference/;
%Docstring
Returns the application's coordinate reference system (CRS) registry, which handles
known CRS definitions (including user-defined CRSes).

.. versionadded:: 3.18
%End

static QgsSvgCache *svgCache();
Expand Down
Expand Up @@ -840,7 +840,7 @@ Update proj.4 parameters in our database from proj.4

long saveAsUserCrs( const QString &name, Format nativeFormat = FormatWkt );
%Docstring
Saves the CRS as a custom ("USER") CRS.
Saves the CRS as a new custom ("USER") CRS.

Returns the new CRS :py:func:`~QgsCoordinateReferenceSystem.srsid`, or -1 if the CRS could not be saved.

Expand All @@ -851,6 +851,10 @@ definition. FormatWkt is recommended as it is a lossless format.

Not all CRS definitions can be represented as a Proj string, so
take care when using the FormatProj option.

.. note::

Since QGIS 3.18, internally this calls :py:func:`QgsCoordinateReferenceSystemRegistry.addUserCrs()`.
%End

QString geographicCrsAuthId() const;
Expand Down
116 changes: 116 additions & 0 deletions python/core/auto_generated/qgscoordinatereferencesystemregistry.sip.in
@@ -0,0 +1,116 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgscoordinatereferencesystemregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsCoordinateReferenceSystemRegistry : QObject
{
%Docstring
A registry for known coordinate reference system (CRS) definitions, including
any user-defined CRSes.

QgsCoordinateReferenceSystemRegistry is not usually directly created, but rather accessed through
:py:func:`QgsApplication.coordinateReferenceSystemRegistry()`.

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgscoordinatereferencesystemregistry.h"
%End
public:

explicit QgsCoordinateReferenceSystemRegistry( QObject *parent = 0 );
%Docstring
Constructor for QgsCoordinateReferenceSystemRegistry, with the specified ``parent`` object.
%End

long addUserCrs( const QgsCoordinateReferenceSystem &crs, const QString &name, QgsCoordinateReferenceSystem::Format nativeFormat = QgsCoordinateReferenceSystem::FormatWkt );
%Docstring
Adds a new ``crs`` definition as a custom ("USER") CRS.

Returns the new CRS :py:func:`~QgsCoordinateReferenceSystemRegistry.srsid`, or -1 if the CRS could not be saved.

The ``nativeFormat`` argument specifies the format to use when saving the CRS
definition. FormatWkt is recommended as it is a lossless format.

.. warning::

Not all CRS definitions can be represented as a Proj string, so
take care when using the FormatProj option.

.. seealso:: :py:func:`updateUserCrs`

.. seealso:: :py:func:`userCrsAdded`
%End

bool updateUserCrs( long id, const QgsCoordinateReferenceSystem &crs, const QString &name, QgsCoordinateReferenceSystem::Format nativeFormat = QgsCoordinateReferenceSystem::FormatWkt );
%Docstring
Updates the definition of the existing user CRS with matching ``id``.

The ``crs`` argument specifies a CRS with the desired new definition.

Returns ``False`` if the new CRS definition could not be saved.

The ``nativeFormat`` argument specifies the format to use when saving the CRS
definition. FormatWkt is recommended as it is a lossless format.

.. warning::

Not all CRS definitions can be represented as a Proj string, so
take care when using the FormatProj option.

.. seealso:: :py:func:`addUserCrs`

.. seealso:: :py:func:`userCrsChanged`
%End

signals:

void userCrsChanged( const QString &id );
%Docstring
Emitted whenever an existing user CRS definition is changed.

The ``id`` argument specifies the ID of the user CRS which has been changed.

Objects which store QgsCoordinateReferenceSystem members should connect to this signal
and update any stored CRS definitions to ensure that they always use the current
definition of any user defined CRSes.

.. seealso:: :py:func:`crsDefinitionsChanged`

.. seealso:: :py:func:`userCrsAdded`
%End

void userCrsAdded( const QString &id );
%Docstring
Emitted whenever a new user CRS definition is added.

The ``id`` argument specifies the ID of the user CRS which has been changed.

.. seealso:: :py:func:`userCrsChanged`

.. seealso:: :py:func:`crsDefinitionsChanged`
%End

void crsDefinitionsChanged();
%Docstring
Emitted whenever an operation has caused any of the known CRS definitions (including
user-defined CRS) to change.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgscoordinatereferencesystemregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -31,6 +31,7 @@
%Include auto_generated/qgsconnectionregistry.sip
%Include auto_generated/qgscoordinateformatter.sip
%Include auto_generated/qgscoordinatereferencesystem.sip
%Include auto_generated/qgscoordinatereferencesystemregistry.sip
%Include auto_generated/qgscoordinatetransform.sip
%Include auto_generated/qgscoordinatetransformcontext.sip
%Include auto_generated/qgscredentials.sip
Expand Down
35 changes: 5 additions & 30 deletions src/app/qgscustomprojectiondialog.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgssettings.h"
#include "qgssqliteutils.h"
#include "qgsgui.h"
#include "qgscoordinatereferencesystemregistry.h"

//qt includes
#include <QFileInfo>
Expand Down Expand Up @@ -259,45 +260,20 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem crs, const
QString ellipsoidAcronym = crs.ellipsoidAcronym();
if ( newEntry )
{
returnId = crs.saveAsUserCrs( name, format );
returnId = QgsApplication::coordinateReferenceSystemRegistry()->addUserCrs( crs, name, format );
if ( returnId == -1 )
return false;
else
id = QString::number( returnId );
}
else
{
sql = "update tbl_srs set description="
+ QgsSqliteUtils::quotedString( name )
+ ",projection_acronym=" + ( !projectionAcronym.isEmpty() ? QgsSqliteUtils::quotedString( projectionAcronym ) : QStringLiteral( "''" ) )
+ ",ellipsoid_acronym=" + ( !ellipsoidAcronym.isEmpty() ? QgsSqliteUtils::quotedString( ellipsoidAcronym ) : QStringLiteral( "''" ) )
+ ",parameters=" + ( !crs.toProj().isEmpty() ? QgsSqliteUtils::quotedString( crs.toProj() ) : QStringLiteral( "''" ) )
+ ",is_geo=0" // <--shamelessly hard coded for now
+ ",wkt=" + ( format == QgsCoordinateReferenceSystem::FormatWkt ? QgsSqliteUtils::quotedString( crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED, false ) ) : QStringLiteral( "''" ) )
+ " where srs_id=" + QgsSqliteUtils::quotedString( id )
;
QgsDebugMsgLevel( sql, 4 );
sqlite3_database_unique_ptr database;
//check if the db is available
int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
if ( result != SQLITE_OK )
if ( !QgsApplication::coordinateReferenceSystemRegistry()->updateUserCrs( id.toLong(), crs, name ) )
{
QgsDebugMsg( QStringLiteral( "Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) " ).arg( database.errorMessage(),
QgsApplication::qgisUserDatabaseFilePath() ) );
// XXX This will likely never happen since on open, sqlite creates the
// database if it does not exist.
Q_ASSERT( result == SQLITE_OK );
}
sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
{
QgsDebugMsg( QStringLiteral( "failed to write to database in custom projection dialog: %1 [%2]" ).arg( sql, database.errorMessage() ) );
}

preparedStatement.reset();
if ( result != SQLITE_OK )
return false;
}
}

mExistingCRSwkt[id] = format == QgsCoordinateReferenceSystem::FormatWkt ? crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED, false ) : QString();
mExistingCRSproj[id] = format == QgsCoordinateReferenceSystem::FormatProj ? crs.toProj() : QString();
mExistingCRSnames[id] = name;
Expand All @@ -313,7 +289,6 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem crs, const
return true;
}


void QgsCustomProjectionDialog::pbnAdd_clicked()
{
QString name = tr( "new CRS" );
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -283,6 +283,7 @@ set(QGIS_CORE_SRCS
qgsconnectionregistry.cpp
qgscoordinateformatter.cpp
qgscoordinatereferencesystem.cpp
qgscoordinatereferencesystemregistry.cpp
qgscoordinatetransform.cpp
qgscoordinatetransform_p.cpp
qgscoordinatetransformcontext.cpp
Expand Down Expand Up @@ -867,6 +868,7 @@ set(QGIS_CORE_HDRS
qgsconnectionregistry.h
qgscoordinateformatter.h
qgscoordinatereferencesystem.h
qgscoordinatereferencesystemregistry.h
qgscoordinatetransform.h
qgscoordinatetransformcontext.h
qgscoordinateutils.h
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -43,6 +43,7 @@
#include "qgsrasterrendererregistry.h"
#include "qgsrendererregistry.h"
#include "qgspointcloudrendererregistry.h"
#include "qgscoordinatereferencesystemregistry.h"
#include "qgssymbollayerregistry.h"
#include "qgssymbollayerutils.h"
#include "qgscalloutsregistry.h"
Expand Down Expand Up @@ -2212,6 +2213,11 @@ QgsDataItemProviderRegistry *QgsApplication::dataItemProviderRegistry()
}
}

QgsCoordinateReferenceSystemRegistry *QgsApplication::coordinateReferenceSystemRegistry()
{
return members()->mCrsRegistry;
}

QgsSvgCache *QgsApplication::svgCache()
{
return members()->mSvgCache;
Expand Down Expand Up @@ -2355,6 +2361,11 @@ QgsApplication::ApplicationMembers::ApplicationMembers()
mMessageLog = new QgsMessageLog();
QgsRuntimeProfiler *profiler = QgsRuntimeProfiler::threadLocalInstance();

{
profiler->start( tr( "Setup coordinate reference system registry" ) );
mCrsRegistry = new QgsCoordinateReferenceSystemRegistry();
profiler->end();
}
{
profiler->start( tr( "Create connection registry" ) );
mConnectionRegistry = new QgsConnectionRegistry();
Expand Down Expand Up @@ -2546,6 +2557,7 @@ QgsApplication::ApplicationMembers::~ApplicationMembers()
delete mBookmarkManager;
delete mConnectionRegistry;
delete mLocalizedDataPathRegistry;
delete mCrsRegistry;
}

QgsApplication::ApplicationMembers *QgsApplication::members()
Expand Down
10 changes: 10 additions & 0 deletions src/core/qgsapplication.h
Expand Up @@ -65,6 +65,7 @@ class QgsScaleBarRendererRegistry;
class Qgs3DSymbolRegistry;
class QgsPointCloudRendererRegistry;
class QgsTileDownloadManager;
class QgsCoordinateReferenceSystemRegistry;

/**
* \ingroup core
Expand Down Expand Up @@ -654,6 +655,14 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
static QgsDataItemProviderRegistry *dataItemProviderRegistry() SIP_KEEPREFERENCE;

/**
* Returns the application's coordinate reference system (CRS) registry, which handles
* known CRS definitions (including user-defined CRSes).
*
* \since QGIS 3.18
*/
static QgsCoordinateReferenceSystemRegistry *coordinateReferenceSystemRegistry() SIP_KEEPREFERENCE;

/**
* Returns the application's SVG cache, used for caching SVG images and handling parameter replacement
* within SVG files.
Expand Down Expand Up @@ -985,6 +994,7 @@ class CORE_EXPORT QgsApplication : public QApplication

struct ApplicationMembers
{
QgsCoordinateReferenceSystemRegistry *mCrsRegistry = nullptr;
Qgs3DRendererRegistry *m3DRendererRegistry = nullptr;
Qgs3DSymbolRegistry *m3DSymbolRegistry = nullptr;
QgsActionScopeRegistry *mActionScopeRegistry = nullptr;
Expand Down

0 comments on commit 1499250

Please sign in to comment.