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 
46 {
47 
48  mMaxColumnWidthMap.clear();
49  mAttributeMaps.clear();
50 
51  //getFeatureAttributes
53  {
54  return;
55  }
56 
57  //since attributes have changed, we also need to recalculate the column widths
58  //and size of table
60 }
61 
62 void QgsComposerTable::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
63 {
64  Q_UNUSED( itemStyle );
65  Q_UNUSED( pWidget );
66  if ( !painter )
67  {
68  return;
69  }
70 
73  {
74  //exporting composition, so force an attribute refresh
75  //we do this in case vector layer has changed via an external source (eg, another database user)
77  }
78 
79  drawBackground( painter );
80  painter->setPen( Qt::SolidLine );
81 
82  //now draw the text
83  double currentX = mGridStrokeWidth;
84  double currentY;
85 
86  QMap<int, QString> headerMap = getHeaderLabels();
87  QMap<int, QString>::const_iterator columnIt = headerMap.constBegin();
88 
89  for ( ; columnIt != headerMap.constEnd(); ++columnIt )
90  {
91  currentY = mGridStrokeWidth;
92  currentY += mLineTextDistance;
93  currentY += fontAscentMillimeters( mHeaderFont );
94  currentX += mLineTextDistance;
95  drawText( painter, currentX, currentY, columnIt.value(), mHeaderFont );
96 
97  currentY += mLineTextDistance;
98  currentY += mGridStrokeWidth;
99 
100  //draw the attribute values
101  QList<QgsAttributeMap>::const_iterator attIt = mAttributeMaps.begin();
102  for ( ; attIt != mAttributeMaps.end(); ++attIt )
103  {
104  currentY += fontAscentMillimeters( mContentFont );
105  currentY += mLineTextDistance;
106 
107  const QgsAttributeMap &currentAttributeMap = *attIt;
108  QString str = currentAttributeMap[ columnIt.key()].toString();
109  drawText( painter, currentX, currentY, str, mContentFont );
110  currentY += mLineTextDistance;
111  currentY += mGridStrokeWidth;
112  }
113 
114  currentX += mMaxColumnWidthMap[columnIt.key()];
115  currentX += mLineTextDistance;
116  currentX += mGridStrokeWidth;
117  }
118 
119  //and the borders
120  if ( mShowGrid )
121  {
122  QPen gridPen;
123  gridPen.setWidthF( mGridStrokeWidth );
124  gridPen.setColor( mGridColor );
125  gridPen.setJoinStyle( Qt::MiterJoin );
126  painter->setPen( gridPen );
127  drawHorizontalGridLines( painter, mAttributeMaps.size() );
129  }
130 
131  //draw frame and selection boxes if necessary
132  drawFrame( painter );
133  if ( isSelected() )
134  {
135  drawSelectionBoxes( painter );
136  }
137 }
138 
139 void QgsComposerTable::setHeaderFont( const QFont& f )
140 {
141  mHeaderFont = f;
142  //since font attributes have changed, we need to recalculate the table size
144 }
145 
146 void QgsComposerTable::setContentFont( const QFont& f )
147 {
148  mContentFont = f;
149  //since font attributes have changed, we need to recalculate the table size
151 }
152 
154 {
155  //check how much space each column needs
157  {
158  return;
159  }
160  //adapt item frame to max width / height
162 
163  repaint();
164 }
165 
166 bool QgsComposerTable::tableWriteXML( QDomElement& elem, QDomDocument & doc ) const
167 {
168  elem.setAttribute( "lineTextDist", QString::number( mLineTextDistance ) );
169  elem.setAttribute( "headerFont", mHeaderFont.toString() );
170  elem.setAttribute( "contentFont", mContentFont.toString() );
171  elem.setAttribute( "gridStrokeWidth", QString::number( mGridStrokeWidth ) );
172  elem.setAttribute( "gridColorRed", mGridColor.red() );
173  elem.setAttribute( "gridColorGreen", mGridColor.green() );
174  elem.setAttribute( "gridColorBlue", mGridColor.blue() );
175  elem.setAttribute( "showGrid", mShowGrid );
176  return _writeXML( elem, doc );
177 }
178 
179 bool QgsComposerTable::tableReadXML( const QDomElement& itemElem, const QDomDocument& doc )
180 {
181  if ( itemElem.isNull() )
182  {
183  return false;
184  }
185 
186  mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
187  mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
188  mLineTextDistance = itemElem.attribute( "lineTextDist", "1.0" ).toDouble();
189  mGridStrokeWidth = itemElem.attribute( "gridStrokeWidth", "0.5" ).toDouble();
190  mShowGrid = itemElem.attribute( "showGrid", "1" ).toInt();
191 
192  //grid color
193  int gridRed = itemElem.attribute( "gridColorRed", "0" ).toInt();
194  int gridGreen = itemElem.attribute( "gridColorGreen", "0" ).toInt();
195  int gridBlue = itemElem.attribute( "gridColorBlue", "0" ).toInt();
196  mGridColor = QColor( gridRed, gridGreen, gridBlue );
197 
198  //restore general composer item properties
199  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
200  if ( composerItemList.size() > 0 )
201  {
202  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
203  _readXML( composerItemElem, doc );
204  }
205  return true;
206 }
207 
208 bool QgsComposerTable::calculateMaxColumnWidths( QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeMaps ) const
209 {
210  maxWidthMap.clear();
211  QMap<int, QString> headerMap = getHeaderLabels();
212  QMap<int, QString>::const_iterator headerIt = headerMap.constBegin();
213  for ( ; headerIt != headerMap.constEnd(); ++headerIt )
214  {
215  maxWidthMap.insert( headerIt.key(), textWidthMillimeters( mHeaderFont, headerIt.value() ) );
216  }
217 
218  //go through all the attributes and adapt the max width values
219  QList<QgsAttributeMap>::const_iterator attIt = attributeMaps.constBegin();
220 
221  double currentAttributeTextWidth;
222 
223  for ( ; attIt != attributeMaps.constEnd(); ++attIt )
224  {
225  QgsAttributeMap::const_iterator attIt2 = attIt->constBegin();
226  for ( ; attIt2 != attIt->constEnd(); ++attIt2 )
227  {
228  currentAttributeTextWidth = textWidthMillimeters( mContentFont, attIt2.value().toString() );
229  if ( currentAttributeTextWidth > maxWidthMap[ attIt2.key()] )
230  {
231  maxWidthMap[ attIt2.key()] = currentAttributeTextWidth;
232  }
233  }
234  }
235  return true;
236 }
237 
238 void QgsComposerTable::adaptItemFrame( const QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeMaps )
239 {
240  //calculate height
241  int n = attributeMaps.size();
242  double totalHeight = fontAscentMillimeters( mHeaderFont )
244  + ( n + 1 ) * mLineTextDistance * 2
245  + ( n + 2 ) * mGridStrokeWidth;
246 
247  //adapt frame to total width
248  double totalWidth = 0;
249  QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
250  for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
251  {
252  totalWidth += maxColWidthIt.value();
253  }
254  totalWidth += ( 2 * maxWidthMap.size() * mLineTextDistance );
255  totalWidth += ( maxWidthMap.size() + 1 ) * mGridStrokeWidth;
256 
257  QgsComposerItem::setSceneRect( QRectF( pos().x(), pos().y(), totalWidth, totalHeight ) );
258 }
259 
260 void QgsComposerTable::drawHorizontalGridLines( QPainter* p, int nAttributes )
261 {
262  //horizontal lines
263  double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
264  double currentY = halfGridStrokeWidth;
265  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
266  currentY += mGridStrokeWidth;
267  currentY += ( fontAscentMillimeters( mHeaderFont ) + 2 * mLineTextDistance );
268  for ( int i = 0; i < nAttributes; ++i )
269  {
270  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
271  currentY += mGridStrokeWidth;
272  currentY += ( fontAscentMillimeters( mContentFont ) + 2 * mLineTextDistance );
273  }
274  p->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( rect().width() - halfGridStrokeWidth, currentY ) );
275 }
276 
277 void QgsComposerTable::drawVerticalGridLines( QPainter* p, const QMap<int, double>& maxWidthMap )
278 {
279  //vertical lines
280  double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
281  double currentX = halfGridStrokeWidth;
282  p->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, rect().height() - halfGridStrokeWidth ) );
283  currentX += mGridStrokeWidth;
284  QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
285  for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
286  {
287  currentX += ( maxColWidthIt.value() + 2 * mLineTextDistance );
288  p->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, rect().height() - halfGridStrokeWidth ) );
289  currentX += mGridStrokeWidth;
290  }
291 }
292 
293 
294 
void setContentFont(const QFont &f)
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()
QgsComposition * mComposition
Graphics scene for map printing.
virtual bool getFeatureAttributes(QList< QgsAttributeMap > &attributeMaps)
Retrieves feature attributes.
virtual void refreshAttributes()
Refreshes the attributes shown in the table by querying the vector layer for new data.
QgsComposerTable(QgsComposition *composition)
void setHeaderFont(const QFont &f)
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
QList< QgsAttributeMap > mAttributeMaps
bool tableReadXML(const QDomElement &itemElem, const QDomDocument &doc)
virtual 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.
QMap< int, double > mMaxColumnWidthMap
void adaptItemFrame(const QMap< int, double > &maxWidthMap, const QList< QgsAttributeMap > &attributeMaps)
Adapts the size of the item frame to match the content.
QgsComposition::PlotStyle plotStyle() const
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)