QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposertable.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposertable.cpp
3  --------------------
4  begin : January 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco at hugis dot net
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 "qgscomposertable.h"
19 #include "qgslogger.h"
20 #include <QPainter>
21 #include <QSettings>
22 
24  : QgsComposerItem( composition )
25  , mLineTextDistance( 1.0 )
26  , mShowGrid( true )
27  , mGridStrokeWidth( 0.5 )
28  , mGridColor( QColor( 0, 0, 0 ) )
29 {
30  //get default composer font from settings
31  QSettings settings;
32  QString defaultFontString = settings.value( "/Composer/defaultFont" ).toString();
33  if ( !defaultFontString.isEmpty() )
34  {
35  mHeaderFont.setFamily( defaultFontString );
36  mContentFont.setFamily( defaultFontString );
37  }
38 }
39 
41 {
42 
43 }
44 
45 void QgsComposerTable::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
46 {
47  Q_UNUSED( itemStyle );
48  Q_UNUSED( pWidget );
49  if ( !painter )
50  {
51  return;
52  }
53 
54  //getFeatureAttributes
55  QList<QgsAttributeMap> attributeMaps;
56  if ( !getFeatureAttributes( attributeMaps ) )
57  {
58  return;
59  }
60 
61  QMap<int, double> maxColumnWidthMap;
62  //check how much space each column needs
63  calculateMaxColumnWidths( maxColumnWidthMap, attributeMaps );
64  //adapt item frame to max width / height
65  adaptItemFrame( maxColumnWidthMap, attributeMaps );
66 
67  drawBackground( painter );
68  painter->setPen( Qt::SolidLine );
69 
70  //now draw the text
71  double currentX = mGridStrokeWidth;
72  double currentY;
73 
74  QMap<int, QString> headerMap = getHeaderLabels();
75  QMap<int, QString>::const_iterator columnIt = headerMap.constBegin();
76 
77  for ( ; columnIt != headerMap.constEnd(); ++columnIt )
78  {
79  currentY = mGridStrokeWidth;
80  currentY += mLineTextDistance;
81  currentY += fontAscentMillimeters( mHeaderFont );
82  currentX += mLineTextDistance;
83  drawText( painter, currentX, currentY, columnIt.value(), mHeaderFont );
84 
85  currentY += mLineTextDistance;
86  currentY += mGridStrokeWidth;
87 
88  //draw the attribute values
89  QList<QgsAttributeMap>::const_iterator attIt = attributeMaps.begin();
90  for ( ; attIt != attributeMaps.end(); ++attIt )
91  {
92  currentY += fontAscentMillimeters( mContentFont );
93  currentY += mLineTextDistance;
94 
95  const QgsAttributeMap &currentAttributeMap = *attIt;
96  QString str = currentAttributeMap[ columnIt.key()].toString();
97  drawText( painter, currentX, currentY, str, mContentFont );
98  currentY += mLineTextDistance;
99  currentY += mGridStrokeWidth;
100  }
101 
102  currentX += maxColumnWidthMap[columnIt.key()];
103  currentX += mLineTextDistance;
104  currentX += mGridStrokeWidth;
105  }
106 
107  //and the borders
108  if ( mShowGrid )
109  {
110  QPen gridPen;
111  gridPen.setWidthF( mGridStrokeWidth );
112  gridPen.setColor( mGridColor );
113  gridPen.setJoinStyle( Qt::MiterJoin );
114  painter->setPen( gridPen );
115  drawHorizontalGridLines( painter, attributeMaps.size() );
116  drawVerticalGridLines( painter, maxColumnWidthMap );
117  }
118 
119  //draw frame and selection boxes if necessary
120  drawFrame( painter );
121  if ( isSelected() )
122  {
123  drawSelectionBoxes( painter );
124  }
125 }
126 
128 {
129  QList<QgsAttributeMap> attributes;
130  if ( !getFeatureAttributes( attributes ) )
131  return;
132 
133  QMap<int, double> maxWidthMap;
134  if ( !calculateMaxColumnWidths( maxWidthMap, attributes ) )
135  return;
136 
137  adaptItemFrame( maxWidthMap, attributes );
138 }
139 
140 bool QgsComposerTable::tableWriteXML( QDomElement& elem, QDomDocument & doc ) const
141 {
142  elem.setAttribute( "lineTextDist", QString::number( mLineTextDistance ) );
143  elem.setAttribute( "headerFont", mHeaderFont.toString() );
144  elem.setAttribute( "contentFont", mContentFont.toString() );
145  elem.setAttribute( "gridStrokeWidth", QString::number( mGridStrokeWidth ) );
146  elem.setAttribute( "gridColorRed", mGridColor.red() );
147  elem.setAttribute( "gridColorGreen", mGridColor.green() );
148  elem.setAttribute( "gridColorBlue", mGridColor.blue() );
149  elem.setAttribute( "showGrid", mShowGrid );
150  return _writeXML( elem, doc );
151 }
152 
153 bool QgsComposerTable::tableReadXML( const QDomElement& itemElem, const QDomDocument& doc )
154 {
155  if ( itemElem.isNull() )
156  {
157  return false;
158  }
159 
160  mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
161  mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
162  mLineTextDistance = itemElem.attribute( "lineTextDist", "1.0" ).toDouble();
163  mGridStrokeWidth = itemElem.attribute( "gridStrokeWidth", "0.5" ).toDouble();
164  mShowGrid = itemElem.attribute( "showGrid", "1" ).toInt();
165 
166  //grid color
167  int gridRed = itemElem.attribute( "gridColorRed", "0" ).toInt();
168  int gridGreen = itemElem.attribute( "gridColorGreen", "0" ).toInt();
169  int gridBlue = itemElem.attribute( "gridColorBlue", "0" ).toInt();
170  mGridColor = QColor( gridRed, gridGreen, gridBlue );
171 
172  //restore general composer item properties
173  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
174  if ( composerItemList.size() > 0 )
175  {
176  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
177  _readXML( composerItemElem, doc );
178  }
179  return true;
180 }
181 
182 bool QgsComposerTable::calculateMaxColumnWidths( QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeMaps ) const
183 {
184  maxWidthMap.clear();
185  QMap<int, QString> headerMap = getHeaderLabels();
186  QMap<int, QString>::const_iterator headerIt = headerMap.constBegin();
187  for ( ; headerIt != headerMap.constEnd(); ++headerIt )
188  {
189  maxWidthMap.insert( headerIt.key(), textWidthMillimeters( mHeaderFont, headerIt.value() ) );
190  }
191 
192  //go through all the attributes and adapt the max width values
193  QList<QgsAttributeMap>::const_iterator attIt = attributeMaps.constBegin();
194 
195  double currentAttributeTextWidth;
196 
197  for ( ; attIt != attributeMaps.constEnd(); ++attIt )
198  {
199  QgsAttributeMap::const_iterator attIt2 = attIt->constBegin();
200  for ( ; attIt2 != attIt->constEnd(); ++attIt2 )
201  {
202  currentAttributeTextWidth = textWidthMillimeters( mContentFont, attIt2.value().toString() );
203  if ( currentAttributeTextWidth > maxWidthMap[ attIt2.key()] )
204  {
205  maxWidthMap[ attIt2.key()] = currentAttributeTextWidth;
206  }
207  }
208  }
209  return true;
210 }
211 
212 void QgsComposerTable::adaptItemFrame( const QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeMaps )
213 {
214  //calculate height
215  int n = attributeMaps.size();
216  double totalHeight = fontAscentMillimeters( mHeaderFont )
218  + ( n + 1 ) * mLineTextDistance * 2
219  + ( n + 2 ) * mGridStrokeWidth;
220 
221  //adapt frame to total width
222  double totalWidth = 0;
223  QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
224  for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
225  {
226  totalWidth += maxColWidthIt.value();
227  }
228  totalWidth += ( 2 * maxWidthMap.size() * mLineTextDistance );
229  totalWidth += ( maxWidthMap.size() + 1 ) * mGridStrokeWidth;
230 
231  QgsComposerItem::setSceneRect( QRectF( pos().x(), pos().y(), totalWidth, totalHeight ) );
232 }
233 
234 void QgsComposerTable::drawHorizontalGridLines( QPainter* p, int nAttributes )
235 {
236  //horizontal lines
237  double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
238  double currentY = halfGridStrokeWidth;
239  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
240  currentY += mGridStrokeWidth;
241  currentY += ( fontAscentMillimeters( mHeaderFont ) + 2 * mLineTextDistance );
242  for ( int i = 0; i < nAttributes; ++i )
243  {
244  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
245  currentY += mGridStrokeWidth;
246  currentY += ( fontAscentMillimeters( mContentFont ) + 2 * mLineTextDistance );
247  }
248  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
249 }
250 
251 void QgsComposerTable::drawVerticalGridLines( QPainter* p, const QMap<int, double>& maxWidthMap )
252 {
253  //vertical lines
254  double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
255  double currentX = halfGridStrokeWidth;
256  p->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, rect().height() - halfGridStrokeWidth ) );
257  currentX += mGridStrokeWidth;
258  QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
259  for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
260  {
261  currentX += ( maxColWidthIt.value() + 2 * mLineTextDistance );
262  p->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, rect().height() - halfGridStrokeWidth ) );
263  currentX += mGridStrokeWidth;
264  }
265 }
266 
267 
268 
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:98
A item that forms part of a map composition.
virtual void drawFrame(QPainter *p)
Draw black frame around item.
virtual QMap< int, QString > getHeaderLabels() const
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
void drawHorizontalGridLines(QPainter *p, int nAttributes)
virtual void drawSelectionBoxes(QPainter *p)
Draw selection boxes around item.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget)
Reimplementation of QCanvasItem::paint.
bool tableWriteXML(QDomElement &itemElem, QDomDocument &doc) const
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
virtual ~QgsComposerTable()
Graphics scene for map printing.
virtual bool getFeatureAttributes(QList< QgsAttributeMap > &attributeMaps)
Retrieves feature attributes.
QgsComposerTable(QgsComposition *composition)
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
bool tableReadXML(const QDomElement &itemElem, const QDomDocument &doc)
void adjustFrameToSize()
Adapts the size of the frame to match the content.
virtual void drawBackground(QPainter *p)
Draw background.
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...
double mLineTextDistance
Distance between table lines and text.
void adaptItemFrame(const QMap< int, double > &maxWidthMap, const QList< QgsAttributeMap > &attributeMaps)
Adapts the size of the item frame to match the content.
virtual bool calculateMaxColumnWidths(QMap< int, double > &maxWidthMap, const QList< QgsAttributeMap > &attributeMaps) const
Calculate the maximum width values of the vector attributes.
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
void drawVerticalGridLines(QPainter *p, const QMap< int, double > &maxWidthMap)