20 #include <QToolButton>    22 #include <QFileDialog>    23 #include <QGridLayout>    38   setBackgroundRole( QPalette::Window );
    39   setAutoFillBackground( 
true );
    41   mLayout = 
new QHBoxLayout();
    42   mLayout->setMargin( 0 );
    45   mLinkLabel = 
new QLabel( 
this );
    47   mLinkLabel->setOpenExternalLinks( 
true );
    50   mLinkLabel->setEnabled( 
true );
    51   mLinkLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
    52   mLinkLabel->setTextFormat( Qt::RichText );
    56   mLineEdit = 
new QgsFileDropEdit( 
this );
    57   mLineEdit->setDragEnabled( 
true );
    58   connect( mLineEdit, &QLineEdit::textChanged, 
this, &QgsFileWidget::textEdited );
    59   mLayout->addWidget( mLineEdit );
    61   mFileWidgetButton = 
new QToolButton( 
this );
    62   mFileWidgetButton->setText( QChar( 0x2026 ) );
    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;
   256   switch ( mStorageMode )
   259       title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( 
"Select a file" );
   260       fileName = QFileDialog::getOpenFileName( 
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
   263       title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( 
"Select one or more files" );
   264       fileNames = QFileDialog::getOpenFileNames( 
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
   267       title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( 
"Select a directory" );
   268       fileName = QFileDialog::getExistingDirectory( 
this, title, QFileInfo( oldPath ).absoluteFilePath(),  QFileDialog::ShowDirsOnly );
   272       title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( 
"Create or select a file" );
   275         fileName = QFileDialog::getSaveFileName( 
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter, QFileDialog::DontConfirmOverwrite );
   279         fileName = QFileDialog::getSaveFileName( 
this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, &mSelectedFilter );
   289   if ( fileName.isEmpty() && fileNames.isEmpty( ) )
   294     fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
   298     for ( 
int i = 0; i < fileNames.length(); i++ )
   300       fileNames.replace( i, QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileNames.at( i ) ).absoluteFilePath() ) ) );
   305   switch ( mStorageMode )
   309       settings.
setValue( QStringLiteral( 
"UI/lastFileNameWidgetDir" ), QFileInfo( fileName ).absolutePath() );
   312       settings.
setValue( QStringLiteral( 
"UI/lastFileNameWidgetDir" ), fileName );
   315       settings.
setValue( QStringLiteral( 
"UI/lastFileNameWidgetDir" ), QFileInfo( fileNames.first( ) ).absolutePath() );
   322     fileName = relativePath( fileName, 
true );
   327     for ( 
int i = 0; i < fileNames.length(); i++ )
   329       fileNames.replace( i, relativePath( fileNames.at( i ), true ) );
   331     if ( fileNames.length() > 1 )
   333       setFilePath( QStringLiteral( 
"\"%1\"" ).arg( fileNames.join( QStringLiteral( 
"\" \"" ) ) ) );
   343 QString QgsFileWidget::relativePath( 
const QString &
filePath, 
bool removeRelative )
 const   345   QString RelativePath;
   348     RelativePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( 
QgsProject::instance()->absoluteFilePath() ).path() ) );
   352     RelativePath = QDir::toNativeSeparators( QDir::cleanPath( mDefaultRoot ) );
   355   if ( !RelativePath.isEmpty() )
   357     if ( removeRelative )
   359       return QDir::cleanPath( QDir( RelativePath ).relativeFilePath( 
filePath ) );
   371 QString QgsFileWidget::toUrl( 
const QString &path )
 const   374   if ( path.isEmpty() )
   379   QString urlStr = relativePath( path, 
false );
   380   QUrl url = QUrl::fromUserInput( urlStr );
   381   if ( !url.isValid() || !url.isLocalFile() )
   383     QgsDebugMsg( QStringLiteral( 
"URL: %1 is not valid or not a local file!" ).arg( path ) );
   387   QString pathStr = url.toString();
   390     rep = QStringLiteral( 
"<a href=\"%1\">%2</a>" ).arg( pathStr, path );
   394     QString fileName = QFileInfo( urlStr ).fileName();
   395     rep = QStringLiteral( 
"<a href=\"%1\">%2</a>" ).arg( pathStr, fileName );
   406 QgsFileDropEdit::QgsFileDropEdit( QWidget *parent )
   410   setAcceptDrops( 
true );
   413 void QgsFileDropEdit::setFilters( 
const QString &filters )
   415   mAcceptableExtensions.clear();
   417   if ( filters.contains( QStringLiteral( 
"*.*" ) ) )
   420   QRegularExpression rx( QStringLiteral( 
"\\*\\.(\\w+)" ) );
   421   QRegularExpressionMatchIterator i = rx.globalMatch( filters );
   422   while ( i.hasNext() )
   424     QRegularExpressionMatch match = i.next();
   425     if ( match.hasMatch() )
   427       mAcceptableExtensions << match.captured( 1 ).toLower();
   432 QString QgsFileDropEdit::acceptableFilePath( QDropEvent *event )
 const   434   QStringList rawPaths;
   436   if ( event->mimeData()->hasUrls() )
   438     const QList< QUrl > urls = 
event->mimeData()->urls();
   439     rawPaths.reserve( urls.count() );
   440     for ( 
const QUrl &url : urls )
   442       const QString local =  url.toLocalFile();
   443       if ( !rawPaths.contains( local ) )
   444         rawPaths.append( local );
   451     if ( !rawPaths.contains( u.uri ) )
   452       rawPaths.append( u.uri );
   455   if ( !event->mimeData()->text().isEmpty() && !rawPaths.contains( event->mimeData()->text() ) )
   456     rawPaths.append( event->mimeData()->text() );
   458   paths.reserve( rawPaths.count() );
   459   for ( 
const QString &path : qgis::as_const( rawPaths ) )
   461     QFileInfo file( path );
   462     switch ( mStorageMode )
   468         if ( file.isFile() && ( mAcceptableExtensions.isEmpty() || mAcceptableExtensions.contains( file.suffix(), Qt::CaseInsensitive ) ) )
   469           paths.append( file.filePath() );
   477           paths.append( file.filePath() );
   478         else if ( file.isFile() )
   481           paths.append( file.absolutePath() );
   489   if ( paths.size() > 1 )
   491     return QStringLiteral( 
"\"%1\"" ).arg( paths.join( QStringLiteral( 
"\" \"" ) ) );
   493   else if ( paths.size() == 1 )
   495     return paths.first();
   503 void QgsFileDropEdit::dragEnterEvent( QDragEnterEvent *event )
   505   QString 
filePath = acceptableFilePath( event );
   506   if ( !filePath.isEmpty() )
   508     event->acceptProposedAction();
   518 void QgsFileDropEdit::dragLeaveEvent( QDragLeaveEvent *event )
   520   QgsFilterLineEdit::dragLeaveEvent( event );
   526 void QgsFileDropEdit::dropEvent( QDropEvent *event )
   528   QString 
filePath = acceptableFilePath( event );
   529   if ( !filePath.isEmpty() )
   533     setFocus( Qt::MouseFocusReason );
   534     event->acceptProposedAction();
   540 void QgsFileDropEdit::paintEvent( QPaintEvent *e )
   542   QgsFilterLineEdit::paintEvent( e );
   547     p.setPen( QPen( palette().highlight(), width ) );
   548     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. 
 
static UriList decodeUriList(const QMimeData *data)
 
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. 
 
QList< QgsMimeDataUtils::Uri > UriList
 
static QString addExtensionFromFilter(const QString &fileName, const QString &filter)
Ensures that a fileName ends with an extension from the specified filter string.