From 9c67560b0c07021b522c7dc69e3d943bc2c1bb67 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Mon, 18 Sep 2017 17:36:26 +0200 Subject: [PATCH] Geopackage import multiple files master task This fixes a problem when importing multiple files into a gpkg. Previous implementation spawned multiple independent task causing the import to fail because of DB being write-locked. This implementation uses a master task with subtask and dependencies. --- src/providers/ogr/qgsgeopackagedataitems.cpp | 29 +++++++++++++------- src/providers/ogr/qgsgeopackagedataitems.h | 20 ++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/providers/ogr/qgsgeopackagedataitems.cpp b/src/providers/ogr/qgsgeopackagedataitems.cpp index c5c39e96ecb..c6e7da91627 100644 --- a/src/providers/ogr/qgsgeopackagedataitems.cpp +++ b/src/providers/ogr/qgsgeopackagedataitems.cpp @@ -28,6 +28,7 @@ #include "qgsmessageoutput.h" #include "qgsvectorlayerexporter.h" #include "qgsgeopackagerasterwritertask.h" +#include "qgstaskmanager.h" #include #include @@ -191,6 +192,10 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct QStringList importResults; bool hasError = false; + // Main task + std::unique_ptr< QgsGeoPackageImportTask > mainTask( new QgsGeoPackageImportTask( tr( "GeoPackage import" ) ) ); + QgsTaskList importTasks; + const auto lst = QgsMimeDataUtils::decodeUriList( data ); for ( const QgsMimeDataUtils::Uri &dropUri : lst ) { @@ -252,10 +257,11 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct options.insert( QStringLiteral( "update" ), true ); options.insert( QStringLiteral( "overwrite" ), true ); options.insert( QStringLiteral( "layerName" ), dropUri.name ); - - std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( vectorSrcLayer, uri, QStringLiteral( "ogr" ), vectorSrcLayer->crs(), options, owner ) ); + QgsVectorLayerExporterTask *exportTask = new QgsVectorLayerExporterTask( vectorSrcLayer, uri, QStringLiteral( "ogr" ), vectorSrcLayer->crs(), options, owner ) ; + mainTask->addSubTask( exportTask, importTasks ); + importTasks << exportTask; // when export is successful: - connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]() + connect( exportTask, &QgsVectorLayerExporterTask::exportComplete, this, [ = ]() { // this is gross - TODO - find a way to get access to messageBar from data items QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) ); @@ -263,7 +269,7 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct } ); // when an error occurs: - connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage ) + connect( exportTask, &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage ) { if ( error != QgsVectorLayerExporter::ErrUserCanceled ) { @@ -274,14 +280,14 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct } } ); - QgsApplication::taskManager()->addTask( exportTask.release() ); } else // Import raster { - - std::unique_ptr< QgsGeoPackageRasterWriterTask > exportTask( new QgsGeoPackageRasterWriterTask( dropUri, mPath ) ); + QgsGeoPackageRasterWriterTask *exportTask = new QgsGeoPackageRasterWriterTask( dropUri, mPath ) ; + mainTask->addSubTask( exportTask, importTasks ); + importTasks << exportTask; // when export is successful: - connect( exportTask.get(), &QgsGeoPackageRasterWriterTask::writeComplete, this, [ = ]() + connect( exportTask, &QgsGeoPackageRasterWriterTask::writeComplete, this, [ = ]() { // this is gross - TODO - find a way to get access to messageBar from data items QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) ); @@ -289,7 +295,7 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct } ); // when an error occurs: - connect( exportTask.get(), &QgsGeoPackageRasterWriterTask::errorOccurred, this, [ = ]( QgsGeoPackageRasterWriter::WriterError error, const QString & errorMessage ) + connect( exportTask, &QgsGeoPackageRasterWriterTask::errorOccurred, this, [ = ]( QgsGeoPackageRasterWriter::WriterError error, const QString & errorMessage ) { if ( error != QgsGeoPackageRasterWriter::WriterError::ErrUserCanceled ) { @@ -304,7 +310,6 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct deleteGeoPackageRasterLayer( QStringLiteral( "GPKG:%1:%2" ).arg( mPath, dropUri.name ), deleteErr ); } ); - QgsApplication::taskManager()->addTask( exportTask.release() ); } } // do not overwrite } @@ -323,6 +328,10 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText ); output->showMessage(); } + else if ( ! importTasks.isEmpty() ) + { + QgsApplication::taskManager()->addTask( mainTask.release() ); + } return true; } diff --git a/src/providers/ogr/qgsgeopackagedataitems.h b/src/providers/ogr/qgsgeopackagedataitems.h index 83f04c8f2da..da219e4691b 100644 --- a/src/providers/ogr/qgsgeopackagedataitems.h +++ b/src/providers/ogr/qgsgeopackagedataitems.h @@ -18,6 +18,7 @@ #include "qgsdataitem.h" #include "qgsdataitemprovider.h" #include "qgsdataprovider.h" +#include "qgstaskmanager.h" /** @@ -128,5 +129,24 @@ class QgsGeoPackageDataItemProvider : public QgsDataItemProvider }; +class QgsGeoPackageImportTask : public QgsTask +{ + Q_OBJECT + + public: + + QgsGeoPackageImportTask( const QString &desc = QString() ) : QgsTask( desc ) {} + + void emitProgressChanged( double progress ) { setProgress( progress ); } + + + protected: + + bool run() override + { + return true; + } + +}; #endif // QGSGEOPACKAGEDATAITEMS_H