Skip to content
Permalink
Browse files

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.
  • Loading branch information
elpaso committed Sep 18, 2017
1 parent 2cf2ad2 commit 9c67560b0c07021b522c7dc69e3d943bc2c1bb67
Showing with 39 additions and 10 deletions.
  1. +19 −10 src/providers/ogr/qgsgeopackagedataitems.cpp
  2. +20 −0 src/providers/ogr/qgsgeopackagedataitems.h
@@ -28,6 +28,7 @@
#include "qgsmessageoutput.h"
#include "qgsvectorlayerexporter.h"
#include "qgsgeopackagerasterwritertask.h"
#include "qgstaskmanager.h"

#include <QAction>
#include <QMessageBox>
@@ -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,18 +257,19 @@ 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." ) );
refreshConnections();
} );

// 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,22 +280,22 @@ 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." ) );
refreshConnections();
} );

// 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;
}

@@ -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

0 comments on commit 9c67560

Please sign in to comment.
You can’t perform that action at this time.