[QGIS Commit] r11571 - in trunk/qgis: python/core src/core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Sep 5 15:49:10 EDT 2009


Author: jef
Date: 2009-09-05 15:49:10 -0400 (Sat, 05 Sep 2009)
New Revision: 11571

Modified:
   trunk/qgis/python/core/qgsproject.sip
   trunk/qgis/src/core/qgsmaplayer.cpp
   trunk/qgis/src/core/qgsproject.cpp
   trunk/qgis/src/core/qgsproject.h
Log:
improve relative path support

Modified: trunk/qgis/python/core/qgsproject.sip
===================================================================
--- trunk/qgis/python/core/qgsproject.sip	2009-09-05 19:45:32 UTC (rev 11570)
+++ trunk/qgis/python/core/qgsproject.sip	2009-09-05 19:49:10 UTC (rev 11571)
@@ -223,6 +223,14 @@
     */
     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

Modified: trunk/qgis/src/core/qgsmaplayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsmaplayer.cpp	2009-09-05 19:45:32 UTC (rev 11570)
+++ trunk/qgis/src/core/qgsmaplayer.cpp	2009-09-05 19:49:10 UTC (rev 11571)
@@ -152,21 +152,8 @@
   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 );
+  mDataSource = QgsProject::instance()->readPath( mDataSource );
 
-      if ( fi.exists() )
-      {
-        mDataSource = fi.canonicalFilePath();
-      }
-    }
-  }
-
   // Set the CRS from project file, asking the user if necessary.
   // Make it the saved CRS to have WMS layer projected correctly.
   // We will still overwrite whatever GDAL etc picks up anyway
@@ -280,20 +267,8 @@
   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 );

Modified: trunk/qgis/src/core/qgsproject.cpp
===================================================================
--- trunk/qgis/src/core/qgsproject.cpp	2009-09-05 19:45:32 UTC (rev 11570)
+++ trunk/qgis/src/core/qgsproject.cpp	2009-09-05 19:49:10 UTC (rev 11571)
@@ -1300,3 +1300,154 @@
 {
   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( "/" );
+}

Modified: trunk/qgis/src/core/qgsproject.h
===================================================================
--- trunk/qgis/src/core/qgsproject.h	2009-09-05 19:45:32 UTC (rev 11570)
+++ trunk/qgis/src/core/qgsproject.h	2009-09-05 19:49:10 UTC (rev 11571)
@@ -255,6 +255,15 @@
     */
     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



More information about the QGIS-commit mailing list