[QGIS Commit] r11366 - trunk/qgis/src/core
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Thu Aug 13 19:10:33 EDT 2009
Author: homann
Date: 2009-08-13 19:10:32 -0400 (Thu, 13 Aug 2009)
New Revision: 11366
Modified:
trunk/qgis/src/core/qgscoordinatereferencesystem.cpp
trunk/qgis/src/core/qgscoordinatereferencesystem.h
Log:
Automatically adds projections previously unknown to QGIS (but still valid) as a Custom CRS. This can later be edited for name etc. No user interaction required, one new text to translate. Fixes #418.
Modified: trunk/qgis/src/core/qgscoordinatereferencesystem.cpp
===================================================================
--- trunk/qgis/src/core/qgscoordinatereferencesystem.cpp 2009-08-13 20:43:26 UTC (rev 11365)
+++ trunk/qgis/src/core/qgscoordinatereferencesystem.cpp 2009-08-13 23:10:32 UTC (rev 11366)
@@ -31,6 +31,7 @@
#include "qgsmessageoutput.h"
#include "qgis.h" //const vals declared here
+#include <cassert>
#include <sqlite3.h>
//gdal and ogr includes (needed for == operator)
@@ -349,18 +350,20 @@
* have been set if this method has been delegated to from createFromWkt.
* Normally we wouldnt expect this to work, but its worth trying first
* as its quicker than methods below..
- */
+ */
long mySrsId = 0;
QgsCoordinateReferenceSystem::RecordMap myRecord;
- if ( !mDescription.trimmed().isEmpty() )
- {
- myRecord = getRecord( "select * from tbl_srs where description='" + mDescription.trimmed() + "'" );
- }
+ // *** Matching on descriptions feels iffy. Different projs can have same description. Homann ***
+ // if ( !mDescription.trimmed().isEmpty() )
+ //{
+ // myRecord = getRecord( "select * from tbl_srs where description='" + mDescription.trimmed() + "'" );
+ //}
+
/*
* - if the above does not match perform a whole text search on proj4 string (if not null)
*/
- QgsDebugMsg( "wholetext match on name failed, trying proj4string match" );
+ // QgsDebugMsg( "wholetext match on name failed, trying proj4string match" );
myRecord = getRecord( "select * from tbl_srs where parameters='" + theProj4String.trimmed() + "'" );
if ( !myRecord.empty() )
{
@@ -434,7 +437,34 @@
// if we failed to look up the projection in database, don't worry. we can still use it :)
if ( !mIsValidFlag )
{
+ QgsDebugMsg( "Projection is not found in databases." );
setProj4String( theProj4String );
+ // Is the SRS is valid now, we know it's a decent +proj string that can be entered into the srs.db
+ if ( mIsValidFlag )
+ {
+ // Try to save. If not possible, set to invalid. Problems on read only systems?
+ QgsDebugMsg( "Projection appears to be valid. Save to database!" );
+ mIsValidFlag = saveAsUserCRS();
+ // The srsid is not set, we should do that now.
+ if ( mIsValidFlag )
+ {
+ myRecord = getRecord( "select * from tbl_srs where parameters='" + theProj4String.trimmed() + "'" );
+ if ( !myRecord.empty() )
+ {
+ mySrsId = myRecord["srs_id"].toLong();
+ QgsDebugMsg( "proj4string match search for srsid returned srsid: " + QString::number( mySrsId ) );
+ if ( mySrsId > 0 )
+ {
+ createFromSrsId( mySrsId );
+ }
+ else
+ {
+ QgsDebugMsg( "Couldn't find newly added proj string?" );
+ mIsValidFlag = false;
+ }
+ }
+ }
+ }
}
@@ -610,7 +640,8 @@
toProj4 = proj4src;
CPLFree( proj4src );
- return toProj4;
+ // Stray spaces at the end?
+ return toProj4.trimmed();
}
bool QgsCoordinateReferenceSystem::geographicFlag() const
@@ -740,7 +771,7 @@
QgsDebugMsg( "entered." );
if ( mEllipsoidAcronym.isNull() || mProjectionAcronym.isNull() || !mIsValidFlag )
{
- QgsLogger::warning( "QgsCoordinateReferenceSystem::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!..." );
+ QgsDebugMsg( "QgsCoordinateReferenceSystem::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!..." );
return 0;
}
@@ -1122,3 +1153,127 @@
{
return mValidationHint;
}
+
+/// Copied from QgsCustomProjectionDialog ///
+/// Please refactor into SQL handler !!! ///
+
+bool QgsCoordinateReferenceSystem::saveAsUserCRS()
+{
+
+ if ( ! mIsValidFlag )
+ {
+ QgsDebugMsg( "Can't save an invalid CRS!" );
+ return false;
+ }
+
+ QString mySql;
+ QString myName = QString( " * %1 (%2)" )
+ .arg( QObject::tr( "Generated CRS", "A CRS automatically generated from layer info get this prefix for description" ))
+ .arg( toProj4() );
+
+ //if this is the first record we need to ensure that its srs_id is 10000. For
+ //any rec after that sqlite3 will take care of the autonumering
+ //this was done to support sqlite 3.0 as it does not yet support
+ //the autoinc related system tables.
+ if ( getRecordCount() == 0 )
+ {
+ mySql = QString( "insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) " )
+ + " values (" + QString::number( USER_CRS_START_ID ) + ",'"
+ + sqlSafeString( myName ) + "','" + projectionAcronym()
+ + "','" + ellipsoidAcronym() + "','" + sqlSafeString( toProj4() )
+ + "',0)"; // <-- is_geo shamelessly hard coded for now
+ }
+ else
+ {
+ mySql = "insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ('"
+ + sqlSafeString( myName ) + "','" + projectionAcronym()
+ + "','" + ellipsoidAcronym() + "','" + sqlSafeString( toProj4() )
+ + "',0)"; // <-- is_geo shamelessly hard coded for now
+ }
+ sqlite3 *myDatabase;
+ const char *myTail;
+ sqlite3_stmt *myPreparedStatement;
+ int myResult;
+ //check the db is available
+ myResult = sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().data(), &myDatabase );
+ if ( myResult != SQLITE_OK )
+ {
+ QgsDebugMsg( QString( "Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) " ).arg( sqlite3_errmsg( myDatabase ) ).arg( QgsApplication::qgisUserDbFilePath() ) );
+ // XXX This will likely never happen since on open, sqlite creates the
+ // database if it does not exist.
+ assert( myResult == SQLITE_OK );
+ }
+ QgsDebugMsg( QString( "Update or insert sql \n%1" ).arg( mySql ) );
+ myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.length(), &myPreparedStatement, &myTail );
+ sqlite3_step( myPreparedStatement );
+ // XXX Need to free memory from the error msg if one is set
+ return myResult == SQLITE_OK;
+
+}
+
+long QgsCoordinateReferenceSystem::getRecordCount()
+{
+ sqlite3 *myDatabase;
+ const char *myTail;
+ sqlite3_stmt *myPreparedStatement;
+ int myResult;
+ long myRecordCount = 0;
+ //check the db is available
+ myResult = sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().data(), &myDatabase );
+ if ( myResult != SQLITE_OK )
+ {
+ QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
+ // XXX This will likely never happen since on open, sqlite creates the
+ // database if it does not exist.
+ assert( myResult == SQLITE_OK );
+ }
+ // Set up the query to retrieve the projection information needed to populate the ELLIPSOID list
+ QString mySql = "select count(*) from tbl_srs";
+ myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.length(), &myPreparedStatement, &myTail );
+ // XXX Need to free memory from the error msg if one is set
+ if ( myResult == SQLITE_OK )
+ {
+ if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
+ {
+ QString myRecordCountString = QString::fromUtf8(( char * )sqlite3_column_text( myPreparedStatement, 0 ) );
+ myRecordCount = myRecordCountString.toLong();
+ }
+ }
+ // close the sqlite3 statement
+ sqlite3_finalize( myPreparedStatement );
+ sqlite3_close( myDatabase );
+ return myRecordCount;
+
+}
+
+const QString QgsCoordinateReferenceSystem::sqlSafeString( const QString theSQL )
+{
+
+ QString myRetval;
+ QChar *it = ( QChar * )theSQL.unicode();
+ for ( int i = 0; i < theSQL.length(); i++ )
+ {
+ if ( *it == '\"' )
+ {
+ myRetval += "\\\"";
+ }
+ else if ( *it == '\'' )
+ {
+ myRetval += "\\'";
+ }
+ else if ( *it == '\\' )
+ {
+ myRetval += "\\\\";
+ }
+ else if ( *it == '%' )
+ {
+ myRetval += "\\%";
+ }
+ else
+ {
+ myRetval += *it;
+ }
+ it++;
+ }
+ return myRetval;
+}
Modified: trunk/qgis/src/core/qgscoordinatereferencesystem.h
===================================================================
--- trunk/qgis/src/core/qgscoordinatereferencesystem.h 2009-08-13 20:43:26 UTC (rev 11365)
+++ trunk/qgis/src/core/qgscoordinatereferencesystem.h 2009-08-13 23:10:32 UTC (rev 11366)
@@ -387,6 +387,15 @@
//! Work out the projection units and set the appropriate local variable
void setMapUnits();
+ //! Save the proj4-string as a custom CRS
+ bool saveAsUserCRS();
+
+ //! Helper for getting number of user CRS already in db
+ long getRecordCount();
+
+ //! Helper for sql-safin strings
+ const QString sqlSafeString( const QString theSQL );
+
void *mCRS;
bool loadFromDb( QString db, QString field, long id );
More information about the QGIS-commit
mailing list