Skip to content
Permalink
Browse files

[FEATURE] Drag'n'drop layers from layer tree view to browser dock

Makes it easy to e.g. store your temporary layers in PostGIS
  • Loading branch information
wonder-sk committed Aug 22, 2016
1 parent b101510 commit 26dd13063e801bf462d36f30c1129076ba2d2e8e
@@ -40,4 +40,10 @@ class QgsMimeDataUtils

static UriList decodeUriList( const QMimeData* data );

/**
* Returns encoded URI list from a list of layer tree nodes.
* @note added in QGIS 3.0
*/
static QByteArray layerTreeNodesToUriList( const QList<QgsLayerTreeNode*>& nodes );

};
@@ -1273,7 +1273,9 @@ void QgisApp::dragEnterEvent( QDragEnterEvent *event )
{
if ( event->mimeData()->hasUrls() || event->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
{
event->acceptProposedAction();
// the mime data are coming from layer tree, so ignore that, do not import those layers again
if ( !event->mimeData()->hasFormat( "application/qgis.layertreemodeldata" ) )
event->acceptProposedAction();
}
}

@@ -767,6 +767,12 @@ QgsDockBrowserTreeView::QgsDockBrowserTreeView( QWidget* parent ) : QgsBrowserTr

void QgsDockBrowserTreeView::dragEnterEvent( QDragEnterEvent* e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( "application/qgis.layertreemodeldata" ) &&
e->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
e->setDropAction( Qt::CopyAction );

// accept drag enter so that our widget will not get ignored
// and drag events will not get passed to QgisApp
e->accept();
@@ -782,6 +788,12 @@ void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent* e )
return;
}*/

// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( "application/qgis.layertreemodeldata" ) &&
e->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
e->setDropAction( Qt::CopyAction );

QTreeView::dragMoveEvent( e );

if ( !e->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
@@ -791,6 +803,17 @@ void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent* e )
}
}

void QgsDockBrowserTreeView::dropEvent( QDropEvent *e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( "application/qgis.layertreemodeldata" ) &&
e->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
e->setDropAction( Qt::CopyAction );

QTreeView::dropEvent( e );
}


//
// QgsBrowserTreeFilterProxyModel
@@ -173,6 +173,7 @@ class QgsDockBrowserTreeView : public QgsBrowserTreeView

void dragEnterEvent( QDragEnterEvent* e ) override;
void dragMoveEvent( QDragMoveEvent* e ) override;
void dropEvent( QDropEvent* e ) override;
};

/**
@@ -1011,6 +1011,9 @@ QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
QString txt = doc.toString();

mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );

mimeData->setData( "application/x-vnd.qgis.qgis.uri", QgsMimeDataUtils::layerTreeNodesToUriList( nodesFinal ) );

return mimeData;
}

@@ -17,7 +17,13 @@
#include "qgsmimedatautils.h"

#include "qgsdataitem.h"
#include "qgslayertree.h"
#include "qgslogger.h"
#include "qgspluginlayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

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

@@ -70,15 +76,8 @@ bool QgsMimeDataUtils::isUriList( const QMimeData* data )
QMimeData* QgsMimeDataUtils::encodeUriList( const QgsMimeDataUtils::UriList& layers )
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;

QDataStream stream( &encodedData, QIODevice::WriteOnly );
Q_FOREACH ( const Uri& u, layers )
{
stream << u.data();
}

mimeData->setData( QGIS_URILIST_MIMETYPE, encodedData );
mimeData->setData( QGIS_URILIST_MIMETYPE, uriListToByteArray( layers ) );
return mimeData;
}

@@ -98,6 +97,52 @@ QgsMimeDataUtils::UriList QgsMimeDataUtils::decodeUriList( const QMimeData* data
return list;
}


static void _addLayerTreeNodeToUriList( QgsLayerTreeNode* node, QgsMimeDataUtils::UriList& uris )
{
if ( QgsLayerTree::isGroup( node ) )
{
Q_FOREACH ( QgsLayerTreeNode* child, QgsLayerTree::toGroup( node )->children() )
_addLayerTreeNodeToUriList( child, uris );
}
else if ( QgsLayerTree::isLayer( node ) )
{
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
if ( !nodeLayer->layer() )
return;

QgsMimeDataUtils::Uri uri;
if ( QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() ) )
{
uri.layerType = "vector";
uri.name = vlayer->name();
uri.providerKey = vlayer->dataProvider()->name();
uri.uri = vlayer->dataProvider()->dataSourceUri();
}
else if ( QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer*>( nodeLayer->layer() ) )
{
uri.layerType = "raster";
uri.name = rlayer->name();
uri.providerKey = rlayer->dataProvider()->name();
uri.uri = rlayer->dataProvider()->dataSourceUri();
}
else
{
// plugin layers do not have a standard way of storing their URI...
return;
}
uris << uri;
}
}

QByteArray QgsMimeDataUtils::layerTreeNodesToUriList( const QList<QgsLayerTreeNode *>& nodes )
{
UriList uris;
Q_FOREACH ( QgsLayerTreeNode* node, nodes )
_addLayerTreeNodeToUriList( node, uris );
return uriListToByteArray( uris );
}

QString QgsMimeDataUtils::encode( const QStringList& items )
{
QString encoded;
@@ -141,3 +186,15 @@ QStringList QgsMimeDataUtils::decode( const QString& encoded )
return items;
}


QByteArray QgsMimeDataUtils::uriListToByteArray( const QgsMimeDataUtils::UriList& layers )
{
QByteArray encodedData;

QDataStream stream( &encodedData, QIODevice::WriteOnly );
Q_FOREACH ( const Uri& u, layers )
{
stream << u.data();
}
return encodedData;
}
@@ -19,6 +19,7 @@
#include <QStringList>

class QgsLayerItem;
class QgsLayerTreeNode;

/** \ingroup core
* \class QgsMimeDataUtils
@@ -62,9 +63,16 @@ class CORE_EXPORT QgsMimeDataUtils

static UriList decodeUriList( const QMimeData* data );

/**
* Returns encoded URI list from a list of layer tree nodes.
* @note added in QGIS 3.0
*/
static QByteArray layerTreeNodesToUriList( const QList<QgsLayerTreeNode*>& nodes );

private:
static QString encode( const QStringList& items );
static QStringList decode( const QString& encoded );
static QByteArray uriListToByteArray( const UriList& layers );

};

2 comments on commit 26dd130

@3nids

This comment has been minimized.

Copy link
Member

@3nids 3nids replied Aug 22, 2016

Or shape to Postgis with a simple drag'n'drop....so cool, thanks!

@gioman

This comment has been minimized.

Copy link
Contributor

@gioman gioman replied Aug 22, 2016

@3nids that was already possible from within the browser, but doing it from the layer tree gave users much more flexibility. Very cool indeed!

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