Skip to content

Commit

Permalink
Add methods to determine visible pages in a view
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 7, 2017
1 parent 9458f1f commit ab726c4
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 1 deletion.
1 change: 1 addition & 0 deletions python/core/layout/qgslayout.sip
Expand Up @@ -228,6 +228,7 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator
:rtype: QgsLayoutPageCollection
%End


QRectF layoutBounds( bool ignorePages = false, double margin = 0.0 ) const;
%Docstring
Calculates the bounds of all non-gui items in the layout. Ignores snap lines, mouse handles
Expand Down
16 changes: 16 additions & 0 deletions python/core/layout/qgslayoutpagecollection.sip
Expand Up @@ -66,6 +66,22 @@ class QgsLayoutPageCollection : QObject
:rtype: int
%End

QList< QgsLayoutItemPage * > visiblePages( QRectF region ) const;
%Docstring
Returns a list of the pages which are visible within the specified
``region`` (in layout coordinates).
.. seealso:: visiblePageNumbers()
:rtype: list of QgsLayoutItemPage
%End

QList< int > visiblePageNumbers( QRectF region ) const;
%Docstring
Returns a list of the page numbers which are visible within the specified
``region`` (in layout coordinates).
.. seealso:: visiblePages()
:rtype: list of int
%End

void addPage( QgsLayoutItemPage *page /Transfer/ );
%Docstring
Adds a ``page`` to the collection. Ownership of the ``page`` is transferred
Expand Down
15 changes: 15 additions & 0 deletions python/gui/layout/qgslayoutview.sip
Expand Up @@ -37,6 +37,7 @@ class QgsLayoutView: QGraphicsView
:rtype: QgsLayout
%End


void setCurrentLayout( QgsLayout *layout /KeepReference/ );
%Docstring
Sets the current ``layout`` to edit in the view.
Expand Down Expand Up @@ -112,6 +113,20 @@ class QgsLayoutView: QGraphicsView
:rtype: int
%End

QList< QgsLayoutItemPage * > visiblePages() const;
%Docstring
Returns a list of page items which are currently visible in the view.
.. seealso:: visiblePageNumbers()
:rtype: list of QgsLayoutItemPage
%End

QList< int > visiblePageNumbers() const;
%Docstring
Returns a list of page numbers for pages which are currently visible in the view.
.. seealso:: visiblePages()
:rtype: list of int
%End

public slots:

void zoomFull();
Expand Down
5 changes: 5 additions & 0 deletions src/core/layout/qgslayout.cpp
Expand Up @@ -135,6 +135,11 @@ QgsLayoutPageCollection *QgsLayout::pageCollection()
return mPageCollection.get();
}

const QgsLayoutPageCollection *QgsLayout::pageCollection() const
{
return mPageCollection.get();
}

QRectF QgsLayout::layoutBounds( bool ignorePages, double margin ) const
{
//start with an empty rectangle
Expand Down
6 changes: 6 additions & 0 deletions src/core/layout/qgslayout.h
Expand Up @@ -262,6 +262,12 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
*/
QgsLayoutPageCollection *pageCollection();

/**
* Returns a pointer to the layout's page collection, which stores and manages
* page items in the layout.
*/
SIP_SKIP const QgsLayoutPageCollection *pageCollection() const;

/**
* Calculates the bounds of all non-gui items in the layout. Ignores snap lines, mouse handles
* and other cosmetic items.
Expand Down
24 changes: 24 additions & 0 deletions src/core/layout/qgslayoutpagecollection.cpp
Expand Up @@ -168,6 +168,30 @@ int QgsLayoutPageCollection::pageNumber( QgsLayoutItemPage *page ) const
return mPages.indexOf( page );
}

QList<QgsLayoutItemPage *> QgsLayoutPageCollection::visiblePages( QRectF region ) const
{
QList<QgsLayoutItemPage *> pages;
Q_FOREACH ( QgsLayoutItemPage *page, mPages )
{
if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
pages << page;
}
return pages;
}

QList<int> QgsLayoutPageCollection::visiblePageNumbers( QRectF region ) const
{
QList< int > pages;
int p = 0;
Q_FOREACH ( QgsLayoutItemPage *page, mPages )
{
if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
pages << p;
p++;
}
return pages;
}

void QgsLayoutPageCollection::addPage( QgsLayoutItemPage *page )
{
mPages.append( page );
Expand Down
14 changes: 14 additions & 0 deletions src/core/layout/qgslayoutpagecollection.h
Expand Up @@ -79,6 +79,20 @@ class CORE_EXPORT QgsLayoutPageCollection : public QObject
*/
int pageNumber( QgsLayoutItemPage *page ) const;

/**
* Returns a list of the pages which are visible within the specified
* \a region (in layout coordinates).
* \see visiblePageNumbers()
*/
QList< QgsLayoutItemPage * > visiblePages( QRectF region ) const;

/**
* Returns a list of the page numbers which are visible within the specified
* \a region (in layout coordinates).
* \see visiblePages()
*/
QList< int > visiblePageNumbers( QRectF region ) const;

/**
* Adds a \a page to the collection. Ownership of the \a page is transferred
* to the collection, and the page will automatically be added to the collection's
Expand Down
21 changes: 21 additions & 0 deletions src/gui/layout/qgslayoutview.cpp
Expand Up @@ -57,6 +57,11 @@ QgsLayout *QgsLayoutView::currentLayout()
return qobject_cast<QgsLayout *>( scene() );
}

const QgsLayout *QgsLayoutView::currentLayout() const
{
return qobject_cast<const QgsLayout *>( scene() );
}

void QgsLayoutView::setCurrentLayout( QgsLayout *layout )
{
setScene( layout );
Expand Down Expand Up @@ -163,6 +168,22 @@ QgsLayoutViewMenuProvider *QgsLayoutView::menuProvider() const
return mMenuProvider.get();
}

QList<QgsLayoutItemPage *> QgsLayoutView::visiblePages() const
{
//get current visible part of scene
QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
return currentLayout()->pageCollection()->visiblePages( visibleRect );
}

QList<int> QgsLayoutView::visiblePageNumbers() const
{
//get current visible part of scene
QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
}

void QgsLayoutView::zoomFull()
{
fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
Expand Down
20 changes: 20 additions & 0 deletions src/gui/layout/qgslayoutview.h
Expand Up @@ -20,6 +20,7 @@
#include "qgis.h"
#include "qgsprevieweffect.h" // for QgsPreviewEffect::PreviewMode
#include "qgis_gui.h"
#include "qgslayoutitempage.h"
#include <QPointer>
#include <QGraphicsView>
#include <QGraphicsRectItem>
Expand Down Expand Up @@ -65,6 +66,13 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
*/
QgsLayout *currentLayout();

/**
* Returns the current layout associated with the view.
* \see setCurrentLayout()
* \see layoutSet()
*/
SIP_SKIP const QgsLayout *currentLayout() const;

/**
* Sets the current \a layout to edit in the view.
* \see currentLayout()
Expand Down Expand Up @@ -137,6 +145,18 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
*/
int currentPage() const { return mCurrentPage; }

/**
* Returns a list of page items which are currently visible in the view.
* \see visiblePageNumbers()
*/
QList< QgsLayoutItemPage * > visiblePages() const;

/**
* Returns a list of page numbers for pages which are currently visible in the view.
* \see visiblePages()
*/
QList< int > visiblePageNumbers() const;

public slots:

/**
Expand Down
41 changes: 40 additions & 1 deletion tests/src/python/test_qgslayoutpagecollection.py
Expand Up @@ -25,7 +25,8 @@
QgsLayoutPageCollection,
QgsSimpleFillSymbolLayer,
QgsFillSymbol)
from qgis.PyQt.QtCore import Qt, QCoreApplication, QEvent, QPointF
from qgis.PyQt.QtCore import Qt, QCoreApplication, QEvent, QPointF, QRectF

from qgis.testing import start_app, unittest

start_app()
Expand Down Expand Up @@ -378,6 +379,44 @@ def testPageAtPoint(self):
self.assertEqual(collection.pageAtPoint(QPointF(10, 500)), page2)
self.assertFalse(collection.pageAtPoint(QPointF(10, 600)))

def testVisiblePages(self):
p = QgsProject()
l = QgsLayout(p)
collection = l.pageCollection()

self.assertFalse(collection.visiblePages(QRectF(0, 0, 10, 10)))
self.assertFalse(collection.visiblePageNumbers(QRectF(0, 0, 10, 10)))

# add a page
page = QgsLayoutItemPage(l)
page.setPageSize('A4')
collection.addPage(page)

self.assertFalse(collection.visiblePages(QRectF(-10, -10, 5, 5)))
self.assertFalse(collection.visiblePageNumbers(QRectF(-10, -10, 5, 5)))
self.assertEqual(collection.visiblePages(QRectF(-10, -10, 15, 15)), [page])
self.assertEqual(collection.visiblePageNumbers(QRectF(-10, -10, 15, 15)), [0])
self.assertEqual(collection.visiblePages(QRectF(200, 200, 115, 115)), [page])
self.assertEqual(collection.visiblePageNumbers(QRectF(200, 200, 115, 115)), [0])

page2 = QgsLayoutItemPage(l)
page2.setPageSize('A5')
collection.addPage(page2)

self.assertFalse(collection.visiblePages(QRectF(-10, -10, 5, 5)))
self.assertFalse(collection.visiblePageNumbers(QRectF(-10, -10, 5, 5)))
self.assertEqual(collection.visiblePages(QRectF(-10, -10, 15, 15)), [page])
self.assertEqual(collection.visiblePageNumbers(QRectF(-10, -10, 15, 15)), [0])
self.assertEqual(collection.visiblePages(QRectF(200, 200, 115, 115)), [page])
self.assertEqual(collection.visiblePageNumbers(QRectF(200, 200, 115, 115)), [0])

self.assertEqual(collection.visiblePages(QRectF(200, 200, 115, 615)), [page])
self.assertEqual(collection.visiblePageNumbers(QRectF(200, 200, 115, 115)), [0])
self.assertEqual(collection.visiblePages(QRectF(100, 200, 115, 615)), [page, page2])
self.assertEqual(collection.visiblePageNumbers(QRectF(100, 200, 115, 115)), [0, 1])
self.assertEqual(collection.visiblePages(QRectF(100, 310, 115, 615)), [page2])
self.assertEqual(collection.visiblePageNumbers(QRectF(100, 310, 115, 115)), [1])


if __name__ == '__main__':
unittest.main()

0 comments on commit ab726c4

Please sign in to comment.