1
/***************************************************************************
2
qgslegend.h - description
4
begin : Sun Jul 28 2002
5
copyright : (C) 2002 by Gary E.Sherman
6
email : sherman at mrcc dot com
7
Romans 3:23=>Romans 6:23=>Romans 10:9,10=>Romans 12
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
26
#include <QTreeWidget>
37
class QTreeWidgetItem;
41
\brief A Legend treeview for QGIS
42
Map legend is a specialised QListView designed to show grooups of map layers,
43
map layers, and the map layer members, properties and symbols for each layer.
45
The legend supports simple operations such as displaying an ordered list of
46
layers in the current canvas, and complex operations such as drag/dropping
47
layer symbologies and properties between layers.
49
There are a variety of different items that can appear in a QgsLegend. All
50
items added to a QgsLegend should be inherited from QgsLegendItem as this
51
will ensure that they can perform legend specific tasks such as seeing if
52
dropping of other items onto them is allowed, returning their type etc.
54
The following types are defined:
56
<li>QgsLegendGroup - a group folder for many layers (can include other groups)</li>
57
<li>QgsLegendLayer - a layer that contains one or more files associated with it.
58
allowing more than one file lets you create virtual layers where
59
1 or more files can share the same symbology and properties
60
and be treated as they are one layer for things such as hiding /
61
showing, scale dependent visibility etc.</li>
62
<li>QgsLegendSymbologyGroup - a collabsable node that contains symbology items. Can
63
only exist inside of a QgsLegendLayer</li>
64
<li>QgsLegendSymbologyItem - a class break (vector) or pallette entry (raster) etc.
65
Double clicking on a symbology item will let you change
66
the properties for only that specific item. Can only exist
67
inside a symbology group.</li>
68
<li>QgsLegendPropertyGroup - a collapsable node that shows 1 or more properties. Can
69
only exist inside of a QgsLegendLayer</li>
70
<li>QgsLegendPropertyItem - A list of properties related to the layer. Double clicking
71
a property item will invoke a dialog that will let you change
72
the property settings. Can only exist inside a property group</li>
74
@note Additional group types may be defined in the future to accommodate WMS, PostGIS etc layers.
75
@author Gary E.Sherman, Tim Sutton, Marco Hugentobler and Jens Oberender
78
class QgsLegend : public QTreeWidget
82
// Moved here to match access of declaration later in file.
83
// Previous location raised a warning in msvc as the forward
84
// declaration was public while the definition was private
85
class QgsLegendPixmaps;
90
* @param qgis_app link to qgisapp
91
* @param theParent An optional parent widget
92
* @param theName An optional name for the widget
94
QgsLegend( QWidget * parent = 0, const char *name = 0 );
99
/** Returns QgsLegendLayer associated with current layer */
100
QgsLegendLayer* currentLegendLayer();
102
/*!Returns the current layer if the current item is a QgsLegendLayer.
103
If the current item is a QgsLegendLayer, its first maplayer is returned.
104
Else, 0 is returned.*/
105
QgsMapLayer* currentLayer();
107
/*!set the current layer
108
returns true if the layer exists, false otherwise*/
109
bool setCurrentLayer( QgsMapLayer *layer );
111
/**Writes the content of the legend to a project file*/
112
bool writeXML( QDomNode & layer_node, QDomDocument & document );
114
/**Restores the legend from a project file*/
115
bool readXML( QDomNode& legendnode );
117
/**Returns true, if the y-coordinate is >= the center of the item*/
118
bool yCoordAboveCenter( QgsLegendItem* it, int ycoord );
120
/**Returns true, if the item at index is a QgsLegendGroup*/
121
bool isLegendGroup( const QModelIndex &index );
123
/**Returns a string list of groups*/
124
QStringList groups();
126
/**Returns the first item in the hierarchy*/
127
QTreeWidgetItem* firstItem();
129
/**Returns the next item (next sibling or next item on level above)*/
130
QTreeWidgetItem* nextItem( QTreeWidgetItem* item );
132
/**Returns the next sibling of an item or 0 if there is none*/
133
QTreeWidgetItem* nextSibling( QTreeWidgetItem* item );
135
/**Returns the previous sibling of an item or 0 if there is none*/
136
QTreeWidgetItem* previousSibling( QTreeWidgetItem* item );
138
/**Finds the next dom node. This function is used by QgsLegend, but probably its not a good place here*/
139
static QDomNode nextDomNode( const QDomNode& theNode );
141
/**Inserts an item into another one. Stores the item specific settings of the moved item (and its subitems)
142
and applies it afterwards again*/
143
void insertItem( QTreeWidgetItem* move, QTreeWidgetItem* into );
145
/**Moves an item after another one. Stores the item specific settings of the moved item (and its subitems)
146
and applies it afterwards again*/
147
void moveItem( QTreeWidgetItem* move, QTreeWidgetItem* after );
149
/**Removes an item from the legend. This is e.g. necessary before shifting it to another place*/
150
void removeItem( QTreeWidgetItem* item );
152
/**Returns the ids of the layers contained in this legend. The order is bottom->top*/
153
std::deque<QString> layerIDs();
155
/**Updates layer set of map canvas*/
156
void updateMapCanvasLayerSet();
158
/**Updates overview*/
159
void updateOverview();
161
/**Show/remove all layer in/from overview*/
162
void enableOverviewModeAllLayers( bool isInOverview );
164
/**Adds an entry to mPixmapWidthValues*/
165
void addPixmapWidthValue( int width );
167
/**Adds an entry to mPixmapHeightValues*/
168
void addPixmapHeightValue( int height );
170
/**Removes an entry from mPixmapWidthValues*/
171
void removePixmapWidthValue( int width );
173
/**Removes an entry from mPixmapHeightValues*/
174
void removePixmapHeightValue( int height );
176
/**Sets the toggle editing action. Usually called from QgisApp*/
177
void setToggleEditingAction( QAction* editingAction ) {mToggleEditingAction = editingAction;}
179
/**Returns structure with legend pixmaps*/
180
QgsLegendPixmaps& pixmaps() { return mPixmaps; }
183
void updateCheckStates( QTreeWidgetItem* item, Qt::CheckState state ) { item->setData( 0, Qt::UserRole, state ); }
187
/*!Adds a new layer group with the maplayer to the canvas*/
188
void addLayer( QgsMapLayer * layer );
190
void setMapCanvas( QgsMapCanvas * canvas ) {mMapCanvas = canvas;}
192
/**Updates symbology items for a layer*/
193
void refreshLayerSymbology( QString key, bool expandItem = true );
196
* Slot called to clear the tree of all items
197
* @note Usually connected to a QgsMapCanvas that will ask its legend to clear itself.
203
* Called when the user wishes to toggle on or off all of the layers in
204
* the legend, and in the map.
207
void selectAll( bool select );
210
* Slot called when user wishes to add a new empty layer group to the legend.
211
* The user will be prompted for the name of the newly added group.
212
* @param name name of the new group
213
* @param expand expand the group
216
int addGroup( QString name = QString(), bool expand = true );
219
* Removes all groups with the given name.
220
* @param name name of the groups to remove
223
void removeGroup( int groupIndex );
225
void removeLayer( QString );
227
/** called to read legend settings from project */
228
void readProject( const QDomDocument & );
230
/** called to write legend settings to project */
231
void writeProject( QDomDocument & );
233
/**Removes the current LegendLayer*/
234
void removeCurrentLayer();
236
/**Removes a layer. If the layer is editable, a dialog is shown where user can select 'save', 'discard' and optionally 'cancel'. Cancel
237
is useful if a single layer is removed whereas on closing of the whole project or application, the cancel option may not be possible
238
@param ml the maplayer to remove
239
@param askCancelOnEditable gibe cancel option in the dialog for editable (and changed) layers
240
@param return false if canceled or in case of error, true else*/
241
bool removeLayer( QgsMapLayer* ml, bool askCancelOnEditable );
244
* Moves a layer to a group.
245
* @param ml the maplayer to move
246
* @param groupIndex index of group
247
* @return false if the group does not exist, false otherwise
249
void moveLayer( QgsMapLayer* ml, int groupIndex );
251
/**Toggle show in overview for current layer*/
252
void legendLayerShowInOverview();
254
/**Zooms to extent of the current legend layer (considers there may be several
256
void legendLayerZoom();
258
/***Zooms so that the pixels of the raster layer occupies exactly one screen pixel.
259
Only works on raster layers*/
260
void legendLayerZoomNative();
262
/**Show attribute table*/
263
void legendLayerAttributeTable();
265
/**Shows the property dialog of the first legend layer file in a legend layer*/
266
void legendLayerShowProperties();
270
/*!Event handler for mouse movements.
271
* Mainly intended so handle cases where user is dragging and dropping
272
* items into or out of groups, or is reordering layers.
273
* @note Overrides method of the same name in the QListView class.
276
void mouseMoveEvent( QMouseEvent * e );
279
* Event handler for buton mouse presses.
280
* Mainly intended so handle cases where user is dragging and dropping
281
* items into or out of groups, or is reordering layers.
282
* @note Overrides method of the same name in the QListView class.
285
void mousePressEvent( QMouseEvent * e );
288
* Event handler for mouse button releases.
289
* Mainly intended so handle cases where user is dragging and dropping
290
* items into or out of groups, or is reordering layers. Each sublass of
291
* QgsLegendItem has an accept method that defines behaviour rules for
292
* whether another QgsLegendItem child instance can be dropped onto it.
293
* <h1>Behaviour rules for dropped legend items</h1>
295
* <li> Symbology groups, properies groups and layers groups can only be dropped
296
* onto QgsLegendLayer nodes. </li>
297
* <li>Only QgsLegendGroup and QgsLegendLayer can be top level items in the view</li>
298
* <li>Groups can be nested by dropping them into each other,</li>
299
* <li>Each group can have one or more layers</li>
300
* <li>Layers can be ordered by dragging them above or below another layer.</li>
301
* <li>The order for QgsLegendSymbologyGroup, QgsLegendPropertyGroup and QgsLegendLayerGroup
302
* is predefined to sort in that order.</li>
304
* @note Overrides method of the same name in the QListView class.
307
void mouseReleaseEvent( QMouseEvent * e );
308
void mouseDoubleClickEvent( QMouseEvent* e );
310
/**Stores the necessary information about the position of an item in the hierarchy. Afterwards,
311
this item may be moved back to the original position with resetToInitialPosition()*/
312
void storeInitialPosition( QTreeWidgetItem* li );
314
/**Moves an item back to the position where storeInitialPosition has been called*/
315
void resetToInitialPosition( QTreeWidgetItem* li );
317
/**Returns the legend layer to which a map layer belongs to*/
318
QgsLegendLayer* findLegendLayer( const QString& layerKey );
320
/**Returns the legend layer to which a map layer belongs to*/
321
QgsLegendLayer* findLegendLayer( const QgsMapLayer *layer );
323
/**Checks mPixmapWidthValues and mPixmapHeightValues and sets a new icon size if necessary*/
324
void adjustIconSize();
326
/**Initialize pixmaps - called when QgsLegend is constructed */
329
/**This function compares the layer order before a drag with the current layer ordering and triggers a canvas repaint if it has changed*/
330
bool checkLayerOrderUpdate();
332
/**The target that the mouse is over when dragging */
333
QTreeWidgetItem *mDropTarget;
335
enum DROP_ACTION_TYPE
342
/** Set when mouse is moved over different kind of items, depending opn what they accept() */
343
DROP_ACTION_TYPE mDropAction;
345
/** Hide the line that indicates insertion position */
348
/** Show the line that indicates insertion position */
349
void showLine( int y, int left );
351
/** Update the widget with latest changes immediately */
352
void updateLineWidget();
354
/** Returns the last visible item in the tree widget */
355
QTreeWidgetItem *lastVisibleItem();
357
/** read layer settings from XML element and add item */
358
QgsLegendLayer* readLayerFromXML( QDomElement& childelem, bool& isOpen );
362
/**Calls 'handleRightClickEvent' on the item*/
363
void handleRightClickEvent( QTreeWidgetItem* item, const QPoint& position );
364
/**Removes the current legend group*/
365
void legendGroupRemove();
366
/**Removes a legend group and its layers*/
367
void removeGroup( QgsLegendGroup * lg );
368
/**Sets all listview items to open*/
370
/**Sets all listview items to closed*/
373
void handleItemChange( QTreeWidgetItem* item, int row );
374
/** delegates current layer to map canvas */
375
void handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous );
376
/**Calls openPersistentEditor for the current item*/
378
/**Removes the current item and inserts it as a toplevel item at the end of the legend*/
379
void makeToTopLevelItem();
383
/*! Prevent the copying of QgsLegends
384
* @todo See if this is really required - we may want multiple map, canvas and
385
legend support at some stage in the future.
387
QgsLegend( QgsLegend const & );
390
* Prevent the copying of QgsLegends
391
* @todo See if this is really required - we may want multiple map, canvas and
392
legend support at some stage in the future.
394
QgsLegend & operator=( QgsLegend const & );
397
* Position of mouse when it is pressed at the start of a drag event.
399
QPoint mLastPressPos;
401
/**True if the mouse is pressed*/
402
bool mMousePressedFlag;
404
/// keep track of the Item being dragged
405
QTreeWidgetItem* mItemBeingMoved;
408
* Position in the list of the item being moved as it was at the start of a drag event.
409
* An item at the top of the list will be 0 and each successive item below it
410
* will be 1,2 3 etc... regardless of nesting level.
412
int mItemBeingMovedOrigPos;
414
/**Information needed by 'storeInitialPosition' and 'resetToInitialPosition'*/
415
enum HIERARCHY_POSITION_TYPE
421
HIERARCHY_POSITION_TYPE mRestoreInformation;
422
QTreeWidgetItem* mRestoreItem;
424
/**Stores the layer ordering before a mouse Move. After the move, this is used to
425
decide if the mapcanvas really has to be refreshed*/
426
std::deque<QString> mLayersPriorToMove;
428
/**Action for the legendlayer right click menu*/
429
QAction* mToggleEditingAction;
432
* A function to determine how far down in the list an item is (starting with one for the first Item).
433
*If the item is not in the legend, -1 is returned
434
* @see mItemBeingMovedOrigPos
436
int getItemPos( QTreeWidgetItem* item );
438
/**Pointer to the main canvas. Used for requiring repaints in case of legend changes*/
439
QgsMapCanvas* mMapCanvas;
441
/**Stores the width values of the LegendSymbologyItem pixmaps. The purpose of this is that the legend may automatically change
442
the global IconWidth when items are added or removed*/
443
std::multiset<int> mPixmapWidthValues;
445
/**Stores the width values of the LegendSymbologyItem pixmaps. The purpose of this is that the legend may automatically change
446
the global IconWidth when items are added or removed*/
447
std::multiset<int> mPixmapHeightValues;
449
/**QgsLegend does not set the icon with/height to values lower than the minimum icon size*/
450
QSize mMinimumIconSize;
452
/** structure which holds pixmap which are used in legend */
453
class QgsLegendPixmaps
456
//! Pixmap which is shown by default
457
QPixmap mOriginalPixmap;
459
//! Pixmap to show a bogus vertex was encoutnered in this layer (applies to vector layers only)
460
QPixmap mProjectionErrorPixmap;
462
//! Pixmap to show if this layer is represented in overview or now
463
QPixmap mInOverviewPixmap;
465
//! Pixmap to show it this layer has currently editing turned on
466
QPixmap mEditablePixmap;
470
//! Widget that holds the indicator line //
471
QWidget *mInsertionLine;
474
void itemMoved( QModelIndex oldIndex, QModelIndex newIndex );
476
void zOrderChanged( QgsLegend * lv );
478
//! Emited whenever current (selected) layer changes
479
// the pointer to layer can be null if no layer is selected
480
void currentLayerChanged( QgsMapLayer * layer );