QGIS API Documentation  master-28efcda
src/core/composer/qgscomposermultiframe.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                               qgscomposermultiframe.cpp
00003     ------------------------------------------------------------
00004     begin                : July 2012
00005     copyright            : (C) 2012 by Marco Hugentobler
00006     email                : marco dot hugentobler at sourcepole dot ch
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #include "qgscomposermultiframe.h"
00017 #include "qgscomposerframe.h"
00018 #include "qgscomposition.h"
00019 
00020 QgsComposerMultiFrame::QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands ): mComposition( c ), mResizeMode( UseExistingFrames ), mCreateUndoCommands( createUndoCommands )
00021 {
00022   mComposition->addMultiFrame( this );
00023   connect( mComposition, SIGNAL( nPagesChanged() ), this, SLOT( handlePageChange() ) );
00024 }
00025 
00026 QgsComposerMultiFrame::QgsComposerMultiFrame(): mComposition( 0 ), mResizeMode( UseExistingFrames )
00027 {
00028 }
00029 
00030 QgsComposerMultiFrame::~QgsComposerMultiFrame()
00031 {
00032   deleteFrames();
00033 }
00034 
00035 void QgsComposerMultiFrame::setResizeMode( ResizeMode mode )
00036 {
00037   if ( mode != mResizeMode )
00038   {
00039     mResizeMode = mode;
00040     recalculateFrameSizes();
00041     emit changed();
00042   }
00043 }
00044 
00045 void QgsComposerMultiFrame::recalculateFrameSizes()
00046 {
00047   if ( mFrameItems.size() < 1 )
00048   {
00049     return;
00050   }
00051 
00052   QSizeF size = totalSize();
00053   double totalHeight = size.height();
00054 
00055   if ( totalHeight < 1 )
00056   {
00057     return;
00058   }
00059 
00060   double currentY = 0;
00061   double currentHeight = 0;
00062   QgsComposerFrame* currentItem = 0;
00063 
00064   for ( int i = 0; i < mFrameItems.size(); ++i )
00065   {
00066     if ( mResizeMode != RepeatOnEveryPage && currentY >= totalHeight )
00067     {
00068       if ( mResizeMode == RepeatUntilFinished || mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
00069       {
00070         for ( int j = mFrameItems.size(); j > i; --j )
00071         {
00072           removeFrame( j - 1 );
00073         }
00074       }
00075       return;
00076     }
00077 
00078     currentItem = mFrameItems.value( i );
00079     currentHeight = currentItem->rect().height();
00080     if ( mResizeMode == RepeatOnEveryPage )
00081     {
00082       currentItem->setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
00083     }
00084     else
00085     {
00086       currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
00087     }
00088     currentItem->update();
00089     currentY += currentHeight;
00090   }
00091 
00092   //at end of frames but there is  still content left. Add other pages if ResizeMode ==
00093   if ( mResizeMode != UseExistingFrames )
00094   {
00095     while (( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
00096     {
00097       //find out on which page the lower left point of the last frame is
00098       int page = currentItem->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
00099       if ( mResizeMode == RepeatOnEveryPage )
00100       {
00101         if ( page > mComposition->numPages() - 2 )
00102         {
00103           break;
00104         }
00105       }
00106       else
00107       {
00108         if ( mComposition->numPages() < ( page + 2 ) )
00109         {
00110           mComposition->setNumPages( page + 2 );
00111         }
00112       }
00113 
00114       double frameHeight = 0;
00115       if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
00116       {
00117         frameHeight = currentItem->rect().height();
00118       }
00119       else //mResizeMode == ExtendToNextPage
00120       {
00121         frameHeight = ( currentY + mComposition->paperHeight() ) > totalHeight ?  totalHeight - currentY : mComposition->paperHeight();
00122       }
00123 
00124       double newFrameY = ( page + 1 ) * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
00125       if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
00126       {
00127         newFrameY += currentItem->transform().dy() - page * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
00128       }
00129       QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, currentItem->transform().dx(),
00130           newFrameY,
00131           currentItem->rect().width(), frameHeight );
00132       if ( mResizeMode == RepeatOnEveryPage )
00133       {
00134         newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
00135       }
00136       else
00137       {
00138         newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), newFrame->rect().height() ) );
00139       }
00140       currentY += frameHeight;
00141       currentItem = newFrame;
00142       addFrame( newFrame, false );
00143     }
00144   }
00145 }
00146 
00147 void QgsComposerMultiFrame::handleFrameRemoval( QgsComposerItem* item )
00148 {
00149   QgsComposerFrame* frame = dynamic_cast<QgsComposerFrame*>( item );
00150   if ( !frame )
00151   {
00152     return;
00153   }
00154   int index = mFrameItems.indexOf( frame );
00155   if ( index == -1 )
00156   {
00157     return;
00158   }
00159   mFrameItems.removeAt( index );
00160   if ( mFrameItems.size() > 0 )
00161   {
00162     recalculateFrameSizes();
00163   }
00164 }
00165 
00166 void QgsComposerMultiFrame::handlePageChange()
00167 {
00168   if ( mComposition->numPages() < 1 )
00169   {
00170     return;
00171   }
00172 
00173   if ( mResizeMode != RepeatOnEveryPage )
00174   {
00175     return;
00176   }
00177 
00178   //remove items beginning on non-existing pages
00179   for ( int i = mFrameItems.size() - 1; i >= 0; --i )
00180   {
00181     QgsComposerFrame* frame = mFrameItems[i];
00182     int page = frame->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
00183     if ( page > ( mComposition->numPages() - 1 ) )
00184     {
00185       removeFrame( i );
00186     }
00187   }
00188 
00189   //page number of the last item
00190   QgsComposerFrame* lastFrame = mFrameItems.last();
00191   int lastItemPage = lastFrame->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
00192 
00193   for ( int i = lastItemPage + 1; i < mComposition->numPages(); ++i )
00194   {
00195     //copy last frame to current page
00196     QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, lastFrame->transform().dx(),
00197         lastFrame->transform().dy() + mComposition->paperHeight() + mComposition->spaceBetweenPages(),
00198         lastFrame->rect().width(), lastFrame->rect().height() );
00199     addFrame( newFrame, false );
00200     lastFrame = newFrame;
00201   }
00202 
00203   recalculateFrameSizes();
00204   update();
00205 }
00206 
00207 void QgsComposerMultiFrame::removeFrame( int i )
00208 {
00209   QgsComposerFrame* frameItem = mFrameItems[i];
00210   if ( mComposition )
00211   {
00212     mComposition->removeComposerItem( frameItem );
00213   }
00214   mFrameItems.removeAt( i );
00215 }
00216 
00217 void QgsComposerMultiFrame::update()
00218 {
00219   QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin();
00220   for ( ; frameIt != mFrameItems.end(); ++frameIt )
00221   {
00222     ( *frameIt )->update();
00223   }
00224 }
00225 
00226 void QgsComposerMultiFrame::deleteFrames()
00227 {
00228   ResizeMode bkResizeMode = mResizeMode;
00229   mResizeMode = UseExistingFrames;
00230   QObject::disconnect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
00231   QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin();
00232   for ( ; frameIt != mFrameItems.end(); ++frameIt )
00233   {
00234     mComposition->removeComposerItem( *frameIt, false );
00235     delete *frameIt;
00236   }
00237   QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
00238   mFrameItems.clear();
00239   mResizeMode = bkResizeMode;
00240 }
00241 
00242 QgsComposerFrame* QgsComposerMultiFrame::frame( int i ) const
00243 {
00244   if ( i >= mFrameItems.size() )
00245   {
00246     return 0;
00247   }
00248   return mFrameItems.at( i );
00249 }
00250 
00251 bool QgsComposerMultiFrame::_writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames ) const
00252 {
00253   elem.setAttribute( "resizeMode", mResizeMode );
00254   if ( !ignoreFrames )
00255   {
00256     QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin();
00257     for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
00258     {
00259       ( *frameIt )->writeXML( elem, doc );
00260     }
00261   }
00262   return true;
00263 }
00264 
00265 bool QgsComposerMultiFrame::_readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
00266 {
00267   mResizeMode = ( ResizeMode )itemElem.attribute( "resizeMode", "0" ).toInt();
00268   if ( !ignoreFrames )
00269   {
00270     QDomNodeList frameList = itemElem.elementsByTagName( "ComposerFrame" );
00271     for ( int i = 0; i < frameList.size(); ++i )
00272     {
00273       QDomElement frameElem = frameList.at( i ).toElement();
00274       QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, 0, 0, 0, 0 );
00275       newFrame->readXML( frameElem, doc );
00276       addFrame( newFrame );
00277     }
00278   }
00279   return true;
00280 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines