Skip to content

Commit

Permalink
[FEATURE] add support for nested layers
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@14394 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
jef committed Oct 18, 2010
1 parent aacf2f7 commit 0c5ebf7
Show file tree
Hide file tree
Showing 40 changed files with 913 additions and 948 deletions.
1,029 changes: 538 additions & 491 deletions src/app/legend/qgslegend.cpp

Large diffs are not rendered by default.

84 changes: 28 additions & 56 deletions src/app/legend/qgslegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
#ifndef QGSLEGEND_H
#define QGSLEGEND_H

#include <deque>
#include <map>
#include <set>
#include <QTreeWidget>
#include <QPair>
#include <set>

class QgsLegendGroup;
class QgsLegendLayer;
Expand Down Expand Up @@ -89,7 +88,6 @@ class QgsLegend : public QTreeWidget
// declaration was public while the definition was private
class QgsLegendPixmaps;


public:
/*! Constructor.
* @param qgis_app link to qgisapp
Expand Down Expand Up @@ -162,7 +160,7 @@ class QgsLegend : public QTreeWidget
void removeItem( QTreeWidgetItem* item );

/**Returns the ids of the layers contained in this legend. The order is bottom->top*/
std::deque<QString> layerIDs();
QStringList layerIDs();

/**Updates layer set of map canvas*/
void updateMapCanvasLayerSet();
Expand Down Expand Up @@ -191,9 +189,10 @@ class QgsLegend : public QTreeWidget
/**Returns a layers check state*/
Qt::CheckState layerCheckState( QgsMapLayer * layer );


void updateCheckStates( QTreeWidgetItem* item, Qt::CheckState state ) { item->setData( 0, Qt::UserRole, state ); }

void updateGroupCheckStates( QTreeWidgetItem *item );

public slots:

/*!Adds a new layer group with the maplayer to the canvas*/
Expand Down Expand Up @@ -270,6 +269,7 @@ class QgsLegend : public QTreeWidget

/** Remove selected layers */
void removeSelectedLayers();

protected:

/*!Event handler for mouse movements.
Expand Down Expand Up @@ -312,13 +312,6 @@ class QgsLegend : public QTreeWidget
void mouseReleaseEvent( QMouseEvent * e );
void mouseDoubleClickEvent( QMouseEvent* e );

/**Stores the necessary information about the position of an item in the hierarchy. Afterwards,
this item may be moved back to the original position with resetToInitialPosition()*/
void storeInitialPosition( QTreeWidgetItem* li );

/**Moves an item back to the position where storeInitialPosition has been called*/
void resetToInitialPosition( QTreeWidgetItem* li );

/**Returns the legend layer to which a map layer belongs to*/
QgsLegendLayer* findLegendLayer( const QString& layerKey );

Expand All @@ -334,18 +327,23 @@ 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 */
// mouse is pressed
bool mMousePressedFlag;

// position of mouse when it is pressed at the start of a drag event.
QPoint mLastPressPos;

// layer our prior to move
QStringList mLayersPriorToMove;

// keep track of the items being dragged
QList< QTreeWidgetItem * > mItemsBeingMoved;

// 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;
// The action when the mouse is released
enum { BEFORE, INSERT, AFTER } mDropAction;

/** Hide the line that indicates insertion position */
void hideLine();
Expand Down Expand Up @@ -374,8 +372,8 @@ class QgsLegend : public QTreeWidget
void expandAll();
/**Sets all listview items to closed*/
void collapseAll();
/**Just for a test*/
void handleItemChange( QTreeWidgetItem* item, int row );
void propagateItemChange( QTreeWidgetItem *item, Qt::CheckState state );
/** delegates current layer to map canvas */
void handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous );
/**Calls openPersistentEditor for the current item*/
Expand All @@ -384,6 +382,8 @@ class QgsLegend : public QTreeWidget
void makeToTopLevelItem();

private:
bool readXML( QgsLegendGroup *parent, const QDomNode &node );
bool writeXML( QList<QTreeWidgetItem *> items, QDomNode &node, QDomDocument &document );

/*! Prevent the copying of QgsLegends
* @todo See if this is really required - we may want multiple map, canvas and
Expand All @@ -398,38 +398,6 @@ class QgsLegend : public QTreeWidget
*/
QgsLegend & operator=( QgsLegend const & );

/*!
* Position of mouse when it is pressed at the start of a drag event.
*/
QPoint mLastPressPos;

/**True if the mouse is pressed*/
bool mMousePressedFlag;

/// keep track of the Item being dragged
QTreeWidgetItem* mItemBeingMoved;

/*!
* Position in the list of the item being moved as it was at the start of a drag event.
* An item at the top of the list will be 0 and each successive item below it
* will be 1,2 3 etc... regardless of nesting level.
*/
int mItemBeingMovedOrigPos;

/**Information needed by 'storeInitialPosition' and 'resetToInitialPosition'*/
enum HIERARCHY_POSITION_TYPE
{
FIRST_ITEM,
FIRST_CHILD,
YOUNGER_SIBLING
};
HIERARCHY_POSITION_TYPE mRestoreInformation;
QTreeWidgetItem* mRestoreItem;

/**Stores the layer ordering before a mouse Move. After the move, this is used to
decide if the mapcanvas really has to be refreshed*/
std::deque<QString> mLayersPriorToMove;

/*!
* A function to determine how far down in the list an item is (starting with one for the first Item).
*If the item is not in the legend, -1 is returned
Expand Down Expand Up @@ -472,6 +440,10 @@ class QgsLegend : public QTreeWidget
//! Widget that holds the indicator line //
QWidget *mInsertionLine;

#ifdef QGISDEBUG
void showItem( QString msg, QTreeWidgetItem *item );
#endif

signals:
void itemMoved( QModelIndex oldIndex, QModelIndex newIndex );

Expand Down
85 changes: 34 additions & 51 deletions src/app/legend/qgslegendgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,47 +57,10 @@ QgsLegendGroup::~QgsLegendGroup()
{}


bool QgsLegendGroup::isLeafNode()
{
return mLeafNodeFlag;
}

QgsLegendItem::DRAG_ACTION QgsLegendGroup::accept( LEGEND_ITEM_TYPE type )
{
if ( type == LEGEND_GROUP )
{
return REORDER;
}
if ( type == LEGEND_LAYER )
{
return INSERT;
}
else
{
return NO_ACTION;
}
}

QgsLegendItem::DRAG_ACTION QgsLegendGroup::accept( const QgsLegendItem* li ) const
{
if ( li )
{
LEGEND_ITEM_TYPE type = li->type();
if ( type == LEGEND_GROUP )
{
return REORDER;
}
if ( type == LEGEND_LAYER )
{
return INSERT;
}
}
return NO_ACTION;
}

bool QgsLegendGroup::insert( QgsLegendItem* theItem )
{
if ( theItem->type() == LEGEND_LAYER )
if ( theItem->type() == LEGEND_GROUP ||
theItem->type() == LEGEND_LAYER )
{
// Always insert at top of list
insertChild( 0, theItem );
Expand All @@ -107,33 +70,53 @@ bool QgsLegendGroup::insert( QgsLegendItem* theItem )
return true;
}

std::list<QgsLegendLayer*> QgsLegendGroup::legendLayers()
QList<QgsLegendLayer*> QgsLegendGroup::legendLayers( bool recurse )
{
std::list<QgsLegendLayer*> result;
QList<QgsLegendLayer*> result;
for ( int i = 0; i < childCount(); ++i )
{
QgsLegendLayer* childItem = dynamic_cast<QgsLegendLayer *>( child( i ) );
if ( childItem )
QgsLegendLayer *layer = dynamic_cast<QgsLegendLayer *>( child( i ) );
if ( layer )
{
result.push_back( layer );
}

if ( !recurse )
continue;

QgsLegendGroup *group = dynamic_cast<QgsLegendGroup *>( child( i ) );
if ( group )
{
result.push_back( childItem );
result << group->legendLayers( true );
}
}
return result;
}

void QgsLegendGroup::updateCheckState()
{
std::list<QgsLegendLayer*> llayers = legendLayers();
if ( llayers.size() == 0 )
QList<QgsLegendItem *> elements;

for ( int i = 0; i < childCount(); i++ )
{
return;
QgsLegendItem *li = dynamic_cast<QgsLegendItem *>( child( i ) );

if ( !li )
continue;

if ( dynamic_cast<QgsLegendGroup *>( li ) || dynamic_cast<QgsLegendLayer *>( li ) )
{
elements << li;
}
}

std::list<QgsLegendLayer*>::iterator iter = llayers.begin();
Qt::CheckState theState = ( *iter )->checkState( 0 );
for ( ; iter != llayers.end(); ++iter )
if ( elements.isEmpty() )
return;

Qt::CheckState theState = elements[0]->checkState( 0 );
foreach( QgsLegendItem *li, elements )
{
if ( theState != ( *iter )->checkState( 0 ) )
if ( theState != li->checkState( 0 ) )
{
theState = Qt::PartiallyChecked;
break;
Expand Down
7 changes: 2 additions & 5 deletions src/app/legend/qgslegendgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ class QgsLegendGroup : public QgsLegendItem
QgsLegendGroup( QString name );
~QgsLegendGroup();

QgsLegendItem::DRAG_ACTION accept( LEGEND_ITEM_TYPE type );
QgsLegendItem::DRAG_ACTION accept( const QgsLegendItem* li ) const;
bool isLeafNode();
bool insert( QgsLegendItem* theItem );
/**Returns all legend layers under this group*/
std::list<QgsLegendLayer*> legendLayers();
/**Returns all legend layers under this group (including those of subgroups by default)*/
QList<QgsLegendLayer*> legendLayers( bool recurse = true );
/**Goes through all the legendlayers and sets check state to checked/partially checked/unchecked*/
void updateCheckState();
};
Expand Down
12 changes: 3 additions & 9 deletions src/app/legend/qgslegenditem.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2005 by Tim Sutton *
* aps02ts@macbuntu *
* Copyright (C) 2005 by Tim Sutton *
* aps02ts@macbuntu *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -62,13 +62,8 @@ class QgsLegendItem : public QTreeWidgetItem, public QObject
NO_ACTION //do nothing
};

virtual bool isLeafNode() = 0;
virtual LEGEND_ITEM_TYPE type() const {return mType;}
/**Returns the type of action that will be done if a drag, originating at a certain
item type, will be released at this item*/
virtual DRAG_ACTION accept( LEGEND_ITEM_TYPE type ) = 0;
/**Retrns the type of action that will be done if a legend item is dragged over this item*/
virtual DRAG_ACTION accept( const QgsLegendItem* li ) const = 0;

/**Subclasses which allow insertion of other items may implement this method.
@param theItem legend item to insert into this item
@param changesettings Some insert actions may change the state of the layers or the map canvas.
Expand Down Expand Up @@ -111,7 +106,6 @@ class QgsLegendItem : public QTreeWidgetItem, public QObject
virtual void release( QgsLegendItem* formerChild ) {}

protected:
bool mLeafNodeFlag;
LEGEND_ITEM_TYPE mType;
/**Stores expanded property when storeAppearanceSettings is called*/
bool mExpanded;
Expand Down
45 changes: 2 additions & 43 deletions src/app/legend/qgslegendlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,48 +99,6 @@ void QgsLegendLayer::setupFont() //private method
setFont( 0, myFont );
}

bool QgsLegendLayer::isLeafNode()
{
return false;
}

QgsLegendItem::DRAG_ACTION QgsLegendLayer::accept( LEGEND_ITEM_TYPE type )
{
if ( type == LEGEND_LAYER || type == LEGEND_GROUP )
{
return REORDER;
}
else
{
return NO_ACTION;
}
}

QgsLegendItem::DRAG_ACTION QgsLegendLayer::accept( const QgsLegendItem* li ) const
{
if ( li && li != this )
{
LEGEND_ITEM_TYPE type = li->type();
if ( type == LEGEND_LAYER )
{
//if(parent() == li->parent())
//{
return REORDER;
//}
}
else if ( type == LEGEND_GROUP )
{
//only parent legend layers can change positions with groups
if ( parent() == 0 )
{
return REORDER;
}
}
}
return NO_ACTION;
}


QgsMapLayer* QgsLegendLayer::layer()
{
return mLyr.layer();
Expand Down Expand Up @@ -456,7 +414,8 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
saveSelectionAsAction->setEnabled( false );
}

theMenu.addAction( tr( "&Query..." ), QgisApp::instance(), SLOT( layerSubsetString() ) );
if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() )
theMenu.addAction( tr( "&Query..." ), QgisApp::instance(), SLOT( layerSubsetString() ) );

theMenu.addSeparator();
}
Expand Down
3 changes: 0 additions & 3 deletions src/app/legend/qgslegendlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ class QgsLegendLayer : public QgsLegendItem
QgsLegendLayer( QgsMapLayer* layer );
~QgsLegendLayer();

bool isLeafNode();
QgsLegendItem::DRAG_ACTION accept( LEGEND_ITEM_TYPE type );
QgsLegendItem::DRAG_ACTION accept( const QgsLegendItem* li ) const;
/**Returns the map layer associated the item*/
QgsMapLayer* layer();
QgsMapCanvasLayer& canvasLayer();
Expand Down
Loading

0 comments on commit 0c5ebf7

Please sign in to comment.