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
This commit is contained in:
homann 2009-07-31 22:37:52 +00:00
parent ddba6694d3
commit 97da8f506a
2 changed files with 182 additions and 76 deletions

View File

@ -75,6 +75,14 @@ QgsLegend::QgsLegend( QWidget * parent, const char *name )
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
this, SLOT( writeProject( QDomDocument & ) ) );
// Initialise the line indicator widget.
mInsertionLine = new QWidget(viewport());
hideLine();
mInsertionLine->setAutoFillBackground(true);
QPalette pal = mInsertionLine->palette();
pal.setColor(mInsertionLine->backgroundRole(), Qt::blue);
mInsertionLine->setPalette(pal);
setSortingEnabled( false );
setDragEnabled( false );
setAutoScroll( true );
@ -91,7 +99,9 @@ QgsLegend::QgsLegend( QWidget * parent, const char *name )
}
QgsLegend::~QgsLegend()
{}
{
delete mInsertionLine;
}
void QgsLegend::handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
{
@ -237,85 +247,97 @@ void QgsLegend::mouseMoveEvent( QMouseEvent * e )
// change the cursor appropriate to if drop is allowed
QTreeWidgetItem* item = itemAt( p );
hideLine();
QgsLegendItem* origin = dynamic_cast<QgsLegendItem*>( mItemBeingMoved );
QgsLegendItem* dest = dynamic_cast<QgsLegendItem*>( item );
if ( !item )
if ( item )
{
setCursor( QCursor( Qt::ForbiddenCursor ) );
mDropTarget = item;
QgsLegendItem::DRAG_ACTION action = dest->accept( origin );
if ( item != mItemBeingMoved )
{
if ( yCoordAboveCenter( dest, e->y() ) ) //over center of item
{
int line_y = visualItemRect(item).top() + 1;
int line_left = visualItemRect(item).left();
if ( action == QgsLegendItem::REORDER || action == QgsLegendItem::INSERT )
{
QgsDebugMsg( "mouseMoveEvent::INSERT or REORDER" );
mDropAction = BEFORE;
showLine( line_y, line_left);
setCursor( QCursor( Qt::SizeVerCursor ) );
}
else //no action
{
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
mDropAction = NO_ACTION;
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
else // below center of item
{
int line_y = visualItemRect(item).bottom() - 2;
int line_left = visualItemRect(item).left();
if ( action == QgsLegendItem::REORDER )
{
QgsDebugMsg( "mouseMoveEvent::REORDER bottom half" );
mDropAction = AFTER;
showLine( line_y, line_left);
setCursor( QCursor( Qt::SizeVerCursor ) );
}
else if ( action == QgsLegendItem::INSERT )
{
QgsDebugMsg( "mouseMoveEvent::INSERT" );
mDropAction = INTO_GROUP;
showLine( line_y, line_left);
setCursor( QCursor( Qt::SizeVerCursor ) );
}
else//no action
{
mDropAction = NO_ACTION;
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
}
else
{
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
else if (!item && e->pos().y() >= 0 && e->pos().y() < viewport()->height() && e->pos().x() >= 0 && e->pos().x() < viewport()->width() )
{
// Outside the listed items, but check if we are in the empty area
// of the viewport, so we can drop after the last top level item.
QgsDebugMsg( "You are below the table" );
mDropTarget = topLevelItem( topLevelItemCount() - 1 );
dest = dynamic_cast<QgsLegendItem*>( mDropTarget );
QgsLegendItem::DRAG_ACTION action = dest->accept( origin );
if ( action == QgsLegendItem::REORDER || action == QgsLegendItem::INSERT )
{
QgsDebugMsg( "mouseMoveEvent::INSERT or REORDER" );
mDropAction = AFTER;
showLine(visualItemRect( lastVisibleItem() ).bottom() + 1, 0);
setCursor( QCursor( Qt::SizeVerCursor ) );
}
else //no action
{
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
mDropAction = NO_ACTION;
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
if ( item && ( item != mItemBeingMoved ) )
else
{
QgsLegendItem::DRAG_ACTION action = dest->accept( origin );
if ( yCoordAboveCenter( dest, e->y() ) ) //over center of item
{
if ( action == QgsLegendItem::REORDER )
{
if ( origin->nextSibling() != dest )
{
moveItem( dest, origin );setCurrentItem( origin );
}
setCurrentItem( origin );
setCursor( QCursor( Qt::SizeVerCursor ) );
}
else if ( action == QgsLegendItem::INSERT )
{
setCursor( QCursor( Qt::PointingHandCursor ) );
if ( origin->parent() != dest )
{
insertItem( origin, dest );
}
setCurrentItem( origin );
setCursor( QCursor( Qt::PointingHandCursor ) );
}
else //no action
{
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
if ( origin->type() == QgsLegendItem::LEGEND_LAYER_FILE && mItemBeingMovedOrigPos != getItemPos( mItemBeingMoved ) )
{
resetToInitialPosition( mItemBeingMoved );
}
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
else // below center of item
{
if ( action == QgsLegendItem::REORDER )
{
QgsDebugMsg( "mouseMoveEvent::REORDER bottom half" );
if ( mItemBeingMoved != dest->nextSibling() )
{
//origin->moveItem(dest);
moveItem( origin, dest );
}
setCursor( QCursor( Qt::SizeVerCursor ) );
setCurrentItem( origin );
}
else if ( action == QgsLegendItem::INSERT )
{
QgsDebugMsg( "mouseMoveEvent::INSERT" );
setCursor( QCursor( Qt::PointingHandCursor ) );
if ( origin->parent() != dest )
{
insertItem( origin, dest );
setCurrentItem( origin );
}
}
else//no action
{
QgsDebugMsg( "mouseMoveEvent::NO_ACTION" );
if ( origin->type() == QgsLegendItem::LEGEND_LAYER_FILE && mItemBeingMovedOrigPos != getItemPos( mItemBeingMoved ) )
{
resetToInitialPosition( mItemBeingMoved );
}
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
QgsDebugMsg( "No item here" );
mDropTarget = NULL;
setCursor( QCursor( Qt::ForbiddenCursor ) );
}
}
}
@ -332,13 +354,15 @@ void QgsLegend::mouseReleaseEvent( QMouseEvent * e )
return;
}
QTreeWidgetItem *destItem = itemAt( e->pos() );
hideLine();
QTreeWidgetItem *destItem = mDropTarget;
QgsLegendItem* origin = dynamic_cast<QgsLegendItem*>( mItemBeingMoved );
QgsLegendItem* dest = dynamic_cast<QgsLegendItem*>( destItem );
// no change?
if ( !dest || !origin )
if ( !dest || !origin || (dest == origin) )
{
checkLayerOrderUpdate();
return;
@ -404,7 +428,40 @@ void QgsLegend::mouseReleaseEvent( QMouseEvent * e )
}
else
{
// Do the actual move here.
QgsDebugMsg( "Other type of drag'n'drop happened!" );
if ( mDropAction == AFTER) //over center of item
{
QgsDebugMsg( "Drop AFTER" );
if ( dest->nextSibling() != origin )
{
moveItem( origin, dest );
setCurrentItem( origin );
}
}
else if ( mDropAction == BEFORE )// below center of item
{
QgsDebugMsg( "Drop BEFORE" );
if ( dest->findYoungerSibling() != origin )
{
moveItem( origin, dest ); // Insert after, as above...
moveItem( dest, origin ); // ... and then switch places!
setCurrentItem( origin );
}
}
else if ( mDropAction == INTO_GROUP )
{
QgsDebugMsg( "Drop INTO_GROUP" );
if ( origin->parent() != dest )
{
insertItem( origin, dest );
setCurrentItem( origin );
}
}
else//no action
{
QgsDebugMsg( "Drop NO_ACTION" );
}
}
checkLayerOrderUpdate();
@ -1375,6 +1432,9 @@ void QgsLegend::insertItem( QTreeWidgetItem* move, QTreeWidgetItem* into )
void QgsLegend::moveItem( QTreeWidgetItem* move, QTreeWidgetItem* after )
{
QgsDebugMsg( QString( "Moving layer : %1 (%2)" ).arg( move->text( 0 ) ).arg( move->type() ) );
QgsDebugMsg( QString( "after layer : %1 (%2)" ).arg( after->text( 0 ) ).arg( after->type() ) );
static_cast<QgsLegendItem*>( move )->storeAppearanceSettings();//store settings in the moved item and its childern
if ( move->parent() )
{
@ -1921,3 +1981,26 @@ bool QgsLegend::checkLayerOrderUpdate()
}
return false;
}
void QgsLegend::hideLine()
{
mInsertionLine->setGeometry(0, -100, 1, 1);
}
void QgsLegend::showLine(int y, int left)
{
mInsertionLine->setGeometry(left, y, viewport()->width(), 2);
}
QTreeWidgetItem * QgsLegend::lastVisibleItem()
{
QTreeWidgetItem *current;
QTreeWidgetItem *next;
current = topLevelItem( topLevelItemCount() - 1 );
while ( ( next = itemBelow( current ) ) )
{
current = next;
}
return current;
}

View File

@ -300,6 +300,28 @@ class QgsLegend : public QTreeWidget
/**This function compares the layer order before a drag with the current layer ordering and triggers a canvas repaint if it has changed*/
bool checkLayerOrderUpdate();
/**The target that the mouse is over when dragging */
QTreeWidgetItem *mDropTarget;
enum DROP_ACTION_TYPE
{
BEFORE,
AFTER,
INTO_GROUP,
NO_ACTION
};
/** Set when mouse is moved over different kind of items, depending opn what they accept() */
DROP_ACTION_TYPE mDropAction;
/** Hide the line that indicates insertion position */
void hideLine();
/** Show the line that indicates insertion position */
void showLine(int y, int left);
/** Returns the last visible item in the tree widget */
QTreeWidgetItem *lastVisibleItem();
private slots:
/**Calls 'handleRightClickEvent' on the item*/
@ -416,7 +438,8 @@ class QgsLegend : public QTreeWidget
} mPixmaps;
//! Widget that holds the indicator line //
QWidget *mInsertionLine;
signals:
void zOrderChanged( QgsLegend * lv );