Skip to content

Commit fb6f181

Browse files
committed
support copy vector layer to browser postgres/spatialite by drag and drop
1 parent c1d4862 commit fb6f181

8 files changed

+81
-18
lines changed

python/core/qgsmimedatautils.sip

+8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ Returns encoded representation of the object
4040
:rtype: str
4141
%End
4242

43+
QgsVectorLayer *vectorLayer( bool &owner, QString &error ) const;
44+
%Docstring
45+
Get vector layer from uri if possible, otherwise returns 0 and error is set
46+
\param owner set to true if caller becomes owner
47+
\param error set to error message if cannot get vector
48+
:rtype: QgsVectorLayer
49+
%End
50+
4351
QString layerType;
4452
%Docstring
4553
Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom"

python/core/qgsvectorlayerexporter.sip

+3-1
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,13 @@ class QgsVectorLayerExporterTask : QgsTask
149149
const QString &uri,
150150
const QString &providerKey,
151151
const QgsCoordinateReferenceSystem &destinationCrs,
152-
QMap<QString, QVariant> *options = 0 );
152+
QMap<QString, QVariant> *options = 0,
153+
bool ownsLayer = false );
153154
%Docstring
154155
Constructor for QgsVectorLayerExporterTask. Takes a source ``layer``, destination ``uri``
155156
and ``providerKey``, and various export related parameters such as destination CRS
156157
and export ``options``.
158+
\param ownsLayer take ownership of layer and deletes it after export
157159
%End
158160

159161
static QgsVectorLayerExporterTask *withLayerOwnership( QgsVectorLayer *layer /Transfer/,

src/core/qgsmimedatautils.cpp

+42-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

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

30-
3130
QgsMimeDataUtils::Uri::Uri()
3231
{
3332
}
@@ -66,6 +65,41 @@ QString QgsMimeDataUtils::Uri::data() const
6665
return encode( QStringList() << layerType << providerKey << name << uri << encode( supportedCrs ) << encode( supportedFormats ) );
6766
}
6867

68+
QgsVectorLayer *QgsMimeDataUtils::Uri::vectorLayer( bool &owner, QString &error ) const
69+
{
70+
owner = false;
71+
if ( layerType != QLatin1String( "vector" ) )
72+
{
73+
error = QObject::tr( "%1: Not a vector layer." ).arg( name );
74+
return nullptr;
75+
}
76+
if ( providerKey == QLatin1String( "memory" ) )
77+
{
78+
QUrl url = QUrl::fromEncoded( uri.toUtf8() );
79+
if ( !url.hasQueryItem( QStringLiteral( "pid" ) ) || !url.hasQueryItem( QStringLiteral( "layerid" ) ) )
80+
{
81+
error = QObject::tr( "Memory layer uri does not contain process or layer id." );
82+
return nullptr;
83+
}
84+
qint64 pid = url.queryItemValue( QStringLiteral( "pid" ) ).toLongLong();
85+
if ( pid != QCoreApplication::applicationPid() )
86+
{
87+
error = QObject::tr( "Memory layer from another QGIS instance." );
88+
return nullptr;
89+
}
90+
QString layerId = url.queryItemValue( QStringLiteral( "layerid" ) );
91+
QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) );
92+
if ( !vectorLayer )
93+
{
94+
error = QObject::tr( "Cannot get memory layer." );
95+
return nullptr;
96+
}
97+
return vectorLayer;
98+
}
99+
owner = true;
100+
return new QgsVectorLayer( uri, name, providerKey );
101+
}
102+
69103
// -----
70104

71105
bool QgsMimeDataUtils::isUriList( const QMimeData *data )
@@ -119,6 +153,13 @@ static void _addLayerTreeNodeToUriList( QgsLayerTreeNode *node, QgsMimeDataUtils
119153
if ( layer->type() == QgsMapLayer::VectorLayer )
120154
{
121155
uri.layerType = QStringLiteral( "vector" );
156+
if ( uri.providerKey == QStringLiteral( "memory" ) )
157+
{
158+
QUrl url = QUrl::fromEncoded( uri.uri.toUtf8() );
159+
url.addQueryItem( QStringLiteral( "pid" ), QString::number( QCoreApplication::applicationPid() ) );
160+
url.addQueryItem( QStringLiteral( "layerid" ), layer->id() );
161+
uri.uri = QString( url.toEncoded() );
162+
}
122163
}
123164
else if ( layer->type() == QgsMapLayer::RasterLayer )
124165
{

src/core/qgsmimedatautils.h

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
class QgsLayerItem;
2424
class QgsLayerTreeNode;
25+
class QgsVectorLayer;
2526

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

48+
/** Get vector layer from uri if possible, otherwise returns 0 and error is set
49+
* \param owner set to true if caller becomes owner
50+
* \param error set to error message if cannot get vector
51+
*/
52+
QgsVectorLayer *vectorLayer( bool &owner, QString &error ) const;
53+
4754
//! Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom"
4855
QString layerType;
4956
//! For "vector" / "raster" type: provider id.

src/core/qgsvectorlayerexporter.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,10 @@ QgsVectorLayerExporter::exportLayer( QgsVectorLayer *layer,
456456
// QgsVectorLayerExporterTask
457457
//
458458

459-
QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, QMap<QString, QVariant> *options )
459+
QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, QMap<QString, QVariant> *options, bool ownsLayer )
460460
: QgsTask( tr( "Exporting %1" ).arg( layer->name() ), QgsTask::CanCancel )
461461
, mLayer( layer )
462+
, mOwnsLayer( ownsLayer )
462463
, mDestUri( uri )
463464
, mDestProviderKey( providerKey )
464465
, mDestCrs( destinationCrs )

src/core/qgsvectorlayerexporter.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,14 @@ class CORE_EXPORT QgsVectorLayerExporterTask : public QgsTask
189189
* Constructor for QgsVectorLayerExporterTask. Takes a source \a layer, destination \a uri
190190
* and \a providerKey, and various export related parameters such as destination CRS
191191
* and export \a options.
192+
* \param ownsLayer take ownership of layer and deletes it after export
192193
*/
193194
QgsVectorLayerExporterTask( QgsVectorLayer *layer,
194195
const QString &uri,
195196
const QString &providerKey,
196197
const QgsCoordinateReferenceSystem &destinationCrs,
197-
QMap<QString, QVariant> *options = nullptr );
198+
QMap<QString, QVariant> *options = nullptr,
199+
bool ownsLayer = false );
198200

199201
/**
200202
* Creates a new QgsVectorLayerExporterTask which has ownership over a source \a layer.

src/providers/postgres/qgspostgresdataitems.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,17 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData *data, const QString &toSc
201201
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
202202
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
203203
{
204-
if ( u.layerType != QLatin1String( "vector" ) )
204+
// open the source layer
205+
bool owner;
206+
QString error;
207+
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
208+
if ( !srcLayer )
205209
{
206-
importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
207-
hasError = true; // only vectors can be imported
210+
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
211+
hasError = true;
208212
continue;
209213
}
210214

211-
// open the source layer
212-
QgsVectorLayer *srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );
213-
214215
if ( srcLayer->isValid() )
215216
{
216217
uri.setDataSource( QString(), u.name, srcLayer->geometryType() != QgsWkbTypes::NullGeometry ? QStringLiteral( "geom" ) : QString() );
@@ -221,7 +222,7 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData *data, const QString &toSc
221222
uri.setSchema( toSchema );
222223
}
223224

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

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

src/providers/spatialite/qgsspatialitedataitems.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -205,22 +205,23 @@ bool QgsSLConnectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
205205
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
206206
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
207207
{
208-
if ( u.layerType != QLatin1String( "vector" ) )
208+
// open the source layer
209+
bool owner;
210+
QString error;
211+
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
212+
if ( !srcLayer )
209213
{
210-
importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
211-
hasError = true; // only vectors can be imported
214+
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
215+
hasError = true;
212216
continue;
213217
}
214218

215-
// open the source layer
216-
QgsVectorLayer *srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );
217-
218219
if ( srcLayer->isValid() )
219220
{
220221
destUri.setDataSource( QString(), u.name, srcLayer->geometryType() != QgsWkbTypes::NullGeometry ? QStringLiteral( "geom" ) : QString() );
221222
QgsDebugMsg( "URI " + destUri.uri() );
222223

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

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

0 commit comments

Comments
 (0)