Skip to content

Commit

Permalink
Move logic for removing user crs to QgsCoordinateReferenceSystemRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jan 27, 2021
1 parent bc9919c commit fae30b5
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 33 deletions.
Expand Up @@ -69,6 +69,15 @@ definition. FormatWkt is recommended as it is a lossless format.
.. seealso:: :py:func:`addUserCrs`

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

bool removeUserCrs( long id );
%Docstring
Removes the existing user CRS with matching ``id``.

Returns ``False`` if the CRS could not be removed.

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

signals:
Expand Down Expand Up @@ -97,6 +106,14 @@ The ``id`` argument specifies the ID of the user CRS which has been changed.
.. seealso:: :py:func:`userCrsChanged`

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

void userCrsRemoved( long id );
%Docstring
Emitted when the user CRS with matching ``id`` is removed
from the database.

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

void crsDefinitionsChanged();
Expand Down
34 changes: 2 additions & 32 deletions src/app/qgscustomprojectiondialog.cpp
Expand Up @@ -168,36 +168,6 @@ void QgsCustomProjectionDialog::populateList()
}
}

bool QgsCustomProjectionDialog::deleteCrs( const QString &id )
{
sqlite3_database_unique_ptr database;

QString sql = "delete from tbl_srs where srs_id=" + QgsSqliteUtils::quotedString( id );
QgsDebugMsgLevel( sql, 4 );
//check the db is available
int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
if ( result != SQLITE_OK )
{
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 remove CRS from database in custom projection dialog: %1 [%2]" ).arg( sql, database.errorMessage() ) );
}
}

QgsCoordinateReferenceSystem::invalidateCache();
QgsCoordinateTransform::invalidateCache();

return result == SQLITE_OK;
}

void QgsCustomProjectionDialog::insertProjection( const QString &projectionAcronym )
{
sqlite3_database_unique_ptr database;
Expand Down Expand Up @@ -268,7 +238,7 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem crs, const
}
else
{
if ( !QgsApplication::coordinateReferenceSystemRegistry()->updateUserCrs( id.toLong(), crs, name ) )
if ( !QgsApplication::coordinateReferenceSystemRegistry()->updateUserCrs( id.toLong(), crs, name, format ) )
{
return false;
}
Expand Down Expand Up @@ -513,7 +483,7 @@ void QgsCustomProjectionDialog::buttonBox_accepted()
QgsDebugMsgLevel( QStringLiteral( "We remove the deleted CRS." ), 4 );
for ( int i = 0; i < mDeletedCRSs.size(); ++i )
{
saveSuccess &= deleteCrs( mDeletedCRSs[i] );
saveSuccess &= QgsApplication::coordinateReferenceSystemRegistry()->removeUserCrs( mDeletedCRSs[i].toLong() );
if ( ! saveSuccess )
{
QgsDebugMsg( QStringLiteral( "Error deleting CRS for '%1'" ).arg( mDefinitions[i].name ) );
Expand Down
1 change: 0 additions & 1 deletion src/app/qgscustomprojectiondialog.h
Expand Up @@ -52,7 +52,6 @@ class APP_EXPORT QgsCustomProjectionDialog : public QDialog, private Ui::QgsCust

//helper functions
void populateList();
bool deleteCrs( const QString &id );
bool saveCrs( QgsCoordinateReferenceSystem crs, const QString &name, const QString &id, bool newEntry, QgsCoordinateReferenceSystem::Format format );
void insertProjection( const QString &projectionAcronym );
void showHelp();
Expand Down
50 changes: 50 additions & 0 deletions src/core/qgscoordinatereferencesystemregistry.cpp
Expand Up @@ -176,3 +176,53 @@ bool QgsCoordinateReferenceSystemRegistry::updateUserCrs( long id, const QgsCoor

return res;
}

bool QgsCoordinateReferenceSystemRegistry::removeUserCrs( long id )
{
sqlite3_database_unique_ptr database;

QString sql = "delete from tbl_srs where srs_id=" + QgsSqliteUtils::quotedString( QString::number( id ) );
QgsDebugMsgLevel( sql, 4 );
//check the db is available
int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
if ( result != SQLITE_OK )
{
QgsDebugMsg( QStringLiteral( "Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) " ).arg( database.errorMessage(),
QgsApplication::qgisUserDatabaseFilePath() ) );
return false;
}

bool res = true;
{
sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
{
QgsDebugMsg( QStringLiteral( "failed to remove custom CRS from database: %1 [%2]" ).arg( sql, database.errorMessage() ) );
res = false;
}
else
{
const int changed = sqlite3_changes( database.get() );
if ( changed )
{
QgsMessageLog::logMessage( QObject::tr( "Removed user CRS [%1]" ).arg( id ), QObject::tr( "CRS" ) );
}
else
{
QgsMessageLog::logMessage( QObject::tr( "Error removing user CRS [%1]: No matching ID found in database" ).arg( id ), QObject::tr( "CRS" ) );
res = false;
}
}
}

QgsCoordinateReferenceSystem::invalidateCache();
QgsCoordinateTransform::invalidateCache();

if ( res )
{
emit userCrsRemoved( id );
emit crsDefinitionsChanged();
}

return res;
}
17 changes: 17 additions & 0 deletions src/core/qgscoordinatereferencesystemregistry.h
Expand Up @@ -76,6 +76,15 @@ class CORE_EXPORT QgsCoordinateReferenceSystemRegistry : public QObject
*/
bool updateUserCrs( long id, const QgsCoordinateReferenceSystem &crs, const QString &name, QgsCoordinateReferenceSystem::Format nativeFormat = QgsCoordinateReferenceSystem::FormatWkt );

/**
* Removes the existing user CRS with matching \a id.
*
* Returns FALSE if the CRS could not be removed.
*
* \see userCrsRemoved()
*/
bool removeUserCrs( long id );

signals:

/**
Expand All @@ -102,6 +111,14 @@ class CORE_EXPORT QgsCoordinateReferenceSystemRegistry : public QObject
*/
void userCrsAdded( const QString &id );

/**
* Emitted when the user CRS with matching \a id is removed
* from the database.
*
* \see removeUserCrs()
*/
void userCrsRemoved( long id );

/**
* Emitted whenever an operation has caused any of the known CRS definitions (including
* user-defined CRS) to change.
Expand Down
57 changes: 57 additions & 0 deletions tests/src/core/testqgscoordinatereferencesystemregistry.cpp
Expand Up @@ -30,6 +30,7 @@ class TestQgsCoordinateReferenceSystemRegistry: public QObject
void cleanupTestCase();
void addUserCrs();
void changeUserCrs();
void removeUserCrs();

private:

Expand Down Expand Up @@ -178,5 +179,61 @@ void TestQgsCoordinateReferenceSystemRegistry::changeUserCrs()
QCOMPARE( crs3.toProj(), madeUpProjection2 );
}

void TestQgsCoordinateReferenceSystemRegistry::removeUserCrs()
{
QgsCoordinateReferenceSystemRegistry *registry = QgsApplication::coordinateReferenceSystemRegistry();

QString madeUpProjection = QStringLiteral( "+proj=aea +lat_1=27 +lat_2=-26 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs" );
QgsCoordinateReferenceSystem userCrs = QgsCoordinateReferenceSystem::fromProj( madeUpProjection );
QVERIFY( userCrs.isValid() );
QCOMPARE( userCrs.toProj(), madeUpProjection );
QCOMPARE( userCrs.srsid(), 0L ); // not saved to database yet

QSignalSpy spyAdded( registry, &QgsCoordinateReferenceSystemRegistry::userCrsAdded );
QSignalSpy spyChanged( registry, &QgsCoordinateReferenceSystemRegistry::userCrsChanged );
QSignalSpy spyRemoved( registry, &QgsCoordinateReferenceSystemRegistry::userCrsRemoved );
QSignalSpy spyCrsDefsChanged( registry, &QgsCoordinateReferenceSystemRegistry::crsDefinitionsChanged );

// non-existing crs - should be rejected
bool res = registry->removeUserCrs( 100100 );
QVERIFY( !res );
QCOMPARE( spyAdded.length(), 0 );
QCOMPARE( spyChanged.length(), 0 );
QCOMPARE( spyRemoved.length(), 0 );
QCOMPARE( spyCrsDefsChanged.length(), 0 );

// add valid new user crs
const long id = registry->addUserCrs( userCrs, QStringLiteral( "test" ) );
QVERIFY( id != -1L );
const QString authid = userCrs.authid();
QCOMPARE( spyAdded.length(), 1 );
QCOMPARE( spyAdded.at( 0 ).at( 0 ).toString(), authid );
QCOMPARE( spyChanged.length(), 0 );
QCOMPARE( spyRemoved.length(), 0 );
QCOMPARE( spyCrsDefsChanged.length(), 1 );

QgsCoordinateReferenceSystem crs2( authid );
QVERIFY( crs2.isValid() );

// now try removing it
connect( registry, &QgsCoordinateReferenceSystemRegistry::userCrsRemoved, this, [&]
{
// make sure that caches are invalidated before the signals are emitted
QgsCoordinateReferenceSystem crs4( authid );
QVERIFY( !crs4.isValid() );
} );
QVERIFY( registry->removeUserCrs( id ) );

QCOMPARE( spyAdded.length(), 1 );
QCOMPARE( spyChanged.length(), 0 );
QCOMPARE( spyRemoved.length(), 1 );
QCOMPARE( spyRemoved.at( 0 ).at( 0 ).toLongLong(), static_cast< long long >( id ) );
QCOMPARE( spyCrsDefsChanged.length(), 2 );

// doesn't exist anymore...
QgsCoordinateReferenceSystem crs3( authid );
QVERIFY( !crs3.isValid() );
}

QGSTEST_MAIN( TestQgsCoordinateReferenceSystemRegistry )
#include "testqgscoordinatereferencesystemregistry.moc"

0 comments on commit fae30b5

Please sign in to comment.