From ea323912809921b95c00286ea96f1a7b0f19490c Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 19 Jul 2017 07:46:15 +1000 Subject: [PATCH] Add methods for handling page size to QgsLayoutItemPage --- python/core/layout/qgslayout.sip | 1 + python/core/layout/qgslayoutitempage.sip | 48 +++++++++ src/core/layout/qgslayout.h | 3 +- src/core/layout/qgslayoutitem.cpp | 2 +- src/core/layout/qgslayoutitempage.cpp | 71 +++++++++++++ src/core/layout/qgslayoutitempage.h | 44 ++++++++ tests/src/core/CMakeLists.txt | 1 + tests/src/core/testqgslayoutpage.cpp | 129 +++++++++++++++++++++++ 8 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 tests/src/core/testqgslayoutpage.cpp diff --git a/python/core/layout/qgslayout.sip b/python/core/layout/qgslayout.sip index 67bea024d1a..e7ab07f20a2 100644 --- a/python/core/layout/qgslayout.sip +++ b/python/core/layout/qgslayout.sip @@ -22,6 +22,7 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator enum ZValues { + ZPage, ZMapTool, }; diff --git a/python/core/layout/qgslayoutitempage.sip b/python/core/layout/qgslayoutitempage.sip index a47da41c5cb..0d9e190a2f0 100644 --- a/python/core/layout/qgslayoutitempage.sip +++ b/python/core/layout/qgslayoutitempage.sip @@ -20,6 +20,12 @@ class QgsLayoutItemPage : QgsLayoutItem %End public: + enum Orientation + { + Portrait, + Landscape + }; + explicit QgsLayoutItemPage( QgsLayout *layout /TransferThis/ ); %Docstring Constructor for QgsLayoutItemPage, with the specified parent ``layout``. @@ -27,6 +33,48 @@ class QgsLayoutItemPage : QgsLayoutItem virtual int type() const; virtual QString stringType() const; + void setPageSize( const QgsLayoutSize &size ); +%Docstring + Sets the ``size`` of the page. +.. seealso:: pageSize() +%End + + bool setPageSize( const QString &size, Orientation orientation = Portrait ); +%Docstring + Sets the page size to a known page ``size``, e.g. "A4" and ``orientation``. + The known page sizes are managed by QgsPageSizeRegistry. Valid page sizes + can be retrieved via QgsPageSizeRegistry.entries(). + The function returns true if ``size`` was a valid page size and the page + size was changed. If false is returned then ``size`` could not be matched + to a known page size. +.. seealso:: pageSize() + :rtype: bool +%End + + QgsLayoutSize pageSize() const; +%Docstring + Returns the size of the page. +.. seealso:: setPageSize() + :rtype: QgsLayoutSize +%End + + Orientation orientation() const; +%Docstring + Returns the page orientiation. +.. note:: + + There is no direct setter for page orientation - use setPageSize() instead. + :rtype: Orientation +%End + + static QgsLayoutItemPage::Orientation decodePageOrientation( const QString &string, bool *ok /Out/ = 0 ); +%Docstring + Decodes a ``string`` representing a page orientation. If specified, ``ok`` + will be set to true if string could be successfully interpreted as a + page orientation. + :rtype: QgsLayoutItemPage.Orientation +%End + protected: virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 ); diff --git a/src/core/layout/qgslayout.h b/src/core/layout/qgslayout.h index ffbf1bf9373..5c79b5e1979 100644 --- a/src/core/layout/qgslayout.h +++ b/src/core/layout/qgslayout.h @@ -39,7 +39,8 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext //! Preset item z-values, to ensure correct stacking enum ZValues { - ZMapTool = 10000, //!< Z-Value for temporary map tool items + ZPage = 0, //!< Z-value for page (paper) items + ZMapTool = 10000, //!< Z-value for temporary map tool items }; /** diff --git a/src/core/layout/qgslayoutitem.cpp b/src/core/layout/qgslayoutitem.cpp index 132ddf24dc2..53abde383ed 100644 --- a/src/core/layout/qgslayoutitem.cpp +++ b/src/core/layout/qgslayoutitem.cpp @@ -78,7 +78,7 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it } double destinationDpi = itemStyle->matrix.m11() * 25.4; - bool useImageCache = false; + bool useImageCache = true; if ( useImageCache ) { diff --git a/src/core/layout/qgslayoutitempage.cpp b/src/core/layout/qgslayoutitempage.cpp index 1f1d3075b69..aa60909f5a8 100644 --- a/src/core/layout/qgslayoutitempage.cpp +++ b/src/core/layout/qgslayoutitempage.cpp @@ -17,6 +17,7 @@ #include "qgslayoutitempage.h" #include "qgslayout.h" #include "qgslayoututils.h" +#include "qgspagesizeregistry.h" #include "qgssymbollayerutils.h" #include @@ -24,7 +25,77 @@ QgsLayoutItemPage::QgsLayoutItemPage( QgsLayout *layout ) : QgsLayoutItem( layout ) { + setFlag( QGraphicsItem::ItemIsSelectable, false ); + setFlag( QGraphicsItem::ItemIsMovable, false ); + setZValue( QgsLayout::ZPage ); +} +void QgsLayoutItemPage::setPageSize( const QgsLayoutSize &size ) +{ + attemptResize( size ); +} + +bool QgsLayoutItemPage::setPageSize( const QString &size, Orientation orientation ) +{ + QgsPageSize newSize; + if ( QgsApplication::pageSizeRegistry()->decodePageSize( size, newSize ) ) + { + switch ( orientation ) + { + case Portrait: + break; // nothing to do + + case Landscape: + { + // flip height and width + double x = newSize.size.width(); + newSize.size.setWidth( newSize.size.height() ); + newSize.size.setHeight( x ); + break; + } + } + + setPageSize( newSize.size ); + return true; + } + else + { + return false; + } +} + +QgsLayoutSize QgsLayoutItemPage::pageSize() const +{ + return sizeWithUnits(); +} + +QgsLayoutItemPage::Orientation QgsLayoutItemPage::orientation() const +{ + if ( sizeWithUnits().width() >= sizeWithUnits().height() ) + return Landscape; + else + return Portrait; +} + +QgsLayoutItemPage::Orientation QgsLayoutItemPage::decodePageOrientation( const QString &string, bool *ok ) +{ + if ( ok ) + *ok = false; + + QString trimmedString = string.trimmed(); + if ( trimmedString.compare( QStringLiteral( "portrait" ), Qt::CaseInsensitive ) == 0 ) + { + if ( ok ) + *ok = true; + return Portrait; + } + else if ( trimmedString.compare( QStringLiteral( "landscape" ), Qt::CaseInsensitive ) == 0 ) + { + if ( ok ) + *ok = true; + return Landscape; + } + return Landscape; } void QgsLayoutItemPage::draw( QgsRenderContext &context, const QStyleOptionGraphicsItem * ) diff --git a/src/core/layout/qgslayoutitempage.h b/src/core/layout/qgslayoutitempage.h index 6b85c2bb840..6c062ee562e 100644 --- a/src/core/layout/qgslayoutitempage.h +++ b/src/core/layout/qgslayoutitempage.h @@ -20,6 +20,7 @@ #include "qgis_core.h" #include "qgslayoutitem.h" #include "qgslayoutitemregistry.h" +#include "qgis_sip.h" /** * \ingroup core @@ -34,6 +35,13 @@ class CORE_EXPORT QgsLayoutItemPage : public QgsLayoutItem public: + //! Page orientiation + enum Orientation + { + Portrait, //!< Portrait orientation + Landscape //!< Landscape orientation + }; + /** * Constructor for QgsLayoutItemPage, with the specified parent \a layout. */ @@ -41,6 +49,42 @@ class CORE_EXPORT QgsLayoutItemPage : public QgsLayoutItem int type() const override { return QgsLayoutItemRegistry::LayoutPage; } QString stringType() const override { return QStringLiteral( "ItemPaper" ); } + /** + * Sets the \a size of the page. + * \see pageSize() + */ + void setPageSize( const QgsLayoutSize &size ); + + /** + * Sets the page size to a known page \a size, e.g. "A4" and \a orientation. + * The known page sizes are managed by QgsPageSizeRegistry. Valid page sizes + * can be retrieved via QgsPageSizeRegistry::entries(). + * The function returns true if \a size was a valid page size and the page + * size was changed. If false is returned then \a size could not be matched + * to a known page size. + * \see pageSize() + */ + bool setPageSize( const QString &size, Orientation orientation = Portrait ); + + /** + * Returns the size of the page. + * \see setPageSize() + */ + QgsLayoutSize pageSize() const; + + /** + * Returns the page orientiation. + * \note There is no direct setter for page orientation - use setPageSize() instead. + */ + Orientation orientation() const; + + /** + * Decodes a \a string representing a page orientation. If specified, \a ok + * will be set to true if string could be successfully interpreted as a + * page orientation. + */ + static QgsLayoutItemPage::Orientation decodePageOrientation( const QString &string, bool *ok SIP_OUT = nullptr ); + protected: void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = nullptr ) override; diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt index 50c9693bc8a..86f196183ce 100755 --- a/tests/src/core/CMakeLists.txt +++ b/tests/src/core/CMakeLists.txt @@ -130,6 +130,7 @@ SET(TESTS testqgslayoutcontext.cpp testqgslayoutitem.cpp testqgslayoutobject.cpp + testqgslayoutpage.cpp testqgslayoutunits.cpp testqgslayoututils.cpp testqgslegendrenderer.cpp diff --git a/tests/src/core/testqgslayoutpage.cpp b/tests/src/core/testqgslayoutpage.cpp new file mode 100644 index 00000000000..10cd46d3742 --- /dev/null +++ b/tests/src/core/testqgslayoutpage.cpp @@ -0,0 +1,129 @@ +/*************************************************************************** + testqgslayoutpage.cpp + --------------------- + begin : November 2014 + copyright : (C) 2014 by Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgslayout.h" +#include "qgslayoutitempage.h" +#include "qgslayoutitemregistry.h" +#include "qgis.h" +#include "qgsproject.h" +#include +#include "qgstest.h" + +class TestQgsLayoutPage : public QObject +{ + Q_OBJECT + + private slots: + void initTestCase();// will be called before the first testfunction is executed. + void cleanupTestCase();// will be called after the last testfunction was executed. + void init();// will be called before each testfunction is executed. + void cleanup();// will be called after every testfunction. + void itemType(); + void pageSize(); + void decodePageOrientation(); + + private: + QString mReport; + +}; + +void TestQgsLayoutPage::initTestCase() +{ + mReport = "

Layout Page Tests

\n"; +} + +void TestQgsLayoutPage::cleanupTestCase() +{ + QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html"; + QFile myFile( myReportFile ); + if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) ) + { + QTextStream myQTextStream( &myFile ); + myQTextStream << mReport; + myFile.close(); + } +} + +void TestQgsLayoutPage::init() +{ + +} + +void TestQgsLayoutPage::cleanup() +{ + +} + +void TestQgsLayoutPage::itemType() +{ + QgsProject p; + QgsLayout l( &p ); + QgsLayoutItemPage *page = new QgsLayoutItemPage( &l ); + QCOMPARE( page->type(), static_cast< int >( QgsLayoutItemRegistry::LayoutPage ) ); +} + +void TestQgsLayoutPage::pageSize() +{ + QgsProject p; + QgsLayout l( &p ); + QgsLayoutItemPage *page = new QgsLayoutItemPage( &l ); + page->setPageSize( QgsLayoutSize( 270, 297, QgsUnitTypes::LayoutMeters ) ); + QCOMPARE( page->pageSize().width(), 270.0 ); + QCOMPARE( page->pageSize().height(), 297.0 ); + QCOMPARE( page->pageSize().units(), QgsUnitTypes::LayoutMeters ); + QCOMPARE( page->orientation(), QgsLayoutItemPage::Portrait ); + page->setPageSize( QgsLayoutSize( 297, 270, QgsUnitTypes::LayoutMeters ) ); + QCOMPARE( page->orientation(), QgsLayoutItemPage::Landscape ); + + // from registry + QVERIFY( !page->setPageSize( "hoooyeah" ) ); + // should be unchanged + QCOMPARE( page->pageSize().width(), 297.0 ); + QCOMPARE( page->pageSize().height(), 270.0 ); + QCOMPARE( page->pageSize().units(), QgsUnitTypes::LayoutMeters ); + + // good size + QVERIFY( page->setPageSize( "A5" ) ); + QCOMPARE( page->pageSize().width(), 148.0 ); + QCOMPARE( page->pageSize().height(), 210.0 ); + QCOMPARE( page->pageSize().units(), QgsUnitTypes::LayoutMillimeters ); + QCOMPARE( page->orientation(), QgsLayoutItemPage::Portrait ); + + QVERIFY( page->setPageSize( "A5", QgsLayoutItemPage::Landscape ) ); + QCOMPARE( page->pageSize().width(), 210.0 ); + QCOMPARE( page->pageSize().height(), 148.0 ); + QCOMPARE( page->pageSize().units(), QgsUnitTypes::LayoutMillimeters ); + QCOMPARE( page->orientation(), QgsLayoutItemPage::Landscape ); + +} + +void TestQgsLayoutPage::decodePageOrientation() +{ + //test good string + bool ok = false; + QCOMPARE( QgsLayoutItemPage::decodePageOrientation( QString( " porTrait " ), &ok ), QgsLayoutItemPage::Portrait ); + QVERIFY( ok ); + QCOMPARE( QgsLayoutItemPage::decodePageOrientation( QString( "landscape" ), &ok ), QgsLayoutItemPage::Landscape ); + QVERIFY( ok ); + + //test bad string + QgsLayoutItemPage::decodePageOrientation( QString(), &ok ); + QVERIFY( !ok ); +} + +QGSTEST_MAIN( TestQgsLayoutPage ) +#include "testqgslayoutpage.moc"