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