Skip to content

Commit

Permalink
[needs-docs] Append a local, user writable folder to proj 6 search paths
Browse files Browse the repository at this point in the history
Now, proj will search in the current user profile "proj" folder (e.g.
.local/share/QGIS/QGIS3/profiles/default/proj" on linux) for
grid files and other proj helper files.

This allows users (and plugins) to install grid files and make them
available for use in QGIS without requiring administrator access
to the system.
  • Loading branch information
nyalldawson committed Jun 3, 2019
1 parent 19933e0 commit a4e5e6a
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 0 deletions.
10 changes: 10 additions & 0 deletions python/core/auto_generated/qgsprojutils.sip.in
Expand Up @@ -29,6 +29,16 @@ Utility functions for working with the proj library.
Returns the proj library major version number.
%End

static QStringList searchPaths();
%Docstring
Returns the current list of Proj file search paths.

.. note::

Only available on builds based on Proj >= 6.0. Builds based on
earlier Proj versions will always return an empty list.
%End

};

/************************************************************************
Expand Down
20 changes: 20 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -51,6 +51,7 @@
#include "qgslayoutrendercontext.h"
#include "qgssqliteutils.h"
#include "qgsstyle.h"
#include "qgsprojutils.h"
#include "qgsvaliditycheckregistry.h"

#include "gps/qgsgpsconnectionregistry.h"
Expand Down Expand Up @@ -91,6 +92,11 @@
#include <cpl_conv.h> // for setting gdal options
#include <sqlite3.h>

#if PROJ_VERSION_MAJOR>=6
#include <proj.h>
#endif


#define CONN_POOL_MAX_CONCURRENT_CONNS 4

QObject *ABISYM( QgsApplication::mFileOpenEventReceiver );
Expand Down Expand Up @@ -295,6 +301,20 @@ void QgsApplication::init( QString profileFolder )
}
ABISYM( mSystemEnvVars ) = systemEnvVarMap;

#if PROJ_VERSION_MAJOR>=6
// append local user-writable folder as a proj search path
QStringList currentProjSearchPaths = QgsProjUtils::searchPaths();
currentProjSearchPaths.append( qgisSettingsDirPath() + QStringLiteral( "proj" ) );
const char **newPaths = new const char *[currentProjSearchPaths.length()];
for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
{
newPaths[i] = currentProjSearchPaths.at( i ).toUtf8().constData();
}
proj_context_set_search_paths( nullptr, currentProjSearchPaths.count(), newPaths );
delete [] newPaths;
#endif


// allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
QCoreApplication::addLibraryPath( pluginPath() );

Expand Down
31 changes: 31 additions & 0 deletions src/core/qgsprojutils.cpp
Expand Up @@ -15,7 +15,9 @@
* *
***************************************************************************/
#include "qgsprojutils.h"
#include "qgis.h"
#include <QString>
#include <QSet>

#if PROJ_VERSION_MAJOR>=6
#include <proj.h>
Expand Down Expand Up @@ -215,3 +217,32 @@ QStringList QgsProjUtils::nonAvailableGrids( const QString &projDef )

#endif

QStringList QgsProjUtils::searchPaths()
{
#if PROJ_VERSION_MAJOR >= 6
const QString path( proj_info().searchpath );
QStringList paths;
// #ifdef Q_OS_WIN
#if 1 // -- see https://github.com/OSGeo/proj.4/pull/1497
paths = path.split( ';' );
#else
paths = path.split( ':' );
#endif

QSet<QString> existing;
// thin out duplicates from paths -- see https://github.com/OSGeo/proj.4/pull/1498
QStringList res;
res.reserve( paths.count() );
for ( const QString &p : qgis::as_const( paths ) )
{
if ( existing.contains( p ) )
continue;

existing.insert( p );
res << p;
}
return res;
#else
return QStringList();
#endif
}
8 changes: 8 additions & 0 deletions src/core/qgsprojutils.h
Expand Up @@ -53,6 +53,14 @@ class CORE_EXPORT QgsProjUtils
return PROJ_VERSION_MAJOR;
}

/**
* Returns the current list of Proj file search paths.
*
* \note Only available on builds based on Proj >= 6.0. Builds based on
* earlier Proj versions will always return an empty list.
*/
static QStringList searchPaths();

#ifndef SIP_RUN
#if PROJ_VERSION_MAJOR >= 6

Expand Down
10 changes: 10 additions & 0 deletions tests/src/core/testqgsprojutils.cpp
Expand Up @@ -35,6 +35,7 @@ class TestQgsProjUtils: public QObject
void threadSafeContext();
void usesAngularUnits();
void axisOrderIsSwapped();
void searchPath();

};

Expand Down Expand Up @@ -97,5 +98,14 @@ void TestQgsProjUtils::axisOrderIsSwapped()
#endif
}

void TestQgsProjUtils::searchPath()
{
#if PROJ_VERSION_MAJOR>=6
// ensure local user-writable path is present in Proj search paths
const QStringList paths = QgsProjUtils::searchPaths();
QVERIFY( paths.contains( QgsApplication::qgisSettingsDirPath() + QStringLiteral( "proj" ) ) );
#endif
}

QGSTEST_MAIN( TestQgsProjUtils )
#include "testqgsprojutils.moc"

0 comments on commit a4e5e6a

Please sign in to comment.