Skip to content

Commit a4e5e6a

Browse files
committedJun 3, 2019
[needs-docs] Append a local, user writable folder to proj 6 search paths
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.
1 parent 19933e0 commit a4e5e6a

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed
 

‎python/core/auto_generated/qgsprojutils.sip.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ Utility functions for working with the proj library.
2929
Returns the proj library major version number.
3030
%End
3131

32+
static QStringList searchPaths();
33+
%Docstring
34+
Returns the current list of Proj file search paths.
35+
36+
.. note::
37+
38+
Only available on builds based on Proj >= 6.0. Builds based on
39+
earlier Proj versions will always return an empty list.
40+
%End
41+
3242
};
3343

3444
/************************************************************************

‎src/core/qgsapplication.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "qgslayoutrendercontext.h"
5252
#include "qgssqliteutils.h"
5353
#include "qgsstyle.h"
54+
#include "qgsprojutils.h"
5455
#include "qgsvaliditycheckregistry.h"
5556

5657
#include "gps/qgsgpsconnectionregistry.h"
@@ -91,6 +92,11 @@
9192
#include <cpl_conv.h> // for setting gdal options
9293
#include <sqlite3.h>
9394

95+
#if PROJ_VERSION_MAJOR>=6
96+
#include <proj.h>
97+
#endif
98+
99+
94100
#define CONN_POOL_MAX_CONCURRENT_CONNS 4
95101

96102
QObject *ABISYM( QgsApplication::mFileOpenEventReceiver );
@@ -295,6 +301,20 @@ void QgsApplication::init( QString profileFolder )
295301
}
296302
ABISYM( mSystemEnvVars ) = systemEnvVarMap;
297303

304+
#if PROJ_VERSION_MAJOR>=6
305+
// append local user-writable folder as a proj search path
306+
QStringList currentProjSearchPaths = QgsProjUtils::searchPaths();
307+
currentProjSearchPaths.append( qgisSettingsDirPath() + QStringLiteral( "proj" ) );
308+
const char **newPaths = new const char *[currentProjSearchPaths.length()];
309+
for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
310+
{
311+
newPaths[i] = currentProjSearchPaths.at( i ).toUtf8().constData();
312+
}
313+
proj_context_set_search_paths( nullptr, currentProjSearchPaths.count(), newPaths );
314+
delete [] newPaths;
315+
#endif
316+
317+
298318
// allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
299319
QCoreApplication::addLibraryPath( pluginPath() );
300320

‎src/core/qgsprojutils.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
* *
1616
***************************************************************************/
1717
#include "qgsprojutils.h"
18+
#include "qgis.h"
1819
#include <QString>
20+
#include <QSet>
1921

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

216218
#endif
217219

220+
QStringList QgsProjUtils::searchPaths()
221+
{
222+
#if PROJ_VERSION_MAJOR >= 6
223+
const QString path( proj_info().searchpath );
224+
QStringList paths;
225+
// #ifdef Q_OS_WIN
226+
#if 1 // -- see https://github.com/OSGeo/proj.4/pull/1497
227+
paths = path.split( ';' );
228+
#else
229+
paths = path.split( ':' );
230+
#endif
231+
232+
QSet<QString> existing;
233+
// thin out duplicates from paths -- see https://github.com/OSGeo/proj.4/pull/1498
234+
QStringList res;
235+
res.reserve( paths.count() );
236+
for ( const QString &p : qgis::as_const( paths ) )
237+
{
238+
if ( existing.contains( p ) )
239+
continue;
240+
241+
existing.insert( p );
242+
res << p;
243+
}
244+
return res;
245+
#else
246+
return QStringList();
247+
#endif
248+
}

‎src/core/qgsprojutils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ class CORE_EXPORT QgsProjUtils
5353
return PROJ_VERSION_MAJOR;
5454
}
5555

56+
/**
57+
* Returns the current list of Proj file search paths.
58+
*
59+
* \note Only available on builds based on Proj >= 6.0. Builds based on
60+
* earlier Proj versions will always return an empty list.
61+
*/
62+
static QStringList searchPaths();
63+
5664
#ifndef SIP_RUN
5765
#if PROJ_VERSION_MAJOR >= 6
5866

‎tests/src/core/testqgsprojutils.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class TestQgsProjUtils: public QObject
3535
void threadSafeContext();
3636
void usesAngularUnits();
3737
void axisOrderIsSwapped();
38+
void searchPath();
3839

3940
};
4041

@@ -97,5 +98,14 @@ void TestQgsProjUtils::axisOrderIsSwapped()
9798
#endif
9899
}
99100

101+
void TestQgsProjUtils::searchPath()
102+
{
103+
#if PROJ_VERSION_MAJOR>=6
104+
// ensure local user-writable path is present in Proj search paths
105+
const QStringList paths = QgsProjUtils::searchPaths();
106+
QVERIFY( paths.contains( QgsApplication::qgisSettingsDirPath() + QStringLiteral( "proj" ) ) );
107+
#endif
108+
}
109+
100110
QGSTEST_MAIN( TestQgsProjUtils )
101111
#include "testqgsprojutils.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.