QGIS API Documentation  2.14.0-Essen
qgsfilewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfilewidget.cpp
3 
4  ---------------------
5  begin : 17.12.2015
6  copyright : (C) 2015 by Denis Rouzaud
7  email : [email protected]
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgsfilewidget.h"
18 
19 #include <QLineEdit>
20 #include <QToolButton>
21 #include <QLabel>
22 #include <QFileDialog>
23 #include <QSettings>
24 #include <QGridLayout>
25 #include <QUrl>
26 
27 #include "qgsfilterlineedit.h"
28 #include "qgslogger.h"
29 #include "qgsproject.h"
30 
32  : QWidget( parent )
33  , mFilePath( QString() )
34  , mButtonVisible( true )
35  , mUseLink( false )
36  , mFullUrl( false )
37  , mDialogTitle( QString() )
38  , mFilter( QString() )
39  , mDefaultRoot( QString() )
40  , mStorageMode( GetFile )
41  , mRelativeStorage( Absolute )
42 {
43  setBackgroundRole( QPalette::Window );
44  setAutoFillBackground( true );
45 
47  layout->setMargin( 0 );
48 
49  // If displaying a hyperlink, use a QLabel
50  mLinkLabel = new QLabel( this );
51  // Make Qt opens the link with the OS defined viewer
52  mLinkLabel->setOpenExternalLinks( true );
53  // Label should always be enabled to be able to open
54  // the link on read only mode.
55  mLinkLabel->setEnabled( true );
56  mLinkLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
57  mLinkLabel->setTextFormat( Qt::RichText );
58  layout->addWidget( mLinkLabel, 0, 0 );
59  mLinkLabel->hide(); // do not show by default
60 
61  // otherwise, use the traditional QLineEdit
62  mLineEdit = new QgsFilterLineEdit( this );
63  connect( mLineEdit, SIGNAL( textEdited( QString ) ), this, SLOT( textEdited( QString ) ) );
64  layout->addWidget( mLineEdit, 1, 0 );
65 
66  mFileWidgetButton = new QToolButton( this );
67  mFileWidgetButton->setText( "..." );
68  connect( mFileWidgetButton, SIGNAL( clicked() ), this, SLOT( openFileDialog() ) );
69  layout->addWidget( mFileWidgetButton, 0, 1, 2, 1 );
70 
71  setLayout( layout );
72 }
73 
75 {
76 }
77 
79 {
80  return mFilePath;
81 }
82 
84 {
85  if ( path == QSettings().value( "qgis/nullValue", "NULL" ) )
86  {
87  path = "";
88  }
89  mFilePath = path;
90  mLineEdit->setText( path );
91  mLinkLabel->setText( toUrl( path ) );
92  emit fileChanged( mFilePath );
93 }
94 
95 void QgsFileWidget::setReadOnly( bool readOnly )
96 {
97  mFileWidgetButton->setEnabled( !readOnly );
98  mLineEdit->setEnabled( !readOnly );
99 }
100 
102 {
103  return mDialogTitle;
104 }
105 
107 {
108  mDialogTitle = title;
109 }
110 
112 {
113  return mFilter;
114 }
115 
116 void QgsFileWidget::setFilter( const QString& filters )
117 {
118  mFilter = filters;
119 }
120 
122 {
123  return mButtonVisible;
124 }
125 
127 {
128  mButtonVisible = visible;
129  mFileWidgetButton->setVisible( visible );
130 }
131 
132 void QgsFileWidget::textEdited( const QString& path )
133 {
134  mFilePath = path;
135  mLinkLabel->setText( toUrl( path ) );
136  emit fileChanged( mFilePath );
137 }
138 
139 bool QgsFileWidget::useLink() const
140 {
141  return mUseLink;
142 }
143 
145 {
146  mUseLink = useLink;
147  mLinkLabel->setVisible( mUseLink );
148  mLineEdit->setVisible( !mUseLink );
149 }
150 
151 bool QgsFileWidget::fullUrl() const
152 {
153  return mFullUrl;
154 }
155 
157 {
158  mFullUrl = fullUrl;
159 }
160 
162 {
163  return mDefaultRoot;
164 }
165 
167 {
168  mDefaultRoot = defaultRoot;
169 }
170 
172 {
173  return mStorageMode;
174 }
175 
177 {
178  mStorageMode = storageMode;
179 }
180 
182 {
183  return mRelativeStorage;
184 }
185 
187 {
188  mRelativeStorage = relativeStorage;
189 }
190 
191 void QgsFileWidget::openFileDialog()
192 {
193  QSettings settings;
194  QString oldPath;
195 
196  // If we use fixed default path
197  if ( !mDefaultRoot.isEmpty() )
198  {
199  oldPath = QDir::cleanPath( mDefaultRoot );
200  }
201  // if we use a relative path option, we need to obtain the full path
202  else if ( !mFilePath.isEmpty() )
203  {
204  oldPath = relativePath( mFilePath, false );
205  }
206 
207  // If there is no valid value, find a default path to use
208  QUrl theUrl = QUrl::fromUserInput( oldPath );
209  if ( !theUrl.isValid() )
210  {
211  QString defPath = QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() );
212  if ( defPath.isEmpty() )
213  {
214  defPath = QDir::homePath();
215  }
216  oldPath = settings.value( "/UI/lastExternalResourceWidgetDefaultPath", defPath ).toString();
217  }
218 
219  // Handle Storage
220  QString fileName;
221  QString title;
222  if ( mStorageMode == GetFile )
223  {
224  title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a file" );
225  fileName = QFileDialog::getOpenFileName( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter );
226  }
227  else if ( mStorageMode == GetDirectory )
228  {
229  title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a directory" );
230  fileName = QFileDialog::getExistingDirectory( this, title, QFileInfo( oldPath ).absoluteFilePath(), QFileDialog::ShowDirsOnly );
231  }
232 
233  if ( fileName.isEmpty() )
234  return;
235 
236 
237  fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
238  // Store the last used path:
239 
240  if ( mStorageMode == GetFile )
241  {
242  settings.setValue( "/UI/lastFileNameWidgetDir", QFileInfo( fileName ).absolutePath() );
243  }
244  else if ( mStorageMode == GetDirectory )
245  {
246  settings.setValue( "/UI/lastFileNameWidgetDir", fileName );
247  }
248 
249  // Handle relative Path storage
250  fileName = relativePath( fileName, true );
251 
252  // Keep the new value
253  setFilePath( fileName );
254 }
255 
256 
257 QString QgsFileWidget::relativePath( const QString& filePath, bool removeRelative ) const
258 {
259  QString RelativePath;
260  if ( mRelativeStorage == RelativeProject )
261  {
262  RelativePath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
263  }
264  else if ( mRelativeStorage == RelativeDefaultPath && !mDefaultRoot.isEmpty() )
265  {
266  RelativePath = QDir::toNativeSeparators( QDir::cleanPath( mDefaultRoot ) );
267  }
268 
269  if ( !RelativePath.isEmpty() )
270  {
271  if ( removeRelative )
272  {
273  return QDir::cleanPath( QDir( RelativePath ).relativeFilePath( filePath ) );
274  }
275  else
276  {
277  return QDir::cleanPath( QDir( RelativePath ).filePath( filePath ) );
278  }
279  }
280 
281  return filePath;
282 }
283 
284 
285 QString QgsFileWidget::toUrl( const QString& path ) const
286 {
287  QString rep;
288  if ( path.isEmpty() )
289  {
290  return QSettings().value( "qgis/nullValue", "NULL" ).toString();
291  }
292 
293  QString urlStr = relativePath( path, false );
294  QUrl url = QUrl::fromUserInput( urlStr );
295  if ( !url.isValid() || !url.isLocalFile() )
296  {
297  QgsDebugMsg( QString( "URL: %1 is not valid or not a local file !" ).arg( path ) );
298  rep = path;
299  }
300 
301  QString pathStr = url.toString();
302  if ( mFullUrl )
303  {
304  rep = QString( "<a href=\"%1\">%2</a>" ).arg( pathStr, path );
305  }
306  else
307  {
308  QString fileName = QFileInfo( urlStr ).fileName();
309  rep = QString( "<a href=\"%1\">%2</a>" ).arg( pathStr, fileName );
310  }
311 
312  return rep;
313 }
QLayout * layout() const
void setDefaultRoot(const QString &defaultRoot)
determines the default root path used as the first shown location when picking a file and used if the...
QString toNativeSeparators(const QString &pathName)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFlags< QFileDialog::Option > options)
void setFilter(const QString &filter)
setFilter sets the filter used by the model to filters.
void fileChanged(const QString &)
emitted as soon as the current file or directory is changed
void setUseLink(bool useLink)
determines if the file path will be shown as a link
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
void setText(const QString &)
bool useLink() const
determines if the file path will be shown as a link
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool fileWidgetButtonVisible() const
determines if the tool button is shown
void setReadOnly(bool readOnly)
defines if the widget is readonly
bool fullUrl() const
returns if the links shows the full path or not
void setStorageMode(QgsFileWidget::StorageMode storageMode)
determines the storage mode (i.e. file or directory)
QUrl fromUserInput(const QString &userInput)
QString dialogTitle() const
returns the open file dialog title
QString homePath()
QString toString(QFlags< QUrl::FormattingOption > options) const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString filePath()
Returns the current file path.
void setValue(const QString &key, const QVariant &value)
void setEnabled(bool)
void setLayout(QLayout *layout)
void setRelativeStorage(QgsFileWidget::RelativeStorage relativeStorage)
determines if the relative path is with respect to the project path or the default path ...
QString fileName() const
bool isEmpty() const
void setDialogTitle(const QString &title)
setDialogTitle defines the open file dialog title
void setTextFormat(Qt::TextFormat)
Lineedit with builtin clear button.
void setText(const QString &)
void hide()
void setMargin(int margin)
void setSizePolicy(QSizePolicy)
void setFileWidgetButtonVisible(bool visible)
determines if the tool button is shown
QgsFileWidget::StorageMode storageMode() const
returns the storage mode (i.e. file or directory)
StorageMode
The StorageMode enum determines if the file picker should pick files or directories.
Definition: qgsfilewidget.h:47
QString cleanPath(const QString &path)
QVariant value(const QString &key, const QVariant &defaultValue) const
bool isValid() const
QString filter() const
returns the filters used for QDialog::getOpenFileName
QString defaultRoot() const
returns the default root path
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:381
QgsFileWidget::RelativeStorage relativeStorage() const
returns if the relative path is with respect to the project path or the default path ...
void setText(const QString &text)
void setAutoFillBackground(bool enabled)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
void setBackgroundRole(QPalette::ColorRole role)
QgsFileWidget(QWidget *parent=0)
QgsFileWidget creates a widget for selecting a file or a folder.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void setFullUrl(bool fullUrl)
determines if the links shows the full path or not
void setFilePath(QString path)
Sets the file path.
RelativeStorage
The RelativeStorage enum determines if path is absolute, relative to the current project path or rela...
Definition: qgsfilewidget.h:56
bool isLocalFile() const