@@ -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
93101QgsLegend::~QgsLegend ()
94- {}
102+ {
103+ delete mInsertionLine ;
104+ }
95105
96106void 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
13761433void 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+ }
0 commit comments