QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsmaplayerlegend.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayerlegend.cpp
3  --------------------------------------
4  Date : July 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsmaplayerlegend.h"
17 
18 #include <QSettings>
19 
20 #include "qgslayertree.h"
22 #include "qgspluginlayer.h"
23 #include "qgsrasterlayer.h"
24 #include "qgsrendererv2.h"
25 #include "qgsvectorlayer.h"
26 
27 
29  QObject( parent )
30 {
31 }
32 
34 {
35  return new QgsDefaultVectorLayerLegend( vl );
36 }
37 
39 {
40  return new QgsDefaultRasterLayerLegend( rl );
41 }
42 
44 {
45  return new QgsDefaultPluginLayerLegend( pl );
46 }
47 
48 // -------------------------------------------------------------------------
49 
50 
51 void QgsMapLayerLegendUtils::setLegendNodeOrder( QgsLayerTreeLayer* nodeLayer, const QList<int>& order )
52 {
53  QStringList orderStr;
54  foreach ( int id, order )
55  orderStr << QString::number( id );
56  QString str = orderStr.isEmpty() ? "empty" : orderStr.join( "," );
57 
58  nodeLayer->setCustomProperty( "legend/node-order", str );
59 }
60 
62 {
63  // this is not particularly efficient way of finding out number of legend nodes
64  QList<QgsLayerTreeModelLegendNode*> lst = nodeLayer->layer()->legend()->createLayerTreeModelLegendNodes( nodeLayer );
65  int numNodes = lst.count();
66  qDeleteAll( lst );
67  return numNodes;
68 }
69 
70 static QList<int> _makeNodeOrder( QgsLayerTreeLayer* nodeLayer )
71 {
72  if ( !nodeLayer->layer() || !nodeLayer->layer()->legend() )
73  {
74  QgsDebugMsg( "Legend node order manipulation is invalid without existing legend" );
75  return QList<int>();
76  }
77 
78  int numNodes = _originalLegendNodeCount( nodeLayer );
79 
80  QList<int> order;
81  for ( int i = 0; i < numNodes; ++i )
82  order << i;
83  return order;
84 }
85 
87 {
88  QString orderStr = nodeLayer->customProperty( "legend/node-order" ).toString();
89 
90  if ( orderStr.isEmpty() )
91  return _makeNodeOrder( nodeLayer );
92 
93  if ( orderStr == "empty" )
94  return QList<int>();
95 
96  int numNodes = _originalLegendNodeCount( nodeLayer );
97 
98  QList<int> lst;
99  foreach ( QString item, orderStr.split( "," ) )
100  {
101  bool ok;
102  int id = item.toInt( &ok );
103  if ( !ok || id < 0 || id >= numNodes )
104  return _makeNodeOrder( nodeLayer );
105 
106  lst << id;
107  }
108 
109  return lst;
110 }
111 
113 {
114  return nodeLayer->customProperties().contains( "legend/node-order" );
115 }
116 
117 void QgsMapLayerLegendUtils::setLegendNodeUserLabel( QgsLayerTreeLayer* nodeLayer, int originalIndex, const QString& newLabel )
118 {
119  nodeLayer->setCustomProperty( "legend/label-" + QString::number( originalIndex ), newLabel );
120 }
121 
122 QString QgsMapLayerLegendUtils::legendNodeUserLabel( QgsLayerTreeLayer* nodeLayer, int originalIndex )
123 {
124  return nodeLayer->customProperty( "legend/label-" + QString::number( originalIndex ) ).toString();
125 }
126 
128 {
129  return nodeLayer->customProperties().contains( "legend/label-" + QString::number( originalIndex ) );
130 }
131 
132 
133 void QgsMapLayerLegendUtils::applyLayerNodeProperties( QgsLayerTreeLayer* nodeLayer, QList<QgsLayerTreeModelLegendNode*>& nodes )
134 {
135  // handle user labels
136  int i = 0;
137  foreach ( QgsLayerTreeModelLegendNode* legendNode, nodes )
138  {
139  QString userLabel = QgsMapLayerLegendUtils::legendNodeUserLabel( nodeLayer, i++ );
140  if ( !userLabel.isNull() )
141  legendNode->setUserLabel( userLabel );
142  }
143 
144  // handle user order of nodes
146  {
147  QList<int> order = QgsMapLayerLegendUtils::legendNodeOrder( nodeLayer );
148 
149  QList<QgsLayerTreeModelLegendNode*> newOrder;
150  QSet<int> usedIndices;
151  foreach ( int idx, order )
152  {
153  if ( usedIndices.contains( idx ) )
154  {
155  QgsDebugMsg( "invalid node order. ignoring." );
156  return;
157  }
158 
159  newOrder << nodes[idx];
160  usedIndices << idx;
161  }
162 
163  // delete unused nodes
164  for ( int i = 0; i < nodes.count(); ++i )
165  {
166  if ( !usedIndices.contains( i ) )
167  delete nodes[i];
168  }
169 
170  nodes = newOrder;
171  }
172 
173 }
174 
175 // -------------------------------------------------------------------------
176 
177 
179  : mLayer( vl )
180 {
181  connect( mLayer, SIGNAL( rendererChanged() ), this, SIGNAL( itemsChanged() ) );
182 }
183 
185 {
186  QList<QgsLayerTreeModelLegendNode*> nodes;
187 
189  if ( !r )
190  return nodes;
191 
192  if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toBool() )
194 
195  QSettings settings;
196  if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() && !r->legendClassificationAttribute().isEmpty() )
197  {
198  nodes.append( new QgsSimpleLegendNode( nodeLayer, r->legendClassificationAttribute() ) );
199  }
200 
201  foreach ( const QgsLegendSymbolItemV2& i, r->legendSymbolItemsV2() )
202  {
203  nodes.append( new QgsSymbolV2LegendNode( nodeLayer, i ) );
204  }
205 
206  if ( nodes.count() == 1 && nodes[0]->data( Qt::EditRole ).toString().isEmpty() )
207  nodes[0]->setEmbeddedInParent( true );
208 
209  return nodes;
210 }
211 
212 
213 
214 // -------------------------------------------------------------------------
215 
216 
218  : mLayer( rl )
219 {
220  connect( mLayer, SIGNAL( rendererChanged() ), this, SIGNAL( itemsChanged() ) );
221 }
222 
224 {
225  QList<QgsLayerTreeModelLegendNode*> nodes;
226 
227  // temporary solution for WMS. Ideally should be done with a delegate.
228  if ( mLayer->providerType() == "wms" )
229  {
230  QImage legendGraphic = mLayer->dataProvider()->getLegendGraphic();
231  if ( !legendGraphic.isNull() )
232  {
233  QgsDebugMsg( QString( "downloaded legend with dimension width:" ) + QString::number( legendGraphic.width() ) + QString( " and Height:" ) + QString::number( legendGraphic.height() ) );
234  nodes << new QgsImageLegendNode( nodeLayer, legendGraphic );
235  }
236  }
237 
238  QgsLegendColorList rasterItemList = mLayer->legendSymbologyItems();
239  if ( rasterItemList.count() == 0 )
240  return nodes;
241 
242  // Paletted raster may have many colors, for example UInt16 may have 65536 colors
243  // and it is very slow, so we limit max count
244  int count = 0;
245  int max_count = 1000;
246 
247  for ( QgsLegendColorList::const_iterator itemIt = rasterItemList.constBegin();
248  itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
249  {
250  nodes << new QgsRasterSymbolLegendNode( nodeLayer, itemIt->second, itemIt->first );
251 
252  if ( count == max_count )
253  {
254  QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
255  nodes << new QgsSimpleLegendNode( nodeLayer, label );
256  break;
257  }
258  }
259 
260  return nodes;
261 }
262 
263 
264 // -------------------------------------------------------------------------
265 
266 
268  : mLayer( pl )
269 {
270 }
271 
273 {
274  QList<QgsLayerTreeModelLegendNode*> nodes;
275 
276  QSize iconSize( 16, 16 );
277  QgsLegendSymbologyList symbologyList = mLayer->legendSymbologyItems( iconSize );
278 
279  if ( symbologyList.count() == 0 )
280  return nodes;
281 
282  typedef QPair<QString, QPixmap> XY;
283  foreach ( XY item, symbologyList )
284  {
285  nodes << new QgsSimpleLegendNode( nodeLayer, item.first, QIcon( item.second ) );
286  }
287 
288  return nodes;
289 }
290 
Implementation of legend node interface for displaying arbitrary raster image.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static void setLegendNodeOrder(QgsLayerTreeLayer *nodeLayer, const QList< int > &order)
static QgsMapLayerLegend * defaultPluginLegend(QgsPluginLayer *pl)
Create new legend implementation for raster layer.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
static void setLegendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QString &newLabel)
virtual QgsLegendSymbologyList legendSymbologyItems(const QSize &iconSize)
return a list of symbology items for the legend (defult implementation returns nothing) ...
QgsMapLayer * layer() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
Base class for plugin layers.
virtual QList< QgsLayerTreeModelLegendNode * > createLayerTreeModelLegendNodes(QgsLayerTreeLayer *nodeLayer)
Return list of legend nodes to be used for a particular layer tree layer node.
QStringList customProperties() const
Return list of keys stored in custom properties.
Implementation of legend node interface for displaying raster legend entries.
static QList< int > legendNodeOrder(QgsLayerTreeLayer *nodeLayer)
QgsDefaultPluginLayerLegend(QgsPluginLayer *pl)
Default legend implementation for raster layers.
static bool hasLegendNodeOrder(QgsLayerTreeLayer *nodeLayer)
QgsDefaultVectorLayerLegend(QgsVectorLayer *vl)
static int _originalLegendNodeCount(QgsLayerTreeLayer *nodeLayer)
virtual QString legendClassificationAttribute() const
If supported by the renderer, return classification attribute for the use in legend.
static QString legendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex)
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
static bool hasLegendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex)
Implementation of legend node interface for displaying arbitrary label with icon. ...
QList< QPair< QString, QPixmap > > QgsLegendSymbologyList
static void applyLayerNodeProperties(QgsLayerTreeLayer *nodeLayer, QList< QgsLayerTreeModelLegendNode * > &nodes)
update according to layer node's custom properties (order of items, user labels for items) ...
bool countSymbolFeatures(bool showProgress=true)
Count features for symbols.
static QgsMapLayerLegend * defaultVectorLegend(QgsVectorLayer *vl)
Create new legend implementation for vector layer.
virtual QImage getLegendGraphic(double scale=0, bool forceRefresh=false)
Returns the legend rendered as pixmap useful for that layer that need to get legend layer remotly as ...
QgsMapLayerLegend * legend() const
Can be null.
QList< QPair< QString, QColor > > QgsLegendColorList
void itemsChanged()
Emitted when existing items/nodes got invalid and should be replaced by new ones. ...
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
virtual QList< QgsLayerTreeModelLegendNode * > createLayerTreeModelLegendNodes(QgsLayerTreeLayer *nodeLayer)
Return list of legend nodes to be used for a particular layer tree layer node.
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const
Return a list of symbology items for the legend.
QgsDefaultRasterLayerLegend(QgsRasterLayer *rl)
Default legend implementation for plugin layers.
static QList< int > _makeNodeOrder(QgsLayerTreeLayer *nodeLayer)
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
QgsMapLayerLegend(QObject *parent=0)
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
virtual QList< QgsLayerTreeModelLegendNode * > createLayerTreeModelLegendNodes(QgsLayerTreeLayer *nodeLayer)
Return list of legend nodes to be used for a particular layer tree layer node.
QgsRasterDataProvider * dataProvider()
Returns the data provider.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
Default legend implementation for vector layers.
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
Represents a vector layer which manages a vector based data sets.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
virtual QList< QgsLayerTreeModelLegendNode * > createLayerTreeModelLegendNodes(QgsLayerTreeLayer *nodeLayer)=0
Return list of legend nodes to be used for a particular layer tree layer node.
virtual void setUserLabel(const QString &userLabel)
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node.
Layer tree node points to a map layer.
#define tr(sourceText)