Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
support copy vector layer to browser postgres/spatialite by drag and …
…drop
  • Loading branch information
blazek committed Jun 21, 2017
1 parent c1d4862 commit fb6f181
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 18 deletions.
8 changes: 8 additions & 0 deletions python/core/qgsmimedatautils.sip
Expand Up @@ -40,6 +40,14 @@ Returns encoded representation of the object
:rtype: str
%End

QgsVectorLayer *vectorLayer( bool &owner, QString &error ) const;
%Docstring
Get vector layer from uri if possible, otherwise returns 0 and error is set
\param owner set to true if caller becomes owner
\param error set to error message if cannot get vector
:rtype: QgsVectorLayer
%End

QString layerType;
%Docstring
Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom"
Expand Down
4 changes: 3 additions & 1 deletion python/core/qgsvectorlayerexporter.sip
Expand Up @@ -149,11 +149,13 @@ class QgsVectorLayerExporterTask : QgsTask
const QString &uri,
const QString &providerKey,
const QgsCoordinateReferenceSystem &destinationCrs,
QMap<QString, QVariant> *options = 0 );
QMap<QString, QVariant> *options = 0,
bool ownsLayer = false );
%Docstring
Constructor for QgsVectorLayerExporterTask. Takes a source ``layer``, destination ``uri``
and ``providerKey``, and various export related parameters such as destination CRS
and export ``options``.
\param ownsLayer take ownership of layer and deletes it after export
%End

static QgsVectorLayerExporterTask *withLayerOwnership( QgsVectorLayer *layer /Transfer/,
Expand Down
43 changes: 42 additions & 1 deletion src/core/qgsmimedatautils.cpp
Expand Up @@ -27,7 +27,6 @@

static const char *QGIS_URILIST_MIMETYPE = "application/x-vnd.qgis.qgis.uri";


QgsMimeDataUtils::Uri::Uri()
{
}
Expand Down Expand Up @@ -66,6 +65,41 @@ QString QgsMimeDataUtils::Uri::data() const
return encode( QStringList() << layerType << providerKey << name << uri << encode( supportedCrs ) << encode( supportedFormats ) );
}

QgsVectorLayer *QgsMimeDataUtils::Uri::vectorLayer( bool &owner, QString &error ) const
{
owner = false;
if ( layerType != QLatin1String( "vector" ) )
{
error = QObject::tr( "%1: Not a vector layer." ).arg( name );
return nullptr;
}
if ( providerKey == QLatin1String( "memory" ) )
{
QUrl url = QUrl::fromEncoded( uri.toUtf8() );
if ( !url.hasQueryItem( QStringLiteral( "pid" ) ) || !url.hasQueryItem( QStringLiteral( "layerid" ) ) )
{
error = QObject::tr( "Memory layer uri does not contain process or layer id." );
return nullptr;
}
qint64 pid = url.queryItemValue( QStringLiteral( "pid" ) ).toLongLong();
if ( pid != QCoreApplication::applicationPid() )
{
error = QObject::tr( "Memory layer from another QGIS instance." );
return nullptr;
}
QString layerId = url.queryItemValue( QStringLiteral( "layerid" ) );
QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) );
if ( !vectorLayer )
{
error = QObject::tr( "Cannot get memory layer." );
return nullptr;
}
return vectorLayer;
}
owner = true;
return new QgsVectorLayer( uri, name, providerKey );
}

// -----

bool QgsMimeDataUtils::isUriList( const QMimeData *data )
Expand Down Expand Up @@ -119,6 +153,13 @@ static void _addLayerTreeNodeToUriList( QgsLayerTreeNode *node, QgsMimeDataUtils
if ( layer->type() == QgsMapLayer::VectorLayer )
{
uri.layerType = QStringLiteral( "vector" );
if ( uri.providerKey == QStringLiteral( "memory" ) )
{
QUrl url = QUrl::fromEncoded( uri.uri.toUtf8() );
url.addQueryItem( QStringLiteral( "pid" ), QString::number( QCoreApplication::applicationPid() ) );
url.addQueryItem( QStringLiteral( "layerid" ), layer->id() );
uri.uri = QString( url.toEncoded() );
}
}
else if ( layer->type() == QgsMapLayer::RasterLayer )
{
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsmimedatautils.h
Expand Up @@ -22,6 +22,7 @@

class QgsLayerItem;
class QgsLayerTreeNode;
class QgsVectorLayer;

/** \ingroup core
* \class QgsMimeDataUtils
Expand All @@ -44,6 +45,12 @@ class CORE_EXPORT QgsMimeDataUtils
//! Returns encoded representation of the object
QString data() const;

/** Get vector layer from uri if possible, otherwise returns 0 and error is set
* \param owner set to true if caller becomes owner
* \param error set to error message if cannot get vector
*/
QgsVectorLayer *vectorLayer( bool &owner, QString &error ) const;

//! Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom"
QString layerType;
//! For "vector" / "raster" type: provider id.
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayerexporter.cpp
Expand Up @@ -456,9 +456,10 @@ QgsVectorLayerExporter::exportLayer( QgsVectorLayer *layer,
// QgsVectorLayerExporterTask
//

QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, QMap<QString, QVariant> *options )
QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, QMap<QString, QVariant> *options, bool ownsLayer )
: QgsTask( tr( "Exporting %1" ).arg( layer->name() ), QgsTask::CanCancel )
, mLayer( layer )
, mOwnsLayer( ownsLayer )
, mDestUri( uri )
, mDestProviderKey( providerKey )
, mDestCrs( destinationCrs )
Expand Down
4 changes: 3 additions & 1 deletion src/core/qgsvectorlayerexporter.h
Expand Up @@ -189,12 +189,14 @@ class CORE_EXPORT QgsVectorLayerExporterTask : public QgsTask
* Constructor for QgsVectorLayerExporterTask. Takes a source \a layer, destination \a uri
* and \a providerKey, and various export related parameters such as destination CRS
* and export \a options.
* \param ownsLayer take ownership of layer and deletes it after export
*/
QgsVectorLayerExporterTask( QgsVectorLayer *layer,
const QString &uri,
const QString &providerKey,
const QgsCoordinateReferenceSystem &destinationCrs,
QMap<QString, QVariant> *options = nullptr );
QMap<QString, QVariant> *options = nullptr,
bool ownsLayer = false );

/**
* Creates a new QgsVectorLayerExporterTask which has ownership over a source \a layer.
Expand Down
15 changes: 8 additions & 7 deletions src/providers/postgres/qgspostgresdataitems.cpp
Expand Up @@ -201,16 +201,17 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData *data, const QString &toSc
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
{
if ( u.layerType != QLatin1String( "vector" ) )
// open the source layer
bool owner;
QString error;
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
if ( !srcLayer )
{
importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
hasError = true; // only vectors can be imported
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
hasError = true;
continue;
}

// open the source layer
QgsVectorLayer *srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );

if ( srcLayer->isValid() )
{
uri.setDataSource( QString(), u.name, srcLayer->geometryType() != QgsWkbTypes::NullGeometry ? QStringLiteral( "geom" ) : QString() );
Expand All @@ -221,7 +222,7 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData *data, const QString &toSc
uri.setSchema( toSchema );
}

std::unique_ptr< QgsVectorLayerExporterTask > exportTask( QgsVectorLayerExporterTask::withLayerOwnership( srcLayer, uri.uri( false ), QStringLiteral( "postgres" ), srcLayer->crs() ) );
std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( srcLayer, uri.uri( false ), QStringLiteral( "postgres" ), srcLayer->crs(), nullptr, owner ) );

// when export is successful:
connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]()
Expand Down
15 changes: 8 additions & 7 deletions src/providers/spatialite/qgsspatialitedataitems.cpp
Expand Up @@ -205,22 +205,23 @@ bool QgsSLConnectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
{
if ( u.layerType != QLatin1String( "vector" ) )
// open the source layer
bool owner;
QString error;
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
if ( !srcLayer )
{
importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
hasError = true; // only vectors can be imported
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
hasError = true;
continue;
}

// open the source layer
QgsVectorLayer *srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );

if ( srcLayer->isValid() )
{
destUri.setDataSource( QString(), u.name, srcLayer->geometryType() != QgsWkbTypes::NullGeometry ? QStringLiteral( "geom" ) : QString() );
QgsDebugMsg( "URI " + destUri.uri() );

std::unique_ptr< QgsVectorLayerExporterTask > exportTask( QgsVectorLayerExporterTask::withLayerOwnership( srcLayer, destUri.uri(), QStringLiteral( "spatialite" ), srcLayer->crs() ) );
std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( srcLayer, destUri.uri(), QStringLiteral( "spatialite" ), srcLayer->crs(), nullptr, owner ) );

// when export is successful:
connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]()
Expand Down

0 comments on commit fb6f181

Please sign in to comment.