Skip to content

Commit e6814bc

Browse files
committed
[feature] Geopackage handle drops in the browser
It is now possible to drag and drop from any vector layer onto a gpkg node layer and import a layer. Overwrites are protected by a confirmation dialog.
1 parent 0be0a4e commit e6814bc

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

src/providers/ogr/qgsgeopackagedataitems.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "qgsvectorlayer.h"
2222
#include "qgsrasterlayer.h"
2323
#include "qgsnewgeopackagelayerdialog.h"
24+
#include "qgsmessageoutput.h"
25+
#include "qgsvectorlayerexporter.h"
2426

2527
#include <QAction>
2628
#include <QMessageBox>
@@ -268,6 +270,115 @@ QList<QAction *> QgsGeoPackageConnectionItem::actions()
268270
}
269271
#endif
270272

273+
274+
275+
bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
276+
{
277+
278+
if ( !QgsMimeDataUtils::isUriList( data ) )
279+
return false;
280+
281+
// TODO: probably should show a GUI with settings etc
282+
QString uri;
283+
284+
QStringList importResults;
285+
bool hasError = false;
286+
287+
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
288+
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
289+
{
290+
if ( u.layerType == QStringLiteral( "vector" ) )
291+
{
292+
// open the source layer
293+
bool owner;
294+
QString error;
295+
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
296+
if ( !srcLayer )
297+
{
298+
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
299+
hasError = true;
300+
continue;
301+
}
302+
303+
if ( srcLayer->isValid() )
304+
{
305+
uri = mPath;
306+
QgsDebugMsgLevel( "URI " + uri, 3 );
307+
308+
// check if the destination layer already exists
309+
bool exists = false;
310+
// Q_FOREACH won't detach ...
311+
for ( const auto child : children() )
312+
{
313+
if ( child->name() == u.name )
314+
{
315+
exists = true;
316+
}
317+
}
318+
if ( ! exists || QMessageBox::question( nullptr, tr( "Overwrite Layer" ),
319+
tr( "Destination layer <b>%1</b> already exists. Do you want to overwrite it?" ).arg( u.name ), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes )
320+
{
321+
322+
std::unique_ptr< QMap<QString, QVariant> > options( new QMap<QString, QVariant> );
323+
options->insert( QStringLiteral( "driverName" ), QStringLiteral( "GPKG" ) );
324+
options->insert( QStringLiteral( "update" ), true );
325+
options->insert( QStringLiteral( "overwrite" ), true );
326+
options->insert( QStringLiteral( "layerName" ), u.name );
327+
328+
std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( srcLayer, uri, QStringLiteral( "ogr" ), srcLayer->crs(), options.get(), owner ) );
329+
330+
// when export is successful:
331+
connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]()
332+
{
333+
// this is gross - TODO - find a way to get access to messageBar from data items
334+
QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) );
335+
refreshConnections();
336+
} );
337+
338+
// when an error occurs:
339+
connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage )
340+
{
341+
if ( error != QgsVectorLayerExporter::ErrUserCanceled )
342+
{
343+
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
344+
output->setTitle( tr( "Import to GeoPackage database" ) );
345+
output->setMessage( tr( "Failed to import some layers!\n\n" ) + errorMessage, QgsMessageOutput::MessageText );
346+
output->showMessage();
347+
}
348+
} );
349+
350+
QgsApplication::taskManager()->addTask( exportTask.release() );
351+
}
352+
}
353+
else
354+
{
355+
importResults.append( tr( "%1: Not a valid layer!" ).arg( u.name ) );
356+
hasError = true;
357+
}
358+
}
359+
else
360+
{
361+
// TODO: implemnent raster import
362+
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
363+
output->setTitle( tr( "Import to GeoPackage database faile" ) );
364+
output->setMessage( tr( "Failed to import some layers!\n\n" ) + QStringLiteral( "Raster import is not yet implemented!\n" ), QgsMessageOutput::MessageText );
365+
output->showMessage();
366+
}
367+
368+
}
369+
370+
if ( hasError )
371+
{
372+
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
373+
output->setTitle( tr( "Import to GeoPackage database" ) );
374+
output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText );
375+
output->showMessage();
376+
}
377+
378+
return true;
379+
}
380+
381+
271382
QgsLayerItem::LayerType QgsGeoPackageConnectionItem::layerTypeFromDb( const QString &geometryType )
272383
{
273384
if ( geometryType.contains( QStringLiteral( "Point" ), Qt::CaseInsensitive ) )

src/providers/ogr/qgsgeopackagedataitems.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
6767
#endif
6868

6969
virtual bool acceptDrop() override { return true; }
70-
//virtual bool handleDrop( const QMimeData *data, Qt::DropAction action ) override;
70+
virtual bool handleDrop( const QMimeData *data, Qt::DropAction action ) override;
7171

7272
//! Return the layer type from \a geometryType
7373
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );

0 commit comments

Comments
 (0)