QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposerlegend.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerlegend.cpp - description
3  ---------------------
4  begin : June 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz 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 #include <limits>
18 
19 #include "qgscomposerlegendstyle.h"
20 #include "qgscomposerlegend.h"
21 #include "qgscomposerlegenditem.h"
22 #include "qgscomposermap.h"
23 #include "qgscomposition.h"
24 #include "qgslegendrenderer.h"
25 #include "qgslogger.h"
26 #include <QDomDocument>
27 #include <QDomElement>
28 #include <QPainter>
29 
31  : QgsComposerItem( composition )
32  , mComposerMap( 0 )
33 {
34 
35  adjustBoxSize();
36 
37  connect( &mLegendModel, SIGNAL( layersChanged() ), this, SLOT( synchronizeWithModel() ) );
38 }
39 
41 {
42 
43 }
44 
46 {
47 }
48 
49 void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
50 {
51  Q_UNUSED( itemStyle );
52  Q_UNUSED( pWidget );
53 
54 
55  if ( mComposition )
57  if ( mComposerMap )
59 
60  if ( !painter )
61  return;
62 
63  drawBackground( painter );
64  painter->save();
65  //antialiasing on
66  painter->setRenderHint( QPainter::Antialiasing, true );
67  painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
68 
69  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
70  legendRenderer.setLegendSize( rect().size() );
71  legendRenderer.drawLegend( painter );
72 
73  painter->restore();
74 
75  //draw frame and selection boxes if necessary
76  drawFrame( painter );
77  if ( isSelected() )
78  {
79  drawSelectionBoxes( painter );
80  }
81 }
82 
83 QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
84 {
85  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
86  QSizeF size = legendRenderer.minimumSize();
87  if ( !painter )
88  legendRenderer.drawLegend( painter );
89  return size;
90 }
91 
92 
94 {
95  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
96  QSizeF size = legendRenderer.minimumSize();
97  QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
98  if ( size.isValid() )
99  {
100  setSceneRect( QRectF( pos().x(), pos().y(), size.width(), size.height() ) );
101  }
102 }
103 
104 void QgsComposerLegend::setTitle( const QString& t ) { mSettings.setTitle( t ); }
105 QString QgsComposerLegend::title() const { return mSettings.title(); }
106 
107 Qt::AlignmentFlag QgsComposerLegend::titleAlignment() const { return mSettings.titleAlignment(); }
108 void QgsComposerLegend::setTitleAlignment( Qt::AlignmentFlag alignment ) { mSettings.setTitleAlignment( alignment ); }
109 
113 
116 
119 
120 double QgsComposerLegend::boxSpace() const { return mSettings.boxSpace(); }
122 
125 
127 void QgsComposerLegend::setFontColor( const QColor& c ) { mSettings.setFontColor( c ); }
128 
129 double QgsComposerLegend::symbolWidth() const { return mSettings.symbolSize().width(); }
130 void QgsComposerLegend::setSymbolWidth( double w ) { mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) ); }
131 
132 double QgsComposerLegend::symbolHeight() const { return mSettings.symbolSize().height(); }
133 void QgsComposerLegend::setSymbolHeight( double h ) { mSettings.setSymbolSize( QSizeF( mSettings.symbolSize().width(), h ) ); }
134 
135 double QgsComposerLegend::wmsLegendWidth() const { return mSettings.wmsLegendSize().width(); }
137 
138 double QgsComposerLegend::wmsLegendHeight() const {return mSettings.wmsLegendSize().height(); }
140 
141 void QgsComposerLegend::setWrapChar( const QString& t ) { mSettings.setWrapChar( t ); }
142 QString QgsComposerLegend::wrapChar() const {return mSettings.wrapChar(); }
143 
146 
149 
152 
153 
155 {
156  QgsDebugMsg( "Entered" );
157  adjustBoxSize();
158  update();
159 }
160 
162 {
163  // take layer list from map renderer (to have legend order)
165  adjustBoxSize();
166  update();
167 }
168 
169 bool QgsComposerLegend::writeXML( QDomElement& elem, QDomDocument & doc ) const
170 {
171  if ( elem.isNull() )
172  {
173  return false;
174  }
175 
176  QDomElement composerLegendElem = doc.createElement( "ComposerLegend" );
177  elem.appendChild( composerLegendElem );
178 
179  //write general properties
180  composerLegendElem.setAttribute( "title", mSettings.title() );
181  composerLegendElem.setAttribute( "titleAlignment", QString::number(( int ) mSettings.titleAlignment() ) );
182  composerLegendElem.setAttribute( "columnCount", QString::number( mSettings.columnCount() ) );
183  composerLegendElem.setAttribute( "splitLayer", QString::number( mSettings.splitLayer() ) );
184  composerLegendElem.setAttribute( "equalColumnWidth", QString::number( mSettings.equalColumnWidth() ) );
185 
186  composerLegendElem.setAttribute( "boxSpace", QString::number( mSettings.boxSpace() ) );
187  composerLegendElem.setAttribute( "columnSpace", QString::number( mSettings.columnSpace() ) );
188 
189  composerLegendElem.setAttribute( "symbolWidth", QString::number( mSettings.symbolSize().width() ) );
190  composerLegendElem.setAttribute( "symbolHeight", QString::number( mSettings.symbolSize().height() ) );
191  composerLegendElem.setAttribute( "wmsLegendWidth", QString::number( mSettings.wmsLegendSize().width() ) );
192  composerLegendElem.setAttribute( "wmsLegendHeight", QString::number( mSettings.wmsLegendSize().height() ) );
193  composerLegendElem.setAttribute( "wrapChar", mSettings.wrapChar() );
194  composerLegendElem.setAttribute( "fontColor", mSettings.fontColor().name() );
195 
196  if ( mComposerMap )
197  {
198  composerLegendElem.setAttribute( "map", mComposerMap->id() );
199  }
200 
201  QDomElement composerLegendStyles = doc.createElement( "styles" );
202  composerLegendElem.appendChild( composerLegendStyles );
203 
204  style( QgsComposerLegendStyle::Title ).writeXML( "title", composerLegendStyles, doc );
205  style( QgsComposerLegendStyle::Group ).writeXML( "group", composerLegendStyles, doc );
206  style( QgsComposerLegendStyle::Subgroup ).writeXML( "subgroup", composerLegendStyles, doc );
207  style( QgsComposerLegendStyle::Symbol ).writeXML( "symbol", composerLegendStyles, doc );
208  style( QgsComposerLegendStyle::SymbolLabel ).writeXML( "symbolLabel", composerLegendStyles, doc );
209 
210  //write model properties
211  mLegendModel.writeXML( composerLegendElem, doc );
212 
213  return _writeXML( composerLegendElem, doc );
214 }
215 
216 bool QgsComposerLegend::readXML( const QDomElement& itemElem, const QDomDocument& doc )
217 {
218  if ( itemElem.isNull() )
219  {
220  return false;
221  }
222 
223  //read general properties
224  mSettings.setTitle( itemElem.attribute( "title" ) );
225  if ( !itemElem.attribute( "titleAlignment" ).isEmpty() )
226  {
227  mSettings.setTitleAlignment(( Qt::AlignmentFlag )itemElem.attribute( "titleAlignment" ).toInt() );
228  }
229  int colCount = itemElem.attribute( "columnCount", "1" ).toInt();
230  if ( colCount < 1 ) colCount = 1;
231  mSettings.setColumnCount( colCount );
232  mSettings.setSplitLayer( itemElem.attribute( "splitLayer", "0" ).toInt() == 1 );
233  mSettings.setEqualColumnWidth( itemElem.attribute( "equalColumnWidth", "0" ).toInt() == 1 );
234 
235  QDomNodeList stylesNodeList = itemElem.elementsByTagName( "styles" );
236  if ( stylesNodeList.size() > 0 )
237  {
238  QDomNode stylesNode = stylesNodeList.at( 0 );
239  for ( int i = 0; i < stylesNode.childNodes().size(); i++ )
240  {
241  QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
243  style.readXML( styleElem, doc );
244  QString name = styleElem.attribute( "name" );
246  if ( name == "title" ) s = QgsComposerLegendStyle::Title;
247  else if ( name == "group" ) s = QgsComposerLegendStyle::Group;
248  else if ( name == "subgroup" ) s = QgsComposerLegendStyle::Subgroup;
249  else if ( name == "symbol" ) s = QgsComposerLegendStyle::Symbol;
250  else if ( name == "symbolLabel" ) s = QgsComposerLegendStyle::SymbolLabel;
251  else continue;
252  setStyle( s, style );
253  }
254  }
255 
256  //font color
257  QColor fontClr;
258  fontClr.setNamedColor( itemElem.attribute( "fontColor", "#000000" ) );
259  mSettings.setFontColor( fontClr );
260 
261  //spaces
262  mSettings.setBoxSpace( itemElem.attribute( "boxSpace", "2.0" ).toDouble() );
263  mSettings.setColumnSpace( itemElem.attribute( "columnSpace", "2.0" ).toDouble() );
264 
265  mSettings.setSymbolSize( QSizeF( itemElem.attribute( "symbolWidth", "7.0" ).toDouble(), itemElem.attribute( "symbolHeight", "14.0" ).toDouble() ) );
266  mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( "wmsLegendWidth", "50" ).toDouble(), itemElem.attribute( "wmsLegendHeight", "25" ).toDouble() ) );
267 
268  mSettings.setWrapChar( itemElem.attribute( "wrapChar" ) );
269 
270  //composer map
271  if ( !itemElem.attribute( "map" ).isEmpty() )
272  {
273  mComposerMap = mComposition->getComposerMapById( itemElem.attribute( "map" ).toInt() );
274  }
275 
276  //read model properties
277  QDomNodeList modelNodeList = itemElem.elementsByTagName( "Model" );
278  if ( modelNodeList.size() > 0 )
279  {
280  QDomElement modelElem = modelNodeList.at( 0 ).toElement();
281  mLegendModel.readXML( modelElem, doc );
282  }
283 
284  //restore general composer item properties
285  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
286  if ( composerItemList.size() > 0 )
287  {
288  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
289  _readXML( composerItemElem, doc );
290  }
291 
292  // < 2.0 projects backward compatibility >>>>>
293  //title font
294  QString titleFontString = itemElem.attribute( "titleFont" );
295  if ( !titleFontString.isEmpty() )
296  {
297  rstyle( QgsComposerLegendStyle::Title ).rfont().fromString( titleFontString );
298  }
299  //group font
300  QString groupFontString = itemElem.attribute( "groupFont" );
301  if ( !groupFontString.isEmpty() )
302  {
303  rstyle( QgsComposerLegendStyle::Group ).rfont().fromString( groupFontString );
304  }
305 
306  //layer font
307  QString layerFontString = itemElem.attribute( "layerFont" );
308  if ( !layerFontString.isEmpty() )
309  {
310  rstyle( QgsComposerLegendStyle::Subgroup ).rfont().fromString( layerFontString );
311  }
312  //item font
313  QString itemFontString = itemElem.attribute( "itemFont" );
314  if ( !itemFontString.isEmpty() )
315  {
316  rstyle( QgsComposerLegendStyle::SymbolLabel ).rfont().fromString( itemFontString );
317  }
318 
319  if ( !itemElem.attribute( "groupSpace" ).isEmpty() )
320  {
321  rstyle( QgsComposerLegendStyle::Group ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "groupSpace", "3.0" ).toDouble() );
322  }
323  if ( !itemElem.attribute( "layerSpace" ).isEmpty() )
324  {
325  rstyle( QgsComposerLegendStyle::Subgroup ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "layerSpace", "3.0" ).toDouble() );
326  }
327  if ( !itemElem.attribute( "symbolSpace" ).isEmpty() )
328  {
329  rstyle( QgsComposerLegendStyle::Symbol ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "symbolSpace", "2.0" ).toDouble() );
330  rstyle( QgsComposerLegendStyle::SymbolLabel ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "symbolSpace", "2.0" ).toDouble() );
331  }
332  // <<<<<<< < 2.0 projects backward compatibility
333 
334  emit itemChanged();
335  return true;
336 }
337 
339 {
340  mComposerMap = map;
341  if ( map )
342  {
343  QObject::connect( map, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
344  }
345 }
346 
348 {
349  if ( mComposerMap )
350  {
351  disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
352  }
353  mComposerMap = 0;
354 }
double boxSpace() const
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
QString wrapChar() const
void setWrapChar(const QString &t)
void setLegendSize(QSizeF s)
Set the preferred resulting legend size.
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style.
double boxSpace() const
void setEqualColumnWidth(bool s)
void setBoxSpace(double s)
void setMmPerMapUnit(double mmPerMapUnit)
void readXML(const QDomElement &elem, const QDomDocument &doc)
double mapUnitsToMM() const
Returns the conversion factor map units -> mm.
QgsComposerLegendStyle & rstyle(QgsComposerLegendStyle::Style s)
Returns reference to modifiable style.
void setMargin(Side side, double margin)
int columnCount() const
void setSplitLayer(bool s)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
bool writeXML(QDomElement &elem, QDomDocument &doc) const
stores state in Dom node
void itemChanged()
Emitted when the item changes.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
void setSymbolSize(QSizeF s)
void drawLegend(QPainter *painter)
Draw the legend with given painter.
void setColumnSpace(double s)
A item that forms part of a map composition.
double columnSpace() const
double columnSpace() const
QgsLegendModel mLegendModel
double wmsLegendWidth() const
virtual void drawFrame(QPainter *p)
Draw black frame around item.
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style.
void setTitle(const QString &t)
void updateLegend()
Updates the model and all legend entries.
void setWmsLegendHeight(double h)
QgsComposerLegendStyle & rstyle(QgsComposerLegendStyle::Style s)
Returns reference to modifiable style.
void adjustBoxSize()
Sets item box to the whole content.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
QColor fontColor() const
const QgsComposerMap * mComposerMap
void setLayerSet(const QStringList &layerIds, double scaleDenominator=-1, QString rule="")
int splitLayer() const
void setSymbolHeight(double h)
virtual void drawSelectionBoxes(QPainter *p)
Draw selection boxes around item.
QColor fontColor() const
void setComposerMap(const QgsComposerMap *map)
void synchronizeWithModel()
Data changed.
void setStyleFont(QgsComposerLegendStyle::Style s, const QFont &f)
Set style font.
QString wrapChar() const
void setTitle(const QString &t)
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
QString title() const
bool writeXML(QDomElement &composerLegendElem, QDomDocument &doc) const
void setFontColor(const QColor &c)
void setColumnSpace(double s)
Graphics scene for map printing.
QSizeF minimumSize()
Run the layout algorithm and determine the size required for legend.
QFont styleFont(QgsComposerLegendStyle::Style s) const
Object representing map window.
void setSymbolWidth(double w)
QSizeF paintAndDetermineSize(QPainter *painter)
Paints the legend and calculates its size.
void setStyle(QgsComposerLegendStyle::Style s, const QgsComposerLegendStyle style)
void invalidateCurrentMap()
Sets mCompositionMap to 0 if the map is deleted.
bool readXML(const QDomElement &legendModelElem, const QDomDocument &doc)
double symbolWidth() const
void setWmsLegendWidth(double w)
void writeXML(QString name, QDomElement &elem, QDomDocument &doc) const
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
bool useAdvancedEffects() const
Returns true if a composition should use advanced effects such as blend modes.
int id() const
Get identification number.
QgsComposition * mComposition
Composer legend components style.
void setWmsLegendSize(QSizeF s)
void setUseAdvancedEffects(bool use)
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
void setStyleMargin(QgsComposerLegendStyle::Style s, double margin)
Set style margin.
void setWrapChar(const QString &t)
virtual void drawBackground(QPainter *p)
Draw background.
void setColumnCount(int c)
double wmsLegendHeight() const
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
int equalColumnWidth() const
void setEqualColumnWidth(bool s)
void setStyle(QgsComposerLegendStyle::Style s, const QgsComposerLegendStyle style)
QString title() const
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
QgsLegendSettings mSettings
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget)
Reimplementation of QCanvasItem::paint.
QSizeF symbolSize() const
QSizeF wmsLegendSize() const
void setFontColor(const QColor &c)
const QgsComposerMap * getComposerMapById(const int id) const
Returns the composer map with specified id.
double size
Definition: qgssvgcache.cpp:77
bool readXML(const QDomElement &itemElem, const QDomDocument &doc)
sets state from Dom document
void setBoxSpace(double s)
double symbolHeight() const
int equalColumnWidth() const
void setSplitLayer(bool s)
The QgsLegendRenderer class handles automatic layout and rendering of legend.
void setFont(const QFont &font)