|
31 | 31 | #include "qgsmessageoutput.h"
|
32 | 32 | #include "qgis.h" //const vals declared here
|
33 | 33 |
|
| 34 | +#include <cassert> |
34 | 35 | #include <sqlite3.h>
|
35 | 36 |
|
36 | 37 | //gdal and ogr includes (needed for == operator)
|
@@ -349,18 +350,20 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
|
349 | 350 | * have been set if this method has been delegated to from createFromWkt.
|
350 | 351 | * Normally we wouldnt expect this to work, but its worth trying first
|
351 | 352 | * as its quicker than methods below..
|
352 |
| - */ |
| 353 | + */ |
353 | 354 | long mySrsId = 0;
|
354 | 355 | QgsCoordinateReferenceSystem::RecordMap myRecord;
|
355 |
| - if ( !mDescription.trimmed().isEmpty() ) |
356 |
| - { |
357 |
| - myRecord = getRecord( "select * from tbl_srs where description='" + mDescription.trimmed() + "'" ); |
358 |
| - } |
| 356 | + |
| 357 | + // *** Matching on descriptions feels iffy. Different projs can have same description. Homann *** |
| 358 | + // if ( !mDescription.trimmed().isEmpty() ) |
| 359 | + //{ |
| 360 | + // myRecord = getRecord( "select * from tbl_srs where description='" + mDescription.trimmed() + "'" ); |
| 361 | + //} |
359 | 362 |
|
360 | 363 | /*
|
361 | 364 | * - if the above does not match perform a whole text search on proj4 string (if not null)
|
362 | 365 | */
|
363 |
| - QgsDebugMsg( "wholetext match on name failed, trying proj4string match" ); |
| 366 | + // QgsDebugMsg( "wholetext match on name failed, trying proj4string match" ); |
364 | 367 | myRecord = getRecord( "select * from tbl_srs where parameters='" + theProj4String.trimmed() + "'" );
|
365 | 368 | if ( !myRecord.empty() )
|
366 | 369 | {
|
@@ -434,7 +437,34 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
|
434 | 437 | // if we failed to look up the projection in database, don't worry. we can still use it :)
|
435 | 438 | if ( !mIsValidFlag )
|
436 | 439 | {
|
| 440 | + QgsDebugMsg( "Projection is not found in databases." ); |
437 | 441 | setProj4String( theProj4String );
|
| 442 | + // Is the SRS is valid now, we know it's a decent +proj string that can be entered into the srs.db |
| 443 | + if ( mIsValidFlag ) |
| 444 | + { |
| 445 | + // Try to save. If not possible, set to invalid. Problems on read only systems? |
| 446 | + QgsDebugMsg( "Projection appears to be valid. Save to database!" ); |
| 447 | + mIsValidFlag = saveAsUserCRS(); |
| 448 | + // The srsid is not set, we should do that now. |
| 449 | + if ( mIsValidFlag ) |
| 450 | + { |
| 451 | + myRecord = getRecord( "select * from tbl_srs where parameters='" + theProj4String.trimmed() + "'" ); |
| 452 | + if ( !myRecord.empty() ) |
| 453 | + { |
| 454 | + mySrsId = myRecord["srs_id"].toLong(); |
| 455 | + QgsDebugMsg( "proj4string match search for srsid returned srsid: " + QString::number( mySrsId ) ); |
| 456 | + if ( mySrsId > 0 ) |
| 457 | + { |
| 458 | + createFromSrsId( mySrsId ); |
| 459 | + } |
| 460 | + else |
| 461 | + { |
| 462 | + QgsDebugMsg( "Couldn't find newly added proj string?" ); |
| 463 | + mIsValidFlag = false; |
| 464 | + } |
| 465 | + } |
| 466 | + } |
| 467 | + } |
438 | 468 | }
|
439 | 469 |
|
440 | 470 |
|
@@ -610,7 +640,8 @@ QString QgsCoordinateReferenceSystem::toProj4() const
|
610 | 640 | toProj4 = proj4src;
|
611 | 641 | CPLFree( proj4src );
|
612 | 642 |
|
613 |
| - return toProj4; |
| 643 | + // Stray spaces at the end? |
| 644 | + return toProj4.trimmed(); |
614 | 645 | }
|
615 | 646 |
|
616 | 647 | bool QgsCoordinateReferenceSystem::geographicFlag() const
|
@@ -740,7 +771,7 @@ long QgsCoordinateReferenceSystem::findMatchingProj()
|
740 | 771 | QgsDebugMsg( "entered." );
|
741 | 772 | if ( mEllipsoidAcronym.isNull() || mProjectionAcronym.isNull() || !mIsValidFlag )
|
742 | 773 | {
|
743 |
| - QgsLogger::warning( "QgsCoordinateReferenceSystem::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!..." ); |
| 774 | + QgsDebugMsg( "QgsCoordinateReferenceSystem::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!..." ); |
744 | 775 | return 0;
|
745 | 776 | }
|
746 | 777 |
|
@@ -1122,3 +1153,127 @@ QString QgsCoordinateReferenceSystem::validationHint()
|
1122 | 1153 | {
|
1123 | 1154 | return mValidationHint;
|
1124 | 1155 | }
|
| 1156 | + |
| 1157 | +/// Copied from QgsCustomProjectionDialog /// |
| 1158 | +/// Please refactor into SQL handler !!! /// |
| 1159 | + |
| 1160 | +bool QgsCoordinateReferenceSystem::saveAsUserCRS() |
| 1161 | +{ |
| 1162 | + |
| 1163 | + if ( ! mIsValidFlag ) |
| 1164 | + { |
| 1165 | + QgsDebugMsg( "Can't save an invalid CRS!" ); |
| 1166 | + return false; |
| 1167 | + } |
| 1168 | + |
| 1169 | + QString mySql; |
| 1170 | + QString myName = QString( " * %1 (%2)" ) |
| 1171 | + .arg( QObject::tr( "Generated CRS", "A CRS automatically generated from layer info get this prefix for description" )) |
| 1172 | + .arg( toProj4() ); |
| 1173 | + |
| 1174 | + //if this is the first record we need to ensure that its srs_id is 10000. For |
| 1175 | + //any rec after that sqlite3 will take care of the autonumering |
| 1176 | + //this was done to support sqlite 3.0 as it does not yet support |
| 1177 | + //the autoinc related system tables. |
| 1178 | + if ( getRecordCount() == 0 ) |
| 1179 | + { |
| 1180 | + mySql = QString( "insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) " ) |
| 1181 | + + " values (" + QString::number( USER_CRS_START_ID ) + ",'" |
| 1182 | + + sqlSafeString( myName ) + "','" + projectionAcronym() |
| 1183 | + + "','" + ellipsoidAcronym() + "','" + sqlSafeString( toProj4() ) |
| 1184 | + + "',0)"; // <-- is_geo shamelessly hard coded for now |
| 1185 | + } |
| 1186 | + else |
| 1187 | + { |
| 1188 | + mySql = "insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ('" |
| 1189 | + + sqlSafeString( myName ) + "','" + projectionAcronym() |
| 1190 | + + "','" + ellipsoidAcronym() + "','" + sqlSafeString( toProj4() ) |
| 1191 | + + "',0)"; // <-- is_geo shamelessly hard coded for now |
| 1192 | + } |
| 1193 | + sqlite3 *myDatabase; |
| 1194 | + const char *myTail; |
| 1195 | + sqlite3_stmt *myPreparedStatement; |
| 1196 | + int myResult; |
| 1197 | + //check the db is available |
| 1198 | + myResult = sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().data(), &myDatabase ); |
| 1199 | + if ( myResult != SQLITE_OK ) |
| 1200 | + { |
| 1201 | + 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() ) ); |
| 1202 | + // XXX This will likely never happen since on open, sqlite creates the |
| 1203 | + // database if it does not exist. |
| 1204 | + assert( myResult == SQLITE_OK ); |
| 1205 | + } |
| 1206 | + QgsDebugMsg( QString( "Update or insert sql \n%1" ).arg( mySql ) ); |
| 1207 | + myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.length(), &myPreparedStatement, &myTail ); |
| 1208 | + sqlite3_step( myPreparedStatement ); |
| 1209 | + // XXX Need to free memory from the error msg if one is set |
| 1210 | + return myResult == SQLITE_OK; |
| 1211 | + |
| 1212 | +} |
| 1213 | + |
| 1214 | +long QgsCoordinateReferenceSystem::getRecordCount() |
| 1215 | +{ |
| 1216 | + sqlite3 *myDatabase; |
| 1217 | + const char *myTail; |
| 1218 | + sqlite3_stmt *myPreparedStatement; |
| 1219 | + int myResult; |
| 1220 | + long myRecordCount = 0; |
| 1221 | + //check the db is available |
| 1222 | + myResult = sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().data(), &myDatabase ); |
| 1223 | + if ( myResult != SQLITE_OK ) |
| 1224 | + { |
| 1225 | + QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) ); |
| 1226 | + // XXX This will likely never happen since on open, sqlite creates the |
| 1227 | + // database if it does not exist. |
| 1228 | + assert( myResult == SQLITE_OK ); |
| 1229 | + } |
| 1230 | + // Set up the query to retrieve the projection information needed to populate the ELLIPSOID list |
| 1231 | + QString mySql = "select count(*) from tbl_srs"; |
| 1232 | + myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.length(), &myPreparedStatement, &myTail ); |
| 1233 | + // XXX Need to free memory from the error msg if one is set |
| 1234 | + if ( myResult == SQLITE_OK ) |
| 1235 | + { |
| 1236 | + if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW ) |
| 1237 | + { |
| 1238 | + QString myRecordCountString = QString::fromUtf8(( char * )sqlite3_column_text( myPreparedStatement, 0 ) ); |
| 1239 | + myRecordCount = myRecordCountString.toLong(); |
| 1240 | + } |
| 1241 | + } |
| 1242 | + // close the sqlite3 statement |
| 1243 | + sqlite3_finalize( myPreparedStatement ); |
| 1244 | + sqlite3_close( myDatabase ); |
| 1245 | + return myRecordCount; |
| 1246 | + |
| 1247 | +} |
| 1248 | + |
| 1249 | +const QString QgsCoordinateReferenceSystem::sqlSafeString( const QString theSQL ) |
| 1250 | +{ |
| 1251 | + |
| 1252 | + QString myRetval; |
| 1253 | + QChar *it = ( QChar * )theSQL.unicode(); |
| 1254 | + for ( int i = 0; i < theSQL.length(); i++ ) |
| 1255 | + { |
| 1256 | + if ( *it == '\"' ) |
| 1257 | + { |
| 1258 | + myRetval += "\\\""; |
| 1259 | + } |
| 1260 | + else if ( *it == '\'' ) |
| 1261 | + { |
| 1262 | + myRetval += "\\'"; |
| 1263 | + } |
| 1264 | + else if ( *it == '\\' ) |
| 1265 | + { |
| 1266 | + myRetval += "\\\\"; |
| 1267 | + } |
| 1268 | + else if ( *it == '%' ) |
| 1269 | + { |
| 1270 | + myRetval += "\\%"; |
| 1271 | + } |
| 1272 | + else |
| 1273 | + { |
| 1274 | + myRetval += *it; |
| 1275 | + } |
| 1276 | + it++; |
| 1277 | + } |
| 1278 | + return myRetval; |
| 1279 | +} |
0 commit comments