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.
This commit is contained in:
Alessandro Pasotti 2017-09-18 17:36:26 +02:00
parent 2cf2ad25b4
commit 9c67560b0c
2 changed files with 39 additions and 10 deletions

View File

@ -28,6 +28,7 @@
#include "qgsmessageoutput.h" #include "qgsmessageoutput.h"
#include "qgsvectorlayerexporter.h" #include "qgsvectorlayerexporter.h"
#include "qgsgeopackagerasterwritertask.h" #include "qgsgeopackagerasterwritertask.h"
#include "qgstaskmanager.h"
#include <QAction> #include <QAction>
#include <QMessageBox> #include <QMessageBox>
@ -191,6 +192,10 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct
QStringList importResults; QStringList importResults;
bool hasError = false; bool hasError = false;
// Main task
std::unique_ptr< QgsGeoPackageImportTask > mainTask( new QgsGeoPackageImportTask( tr( "GeoPackage import" ) ) );
QgsTaskList importTasks;
const auto lst = QgsMimeDataUtils::decodeUriList( data ); const auto lst = QgsMimeDataUtils::decodeUriList( data );
for ( const QgsMimeDataUtils::Uri &dropUri : lst ) 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( "update" ), true );
options.insert( QStringLiteral( "overwrite" ), true ); options.insert( QStringLiteral( "overwrite" ), true );
options.insert( QStringLiteral( "layerName" ), dropUri.name ); options.insert( QStringLiteral( "layerName" ), dropUri.name );
QgsVectorLayerExporterTask *exportTask = new QgsVectorLayerExporterTask( vectorSrcLayer, uri, QStringLiteral( "ogr" ), vectorSrcLayer->crs(), options, owner ) ;
std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( vectorSrcLayer, uri, QStringLiteral( "ogr" ), vectorSrcLayer->crs(), options, owner ) ); mainTask->addSubTask( exportTask, importTasks );
importTasks << exportTask;
// when export is successful: // 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 // 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." ) ); 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: // 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 ) if ( error != QgsVectorLayerExporter::ErrUserCanceled )
{ {
@ -274,14 +280,14 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct
} }
} ); } );
QgsApplication::taskManager()->addTask( exportTask.release() );
} }
else // Import raster else // Import raster
{ {
QgsGeoPackageRasterWriterTask *exportTask = new QgsGeoPackageRasterWriterTask( dropUri, mPath ) ;
std::unique_ptr< QgsGeoPackageRasterWriterTask > exportTask( new QgsGeoPackageRasterWriterTask( dropUri, mPath ) ); mainTask->addSubTask( exportTask, importTasks );
importTasks << exportTask;
// when export is successful: // 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 // 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." ) ); 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: // 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 ) 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 ); deleteGeoPackageRasterLayer( QStringLiteral( "GPKG:%1:%2" ).arg( mPath, dropUri.name ), deleteErr );
} ); } );
QgsApplication::taskManager()->addTask( exportTask.release() );
} }
} // do not overwrite } // 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->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText );
output->showMessage(); output->showMessage();
} }
else if ( ! importTasks.isEmpty() )
{
QgsApplication::taskManager()->addTask( mainTask.release() );
}
return true; return true;
} }

View File

@ -18,6 +18,7 @@
#include "qgsdataitem.h" #include "qgsdataitem.h"
#include "qgsdataitemprovider.h" #include "qgsdataitemprovider.h"
#include "qgsdataprovider.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 #endif // QGSGEOPACKAGEDATAITEMS_H