[georef] Allow report to flow onto multiple pages to show all

GCPs (fix #4602)
This commit is contained in:
Nyall Dawson 2015-06-22 07:31:13 +10:00
parent 0912314f0c
commit f037b11f8e
9 changed files with 216 additions and 42 deletions

View File

@ -8,7 +8,11 @@ class QgsComposerTableColumn: QObject
%End
public:
QgsComposerTableColumn();
/** Constructor for QgsComposerTableColumn.
* @param heading column heading
*/
QgsComposerTableColumn( const QString& heading = QString() );
virtual ~QgsComposerTableColumn();
/**Writes the column's properties to xml for storage.

View File

@ -46,3 +46,41 @@ class QgsComposerTextTable: QgsComposerTable
*/
// bool getFeatureAttributes( QList<QgsAttributeMap>& attributeMaps );
};
/**A text table item that reads text from string lists
* @note added in QGIS 2.10
*/
class QgsComposerTextTableV2 : QgsComposerTableV2
{
%TypeHeaderCode
#include <qgscomposertexttable.h>
%End
public:
QgsComposerTextTableV2( QgsComposition* c /TransferThis/, bool createUndoCommands );
~QgsComposerTextTableV2();
/** Adds a row to the table
* @param row list of strings to use for each cell's value in the newly added row
* @note If row is shorter than the number of columns in the table than blank cells
* will be inserted at the end of the row. If row co ntains more strings then the number
* of columns in the table then these extra strings will be ignored.
* @note if adding many rows, @link setContents @endlink is much faster
*/
void addRow( const QStringList& row );
/** Sets the contents of the text table.
* @param contents list of table rows
* @see addRow
*/
void setContents( const QList< QStringList >& contents );
bool getTableContents( QgsComposerTableContents &contents );
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true );
};

View File

@ -433,6 +433,7 @@ SET(QGIS_CORE_MOC_HDRS
composer/qgscomposertable.h
composer/qgscomposertablev2.h
composer/qgscomposertablecolumn.h
composer/qgscomposertexttable.h
composer/qgscomposerhtml.h
composer/qgscomposermultiframe.h
composer/qgscomposereffect.h

View File

@ -17,9 +17,10 @@
#include "qgscomposertablecolumn.h"
QgsComposerTableColumn::QgsComposerTableColumn() :
QgsComposerTableColumn::QgsComposerTableColumn( const QString& heading ) :
mBackgroundColor( Qt::transparent ),
mHAlignment( Qt::AlignLeft ),
mHeading( heading ),
mSortByRank( 0 ),
mSortOrder( Qt::AscendingOrder ),
mWidth( 0.0 )
@ -27,6 +28,7 @@ QgsComposerTableColumn::QgsComposerTableColumn() :
}
QgsComposerTableColumn::~QgsComposerTableColumn()
{

View File

@ -30,7 +30,11 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
public:
QgsComposerTableColumn();
/** Constructor for QgsComposerTableColumn.
* @param heading column heading
*/
QgsComposerTableColumn( const QString& heading = QString() );
virtual ~QgsComposerTableColumn();
/**Writes the column's properties to xml for storage.

View File

@ -265,9 +265,6 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
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 )
{
@ -276,6 +273,9 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
refreshAttributes();
}
//calculate which rows to show in this frame
QPair< int, int > rowsToShow = rowRange( renderExtent, frameIndex );
double gridSize = mShowGrid ? mGridStrokeWidth : 0;
QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin();

View File

@ -17,6 +17,7 @@
#include "qgscomposertexttable.h"
#include "qgscomposertablecolumn.h"
#include "qgscomposerframe.h"
QgsComposerTextTable::QgsComposerTextTable( QgsComposition* c ): QgsComposerTable( c )
{
@ -84,3 +85,72 @@ bool QgsComposerTextTable::getFeatureAttributes( QList<QgsAttributeMap>& attribu
return true;
}
QgsComposerTextTableV2::QgsComposerTextTableV2( QgsComposition* c, bool createUndoCommands )
: QgsComposerTableV2( c, createUndoCommands )
{
}
QgsComposerTextTableV2::~QgsComposerTextTableV2()
{
}
void QgsComposerTextTableV2::addRow( const QStringList& row )
{
mRowText.append( row );
refreshAttributes();
}
void QgsComposerTextTableV2::setContents( const QList<QStringList>& contents )
{
mRowText = contents;
refreshAttributes();
}
bool QgsComposerTextTableV2::getTableContents( QgsComposerTableContents& contents )
{
contents.clear();
QList< QStringList >::const_iterator rowIt = mRowText.constBegin();
for ( ; rowIt != mRowText.constEnd(); ++rowIt )
{
QgsComposerTableRow currentRow;
for ( int i = 0; i < mColumns.count(); ++i )
{
if ( i < ( *rowIt ).count() )
{
currentRow << ( *rowIt ).at( i );
}
else
{
currentRow << QString();
}
}
contents << currentRow;
}
recalculateTableSize();
return true;
}
void QgsComposerTextTableV2::addFrame( QgsComposerFrame* frame, bool recalcFrameSizes )
{
mFrameItems.push_back( frame );
connect( frame, SIGNAL( sizeChanged() ), this, SLOT( recalculateFrameSizes() ) );
if ( mComposition )
{
//TODO - if QgsComposerTextTableV2 gains a UI, this will need a dedicated add method
//added to QgsComposition
mComposition->addItem( frame );
}
if ( recalcFrameSizes )
{
recalculateFrameSizes();
}
}

View File

@ -19,6 +19,7 @@
#define QGSCOMPOSERTEXTTABLE_H
#include "qgscomposertable.h"
#include "qgscomposertablev2.h"
/**A text table item that reads text from string lists*/
class CORE_EXPORT QgsComposerTextTable: public QgsComposerTable
@ -70,4 +71,40 @@ class CORE_EXPORT QgsComposerTextTable: public QgsComposerTable
QList< QStringList > mRowText;
};
/**A text table item that reads text from string lists
* @note added in QGIS 2.10
*/
class CORE_EXPORT QgsComposerTextTableV2 : public QgsComposerTableV2
{
Q_OBJECT
public:
QgsComposerTextTableV2( QgsComposition* c, bool createUndoCommands );
~QgsComposerTextTableV2();
/** Adds a row to the table
* @param row list of strings to use for each cell's value in the newly added row
* @note If row is shorter than the number of columns in the table than blank cells
* will be inserted at the end of the row. If row contains more strings then the number
* of columns in the table then these extra strings will be ignored.
* @note if adding many rows, @link setContents @endlink is much faster
*/
void addRow( const QStringList& row );
/** Sets the contents of the text table.
* @param contents list of table rows
* @see addRow
*/
void setContents( const QList< QStringList >& contents );
bool getTableContents( QgsComposerTableContents &contents ) override;
virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) override;
private:
/**One stringlist per row*/
QList< QStringList > mRowText;
};
#endif // QGSCOMPOSERTEXTTABLE_H

View File

@ -38,6 +38,8 @@
#include "qgscomposerlabel.h"
#include "qgscomposermap.h"
#include "qgscomposertexttable.h"
#include "qgscomposertablecolumn.h"
#include "qgscomposerframe.h"
#include "qgsmapcanvas.h"
#include "qgsmapcoordsdialog.h"
#include "qgsmaplayerregistry.h"
@ -1585,15 +1587,11 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
return false;
}
QPrinter printer;
printer.setOutputFormat( QPrinter::PdfFormat );
printer.setOutputFileName( fileName );
//create composition A4 with 300 dpi
QgsComposition* composition = new QgsComposition( mCanvas->mapSettings() );
composition->setPaperSize( 210, 297 ); //A4
composition->setPrintResolution( 300 );
printer.setPaperSize( QSizeF( composition->paperWidth(), composition->paperHeight() ), QPrinter::Millimeter );
composition->setNumPages( 2 );
QFont titleFont;
titleFont.setPointSize( 9 );
@ -1646,10 +1644,8 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
composerMap->zoomToExtent( layerExtent );
composerMap->setMapCanvas( mCanvas );
composition->addItem( composerMap );
printer.setFullPage( true );
printer.setColorMode( QPrinter::Color );
QgsComposerTextTable* parameterTable = 0;
QgsComposerTextTableV2* parameterTable = 0;
double scaleX, scaleY, rotation;
QgsPoint origin;
@ -1667,6 +1663,7 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
residualUnits = tr( "pixels" );
}
QGraphicsRectItem* previousItem = composerMap;
if ( wldTransform )
{
QString parameterTitle = tr( "Transformation parameters" ) + QString( " (" ) + convertTransformEnumToString( transform.transformParametrisation() ) + QString( ")" );
@ -1682,25 +1679,30 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
double meanError = 0;
calculateMeanError( meanError );
parameterTable = new QgsComposerTextTable( composition );
parameterTable = new QgsComposerTextTableV2( composition, false );
parameterTable->setHeaderFont( tableHeaderFont );
parameterTable->setContentFont( tableContentFont );
QStringList headers;
headers << tr( "Translation x" ) << tr( "Translation y" ) << tr( "Scale x" ) << tr( "Scale y" ) << tr( "Rotation [degrees]" ) << tr( "Mean error [%1]" ).arg( residualUnits );
parameterTable->setHeaderLabels( headers );
QgsComposerTableColumns columns;
columns << new QgsComposerTableColumn( tr( "Translation x" ) )
<< new QgsComposerTableColumn( tr( "Translation y" ) )
<< new QgsComposerTableColumn( tr( "Scale x" ) )
<< new QgsComposerTableColumn( tr( "Scale y" ) )
<< new QgsComposerTableColumn( tr( "Rotation [degrees]" ) )
<< new QgsComposerTableColumn( tr( "Mean error [%1]" ).arg( residualUnits ) );
parameterTable->setColumns( columns );
QStringList row;
row << QString::number( origin.x(), 'f', 3 ) << QString::number( origin.y(), 'f', 3 ) << QString::number( scaleX ) << QString::number( scaleY ) << QString::number( rotation * 180 / M_PI ) << QString::number( meanError );
parameterTable->addRow( row );
composition->addItem( parameterTable );
parameterTable->setSceneRect( QRectF( leftMargin, parameterLabel->rect().bottom() + parameterLabel->pos().y() + 5, contentWidth, 20 ) );
parameterTable->setGridStrokeWidth( 0.1 );
parameterTable->adjustFrameToSize();
}
QGraphicsRectItem* previousItem = composerMap;
if ( parameterTable )
{
previousItem = parameterTable;
QgsComposerFrame* tableFrame = new QgsComposerFrame( composition, parameterTable, leftMargin, parameterLabel->rect().bottom() + parameterLabel->pos().y() + 5, contentWidth, 12 );
parameterTable->addFrame( tableFrame );
composition->addItem( tableFrame );
parameterTable->setGridStrokeWidth( 0.1 );
previousItem = tableFrame;
}
QgsComposerLabel* residualLabel = new QgsComposerLabel( composition );
@ -1720,14 +1722,25 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
//necessary for the correct scale bar unit label
resPlotItem->setConvertScaleToMapUnits( residualUnits == tr( "map units" ) );
QgsComposerTextTable* gcpTable = new QgsComposerTextTable( composition );
QgsComposerTextTableV2* gcpTable = new QgsComposerTextTableV2( composition, false );
gcpTable->setHeaderFont( tableHeaderFont );
gcpTable->setContentFont( tableContentFont );
QStringList gcpHeader;
gcpHeader << "id" << "enabled" << "pixelX" << "pixelY" << "mapX" << "mapY" << "resX [" + residualUnits + "]" << "resY [" + residualUnits + "]" << "resTot [" + residualUnits + "]";
gcpTable->setHeaderLabels( gcpHeader );
gcpTable->setHeaderMode( QgsComposerTableV2::AllFrames );
QgsComposerTableColumns columns;
columns << new QgsComposerTableColumn( tr( "ID" ) )
<< new QgsComposerTableColumn( tr( "Enabled" ) )
<< new QgsComposerTableColumn( tr( "Pixel X" ) )
<< new QgsComposerTableColumn( tr( "Pixel Y" ) )
<< new QgsComposerTableColumn( tr( "Map X" ) )
<< new QgsComposerTableColumn( tr( "Map Y" ) )
<< new QgsComposerTableColumn( tr( "Res X (%1)" ).arg( residualUnits ) )
<< new QgsComposerTableColumn( tr( "Res Y (%1)" ).arg( residualUnits ) )
<< new QgsComposerTableColumn( tr( "Res Total (%1)" ).arg( residualUnits ) );
gcpTable->setColumns( columns );
QgsGCPList::const_iterator gcpIt = mPoints.constBegin();
QList< QStringList > gcpTableContents;
for ( ; gcpIt != mPoints.constEnd(); ++gcpIt )
{
QStringList currentGCPStrings;
@ -1745,27 +1758,32 @@ bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsG
}
currentGCPStrings << QString::number(( *gcpIt )->pixelCoords().x(), 'f', 0 ) << QString::number(( *gcpIt )->pixelCoords().y(), 'f', 0 ) << QString::number(( *gcpIt )->mapCoords().x(), 'f', 3 )
<< QString::number(( *gcpIt )->mapCoords().y(), 'f', 3 ) << QString::number( residual.x() ) << QString::number( residual.y() ) << QString::number( residualTot );
gcpTable->addRow( currentGCPStrings );
gcpTableContents << currentGCPStrings ;
}
composition->addItem( gcpTable );
gcpTable->setContents( gcpTableContents );
double firstFrameY = resPlotItem->rect().bottom() + resPlotItem->pos().y() + 5;
double firstFrameHeight = 287 - firstFrameY;
QgsComposerFrame* gcpFirstFrame = new QgsComposerFrame( composition, gcpTable, leftMargin, firstFrameY, contentWidth, firstFrameHeight );
gcpTable->addFrame( gcpFirstFrame );
composition->addItem( gcpFirstFrame );
QgsComposerFrame* gcpSecondFrame = new QgsComposerFrame( composition, gcpTable, leftMargin, 10, contentWidth, 277.0 );
gcpSecondFrame->setItemPosition( leftMargin, 10, QgsComposerItem::UpperLeft, 2 );
gcpSecondFrame->setHidePageIfEmpty( true );
gcpTable->addFrame( gcpSecondFrame );
composition->addItem( gcpSecondFrame );
gcpTable->setSceneRect( QRectF( leftMargin, resPlotItem->rect().bottom() + resPlotItem->pos().y() + 5, contentWidth, 100 ) );
gcpTable->setGridStrokeWidth( 0.1 );
gcpTable->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
printer.setResolution( composition->printResolution() );
QPainter p( &printer );
composition->setPlotStyle( QgsComposition::Print );
QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
composition->render( &p, paperRectPixel, paperRectMM );
composition->exportAsPDF( fileName );
delete titleLabel;
delete parameterLabel;
delete residualLabel;
delete resPlotItem;
delete parameterTable;
delete gcpTable;
delete composerMap;
delete composition;
return true;