QGIS API Documentation  2.8.2-Wien
 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 
188  QgsFeatureRendererV2* r = mLayer->rendererV2();
189  if ( !r )
190  return nodes;
191 
192  if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toBool() )
193  mLayer->countSymbolFeatures();
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  nodes << new QgsWMSLegendNode( nodeLayer );
231  }
232 
233  QgsLegendColorList rasterItemList = mLayer->legendSymbologyItems();
234  if ( rasterItemList.count() == 0 )
235  return nodes;
236 
237  // Paletted raster may have many colors, for example UInt16 may have 65536 colors
238  // and it is very slow, so we limit max count
239  int count = 0;
240  int max_count = 1000;
241 
242  for ( QgsLegendColorList::const_iterator itemIt = rasterItemList.constBegin();
243  itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
244  {
245  nodes << new QgsRasterSymbolLegendNode( nodeLayer, itemIt->second, itemIt->first );
246 
247  if ( count == max_count )
248  {
249  QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
250  nodes << new QgsSimpleLegendNode( nodeLayer, label );
251  break;
252  }
253  }
254 
255  return nodes;
256 }
257 
258 
259 // -------------------------------------------------------------------------
260 
261 
263  : mLayer( pl )
264 {
265 }
266 
268 {
269  QList<QgsLayerTreeModelLegendNode*> nodes;
270 
271  QSize iconSize( 16, 16 );
272  QgsLegendSymbologyList symbologyList = mLayer->legendSymbologyItems( iconSize );
273 
274  if ( symbologyList.count() == 0 )
275  return nodes;
276 
277  typedef QPair<QString, QPixmap> XY;
278  foreach ( XY item, symbologyList )
279  {
280  nodes << new QgsSimpleLegendNode( nodeLayer, item.first, QIcon( item.second ) );
281  }
282 
283  return nodes;
284 }
285