Skip to content

Commit 37dbbd5

Browse files
committedSep 17, 2014
[composer] Begin work on calculating rows for QgsComposerTableV2
(sponsored by City of Uster, Switzerland)
1 parent d1e26f2 commit 37dbbd5

File tree

9 files changed

+170
-49
lines changed

9 files changed

+170
-49
lines changed
 

‎python/core/composer/qgscomposerhtml.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ class QgsComposerHtml: QgsComposerMultiFrame
9595
void setEvaluateExpressions( bool evaluateExpressions );
9696

9797
QSizeF totalSize() const;
98-
void render( QPainter* p, const QRectF& renderExtent );
98+
99+
void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
99100

100101
bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const;
101102
bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );

‎python/core/composer/qgscomposermultiframe.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ class QgsComposerMultiFrame: QgsComposerObject
2828
*/
2929
virtual QSizeF fixedFrameSize() const;
3030

31-
virtual void render( QPainter* p, const QRectF& renderExtent ) = 0;
31+
virtual void render( QPainter* p, const QRectF& renderExtent );
32+
virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
3233

3334
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0;
3435

‎src/core/composer/qgscomposerframe.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ void QgsComposerFrame::paint( QPainter* painter, const QStyleOptionGraphicsItem*
106106
drawBackground( painter );
107107
if ( mMultiFrame )
108108
{
109-
mMultiFrame->render( painter, mSection );
109+
//calculate index of frame
110+
int frameIndex = mMultiFrame->frameIndex( this );
111+
mMultiFrame->render( painter, mSection, frameIndex );
110112
}
111113

112114
drawFrame( painter );

‎src/core/composer/qgscomposerhtml.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,10 @@ QSizeF QgsComposerHtml::totalSize() const
252252
return mSize;
253253
}
254254

255-
void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent )
255+
void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent, const int frameIndex )
256256
{
257+
Q_UNUSED( frameIndex );
258+
257259
if ( !mWebPage )
258260
{
259261
return;

‎src/core/composer/qgscomposerhtml.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
118118
void setEvaluateExpressions( bool evaluateExpressions );
119119

120120
QSizeF totalSize() const;
121-
void render( QPainter* p, const QRectF& renderExtent );
121+
void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
122122

123123
bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const;
124124
bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );

‎src/core/composer/qgscomposermultiframe.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ QgsComposerMultiFrame::~QgsComposerMultiFrame()
4040
deleteFrames();
4141
}
4242

43+
void QgsComposerMultiFrame::render( QPainter *p, const QRectF &renderExtent )
44+
{
45+
//base implementation does nothing
46+
Q_UNUSED( p );
47+
Q_UNUSED( renderExtent );
48+
}
49+
50+
void QgsComposerMultiFrame::render( QPainter *p, const QRectF &renderExtent, const int frameIndex )
51+
{
52+
Q_UNUSED( frameIndex );
53+
//base implementation ignores frameIndex
54+
Q_NOWARN_DEPRECATED_PUSH
55+
render( p, renderExtent );
56+
Q_NOWARN_DEPRECATED_POP
57+
}
58+
4359
void QgsComposerMultiFrame::setResizeMode( ResizeMode mode )
4460
{
4561
if ( mode != mResizeMode )
@@ -307,6 +323,11 @@ QgsComposerFrame* QgsComposerMultiFrame::frame( int i ) const
307323
return mFrameItems.at( i );
308324
}
309325

326+
int QgsComposerMultiFrame::frameIndex( QgsComposerFrame *frame ) const
327+
{
328+
return mFrameItems.indexOf( frame );
329+
}
330+
310331
bool QgsComposerMultiFrame::_writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames ) const
311332
{
312333
elem.setAttribute( "resizeMode", mResizeMode );

‎src/core/composer/qgscomposermultiframe.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject
5555
*/
5656
virtual QSizeF fixedFrameSize() const { return QSizeF( 0, 0 ); }
5757

58-
virtual void render( QPainter* p, const QRectF& renderExtent ) = 0;
58+
Q_DECL_DEPRECATED virtual void render( QPainter* p, const QRectF& renderExtent );
59+
60+
virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
5961

6062
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0;
6163

@@ -91,8 +93,16 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject
9193
@note added in 2.0, replaces nFrames
9294
**/
9395
int frameCount() const { return mFrameItems.size(); }
96+
9497
QgsComposerFrame* frame( int i ) const;
9598

99+
/**Returns the index of a frame within the multiframe
100+
* @param frame frame to find index of
101+
* @returns index for frame if found, -1 if frame not found in multiframe
102+
* @note added in version 2.5
103+
*/
104+
int frameIndex( QgsComposerFrame *frame ) const;
105+
96106
/**Creates a new frame and adds it to the multi frame and composition.
97107
* @param currentFrame an existing QgsComposerFrame from which to copy the size
98108
* and general frame properties (eg frame style, background, rendering settings).

‎src/core/composer/qgscomposertablev2.cpp

Lines changed: 108 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,55 @@ bool QgsComposerTableV2::readXML( const QDomElement &itemElem, const QDomDocumen
122122
QSizeF QgsComposerTableV2::totalSize() const
123123
{
124124
//TODO - handle multiple cell headers
125+
//also check height calculation function
126+
125127
return mTableSize;
126128
}
127129

128-
void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
130+
131+
QPair< int, int > QgsComposerTableV2::rowRange( const QRectF extent, const int frameIndex ) const
129132
{
130-
//do this via rows
131-
//eg, calculate how rows to->from
132-
//and render them
133+
//calculate row height
134+
//TODO - handle different header modes
135+
//TODO - need to traverse all previous frames to calculate what is visible in each
136+
//as the entire height of a frame may not be used for content
137+
double headerHeight = 0;
138+
double firstHeaderHeight = 2 * mGridStrokeWidth + 2 * mCellMargin + QgsComposerUtils::fontAscentMM( mHeaderFont );
139+
140+
//int frameNumber = mFrameItems.indexOf( this );
141+
if ( frameIndex < 1 )
142+
{
143+
//currently only header on first
144+
headerHeight = firstHeaderHeight;
145+
}
146+
else
147+
{
148+
headerHeight = mGridStrokeWidth;
149+
}
150+
151+
//remaining height available for content rows
152+
double contentHeight = extent.height() - headerHeight;
153+
double rowHeight = mGridStrokeWidth + 2 * mCellMargin + QgsComposerUtils::fontAscentMM( mContentFont );
154+
155+
//using zero based indexes
156+
int firstVisible = qMax( floor(( extent.top() - firstHeaderHeight ) / rowHeight ), 0.0 );
157+
int rowsVisible = qMax( floor( contentHeight / rowHeight ), 0.0 );
158+
int lastVisible = qMin( firstVisible + rowsVisible, mTableContents.length() );
159+
160+
return qMakePair( firstVisible, lastVisible );
161+
}
133162

163+
164+
void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const int frameIndex )
165+
{
134166
if ( !p )
135167
{
136168
return;
137169
}
138170

171+
//calculate which rows to show in this frame
172+
QPair< int, int > rowsToShow = rowRange( renderExtent, frameIndex );
173+
139174
if ( mComposition->plotStyle() == QgsComposition::Print ||
140175
mComposition->plotStyle() == QgsComposition::Postscript )
141176
{
@@ -160,43 +195,52 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
160195
double cellHeaderHeight = QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin;
161196
double cellBodyHeight = QgsComposerUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin;
162197
QRectF cell;
198+
199+
//TODO - should be controlled via a property, eg an enum with values
200+
//always/never/first frame
201+
bool drawHeader = frameIndex < 1;
202+
163203
for ( ; columnIt != mColumns.constEnd(); ++columnIt )
164204
{
165205
currentY = mGridStrokeWidth;
166206
currentX += mCellMargin;
167207

168-
cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight );
169-
170-
//calculate alignment of header
171-
Qt::AlignmentFlag headerAlign = Qt::AlignLeft;
172-
switch ( mHeaderHAlignment )
208+
if ( drawHeader )
173209
{
174-
case FollowColumn:
175-
headerAlign = ( *columnIt )->hAlignment();
176-
break;
177-
case HeaderLeft:
178-
headerAlign = Qt::AlignLeft;
179-
break;
180-
case HeaderCenter:
181-
headerAlign = Qt::AlignHCenter;
182-
break;
183-
case HeaderRight:
184-
headerAlign = Qt::AlignRight;
185-
break;
210+
//draw the header
211+
cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight );
212+
213+
//calculate alignment of header
214+
Qt::AlignmentFlag headerAlign = Qt::AlignLeft;
215+
switch ( mHeaderHAlignment )
216+
{
217+
case FollowColumn:
218+
headerAlign = ( *columnIt )->hAlignment();
219+
break;
220+
case HeaderLeft:
221+
headerAlign = Qt::AlignLeft;
222+
break;
223+
case HeaderCenter:
224+
headerAlign = Qt::AlignHCenter;
225+
break;
226+
case HeaderRight:
227+
headerAlign = Qt::AlignRight;
228+
break;
229+
}
230+
231+
232+
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
233+
234+
currentY += cellHeaderHeight;
235+
currentY += mGridStrokeWidth;
186236
}
187237

188-
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
189-
190-
currentY += cellHeaderHeight;
191-
currentY += mGridStrokeWidth;
192-
193238
//draw the attribute values
194-
QgsComposerTableContents::const_iterator attIt = mTableContents.begin();
195-
for ( ; attIt != mTableContents.end(); ++attIt )
239+
for ( int row = rowsToShow.first; row < rowsToShow.second; ++row )
196240
{
197241
cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellBodyHeight );
198242

199-
QVariant cellContents = ( *attIt ).at( col );
243+
QVariant cellContents = mTableContents.at( row ).at( col );
200244
QString str = cellContents.toString();
201245
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip );
202246

@@ -210,6 +254,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
210254
col++;
211255
}
212256

257+
213258
//and the borders
214259
if ( mShowGrid )
215260
{
@@ -218,13 +263,12 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
218263
gridPen.setColor( mGridColor );
219264
gridPen.setJoinStyle( Qt::MiterJoin );
220265
p->setPen( gridPen );
221-
drawHorizontalGridLines( p, mTableContents.size() );
222-
drawVerticalGridLines( p, mMaxColumnWidthMap );
266+
drawHorizontalGridLines( p, rowsToShow.second - rowsToShow.first, drawHeader );
267+
drawVerticalGridLines( p, mMaxColumnWidthMap, rowsToShow.second - rowsToShow.first, drawHeader );
223268
}
224269

225270
p->restore();
226271

227-
228272
}
229273

230274
void QgsComposerTableV2::setCellMargin( const double margin )
@@ -438,14 +482,23 @@ double QgsComposerTableV2::totalHeight() const
438482
return totalHeight;
439483
}
440484

441-
void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int rows ) const
485+
void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int rows, const bool drawHeaderLines ) const
442486
{
443487
//horizontal lines
488+
if ( rows < 1 && !drawHeaderLines )
489+
{
490+
return;
491+
}
492+
444493
double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
445-
double currentY = halfGridStrokeWidth;
446-
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
447-
currentY += mGridStrokeWidth;
448-
currentY += ( QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin );
494+
double currentY = 0;
495+
currentY = halfGridStrokeWidth;
496+
if ( drawHeaderLines )
497+
{
498+
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
499+
currentY += mGridStrokeWidth;
500+
currentY += ( QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin );
501+
}
449502
for ( int row = 0; row < rows; ++row )
450503
{
451504
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
@@ -455,18 +508,33 @@ void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int r
455508
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
456509
}
457510

458-
void QgsComposerTableV2::drawVerticalGridLines( QPainter *painter, const QMap<int, double> &maxWidthMap ) const
511+
void QgsComposerTableV2::drawVerticalGridLines( QPainter *painter, const QMap<int, double> &maxWidthMap, const int numberRows, const bool hasHeader ) const
459512
{
460513
//vertical lines
514+
if ( numberRows < 1 && !hasHeader )
515+
{
516+
return;
517+
}
518+
519+
//calculate height of table within frame
520+
double tableHeight = 0;
521+
if ( hasHeader )
522+
{
523+
tableHeight += mGridStrokeWidth + mCellMargin * 2 + QgsComposerUtils::fontAscentMM( mHeaderFont );
524+
}
525+
526+
tableHeight += numberRows * ( mGridStrokeWidth + mCellMargin * 2 + QgsComposerUtils::fontAscentMM( mContentFont ) );
527+
tableHeight += mGridStrokeWidth;
528+
461529
double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
462530
double currentX = halfGridStrokeWidth;
463-
painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, mTableSize.height() - halfGridStrokeWidth ) );
531+
painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
464532
currentX += mGridStrokeWidth;
465533
QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
466534
for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
467535
{
468536
currentX += ( maxColWidthIt.value() + 2 * mCellMargin );
469-
painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, mTableSize.height() - halfGridStrokeWidth ) );
537+
painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
470538
currentX += mGridStrokeWidth;
471539
}
472540
}

‎src/core/composer/qgscomposertablev2.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgscomposermultiframe.h"
2222
#include <QFont>
2323
#include <QColor>
24+
#include <QPair>
2425

2526
class QgsComposerTableColumn;
2627

@@ -49,6 +50,7 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
4950
{
5051
Q_OBJECT
5152

53+
5254
public:
5355

5456
/*! Controls how headers are horizontally aligned in a table
@@ -71,7 +73,9 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
7173
virtual bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );
7274

7375
virtual QSizeF totalSize() const;
74-
virtual void render( QPainter* p, const QRectF& renderExtent );
76+
77+
virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
78+
7579

7680
/**Sets the margin distance between cell borders and their contents.
7781
* @param margin margin for cell contents
@@ -291,22 +295,34 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
291295

292296
double totalHeight() const;
293297

298+
/**Calculates a range of rows which should be visible in a given
299+
* rectangle.
300+
* @param extent visible extent
301+
* @param frameIndex index number for frame
302+
* @returns row range
303+
*/
304+
QPair<int, int> rowRange( const QRectF extent, const int frameIndex ) const;
305+
306+
294307
/**Draws the horizontal grid lines for the table.
295308
* @param painter destination painter for grid lines
296309
* @param rows number of rows shown in table
310+
* @param drawHeaderLines set to true to include for the table header
297311
* @see drawVerticalGridLines
298312
*/
299-
void drawHorizontalGridLines( QPainter* painter, const int rows ) const;
313+
void drawHorizontalGridLines( QPainter* painter, const int rows, const bool drawHeaderLines ) const;
300314

301315
/**Draws the vertical grid lines for the table.
302316
* @param painter destination painter for grid lines
303317
* @param maxWidthMap QMap of int to double, where the int contains the column number and the double is the
304318
* maximum width of text present in the column.
319+
* @param numberRows number of rows of content in table frame
320+
* @param hasHeader set to true if table frame includes header cells
305321
* @note not available in python bindings
306322
* @see drawVerticalGridLines
307323
* @see calculateMaxColumnWidths
308324
*/
309-
void drawVerticalGridLines( QPainter* painter, const QMap<int, double>& maxWidthMap ) const;
325+
void drawVerticalGridLines( QPainter* painter, const QMap<int, double>& maxWidthMap, const int numberRows, const bool hasHeader ) const;
310326

311327
void adjustFrameToSize();
312328
};

0 commit comments

Comments
 (0)
Please sign in to comment.