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