183 changes: 122 additions & 61 deletions src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,30 @@
#include <QDomDocument>
#include <QDomElement>
#include <QGraphicsRectItem>
#include <QPainter>
#include <QSettings>

QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ):
QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ), mSelectionTolerance( 0.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 ), mActiveCommand( 0 )
{
setBackgroundBrush( Qt::gray );
addPaperItem();

//set paper item
mPaperItem = new QgsPaperItem( 0, 0, 297, 210, this ); //default size A4
mPaperItem->setBrush( Qt::white );
addItem( mPaperItem );
mPaperItem->setZValue( 0 );
mPrintResolution = 300; //hardcoded default
loadSettings();
}

QgsComposition::QgsComposition():
QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ),
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 ), mActiveCommand( 0 )
{
loadSettings();
}

QgsComposition::~QgsComposition()
{
delete mPaperItem;

removePaperItems();
// make sure that all composer items are removed before
// this class is deconstructed - to avoid segfaults
// when composer items access in destructor composition that isn't valid anymore
Expand All @@ -66,21 +62,51 @@ QgsComposition::~QgsComposition()

void QgsComposition::setPaperSize( double width, double height )
{
if ( mPaperItem )
mPageWidth = width;
mPageHeight = height;
double currentY = 0;
for ( int i = 0; i < mPages.size(); ++i )
{
mPaperItem->setRect( QRectF( 0, 0, width, height ) );
emit paperSizeChanged();
mPages.at( i )->setSceneRect( QRectF( 0, currentY, width, height ) );
currentY += ( height + mSpaceBetweenPages );
}
}

double QgsComposition::paperHeight() const
{
return mPaperItem->rect().height();
return mPageHeight;
}

double QgsComposition::paperWidth() const
{
return mPaperItem->rect().width();
return mPageWidth;
}

void QgsComposition::setNumPages( int pages )
{
int currentPages = numPages();
int diff = pages - currentPages;
if ( diff >= 0 )
{
for ( int i = 0; i < diff; ++i )
{
addPaperItem();
}
}
else
{
diff = -diff;
for ( int i = 0; i < diff; ++i )
{
delete mPages.last();
mPages.removeLast();
}
}
}

int QgsComposition::numPages() const
{
return mPages.size();
}

QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
Expand All @@ -100,7 +126,8 @@ QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
for ( ; itemIt != itemList.end(); ++itemIt )
{
QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIt );
if ( composerItem && composerItem != mPaperItem )
QgsPaperItem* paperItem = dynamic_cast<QgsPaperItem*>( *itemIt );
if ( composerItem && !paperItem )
{
return composerItem;
}
Expand Down Expand Up @@ -187,11 +214,9 @@ bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
}

QDomElement compositionElem = doc.createElement( "Composition" );
if ( mPaperItem )
{
compositionElem.setAttribute( "paperWidth", QString::number( mPaperItem->rect().width() ) );
compositionElem.setAttribute( "paperHeight", QString::number( mPaperItem->rect().height() ) );
}
compositionElem.setAttribute( "paperWidth", QString::number( mPageWidth ) );
compositionElem.setAttribute( "paperHeight", QString::number( mPageHeight ) );
compositionElem.setAttribute( "numPages", mPages.size() );

//snapping
if ( mSnapToGrid )
Expand Down Expand Up @@ -222,18 +247,19 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
return false;
}

//create paper item
//create pages
bool widthConversionOk, heightConversionOk;
double paperWidth = compositionElem.attribute( "paperWidth" ).toDouble( &widthConversionOk );
double paperHeight = compositionElem.attribute( "paperHeight" ).toDouble( &heightConversionOk );
mPageWidth = compositionElem.attribute( "paperWidth" ).toDouble( &widthConversionOk );
mPageHeight = compositionElem.attribute( "paperHeight" ).toDouble( &heightConversionOk );
int numPages = compositionElem.attribute( "numPages", "1" ).toInt();

if ( widthConversionOk && heightConversionOk )
{
delete mPaperItem;
mPaperItem = new QgsPaperItem( 0, 0, paperWidth, paperHeight, this );
mPaperItem->setBrush( Qt::white );
addItem( mPaperItem );
mPaperItem->setZValue( 0 );
removePaperItems();
for ( int i = 0; i < numPages; ++i )
{
addPaperItem();
}
}

//snapping
Expand All @@ -251,12 +277,7 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
mPrintAsRaster = compositionElem.attribute( "printAsRaster" ).toInt();

mPrintResolution = compositionElem.attribute( "printResolution", "300" ).toInt();

if ( mPaperItem )
{
mPaperItem->update();
}

updatePaperItems();
return true;
}

Expand Down Expand Up @@ -774,11 +795,16 @@ QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
return scenePoint;
}

//snap x coordinate //todo: add support for x- and y- offset
//y offset to current page
int pageNr = ( int )( scenePoint.y() / ( mPageHeight + mSpaceBetweenPages ) );
double yOffset = pageNr * ( mPageHeight + mSpaceBetweenPages );
double yPage = scenePoint.y() - yOffset; //y-coordinate relative to current page

//snap x coordinate
int xRatio = ( int )(( scenePoint.x() - mSnapGridOffsetX ) / mSnapGridResolution + 0.5 );
int yRatio = ( int )(( scenePoint.y() - mSnapGridOffsetY ) / mSnapGridResolution + 0.5 );
int yRatio = ( int )(( yPage - mSnapGridOffsetY ) / mSnapGridResolution + 0.5 );

return QPointF( xRatio * mSnapGridResolution + mSnapGridOffsetX, yRatio * mSnapGridResolution + mSnapGridOffsetY );
return QPointF( xRatio * mSnapGridResolution + mSnapGridOffsetX, yRatio * mSnapGridResolution + mSnapGridOffsetY + yOffset );
}

int QgsComposition::boundingRectOfSelectedItems( QRectF& bRect )
Expand Down Expand Up @@ -824,60 +850,42 @@ int QgsComposition::boundingRectOfSelectedItems( QRectF& bRect )
void QgsComposition::setSnapToGridEnabled( bool b )
{
mSnapToGrid = b;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

void QgsComposition::setSnapGridResolution( double r )
{
mSnapGridResolution = r;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

void QgsComposition::setSnapGridOffsetX( double offset )
{
mSnapGridOffsetX = offset;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

void QgsComposition::setSnapGridOffsetY( double offset )
{
mSnapGridOffsetY = offset;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

void QgsComposition::setGridPen( const QPen& p )
{
mGridPen = p;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

void QgsComposition::setGridStyle( GridStyle s )
{
mGridStyle = s;
if ( mPaperItem )
{
mPaperItem->update();
}
updatePaperItems();
saveSettings();
}

Expand Down Expand Up @@ -1197,3 +1205,56 @@ void QgsComposition::sendItemAddedSignal( QgsComposerItem* item )
return;
}
}

void QgsComposition::updatePaperItems()
{
QList< QgsPaperItem* >::iterator paperIt = mPages.begin();
for ( ; paperIt != mPages.end(); ++paperIt )
{
( *paperIt )->update();
}
}

void QgsComposition::addPaperItem()
{
double paperHeight = this->paperHeight();
double paperWidth = this->paperWidth();
double currentY = paperHeight * mPages.size() + mPages.size() * mSpaceBetweenPages; //add 10mm visible space between pages
QgsPaperItem* paperItem = new QgsPaperItem( 0, currentY, paperWidth, paperHeight, this ); //default size A4
paperItem->setBrush( Qt::white );
addItem( paperItem );
paperItem->setZValue( 0 );
mPages.push_back( paperItem );
}

void QgsComposition::removePaperItems()
{
for ( int i = 0; i < mPages.size(); ++i )
{
delete mPages.at( i );
}
mPages.clear();
}

void QgsComposition::renderPage( QPainter* p, int page )
{
if ( mPages.size() <= page )
{
return;
}

QgsPaperItem* paperItem = mPages[page];
if ( !paperItem )
{
return;
}

QPaintDevice* paintDevice = p->device();
if ( !paintDevice )
{
return;
}

QRectF paperRect = QRectF( paperItem->transform().dx(), paperItem->transform().dy(), paperItem->rect().width(), paperItem->rect().height() );
render( p, QRectF( 0, 0, paintDevice->width(), paintDevice->height() ), paperRect );
}
20 changes: 19 additions & 1 deletion src/core/composer/qgscomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
/**Returns width of paper item*/
double paperWidth() const;

double spaceBetweenPages() const { return mSpaceBetweenPages; }

/**Note: added in version 1.9*/
void setNumPages( int pages );
/**Note: added in version 1.9*/
int numPages() const;

void setSnapToGridEnabled( bool b );
bool snapToGridEnabled() const {return mSnapToGrid;}

Expand Down Expand Up @@ -214,6 +221,10 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
/**Convenience function to create a QgsAddRemoveItemCommand, connect its signals and push it to the undo stack*/
void pushAddRemoveCommand( QgsComposerItem* item, const QString& text, QgsAddRemoveItemCommand::State state = QgsAddRemoveItemCommand::Added );

/**Render a page to a paint device
@note added in version 1.9*/
void renderPage( QPainter* p, int page );

public slots:
/**Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );
Expand All @@ -222,7 +233,10 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
/**Pointer to map renderer of QGIS main map*/
QgsMapRenderer* mMapRenderer;
QgsComposition::PlotStyle mPlotStyle;
QgsPaperItem* mPaperItem;
double mPageWidth;
double mPageHeight;
QList< QgsPaperItem* > mPages;
double mSpaceBetweenPages; //space in preview between pages

/**Maintains z-Order of items. Starts with item at position 1 (position 0 is always paper item)*/
QLinkedList<QgsComposerItem*> mItemZList;
Expand Down Expand Up @@ -262,6 +276,10 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene

void connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c );

void updatePaperItems();
void addPaperItem();
void removePaperItems();

signals:
void paperSizeChanged();

Expand Down
18 changes: 14 additions & 4 deletions src/ui/qgscompositionwidgetbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
</item>
</layout>
</item>
<item row="2" column="0">
<item row="4" column="0">
<widget class="QLabel" name="textLabel7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand All @@ -171,7 +171,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="4" column="1">
<widget class="QComboBox" name="mPaperOrientationComboBox">
<property name="enabled">
<bool>true</bool>
Expand All @@ -184,7 +184,7 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QCheckBox" name="mPrintAsRasterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
Expand All @@ -197,7 +197,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="mResolutionSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
Expand All @@ -216,6 +216,16 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="mNumPagesSpinBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mNumPagesLabel">
<property name="text">
<string>Number of pages</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down