QGIS API Documentation  2.99.0-Master (08ee180)
qgscomposerlegenditem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerlegenditem.cpp - description
3  -------------------------
4  begin : May 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscomposerlegendstyle.h"
19 #include "qgscomposerlegenditem.h"
20 #include "qgscomposerlegend.h"
21 #include "qgsmaplayerregistry.h"
22 #include "qgsrasterlayer.h"
23 #include "qgsrenderer.h"
24 #include "qgssymbol.h"
25 #include "qgssymbollayerutils.h"
26 #include "qgsvectorlayer.h"
27 #include "qgsapplication.h"
28 #include <QDomDocument>
29 #include <QDomElement>
30 
32  , mStyle( s )
33 {
34 }
35 
36 QgsComposerLegendItem::QgsComposerLegendItem( const QString& text, QgsComposerLegendStyle::Style s ): QStandardItem( text )
37  , mStyle( s )
38 {
39 }
40 
41 QgsComposerLegendItem::QgsComposerLegendItem( const QIcon& icon, const QString& text, QgsComposerLegendStyle::Style s ): QStandardItem( icon, text )
42  , mStyle( s )
43 {
44 }
45 
47 {
48 }
49 
50 void QgsComposerLegendItem::writeXmlChildren( QDomElement& elem, QDomDocument& doc ) const
51 {
52  int numRows = rowCount();
53  QgsComposerLegendItem* currentItem = nullptr;
54  for ( int i = 0; i < numRows; ++i )
55  {
56  currentItem = dynamic_cast<QgsComposerLegendItem*>( child( i, 0 ) );
57  if ( currentItem )
58  {
59  currentItem->writeXml( elem, doc );
60  }
61  }
62 }
63 
64 
66 
67 
69 {
70 }
71 
72 QgsComposerSymbolItem::QgsComposerSymbolItem( const QString& text ): QgsComposerLegendItem( text, QgsComposerLegendStyle::Symbol ), mSymbol( nullptr )
73 {
74 }
75 
76 QgsComposerSymbolItem::QgsComposerSymbolItem( const QIcon& icon, const QString& text ): QgsComposerLegendItem( icon, text, QgsComposerLegendStyle::Symbol ), mSymbol( nullptr )
77 {
78 }
79 
81 {
82  delete mSymbol;
83 }
84 
85 QStandardItem* QgsComposerSymbolItem::clone() const
86 {
88  *cloneItem = *this;
89  if ( mSymbol )
90  {
91  cloneItem->setSymbol( mSymbol->clone() );
92  }
93  return cloneItem;
94 }
95 
96 void QgsComposerSymbolItem::writeXml( QDomElement& elem, QDomDocument& doc ) const
97 {
98  QDomElement vectorClassElem = doc.createElement( QStringLiteral( "VectorClassificationItemNg" ) );
99  if ( mSymbol )
100  {
101  QgsSymbolMap saveSymbolMap;
102  saveSymbolMap.insert( QStringLiteral( "classificationSymbol" ), mSymbol );
103  QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( saveSymbolMap, QStringLiteral( "symbols" ), doc );
104  vectorClassElem.appendChild( symbolsElem );
105  }
106  vectorClassElem.setAttribute( QStringLiteral( "text" ), text() );
107  vectorClassElem.setAttribute( QStringLiteral( "userText" ), userText() );
108  elem.appendChild( vectorClassElem );
109 }
110 
111 void QgsComposerSymbolItem::readXml( const QDomElement& itemElem, bool xServerAvailable )
112 {
113  if ( itemElem.isNull() )
114  {
115  return;
116  }
117 
118  setText( itemElem.attribute( QStringLiteral( "text" ), QLatin1String( "" ) ) );
119  setUserText( itemElem.attribute( QStringLiteral( "userText" ), QLatin1String( "" ) ) );
120  QDomElement symbolsElem = itemElem.firstChildElement( QStringLiteral( "symbols" ) );
121  if ( !symbolsElem.isNull() )
122  {
123  QgsSymbolMap loadSymbolMap = QgsSymbolLayerUtils::loadSymbols( symbolsElem );
124  //we assume there is only one symbol in the map...
125  QgsSymbolMap::iterator mapIt = loadSymbolMap.begin();
126  if ( mapIt != loadSymbolMap.end() )
127  {
128  QgsSymbol* symbolNg = mapIt.value();
129  if ( symbolNg )
130  {
131  setSymbol( symbolNg );
132  if ( xServerAvailable )
133  {
134  setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( symbolNg, QSize( 30, 30 ) ) );
135  }
136  }
137  }
138  }
139 }
140 
142 {
143  delete mSymbol;
144  mSymbol = s;
145 }
146 
148 
150 {
151 }
152 
154 {
155 }
156 
157 QgsComposerRasterSymbolItem::QgsComposerRasterSymbolItem( const QIcon& icon, const QString& text ): QgsComposerLegendItem( icon, text, QgsComposerLegendStyle::Symbol )
158 {
159 }
160 
162 {
163 }
164 
166 {
168  *cloneItem = *this;
169  cloneItem->setLayerId( mLayerID );
170  return cloneItem;
171 }
172 
173 void QgsComposerRasterSymbolItem::writeXml( QDomElement& elem, QDomDocument& doc ) const
174 {
175  QDomElement rasterClassElem = doc.createElement( QStringLiteral( "RasterClassificationItem" ) );
176  rasterClassElem.setAttribute( QStringLiteral( "layerId" ), mLayerID );
177  rasterClassElem.setAttribute( QStringLiteral( "text" ), text() );
178  rasterClassElem.setAttribute( QStringLiteral( "userText" ), userText() );
179  rasterClassElem.setAttribute( QStringLiteral( "color" ), mColor.name() );
180  elem.appendChild( rasterClassElem );
181 }
182 
183 void QgsComposerRasterSymbolItem::readXml( const QDomElement& itemElem, bool xServerAvailable )
184 {
185  if ( itemElem.isNull() )
186  {
187  return;
188  }
189  setText( itemElem.attribute( QStringLiteral( "text" ), QLatin1String( "" ) ) );
190  setUserText( itemElem.attribute( QStringLiteral( "userText" ), QLatin1String( "" ) ) );
191  setLayerId( itemElem.attribute( QStringLiteral( "layerId" ), QLatin1String( "" ) ) );
192  setColor( QColor( itemElem.attribute( QStringLiteral( "color" ) ) ) );
193 
194  if ( xServerAvailable )
195  {
196  QPixmap itemPixmap( 20, 20 );
197  itemPixmap.fill( mColor );
198  setIcon( QIcon( itemPixmap ) );
199  }
200 }
201 
203 
205  , mShowFeatureCount( false )
206 {
207 }
208 
210  , mShowFeatureCount( false )
211 {
212 }
213 
215 {
216 }
217 
218 QStandardItem* QgsComposerLayerItem::clone() const
219 {
220  QgsComposerLayerItem* cloneItem = new QgsComposerLayerItem();
221  *cloneItem = *this;
222  cloneItem->setLayerId( mLayerID );
223  return cloneItem;
224 }
225 
226 void QgsComposerLayerItem::writeXml( QDomElement& elem, QDomDocument& doc ) const
227 {
228  QDomElement layerItemElem = doc.createElement( QStringLiteral( "LayerItem" ) );
229  layerItemElem.setAttribute( QStringLiteral( "layerId" ), mLayerID );
230  layerItemElem.setAttribute( QStringLiteral( "text" ), text() );
231  layerItemElem.setAttribute( QStringLiteral( "userText" ), userText() );
232  layerItemElem.setAttribute( QStringLiteral( "showFeatureCount" ), showFeatureCount() );
233  layerItemElem.setAttribute( QStringLiteral( "style" ), QgsComposerLegendStyle::styleName( mStyle ) );
234  writeXmlChildren( layerItemElem, doc );
235  elem.appendChild( layerItemElem );
236 }
237 
238 void QgsComposerLayerItem::readXml( const QDomElement& itemElem, bool xServerAvailable )
239 {
240  if ( itemElem.isNull() )
241  {
242  return;
243  }
244  setText( itemElem.attribute( QStringLiteral( "text" ), QLatin1String( "" ) ) );
245  setUserText( itemElem.attribute( QStringLiteral( "userText" ), QLatin1String( "" ) ) );
246  setLayerId( itemElem.attribute( QStringLiteral( "layerId" ), QLatin1String( "" ) ) );
247  setShowFeatureCount( itemElem.attribute( QStringLiteral( "showFeatureCount" ), QLatin1String( "" ) ) == QLatin1String( "1" ) ? true : false );
248  setStyle( QgsComposerLegendStyle::styleFromName( itemElem.attribute( QStringLiteral( "style" ), QStringLiteral( "subgroup" ) ) ) );
249 
250  //now call readXml for all the child items
251  QDomNodeList childList = itemElem.childNodes();
252  QDomNode currentNode;
253  QDomElement currentElem;
254  QgsComposerLegendItem* currentChildItem = nullptr;
255 
256  int nChildItems = childList.count();
257  for ( int i = 0; i < nChildItems; ++i )
258  {
259  currentNode = childList.at( i );
260  if ( !currentNode.isElement() )
261  {
262  continue;
263  }
264 
265  currentElem = currentNode.toElement();
266  QString elemTag = currentElem.tagName();
267  if ( elemTag == QLatin1String( "VectorClassificationItem" ) )
268  {
269  continue; // legacy - unsupported
270  }
271  else if ( elemTag == QLatin1String( "VectorClassificationItemNg" ) )
272  {
273  currentChildItem = new QgsComposerSymbolItem();
274  }
275  else if ( elemTag == QLatin1String( "RasterClassificationItem" ) )
276  {
277  currentChildItem = new QgsComposerRasterSymbolItem();
278  }
279  else
280  {
281  continue; //unsupported child type
282  }
283  currentChildItem->readXml( currentElem, xServerAvailable );
284  appendRow( currentChildItem );
285  }
286 }
287 
288 void QgsComposerLayerItem::setDefaultStyle( double scaleDenominator, const QString& rule )
289 {
290  // set default style according to number of symbols
291  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId() ) );
292  if ( vLayer )
293  {
294  QgsFeatureRenderer* renderer = vLayer->renderer();
295  if ( renderer )
296  {
297  QPair<QString, QgsSymbol*> symbolItem = renderer->legendSymbolItems( scaleDenominator, rule ).value( 0 );
298  if ( renderer->legendSymbolItems( scaleDenominator, rule ).size() > 1 || !symbolItem.first.isEmpty() )
299  {
301  }
302  else
303  {
304  // Hide title by default for single symbol
306  }
307  }
308  }
309 }
310 
312 
314 {
315 }
316 
318 {
319 }
320 
322 {
323 }
324 
325 QStandardItem* QgsComposerGroupItem::clone() const
326 {
327  QgsComposerGroupItem* cloneItem = new QgsComposerGroupItem();
328  *cloneItem = *this;
329  return cloneItem;
330 }
331 
332 void QgsComposerGroupItem::writeXml( QDomElement& elem, QDomDocument& doc ) const
333 {
334  QDomElement layerGroupElem = doc.createElement( QStringLiteral( "GroupItem" ) );
335  // text is always user text, but for forward compatibility for now write both
336  layerGroupElem.setAttribute( QStringLiteral( "text" ), text() );
337  layerGroupElem.setAttribute( QStringLiteral( "userText" ), userText() );
338  layerGroupElem.setAttribute( QStringLiteral( "style" ), QgsComposerLegendStyle::styleName( mStyle ) );
339  writeXmlChildren( layerGroupElem, doc );
340  elem.appendChild( layerGroupElem );
341 }
342 
343 void QgsComposerGroupItem::readXml( const QDomElement& itemElem, bool xServerAvailable )
344 {
345  if ( itemElem.isNull() )
346  {
347  return;
348  }
349  // text is always user text but for backward compatibility we read also text
350  QString userText = itemElem.attribute( QStringLiteral( "userText" ), QLatin1String( "" ) );
351  if ( userText.isEmpty() )
352  {
353  userText = itemElem.attribute( QStringLiteral( "text" ), QLatin1String( "" ) );
354  }
355  setText( userText );
356  setUserText( userText );
357 
358  setStyle( QgsComposerLegendStyle::styleFromName( itemElem.attribute( QStringLiteral( "style" ), QStringLiteral( "group" ) ) ) );
359 
360  //now call readXml for all the child items
361  QDomNodeList childList = itemElem.childNodes();
362  QDomNode currentNode;
363  QDomElement currentElem;
364  QgsComposerLegendItem* currentChildItem = nullptr;
365 
366  int nChildItems = childList.count();
367  for ( int i = 0; i < nChildItems; ++i )
368  {
369  currentNode = childList.at( i );
370  if ( !currentNode.isElement() )
371  {
372  continue;
373  }
374 
375  currentElem = currentNode.toElement();
376  QString elemTag = currentElem.tagName();
377 
378  if ( elemTag == QLatin1String( "GroupItem" ) )
379  {
380  currentChildItem = new QgsComposerGroupItem();
381  }
382  else if ( elemTag == QLatin1String( "LayerItem" ) )
383  {
384  currentChildItem = new QgsComposerLayerItem();
385  }
386  else
387  {
388  continue; //unsupported child item type
389  }
390  currentChildItem->readXml( currentElem, xServerAvailable );
391 
392  QList<QStandardItem *> itemsList;
393  itemsList << currentChildItem << new QgsComposerStyleItem( currentChildItem );
394  appendRow( itemsList );
395  }
396 }
397 
399 {
400 }
401 
403 {
404  setData( QgsComposerLegendStyle::styleLabel( item->style() ), Qt::DisplayRole );
405 }
406 
408 {
409 }
void setSymbol(QgsSymbol *s)
Set symbol (takes ownership)
static Style styleFromName(const QString &styleName)
Get style from name, used in project file.
QgsComposerLegendStyle::Style style() const
virtual void writeXml(QDomElement &elem, QDomDocument &doc) const override
virtual QStandardItem * clone() const override
virtual void writeXml(QDomElement &elem, QDomDocument &doc) const override
virtual void readXml(const QDomElement &itemElem, bool xServerAvailable=true) override
Read item content from xml.
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
void setLayerId(const QString &id)
Sets the associated layer ID.
virtual QStandardItem * clone() const override
void setLayerId(const QString &id)
virtual void readXml(const QDomElement &itemElem, bool xServerAvailable=true)=0
Read item content from xml.
void setStyle(QgsComposerLegendStyle::Style style)
static QString styleName(Style s)
Get name for style, used in project file.
static QIcon symbolPreviewIcon(QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
virtual QString userText() const
static QString styleLabel(Style s)
Get style label, translated, used in UI.
QString layerId() const
Returns the ID of the associated layer.
QgsFeatureRenderer * renderer()
Return renderer.
virtual void writeXml(QDomElement &elem, QDomDocument &doc) const =0
QgsComposerLegendStyle::Style mStyle
QMap< QString, QgsSymbol *> QgsSymbolMap
Definition: qgsrenderer.h:41
QgsComposerLegendItem(QgsComposerLegendStyle::Style s=QgsComposerLegendStyle::Undefined)
Abstract base class for the legend item types.
virtual void readXml(const QDomElement &itemElem, bool xServerAvailable=true) override
Read item content from xml.
virtual QStandardItem * clone() const override
virtual void writeXml(QDomElement &elem, QDomDocument &doc) const override
Composer legend components style.
virtual QStandardItem * clone() const override
virtual void writeXml(QDomElement &elem, QDomDocument &doc) const override
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void writeXmlChildren(QDomElement &elem, QDomDocument &doc) const
virtual void readXml(const QDomElement &itemElem, bool xServerAvailable=true) override
Read item content from xml.
virtual QgsSymbol * clone() const =0
Get a deep copy of this symbol.
virtual void readXml(const QDomElement &itemElem, bool xServerAvailable=true) override
Read item content from xml.
void setShowFeatureCount(bool show)
Represents a vector layer which manages a vector based data sets.
void setDefaultStyle(double scaleDenominator=-1, const QString &rule="")
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc)
virtual void setUserText(const QString &text)
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="")
return a list of item text / symbol
static QgsSymbolMap loadSymbols(QDomElement &element)