Skip to content

Commit 6308416

Browse files
author
jef
committed
[FEATURE] allow user specific PROJ.4 search paths and update srs.db to include grid reference (fixes #3099)
git-svn-id: http://svn.osgeo.org/qgis/trunk@14399 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 9b287ce commit 6308416

7 files changed

+203
-78
lines changed

resources/srs.db

1 KB
Binary file not shown.

src/app/qgsoptions.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
8585
}
8686
}
8787

88+
//local directories to search when looking for an PROJ.4 file with a given basename
89+
foreach( QString path, settings.value( "projSearchPaths" ).toStringList() )
90+
{
91+
QListWidgetItem* newItem = new QListWidgetItem( mListProjPaths );
92+
newItem->setText( path );
93+
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
94+
mListProjPaths->addItem( newItem );
95+
}
96+
8897
//Network timeout
8998
mNetworkTimeoutSpinBox->setValue( settings.value( "/qgis/networkAndProxy/networkTimeout", "60000" ).toInt() );
9099

@@ -464,6 +473,13 @@ void QgsOptions::saveOptions()
464473
}
465474
settings.setValue( "svg/searchPathsForSVG", myPaths );
466475

476+
QStringList paths;
477+
for ( int i = 0; i < mListProjPaths->count(); ++i )
478+
{
479+
paths << mListProjPaths->item( i )->text();
480+
}
481+
settings.setValue( "projSearchPaths", paths );
482+
467483
//Network timeout
468484
settings.setValue( "/qgis/networkAndProxy/networkTimeout", mNetworkTimeoutSpinBox->value() );
469485

@@ -872,6 +888,33 @@ void QgsOptions::on_mBtnRemoveSVGPath_clicked()
872888
delete itemToRemove;
873889
}
874890

891+
void QgsOptions::on_mBtnAddProjPath_clicked()
892+
{
893+
QString myDir = QFileDialog::getExistingDirectory(
894+
this,
895+
tr( "Choose a directory" ),
896+
QDir::toNativeSeparators( QDir::homePath() ),
897+
QFileDialog::ShowDirsOnly
898+
);
899+
900+
if ( ! myDir.isEmpty() )
901+
{
902+
QListWidgetItem* newItem = new QListWidgetItem( mListProjPaths );
903+
newItem->setText( myDir );
904+
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
905+
mListProjPaths->addItem( newItem );
906+
mListProjPaths->setCurrentItem( newItem );
907+
}
908+
}
909+
910+
void QgsOptions::on_mBtnRemoveProjPath_clicked()
911+
{
912+
int currentRow = mListProjPaths->currentRow();
913+
QListWidgetItem* itemToRemove = mListProjPaths->takeItem( currentRow );
914+
delete itemToRemove;
915+
}
916+
917+
875918
void QgsOptions::on_mAddUrlPushButton_clicked()
876919
{
877920
QListWidgetItem* newItem = new QListWidgetItem( mExcludeUrlListWidget );

src/app/qgsoptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
101101
*/
102102
void on_mBtnRemoveSVGPath_clicked();
103103

104+
/* Let the user add a path to the list of search paths used for finding PROJ.4 files. */
105+
void on_mBtnAddProjPath_clicked();
106+
107+
/* Let the user remove a path to the list of search paths for finding PROJ.4 files. */
108+
void on_mBtnRemoveProjPath_clicked();
109+
104110
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
105111

106112
void on_mBrowseCacheDirectory_clicked();

src/core/qgscoordinatereferencesystem.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,9 +1161,10 @@ int QgsCoordinateReferenceSystem::openDb( QString path, sqlite3 **db )
11611161
// ... unfortunately it happens on Windows
11621162
QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
11631163
output->setTitle( "Error" );
1164-
output->setMessage( "Could not open CRS database " + path +
1165-
"<br>Error(" + QString::number( myResult ) + "): " +
1166-
QString( sqlite3_errmsg( *db ) ), QgsMessageOutput::MessageText );
1164+
output->setMessage( QObject::tr( "Could not open CRS database %1<br>Error(%2): %3" )
1165+
.arg( path )
1166+
.arg( myResult )
1167+
.arg( sqlite3_errmsg( *db ) ), QgsMessageOutput::MessageText );
11671168
output->showMessage();
11681169
}
11691170
return myResult;

src/core/qgscoordinatetransform.cpp

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@
1515
* *
1616
***************************************************************************/
1717
/* $Id$ */
18-
#include <cassert>
1918
#include "qgscoordinatetransform.h"
19+
#include "qgsmessageoutput.h"
2020
#include "qgslogger.h"
2121

2222
//qt includes
2323
#include <QDomNode>
2424
#include <QDomElement>
2525
#include <QApplication>
26-
#include "qgslogger.h"
26+
#include <QSettings>
27+
#include <QStringList>
28+
#include <QFileInfo>
29+
#include <QSet>
2730

2831
extern "C"
2932
{
@@ -33,10 +36,7 @@ extern "C"
3336
// if defined shows all information about transform to stdout
3437
// #define COORDINATE_TRANSFORM_VERBOSE
3538

36-
37-
3839
QgsCoordinateTransform::QgsCoordinateTransform( ) : QObject(), mSourceCRS(), mDestCRS()
39-
4040
{
4141
setFinder();
4242
}
@@ -45,6 +45,7 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
4545
const QgsCoordinateReferenceSystem& dest )
4646
{
4747
setFinder();
48+
4849
mSourceCRS = source;
4950
mDestCRS = dest;
5051
initialise();
@@ -315,7 +316,7 @@ void QgsCoordinateTransform::transformInPlace( std::vector<double>& x,
315316
if ( mShortCircuit || !mInitialisedFlag )
316317
return;
317318

318-
assert( x.size() == y.size() );
319+
Q_ASSERT( x.size() == y.size() );
319320

320321
// Apparently, if one has a std::vector, it is valid to use the
321322
// address of the first element in the vector as a pointer to an
@@ -457,8 +458,8 @@ void QgsCoordinateTransform::transformCoords( const int& numPoints, double *x, d
457458
}
458459
else
459460
{
460-
assert( mSourceProjection != 0 );
461-
assert( mDestinationProjection != 0 );
461+
Q_ASSERT( mSourceProjection != 0 );
462+
Q_ASSERT( mDestinationProjection != 0 );
462463
projResult = pj_transform( mSourceProjection, mDestinationProjection, numPoints, 0, x, y, z );
463464
dir = tr( "forward transform" );
464465
}
@@ -531,7 +532,6 @@ bool QgsCoordinateTransform::readXML( QDomNode & theNode )
531532

532533
bool QgsCoordinateTransform::writeXML( QDomNode & theNode, QDomDocument & theDoc )
533534
{
534-
535535
QDomElement myNodeElement = theNode.toElement();
536536
QDomElement myTransformElement = theDoc.createElement( "coordinatetransform" );
537537

@@ -548,29 +548,51 @@ bool QgsCoordinateTransform::writeXML( QDomNode & theNode, QDomDocument & theDoc
548548
return true;
549549
}
550550

551-
const char *finder( const char *name )
551+
void QgsCoordinateTransform::setFinder()
552552
{
553-
QString proj;
554-
#ifdef WIN32
555-
proj = QApplication::applicationDirPath()
556-
+ "/share/proj/" + QString( name );
557-
#endif
558-
return proj.toUtf8();
553+
pj_set_finder( finder );
559554
}
560555

561-
void QgsCoordinateTransform::setFinder()
556+
const char *QgsCoordinateTransform::finder( const char *name )
562557
{
563-
#ifdef WIN32
564-
// Attention! It should be possible to set PROJ_LIB
565-
// but it can happen that it was previously set by installer
566-
// (version 0.7) and the old installation was deleted
558+
QSettings settings;
559+
QStringList paths = settings.value( "projSearchPaths" ).toStringList();
567560

568-
// Another problem: PROJ checks if pj_finder was set before
569-
// PROJ_LIB environment variable. pj_finder is probably set in
570-
// GRASS gproj library when plugin is loaded, consequently
571-
// PROJ_LIB is ignored
561+
if ( getenv( "PROJ_LIB" ) )
562+
{
563+
paths << getenv( "PROJ_LIB" );
564+
}
572565

573-
pj_set_finder( finder );
566+
#ifdef WIN32
567+
paths << QApplication::applicationDirPath() + "/share/proj";
574568
#endif
575-
}
576569

570+
foreach( QString path, paths )
571+
{
572+
QFileInfo fi( QString( "%1/%2" ).arg( path ).arg( name ) );
573+
if ( fi.exists() )
574+
return fi.canonicalFilePath().toUtf8();
575+
}
576+
577+
if ( QString( name ).endsWith( ".gsb", Qt::CaseInsensitive ) )
578+
{
579+
static QSet<QString> missing;
580+
581+
if ( !missing.contains( name ) )
582+
{
583+
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
584+
output->setTitle( "Grid transformation missing" );
585+
output->setMessage( tr( "PROJ.4 file %1 not found in any of these directories:\n\n"
586+
"%2\n\n"
587+
"Note: This message won't reappear for this file in this session." )
588+
.arg( name )
589+
.arg( paths.join( "\n" ) ),
590+
QgsMessageOutput::MessageText );
591+
output->showMessage();
592+
}
593+
594+
missing << name;
595+
}
596+
597+
return name;
598+
}

src/core/qgscoordinatetransform.h

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,14 @@ class CORE_EXPORT QgsCoordinateTransform: public QObject
256256
projPJ mDestinationProjection;
257257

258258
/*!
259-
* Finder for PROJ grid files.
259+
* Set finder for PROJ grid files.
260260
*/
261261
void setFinder();
262+
263+
/*!
264+
* Finder for PROJ grid files.
265+
*/
266+
static const char *finder( const char *name );
262267
};
263268

264269
//! Output stream operator
@@ -271,45 +276,47 @@ inline std::ostream& operator << ( std::ostream& os, const QgsCoordinateTransfor
271276
{
272277
//do nothing this is a dummy
273278
}
274-
/*
275-
if (r.isInitialised())
276-
{
277-
mySummary += "Yes";
278-
}
279-
else
280-
{
281-
mySummary += "No" ;
282-
}
283-
mySummary += "\n\tShort Circuit? : " ;
284-
if (r.isShortCircuited())
285-
{
286-
mySummary += "Yes";
287-
}
288-
else
289-
{
290-
mySummary += "No" ;
291-
}
292279

293-
mySummary += "\n\tSource Spatial Ref Sys : ";
294-
if (r.sourceCrs())
295-
{
296-
mySummary << r.sourceCrs();
297-
}
298-
else
299-
{
300-
mySummary += "Undefined" ;
301-
}
280+
#if 0
281+
if ( r.isInitialised() )
282+
{
283+
mySummary += "Yes";
284+
}
285+
else
286+
{
287+
mySummary += "No" ;
288+
}
289+
mySummary += "\n\tShort Circuit? : " ;
290+
if ( r.isShortCircuited() )
291+
{
292+
mySummary += "Yes";
293+
}
294+
else
295+
{
296+
mySummary += "No" ;
297+
}
298+
299+
mySummary += "\n\tSource Spatial Ref Sys : ";
300+
if ( r.sourceCrs() )
301+
{
302+
mySummary << r.sourceCrs();
303+
}
304+
else
305+
{
306+
mySummary += "Undefined" ;
307+
}
308+
309+
mySummary += "\n\tDest Spatial Ref Sys : " ;
310+
if ( r.destCRS() )
311+
{
312+
mySummary << r.destCRS();
313+
}
314+
else
315+
{
316+
mySummary += "Undefined" ;
317+
}
318+
#endif
302319

303-
mySummary += "\n\tDest Spatial Ref Sys : " ;
304-
if (r.destCRS())
305-
{
306-
mySummary << r.destCRS();
307-
}
308-
else
309-
{
310-
mySummary += "Undefined" ;
311-
}
312-
*/
313320
mySummary += ( "\nCoordinate Transform def ends \n%%%%%%%%%%%%%%%%%%%%%%%%\n" );
314321
return os << mySummary.toLocal8Bit().data() << std::endl;
315322
}

0 commit comments

Comments
 (0)