Skip to content

Commit 032b743

Browse files
author
jef
committedSep 5, 2009
improve relative path support
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@11571 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

4 files changed

+170
-27
lines changed

4 files changed

+170
-27
lines changed
 

‎python/core/qgsproject.sip

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,14 @@ public:
223223
*/
224224
void dumpProperties() const;
225225

226+
/** prepare a filename to save it to the project file
227+
@note added in 1.3 */
228+
QString writePath( QString filename ) const;
229+
230+
/** turn filename read from the project file to an absolute path
231+
@note added in 1.3 */
232+
QString readPath( QString filename ) const;
233+
226234
signals:
227235

228236
//! emitted when project is being read

‎src/core/qgsmaplayer.cpp

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,7 @@ bool QgsMapLayer::readXML( QDomNode & layer_node )
152152
QDomElement mne = mnl.toElement();
153153
mDataSource = mne.text();
154154

155-
QFileInfo fi( mDataSource );
156-
if ( !fi.exists() && fi.isRelative() )
157-
{
158-
QFileInfo pfi( QgsProject::instance()->fileName() );
159-
if ( pfi.exists() )
160-
{
161-
fi.setFile( pfi.canonicalPath() + QDir::separator() + mDataSource );
162-
163-
if ( fi.exists() )
164-
{
165-
mDataSource = fi.canonicalFilePath();
166-
}
167-
}
168-
}
155+
mDataSource = QgsProject::instance()->readPath( mDataSource );
169156

170157
// Set the CRS from project file, asking the user if necessary.
171158
// Make it the saved CRS to have WMS layer projected correctly.
@@ -280,20 +267,8 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
280267
QDomElement dataSource = document.createElement( "datasource" );
281268

282269
QString src = source();
283-
QFileInfo srcInfo( src );
284270

285-
bool absolutePath = QgsProject::instance()->readBoolEntry( "Paths", "/Absolute", true );
286-
if ( !absolutePath && srcInfo.exists() )
287-
{
288-
QFileInfo pfi( QgsProject::instance()->fileName() );
289-
QgsDebugMsg( "project path: " + pfi.canonicalPath() );
290-
QgsDebugMsg( "src path: " + srcInfo.canonicalFilePath() );
291-
if ( srcInfo.canonicalFilePath().startsWith( pfi.canonicalPath() + "/" ) ) // QFileInfo always uses '/' for directory separator.
292-
{
293-
src = src.mid( pfi.canonicalPath().size() + 1 );
294-
QgsDebugMsg( "use relative path: " + src );
295-
}
296-
}
271+
src = QgsProject::instance()->writePath( src );
297272

298273
QDomText dataSourceText = document.createTextNode( src );
299274
dataSource.appendChild( dataSourceText );

‎src/core/qgsproject.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,3 +1300,154 @@ void QgsProject::dumpProperties() const
13001300
{
13011301
dump_( imp_->properties_ );
13021302
} // QgsProject::dumpProperties
1303+
1304+
1305+
// return the absolute path from a filename read from project file
1306+
QString QgsProject::readPath( QString src ) const
1307+
{
1308+
if ( readBoolEntry( "Paths", "/Absolute", true ) )
1309+
{
1310+
return src;
1311+
}
1312+
1313+
// relative path should always start with ./ or ../
1314+
if ( !src.startsWith( "./" ) && !src.startsWith( "../" ) )
1315+
{
1316+
#if defined(Q_OS_WIN)
1317+
if ( src.startsWith( "\\\\" ) ||
1318+
( src[0].isLetter() && src[1] == ':' ) )
1319+
{
1320+
// UNC or absolute path
1321+
return src;
1322+
}
1323+
#else
1324+
if ( src[0] == '/' )
1325+
{
1326+
// absolute path
1327+
return src;
1328+
}
1329+
#endif
1330+
1331+
// so this one isn't absolute, but also doesn't start // with ./ or ../.
1332+
// That means that it was saved with an earlier version of "relative path support",
1333+
// where the source file had to exist and only the project directory was stripped
1334+
// from the filename.
1335+
QFileInfo pfi( fileName() );
1336+
Q_ASSERT( pfi.exists() );
1337+
QFileInfo fi( pfi.canonicalPath() + "/" + src );
1338+
1339+
if ( !fi.exists() )
1340+
{
1341+
return src;
1342+
}
1343+
else
1344+
{
1345+
return fi.canonicalFilePath();
1346+
}
1347+
}
1348+
1349+
QString srcPath = src;
1350+
QString projPath = fileName();
1351+
1352+
#if defined(Q_OS_WIN)
1353+
srcPath.replace( "\\", "/" );
1354+
projPath.replace( "\\", "/" );
1355+
#endif
1356+
1357+
QStringList srcElems = srcPath.split( "/", QString::SkipEmptyParts );
1358+
QStringList projElems = projPath.split( "/", QString::SkipEmptyParts );
1359+
1360+
// remove project file element
1361+
projElems.removeLast();
1362+
1363+
// append source path elements
1364+
projElems.append( srcElems );
1365+
projElems.removeAll( "." );
1366+
1367+
// resolve ..
1368+
int pos;
1369+
while (( pos = projElems.indexOf( ".." ) ) > 0 )
1370+
{
1371+
// remove preceeding element and ..
1372+
projElems.removeAt( pos - 1 );
1373+
projElems.removeAt( pos - 1 );
1374+
}
1375+
1376+
return projElems.join( "/" );
1377+
}
1378+
1379+
// return the absolute or relative path to write it to the project file
1380+
QString QgsProject::writePath( QString src ) const
1381+
{
1382+
if ( readBoolEntry( "Paths", "/Absolute", true ) )
1383+
{
1384+
return src;
1385+
}
1386+
1387+
QString srcPath = src;
1388+
QString projPath = fileName();
1389+
1390+
#if defined( Q_OS_WIN )
1391+
const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
1392+
1393+
srcPath.replace( "\\", "/" );
1394+
1395+
if ( srcPath.startsWith( "//" ) )
1396+
{
1397+
// keep UNC prefix
1398+
srcPath = "\\\\" + srcPath.mid( 2 );
1399+
}
1400+
1401+
projPath.replace( "\\", "/" );
1402+
if ( projPath.startsWith( "//" ) )
1403+
{
1404+
// keep UNC prefix
1405+
projPath = "\\\\" + projPath.mid( 2 );
1406+
}
1407+
#else
1408+
const Qt::CaseSensitivity cs = Qt::CaseSensitive;
1409+
#endif
1410+
1411+
QStringList projElems = projPath.split( "/", QString::SkipEmptyParts );
1412+
QStringList srcElems = srcPath.split( "/", QString::SkipEmptyParts );
1413+
1414+
// remove project file element
1415+
projElems.removeLast();
1416+
1417+
projElems.removeAll( "." );
1418+
srcElems.removeAll( "." );
1419+
1420+
// remove common part
1421+
int n = 0;
1422+
while ( srcElems.size() > 0 &&
1423+
projElems.size() > 0 &&
1424+
srcElems[0].compare( projElems[0], cs ) == 0 )
1425+
{
1426+
srcElems.removeFirst();
1427+
projElems.removeFirst();
1428+
n++;
1429+
}
1430+
1431+
if ( n == 0 )
1432+
{
1433+
// no common parts; might not even by a file
1434+
return src;
1435+
}
1436+
1437+
if ( projElems.size() > 0 )
1438+
{
1439+
// go up to the common directory
1440+
for ( int i = 0; i < projElems.size(); i++ )
1441+
{
1442+
srcElems.insert( 0, ".." );
1443+
}
1444+
}
1445+
else
1446+
{
1447+
// let it start with . nevertheless,
1448+
// so relative path always start with either ./ or ../
1449+
srcElems.insert( 0, "." );
1450+
}
1451+
1452+
return srcElems.join( "/" );
1453+
}

‎src/core/qgsproject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,15 @@ class CORE_EXPORT QgsProject : public QObject
255255
*/
256256
void dumpProperties() const;
257257

258+
259+
/** prepare a filename to save it to the project file
260+
@note added in 1.3 */
261+
QString writePath( QString filename ) const;
262+
263+
/** turn filename read from the project file to an absolute path
264+
@note added in 1.3 */
265+
QString readPath( QString filename ) const;
266+
258267
signals:
259268

260269
//! emitted when project is being read

0 commit comments

Comments
 (0)
Please sign in to comment.