improve relative path support

git-svn-id: http://svn.osgeo.org/qgis/trunk@11571 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2009-09-05 19:49:10 +00:00
parent a211d66d8f
commit ddd64be82b
4 changed files with 170 additions and 27 deletions

View File

@ -223,6 +223,14 @@ public:
*/
void dumpProperties() const;
/** prepare a filename to save it to the project file
@note added in 1.3 */
QString writePath( QString filename ) const;
/** turn filename read from the project file to an absolute path
@note added in 1.3 */
QString readPath( QString filename ) const;
signals:
//! emitted when project is being read

View File

@ -152,20 +152,7 @@ bool QgsMapLayer::readXML( QDomNode & layer_node )
QDomElement mne = mnl.toElement();
mDataSource = mne.text();
QFileInfo fi( mDataSource );
if ( !fi.exists() && fi.isRelative() )
{
QFileInfo pfi( QgsProject::instance()->fileName() );
if ( pfi.exists() )
{
fi.setFile( pfi.canonicalPath() + QDir::separator() + mDataSource );
if ( fi.exists() )
{
mDataSource = fi.canonicalFilePath();
}
}
}
mDataSource = QgsProject::instance()->readPath( mDataSource );
// Set the CRS from project file, asking the user if necessary.
// Make it the saved CRS to have WMS layer projected correctly.
@ -280,20 +267,8 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
QDomElement dataSource = document.createElement( "datasource" );
QString src = source();
QFileInfo srcInfo( src );
bool absolutePath = QgsProject::instance()->readBoolEntry( "Paths", "/Absolute", true );
if ( !absolutePath && srcInfo.exists() )
{
QFileInfo pfi( QgsProject::instance()->fileName() );
QgsDebugMsg( "project path: " + pfi.canonicalPath() );
QgsDebugMsg( "src path: " + srcInfo.canonicalFilePath() );
if ( srcInfo.canonicalFilePath().startsWith( pfi.canonicalPath() + "/" ) ) // QFileInfo always uses '/' for directory separator.
{
src = src.mid( pfi.canonicalPath().size() + 1 );
QgsDebugMsg( "use relative path: " + src );
}
}
src = QgsProject::instance()->writePath( src );
QDomText dataSourceText = document.createTextNode( src );
dataSource.appendChild( dataSourceText );

View File

@ -1300,3 +1300,154 @@ void QgsProject::dumpProperties() const
{
dump_( imp_->properties_ );
} // QgsProject::dumpProperties
// return the absolute path from a filename read from project file
QString QgsProject::readPath( QString src ) const
{
if ( readBoolEntry( "Paths", "/Absolute", true ) )
{
return src;
}
// relative path should always start with ./ or ../
if ( !src.startsWith( "./" ) && !src.startsWith( "../" ) )
{
#if defined(Q_OS_WIN)
if ( src.startsWith( "\\\\" ) ||
( src[0].isLetter() && src[1] == ':' ) )
{
// UNC or absolute path
return src;
}
#else
if ( src[0] == '/' )
{
// absolute path
return src;
}
#endif
// so this one isn't absolute, but also doesn't start // with ./ or ../.
// That means that it was saved with an earlier version of "relative path support",
// where the source file had to exist and only the project directory was stripped
// from the filename.
QFileInfo pfi( fileName() );
Q_ASSERT( pfi.exists() );
QFileInfo fi( pfi.canonicalPath() + "/" + src );
if ( !fi.exists() )
{
return src;
}
else
{
return fi.canonicalFilePath();
}
}
QString srcPath = src;
QString projPath = fileName();
#if defined(Q_OS_WIN)
srcPath.replace( "\\", "/" );
projPath.replace( "\\", "/" );
#endif
QStringList srcElems = srcPath.split( "/", QString::SkipEmptyParts );
QStringList projElems = projPath.split( "/", QString::SkipEmptyParts );
// remove project file element
projElems.removeLast();
// append source path elements
projElems.append( srcElems );
projElems.removeAll( "." );
// resolve ..
int pos;
while (( pos = projElems.indexOf( ".." ) ) > 0 )
{
// remove preceeding element and ..
projElems.removeAt( pos - 1 );
projElems.removeAt( pos - 1 );
}
return projElems.join( "/" );
}
// return the absolute or relative path to write it to the project file
QString QgsProject::writePath( QString src ) const
{
if ( readBoolEntry( "Paths", "/Absolute", true ) )
{
return src;
}
QString srcPath = src;
QString projPath = fileName();
#if defined( Q_OS_WIN )
const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
srcPath.replace( "\\", "/" );
if ( srcPath.startsWith( "//" ) )
{
// keep UNC prefix
srcPath = "\\\\" + srcPath.mid( 2 );
}
projPath.replace( "\\", "/" );
if ( projPath.startsWith( "//" ) )
{
// keep UNC prefix
projPath = "\\\\" + projPath.mid( 2 );
}
#else
const Qt::CaseSensitivity cs = Qt::CaseSensitive;
#endif
QStringList projElems = projPath.split( "/", QString::SkipEmptyParts );
QStringList srcElems = srcPath.split( "/", QString::SkipEmptyParts );
// remove project file element
projElems.removeLast();
projElems.removeAll( "." );
srcElems.removeAll( "." );
// remove common part
int n = 0;
while ( srcElems.size() > 0 &&
projElems.size() > 0 &&
srcElems[0].compare( projElems[0], cs ) == 0 )
{
srcElems.removeFirst();
projElems.removeFirst();
n++;
}
if ( n == 0 )
{
// no common parts; might not even by a file
return src;
}
if ( projElems.size() > 0 )
{
// go up to the common directory
for ( int i = 0; i < projElems.size(); i++ )
{
srcElems.insert( 0, ".." );
}
}
else
{
// let it start with . nevertheless,
// so relative path always start with either ./ or ../
srcElems.insert( 0, "." );
}
return srcElems.join( "/" );
}

View File

@ -255,6 +255,15 @@ class CORE_EXPORT QgsProject : public QObject
*/
void dumpProperties() const;
/** prepare a filename to save it to the project file
@note added in 1.3 */
QString writePath( QString filename ) const;
/** turn filename read from the project file to an absolute path
@note added in 1.3 */
QString readPath( QString filename ) const;
signals:
//! emitted when project is being read