QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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( textChanged( 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 
90  //will trigger textEdited slot
91  mLineEdit->setValue( path );
92 }
93 
94 void QgsFileWidget::setReadOnly( bool readOnly )
95 {
96  mFileWidgetButton->setEnabled( !readOnly );
97  mLineEdit->setEnabled( !readOnly );
98 }
99 
101 {
102  return mDialogTitle;
103 }
104 
106 {
107  mDialogTitle = title;
108 }
109 
111 {
112  return mFilter;
113 }
114 
115 void QgsFileWidget::setFilter( const QString& filters )
116 {
117  mFilter = filters;
118 }
119 
121 {
122  return mButtonVisible;
123 }
124 
126 {
127  mButtonVisible = visible;
128  mFileWidgetButton->setVisible( visible );
129 }
130 
131 void QgsFileWidget::textEdited( const QString& path )
132 {
133  mFilePath = path;
134  mLinkLabel->setText( toUrl( path ) );
135  emit fileChanged( mFilePath );
136 }
137 
138 bool QgsFileWidget::useLink() const
139 {
140  return mUseLink;
141 }
142 
144 {
145  mUseLink = useLink;
146  mLinkLabel->setVisible( mUseLink );
147  mLineEdit->setVisible( !mUseLink );
148 }
149 
150 bool QgsFileWidget::fullUrl() const
151 {
152  return mFullUrl;
153 }
154 
156 {
157  mFullUrl = fullUrl;
158 }
159 
161 {
162  return mDefaultRoot;
163 }
164 
166 {
167  mDefaultRoot = defaultRoot;
168 }
169 
171 {
172  return mStorageMode;
173 }
174 
176 {
177  mStorageMode = storageMode;
178 }
179 
181 {
182  return mRelativeStorage;
183 }
184 
186 {
187  mRelativeStorage = relativeStorage;
188 }
189 
190 void QgsFileWidget::openFileDialog()
191 {
192  QSettings settings;
193  QString oldPath;
194 
195  // If we use fixed default path
196  if ( !mDefaultRoot.isEmpty() )
197  {
198  oldPath = QDir::cleanPath( mDefaultRoot );
199  }
200  // if we use a relative path option, we need to obtain the full path
201  else if ( !mFilePath.isEmpty() )
202  {
203  oldPath = relativePath( mFilePath, false );
204  }
205 
206  // If there is no valid value, find a default path to use
207  QUrl theUrl = QUrl::fromUserInput( oldPath );
208  if ( !theUrl.isValid() )
209  {
210  QString defPath = QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() );
211  if ( defPath.isEmpty() )
212  {
213  defPath = QDir::homePath();
214  }
215  oldPath = settings.value( "/UI/lastExternalResourceWidgetDefaultPath", defPath ).toString();
216  }
217 
218  // Handle Storage
219  QString fileName;
220  QString title;
221  if ( mStorageMode == GetFile )
222  {
223  title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a file" );
224  fileName = QFileDialog::getOpenFileName( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter );
225  }
226  else if ( mStorageMode == GetDirectory )
227  {
228  title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a directory" );
229  fileName = QFileDialog::getExistingDirectory( this, title, QFileInfo( oldPath ).absoluteFilePath(), QFileDialog::ShowDirsOnly );
230  }
231 
232  if ( fileName.isEmpty() )
233  return;
234 
235 
236  fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
237  // Store the last used path:
238 
239  if ( mStorageMode == GetFile )
240  {
241  settings.setValue( "/UI/lastFileNameWidgetDir", QFileInfo( fileName ).absolutePath() );
242  }
243  else if ( mStorageMode == GetDirectory )
244  {
245  settings.setValue( "/UI/lastFileNameWidgetDir", fileName );
246  }
247 
248  // Handle relative Path storage
249  fileName = relativePath( fileName, true );
250 
251  // Keep the new value
252  setFilePath( fileName );
253 }
254 
255 
256 QString QgsFileWidget::relativePath( const QString& filePath, bool removeRelative ) const
257 {
258  QString RelativePath;
259  if ( mRelativeStorage == RelativeProject )
260  {
261  RelativePath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
262  }
263  else if ( mRelativeStorage == RelativeDefaultPath && !mDefaultRoot.isEmpty() )
264  {
265  RelativePath = QDir::toNativeSeparators( QDir::cleanPath( mDefaultRoot ) );
266  }
267 
268  if ( !RelativePath.isEmpty() )
269  {
270  if ( removeRelative )
271  {
272  return QDir::cleanPath( QDir( RelativePath ).relativeFilePath( filePath ) );
273  }
274  else
275  {
276  return QDir::cleanPath( QDir( RelativePath ).filePath( filePath ) );
277  }
278  }
279 
280  return filePath;
281 }
282 
283 
284 QString QgsFileWidget::toUrl( const QString& path ) const
285 {
286  QString rep;
287  if ( path.isEmpty() )
288  {
289  return QSettings().value( "qgis/nullValue", "NULL" ).toString();
290  }
291 
292  QString urlStr = relativePath( path, false );
293  QUrl url = QUrl::fromUserInput( urlStr );
294  if ( !url.isValid() || !url.isLocalFile() )
295  {
296  QgsDebugMsg( QString( "URL: %1 is not valid or not a local file!" ).arg( path ) );
297  rep = path;
298  }
299 
300  QString pathStr = url.toString();
301  if ( mFullUrl )
302  {
303  rep = QString( "<a href=\"%1\">%2</a>" ).arg( pathStr, path );
304  }
305  else
306  {
307  QString fileName = QFileInfo( urlStr ).fileName();
308  rep = QString( "<a href=\"%1\">%2</a>" ).arg( pathStr, fileName );
309  }
310 
311  return rep;
312 }
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...
bool useLink() const
determines if the file path will be shown as a link
QString toNativeSeparators(const QString &pathName)
QgsFileWidget::StorageMode storageMode() const
returns the storage mode (i.e. file or directory)
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)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setReadOnly(bool readOnly)
defines if the widget is readonly
void setStorageMode(QgsFileWidget::StorageMode storageMode)
determines the storage mode (i.e. file or directory)
QUrl fromUserInput(const QString &userInput)
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.
QString defaultRoot() const
returns the default root path
void setValue(const QString &key, const QVariant &value)
void setEnabled(bool)
QString dialogTitle() const
returns the open file dialog title
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)
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
void setText(const QString &)
void hide()
void setMargin(int margin)
void setSizePolicy(QSizePolicy)
void setFileWidgetButtonVisible(bool visible)
determines if the tool button is shown
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
QgsFileWidget::RelativeStorage relativeStorage() const
returns if the relative path is with respect to the project path or the default path ...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
void setText(const QString &text)
bool fileWidgetButtonVisible() const
determines if the tool button is shown
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)
bool fullUrl() const
returns if the links shows the full path or not
QString filter() const
returns the filters used for QDialog::getOpenFileName
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.
void setValue(const QString &value)
Sets the current text for the widget with support for handling null values.
RelativeStorage
The RelativeStorage enum determines if path is absolute, relative to the current project path or rela...
Definition: qgsfilewidget.h:56
bool isLocalFile() const