Skip to content

Commit 97da8f5

Browse files
author
homann
committed
Change behaviour of legend layer reordering with the mouse. The code needs major cleanup, but the we need to settle on behaviour first.
git-svn-id: http://svn.osgeo.org/qgis/trunk@11233 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent ddba669 commit 97da8f5

File tree

2 files changed

+167
-61
lines changed

2 files changed

+167
-61
lines changed

src/app/legend/qgslegend.cpp

Lines changed: 143 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ QgsLegend::QgsLegend( QWidget * parent, const char *name )
7575
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
7676
this, SLOT( writeProject( QDomDocument & ) ) );
7777

78+
// Initialise the line indicator widget.
79+
mInsertionLine = new QWidget(viewport());
80+
hideLine();
81+
mInsertionLine->setAutoFillBackground(true);
82+
QPalette pal = mInsertionLine->palette();
83+
pal.setColor(mInsertionLine->backgroundRole(), Qt::blue);
84+
mInsertionLine->setPalette(pal);
85+
7886
setSortingEnabled( false );
7987
setDragEnabled( false );
8088
setAutoScroll( true );
@@ -91,7 +99,9 @@ QgsLegend::QgsLegend( QWidget * parent, const char *name )
9199
}
92100

93101
QgsLegend::~QgsLegend()
94-
{}
102+
{
103+
delete mInsertionLine;
104+
}
95105

96106
void QgsLegend::handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
97107
{
@@ -237,85 +247,97 @@ void QgsLegend::mouseMoveEvent( QMouseEvent * e )
237247

238248
// change the cursor appropriate to if drop is allowed
239249
QTreeWidgetItem* item = itemAt( p );
250+
251+
hideLine();
252+
240253
QgsLegendItem* origin = dynamic_cast<QgsLegendItem*>( mItemBeingMoved );
241254
QgsLegendItem* dest = dynamic_cast<QgsLegendItem*>( item );
242255

243-
if ( !item )
244-
{
245-
setCursor( QCursor( Qt::ForbiddenCursor ) );
246-
}
247-
248-
if ( item && ( item != mItemBeingMoved ) )
256+
if ( item )
249257
{
258+
mDropTarget = item;
250259
QgsLegendItem::DRAG_ACTION action = dest->accept( origin );
251-
if ( yCoordAboveCenter( dest, e->y() ) ) //over center of item
260+
if ( item != mItemBeingMoved )
252261
{
253-
if ( action == QgsLegendItem::REORDER )
262+
if ( yCoordAboveCenter( dest, e->y() ) ) //over center of item
254263
{
255-
if ( origin->nextSibling() != dest )
264+
int line_y = visualItemRect(item).top() + 1;
265+
int line_left = visualItemRect(item).left();
266+
267+
if ( action == QgsLegendItem::REORDER || action == QgsLegendItem::INSERT )
256268
{
257-
moveItem( dest, origin );setCurrentItem( origin );
269+
QgsDebugMsg( "mouseMoveEvent::INSERT or REORDER" );
270+
mDropAction = BEFORE;
271+
showLine( line_y, line_left);
272+
setCursor( QCursor( Qt::SizeVerCursor ) );
258273
}
259-
setCurrentItem( origin );
260-
setCursor( QCursor( Qt::SizeVerCursor ) );
261-
}
262-
else if ( action == QgsLegendItem::INSERT )
263-
{
264-
setCursor( QCursor( Qt::PointingHandCursor ) );
265-
if ( origin->parent() != dest )
274+
else //no action
266275
{
267-
insertItem( origin, dest );
276+
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
277+
mDropAction = NO_ACTION;
278+
setCursor( QCursor( Qt::ForbiddenCursor ) );
268279
}
269-
setCurrentItem( origin );
270-
setCursor( QCursor( Qt::PointingHandCursor ) );
271280
}
272-
else //no action
281+
else // below center of item
273282
{
274-
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
283+
int line_y = visualItemRect(item).bottom() - 2;
284+
int line_left = visualItemRect(item).left();
275285

276-
if ( origin->type() == QgsLegendItem::LEGEND_LAYER_FILE && mItemBeingMovedOrigPos != getItemPos( mItemBeingMoved ) )
286+
if ( action == QgsLegendItem::REORDER )
277287
{
278-
resetToInitialPosition( mItemBeingMoved );
288+
QgsDebugMsg( "mouseMoveEvent::REORDER bottom half" );
289+
mDropAction = AFTER;
290+
showLine( line_y, line_left);
291+
setCursor( QCursor( Qt::SizeVerCursor ) );
279292
}
280-
setCursor( QCursor( Qt::ForbiddenCursor ) );
281-
}
282-
}
283-
else // below center of item
284-
{
285-
286-
if ( action == QgsLegendItem::REORDER )
287-
{
288-
QgsDebugMsg( "mouseMoveEvent::REORDER bottom half" );
289-
if ( mItemBeingMoved != dest->nextSibling() )
290-
{
291-
//origin->moveItem(dest);
292-
moveItem( origin, dest );
293-
}
294-
setCursor( QCursor( Qt::SizeVerCursor ) );
295-
setCurrentItem( origin );
296-
}
297-
else if ( action == QgsLegendItem::INSERT )
298-
{
299-
QgsDebugMsg( "mouseMoveEvent::INSERT" );
300-
301-
setCursor( QCursor( Qt::PointingHandCursor ) );
302-
if ( origin->parent() != dest )
293+
else if ( action == QgsLegendItem::INSERT )
303294
{
304-
insertItem( origin, dest );
305-
setCurrentItem( origin );
295+
QgsDebugMsg( "mouseMoveEvent::INSERT" );
296+
mDropAction = INTO_GROUP;
297+
showLine( line_y, line_left);
298+
setCursor( QCursor( Qt::SizeVerCursor ) );
306299
}
307-
}
308-
else//no action
309-
{
310-
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
311-
312-
if ( origin->type() == QgsLegendItem::LEGEND_LAYER_FILE && mItemBeingMovedOrigPos != getItemPos( mItemBeingMoved ) )
300+
else//no action
313301
{
314-
resetToInitialPosition( mItemBeingMoved );
302+
mDropAction = NO_ACTION;
303+
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
304+
setCursor( QCursor( Qt::ForbiddenCursor ) );
315305
}
316-
setCursor( QCursor( Qt::ForbiddenCursor ) );
317306
}
318307
}
308+
else
309+
{
310+
setCursor( QCursor( Qt::ForbiddenCursor ) );
311+
}
312+
}
313+
else if (!item && e->pos().y() >= 0 && e->pos().y() < viewport()->height() && e->pos().x() >= 0 && e->pos().x() < viewport()->width() )
314+
{
315+
// Outside the listed items, but check if we are in the empty area
316+
// of the viewport, so we can drop after the last top level item.
317+
QgsDebugMsg( "You are below the table" );
318+
mDropTarget = topLevelItem( topLevelItemCount() - 1 );
319+
dest = dynamic_cast<QgsLegendItem*>( mDropTarget );
320+
QgsLegendItem::DRAG_ACTION action = dest->accept( origin );
321+
if ( action == QgsLegendItem::REORDER || action == QgsLegendItem::INSERT )
322+
{
323+
QgsDebugMsg( "mouseMoveEvent::INSERT or REORDER" );
324+
mDropAction = AFTER;
325+
showLine(visualItemRect( lastVisibleItem() ).bottom() + 1, 0);
326+
setCursor( QCursor( Qt::SizeVerCursor ) );
327+
}
328+
else //no action
329+
{
330+
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
331+
mDropAction = NO_ACTION;
332+
setCursor( QCursor( Qt::ForbiddenCursor ) );
333+
}
334+
}
335+
336+
else
337+
{
338+
QgsDebugMsg( "No item here" );
339+
mDropTarget = NULL;
340+
setCursor( QCursor( Qt::ForbiddenCursor ) );
319341
}
320342
}
321343
}
@@ -332,13 +354,15 @@ void QgsLegend::mouseReleaseEvent( QMouseEvent * e )
332354
return;
333355
}
334356

335-
QTreeWidgetItem *destItem = itemAt( e->pos() );
357+
hideLine();
358+
359+
QTreeWidgetItem *destItem = mDropTarget;
336360

337361
QgsLegendItem* origin = dynamic_cast<QgsLegendItem*>( mItemBeingMoved );
338362
QgsLegendItem* dest = dynamic_cast<QgsLegendItem*>( destItem );
339363

340364
// no change?
341-
if ( !dest || !origin )
365+
if ( !dest || !origin || (dest == origin) )
342366
{
343367
checkLayerOrderUpdate();
344368
return;
@@ -404,7 +428,40 @@ void QgsLegend::mouseReleaseEvent( QMouseEvent * e )
404428
}
405429
else
406430
{
431+
// Do the actual move here.
407432
QgsDebugMsg( "Other type of drag'n'drop happened!" );
433+
if ( mDropAction == AFTER) //over center of item
434+
{
435+
QgsDebugMsg( "Drop AFTER" );
436+
if ( dest->nextSibling() != origin )
437+
{
438+
moveItem( origin, dest );
439+
setCurrentItem( origin );
440+
}
441+
}
442+
else if ( mDropAction == BEFORE )// below center of item
443+
{
444+
QgsDebugMsg( "Drop BEFORE" );
445+
if ( dest->findYoungerSibling() != origin )
446+
{
447+
moveItem( origin, dest ); // Insert after, as above...
448+
moveItem( dest, origin ); // ... and then switch places!
449+
setCurrentItem( origin );
450+
}
451+
}
452+
else if ( mDropAction == INTO_GROUP )
453+
{
454+
QgsDebugMsg( "Drop INTO_GROUP" );
455+
if ( origin->parent() != dest )
456+
{
457+
insertItem( origin, dest );
458+
setCurrentItem( origin );
459+
}
460+
}
461+
else//no action
462+
{
463+
QgsDebugMsg( "Drop NO_ACTION" );
464+
}
408465
}
409466

410467
checkLayerOrderUpdate();
@@ -1375,6 +1432,9 @@ void QgsLegend::insertItem( QTreeWidgetItem* move, QTreeWidgetItem* into )
13751432

13761433
void QgsLegend::moveItem( QTreeWidgetItem* move, QTreeWidgetItem* after )
13771434
{
1435+
QgsDebugMsg( QString( "Moving layer : %1 (%2)" ).arg( move->text( 0 ) ).arg( move->type() ) );
1436+
QgsDebugMsg( QString( "after layer : %1 (%2)" ).arg( after->text( 0 ) ).arg( after->type() ) );
1437+
13781438
static_cast<QgsLegendItem*>( move )->storeAppearanceSettings();//store settings in the moved item and its childern
13791439
if ( move->parent() )
13801440
{
@@ -1921,3 +1981,26 @@ bool QgsLegend::checkLayerOrderUpdate()
19211981
}
19221982
return false;
19231983
}
1984+
1985+
void QgsLegend::hideLine()
1986+
{
1987+
mInsertionLine->setGeometry(0, -100, 1, 1);
1988+
}
1989+
1990+
void QgsLegend::showLine(int y, int left)
1991+
{
1992+
mInsertionLine->setGeometry(left, y, viewport()->width(), 2);
1993+
}
1994+
1995+
QTreeWidgetItem * QgsLegend::lastVisibleItem()
1996+
{
1997+
QTreeWidgetItem *current;
1998+
QTreeWidgetItem *next;
1999+
2000+
current = topLevelItem( topLevelItemCount() - 1 );
2001+
while ( ( next = itemBelow( current ) ) )
2002+
{
2003+
current = next;
2004+
}
2005+
return current;
2006+
}

src/app/legend/qgslegend.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,28 @@ class QgsLegend : public QTreeWidget
300300
/**This function compares the layer order before a drag with the current layer ordering and triggers a canvas repaint if it has changed*/
301301
bool checkLayerOrderUpdate();
302302

303+
/**The target that the mouse is over when dragging */
304+
QTreeWidgetItem *mDropTarget;
305+
306+
enum DROP_ACTION_TYPE
307+
{
308+
BEFORE,
309+
AFTER,
310+
INTO_GROUP,
311+
NO_ACTION
312+
};
313+
/** Set when mouse is moved over different kind of items, depending opn what they accept() */
314+
DROP_ACTION_TYPE mDropAction;
315+
316+
/** Hide the line that indicates insertion position */
317+
void hideLine();
318+
319+
/** Show the line that indicates insertion position */
320+
void showLine(int y, int left);
321+
322+
/** Returns the last visible item in the tree widget */
323+
QTreeWidgetItem *lastVisibleItem();
324+
303325
private slots:
304326

305327
/**Calls 'handleRightClickEvent' on the item*/
@@ -416,7 +438,8 @@ class QgsLegend : public QTreeWidget
416438

417439
} mPixmaps;
418440

419-
441+
//! Widget that holds the indicator line //
442+
QWidget *mInsertionLine;
420443

421444
signals:
422445
void zOrderChanged( QgsLegend * lv );

0 commit comments

Comments
 (0)