QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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 "qgscomposermodel.h"
25 #include "qgslegendrenderer.h"
26 #include "qgslogger.h"
27 #include <QDomDocument>
28 #include <QDomElement>
29 #include <QPainter>
30 
32  : QgsComposerItem( composition )
33  , mComposerMap( 0 )
34 {
35 
36  adjustBoxSize();
37 
38  connect( &mLegendModel, SIGNAL( layersChanged() ), this, SLOT( synchronizeWithModel() ) );
39 }
40 
42 {
43 
44 }
45 
47 {
48 }
49 
50 void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
51 {
52  Q_UNUSED( itemStyle );
53  Q_UNUSED( pWidget );
54 
55 
56  if ( mComposition )
58  if ( mComposerMap )
60 
61  if ( !painter )
62  return;
63 
64  drawBackground( painter );
65  painter->save();
66  //antialiasing on
67  painter->setRenderHint( QPainter::Antialiasing, true );
68  painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
69 
70  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
71  legendRenderer.setLegendSize( rect().size() );
72  legendRenderer.drawLegend( painter );
73 
74  painter->restore();
75 
76  //draw frame and selection boxes if necessary
77  drawFrame( painter );
78  if ( isSelected() )
79  {
80  drawSelectionBoxes( painter );
81  }
82 }
83 
84 QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
85 {
86  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
87  QSizeF size = legendRenderer.minimumSize();
88  if ( !painter )
89  legendRenderer.drawLegend( painter );
90  return size;
91 }
92 
93 
95 {
96  QgsLegendRenderer legendRenderer( &mLegendModel, mSettings );
97  QSizeF size = legendRenderer.minimumSize();
98  QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
99  if ( size.isValid() )
100  {
101  setSceneRect( QRectF( pos().x(), pos().y(), size.width(), size.height() ) );
102  }
103 }
104 
105 void QgsComposerLegend::setTitle( const QString& t )
106 {
107  mSettings.setTitle( t );
108 
109  if ( mComposition && id().isEmpty() )
110  {
111  //notify the model that the display name has changed
113  }
114 }
115 QString QgsComposerLegend::title() const { return mSettings.title(); }
116 
117 Qt::AlignmentFlag QgsComposerLegend::titleAlignment() const { return mSettings.titleAlignment(); }
118 void QgsComposerLegend::setTitleAlignment( Qt::AlignmentFlag alignment ) { mSettings.setTitleAlignment( alignment ); }
119 
123 
126 
129 
130 double QgsComposerLegend::boxSpace() const { return mSettings.boxSpace(); }
132 
135 
137 void QgsComposerLegend::setFontColor( const QColor& c ) { mSettings.setFontColor( c ); }
138 
139 double QgsComposerLegend::symbolWidth() const { return mSettings.symbolSize().width(); }
140 void QgsComposerLegend::setSymbolWidth( double w ) { mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) ); }
141 
142 double QgsComposerLegend::symbolHeight() const { return mSettings.symbolSize().height(); }
143 void QgsComposerLegend::setSymbolHeight( double h ) { mSettings.setSymbolSize( QSizeF( mSettings.symbolSize().width(), h ) ); }
144 
145 double QgsComposerLegend::wmsLegendWidth() const { return mSettings.wmsLegendSize().width(); }
147 
148 double QgsComposerLegend::wmsLegendHeight() const {return mSettings.wmsLegendSize().height(); }
150 
151 void QgsComposerLegend::setWrapChar( const QString& t ) { mSettings.setWrapChar( t ); }
152 QString QgsComposerLegend::wrapChar() const {return mSettings.wrapChar(); }
153 
156 
159 
162 
163 
165 {
166  QgsDebugMsg( "Entered" );
167  adjustBoxSize();
168  update();
169 }
170 
172 {
173  // take layer list from map renderer (to have legend order)
175  adjustBoxSize();
176  update();
177 }
178 
179 bool QgsComposerLegend::writeXML( QDomElement& elem, QDomDocument & doc ) const
180 {
181  if ( elem.isNull() )
182  {
183  return false;
184  }
185 
186  QDomElement composerLegendElem = doc.createElement( "ComposerLegend" );
187  elem.appendChild( composerLegendElem );
188 
189  //write general properties
190  composerLegendElem.setAttribute( "title", mSettings.title() );
191  composerLegendElem.setAttribute( "titleAlignment", QString::number(( int ) mSettings.titleAlignment() ) );
192  composerLegendElem.setAttribute( "columnCount", QString::number( mSettings.columnCount() ) );
193  composerLegendElem.setAttribute( "splitLayer", QString::number( mSettings.splitLayer() ) );
194  composerLegendElem.setAttribute( "equalColumnWidth", QString::number( mSettings.equalColumnWidth() ) );
195 
196  composerLegendElem.setAttribute( "boxSpace", QString::number( mSettings.boxSpace() ) );
197  composerLegendElem.setAttribute( "columnSpace", QString::number( mSettings.columnSpace() ) );
198 
199  composerLegendElem.setAttribute( "symbolWidth", QString::number( mSettings.symbolSize().width() ) );
200  composerLegendElem.setAttribute( "symbolHeight", QString::number( mSettings.symbolSize().height() ) );
201  composerLegendElem.setAttribute( "wmsLegendWidth", QString::number( mSettings.wmsLegendSize().width() ) );
202  composerLegendElem.setAttribute( "wmsLegendHeight", QString::number( mSettings.wmsLegendSize().height() ) );
203  composerLegendElem.setAttribute( "wrapChar", mSettings.wrapChar() );
204  composerLegendElem.setAttribute( "fontColor", mSettings.fontColor().name() );
205 
206  if ( mComposerMap )
207  {
208  composerLegendElem.setAttribute( "map", mComposerMap->id() );
209  }
210 
211  QDomElement composerLegendStyles = doc.createElement( "styles" );
212  composerLegendElem.appendChild( composerLegendStyles );
213 
214  style( QgsComposerLegendStyle::Title ).writeXML( "title", composerLegendStyles, doc );
215  style( QgsComposerLegendStyle::Group ).writeXML( "group", composerLegendStyles, doc );
216  style( QgsComposerLegendStyle::Subgroup ).writeXML( "subgroup", composerLegendStyles, doc );
217  style( QgsComposerLegendStyle::Symbol ).writeXML( "symbol", composerLegendStyles, doc );
218  style( QgsComposerLegendStyle::SymbolLabel ).writeXML( "symbolLabel", composerLegendStyles, doc );
219 
220  //write model properties
221  mLegendModel.writeXML( composerLegendElem, doc );
222 
223  return _writeXML( composerLegendElem, doc );
224 }
225 
226 bool QgsComposerLegend::readXML( const QDomElement& itemElem, const QDomDocument& doc )
227 {
228  if ( itemElem.isNull() )
229  {
230  return false;
231  }
232 
233  //read general properties
234  mSettings.setTitle( itemElem.attribute( "title" ) );
235  if ( !itemElem.attribute( "titleAlignment" ).isEmpty() )
236  {
237  mSettings.setTitleAlignment(( Qt::AlignmentFlag )itemElem.attribute( "titleAlignment" ).toInt() );
238  }
239  int colCount = itemElem.attribute( "columnCount", "1" ).toInt();
240  if ( colCount < 1 ) colCount = 1;
241  mSettings.setColumnCount( colCount );
242  mSettings.setSplitLayer( itemElem.attribute( "splitLayer", "0" ).toInt() == 1 );
243  mSettings.setEqualColumnWidth( itemElem.attribute( "equalColumnWidth", "0" ).toInt() == 1 );
244 
245  QDomNodeList stylesNodeList = itemElem.elementsByTagName( "styles" );
246  if ( stylesNodeList.size() > 0 )
247  {
248  QDomNode stylesNode = stylesNodeList.at( 0 );
249  for ( int i = 0; i < stylesNode.childNodes().size(); i++ )
250  {
251  QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
253  style.readXML( styleElem, doc );
254  QString name = styleElem.attribute( "name" );
256  if ( name == "title" ) s = QgsComposerLegendStyle::Title;
257  else if ( name == "group" ) s = QgsComposerLegendStyle::Group;
258  else if ( name == "subgroup" ) s = QgsComposerLegendStyle::Subgroup;
259  else if ( name == "symbol" ) s = QgsComposerLegendStyle::Symbol;
260  else if ( name == "symbolLabel" ) s = QgsComposerLegendStyle::SymbolLabel;
261  else continue;
262  setStyle( s, style );
263  }
264  }
265 
266  //font color
267  QColor fontClr;
268  fontClr.setNamedColor( itemElem.attribute( "fontColor", "#000000" ) );
269  mSettings.setFontColor( fontClr );
270 
271  //spaces
272  mSettings.setBoxSpace( itemElem.attribute( "boxSpace", "2.0" ).toDouble() );
273  mSettings.setColumnSpace( itemElem.attribute( "columnSpace", "2.0" ).toDouble() );
274 
275  mSettings.setSymbolSize( QSizeF( itemElem.attribute( "symbolWidth", "7.0" ).toDouble(), itemElem.attribute( "symbolHeight", "14.0" ).toDouble() ) );
276  mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( "wmsLegendWidth", "50" ).toDouble(), itemElem.attribute( "wmsLegendHeight", "25" ).toDouble() ) );
277 
278  mSettings.setWrapChar( itemElem.attribute( "wrapChar" ) );
279 
280  //composer map
281  if ( !itemElem.attribute( "map" ).isEmpty() )
282  {
283  mComposerMap = mComposition->getComposerMapById( itemElem.attribute( "map" ).toInt() );
284  }
285 
286  //read model properties
287  QDomNodeList modelNodeList = itemElem.elementsByTagName( "Model" );
288  if ( modelNodeList.size() > 0 )
289  {
290  QDomElement modelElem = modelNodeList.at( 0 ).toElement();
291  mLegendModel.readXML( modelElem, doc );
292  }
293 
294  //restore general composer item properties
295  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
296  if ( composerItemList.size() > 0 )
297  {
298  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
299  _readXML( composerItemElem, doc );
300  }
301 
302  // < 2.0 projects backward compatibility >>>>>
303  //title font
304  QString titleFontString = itemElem.attribute( "titleFont" );
305  if ( !titleFontString.isEmpty() )
306  {
307  rstyle( QgsComposerLegendStyle::Title ).rfont().fromString( titleFontString );
308  }
309  //group font
310  QString groupFontString = itemElem.attribute( "groupFont" );
311  if ( !groupFontString.isEmpty() )
312  {
313  rstyle( QgsComposerLegendStyle::Group ).rfont().fromString( groupFontString );
314  }
315 
316  //layer font
317  QString layerFontString = itemElem.attribute( "layerFont" );
318  if ( !layerFontString.isEmpty() )
319  {
320  rstyle( QgsComposerLegendStyle::Subgroup ).rfont().fromString( layerFontString );
321  }
322  //item font
323  QString itemFontString = itemElem.attribute( "itemFont" );
324  if ( !itemFontString.isEmpty() )
325  {
326  rstyle( QgsComposerLegendStyle::SymbolLabel ).rfont().fromString( itemFontString );
327  }
328 
329  if ( !itemElem.attribute( "groupSpace" ).isEmpty() )
330  {
331  rstyle( QgsComposerLegendStyle::Group ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "groupSpace", "3.0" ).toDouble() );
332  }
333  if ( !itemElem.attribute( "layerSpace" ).isEmpty() )
334  {
335  rstyle( QgsComposerLegendStyle::Subgroup ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "layerSpace", "3.0" ).toDouble() );
336  }
337  if ( !itemElem.attribute( "symbolSpace" ).isEmpty() )
338  {
339  rstyle( QgsComposerLegendStyle::Symbol ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "symbolSpace", "2.0" ).toDouble() );
340  rstyle( QgsComposerLegendStyle::SymbolLabel ).setMargin( QgsComposerLegendStyle::Top, itemElem.attribute( "symbolSpace", "2.0" ).toDouble() );
341  }
342  // <<<<<<< < 2.0 projects backward compatibility
343 
344  emit itemChanged();
345  return true;
346 }
347 
349 {
350  if ( !id().isEmpty() )
351  {
352  return id();
353  }
354 
355  //if no id, default to portion of title text
356  QString text = mSettings.title();
357  if ( text.isEmpty() )
358  {
359  return tr( "<legend>" );
360  }
361  if ( text.length() > 25 )
362  {
363  return QString( tr( "%1..." ) ).arg( text.left( 25 ) );
364  }
365  else
366  {
367  return text;
368  }
369 }
370 
372 {
373  mComposerMap = map;
374  if ( map )
375  {
376  QObject::connect( map, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
377  }
378 }
379 
381 {
382  if ( mComposerMap )
383  {
384  disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
385  }
386  mComposerMap = 0;
387 }
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)
QgsComposerModel * itemsModel()
Returns the items model attached to the composition.
#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 updateItemDisplayName(QgsComposerItem *item)
Must be called when an item's display name is modified.
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)
Draws additional graphics on selected items.
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)
virtual QString displayName() const
Get item display name.
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.
#define tr(sourceText)
void setFont(const QFont &font)
QString id() const
Get item's id (which is not necessarly unique)