diff --git a/python/core/composer/qgscomposerhtml.sip b/python/core/composer/qgscomposerhtml.sip
index 1133c631415..9960c00aefa 100644
--- a/python/core/composer/qgscomposerhtml.sip
+++ b/python/core/composer/qgscomposerhtml.sip
@@ -95,7 +95,8 @@ class QgsComposerHtml: QgsComposerMultiFrame
void setEvaluateExpressions( bool evaluateExpressions );
QSizeF totalSize() const;
- void render( QPainter* p, const QRectF& renderExtent );
+
+ void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const;
bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );
diff --git a/python/core/composer/qgscomposermultiframe.sip b/python/core/composer/qgscomposermultiframe.sip
index 7f6600d3182..266d2edd50b 100644
--- a/python/core/composer/qgscomposermultiframe.sip
+++ b/python/core/composer/qgscomposermultiframe.sip
@@ -28,7 +28,8 @@ class QgsComposerMultiFrame: QgsComposerObject
*/
virtual QSizeF fixedFrameSize() const;
- virtual void render( QPainter* p, const QRectF& renderExtent ) = 0;
+ virtual void render( QPainter* p, const QRectF& renderExtent );
+ virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0;
diff --git a/src/core/composer/qgscomposerframe.cpp b/src/core/composer/qgscomposerframe.cpp
index 19cdc7ce308..cda6c504190 100644
--- a/src/core/composer/qgscomposerframe.cpp
+++ b/src/core/composer/qgscomposerframe.cpp
@@ -106,7 +106,9 @@ void QgsComposerFrame::paint( QPainter* painter, const QStyleOptionGraphicsItem*
drawBackground( painter );
if ( mMultiFrame )
{
- mMultiFrame->render( painter, mSection );
+ //calculate index of frame
+ int frameIndex = mMultiFrame->frameIndex( this );
+ mMultiFrame->render( painter, mSection, frameIndex );
}
drawFrame( painter );
diff --git a/src/core/composer/qgscomposerhtml.cpp b/src/core/composer/qgscomposerhtml.cpp
index 60d8c1a99b3..871a87e5005 100644
--- a/src/core/composer/qgscomposerhtml.cpp
+++ b/src/core/composer/qgscomposerhtml.cpp
@@ -252,8 +252,10 @@ QSizeF QgsComposerHtml::totalSize() const
return mSize;
}
-void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent )
+void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent, const int frameIndex )
{
+ Q_UNUSED( frameIndex );
+
if ( !mWebPage )
{
return;
diff --git a/src/core/composer/qgscomposerhtml.h b/src/core/composer/qgscomposerhtml.h
index 977f7487d3f..64d0b9d99d7 100644
--- a/src/core/composer/qgscomposerhtml.h
+++ b/src/core/composer/qgscomposerhtml.h
@@ -118,7 +118,7 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
void setEvaluateExpressions( bool evaluateExpressions );
QSizeF totalSize() const;
- void render( QPainter* p, const QRectF& renderExtent );
+ void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const;
bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );
diff --git a/src/core/composer/qgscomposermultiframe.cpp b/src/core/composer/qgscomposermultiframe.cpp
index 53a9726c58e..14cd6f26794 100644
--- a/src/core/composer/qgscomposermultiframe.cpp
+++ b/src/core/composer/qgscomposermultiframe.cpp
@@ -40,6 +40,22 @@ QgsComposerMultiFrame::~QgsComposerMultiFrame()
deleteFrames();
}
+void QgsComposerMultiFrame::render( QPainter *p, const QRectF &renderExtent )
+{
+ //base implementation does nothing
+ Q_UNUSED( p );
+ Q_UNUSED( renderExtent );
+}
+
+void QgsComposerMultiFrame::render( QPainter *p, const QRectF &renderExtent, const int frameIndex )
+{
+ Q_UNUSED( frameIndex );
+ //base implementation ignores frameIndex
+ Q_NOWARN_DEPRECATED_PUSH
+ render( p, renderExtent );
+ Q_NOWARN_DEPRECATED_POP
+}
+
void QgsComposerMultiFrame::setResizeMode( ResizeMode mode )
{
if ( mode != mResizeMode )
@@ -307,6 +323,11 @@ QgsComposerFrame* QgsComposerMultiFrame::frame( int i ) const
return mFrameItems.at( i );
}
+int QgsComposerMultiFrame::frameIndex( QgsComposerFrame *frame ) const
+{
+ return mFrameItems.indexOf( frame );
+}
+
bool QgsComposerMultiFrame::_writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames ) const
{
elem.setAttribute( "resizeMode", mResizeMode );
diff --git a/src/core/composer/qgscomposermultiframe.h b/src/core/composer/qgscomposermultiframe.h
index 5b55a83d11b..ba3dc0bd8e0 100644
--- a/src/core/composer/qgscomposermultiframe.h
+++ b/src/core/composer/qgscomposermultiframe.h
@@ -55,7 +55,9 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject
*/
virtual QSizeF fixedFrameSize() const { return QSizeF( 0, 0 ); }
- virtual void render( QPainter* p, const QRectF& renderExtent ) = 0;
+ Q_DECL_DEPRECATED virtual void render( QPainter* p, const QRectF& renderExtent );
+
+ virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0;
@@ -91,8 +93,16 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject
@note added in 2.0, replaces nFrames
**/
int frameCount() const { return mFrameItems.size(); }
+
QgsComposerFrame* frame( int i ) const;
+ /**Returns the index of a frame within the multiframe
+ * @param frame frame to find index of
+ * @returns index for frame if found, -1 if frame not found in multiframe
+ * @note added in version 2.5
+ */
+ int frameIndex( QgsComposerFrame *frame ) const;
+
/**Creates a new frame and adds it to the multi frame and composition.
* @param currentFrame an existing QgsComposerFrame from which to copy the size
* and general frame properties (eg frame style, background, rendering settings).
diff --git a/src/core/composer/qgscomposertablev2.cpp b/src/core/composer/qgscomposertablev2.cpp
index 3b6f00395cf..48417b43a52 100644
--- a/src/core/composer/qgscomposertablev2.cpp
+++ b/src/core/composer/qgscomposertablev2.cpp
@@ -122,20 +122,55 @@ bool QgsComposerTableV2::readXML( const QDomElement &itemElem, const QDomDocumen
QSizeF QgsComposerTableV2::totalSize() const
{
//TODO - handle multiple cell headers
+ //also check height calculation function
+
return mTableSize;
}
-void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
-{
-//do this via rows
- //eg, calculate how rows to->from
- //and render them
+QPair< int, int > QgsComposerTableV2::rowRange( const QRectF extent, const int frameIndex ) const
+{
+ //calculate row height
+ //TODO - handle different header modes
+ //TODO - need to traverse all previous frames to calculate what is visible in each
+ //as the entire height of a frame may not be used for content
+ double headerHeight = 0;
+ double firstHeaderHeight = 2 * mGridStrokeWidth + 2 * mCellMargin + QgsComposerUtils::fontAscentMM( mHeaderFont );
+
+ //int frameNumber = mFrameItems.indexOf( this );
+ if ( frameIndex < 1 )
+ {
+ //currently only header on first
+ headerHeight = firstHeaderHeight;
+ }
+ else
+ {
+ headerHeight = mGridStrokeWidth;
+ }
+
+ //remaining height available for content rows
+ double contentHeight = extent.height() - headerHeight;
+ double rowHeight = mGridStrokeWidth + 2 * mCellMargin + QgsComposerUtils::fontAscentMM( mContentFont );
+
+ //using zero based indexes
+ int firstVisible = qMax( floor(( extent.top() - firstHeaderHeight ) / rowHeight ), 0.0 );
+ int rowsVisible = qMax( floor( contentHeight / rowHeight ), 0.0 );
+ int lastVisible = qMin( firstVisible + rowsVisible, mTableContents.length() );
+
+ return qMakePair( firstVisible, lastVisible );
+}
+
+
+void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const int frameIndex )
+{
if ( !p )
{
return;
}
+ //calculate which rows to show in this frame
+ QPair< int, int > rowsToShow = rowRange( renderExtent, frameIndex );
+
if ( mComposition->plotStyle() == QgsComposition::Print ||
mComposition->plotStyle() == QgsComposition::Postscript )
{
@@ -160,43 +195,52 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
double cellHeaderHeight = QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin;
double cellBodyHeight = QgsComposerUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin;
QRectF cell;
+
+ //TODO - should be controlled via a property, eg an enum with values
+ //always/never/first frame
+ bool drawHeader = frameIndex < 1;
+
for ( ; columnIt != mColumns.constEnd(); ++columnIt )
{
currentY = mGridStrokeWidth;
currentX += mCellMargin;
- cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight );
-
- //calculate alignment of header
- Qt::AlignmentFlag headerAlign = Qt::AlignLeft;
- switch ( mHeaderHAlignment )
+ if ( drawHeader )
{
- case FollowColumn:
- headerAlign = ( *columnIt )->hAlignment();
- break;
- case HeaderLeft:
- headerAlign = Qt::AlignLeft;
- break;
- case HeaderCenter:
- headerAlign = Qt::AlignHCenter;
- break;
- case HeaderRight:
- headerAlign = Qt::AlignRight;
- break;
+ //draw the header
+ cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight );
+
+ //calculate alignment of header
+ Qt::AlignmentFlag headerAlign = Qt::AlignLeft;
+ switch ( mHeaderHAlignment )
+ {
+ case FollowColumn:
+ headerAlign = ( *columnIt )->hAlignment();
+ break;
+ case HeaderLeft:
+ headerAlign = Qt::AlignLeft;
+ break;
+ case HeaderCenter:
+ headerAlign = Qt::AlignHCenter;
+ break;
+ case HeaderRight:
+ headerAlign = Qt::AlignRight;
+ break;
+ }
+
+
+ QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
+
+ currentY += cellHeaderHeight;
+ currentY += mGridStrokeWidth;
}
- QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
-
- currentY += cellHeaderHeight;
- currentY += mGridStrokeWidth;
-
//draw the attribute values
- QgsComposerTableContents::const_iterator attIt = mTableContents.begin();
- for ( ; attIt != mTableContents.end(); ++attIt )
+ for ( int row = rowsToShow.first; row < rowsToShow.second; ++row )
{
cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellBodyHeight );
- QVariant cellContents = ( *attIt ).at( col );
+ QVariant cellContents = mTableContents.at( row ).at( col );
QString str = cellContents.toString();
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip );
@@ -210,6 +254,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
col++;
}
+
//and the borders
if ( mShowGrid )
{
@@ -218,13 +263,12 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent )
gridPen.setColor( mGridColor );
gridPen.setJoinStyle( Qt::MiterJoin );
p->setPen( gridPen );
- drawHorizontalGridLines( p, mTableContents.size() );
- drawVerticalGridLines( p, mMaxColumnWidthMap );
+ drawHorizontalGridLines( p, rowsToShow.second - rowsToShow.first, drawHeader );
+ drawVerticalGridLines( p, mMaxColumnWidthMap, rowsToShow.second - rowsToShow.first, drawHeader );
}
p->restore();
-
}
void QgsComposerTableV2::setCellMargin( const double margin )
@@ -438,14 +482,23 @@ double QgsComposerTableV2::totalHeight() const
return totalHeight;
}
-void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int rows ) const
+void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int rows, const bool drawHeaderLines ) const
{
//horizontal lines
+ if ( rows < 1 && !drawHeaderLines )
+ {
+ return;
+ }
+
double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
- double currentY = halfGridStrokeWidth;
- painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
- currentY += mGridStrokeWidth;
- currentY += ( QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin );
+ double currentY = 0;
+ currentY = halfGridStrokeWidth;
+ if ( drawHeaderLines )
+ {
+ painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
+ currentY += mGridStrokeWidth;
+ currentY += ( QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin );
+ }
for ( int row = 0; row < rows; ++row )
{
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
@@ -455,18 +508,33 @@ void QgsComposerTableV2::drawHorizontalGridLines( QPainter *painter, const int r
painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) );
}
-void QgsComposerTableV2::drawVerticalGridLines( QPainter *painter, const QMap &maxWidthMap ) const
+void QgsComposerTableV2::drawVerticalGridLines( QPainter *painter, const QMap &maxWidthMap, const int numberRows, const bool hasHeader ) const
{
//vertical lines
+ if ( numberRows < 1 && !hasHeader )
+ {
+ return;
+ }
+
+ //calculate height of table within frame
+ double tableHeight = 0;
+ if ( hasHeader )
+ {
+ tableHeight += mGridStrokeWidth + mCellMargin * 2 + QgsComposerUtils::fontAscentMM( mHeaderFont );
+ }
+
+ tableHeight += numberRows * ( mGridStrokeWidth + mCellMargin * 2 + QgsComposerUtils::fontAscentMM( mContentFont ) );
+ tableHeight += mGridStrokeWidth;
+
double halfGridStrokeWidth = mGridStrokeWidth / 2.0;
double currentX = halfGridStrokeWidth;
- painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, mTableSize.height() - halfGridStrokeWidth ) );
+ painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
currentX += mGridStrokeWidth;
QMap::const_iterator maxColWidthIt = maxWidthMap.constBegin();
for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
{
currentX += ( maxColWidthIt.value() + 2 * mCellMargin );
- painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, mTableSize.height() - halfGridStrokeWidth ) );
+ painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
currentX += mGridStrokeWidth;
}
}
diff --git a/src/core/composer/qgscomposertablev2.h b/src/core/composer/qgscomposertablev2.h
index ac40a68dcdd..323cc0d2591 100644
--- a/src/core/composer/qgscomposertablev2.h
+++ b/src/core/composer/qgscomposertablev2.h
@@ -21,6 +21,7 @@
#include "qgscomposermultiframe.h"
#include
#include
+#include
class QgsComposerTableColumn;
@@ -49,6 +50,7 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
{
Q_OBJECT
+
public:
/*! Controls how headers are horizontally aligned in a table
@@ -71,7 +73,9 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
virtual bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false );
virtual QSizeF totalSize() const;
- virtual void render( QPainter* p, const QRectF& renderExtent );
+
+ virtual void render( QPainter* p, const QRectF& renderExtent, const int frameIndex );
+
/**Sets the margin distance between cell borders and their contents.
* @param margin margin for cell contents
@@ -291,22 +295,34 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
double totalHeight() const;
+ /**Calculates a range of rows which should be visible in a given
+ * rectangle.
+ * @param extent visible extent
+ * @param frameIndex index number for frame
+ * @returns row range
+ */
+ QPair rowRange( const QRectF extent, const int frameIndex ) const;
+
+
/**Draws the horizontal grid lines for the table.
* @param painter destination painter for grid lines
* @param rows number of rows shown in table
+ * @param drawHeaderLines set to true to include for the table header
* @see drawVerticalGridLines
*/
- void drawHorizontalGridLines( QPainter* painter, const int rows ) const;
+ void drawHorizontalGridLines( QPainter* painter, const int rows, const bool drawHeaderLines ) const;
/**Draws the vertical grid lines for the table.
* @param painter destination painter for grid lines
* @param maxWidthMap QMap of int to double, where the int contains the column number and the double is the
* maximum width of text present in the column.
+ * @param numberRows number of rows of content in table frame
+ * @param hasHeader set to true if table frame includes header cells
* @note not available in python bindings
* @see drawVerticalGridLines
* @see calculateMaxColumnWidths
*/
- void drawVerticalGridLines( QPainter* painter, const QMap& maxWidthMap ) const;
+ void drawVerticalGridLines( QPainter* painter, const QMap& maxWidthMap, const int numberRows, const bool hasHeader ) const;
void adjustFrameToSize();
};