Skip to content
Permalink
Browse files

Fix a number of multiframe methods

  • Loading branch information
nyalldawson committed Nov 24, 2017
1 parent ee45ec9 commit 0e71505fe83ce99029c5f620705b6a4bb79f8740
@@ -80,6 +80,19 @@ class QgsLayoutPageCollection : QObject, QgsLayoutSerializableObject
:rtype: list of int
%End

bool pageIsEmpty( int page ) const;
%Docstring
Returns whether a given ``page`` index is empty, ie, it contains no items except for the background
paper item.
:rtype: bool
%End

QList< QgsLayoutItem *> itemsOnPage( int page ) const;
%Docstring
Returns a list of layout items on the specified ``page`` index.
:rtype: list of QgsLayoutItem
%End

void addPage( QgsLayoutItemPage *page /Transfer/ );
%Docstring
Adds a ``page`` to the collection. Ownership of the ``page`` is transferred
@@ -89,9 +102,22 @@ class QgsLayoutPageCollection : QObject, QgsLayoutSerializableObject

Calling addPage() automatically triggers a reflow() of pages.

.. seealso:: extendByNewPage()
.. seealso:: insertPage()
%End

QgsLayoutItemPage *extendByNewPage();
%Docstring
Adds a new page to the end of the collection. This page will inherit the
same size as the current final page in the collection.

The newly created page will be returned.

.. seealso:: addPage()
.. seealso:: insertPage()
:rtype: QgsLayoutItemPage
%End

void insertPage( QgsLayoutItemPage *page /Transfer/, int beforePage );
%Docstring
Inserts a ``page`` into a specific position in the collection.
@@ -175,6 +201,25 @@ class QgsLayoutPageCollection : QObject, QgsLayoutSerializableObject
it does not consider x coordinates and vertical coordinates before the first page or
after the last page will still return the nearest page.

.. seealso:: predicatePageNumberForPoint()
.. seealso:: pageAtPoint()
.. seealso:: positionOnPage()
:rtype: int
%End

int predictPageNumberForPoint( QPointF point ) const;
%Docstring
Returns the theoretical page number corresponding to a ``point`` in the layout (in layout units),
assuming that enough pages exist in the layout to cover that point.

If there are insufficient pages currently in the layout, this method will assume that extra
"imaginary" pages have been added at the end of the layout until that point is reached. These
imaginary pages will inherit the size of the existing final page in the layout.

Page numbers in collections begin at 0 - so a page number of 0 indicates the
first page.

.. seealso:: pageNumberForPoint()
.. seealso:: pageAtPoint()
.. seealso:: positionOnPage()
:rtype: int
@@ -23,9 +23,7 @@ QgsLayoutMultiFrame::QgsLayoutMultiFrame( QgsLayout *layout )
{
mLayout->addMultiFrame( this );

#if 0 //TODO
connect( mLayout, &QgsLayout::nPagesChanged, this, &QgsLayoutMultiFrame::handlePageChange );
#endif
connect( mLayout->pageCollection(), &QgsLayoutPageCollection::changed, this, &QgsLayoutMultiFrame::handlePageChange );
}

QgsLayoutMultiFrame::~QgsLayoutMultiFrame()
@@ -86,7 +84,6 @@ QList<QgsLayoutFrame *> QgsLayoutMultiFrame::frames() const

void QgsLayoutMultiFrame::recalculateFrameSizes()
{
#if 0 //TODO
if ( mFrameItems.empty() )
{
return;
@@ -143,38 +140,49 @@ void QgsLayoutMultiFrame::recalculateFrameSizes()
while ( ( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
{
//find out on which page the lower left point of the last frame is
int page = std::floor( ( currentItem->pos().y() + currentItem->rect().height() ) / ( mLayout->paperHeight() + mComposition->spaceBetweenPages() ) ) + 1;
int page = mLayout->pageCollection()->predictPageNumberForPoint( QPointF( 0, currentItem->pos().y() + currentItem->rect().height() ) );

if ( mResizeMode == RepeatOnEveryPage )
{
if ( page >= mComposition->numPages() )
if ( page >= mLayout->pageCollection()->pageCount() )
{
break;
}
}
else
{
//add an extra page if required
if ( mComposition->numPages() < ( page + 1 ) )
//add new pages if required
for ( int p = mLayout->pageCollection()->pageCount() - 1 ; p < page; ++p )
{
mComposition->setNumPages( page + 1 );
mLayout->pageCollection()->extendByNewPage();
}
}

double currentPageHeight = mLayout->pageCollection()->page( page )->rect().height();

double frameHeight = 0;
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
switch ( mResizeMode )
{
frameHeight = currentItem->rect().height();
}
else //mResizeMode == ExtendToNextPage
{
frameHeight = ( currentY + mComposition->paperHeight() ) > totalHeight ? totalHeight - currentY : mComposition->paperHeight();
case RepeatUntilFinished:
case RepeatOnEveryPage:
{
frameHeight = currentItem->rect().height();
break;
}
case ExtendToNextPage:
{
frameHeight = ( currentY + currentPageHeight ) > totalHeight ? totalHeight - currentY : currentPageHeight;
break;
}

case UseExistingFrames:
break;
}

double newFrameY = page * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
double newFrameY = mLayout->pageCollection()->page( page )->pos().y();
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
{
newFrameY += currentItem->pos().y() - ( page - 1 ) * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
newFrameY += currentItem->pagePos().y();
}

//create new frame
@@ -197,7 +205,6 @@ void QgsLayoutMultiFrame::recalculateFrameSizes()
currentItem = newFrame;
}
}
#endif
}

void QgsLayoutMultiFrame::recalculateFrameRects()
@@ -281,7 +288,6 @@ void QgsLayoutMultiFrame::handleFrameRemoval()

void QgsLayoutMultiFrame::handlePageChange()
{
#if 0 //TODO
if ( mLayout->pageCollection()->pageCount() < 1 )
{
return;
@@ -296,30 +302,31 @@ void QgsLayoutMultiFrame::handlePageChange()
for ( int i = mFrameItems.size() - 1; i >= 0; --i )
{
QgsLayoutFrame *frame = mFrameItems.at( i );
int page = frame->pos().y() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
if ( page > ( mComposition->numPages() - 1 ) )
int page = mLayout->pageCollection()->predictPageNumberForPoint( frame->pos() );
if ( page >= mLayout->pageCollection()->pageCount() )
{
removeFrame( i );
}
}

//page number of the last item
QgsLayoutFrame *lastFrame = mFrameItems.last();
int lastItemPage = lastFrame->pos().y() / ( mLayout->paperHeight() + mLayout->spaceBetweenPages() );
int lastItemPage = mLayout->pageCollection()->predictPageNumberForPoint( lastFrame->pos() );

for ( int i = lastItemPage + 1; i < mLayout->pageCollection()->pageCount(); ++i )
{
//copy last frame to current page
QgsLayoutFrame *newFrame = new QgsLayoutFrame( mLayout, this, lastFrame->pos().x(),
lastFrame->pos().y() + mLayout->paperHeight() + mLayout->spaceBetweenPages(),
lastFrame->rect().width(), lastFrame->rect().height() );
addFrame( newFrame, false );
lastFrame = newFrame;
std::unique_ptr< QgsLayoutFrame > newFrame = qgis::make_unique< QgsLayoutFrame >( mLayout, this );

newFrame->attemptSetSceneRect( QRectF( lastFrame->pos().x(),
mLayout->pageCollection()->page( i )->pos().y() + lastFrame->pagePos().y(),
lastFrame->rect().width(), lastFrame->rect().height() ) );
lastFrame = newFrame.get();
addFrame( newFrame.release(), false );
}

recalculateFrameSizes();
update();
#endif
}

void QgsLayoutMultiFrame::removeFrame( int i, const bool removeEmptyPages )
@@ -333,18 +340,16 @@ void QgsLayoutMultiFrame::removeFrame( int i, const bool removeEmptyPages )
if ( mLayout )
{
mIsRecalculatingSize = true;
#if 0 //TODO
int pageNumber = frameItem->page();
//remove item, but don't create undo command
#if 0 //TODO - block undo commands
#endif
mLayout->removeLayoutItem( frameItem );
//if frame was the only item on the page, remove the page
if ( removeEmptyPages && mComposition->pageIsEmpty( pageNumber ) )
if ( removeEmptyPages && mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
{
mComposition->setNumPages( mComposition->numPages() - 1 );
mLayout->pageCollection()->deletePage( pageNumber );
}
#endif
mIsRecalculatingSize = false;
}
mFrameItems.removeAt( i );
@@ -93,6 +93,36 @@ int QgsLayoutPageCollection::pageNumberForPoint( QPointF point ) const
return pageNumber;
}

int QgsLayoutPageCollection::predictPageNumberForPoint( QPointF point ) const
{
int pageNumber = 0;
double startNextPageY = 0;
Q_FOREACH ( QgsLayoutItemPage *page, mPages )
{
startNextPageY += page->rect().height() + spaceBetweenPages();
if ( startNextPageY >= point.y() )
break;
pageNumber++;
}

if ( startNextPageY >= point.y() )
{
// found an existing page
return pageNumber;
}

double lastPageHeight = mPages.last()->rect().height();
while ( startNextPageY < point.y() )
{
startNextPageY += lastPageHeight + spaceBetweenPages();
if ( startNextPageY >= point.y() )
break;
pageNumber++;
}

return pageNumber;
}

QgsLayoutItemPage *QgsLayoutPageCollection::pageAtPoint( QPointF point ) const
{
Q_FOREACH ( QGraphicsItem *item, mLayout->items( point ) )
@@ -301,6 +331,40 @@ QList<int> QgsLayoutPageCollection::visiblePageNumbers( QRectF region ) const
return pages;
}

bool QgsLayoutPageCollection::pageIsEmpty( int page ) const
{
//get all items on page
const QList<QgsLayoutItem *> items = mLayout->pageCollection()->itemsOnPage( page );

//loop through and check for non-paper items
for ( QgsLayoutItem *item : items )
{
//is item a paper item?
if ( item->type() != QgsLayoutItemRegistry::LayoutPage )
{
//item is not a paper item, so we have other items on the page
return false;
}
}
//no non-paper items
return true;
}

QList<QgsLayoutItem *> QgsLayoutPageCollection::itemsOnPage( int page ) const
{
QList<QgsLayoutItem *> itemList;
const QList<QGraphicsItem *> graphicsItemList = mLayout->items();
for ( QGraphicsItem *graphicsItem : graphicsItemList )
{
QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
if ( item && item->page() == page )
{
itemList.push_back( item );
}
}
return itemList;
}

void QgsLayoutPageCollection::addPage( QgsLayoutItemPage *page )
{
if ( !mBlockUndoCommands )
@@ -312,6 +376,18 @@ void QgsLayoutPageCollection::addPage( QgsLayoutItemPage *page )
mLayout->undoStack()->endCommand();
}

QgsLayoutItemPage *QgsLayoutPageCollection::extendByNewPage()
{
if ( mPages.empty() )
return nullptr;

QgsLayoutItemPage *lastPage = mPages.at( mPages.count() - 1 );
std::unique_ptr< QgsLayoutItemPage > newPage = qgis::make_unique< QgsLayoutItemPage >( mLayout );
newPage->attemptResize( lastPage->sizeWithUnits() );
addPage( newPage.release() );
return mPages.at( mPages.count() - 1 );
}

void QgsLayoutPageCollection::insertPage( QgsLayoutItemPage *page, int beforePage )
{
if ( !mBlockUndoCommands )
@@ -392,3 +468,5 @@ void QgsLayoutPageCollection::createDefaultPageStyleSymbol()
properties.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
mPageStyleSymbol.reset( QgsFillSymbol::createSimple( properties ) );
}


0 comments on commit 0e71505

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