Skip to content

Commit 0c5ebf7

Browse files
author
jef
committedOct 18, 2010
[FEATURE] add support for nested layers
git-svn-id: http://svn.osgeo.org/qgis/trunk@14394 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent aacf2f7 commit 0c5ebf7

40 files changed

+913
-948
lines changed
 

‎src/app/legend/qgslegend.cpp

Lines changed: 538 additions & 491 deletions
Large diffs are not rendered by default.

‎src/app/legend/qgslegend.h

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
#ifndef QGSLEGEND_H
2121
#define QGSLEGEND_H
2222

23-
#include <deque>
24-
#include <map>
25-
#include <set>
2623
#include <QTreeWidget>
24+
#include <QPair>
25+
#include <set>
2726

2827
class QgsLegendGroup;
2928
class QgsLegendLayer;
@@ -89,7 +88,6 @@ class QgsLegend : public QTreeWidget
8988
// declaration was public while the definition was private
9089
class QgsLegendPixmaps;
9190

92-
9391
public:
9492
/*! Constructor.
9593
* @param qgis_app link to qgisapp
@@ -162,7 +160,7 @@ class QgsLegend : public QTreeWidget
162160
void removeItem( QTreeWidgetItem* item );
163161

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

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

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

194+
void updateGroupCheckStates( QTreeWidgetItem *item );
195+
197196
public slots:
198197

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

271270
/** Remove selected layers */
272271
void removeSelectedLayers();
272+
273273
protected:
274274

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

315-
/**Stores the necessary information about the position of an item in the hierarchy. Afterwards,
316-
this item may be moved back to the original position with resetToInitialPosition()*/
317-
void storeInitialPosition( QTreeWidgetItem* li );
318-
319-
/**Moves an item back to the position where storeInitialPosition has been called*/
320-
void resetToInitialPosition( QTreeWidgetItem* li );
321-
322315
/**Returns the legend layer to which a map layer belongs to*/
323316
QgsLegendLayer* findLegendLayer( const QString& layerKey );
324317

@@ -334,18 +327,23 @@ class QgsLegend : public QTreeWidget
334327
/**This function compares the layer order before a drag with the current layer ordering and triggers a canvas repaint if it has changed*/
335328
bool checkLayerOrderUpdate();
336329

337-
/**The target that the mouse is over when dragging */
330+
// mouse is pressed
331+
bool mMousePressedFlag;
332+
333+
// position of mouse when it is pressed at the start of a drag event.
334+
QPoint mLastPressPos;
335+
336+
// layer our prior to move
337+
QStringList mLayersPriorToMove;
338+
339+
// keep track of the items being dragged
340+
QList< QTreeWidgetItem * > mItemsBeingMoved;
341+
342+
// The target that the mouse is over when dragging
338343
QTreeWidgetItem *mDropTarget;
339344

340-
enum DROP_ACTION_TYPE
341-
{
342-
BEFORE,
343-
AFTER,
344-
INTO_GROUP,
345-
NO_ACTION
346-
};
347-
/** Set when mouse is moved over different kind of items, depending opn what they accept() */
348-
DROP_ACTION_TYPE mDropAction;
345+
// The action when the mouse is released
346+
enum { BEFORE, INSERT, AFTER } mDropAction;
349347

350348
/** Hide the line that indicates insertion position */
351349
void hideLine();
@@ -374,8 +372,8 @@ class QgsLegend : public QTreeWidget
374372
void expandAll();
375373
/**Sets all listview items to closed*/
376374
void collapseAll();
377-
/**Just for a test*/
378375
void handleItemChange( QTreeWidgetItem* item, int row );
376+
void propagateItemChange( QTreeWidgetItem *item, Qt::CheckState state );
379377
/** delegates current layer to map canvas */
380378
void handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous );
381379
/**Calls openPersistentEditor for the current item*/
@@ -384,6 +382,8 @@ class QgsLegend : public QTreeWidget
384382
void makeToTopLevelItem();
385383

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

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

401-
/*!
402-
* Position of mouse when it is pressed at the start of a drag event.
403-
*/
404-
QPoint mLastPressPos;
405-
406-
/**True if the mouse is pressed*/
407-
bool mMousePressedFlag;
408-
409-
/// keep track of the Item being dragged
410-
QTreeWidgetItem* mItemBeingMoved;
411-
412-
/*!
413-
* Position in the list of the item being moved as it was at the start of a drag event.
414-
* An item at the top of the list will be 0 and each successive item below it
415-
* will be 1,2 3 etc... regardless of nesting level.
416-
*/
417-
int mItemBeingMovedOrigPos;
418-
419-
/**Information needed by 'storeInitialPosition' and 'resetToInitialPosition'*/
420-
enum HIERARCHY_POSITION_TYPE
421-
{
422-
FIRST_ITEM,
423-
FIRST_CHILD,
424-
YOUNGER_SIBLING
425-
};
426-
HIERARCHY_POSITION_TYPE mRestoreInformation;
427-
QTreeWidgetItem* mRestoreItem;
428-
429-
/**Stores the layer ordering before a mouse Move. After the move, this is used to
430-
decide if the mapcanvas really has to be refreshed*/
431-
std::deque<QString> mLayersPriorToMove;
432-
433401
/*!
434402
* A function to determine how far down in the list an item is (starting with one for the first Item).
435403
*If the item is not in the legend, -1 is returned
@@ -472,6 +440,10 @@ class QgsLegend : public QTreeWidget
472440
//! Widget that holds the indicator line //
473441
QWidget *mInsertionLine;
474442

443+
#ifdef QGISDEBUG
444+
void showItem( QString msg, QTreeWidgetItem *item );
445+
#endif
446+
475447
signals:
476448
void itemMoved( QModelIndex oldIndex, QModelIndex newIndex );
477449

‎src/app/legend/qgslegendgroup.cpp

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -57,47 +57,10 @@ QgsLegendGroup::~QgsLegendGroup()
5757
{}
5858

5959

60-
bool QgsLegendGroup::isLeafNode()
61-
{
62-
return mLeafNodeFlag;
63-
}
64-
65-
QgsLegendItem::DRAG_ACTION QgsLegendGroup::accept( LEGEND_ITEM_TYPE type )
66-
{
67-
if ( type == LEGEND_GROUP )
68-
{
69-
return REORDER;
70-
}
71-
if ( type == LEGEND_LAYER )
72-
{
73-
return INSERT;
74-
}
75-
else
76-
{
77-
return NO_ACTION;
78-
}
79-
}
80-
81-
QgsLegendItem::DRAG_ACTION QgsLegendGroup::accept( const QgsLegendItem* li ) const
82-
{
83-
if ( li )
84-
{
85-
LEGEND_ITEM_TYPE type = li->type();
86-
if ( type == LEGEND_GROUP )
87-
{
88-
return REORDER;
89-
}
90-
if ( type == LEGEND_LAYER )
91-
{
92-
return INSERT;
93-
}
94-
}
95-
return NO_ACTION;
96-
}
97-
9860
bool QgsLegendGroup::insert( QgsLegendItem* theItem )
9961
{
100-
if ( theItem->type() == LEGEND_LAYER )
62+
if ( theItem->type() == LEGEND_GROUP ||
63+
theItem->type() == LEGEND_LAYER )
10164
{
10265
// Always insert at top of list
10366
insertChild( 0, theItem );
@@ -107,33 +70,53 @@ bool QgsLegendGroup::insert( QgsLegendItem* theItem )
10770
return true;
10871
}
10972

110-
std::list<QgsLegendLayer*> QgsLegendGroup::legendLayers()
73+
QList<QgsLegendLayer*> QgsLegendGroup::legendLayers( bool recurse )
11174
{
112-
std::list<QgsLegendLayer*> result;
75+
QList<QgsLegendLayer*> result;
11376
for ( int i = 0; i < childCount(); ++i )
11477
{
115-
QgsLegendLayer* childItem = dynamic_cast<QgsLegendLayer *>( child( i ) );
116-
if ( childItem )
78+
QgsLegendLayer *layer = dynamic_cast<QgsLegendLayer *>( child( i ) );
79+
if ( layer )
80+
{
81+
result.push_back( layer );
82+
}
83+
84+
if ( !recurse )
85+
continue;
86+
87+
QgsLegendGroup *group = dynamic_cast<QgsLegendGroup *>( child( i ) );
88+
if ( group )
11789
{
118-
result.push_back( childItem );
90+
result << group->legendLayers( true );
11991
}
12092
}
12193
return result;
12294
}
12395

12496
void QgsLegendGroup::updateCheckState()
12597
{
126-
std::list<QgsLegendLayer*> llayers = legendLayers();
127-
if ( llayers.size() == 0 )
98+
QList<QgsLegendItem *> elements;
99+
100+
for ( int i = 0; i < childCount(); i++ )
128101
{
129-
return;
102+
QgsLegendItem *li = dynamic_cast<QgsLegendItem *>( child( i ) );
103+
104+
if ( !li )
105+
continue;
106+
107+
if ( dynamic_cast<QgsLegendGroup *>( li ) || dynamic_cast<QgsLegendLayer *>( li ) )
108+
{
109+
elements << li;
110+
}
130111
}
131112

132-
std::list<QgsLegendLayer*>::iterator iter = llayers.begin();
133-
Qt::CheckState theState = ( *iter )->checkState( 0 );
134-
for ( ; iter != llayers.end(); ++iter )
113+
if ( elements.isEmpty() )
114+
return;
115+
116+
Qt::CheckState theState = elements[0]->checkState( 0 );
117+
foreach( QgsLegendItem *li, elements )
135118
{
136-
if ( theState != ( *iter )->checkState( 0 ) )
119+
if ( theState != li->checkState( 0 ) )
137120
{
138121
theState = Qt::PartiallyChecked;
139122
break;

‎src/app/legend/qgslegendgroup.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,9 @@ class QgsLegendGroup : public QgsLegendItem
3737
QgsLegendGroup( QString name );
3838
~QgsLegendGroup();
3939

40-
QgsLegendItem::DRAG_ACTION accept( LEGEND_ITEM_TYPE type );
41-
QgsLegendItem::DRAG_ACTION accept( const QgsLegendItem* li ) const;
42-
bool isLeafNode();
4340
bool insert( QgsLegendItem* theItem );
44-
/**Returns all legend layers under this group*/
45-
std::list<QgsLegendLayer*> legendLayers();
41+
/**Returns all legend layers under this group (including those of subgroups by default)*/
42+
QList<QgsLegendLayer*> legendLayers( bool recurse = true );
4643
/**Goes through all the legendlayers and sets check state to checked/partially checked/unchecked*/
4744
void updateCheckState();
4845
};

‎src/app/legend/qgslegenditem.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/***************************************************************************
2-
* Copyright (C) 2005 by Tim Sutton *
3-
* aps02ts@macbuntu *
2+
* Copyright (C) 2005 by Tim Sutton *
3+
* aps02ts@macbuntu *
44
* *
55
* This program is free software; you can redistribute it and/or modify *
66
* it under the terms of the GNU General Public License as published by *
@@ -62,13 +62,8 @@ class QgsLegendItem : public QTreeWidgetItem, public QObject
6262
NO_ACTION //do nothing
6363
};
6464

65-
virtual bool isLeafNode() = 0;
6665
virtual LEGEND_ITEM_TYPE type() const {return mType;}
67-
/**Returns the type of action that will be done if a drag, originating at a certain
68-
item type, will be released at this item*/
69-
virtual DRAG_ACTION accept( LEGEND_ITEM_TYPE type ) = 0;
70-
/**Retrns the type of action that will be done if a legend item is dragged over this item*/
71-
virtual DRAG_ACTION accept( const QgsLegendItem* li ) const = 0;
66+
7267
/**Subclasses which allow insertion of other items may implement this method.
7368
@param theItem legend item to insert into this item
7469
@param changesettings Some insert actions may change the state of the layers or the map canvas.
@@ -111,7 +106,6 @@ class QgsLegendItem : public QTreeWidgetItem, public QObject
111106
virtual void release( QgsLegendItem* formerChild ) {}
112107

113108
protected:
114-
bool mLeafNodeFlag;
115109
LEGEND_ITEM_TYPE mType;
116110
/**Stores expanded property when storeAppearanceSettings is called*/
117111
bool mExpanded;

‎src/app/legend/qgslegendlayer.cpp

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -99,48 +99,6 @@ void QgsLegendLayer::setupFont() //private method
9999
setFont( 0, myFont );
100100
}
101101

102-
bool QgsLegendLayer::isLeafNode()
103-
{
104-
return false;
105-
}
106-
107-
QgsLegendItem::DRAG_ACTION QgsLegendLayer::accept( LEGEND_ITEM_TYPE type )
108-
{
109-
if ( type == LEGEND_LAYER || type == LEGEND_GROUP )
110-
{
111-
return REORDER;
112-
}
113-
else
114-
{
115-
return NO_ACTION;
116-
}
117-
}
118-
119-
QgsLegendItem::DRAG_ACTION QgsLegendLayer::accept( const QgsLegendItem* li ) const
120-
{
121-
if ( li && li != this )
122-
{
123-
LEGEND_ITEM_TYPE type = li->type();
124-
if ( type == LEGEND_LAYER )
125-
{
126-
//if(parent() == li->parent())
127-
//{
128-
return REORDER;
129-
//}
130-
}
131-
else if ( type == LEGEND_GROUP )
132-
{
133-
//only parent legend layers can change positions with groups
134-
if ( parent() == 0 )
135-
{
136-
return REORDER;
137-
}
138-
}
139-
}
140-
return NO_ACTION;
141-
}
142-
143-
144102
QgsMapLayer* QgsLegendLayer::layer()
145103
{
146104
return mLyr.layer();
@@ -456,7 +414,8 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
456414
saveSelectionAsAction->setEnabled( false );
457415
}
458416

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

461420
theMenu.addSeparator();
462421
}

‎src/app/legend/qgslegendlayer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ class QgsLegendLayer : public QgsLegendItem
4848
QgsLegendLayer( QgsMapLayer* layer );
4949
~QgsLegendLayer();
5050

51-
bool isLeafNode();
52-
QgsLegendItem::DRAG_ACTION accept( LEGEND_ITEM_TYPE type );
53-
QgsLegendItem::DRAG_ACTION accept( const QgsLegendItem* li ) const;
5451
/**Returns the map layer associated the item*/
5552
QgsMapLayer* layer();
5653
QgsMapCanvasLayer& canvasLayer();

0 commit comments

Comments
 (0)
Please sign in to comment.