Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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 75df5f2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 13 deletions.
11 changes: 9 additions & 2 deletions src/gui/editorwidgets/qgsfilenamewidgetwrapper.cpp
Expand Up @@ -16,6 +16,7 @@
#include "qgsfilenamewidgetwrapper.h"

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

#include <QFileDialog>
#include <QSettings>
Expand Down Expand Up @@ -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 );
}
33 changes: 24 additions & 9 deletions src/gui/editorwidgets/qgsphotowidgetwrapper.cpp
Expand Up @@ -14,6 +14,7 @@
***************************************************************************/

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

#include <QGridLayout>
#include <QFileDialog>
Expand All @@ -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() );
Expand Down
16 changes: 14 additions & 2 deletions src/gui/editorwidgets/qgswebviewwidgetwrapper.cpp
Expand Up @@ -17,6 +17,7 @@

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

#include <QGridLayout>
#include <QFileDialog>
Expand All @@ -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()
Expand Down Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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
Copy link
Member Author

@m-kuhn m-kuhn commented on 75df5f2 Sep 8, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@m-kuhn
Copy link
Member Author

@m-kuhn m-kuhn commented on 75df5f2 Sep 8, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.