mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[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
This commit is contained in:
parent
9b287cef3a
commit
6308416ad6
BIN
resources/srs.db
BIN
resources/srs.db
Binary file not shown.
@ -85,6 +85,15 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
|
||||
}
|
||||
}
|
||||
|
||||
//local directories to search when looking for an PROJ.4 file with a given basename
|
||||
foreach( QString path, settings.value( "projSearchPaths" ).toStringList() )
|
||||
{
|
||||
QListWidgetItem* newItem = new QListWidgetItem( mListProjPaths );
|
||||
newItem->setText( path );
|
||||
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
|
||||
mListProjPaths->addItem( newItem );
|
||||
}
|
||||
|
||||
//Network timeout
|
||||
mNetworkTimeoutSpinBox->setValue( settings.value( "/qgis/networkAndProxy/networkTimeout", "60000" ).toInt() );
|
||||
|
||||
@ -464,6 +473,13 @@ void QgsOptions::saveOptions()
|
||||
}
|
||||
settings.setValue( "svg/searchPathsForSVG", myPaths );
|
||||
|
||||
QStringList paths;
|
||||
for ( int i = 0; i < mListProjPaths->count(); ++i )
|
||||
{
|
||||
paths << mListProjPaths->item( i )->text();
|
||||
}
|
||||
settings.setValue( "projSearchPaths", paths );
|
||||
|
||||
//Network timeout
|
||||
settings.setValue( "/qgis/networkAndProxy/networkTimeout", mNetworkTimeoutSpinBox->value() );
|
||||
|
||||
@ -872,6 +888,33 @@ void QgsOptions::on_mBtnRemoveSVGPath_clicked()
|
||||
delete itemToRemove;
|
||||
}
|
||||
|
||||
void QgsOptions::on_mBtnAddProjPath_clicked()
|
||||
{
|
||||
QString myDir = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr( "Choose a directory" ),
|
||||
QDir::toNativeSeparators( QDir::homePath() ),
|
||||
QFileDialog::ShowDirsOnly
|
||||
);
|
||||
|
||||
if ( ! myDir.isEmpty() )
|
||||
{
|
||||
QListWidgetItem* newItem = new QListWidgetItem( mListProjPaths );
|
||||
newItem->setText( myDir );
|
||||
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
|
||||
mListProjPaths->addItem( newItem );
|
||||
mListProjPaths->setCurrentItem( newItem );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsOptions::on_mBtnRemoveProjPath_clicked()
|
||||
{
|
||||
int currentRow = mListProjPaths->currentRow();
|
||||
QListWidgetItem* itemToRemove = mListProjPaths->takeItem( currentRow );
|
||||
delete itemToRemove;
|
||||
}
|
||||
|
||||
|
||||
void QgsOptions::on_mAddUrlPushButton_clicked()
|
||||
{
|
||||
QListWidgetItem* newItem = new QListWidgetItem( mExcludeUrlListWidget );
|
||||
|
@ -101,6 +101,12 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
|
||||
*/
|
||||
void on_mBtnRemoveSVGPath_clicked();
|
||||
|
||||
/* Let the user add a path to the list of search paths used for finding PROJ.4 files. */
|
||||
void on_mBtnAddProjPath_clicked();
|
||||
|
||||
/* Let the user remove a path to the list of search paths for finding PROJ.4 files. */
|
||||
void on_mBtnRemoveProjPath_clicked();
|
||||
|
||||
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
|
||||
|
||||
void on_mBrowseCacheDirectory_clicked();
|
||||
|
@ -1161,9 +1161,10 @@ int QgsCoordinateReferenceSystem::openDb( QString path, sqlite3 **db )
|
||||
// ... unfortunately it happens on Windows
|
||||
QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
|
||||
output->setTitle( "Error" );
|
||||
output->setMessage( "Could not open CRS database " + path +
|
||||
"<br>Error(" + QString::number( myResult ) + "): " +
|
||||
QString( sqlite3_errmsg( *db ) ), QgsMessageOutput::MessageText );
|
||||
output->setMessage( QObject::tr( "Could not open CRS database %1<br>Error(%2): %3" )
|
||||
.arg( path )
|
||||
.arg( myResult )
|
||||
.arg( sqlite3_errmsg( *db ) ), QgsMessageOutput::MessageText );
|
||||
output->showMessage();
|
||||
}
|
||||
return myResult;
|
||||
|
@ -15,15 +15,18 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
/* $Id$ */
|
||||
#include <cassert>
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgsmessageoutput.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
//qt includes
|
||||
#include <QDomNode>
|
||||
#include <QDomElement>
|
||||
#include <QApplication>
|
||||
#include "qgslogger.h"
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QFileInfo>
|
||||
#include <QSet>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -33,10 +36,7 @@ extern "C"
|
||||
// if defined shows all information about transform to stdout
|
||||
// #define COORDINATE_TRANSFORM_VERBOSE
|
||||
|
||||
|
||||
|
||||
QgsCoordinateTransform::QgsCoordinateTransform( ) : QObject(), mSourceCRS(), mDestCRS()
|
||||
|
||||
{
|
||||
setFinder();
|
||||
}
|
||||
@ -45,6 +45,7 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
|
||||
const QgsCoordinateReferenceSystem& dest )
|
||||
{
|
||||
setFinder();
|
||||
|
||||
mSourceCRS = source;
|
||||
mDestCRS = dest;
|
||||
initialise();
|
||||
@ -315,7 +316,7 @@ void QgsCoordinateTransform::transformInPlace( std::vector<double>& x,
|
||||
if ( mShortCircuit || !mInitialisedFlag )
|
||||
return;
|
||||
|
||||
assert( x.size() == y.size() );
|
||||
Q_ASSERT( x.size() == y.size() );
|
||||
|
||||
// Apparently, if one has a std::vector, it is valid to use the
|
||||
// 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
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( mSourceProjection != 0 );
|
||||
assert( mDestinationProjection != 0 );
|
||||
Q_ASSERT( mSourceProjection != 0 );
|
||||
Q_ASSERT( mDestinationProjection != 0 );
|
||||
projResult = pj_transform( mSourceProjection, mDestinationProjection, numPoints, 0, x, y, z );
|
||||
dir = tr( "forward transform" );
|
||||
}
|
||||
@ -531,7 +532,6 @@ bool QgsCoordinateTransform::readXML( QDomNode & theNode )
|
||||
|
||||
bool QgsCoordinateTransform::writeXML( QDomNode & theNode, QDomDocument & theDoc )
|
||||
{
|
||||
|
||||
QDomElement myNodeElement = theNode.toElement();
|
||||
QDomElement myTransformElement = theDoc.createElement( "coordinatetransform" );
|
||||
|
||||
@ -548,29 +548,51 @@ bool QgsCoordinateTransform::writeXML( QDomNode & theNode, QDomDocument & theDoc
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *finder( const char *name )
|
||||
{
|
||||
QString proj;
|
||||
#ifdef WIN32
|
||||
proj = QApplication::applicationDirPath()
|
||||
+ "/share/proj/" + QString( name );
|
||||
#endif
|
||||
return proj.toUtf8();
|
||||
}
|
||||
|
||||
void QgsCoordinateTransform::setFinder()
|
||||
{
|
||||
#ifdef WIN32
|
||||
// Attention! It should be possible to set PROJ_LIB
|
||||
// but it can happen that it was previously set by installer
|
||||
// (version 0.7) and the old installation was deleted
|
||||
|
||||
// Another problem: PROJ checks if pj_finder was set before
|
||||
// PROJ_LIB environment variable. pj_finder is probably set in
|
||||
// GRASS gproj library when plugin is loaded, consequently
|
||||
// PROJ_LIB is ignored
|
||||
|
||||
pj_set_finder( finder );
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *QgsCoordinateTransform::finder( const char *name )
|
||||
{
|
||||
QSettings settings;
|
||||
QStringList paths = settings.value( "projSearchPaths" ).toStringList();
|
||||
|
||||
if ( getenv( "PROJ_LIB" ) )
|
||||
{
|
||||
paths << getenv( "PROJ_LIB" );
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
paths << QApplication::applicationDirPath() + "/share/proj";
|
||||
#endif
|
||||
|
||||
foreach( QString path, paths )
|
||||
{
|
||||
QFileInfo fi( QString( "%1/%2" ).arg( path ).arg( name ) );
|
||||
if ( fi.exists() )
|
||||
return fi.canonicalFilePath().toUtf8();
|
||||
}
|
||||
|
||||
if ( QString( name ).endsWith( ".gsb", Qt::CaseInsensitive ) )
|
||||
{
|
||||
static QSet<QString> missing;
|
||||
|
||||
if ( !missing.contains( name ) )
|
||||
{
|
||||
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
|
||||
output->setTitle( "Grid transformation missing" );
|
||||
output->setMessage( tr( "PROJ.4 file %1 not found in any of these directories:\n\n"
|
||||
"%2\n\n"
|
||||
"Note: This message won't reappear for this file in this session." )
|
||||
.arg( name )
|
||||
.arg( paths.join( "\n" ) ),
|
||||
QgsMessageOutput::MessageText );
|
||||
output->showMessage();
|
||||
}
|
||||
|
||||
missing << name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
@ -256,9 +256,14 @@ class CORE_EXPORT QgsCoordinateTransform: public QObject
|
||||
projPJ mDestinationProjection;
|
||||
|
||||
/*!
|
||||
* Finder for PROJ grid files.
|
||||
* Set finder for PROJ grid files.
|
||||
*/
|
||||
void setFinder();
|
||||
|
||||
/*!
|
||||
* Finder for PROJ grid files.
|
||||
*/
|
||||
static const char *finder( const char *name );
|
||||
};
|
||||
|
||||
//! Output stream operator
|
||||
@ -271,45 +276,47 @@ inline std::ostream& operator << ( std::ostream& os, const QgsCoordinateTransfor
|
||||
{
|
||||
//do nothing this is a dummy
|
||||
}
|
||||
/*
|
||||
if (r.isInitialised())
|
||||
{
|
||||
mySummary += "Yes";
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "No" ;
|
||||
}
|
||||
mySummary += "\n\tShort Circuit? : " ;
|
||||
if (r.isShortCircuited())
|
||||
{
|
||||
mySummary += "Yes";
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "No" ;
|
||||
}
|
||||
|
||||
mySummary += "\n\tSource Spatial Ref Sys : ";
|
||||
if (r.sourceCrs())
|
||||
{
|
||||
mySummary << r.sourceCrs();
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "Undefined" ;
|
||||
}
|
||||
#if 0
|
||||
if ( r.isInitialised() )
|
||||
{
|
||||
mySummary += "Yes";
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "No" ;
|
||||
}
|
||||
mySummary += "\n\tShort Circuit? : " ;
|
||||
if ( r.isShortCircuited() )
|
||||
{
|
||||
mySummary += "Yes";
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "No" ;
|
||||
}
|
||||
|
||||
mySummary += "\n\tSource Spatial Ref Sys : ";
|
||||
if ( r.sourceCrs() )
|
||||
{
|
||||
mySummary << r.sourceCrs();
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "Undefined" ;
|
||||
}
|
||||
|
||||
mySummary += "\n\tDest Spatial Ref Sys : " ;
|
||||
if ( r.destCRS() )
|
||||
{
|
||||
mySummary << r.destCRS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "Undefined" ;
|
||||
}
|
||||
#endif
|
||||
|
||||
mySummary += "\n\tDest Spatial Ref Sys : " ;
|
||||
if (r.destCRS())
|
||||
{
|
||||
mySummary << r.destCRS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mySummary += "Undefined" ;
|
||||
}
|
||||
*/
|
||||
mySummary += ( "\nCoordinate Transform def ends \n%%%%%%%%%%%%%%%%%%%%%%%%\n" );
|
||||
return os << mySummary.toLocal8Bit().data() << std::endl;
|
||||
}
|
||||
|
@ -212,6 +212,16 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
@ -624,6 +634,52 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>PROJ.4 search paths</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="4" column="0" colspan="4">
|
||||
<widget class="QListWidget" name="mListProjPaths"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="spacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>31</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="mBtnAddProjPath">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="mBtnRemoveProjPath">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mProjLabel">
|
||||
<property name="text">
|
||||
<string>Path(s) to search for PROJ.4 files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="stackedWidgetPage3">
|
||||
@ -1599,16 +1655,6 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user