Navigation Menu

Skip to content

Commit

Permalink
[needs-docs] Allow dragging project layers from legend over map layer…
Browse files Browse the repository at this point in the history
… comboboxes to select

Greatly assists with usability of the combobox with large projects,
especially those with multiple copies of layers with the same name...
  • Loading branch information
nyalldawson committed Jun 12, 2019
1 parent d56ddc2 commit cf63a7a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
11 changes: 11 additions & 0 deletions python/gui/auto_generated/qgsmaplayercombobox.sip.in
Expand Up @@ -154,6 +154,17 @@ setLayer set the current layer selected in the combo
Emitted whenever the currently selected layer changes.
%End

protected:

virtual void dragEnterEvent( QDragEnterEvent *event );

virtual void dragLeaveEvent( QDragLeaveEvent *event );

virtual void dropEvent( QDropEvent *event );

virtual void paintEvent( QPaintEvent *e );


protected slots:
void indexChanged( int i );
void rowsChanged();
Expand Down
77 changes: 76 additions & 1 deletion src/gui/qgsmaplayercombobox.cpp
Expand Up @@ -15,7 +15,9 @@

#include "qgsmaplayercombobox.h"
#include "qgsmaplayermodel.h"

#include "qgsmimedatautils.h"
#include <QDragEnterEvent>
#include <QPainter>

QgsMapLayerComboBox::QgsMapLayerComboBox( QWidget *parent )
: QComboBox( parent )
Expand All @@ -26,6 +28,8 @@ QgsMapLayerComboBox::QgsMapLayerComboBox( QWidget *parent )
connect( this, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::activated ), this, &QgsMapLayerComboBox::indexChanged );
connect( mProxyModel, &QAbstractItemModel::rowsInserted, this, &QgsMapLayerComboBox::rowsChanged );
connect( mProxyModel, &QAbstractItemModel::rowsRemoved, this, &QgsMapLayerComboBox::rowsChanged );

setAcceptDrops( true );
}

void QgsMapLayerComboBox::setExcludedProviders( const QStringList &providers )
Expand Down Expand Up @@ -138,3 +142,74 @@ void QgsMapLayerComboBox::rowsChanged()
}
}

QgsMapLayer *QgsMapLayerComboBox::compatibleMapLayerFromMimeData( const QMimeData *data ) const
{
const QgsMimeDataUtils::UriList uriList = QgsMimeDataUtils::decodeUriList( data );
for ( const QgsMimeDataUtils::Uri &u : uriList )
{
// is this uri from the current project?
if ( QgsMapLayer *layer = u.mapLayer() )
{
if ( mProxyModel->acceptsLayer( layer ) )
return layer;
}
}
return nullptr;
}

void QgsMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
{
if ( !( event->possibleActions() & Qt::CopyAction ) )
return;

if ( compatibleMapLayerFromMimeData( event->mimeData() ) )
{
// dragged an acceptable layer, phew
event->setDropAction( Qt::CopyAction );
event->accept();
mDragActive = true;
update();
}
}

void QgsMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
{
QComboBox::dragLeaveEvent( event );
if ( mDragActive )
{
event->accept();
mDragActive = false;
update();
}
}

void QgsMapLayerComboBox::dropEvent( QDropEvent *event )
{
if ( !( event->possibleActions() & Qt::CopyAction ) )
return;

if ( QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData() ) )
{
// dropped an acceptable layer, phew
setFocus( Qt::MouseFocusReason );
event->setDropAction( Qt::CopyAction );
event->accept();

setLayer( layer );
}
mDragActive = false;
update();
}

void QgsMapLayerComboBox::paintEvent( QPaintEvent *e )
{
QComboBox::paintEvent( e );
if ( mDragActive )
{
QPainter p( this );
int width = 2; // width of highlight rectangle inside frame
p.setPen( QPen( palette().highlight(), width ) );
QRect r = rect().adjusted( width, width, -width, -width );
p.drawRect( r );
}
}
14 changes: 14 additions & 0 deletions src/gui/qgsmaplayercombobox.h
Expand Up @@ -139,12 +139,26 @@ class GUI_EXPORT QgsMapLayerComboBox : public QComboBox
//! Emitted whenever the currently selected layer changes.
void layerChanged( QgsMapLayer *layer );

protected:

void dragEnterEvent( QDragEnterEvent *event ) override;
void dragLeaveEvent( QDragLeaveEvent *event ) override;
void dropEvent( QDropEvent *event ) override;
void paintEvent( QPaintEvent *e ) override;

protected slots:
void indexChanged( int i );
void rowsChanged();

private:
QgsMapLayerProxyModel *mProxyModel = nullptr;
bool mDragActive = false;

/**
* Returns a map layer, compatible with the filters set for the combo box, from
* the specified mime \a data (if possible!).
*/
QgsMapLayer *compatibleMapLayerFromMimeData( const QMimeData *data ) const;
};

#endif // QGSMAPLAYERCOMBOBOX_H

0 comments on commit cf63a7a

Please sign in to comment.