QGIS API Documentation 4.3.0-Master (0cfde48c85b)
Loading...
Searching...
No Matches
qgsmimedatautils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmimedatautils.cpp
3 ---------------------
4 begin : November 2011
5 copyright : (C) 2011 by Martin Dobias
6 email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgsmimedatautils.h"
16
17#include "qgslayertree.h"
18#include "qgslogger.h"
19#include "qgsmaplayerfactory.h"
20#include "qgsmeshlayer.h"
21#include "qgsrasterlayer.h"
22#include "qgsvectorlayer.h"
23
24#include <QRegularExpression>
25#include <QString>
26#include <QStringList>
27
28using namespace Qt::StringLiterals;
29
30static const char *QGIS_URILIST_MIMETYPE = "application/x-vnd.qgis.qgis.uri";
31
32QgsMimeDataUtils::Uri::Uri( const QString &encData )
33{
34 QgsDebugMsgLevel( "encData: " + encData, 4 );
35 const QStringList decoded = decode( encData );
36 if ( decoded.size() < 4 )
37 return;
38
39 layerType = decoded[0];
40 providerKey = decoded[1];
41 name = decoded[2];
42 uri = decoded[3];
43
44 if ( layerType == "raster"_L1 && decoded.size() >= 6 )
45 {
46 supportedCrs = decode( decoded[4] );
47 supportedFormats = decode( decoded[5] );
48 }
49 else
50 {
51 supportedCrs.clear();
52 supportedFormats.clear();
53 }
54
55 if ( decoded.size() > 6 )
56 layerId = decoded.at( 6 );
57 if ( decoded.size() > 7 )
58 pId = decoded.at( 7 );
59 if ( decoded.size() > 8 )
60 wkbType = QgsWkbTypes::parseType( decoded.at( 8 ) );
61 if ( decoded.size() > 9 )
62 filePath = decoded.at( 9 );
63
64 QgsDebugMsgLevel( u"type:%1 key:%2 name:%3 uri:%4 supportedCRS:%5 supportedFormats:%6"_s.arg( layerType, providerKey, name, uri, supportedCrs.join( ',' ), supportedFormats.join( ',' ) ), 2 );
65}
66
68 : providerKey( layer->providerType() )
69 , name( layer->name() )
70 , uri( layer->dataProvider() ? layer->dataProvider()->dataSourceUri() : layer->source() )
71 , layerId( layer->id() )
72 , pId( QString::number( QCoreApplication::applicationPid() ) )
73{
75 switch ( layer->type() )
76 {
78 {
79 wkbType = qobject_cast< QgsVectorLayer *>( layer )->wkbType();
80 break;
81 }
87 {
88 break;
89 }
90
94 {
95 // plugin layers do not have a standard way of storing their URI...
96 return;
97 }
98 }
99}
100
102{
104}
105
106QgsVectorLayer *QgsMimeDataUtils::Uri::vectorLayer( bool &owner, QString &error ) const
107{
108 return vectorLayer( owner, error, QgsProject::instance() ); // skip-keyword-check
109}
110
111QgsVectorLayer *QgsMimeDataUtils::Uri::vectorLayer( bool &owner, QString &error, QgsProject *project ) const
112{
113 owner = false;
114 error.clear();
115 if ( layerType != "vector"_L1 )
116 {
117 error = QObject::tr( "%1: Not a vector layer." ).arg( name );
118 return nullptr;
119 }
120
122 {
124 {
125 return vectorLayer;
126 }
127 }
128 if ( providerKey == "memory"_L1 )
129 {
130 error = QObject::tr( "Cannot get memory layer." );
131 return nullptr;
132 }
133
134 owner = true;
135 const QgsVectorLayer::LayerOptions options { project->transformContext() };
136 return new QgsVectorLayer( uri, name, providerKey, options );
137}
138
139QgsRasterLayer *QgsMimeDataUtils::Uri::rasterLayer( bool &owner, QString &error ) const
140{
141 return rasterLayer( owner, error, QgsProject::instance() ); // skip-keyword-check
142}
143
144QgsRasterLayer *QgsMimeDataUtils::Uri::rasterLayer( bool &owner, QString &error, QgsProject *project ) const
145{
146 owner = false;
147 error.clear();
148 if ( layerType != "raster"_L1 )
149 {
150 error = QObject::tr( "%1: Not a raster layer." ).arg( name );
151 return nullptr;
152 }
153
155 {
157 {
158 return rasterLayer;
159 }
160 }
161
162 owner = true;
163 return new QgsRasterLayer( uri, name, providerKey );
164}
165
166QgsMeshLayer *QgsMimeDataUtils::Uri::meshLayer( bool &owner, QString &error ) const
167{
168 return meshLayer( owner, error, QgsProject::instance() ); // skip-keyword-check
169}
170
171QgsMeshLayer *QgsMimeDataUtils::Uri::meshLayer( bool &owner, QString &error, QgsProject *project ) const
172{
173 owner = false;
174 error.clear();
175 if ( layerType != "mesh"_L1 )
176 {
177 error = QObject::tr( "%1: Not a mesh layer." ).arg( name );
178 return nullptr;
179 }
180
182 {
183 if ( QgsMeshLayer *meshLayer = project->mapLayer<QgsMeshLayer *>( layerId ) )
184 {
185 return meshLayer;
186 }
187 }
188
189 owner = true;
190 return new QgsMeshLayer( uri, name, providerKey );
191}
192
194{
195 return mapLayer( QgsProject::instance() ); // skip-keyword-check
196}
197
199{
201 {
202 return project->mapLayer( layerId );
203 }
204 return nullptr;
205}
206
207// -----
208
209bool QgsMimeDataUtils::isUriList( const QMimeData *data )
210{
211 return data->hasFormat( QGIS_URILIST_MIMETYPE );
212}
213
215{
216 QMimeData *mimeData = new QMimeData();
217
218 mimeData->setData( QGIS_URILIST_MIMETYPE, uriListToByteArray( layers ) );
219 return mimeData;
220}
221
222
224{
225 QByteArray encodedData = data->data( QGIS_URILIST_MIMETYPE );
226 QDataStream stream( &encodedData, QIODevice::ReadOnly );
227 QString xUri; // extended uri: layer_type:provider_key:uri
228 UriList list;
229 while ( !stream.atEnd() )
230 {
231 stream >> xUri;
232 QgsDebugMsgLevel( xUri, 4 );
233 list.append( Uri( xUri ) );
234 }
235 return list;
236}
237
238
239static void _addLayerTreeNodeToUriList( QgsLayerTreeNode *node, QgsMimeDataUtils::UriList &uris )
240{
241 if ( QgsLayerTree::isGroup( node ) )
242 {
243 const auto constChildren = QgsLayerTree::toGroup( node )->children();
244 for ( QgsLayerTreeNode *child : constChildren )
245 _addLayerTreeNodeToUriList( child, uris );
246 }
247 else if ( QgsLayerTree::isLayer( node ) )
248 {
249 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
250 QgsMapLayer *layer = nodeLayer->layer();
251 if ( !layer )
252 return;
253
254 if ( layer->type() == Qgis::LayerType::Plugin )
255 return; // plugin layers do not have a standard way of storing their URI...
256
257 uris << QgsMimeDataUtils::Uri( layer );
258 }
259}
260
261QByteArray QgsMimeDataUtils::layerTreeNodesToUriList( const QList<QgsLayerTreeNode *> &nodes )
262{
263 UriList uris;
264 const auto constNodes = nodes;
265 for ( QgsLayerTreeNode *node : constNodes )
266 _addLayerTreeNodeToUriList( node, uris );
267 return uriListToByteArray( uris );
268}
269
271{
272 if ( uri.pId.isEmpty() )
273 return false;
274
275 const qint64 pid = uri.pId.toLongLong();
276 return pid == QCoreApplication::applicationPid();
277}
278
279QString QgsMimeDataUtils::encode( const QStringList &items )
280{
281 QString encoded;
282 // Do not escape colon twice
283 const thread_local QRegularExpression re( u"(?<!\\\\):"_s );
284 const auto constItems = items;
285 for ( const QString &item : constItems )
286 {
287 QString str = item;
288 str.replace( '\\', "\\\\"_L1 );
289 str.replace( re, u"\\:"_s );
290 encoded += str + ':';
291 }
292 return encoded.left( encoded.length() - 1 );
293}
294
295QStringList QgsMimeDataUtils::decode( const QString &encoded )
296{
297 QStringList items;
298 QString item;
299 bool inEscape = false;
300 const auto constEncoded = encoded;
301 for ( const QChar c : constEncoded )
302 {
303 if ( c == '\\' && inEscape )
304 {
305 item += c;
306 }
307 else if ( c == '\\' )
308 {
309 inEscape = true;
310 }
311 else if ( c == ':' && !inEscape )
312 {
313 items.append( item );
314 item.clear();
315 }
316 else
317 {
318 item += c;
319 inEscape = false;
320 }
321 }
322 items.append( item );
323 return items;
324}
325
326
327QByteArray QgsMimeDataUtils::uriListToByteArray( const QgsMimeDataUtils::UriList &layers )
328{
329 QByteArray encodedData;
330
331 QDataStream stream( &encodedData, QIODevice::WriteOnly );
332 const auto constLayers = layers;
333 for ( const Uri &u : constLayers )
334 {
335 stream << u.data();
336 }
337 return encodedData;
338}
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:215
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
QgsMapLayer * layer() const
Returns the map layer associated with this node.
Base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
static QString typeToString(Qgis::LayerType type)
Converts a map layer type to a string value.
Base class for all map layer types.
Definition qgsmaplayer.h:83
Qgis::LayerType type
Definition qgsmaplayer.h:93
Represents a mesh layer supporting display of data on structured or unstructured meshes.
static QByteArray layerTreeNodesToUriList(const QList< QgsLayerTreeNode * > &nodes)
Returns encoded URI list from a list of layer tree nodes.
static bool isUriList(const QMimeData *data)
QList< QgsMimeDataUtils::Uri > UriList
static QMimeData * encodeUriList(const UriList &layers)
Encodes a URI list to a new QMimeData object.
static UriList decodeUriList(const QMimeData *data)
static bool hasOriginatedFromCurrentAppInstance(const QgsMimeDataUtils::Uri &uri)
Returns true if uri originated from the current QGIS application instance.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:121
Represents a raster layer.
Represents a vector layer which manages a vector based dataset.
static Qgis::WkbType parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:80
Q_DECL_DEPRECATED QgsMeshLayer * meshLayer(bool &owner, QString &error) const
Gets mesh layer from uri if possible, otherwise returns nullptr and error is set.
Qgis::WkbType wkbType
WKB type, if associated with a vector layer, or QgsWkbTypes::Unknown if not yet known.
QString filePath
Path to file, if uri is associated with a file.
QString uri
Identifier of the data source recognized by its providerKey.
QString name
Human readable name to be used e.g. in layer tree.
Q_DECL_DEPRECATED QgsMapLayer * mapLayer() const
Returns the layer from the active project corresponding to this uri (if possible),...
QString pId
Unique ID associated with application instance.
Q_DECL_DEPRECATED QgsRasterLayer * rasterLayer(bool &owner, QString &error) const
Gets raster layer from uri if possible, otherwise returns nullptr and error is set.
QString providerKey
For "vector" / "raster" type: provider id.
Q_DECL_DEPRECATED QgsVectorLayer * vectorLayer(bool &owner, QString &error) const
Gets vector layer from uri if possible, otherwise returns nullptr and error is set.
QString layerId
Layer ID, if uri is associated with a layer from a QgsProject.
QString data() const
Returns encoded representation of the object.
Uri()=default
Constructs invalid URI.
QString layerType
Type of URI.
Setting options for loading vector layers.