Skip to content

Commit cf63a7a

Browse files
committedJun 12, 2019
[needs-docs] Allow dragging project layers from legend over map layer comboboxes to select
Greatly assists with usability of the combobox with large projects, especially those with multiple copies of layers with the same name...
1 parent d56ddc2 commit cf63a7a

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed
 

‎python/gui/auto_generated/qgsmaplayercombobox.sip.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ setLayer set the current layer selected in the combo
154154
Emitted whenever the currently selected layer changes.
155155
%End
156156

157+
protected:
158+
159+
virtual void dragEnterEvent( QDragEnterEvent *event );
160+
161+
virtual void dragLeaveEvent( QDragLeaveEvent *event );
162+
163+
virtual void dropEvent( QDropEvent *event );
164+
165+
virtual void paintEvent( QPaintEvent *e );
166+
167+
157168
protected slots:
158169
void indexChanged( int i );
159170
void rowsChanged();

‎src/gui/qgsmaplayercombobox.cpp

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515

1616
#include "qgsmaplayercombobox.h"
1717
#include "qgsmaplayermodel.h"
18-
18+
#include "qgsmimedatautils.h"
19+
#include <QDragEnterEvent>
20+
#include <QPainter>
1921

2022
QgsMapLayerComboBox::QgsMapLayerComboBox( QWidget *parent )
2123
: QComboBox( parent )
@@ -26,6 +28,8 @@ QgsMapLayerComboBox::QgsMapLayerComboBox( QWidget *parent )
2628
connect( this, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::activated ), this, &QgsMapLayerComboBox::indexChanged );
2729
connect( mProxyModel, &QAbstractItemModel::rowsInserted, this, &QgsMapLayerComboBox::rowsChanged );
2830
connect( mProxyModel, &QAbstractItemModel::rowsRemoved, this, &QgsMapLayerComboBox::rowsChanged );
31+
32+
setAcceptDrops( true );
2933
}
3034

3135
void QgsMapLayerComboBox::setExcludedProviders( const QStringList &providers )
@@ -138,3 +142,74 @@ void QgsMapLayerComboBox::rowsChanged()
138142
}
139143
}
140144

145+
QgsMapLayer *QgsMapLayerComboBox::compatibleMapLayerFromMimeData( const QMimeData *data ) const
146+
{
147+
const QgsMimeDataUtils::UriList uriList = QgsMimeDataUtils::decodeUriList( data );
148+
for ( const QgsMimeDataUtils::Uri &u : uriList )
149+
{
150+
// is this uri from the current project?
151+
if ( QgsMapLayer *layer = u.mapLayer() )
152+
{
153+
if ( mProxyModel->acceptsLayer( layer ) )
154+
return layer;
155+
}
156+
}
157+
return nullptr;
158+
}
159+
160+
void QgsMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
161+
{
162+
if ( !( event->possibleActions() & Qt::CopyAction ) )
163+
return;
164+
165+
if ( compatibleMapLayerFromMimeData( event->mimeData() ) )
166+
{
167+
// dragged an acceptable layer, phew
168+
event->setDropAction( Qt::CopyAction );
169+
event->accept();
170+
mDragActive = true;
171+
update();
172+
}
173+
}
174+
175+
void QgsMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
176+
{
177+
QComboBox::dragLeaveEvent( event );
178+
if ( mDragActive )
179+
{
180+
event->accept();
181+
mDragActive = false;
182+
update();
183+
}
184+
}
185+
186+
void QgsMapLayerComboBox::dropEvent( QDropEvent *event )
187+
{
188+
if ( !( event->possibleActions() & Qt::CopyAction ) )
189+
return;
190+
191+
if ( QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData() ) )
192+
{
193+
// dropped an acceptable layer, phew
194+
setFocus( Qt::MouseFocusReason );
195+
event->setDropAction( Qt::CopyAction );
196+
event->accept();
197+
198+
setLayer( layer );
199+
}
200+
mDragActive = false;
201+
update();
202+
}
203+
204+
void QgsMapLayerComboBox::paintEvent( QPaintEvent *e )
205+
{
206+
QComboBox::paintEvent( e );
207+
if ( mDragActive )
208+
{
209+
QPainter p( this );
210+
int width = 2; // width of highlight rectangle inside frame
211+
p.setPen( QPen( palette().highlight(), width ) );
212+
QRect r = rect().adjusted( width, width, -width, -width );
213+
p.drawRect( r );
214+
}
215+
}

‎src/gui/qgsmaplayercombobox.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,26 @@ class GUI_EXPORT QgsMapLayerComboBox : public QComboBox
139139
//! Emitted whenever the currently selected layer changes.
140140
void layerChanged( QgsMapLayer *layer );
141141

142+
protected:
143+
144+
void dragEnterEvent( QDragEnterEvent *event ) override;
145+
void dragLeaveEvent( QDragLeaveEvent *event ) override;
146+
void dropEvent( QDropEvent *event ) override;
147+
void paintEvent( QPaintEvent *e ) override;
148+
142149
protected slots:
143150
void indexChanged( int i );
144151
void rowsChanged();
145152

146153
private:
147154
QgsMapLayerProxyModel *mProxyModel = nullptr;
155+
bool mDragActive = false;
156+
157+
/**
158+
* Returns a map layer, compatible with the filters set for the combo box, from
159+
* the specified mime \a data (if possible!).
160+
*/
161+
QgsMapLayer *compatibleMapLayerFromMimeData( const QMimeData *data ) const;
148162
};
149163

150164
#endif // QGSMAPLAYERCOMBOBOX_H

0 commit comments

Comments
 (0)
Please sign in to comment.