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