** autoscroll the legend view when dragging layers

** gave file the indent treatment


git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@1439 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
stevehalasz 2004-05-20 21:22:50 +00:00
parent 635b6d78c4
commit e250650c98

View File

@ -26,7 +26,7 @@
#include <qvbox.h>
#include <qlistview.h>
#include <qptrlist.h>
#include <qobjectlist.h>
#include <qobjectlist.h>
#include "qgsmapcanvas.h"
@ -35,21 +35,22 @@
#include "qgslegend.h"
static const char* const ident_
= "$Id$";
static const char *const ident_ = "$Id$";
const int AUTOSCROLL_MARGIN = 16;
/**
@note
set movingItem pointer to 0 to prevent SuSE 9.0 crash
*/
QgsLegend::QgsLegend(QWidget * parent, const char *name)
: QListView(parent, name), mousePressed(false), movingItem(0)
{}
QgsLegend::QgsLegend(QWidget * parent, const char *name):QListView(parent, name), mousePressed(false), movingItem(0)
{
}
QgsLegend::~QgsLegend()
{}
{
}
void QgsLegend::setMapCanvas(QgsMapCanvas * canvas)
@ -74,13 +75,12 @@ QString QgsLegend::currentLayerName()
QListViewItem *li = currentItem();
if (li)
{
return li->text(0);
}
else
{
{
return li->text(0);
} else
{
return 0;
}
}
}
@ -91,91 +91,82 @@ QString QgsLegend::currentLayerName()
@return pointer to QgsLegendItem with that name, otherwise null.
*/
static
QgsLegendItem *
findLegendItem_( QgsLegend * legend, QString const & name )
static QgsLegendItem *findLegendItem_(QgsLegend * legend, QString const &name)
{
QListViewItemIterator it(legend);
while (it.current())
{
QgsLegendItem * li = dynamic_cast<QgsLegendItem*>(it.current());
{
QgsLegendItem *li = dynamic_cast < QgsLegendItem * >(it.current());
Q_CHECK_PTR( li );
Q_CHECK_PTR(li);
if ( li )
{
std::cerr << "comparing " << li->layerID()
<< " and " << name << "\n";
if ( li->layerID() == name )
{
if (li)
{
std::cerr << "comparing " << li->layerID() << " and " << name << "\n";
if (li->layerID() == name)
{
return li;
}
}
}
}
++it;
}
}
return 0x0;
} // findLegendItem_( QString const & name )
} // findLegendItem_( QString const & name )
#ifdef DEPRECATED
void QgsLegend::update()
{
// if there are already items in the legend, then we need to be careful to
// only add new items, and to keep the items that are selected selected
if ( childCount() )
{ // we have legend items, so add ONLY NEW ONES leaving original items
// if there are already items in the legend, then we need to be careful to
// only add new items, and to keep the items that are selected selected
if (childCount())
{ // we have legend items, so add ONLY NEW ONES leaving original items
// alone
// current map layer
QgsMapLayer * currentMapLayer = 0x0;
// current map layer
QgsMapLayer *currentMapLayer = 0x0;
// grind through all the layers in "Z" order (i.e., front to back)
for ( int currentLayer = 0;
currentLayer < map->zOrders().size();
++currentLayer )
// grind through all the layers in "Z" order (i.e., front to back)
for (int currentLayer = 0; currentLayer < map->zOrders().size(); ++currentLayer)
{
currentMapLayer = map->getZpos( currentLayer );
currentMapLayer = map->getZpos(currentLayer);
// if the map layer isn't in the legend, add it
if ( ! findLegendItem_( this, currentMapLayer->name() ) )
// if the map layer isn't in the legend, add it
if (!findLegendItem_(this, currentMapLayer->name()))
{
std::cerr << __FILE__ << ":" << __LINE__
<< " didn't find " << currentMapLayer->name() << "'s legend item ... adding new item\n";
std::cerr << __FILE__ << ":" << __LINE__
<< " didn't find " << currentMapLayer->name() << "'s legend item ... adding new item\n";
QgsLegendItem *lvi =
new QgsLegendItem(currentMapLayer, this);
currentMapLayer->setLegendItem(lvi);
lvi->setPixmap(0, *currentMapLayer->legendPixmap());
}
else
QgsLegendItem *lvi = new QgsLegendItem(currentMapLayer, this);
currentMapLayer->setLegendItem(lvi);
lvi->setPixmap(0, *currentMapLayer->legendPixmap());
} else
{
std::cerr << __FILE__ << ":" << __LINE__
<< " found " << currentMapLayer->name() << "'s legend item ... skipping\n";
std::cerr << __FILE__ << ":" << __LINE__ << " found " << currentMapLayer->name() << "'s legend item ... skipping\n";
}
++currentLayer;
++currentLayer;
}
}
else
{ // no layers loaded, so just load 'em all up
} else
{ // no layers loaded, so just load 'em all up
std::list < QString >::iterator zi = map->zOrders().begin();
while (zi != map->zOrders().end())
std::list < QString >::iterator zi = map->zOrders().begin();
while (zi != map->zOrders().end())
{
QgsMapLayer *lyr = map->layerByName(*zi);
QgsLegendItem *lvi = new QgsLegendItem(lyr, this); // lyr->name(), QCheckListItem::CheckBox );
lyr->setLegendItem(lvi);
lvi->setPixmap(0, *lyr->legendPixmap());
zi++;
QgsMapLayer *lyr = map->layerByName(*zi);
QgsLegendItem *lvi = new QgsLegendItem(lyr, this); // lyr->name(), QCheckListItem::CheckBox );
lyr->setLegendItem(lvi);
lvi->setPixmap(0, *lyr->legendPixmap());
zi++;
}
// highlight the top item
// highlight the top item
setCurrentItem( firstChild() );
setSelected( firstChild(), true );
setCurrentItem(firstChild());
setSelected(firstChild(), true);
}
emit currentChanged(currentItem());
@ -197,140 +188,143 @@ void QgsLegend::update()
*/
} // QgsLegend::update()
} // QgsLegend::update()
#endif // DEPRECATED
/* slot */
void QgsLegend::addLayer( QgsMapLayer * layer )
void QgsLegend::addLayer(QgsMapLayer * layer)
{
// XXX check for duplicates first?
// XXX check for duplicates first?
Q_CHECK_PTR( layer );
Q_CHECK_PTR(layer);
if ( ! layer )
{ return; }
QgsLegendItem * legend_item = new QgsLegendItem( layer, this );
// done in QgsLegendItem ctor legend_item->setPixmap( 0, *layer->legendPixmap() );
// XXX we could probably make map layers ignorant of corresponding legend
// XXX item through use of signals/slots
layer->setLegendItem( legend_item );
// if the newly added legend item is the first one, then go ahead and
// highlight it indicating it is selected
if ( 1 == childCount() )
if (!layer)
{
setCurrentItem( firstChild() );
setSelected( firstChild(), true ); // shouldn't have to do this,
// but for some reason making it current
// item doesn't select it
return;
}
} // QgsLegend::addLayer
QgsLegendItem *legend_item = new QgsLegendItem(layer, this);
// done in QgsLegendItem ctor legend_item->setPixmap( 0, *layer->legendPixmap() );
// XXX we could probably make map layers ignorant of corresponding legend
// XXX item through use of signals/slots
layer->setLegendItem(legend_item);
// if the newly added legend item is the first one, then go ahead and
// highlight it indicating it is selected
if (1 == childCount())
{
setCurrentItem(firstChild());
setSelected(firstChild(), true); // shouldn't have to do this,
// but for some reason making it current
// item doesn't select it
}
} // QgsLegend::addLayer
/* slot */
void QgsLegend::removeLayer( QString layer_key )
void QgsLegend::removeLayer(QString layer_key)
{
// There are three possible starting legend states when this is invoked.
//
// 1. there is currently only one layer
// 2. there is currently more than one layer, and this layer isn't selected
// 3. there is currently more than one layer, and this layer is selected
// There are three possible starting legend states when this is invoked.
//
// 1. there is currently only one layer
// 2. there is currently more than one layer, and this layer isn't selected
// 3. there is currently more than one layer, and this layer is selected
// For #1, we just remove the layer. For #2, we also just remove the
// layer. #3 is more complicated in that if it's the _only_ selected
// layer, we should reset what is the current layer and toggle on its
// selection; if there're more than one selected layer, then just remove
// this layer. We arbitrarily make firstChild() the new selected layer,
// in the case of new selected layers after deleting this one. (Because
// it's easy.)
// For #1, we just remove the layer. For #2, we also just remove the
// layer. #3 is more complicated in that if it's the _only_ selected
// layer, we should reset what is the current layer and toggle on its
// selection; if there're more than one selected layer, then just remove
// this layer. We arbitrarily make firstChild() the new selected layer,
// in the case of new selected layers after deleting this one. (Because
// it's easy.)
// first find the layer
QListViewItemIterator it(this);
// first find the layer
for ( ; it.current(); ++it )
QListViewItemIterator it(this);
for (; it.current(); ++it)
{
QgsLegendItem *li = (QgsLegendItem *) it.current();
if ( li->layerID() == layer_key )
{ break; }
QgsLegendItem *li = (QgsLegendItem *) it.current();
if (li->layerID() == layer_key)
{
break;
}
}
if ( it.current() ) // will be non-NULL if found layer
if (it.current()) // will be non-NULL if found layer
{
bool makeNewCurrentItem(false);
bool makeNewCurrentItem(false);
// if the current item is about to be deleted, make a note of it so
// that we can select a new one later
if ( it.current() == currentItem() )
// if the current item is about to be deleted, make a note of it so
// that we can select a new one later
if (it.current() == currentItem())
{
makeNewCurrentItem = true;
makeNewCurrentItem = true;
}
delete it.current(); // remove from list
delete it.current(); // remove from list
map->remove( layer_key ); // tell canvas map to remove the layer; note
// that a revese "removeLayer" signal will
// call this function -- which will be fine
// because the second invocation won't find
// the layer and just exit
map->remove(layer_key); // tell canvas map to remove the layer; note
// that a revese "removeLayer" signal will
// call this function -- which will be fine
// because the second invocation won't find
// the layer and just exit
// if we find a selected layer, do nothing; if
// we don't then arbitrarily set firstChild()
// to be the current layer
// if we find a selected layer, do nothing; if
// we don't then arbitrarily set firstChild()
// to be the current layer
// not Qt 3.1.2 compatible QListViewItemIterator select_it(this, QListViewItemIterator::Selected);
QListViewItemIterator select_it(this);
// not Qt 3.1.2 compatible QListViewItemIterator select_it(this, QListViewItemIterator::Selected);
QListViewItemIterator select_it(this);
for ( ; select_it.current(); ++select_it )
for (; select_it.current(); ++select_it)
{
if ( it.current()->isSelected() )
if (it.current()->isSelected())
{
// if we even find ONE SELECTED ITEM, we're done since there's
// still at least one other layer that's selected
// if we even find ONE SELECTED ITEM, we're done since there's
// still at least one other layer that's selected
// Wellll, ok, we'll have to possibly set the current item
if ( makeNewCurrentItem )
// Wellll, ok, we'll have to possibly set the current item
if (makeNewCurrentItem)
{
setCurrentItem( select_it.current() );
emit currentChanged( firstChild() );
setCurrentItem(select_it.current());
emit currentChanged(firstChild());
}
break;
break;
}
}
if ( ! select_it.current() )
if (!select_it.current())
{
// if there're NO CURRENTLY SELECTED ITEMS, arbitrarily make
// firstChild() the current selected item
// if there're NO CURRENTLY SELECTED ITEMS, arbitrarily make
// firstChild() the current selected item
setCurrentItem( firstChild() );
emit currentChanged( firstChild() );
setCurrentItem(firstChild());
emit currentChanged(firstChild());
}
emit layerRemoved( layer_key );
}
else
emit layerRemoved(layer_key);
} else
{
// NOP -- this might actually be ok since it's possible for this
// function to be invoked twice because map canvas signal
// "removedLayer" will call this slot; but the second go round the
// layer will already be gone, so it'll just return.
// NOP -- this might actually be ok since it's possible for this
// function to be invoked twice because map canvas signal
// "removedLayer" will call this slot; but the second go round the
// layer will already be gone, so it'll just return.
// XXX this still seems kludgy to me; but it's better than what was
// XXX here before; we could probably correct by working out better
// XXX signal/slot system network
// XXX this still seems kludgy to me; but it's better than what was
// XXX here before; we could probably correct by working out better
// XXX signal/slot system network
}
} // removeLayer
} // removeLayer
@ -349,7 +343,7 @@ void QgsLegend::contentsMousePressEvent(QMouseEvent * e)
QListView::contentsMousePressEvent(e);
} // contentsMousePressEvent
} // contentsMousePressEvent
@ -369,17 +363,19 @@ void QgsLegend::contentsMouseMoveEvent(QMouseEvent * e)
}
} else if (movingItem)
{
// scroll view if we're near the edge
QPoint p(contentsToViewport(e->pos()));
//if (p.y() < 15)
// {
// scrollBy(0, -(15 - p.y()));
//} else if (p.y() > visibleHeight() - 15)
// {
// scrollBy(0, p.y() - visibleHeight() - 15)
// }
// scroll list if we're near the edge of the viewport
// code lifted from the poa project: http://poa.berlios.de/
QPoint p(contentsToViewport(e->pos()));
if (p.y() < AUTOSCROLL_MARGIN)
{
// scroll up
scrollBy(0, -(AUTOSCROLL_MARGIN - p.y()));
} else if (p.y() > visibleHeight() - AUTOSCROLL_MARGIN)
{
// scroll down
scrollBy(0, (p.y() - (visibleHeight() - AUTOSCROLL_MARGIN)));
}
// move item in list if we're dragging over another item
QListViewItem *item = itemAt(p);
if (item && (item != movingItem))
@ -405,7 +401,7 @@ void QgsLegend::contentsMouseMoveEvent(QMouseEvent * e)
{
movingItem->moveItem(item);
}
}
}
}
}
}