Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgspathresolver.h 3 : : -------------------------------------- 4 : : Date : February 2017 5 : : Copyright : (C) 2017 by Martin Dobias 6 : : Email : wonder dot sk at gmail dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSPATHRESOLVER_H 17 : : #define QGSPATHRESOLVER_H 18 : : 19 : : #include "qgis_core.h" 20 : : 21 : : #include <QString> 22 : : #include <functional> 23 : : #include <vector> 24 : : 25 : : /** 26 : : * \ingroup core 27 : : * \brief Resolves relative paths into absolute paths and vice versa. Used for writing 28 : : * 29 : : * \since QGIS 3.0 30 : : */ 31 : 589 : class CORE_EXPORT QgsPathResolver 32 : : { 33 : : public: 34 : : //! Initialize path resolver with a base filename. Null filename means no conversion between relative/absolute path 35 : : explicit QgsPathResolver( const QString &baseFileName = QString() ); 36 : : 37 : : /** 38 : : * Prepare a filename to save it to the project file. 39 : : * Creates an absolute or relative path according to the project settings. 40 : : * Paths written to the project file should be prepared with this method. 41 : : */ 42 : : QString writePath( const QString &filename ) const; 43 : : 44 : : //! Turn filename read from the project file to an absolute path 45 : : QString readPath( const QString &filename ) const; 46 : : 47 : : #ifndef SIP_RUN 48 : : 49 : : /** 50 : : * Sets a path pre-processor function, which allows for manipulation of paths and data sources prior 51 : : * to resolving them to file references or layer sources. 52 : : * 53 : : * The \a processor function must accept a single string argument (representing the original file path 54 : : * or data source), and return a processed version of this path. 55 : : * 56 : : * The path pre-processor function is called before any bad layer handler. 57 : : * 58 : : * If multiple preprocessors are set, they will be called in sequence based on the order in which 59 : : * they were originally set. 60 : : * 61 : : * \returns An auto-generated string uniquely identifying the preprocessor, which can later be 62 : : * used to remove the processor (via a call to removePathPreprocessor()). 63 : : * 64 : : * \see removePathPreprocessor() 65 : : * \since QGIS 3.10 66 : : */ 67 : : static QString setPathPreprocessor( const std::function< QString( const QString &filename )> &processor ); 68 : : #else 69 : : 70 : : /** 71 : : * Sets a path pre-processor function, which allows for manipulation of paths and data sources prior 72 : : * to resolving them to file references or layer sources. 73 : : * 74 : : * The \a processor function must accept a single string argument (representing the original file path 75 : : * or data source), and return a processed version of this path. 76 : : * 77 : : * The path pre-processor function is called before any bad layer handler. 78 : : * 79 : : * \note Setting a new \a processor replaces any existing processor. 80 : : * 81 : : * Example - replace an outdated folder path with a new one: 82 : : * 83 : : * \code{.py} 84 : : * def my_processor(path): 85 : : * return path.replace('c:/Users/ClintBarton/Documents/Projects', 'x:/Projects/') 86 : : * 87 : : * QgsPathResolver.setPathPreprocessor(my_processor) 88 : : * \endcode 89 : : * 90 : : * Example - replace a stored database host with a new one: 91 : : * 92 : : * \code{.py} 93 : : * def my_processor(path): 94 : : * return path.replace('host=10.1.1.115', 'host=10.1.1.116') 95 : : * 96 : : * QgsPathResolver.setPathPreprocessor(my_processor) 97 : : * \endcode 98 : : * 99 : : * Example - replace stored database credentials with new ones: 100 : : * 101 : : * \code{.py} 102 : : * def my_processor(path): 103 : : * path = path.replace("user='gis_team'", "user='team_awesome'") 104 : : * path = path.replace("password='cats'", "password='g7as!m*'") 105 : : * return path 106 : : * 107 : : * QgsPathResolver.setPathPreprocessor(my_processor) 108 : : * \endcode 109 : : * 110 : : * \since QGIS 3.10 111 : : */ 112 : : static QString setPathPreprocessor( SIP_PYCALLABLE / AllowNone / ); 113 : : % MethodCode 114 : : PyObject *s = 0; 115 : : Py_BEGIN_ALLOW_THREADS 116 : : Py_XINCREF( a0 ); 117 : : QString id = QgsPathResolver::setPathPreprocessor( [a0]( const QString &arg )->QString 118 : : { 119 : : QString res; 120 : : SIP_BLOCK_THREADS 121 : : PyObject *s = sipCallMethod( NULL, a0, "D", &arg, sipType_QString, NULL ); 122 : : int state; 123 : : int sipIsError = 0; 124 : : QString *t1 = reinterpret_cast<QString *>( sipConvertToType( s, sipType_QString, 0, SIP_NOT_NONE, &state, &sipIsError ) ); 125 : : if ( sipIsError == 0 ) 126 : : { 127 : : res = QString( *t1 ); 128 : : } 129 : : sipReleaseType( t1, sipType_QString, state ); 130 : : SIP_UNBLOCK_THREADS 131 : : return res; 132 : : } ); 133 : : 134 : : s = sipConvertFromNewType( new QString( id ), sipType_QString, 0 ); 135 : : Py_END_ALLOW_THREADS 136 : : return s; 137 : : % End 138 : : #endif 139 : : 140 : : #ifndef SIP_RUN 141 : : 142 : : /** 143 : : * Removes the custom pre-processor function with matching \a id. 144 : : * 145 : : * The \a id must correspond to a pre-processor previously added via a call to setPathPreprocessor(). 146 : : * 147 : : * Returns TRUE if processor existed and was removed. 148 : : * 149 : : * \see setPathPreprocessor() 150 : : * \since QGIS 3.10 151 : : */ 152 : : static bool removePathPreprocessor( const QString &id ); 153 : : #else 154 : : 155 : : /** 156 : : * Removes the custom pre-processor function with matching \a id. 157 : : * 158 : : * The \a id must correspond to a pre-processor previously added via a call to setPathPreprocessor(). 159 : : * An KeyError will be raised if no processor with the specified \a id exists. 160 : : * 161 : : * \see setPathPreprocessor() 162 : : * \since QGIS 3.10 163 : : */ 164 : : static void removePathPreprocessor( const QString &id ); 165 : : % MethodCode 166 : : if ( !QgsPathResolver::removePathPreprocessor( *a0 ) ) 167 : : { 168 : : PyErr_SetString( PyExc_KeyError, QStringLiteral( "No processor with id %1 exists." ).arg( *a0 ).toUtf8().constData() ); 169 : : sipIsErr = 1; 170 : : } 171 : : % End 172 : : #endif 173 : : 174 : : private: 175 : : //! path to a file that is the base for relative path resolution 176 : : QString mBaseFileName; 177 : : }; 178 : : 179 : : #endif // QGSPATHRESOLVER_H