~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/app/legend/qgslegend.h

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                          qgslegend.h  -  description
 
3
                             -------------------
 
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
 ***************************************************************************/
 
9
 
 
10
/***************************************************************************
 
11
 *                                                                         *
 
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.                                   *
 
16
 *                                                                         *
 
17
 ***************************************************************************/
 
18
/* $Id$ */
 
19
 
 
20
#ifndef QGSLEGEND_H
 
21
#define QGSLEGEND_H
 
22
 
 
23
#include <deque>
 
24
#include <map>
 
25
#include <set>
 
26
#include <QTreeWidget>
 
27
 
 
28
class QgsLegendGroup;
 
29
class QgsLegendLayer;
 
30
class QgsLegendItem;
 
31
class QgsMapLayer;
 
32
class QgsMapCanvas;
 
33
class QDomDocument;
 
34
class QDomElement;
 
35
class QDomNode;
 
36
class QMouseEvent;
 
37
class QTreeWidgetItem;
 
38
 
 
39
/**
 
40
   \class QgsLegend
 
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.
 
44
 
 
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.
 
48
 
 
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.
 
53
 
 
54
   The following types are defined:
 
55
   <ul>
 
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>
 
73
   </ul>
 
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
 
76
*/
 
77
 
 
78
class QgsLegend : public QTreeWidget
 
79
{
 
80
    Q_OBJECT
 
81
  private:
 
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;
 
86
 
 
87
 
 
88
  public:
 
89
    /*! Constructor.
 
90
    * @param qgis_app link to qgisapp
 
91
    * @param theParent An optional parent widget
 
92
    * @param theName An optional name for the widget
 
93
    */
 
94
    QgsLegend( QWidget * parent = 0, const char *name = 0 );
 
95
 
 
96
    //! Destructor
 
97
    ~QgsLegend();
 
98
 
 
99
    /** Returns QgsLegendLayer associated with current layer */
 
100
    QgsLegendLayer* currentLegendLayer();
 
101
 
 
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();
 
106
 
 
107
    /*!set the current layer
 
108
    returns true if the layer exists, false otherwise*/
 
109
    bool setCurrentLayer( QgsMapLayer *layer );
 
110
 
 
111
    /**Writes the content of the legend to a project file*/
 
112
    bool writeXML( QDomNode & layer_node, QDomDocument & document );
 
113
 
 
114
    /**Restores the legend from a project file*/
 
115
    bool readXML( QDomNode& legendnode );
 
116
 
 
117
    /**Returns true, if the y-coordinate is >= the center of the item*/
 
118
    bool yCoordAboveCenter( QgsLegendItem* it, int ycoord );
 
119
 
 
120
    /**Returns true, if the item at index is a QgsLegendGroup*/
 
121
    bool isLegendGroup( const QModelIndex &index );
 
122
 
 
123
    /**Returns a string list of groups*/
 
124
    QStringList groups();
 
125
 
 
126
    /**Returns the first item in the hierarchy*/
 
127
    QTreeWidgetItem* firstItem();
 
128
 
 
129
    /**Returns the next item (next sibling or next item on level above)*/
 
130
    QTreeWidgetItem* nextItem( QTreeWidgetItem* item );
 
131
 
 
132
    /**Returns the next sibling of an item or 0 if there is none*/
 
133
    QTreeWidgetItem* nextSibling( QTreeWidgetItem* item );
 
134
 
 
135
    /**Returns the previous sibling of an item or 0 if there is none*/
 
136
    QTreeWidgetItem* previousSibling( QTreeWidgetItem* item );
 
137
 
 
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 );
 
140
 
 
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 );
 
144
 
 
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 );
 
148
 
 
149
    /**Removes an item from the legend. This is e.g. necessary before shifting it to another place*/
 
150
    void removeItem( QTreeWidgetItem* item );
 
151
 
 
152
    /**Returns the ids of the layers contained in this legend. The order is bottom->top*/
 
153
    std::deque<QString> layerIDs();
 
154
 
 
155
    /**Updates layer set of map canvas*/
 
156
    void updateMapCanvasLayerSet();
 
157
 
 
158
    /**Updates overview*/
 
159
    void updateOverview();
 
160
 
 
161
    /**Show/remove all layer in/from overview*/
 
162
    void enableOverviewModeAllLayers( bool isInOverview );
 
163
 
 
164
    /**Adds an entry to mPixmapWidthValues*/
 
165
    void addPixmapWidthValue( int width );
 
166
 
 
167
    /**Adds an entry to mPixmapHeightValues*/
 
168
    void addPixmapHeightValue( int height );
 
169
 
 
170
    /**Removes an entry from mPixmapWidthValues*/
 
171
    void removePixmapWidthValue( int width );
 
172
 
 
173
    /**Removes an entry from mPixmapHeightValues*/
 
174
    void removePixmapHeightValue( int height );
 
175
 
 
176
    /**Sets the toggle editing action. Usually called from QgisApp*/
 
177
    void setToggleEditingAction( QAction* editingAction ) {mToggleEditingAction = editingAction;}
 
178
 
 
179
    /**Returns structure with legend pixmaps*/
 
180
    QgsLegendPixmaps& pixmaps() { return mPixmaps; }
 
181
 
 
182
 
 
183
    void updateCheckStates( QTreeWidgetItem* item, Qt::CheckState state ) { item->setData( 0, Qt::UserRole, state ); }
 
184
 
 
185
  public slots:
 
186
 
 
187
    /*!Adds a new layer group with the maplayer to the canvas*/
 
188
    void addLayer( QgsMapLayer * layer );
 
189
 
 
190
    void setMapCanvas( QgsMapCanvas * canvas ) {mMapCanvas = canvas;}
 
191
 
 
192
    /**Updates symbology items for a layer*/
 
193
    void refreshLayerSymbology( QString key, bool expandItem = true );
 
194
 
 
195
    /*!
 
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.
 
198
      * @return void
 
199
      */
 
200
    void removeAll();
 
201
 
 
202
    /*!
 
203
     * Called when the user wishes to toggle on or off all of the layers in
 
204
     * the legend, and in the map.
 
205
     * @return void
 
206
     */
 
207
    void selectAll( bool select );
 
208
 
 
209
    /*!
 
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
 
214
     * @return void
 
215
     */
 
216
    int addGroup( QString name = QString(), bool expand = true );
 
217
 
 
218
    /*!
 
219
     * Removes all groups with the given name.
 
220
     * @param name name of the groups to remove
 
221
     * @return void
 
222
     */
 
223
    void removeGroup( int groupIndex );
 
224
 
 
225
    void removeLayer( QString );
 
226
 
 
227
    /** called to read legend settings from project */
 
228
    void readProject( const QDomDocument & );
 
229
 
 
230
    /** called to write legend settings to project */
 
231
    void writeProject( QDomDocument & );
 
232
 
 
233
    /**Removes the current LegendLayer*/
 
234
    void removeCurrentLayer();
 
235
 
 
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 );
 
242
 
 
243
    /*!
 
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
 
248
     */
 
249
    void moveLayer( QgsMapLayer* ml, int groupIndex );
 
250
 
 
251
    /**Toggle show in overview for current layer*/
 
252
    void legendLayerShowInOverview();
 
253
 
 
254
    /**Zooms to extent of the current legend layer (considers there may be several
 
255
    legend layer files*/
 
256
    void legendLayerZoom();
 
257
 
 
258
    /***Zooms so that the pixels of the raster layer occupies exactly one screen pixel.
 
259
        Only works on raster layers*/
 
260
    void legendLayerZoomNative();
 
261
 
 
262
    /**Show attribute table*/
 
263
    void legendLayerAttributeTable();
 
264
 
 
265
    /**Shows the property dialog of the first legend layer file in a legend layer*/
 
266
    void legendLayerShowProperties();
 
267
 
 
268
  protected:
 
269
 
 
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.
 
274
     * @return void
 
275
     */
 
276
    void mouseMoveEvent( QMouseEvent * e );
 
277
 
 
278
    /*!
 
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.
 
283
     * @return void
 
284
     */
 
285
    void mousePressEvent( QMouseEvent * e );
 
286
 
 
287
    /*!
 
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>
 
294
     * <ul>
 
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>
 
303
     * </ul>
 
304
     * @note Overrides method of the same name in the QListView class.
 
305
     * @return void
 
306
     */
 
307
    void mouseReleaseEvent( QMouseEvent * e );
 
308
    void mouseDoubleClickEvent( QMouseEvent* e );
 
309
 
 
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 );
 
313
 
 
314
    /**Moves an item back to the position where storeInitialPosition has been called*/
 
315
    void resetToInitialPosition( QTreeWidgetItem* li );
 
316
 
 
317
    /**Returns the legend layer to which a map layer belongs to*/
 
318
    QgsLegendLayer* findLegendLayer( const QString& layerKey );
 
319
 
 
320
    /**Returns the legend layer to which a map layer belongs to*/
 
321
    QgsLegendLayer* findLegendLayer( const QgsMapLayer *layer );
 
322
 
 
323
    /**Checks mPixmapWidthValues and mPixmapHeightValues and sets a new icon size if necessary*/
 
324
    void adjustIconSize();
 
325
 
 
326
    /**Initialize pixmaps - called when QgsLegend is constructed */
 
327
    void initPixmaps();
 
328
 
 
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();
 
331
 
 
332
    /**The target that the mouse is over when dragging */
 
333
    QTreeWidgetItem *mDropTarget;
 
334
 
 
335
    enum DROP_ACTION_TYPE
 
336
    {
 
337
      BEFORE,
 
338
      AFTER,
 
339
      INTO_GROUP,
 
340
      NO_ACTION
 
341
    };
 
342
    /** Set when mouse is moved over different kind of items, depending opn what they accept() */
 
343
    DROP_ACTION_TYPE mDropAction;
 
344
 
 
345
    /** Hide the line that indicates insertion position */
 
346
    void hideLine();
 
347
 
 
348
    /** Show the line that indicates insertion position */
 
349
    void showLine( int y, int left );
 
350
 
 
351
    /** Update the widget with latest changes immediately */
 
352
    void updateLineWidget();
 
353
 
 
354
    /** Returns the last visible item in the tree widget */
 
355
    QTreeWidgetItem *lastVisibleItem();
 
356
 
 
357
    /** read layer settings from XML element and add item */
 
358
    QgsLegendLayer* readLayerFromXML( QDomElement& childelem, bool& isOpen );
 
359
 
 
360
  private slots:
 
361
 
 
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*/
 
369
    void expandAll();
 
370
    /**Sets all listview items to closed*/
 
371
    void collapseAll();
 
372
    /**Just for a test*/
 
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*/
 
377
    void openEditor();
 
378
    /**Removes the current item and inserts it as a toplevel item at the end of the legend*/
 
379
    void makeToTopLevelItem();
 
380
 
 
381
  private:
 
382
 
 
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.
 
386
    */
 
387
    QgsLegend( QgsLegend const & );
 
388
 
 
389
    /*!
 
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.
 
393
     */
 
394
    QgsLegend & operator=( QgsLegend const & );
 
395
 
 
396
    /*!
 
397
     * Position of mouse when it is pressed at the start of a drag event.
 
398
     */
 
399
    QPoint mLastPressPos;
 
400
 
 
401
    /**True if the mouse is pressed*/
 
402
    bool mMousePressedFlag;
 
403
 
 
404
    /// keep track of the Item being dragged
 
405
    QTreeWidgetItem* mItemBeingMoved;
 
406
 
 
407
    /*!
 
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.
 
411
     */
 
412
    int mItemBeingMovedOrigPos;
 
413
 
 
414
    /**Information needed by 'storeInitialPosition' and 'resetToInitialPosition'*/
 
415
    enum HIERARCHY_POSITION_TYPE
 
416
    {
 
417
      FIRST_ITEM,
 
418
      FIRST_CHILD,
 
419
      YOUNGER_SIBLING
 
420
    };
 
421
    HIERARCHY_POSITION_TYPE mRestoreInformation;
 
422
    QTreeWidgetItem* mRestoreItem;
 
423
 
 
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;
 
427
 
 
428
    /**Action for the legendlayer right click menu*/
 
429
    QAction* mToggleEditingAction;
 
430
 
 
431
    /*!
 
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
 
435
     */
 
436
    int getItemPos( QTreeWidgetItem* item );
 
437
 
 
438
    /**Pointer to the main canvas. Used for requiring repaints in case of legend changes*/
 
439
    QgsMapCanvas* mMapCanvas;
 
440
 
 
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;
 
444
 
 
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;
 
448
 
 
449
    /**QgsLegend does not set the icon with/height to values lower than the minimum icon size*/
 
450
    QSize mMinimumIconSize;
 
451
 
 
452
    /** structure which holds pixmap which are used in legend */
 
453
    class QgsLegendPixmaps
 
454
    {
 
455
      public:
 
456
        //! Pixmap which is shown by default
 
457
        QPixmap mOriginalPixmap;
 
458
 
 
459
        //! Pixmap to show a bogus vertex was encoutnered in this layer (applies to vector layers only)
 
460
        QPixmap mProjectionErrorPixmap;
 
461
 
 
462
        //! Pixmap to show if this layer is represented in overview or now
 
463
        QPixmap mInOverviewPixmap;
 
464
 
 
465
        //! Pixmap to show it this layer has currently editing turned on
 
466
        QPixmap mEditablePixmap;
 
467
 
 
468
    } mPixmaps;
 
469
 
 
470
    //! Widget that holds the indicator line //
 
471
    QWidget *mInsertionLine;
 
472
 
 
473
  signals:
 
474
    void itemMoved( QModelIndex oldIndex, QModelIndex newIndex );
 
475
 
 
476
    void zOrderChanged( QgsLegend * lv );
 
477
 
 
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 );
 
481
};
 
482
#endif