20 #include <QToolButton> 22 #include <QFileDialog> 23 #include <QGridLayout> 37 setBackgroundRole( QPalette::Window );
38 setAutoFillBackground(
true );
40 mLayout =
new QHBoxLayout();
41 mLayout->setMargin( 0 );
44 mLinkLabel =
new QLabel(
this );
46 mLinkLabel->setOpenExternalLinks(
true );
49 mLinkLabel->setEnabled(
true );
50 mLinkLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
51 mLinkLabel->setTextFormat( Qt::RichText );
55 mLineEdit =
new QgsFileDropEdit(
this );
56 mLineEdit->setToolTip( tr(
"Full path to the file(s), including name and extension" ) );
57 connect( mLineEdit, &QLineEdit::textChanged,
this, &QgsFileWidget::textEdited );
58 mLayout->addWidget( mLineEdit );
60 mFileWidgetButton =
new QToolButton(
this );
61 mFileWidgetButton->setText( QChar( 0x2026 ) );
62 mFileWidgetButton->setToolTip( tr(
"Browse" ) );
63 connect( mFileWidgetButton, &QAbstractButton::clicked,
this, &QgsFileWidget::openFileDialog );
64 mLayout->addWidget( mFileWidgetButton );
77 const QStringList pathParts = path.split( QRegExp(
"\"\\s+\"" ), QString::SkipEmptyParts );
78 for (
const auto &pathsPart : pathParts )
80 QString cleaned = pathsPart;
81 cleaned.remove( QRegExp(
"(^\\s*\")|(\"\\s*)" ) );
82 paths.append( cleaned );
95 mLineEdit->setValue( path );
101 mFileWidgetButton->setEnabled( !readOnly );
102 mLineEdit->setEnabled( !readOnly );
112 mDialogTitle = title;
123 mLineEdit->setFilters( filters );
128 return mButtonVisible;
133 mButtonVisible = visible;
134 mFileWidgetButton->setVisible( visible );
137 void QgsFileWidget::textEdited(
const QString &path )
140 mLinkLabel->setText( toUrl( path ) );
142 if ( path.contains( QStringLiteral(
"\" \"" ) ) )
144 mLineEdit->setToolTip( tr(
"Selected files:<br><ul><li>%1</li></ul><br>" ).arg(
splitFilePaths( path ).join( QStringLiteral(
"</li><li>" ) ) ) );
148 mLineEdit->setToolTip( QString() );
161 mLinkLabel->setVisible( mUseLink );
162 mLineEdit->setVisible( !mUseLink );
165 mLayout->removeWidget( mLineEdit );
166 mLayout->insertWidget( 0, mLinkLabel );
170 mLayout->removeWidget( mLinkLabel );
171 mLayout->insertWidget( 0, mLineEdit );
203 mLineEdit->setStorageMode( storageMode );
208 return mRelativeStorage;
221 void QgsFileWidget::openFileDialog()
228 if ( !mFilePath.isEmpty() )
230 oldPath = relativePath( mFilePath,
false );
234 else if ( !mDefaultRoot.isEmpty() )
236 oldPath = QDir::cleanPath( mDefaultRoot );
240 QUrl url = QUrl::fromUserInput( oldPath );
241 if ( !url.isValid() )
243 QString defPath = QDir::cleanPath( QFileInfo(
QgsProject::instance()->absoluteFilePath() ).path() );
244 if ( defPath.isEmpty() )
246 defPath = QDir::homePath();
248 oldPath = settings.
value( QStringLiteral(
"UI/lastFileNameWidgetDir" ), defPath ).toString();
253 QStringList fileNames;
257 switch ( mStorageMode )
260 title = !mDialogTitle.isEmpty() ? mDialogTitle : tr(
"Select a file" );
261 fileName = QFileDialog::getOpenFileName(
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
264 title = !mDialogTitle.isEmpty() ? mDialogTitle : tr(
"Select one or more files" );
265 fileNames = QFileDialog::getOpenFileNames(
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
268 title = !mDialogTitle.isEmpty() ? mDialogTitle : tr(
"Select a directory" );
269 fileName = QFileDialog::getExistingDirectory(
this, title, QFileInfo( oldPath ).absoluteFilePath(), QFileDialog::ShowDirsOnly );
273 title = !mDialogTitle.isEmpty() ? mDialogTitle : tr(
"Create or select a file" );
276 fileName = QFileDialog::getSaveFileName(
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter, QFileDialog::DontConfirmOverwrite );
280 fileName = QFileDialog::getSaveFileName(
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
291 if ( fileName.isEmpty() && fileNames.isEmpty( ) )
296 fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
300 for (
int i = 0; i < fileNames.length(); i++ )
302 fileNames.replace( i, QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileNames.at( i ) ).absoluteFilePath() ) ) );
307 switch ( mStorageMode )
311 settings.
setValue( QStringLiteral(
"UI/lastFileNameWidgetDir" ), QFileInfo( fileName ).absolutePath() );
314 settings.
setValue( QStringLiteral(
"UI/lastFileNameWidgetDir" ), fileName );
317 settings.
setValue( QStringLiteral(
"UI/lastFileNameWidgetDir" ), QFileInfo( fileNames.first( ) ).absolutePath() );
324 fileName = relativePath( fileName,
true );
329 for (
int i = 0; i < fileNames.length(); i++ )
331 fileNames.replace( i, relativePath( fileNames.at( i ), true ) );
333 if ( fileNames.length() > 1 )
335 setFilePath( QStringLiteral(
"\"%1\"" ).arg( fileNames.join( QStringLiteral(
"\" \"" ) ) ) );
345 QString QgsFileWidget::relativePath(
const QString &
filePath,
bool removeRelative )
const 347 QString RelativePath;
350 RelativePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo(
QgsProject::instance()->absoluteFilePath() ).path() ) );
354 RelativePath = QDir::toNativeSeparators( QDir::cleanPath( mDefaultRoot ) );
357 if ( !RelativePath.isEmpty() )
359 if ( removeRelative )
361 return QDir::cleanPath( QDir( RelativePath ).relativeFilePath(
filePath ) );
373 QString QgsFileWidget::toUrl(
const QString &path )
const 376 if ( path.isEmpty() )
381 QString urlStr = relativePath( path,
false );
382 QUrl url = QUrl::fromUserInput( urlStr );
383 if ( !url.isValid() || !url.isLocalFile() )
385 QgsDebugMsg( QStringLiteral(
"URL: %1 is not valid or not a local file!" ).arg( path ) );
389 QString pathStr = url.toString();
392 rep = QStringLiteral(
"<a href=\"%1\">%2</a>" ).arg( pathStr, path );
396 QString fileName = QFileInfo( urlStr ).fileName();
397 rep = QStringLiteral(
"<a href=\"%1\">%2</a>" ).arg( pathStr, fileName );
408 QgsFileDropEdit::QgsFileDropEdit( QWidget *parent )
412 setAcceptDrops(
true );
415 void QgsFileDropEdit::setFilters(
const QString &filters )
417 mAcceptableExtensions.clear();
419 if ( filters.contains( QStringLiteral(
"*.*" ) ) )
422 QRegularExpression rx( QStringLiteral(
"\\*\\.(\\w+)" ) );
423 QRegularExpressionMatchIterator i = rx.globalMatch( filters );
424 while ( i.hasNext() )
426 QRegularExpressionMatch match = i.next();
427 if ( match.hasMatch() )
429 mAcceptableExtensions << match.captured( 1 ).toLower();
434 QString QgsFileDropEdit::acceptableFilePath( QDropEvent *event )
const 437 if ( event->mimeData()->hasUrls() )
439 Q_FOREACH (
const QUrl &url, event->mimeData()->urls() )
441 QFileInfo file( url.toLocalFile() );
443 ( mAcceptableExtensions.isEmpty() || mAcceptableExtensions.contains( file.suffix(), Qt::CaseInsensitive ) ) )
445 paths.append( file.filePath() );
448 if ( paths.size() > 1 )
450 return QStringLiteral(
"\"%1\"" ).arg( paths.join( QStringLiteral(
"\" \"" ) ) );
452 else if ( paths.size() == 1 )
454 return paths.first();
462 void QgsFileDropEdit::dragEnterEvent( QDragEnterEvent *event )
464 QString
filePath = acceptableFilePath( event );
465 if ( !filePath.isEmpty() )
467 event->acceptProposedAction();
477 void QgsFileDropEdit::dragLeaveEvent( QDragLeaveEvent *event )
479 QgsFilterLineEdit::dragLeaveEvent( event );
485 void QgsFileDropEdit::dropEvent( QDropEvent *event )
487 QString
filePath = acceptableFilePath( event );
488 if ( !filePath.isEmpty() )
492 setFocus( Qt::MouseFocusReason );
493 event->acceptProposedAction();
499 void QgsFileDropEdit::paintEvent( QPaintEvent *e )
501 QgsFilterLineEdit::paintEvent( e );
506 p.setPen( QPen( palette().highlight(), width ) );
507 QRect r = rect().adjusted( width, width, -width, -width );
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QgsProject * instance()
Returns the QgsProject singleton instance.
static QString addExtensionFromFilter(const QString &fileName, const QString &filter)
Ensures that a fileName ends with an extension from the specified filter string.