Allow multiple raster selection from GDAL source select widget

Since I'm using QgsFileWidget I also added
multiple files support to that widget and
tests for this new behavior.
This commit is contained in:
Alessandro Pasotti 2017-08-23 16:17:15 +02:00
parent c606abc702
commit d1fb2490a7
5 changed files with 95 additions and 23 deletions

View File

@ -30,7 +30,8 @@ class QgsFileWidget : QWidget
enum StorageMode
{
GetFile,
GetDirectory
GetDirectory,
GetMultipleFiles,
};
enum RelativeStorage
@ -72,7 +73,7 @@ returns the open file dialog title
setDialogTitle defines the open file dialog title
.. note::
if not defined, the title is "Select a file" or "Select a directory" depending on the configuration.
if not defined, the title is "Select a file" or "Select a directory" or "Select one or more files" depending on the configuration.
%End
QString filter() const;

View File

@ -231,25 +231,40 @@ void QgsFileWidget::openFileDialog()
// Handle Storage
QString fileName;
QStringList fileNames;
QString title;
if ( mStorageMode == GetFile )
{
title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a file" );
fileName = QFileDialog::getOpenFileName( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter );
}
else if ( mStorageMode == GetMultipleFiles )
{
title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select one ore more files" );
fileNames = QFileDialog::getOpenFileNames( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter );
}
else if ( mStorageMode == GetDirectory )
{
title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a directory" );
fileName = QFileDialog::getExistingDirectory( this, title, QFileInfo( oldPath ).absoluteFilePath(), QFileDialog::ShowDirsOnly );
}
if ( fileName.isEmpty() )
if ( fileName.isEmpty() && fileNames.isEmpty( ) )
return;
if ( mStorageMode != GetMultipleFiles )
{
fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
}
else
{
for ( int i = 0; i < fileNames.length(); i++ )
{
fileNames.replace( i, QDir::cleanPath( QFileInfo( fileNames.at( i ) ).absoluteFilePath() ) ) ;
}
}
fileName = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
// Store the last used path:
if ( mStorageMode == GetFile )
{
settings.setValue( QStringLiteral( "UI/lastFileNameWidgetDir" ), QFileInfo( fileName ).absolutePath() );
@ -258,12 +273,26 @@ void QgsFileWidget::openFileDialog()
{
settings.setValue( QStringLiteral( "UI/lastFileNameWidgetDir" ), fileName );
}
else if ( mStorageMode == GetMultipleFiles )
{
settings.setValue( QStringLiteral( "UI/lastFileNameWidgetDir" ), fileNames.first( ) );
}
// Handle relative Path storage
fileName = relativePath( fileName, true );
// Keep the new value
setFilePath( fileName );
if ( mStorageMode != GetMultipleFiles )
{
fileName = relativePath( fileName, true );
// Keep the new value
setFilePath( fileName );
}
else
{
for ( int i = 0; i < fileNames.length(); i++ )
{
fileNames.replace( i, relativePath( fileNames.at( i ), true ) );
}
setFilePath( QStringLiteral( "\"%1\"" ).arg( fileNames.join( "\" \"" ) ) );
}
}
@ -359,16 +388,30 @@ void QgsFileDropEdit::setFilters( const QString &filters )
QString QgsFileDropEdit::acceptableFilePath( QDropEvent *event ) const
{
QString path;
QStringList paths;
if ( event->mimeData()->hasUrls() )
{
QFileInfo file( event->mimeData()->urls().first().toLocalFile() );
if ( ( mStorageMode == QgsFileWidget::GetFile && file.isFile() &&
( mAcceptableExtensions.isEmpty() || mAcceptableExtensions.contains( file.suffix(), Qt::CaseInsensitive ) ) )
|| ( mStorageMode == QgsFileWidget::GetDirectory && file.isDir() ) )
path = file.filePath();
for ( const auto url : event->mimeData()->urls() )
{
QFileInfo file( url.toLocalFile() );
if ( ( mStorageMode != QgsFileWidget::GetDirectory && file.isFile() &&
( mAcceptableExtensions.isEmpty() || mAcceptableExtensions.contains( file.suffix(), Qt::CaseInsensitive ) ) )
|| ( mStorageMode == QgsFileWidget::GetDirectory && file.isDir() ) )
paths.append( file.filePath() );
}
}
if ( paths.size() > 1 )
{
return QStringLiteral( "\"%1\"" ).arg( paths.join( "\" \"" ) );
}
else if ( paths.size() == 1 )
{
return paths.first();
}
else
{
return QString();
}
return path;
}
void QgsFileDropEdit::dragEnterEvent( QDragEnterEvent *event )

View File

@ -61,8 +61,9 @@ class GUI_EXPORT QgsFileWidget : public QWidget
*/
enum StorageMode
{
GetFile,
GetDirectory
GetFile, //! Select a single file
GetDirectory, //! Select a directory
GetMultipleFiles, //! Select multiple files
};
/**
@ -94,7 +95,7 @@ class GUI_EXPORT QgsFileWidget : public QWidget
/**
* \brief setDialogTitle defines the open file dialog title
* \note if not defined, the title is "Select a file" or "Select a directory" depending on the configuration.
* \note if not defined, the title is "Select a file" or "Select a directory" or "Select one or more files" depending on the configuration.
*/
void setDialogTitle( const QString &title );

View File

@ -24,6 +24,7 @@ QgsGdalSourceSelect::QgsGdalSourceSelect( QWidget *parent, Qt::WindowFlags fl, Q
setupUi( this );
setupButtons( buttonBox );
mQgsFileWidget->setFilter( QgsProviderRegistry::instance()->fileRasterFilters() );
mQgsFileWidget->setStorageMode( QgsFileWidget::GetMultipleFiles );
connect( mQgsFileWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & path )
{
mRasterPath = path;
@ -38,8 +39,19 @@ QgsGdalSourceSelect::~QgsGdalSourceSelect()
void QgsGdalSourceSelect::addButtonClicked()
{
QFileInfo baseName( mRasterPath );
emit addRasterLayer( mRasterPath, baseName.baseName(), QStringLiteral( "gdal" ) );
// Check if multiple files where selected
if ( mRasterPath.startsWith( '"' ) )
{
for ( QString path : mRasterPath.split( QRegExp( "\"\\s+\"" ), QString::SkipEmptyParts ) )
{
QString cleanPath( path.remove( '"' ) );
emit addRasterLayer( cleanPath, QFileInfo( cleanPath ).baseName(), QStringLiteral( "gdal" ) );
}
}
else
{
emit addRasterLayer( mRasterPath, QFileInfo( mRasterPath ).baseName(), QStringLiteral( "gdal" ) );
}
}
QGISEXTERN QgsGdalSourceSelect *selectWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )

View File

@ -1,5 +1,5 @@
/***************************************************************************
testqgsdoublespinbox.cpp
testqgsfilewidget.cpp
--------------------------------------
Date : December 2014
Copyright : (C) 2014 Nyall Dawson
@ -27,10 +27,10 @@ class TestQgsFileWidget: public QObject
void cleanupTestCase(); // will be called after the last testfunction was executed.
void init(); // will be called before each testfunction is executed.
void cleanup(); // will be called after every testfunction.
void relativePath();
void toUrl();
void testDroppedFiles();
void testMultipleFiles();
};
@ -140,5 +140,20 @@ void TestQgsFileWidget::testDroppedFiles()
}
void TestQgsFileWidget::testMultipleFiles()
{
QgsFileWidget *w = new QgsFileWidget();
w->setStorageMode( QgsFileWidget::GetFile );
std::unique_ptr< QMimeData > mime( new QMimeData() );
mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) )
<< QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
std::unique_ptr< QDropEvent > event( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
QCOMPARE( w->lineEdit()->text(), QStringLiteral( "\"%1\" \"%1\"" ).arg( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
}
QGSTEST_MAIN( TestQgsFileWidget )
#include "testqgsfilewidget.moc"