Skip to content
Permalink
Browse files

fix destruction of private members in atlas and add sip bindings (als…

…o adds

CORE_EXPORT)
  • Loading branch information
jef-n committed Sep 29, 2012
1 parent 0c29b4b commit 686f632f328217077f093c1755a8ef7c14508db3
Showing with 129 additions and 81 deletions.
  1. +50 −7 python/core/composer/qgscomposition.sip
  2. +61 −56 src/core/composer/qgscomposition.cpp
  3. +18 −18 src/core/composer/qgscomposition.h
@@ -1,10 +1,36 @@
/** \ingroup MapComposer
* Class used to render an Atlas, iterating over geometry features.
* prepareForFeature() modifies the atlas map's extent to zoom on the given feature.
* This class is used for printing, exporting to PDF and images.
* */
class QgsAtlasRendering
{
public:
QgsAtlasRendering( QgsComposition* composition );
~QgsAtlasRendering();

/** Begins the rendering. Sets an optional output filename pattern */
void begin( const QString& filenamePattern = "" );
/** Ends the rendering. Restores original extent*/
void end();

/** Returns the number of features in the coverage layer */
size_t numFeatures() const;

/** Prepare the atlas map for the given feature. Sets the extent and context variables */
void prepareForFeature( size_t i );

/** Returns the current filename. Must be called after prepareForFeature( i ) */
const QString& currentFilename() const;
};

/** \ingroup MapComposer
* Graphics scene for map printing. The class manages the paper item which always
* is the item in the back (z-value 0). It maintains the z-Values of the items and stores
* them in a list in ascending z-Order. This list can be changed to lower/raise items one position
* or to bring them to front/back.
* */
class QgsComposition: QGraphicsScene
class QgsComposition : QGraphicsScene
{
%TypeHeaderCode
#include <qgscomposition.h>
@@ -67,20 +93,25 @@ class QgsComposition: QGraphicsScene
/**Returns pointer to undo/redo command storage*/
QUndoStack* undoStack();

/**Returns the topmose composer item. Ignores mPaperItem*/
/**Returns the topmost composer item. Ignores mPaperItem*/
QgsComposerItem* composerItemAt( const QPointF & position );

/** Returns the page number (0-bsaed) given a coordinate */
int pageNumberAt( const QPointF& position ) const;

/** Returns on which page number (0-based) is displayed an item */
int itemPageNumber( const QgsComposerItem* ) const;

QList<QgsComposerItem*> selectedComposerItems();

/**Returns pointers to all composer maps in the scene*/
//todo: needs a new mapping for QList<const T*> ?
// QList<const QgsComposerMap*> composerMapItems() const;
QList<const QgsComposerMap*> composerMapItems() const;

/**Return composer items of a specific type*/
// template<class T> void composerItems( QList<T*>& itemList );

/**Returns the composer map with specified id
@return id or 0 pointer if the composer map item does not exist*/
@return QgsComposerMap or 0 pointer if the composer map item does not exist*/
const QgsComposerMap* getComposerMapById( int id ) const;

/*Returns the composer html with specified id (a string as named in the
@@ -111,7 +142,10 @@ class QgsComposition: QGraphicsScene
/**Returns pointer to map renderer of qgis map canvas*/
QgsMapRenderer* mapRenderer();

QgsComposition::PlotStyle plotStyle();
QgsComposerMap* atlasMap();
void setAtlasMap( QgsComposerMap* map );

QgsComposition::PlotStyle plotStyle() const;
void setPlotStyle( QgsComposition::PlotStyle style );

/**Returns the pixel font size for a font that has point size set.
@@ -219,10 +253,19 @@ class QgsComposition: QGraphicsScene

//printing

void exportAsPDF( const QString& file );
/** Prepare the printer for printing */
void beginPrint( QPrinter& printer );
/** Prepare the printer for printing in a PDF */
void beginPrintAsPDF( QPrinter& printer, const QString& file );
/** Print on a preconfigured printer */
void doPrint( QPrinter& printer, QPainter& painter );

/** Convenience function that prepares the printer and prints */
void print( QPrinter &printer );

/** Convenience function that prepares the printer for printing in PDF and prints */
void exportAsPDF( const QString& file );

//! print composer page to image
//! If the image does not fit into memory, a null image is returned
QImage printPageAsRaster( int page );
@@ -67,11 +67,16 @@ struct QgsAtlasRendering::QgsAtlasRenderingImpl

QgsAtlasRendering::QgsAtlasRendering( QgsComposition* composition )
{
impl = std::auto_ptr<QgsAtlasRendering::QgsAtlasRenderingImpl>( new QgsAtlasRendering::QgsAtlasRenderingImpl() );
impl = new QgsAtlasRendering::QgsAtlasRenderingImpl();
impl->composition = composition;
impl->nFeatures = 0;
}

QgsAtlasRendering::~QgsAtlasRendering()
{
delete impl;
}

void QgsAtlasRendering::begin( const QString& filenamePattern )
{
if ( !impl->composition || !impl->composition->atlasMap() || !impl->composition->atlasMap()->atlasCoverageLayer() )
@@ -131,7 +136,7 @@ void QgsAtlasRendering::begin( const QString& filenamePattern )
}

// special columns for expressions
QgsExpression::setSpecialColumn( "$numfeatures", QVariant( (int)impl->nFeatures ) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )impl->nFeatures ) );
}

void QgsAtlasRendering::prepareForFeature( size_t featureI )
@@ -140,24 +145,24 @@ void QgsAtlasRendering::prepareForFeature( size_t featureI )
return;

QgsFeature* fit = &impl->features[featureI];

if ( impl->filenamePattern.size() > 0 )
{
QgsExpression::setSpecialColumn( "$feature", QVariant( (int)featureI + 1 ) );
QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );
QVariant filenameRes = impl->filenameExpr->evaluate( &*fit );
if ( impl->filenameExpr->hasEvalError() )
{
throw std::runtime_error( "Filename eval error: " + impl->filenameExpr->evalErrorString().toStdString() );
}

impl->currentFilename = filenameRes.toString();
}

//
// compute the new extent
// keep the original aspect ratio
// and apply a margin

// QgsGeometry::boundingBox is expressed in the geometry"s native CRS
// We have to transform the grometry to the destination CRS and ask for the bounding box
// Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
@@ -171,63 +176,63 @@ void QgsAtlasRendering::prepareForFeature( size_t featureI )
double ya1 = geom_rect.yMinimum();
double ya2 = geom_rect.yMaximum();
QgsRectangle new_extent = geom_rect;

// restore the original extent
// (successive calls to setNewExtent tend to deform the original rectangle)
impl->composition->atlasMap()->setNewExtent( impl->origExtent );

if ( impl->composition->atlasMap()->atlasFixedScale() )
{
// only translate, keep the original scale (i.e. width x height)
double geom_center_x = (xa1 + xa2) / 2.0;
double geom_center_y = (ya1 + ya2) / 2.0;

double geom_center_x = ( xa1 + xa2 ) / 2.0;
double geom_center_y = ( ya1 + ya2 ) / 2.0;
double xx = geom_center_x - impl->origExtent.width() / 2.0;
double yy = geom_center_y - impl->origExtent.height() / 2.0;
new_extent = QgsRectangle( xx,
yy,
xx + impl->origExtent.width(),
yy + impl->origExtent.height() );
yy,
xx + impl->origExtent.width(),
yy + impl->origExtent.height() );
}
else
{
// auto scale

double geom_ratio = geom_rect.width() / geom_rect.height();
double map_ratio = impl->origExtent.width() / impl->origExtent.height();

// geometry height is too big
if ( geom_ratio < map_ratio )
{
new_extent = QgsRectangle( (xa1 + xa2 + map_ratio * (ya1 - ya2)) / 2.0,
ya1,
xa1 + map_ratio * (ya2 - ya1),
ya2);
new_extent = QgsRectangle(( xa1 + xa2 + map_ratio * ( ya1 - ya2 ) ) / 2.0,
ya1,
xa1 + map_ratio * ( ya2 - ya1 ),
ya2 );
}
// geometry width is too big
else if ( geom_ratio > map_ratio )
{
new_extent = QgsRectangle( xa1,
(ya1 + ya2 + (xa1 - xa2) / map_ratio) / 2.0,
xa2,
ya1 + (xa2 - xa1) / map_ratio);
( ya1 + ya2 + ( xa1 - xa2 ) / map_ratio ) / 2.0,
xa2,
ya1 + ( xa2 - xa1 ) / map_ratio );
}
if ( impl->composition->atlasMap()->atlasMargin() > 0.0 )
{
new_extent.scale( 1 + impl->composition->atlasMap()->atlasMargin() );
}
}

// evaluate label expressions
QList<QgsComposerLabel*> labels;
impl->composition->composerItems( labels );
QgsExpression::setSpecialColumn( "$feature", QVariant( (int)featureI + 1 ) );
QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );

for ( QList<QgsComposerLabel*>::iterator lit = labels.begin(); lit != labels.end(); ++lit )
{
(*lit)->setExpressionContext( fit, impl->composition->atlasMap()->atlasCoverageLayer() );
( *lit )->setExpressionContext( fit, impl->composition->atlasMap()->atlasCoverageLayer() );
}

// set the new extent (and render)
impl->composition->atlasMap()->setNewExtent( new_extent );
}
@@ -252,7 +257,7 @@ void QgsAtlasRendering::end()
impl->composition->composerItems( labels );
for ( QList<QgsComposerLabel*>::iterator lit = labels.begin(); lit != labels.end(); ++lit )
{
(*lit)->setExpressionContext( 0, 0 );
( *lit )->setExpressionContext( 0, 0 );
}

// restore the coverage visibility
@@ -269,9 +274,9 @@ void QgsAtlasRendering::end()
}

QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) :
QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ), mSelectionTolerance( 0.0 ),
mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ),
mAtlasMap( 0 )
QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ), mSelectionTolerance( 0.0 ),
mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ),
mAtlasMap( 0 )
{
setBackgroundBrush( Qt::gray );
addPaperItem();
@@ -280,23 +285,23 @@ QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) :
loadSettings();

// declare special columns with a default value
QgsExpression::setSpecialColumn( "$page", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$feature", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$numpages", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$page", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
}

QgsComposition::QgsComposition():
QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ),
mSelectionTolerance( 0.0 ), mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ),
mAtlasMap( 0 )
QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ),
mSelectionTolerance( 0.0 ), mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ),
mAtlasMap( 0 )
{
loadSettings();

QgsExpression::setSpecialColumn( "$page", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$feature", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$numpages", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$page", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )0 ) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
}

QgsComposition::~QgsComposition()
@@ -356,7 +361,7 @@ void QgsComposition::setNumPages( int pages )
}

// update the corresponding variable
QgsExpression::setSpecialColumn( "$numpages", QVariant((int)numPages()) );
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )numPages() ) );

emit nPagesChanged();
}
@@ -394,12 +399,12 @@ QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )

int QgsComposition::pageNumberAt( const QPointF& position ) const
{
return position.y() / (paperHeight() + spaceBetweenPages() );
return position.y() / ( paperHeight() + spaceBetweenPages() );
}

int QgsComposition::itemPageNumber( const QgsComposerItem* item ) const
{
return pageNumberAt( QPointF( item->transform().dx(), item->transform().dy()) );
return pageNumberAt( QPointF( item->transform().dx(), item->transform().dy() ) );
}

QList<QgsComposerItem*> QgsComposition::selectedComposerItems()
@@ -1715,7 +1720,7 @@ void QgsComposition::addPaperItem()
paperItem->setZValue( 0 );
mPages.push_back( paperItem );

QgsExpression::setSpecialColumn( "$numpages", QVariant((int)mPages.size()) );
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )mPages.size() ) );
}

void QgsComposition::removePaperItems()
@@ -1725,7 +1730,7 @@ void QgsComposition::removePaperItems()
delete mPages.at( i );
}
mPages.clear();
QgsExpression::setSpecialColumn( "$numpages", QVariant((int)0) );
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )0 ) );
}

void QgsComposition::deleteAndRemoveMultiFrames()
@@ -1756,7 +1761,7 @@ void QgsComposition::exportAsPDF( const QString& file )

void QgsComposition::doPrint( QPrinter& printer, QPainter& p )
{
//QgsComposition starts page numbering at 0
//QgsComposition starts page numbering at 0
int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1 ;
int toPage = ( printer.toPage() < 1 ) ? numPages() - 1 : printer.toPage() - 1;

@@ -1859,11 +1864,11 @@ void QgsComposition::setAtlasMap( QgsComposerMap* map )
mAtlasMap = map;
if ( map != 0 )
{
QObject::connect( map, SIGNAL( atlasCoverageLayerChanged( QgsVectorLayer* )), this, SLOT( onAtlasCoverageChanged( QgsVectorLayer* ) ) );
QObject::connect( map, SIGNAL( atlasCoverageLayerChanged( QgsVectorLayer* ) ), this, SLOT( onAtlasCoverageChanged( QgsVectorLayer* ) ) );
}
else
{
QObject::disconnect( map, SIGNAL( atlasCoverageLayerChanged( QgsVectorLayer* )), this, SLOT( onAtlasCoverageChanged( QgsVectorLayer* ) ) );
QObject::disconnect( map, SIGNAL( atlasCoverageLayerChanged( QgsVectorLayer* ) ), this, SLOT( onAtlasCoverageChanged( QgsVectorLayer* ) ) );
}
}

@@ -1873,14 +1878,14 @@ void QgsComposition::onAtlasCoverageChanged( QgsVectorLayer* )
if ( mAtlasMap != 0 && mAtlasMap->atlasCoverageLayer() != 0 )
{
QgsVectorDataProvider* provider = mAtlasMap->atlasCoverageLayer()->dataProvider();
QgsExpression::setSpecialColumn( "$numfeatures", QVariant( (int)provider->featureCount() ) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )provider->featureCount() ) );
}
else
{
QgsExpression::setSpecialColumn( "$numfeatures", QVariant( (int)0 ) );
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
}
//
QgsExpression::setSpecialColumn( "$numpages", QVariant( (int)numPages() ) );
//
QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )numPages() ) );
}

QString QgsComposition::encodeStringForXML( const QString& str )

0 comments on commit 686f632

Please sign in to comment.
You can’t perform that action at this time.