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

Makes it easy to e.g. store your temporary layers in PostGIS
This commit is contained in:
Martin Dobias 2016-08-21 13:24:07 +02:00
parent b101510c84
commit 26dd13063e
7 changed files with 109 additions and 9 deletions

View File

@ -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 );
};

View File

@ -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();
}
}

View File

@ -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

View File

@ -173,6 +173,7 @@ class QgsDockBrowserTreeView : public QgsBrowserTreeView
void dragEnterEvent( QDragEnterEvent* e ) override;
void dragMoveEvent( QDragMoveEvent* e ) override;
void dropEvent( QDropEvent* e ) override;
};
/**

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 );
};