mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-27 00:07:16 -05:00
364 lines
11 KiB
C++
364 lines
11 KiB
C++
/***************************************************************************
|
|
qgscomposermultiframe.cpp
|
|
------------------------------------------------------------
|
|
begin : July 2012
|
|
copyright : (C) 2012 by Marco Hugentobler
|
|
email : marco dot hugentobler at sourcepole dot ch
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgscomposermultiframe.h"
|
|
#include "qgscomposerframe.h"
|
|
#include "qgscomposition.h"
|
|
#include <QtCore>
|
|
|
|
QgsComposerMultiFrame::QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands ):
|
|
QgsComposerObject( c ),
|
|
mResizeMode( UseExistingFrames ),
|
|
mCreateUndoCommands( createUndoCommands ),
|
|
mIsRecalculatingSize( false )
|
|
{
|
|
mComposition->addMultiFrame( this );
|
|
connect( mComposition, SIGNAL( nPagesChanged() ), this, SLOT( handlePageChange() ) );
|
|
}
|
|
|
|
QgsComposerMultiFrame::QgsComposerMultiFrame():
|
|
QgsComposerObject( 0 ),
|
|
mResizeMode( UseExistingFrames ),
|
|
mIsRecalculatingSize( false )
|
|
{
|
|
}
|
|
|
|
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 )
|
|
{
|
|
mResizeMode = mode;
|
|
recalculateFrameSizes();
|
|
emit changed();
|
|
}
|
|
}
|
|
|
|
void QgsComposerMultiFrame::recalculateFrameSizes()
|
|
{
|
|
if ( mFrameItems.size() < 1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QSizeF size = totalSize();
|
|
double totalHeight = size.height();
|
|
|
|
if ( totalHeight < 1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
double currentY = 0;
|
|
double currentHeight = 0;
|
|
QgsComposerFrame* currentItem = 0;
|
|
|
|
for ( int i = 0; i < mFrameItems.size(); ++i )
|
|
{
|
|
if ( mResizeMode != RepeatOnEveryPage && currentY >= totalHeight )
|
|
{
|
|
if ( mResizeMode == RepeatUntilFinished || mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
|
|
{
|
|
for ( int j = mFrameItems.size(); j > i; --j )
|
|
{
|
|
removeFrame( j - 1 );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
currentItem = mFrameItems.value( i );
|
|
currentHeight = currentItem->rect().height();
|
|
if ( mResizeMode == RepeatOnEveryPage )
|
|
{
|
|
currentItem->setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
|
|
}
|
|
else
|
|
{
|
|
currentHeight = findNearbyPageBreak( currentY + currentHeight ) - currentY;
|
|
currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
|
|
}
|
|
currentItem->update();
|
|
currentY += currentHeight;
|
|
}
|
|
|
|
//at end of frames but there is still content left. Add other pages if ResizeMode ==
|
|
if ( mResizeMode != UseExistingFrames )
|
|
{
|
|
while (( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
|
|
{
|
|
//find out on which page the lower left point of the last frame is
|
|
int page = qFloor(( currentItem->pos().y() + currentItem->rect().height() ) / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() ) ) + 1;
|
|
|
|
if ( mResizeMode == RepeatOnEveryPage )
|
|
{
|
|
if ( page >= mComposition->numPages() )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add an extra page if required
|
|
if ( mComposition->numPages() < ( page + 1 ) )
|
|
{
|
|
mComposition->setNumPages( page + 1 );
|
|
}
|
|
}
|
|
|
|
double frameHeight = 0;
|
|
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
|
|
{
|
|
frameHeight = currentItem->rect().height();
|
|
}
|
|
else //mResizeMode == ExtendToNextPage
|
|
{
|
|
frameHeight = ( currentY + mComposition->paperHeight() ) > totalHeight ? totalHeight - currentY : mComposition->paperHeight();
|
|
}
|
|
|
|
double newFrameY = page * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
|
|
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
|
|
{
|
|
newFrameY += currentItem->pos().y() - ( page - 1 ) * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
|
|
}
|
|
|
|
//create new frame
|
|
QgsComposerFrame* newFrame = createNewFrame( currentItem,
|
|
QPointF( currentItem->pos().x(), newFrameY ),
|
|
QSizeF( currentItem->rect().width(), frameHeight ) );
|
|
|
|
if ( mResizeMode == RepeatOnEveryPage )
|
|
{
|
|
newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
|
|
currentY += frameHeight;
|
|
}
|
|
else
|
|
{
|
|
double contentHeight = findNearbyPageBreak( currentY + newFrame->rect().height() ) - currentY;
|
|
newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), contentHeight ) );
|
|
currentY += contentHeight;
|
|
}
|
|
|
|
currentItem = newFrame;
|
|
}
|
|
}
|
|
}
|
|
|
|
QgsComposerFrame* QgsComposerMultiFrame::createNewFrame( QgsComposerFrame* currentFrame, QPointF pos, QSizeF size )
|
|
{
|
|
if ( !currentFrame )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, pos.x(),
|
|
pos.y(), size.width(), size.height() );
|
|
|
|
//copy some settings from the parent frame
|
|
newFrame->setBackgroundColor( currentFrame->backgroundColor() );
|
|
newFrame->setBackgroundEnabled( currentFrame->hasBackground() );
|
|
newFrame->setBlendMode( currentFrame->blendMode() );
|
|
newFrame->setFrameEnabled( currentFrame->hasFrame() );
|
|
newFrame->setFrameJoinStyle( currentFrame->frameJoinStyle() );
|
|
newFrame->setFrameOutlineWidth( currentFrame->frameOutlineWidth() );
|
|
newFrame->setOpacity( currentFrame->opacity() );
|
|
|
|
addFrame( newFrame, false );
|
|
|
|
return newFrame;
|
|
}
|
|
|
|
QString QgsComposerMultiFrame::displayName() const
|
|
{
|
|
return tr( "<frame>" );
|
|
}
|
|
|
|
void QgsComposerMultiFrame::handleFrameRemoval( QgsComposerItem* item )
|
|
{
|
|
QgsComposerFrame* frame = dynamic_cast<QgsComposerFrame*>( item );
|
|
if ( !frame )
|
|
{
|
|
return;
|
|
}
|
|
int index = mFrameItems.indexOf( frame );
|
|
if ( index == -1 )
|
|
{
|
|
return;
|
|
}
|
|
mFrameItems.removeAt( index );
|
|
if ( mFrameItems.size() > 0 )
|
|
{
|
|
if ( resizeMode() != QgsComposerMultiFrame::RepeatOnEveryPage && !mIsRecalculatingSize )
|
|
{
|
|
//removing a frame forces the multi frame to UseExistingFrames resize mode
|
|
//otherwise the frame may not actually be removed, leading to confusing ui behaviour
|
|
mResizeMode = QgsComposerMultiFrame::UseExistingFrames;
|
|
emit changed();
|
|
}
|
|
recalculateFrameSizes();
|
|
}
|
|
}
|
|
|
|
void QgsComposerMultiFrame::handlePageChange()
|
|
{
|
|
if ( mComposition->numPages() < 1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( mResizeMode != RepeatOnEveryPage )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//remove items beginning on non-existing pages
|
|
for ( int i = mFrameItems.size() - 1; i >= 0; --i )
|
|
{
|
|
QgsComposerFrame* frame = mFrameItems[i];
|
|
int page = frame->pos().y() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
|
|
if ( page > ( mComposition->numPages() - 1 ) )
|
|
{
|
|
removeFrame( i );
|
|
}
|
|
}
|
|
|
|
//page number of the last item
|
|
QgsComposerFrame* lastFrame = mFrameItems.last();
|
|
int lastItemPage = lastFrame->pos().y() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
|
|
|
|
for ( int i = lastItemPage + 1; i < mComposition->numPages(); ++i )
|
|
{
|
|
//copy last frame to current page
|
|
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, lastFrame->pos().x(),
|
|
lastFrame->pos().y() + mComposition->paperHeight() + mComposition->spaceBetweenPages(),
|
|
lastFrame->rect().width(), lastFrame->rect().height() );
|
|
addFrame( newFrame, false );
|
|
lastFrame = newFrame;
|
|
}
|
|
|
|
recalculateFrameSizes();
|
|
update();
|
|
}
|
|
|
|
void QgsComposerMultiFrame::removeFrame( int i )
|
|
{
|
|
if ( i >= mFrameItems.count() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QgsComposerFrame* frameItem = mFrameItems[i];
|
|
if ( mComposition )
|
|
{
|
|
mIsRecalculatingSize = true;
|
|
mComposition->removeComposerItem( frameItem );
|
|
mIsRecalculatingSize = false;
|
|
}
|
|
mFrameItems.removeAt( i );
|
|
}
|
|
|
|
void QgsComposerMultiFrame::update()
|
|
{
|
|
QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin();
|
|
for ( ; frameIt != mFrameItems.end(); ++frameIt )
|
|
{
|
|
( *frameIt )->update();
|
|
}
|
|
}
|
|
|
|
void QgsComposerMultiFrame::deleteFrames()
|
|
{
|
|
ResizeMode bkResizeMode = mResizeMode;
|
|
mResizeMode = UseExistingFrames;
|
|
QObject::disconnect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
|
|
QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin();
|
|
for ( ; frameIt != mFrameItems.end(); ++frameIt )
|
|
{
|
|
mComposition->removeComposerItem( *frameIt, false );
|
|
delete *frameIt;
|
|
}
|
|
QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
|
|
mFrameItems.clear();
|
|
mResizeMode = bkResizeMode;
|
|
}
|
|
|
|
QgsComposerFrame* QgsComposerMultiFrame::frame( int i ) const
|
|
{
|
|
if ( i >= mFrameItems.size() )
|
|
{
|
|
return 0;
|
|
}
|
|
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 );
|
|
if ( !ignoreFrames )
|
|
{
|
|
QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin();
|
|
for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
|
|
{
|
|
( *frameIt )->writeXML( elem, doc );
|
|
}
|
|
}
|
|
QgsComposerObject::writeXML( elem, doc );
|
|
return true;
|
|
}
|
|
|
|
bool QgsComposerMultiFrame::_readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
|
|
{
|
|
QgsComposerObject::readXML( itemElem, doc );
|
|
|
|
mResizeMode = ( ResizeMode )itemElem.attribute( "resizeMode", "0" ).toInt();
|
|
if ( !ignoreFrames )
|
|
{
|
|
QDomNodeList frameList = itemElem.elementsByTagName( "ComposerFrame" );
|
|
for ( int i = 0; i < frameList.size(); ++i )
|
|
{
|
|
QDomElement frameElem = frameList.at( i ).toElement();
|
|
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, 0, 0, 0, 0 );
|
|
newFrame->readXML( frameElem, doc );
|
|
addFrame( newFrame );
|
|
}
|
|
}
|
|
return true;
|
|
}
|