Skip to content
Permalink
Browse files

[FEATURE] Support for relative paths in widgets

Is implemented for the following edit widget types:

 * File Name
 * Photo
 * Web View

If the path which is selected with the file browser is located in the same
directory as the .qgs project file or below, paths are converted to relative
paths.
This increases portability of a qgs project with multimedia
information attached.
  • Loading branch information
m-kuhn committed Sep 7, 2015
1 parent 3043f7f commit 75df5f20c9d6ae40dd5b05f4da71defbab84d283
@@ -16,6 +16,7 @@
#include "qgsfilenamewidgetwrapper.h"

#include "qgsfilterlineedit.h"
#include "qgsproject.h"

#include <QFileDialog>
#include <QSettings>
@@ -127,9 +128,15 @@ void QgsFileNameWidgetWrapper::selectFileName()
if ( fileName.isNull() )
return;

QString projPath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
QString filePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );

if ( filePath.startsWith( projPath ) )
filePath = QDir( projPath ).relativeFilePath( filePath );

if ( mLineEdit )
mLineEdit->setText( QDir::toNativeSeparators( fileName ) );
mLineEdit->setText( fileName );

if ( mLabel )
mLineEdit->setText( QDir::toNativeSeparators( fileName ) );
mLineEdit->setText( fileName );
}
@@ -14,6 +14,7 @@
***************************************************************************/

#include "qgsphotowidgetwrapper.h"
#include "qgsproject.h"

#include <QGridLayout>
#include <QFileDialog>
@@ -34,24 +35,38 @@ QgsPhotoWidgetWrapper::QgsPhotoWidgetWrapper( QgsVectorLayer* vl, int fieldIdx,

void QgsPhotoWidgetWrapper::selectFileName()
{
if ( mLineEdit )
{
QString fileName = QFileDialog::getOpenFileName( 0, tr( "Select a picture" ), QFileInfo( mLineEdit->text() ).absolutePath() );
if ( !fileName.isNull() )
mLineEdit->setText( QDir::toNativeSeparators( fileName ) );
}
if ( !mLineEdit )
return;

QString fileName = QFileDialog::getOpenFileName( 0, tr( "Select a picture" ), QFileInfo( mLineEdit->text() ).absolutePath() );

if ( fileName.isNull() )
return;

QString projPath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
QString filePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );

if ( filePath.startsWith( projPath ) )
filePath = QDir( projPath ).relativeFilePath( filePath );

mLineEdit->setText( filePath );
}

void QgsPhotoWidgetWrapper::loadPixmap( const QString &fileName )
void QgsPhotoWidgetWrapper::loadPixmap( const QString& fileName )
{
QString filePath = fileName;

if ( QUrl( fileName ).isRelative() )
filePath = QDir( QgsProject::instance()->fileInfo().absolutePath() ).filePath( fileName );

#ifdef WITH_QTWEBKIT
if ( mWebView )
{
mWebView->setUrl( fileName );
mWebView->setUrl( filePath );
}
#endif

QPixmap pm( fileName );
QPixmap pm( filePath );
if ( !pm.isNull() && mPhotoLabel )
{
QSize size( config( "Width" ).toInt(), config( "Height" ).toInt() );
@@ -17,6 +17,7 @@

#include "qgsfilterlineedit.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsproject.h"

#include <QGridLayout>
#include <QFileDialog>
@@ -32,8 +33,13 @@ QgsWebViewWidgetWrapper::QgsWebViewWidgetWrapper( QgsVectorLayer* vl, int fieldI

void QgsWebViewWidgetWrapper::loadUrl( const QString &url )
{
QString path = url;

if ( QUrl( url ).isRelative() )
path = QDir( QgsProject::instance()->fileInfo().absolutePath() ).filePath( url );

if ( mWebView )
mWebView->load( url );
mWebView->load( path );
}

QVariant QgsWebViewWidgetWrapper::value()
@@ -160,6 +166,12 @@ void QgsWebViewWidgetWrapper::selectFileName()
if ( fileName.isNull() )
return;

QString projPath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
QString filePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );

if ( filePath.startsWith( projPath ) )
filePath = QDir( projPath ).relativeFilePath( filePath );

if ( mLineEdit )
mLineEdit->setText( QDir::toNativeSeparators( fileName ) );
mLineEdit->setText( filePath );
}

4 comments on commit 75df5f2

@nyalldawson

This comment has been minimized.

Copy link
Collaborator

@nyalldawson nyalldawson replied Sep 7, 2015

@m-kuhn nice! One thing I'm not sure about is whether this is a good idea to have this behaviour by default. I think it should be a non-default option for the widgets, so that users have to opt-in to storing relative paths.

My rationale is that otherwise this is making data dependant on a project's location. I think in general it is bad practice to make data dependant on a project, as it breaks portability of the data.

@m-kuhn

This comment has been minimized.

Copy link
Member Author

@m-kuhn m-kuhn replied Sep 8, 2015

As soon as a path outside the .qgs project folder is chosen the absolute path will be used.

I assume that whenever you place a file in the same (or a sub-) folder of the .qgs project it's ok to assume it's bound to this directory structure.

@nyalldawson

This comment has been minimized.

Copy link
Collaborator

@nyalldawson nyalldawson replied Sep 8, 2015

@m-kuhn i still disagree :) I think at least the project setting for storing absolute/relative paths should be respected.

@m-kuhn

This comment has been minimized.

Copy link
Member Author

@m-kuhn m-kuhn replied Sep 8, 2015

@nyalldawson I agree that there still is a small risk that it is desirable to turn it off in certain situations.
I think that in general the assumption of a common directory indicating a preference for relative paths is quite accurate.

What I want to avoid is having to enable it for 20 different file widgets in the same project, so respecting the project setting would be a good approach (a widget-specific override flag can still be added later) but the project setting is off by default :(

Please sign in to comment.
You can’t perform that action at this time.