Skip to content

Commit

Permalink
Allow multiple raster selection from GDAL source select widget
Browse files Browse the repository at this point in the history
Since I'm using QgsFileWidget I also added
multiple files support to that widget and
tests for this new behavior.
  • Loading branch information
elpaso committed Aug 23, 2017
1 parent c606abc commit d1fb249
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 23 deletions.
5 changes: 3 additions & 2 deletions python/gui/qgsfilewidget.sip
Expand Up @@ -30,7 +30,8 @@ class QgsFileWidget : QWidget
enum StorageMode
{
GetFile,
GetDirectory
GetDirectory,
GetMultipleFiles,
};

enum RelativeStorage
Expand Down Expand Up @@ -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;
Expand Down
71 changes: 57 additions & 14 deletions src/gui/qgsfilewidget.cpp
Expand Up @@ -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() );
Expand All @@ -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( "\" \"" ) ) );
}
}


Expand Down Expand Up @@ -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 )
Expand Down
7 changes: 4 additions & 3 deletions src/gui/qgsfilewidget.h
Expand Up @@ -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
};

/**
Expand Down Expand Up @@ -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 );

Expand Down
16 changes: 14 additions & 2 deletions src/providers/gdal/qgsgdalsourceselect.cpp
Expand Up @@ -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;
Expand All @@ -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 )
Expand Down
19 changes: 17 additions & 2 deletions tests/src/gui/testqgsfilewidget.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
testqgsdoublespinbox.cpp
testqgsfilewidget.cpp
--------------------------------------
Date : December 2014
Copyright : (C) 2014 Nyall Dawson
Expand Down Expand Up @@ -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();

};

Expand Down Expand Up @@ -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"

0 comments on commit d1fb249

Please sign in to comment.