Skip to content
Permalink
Browse files

Partially port some layout utils for render context creation

  • Loading branch information
nyalldawson committed Jul 14, 2017
1 parent 7a0851c commit c28202474812375fcea5e1695a7b186e8f992c87
@@ -7,6 +7,7 @@
************************************************************************/



class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator
{
%Docstring
@@ -175,6 +176,13 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator
:rtype: list of str
%End

QgsLayoutItemMap *referenceMap() const;
%Docstring
:rtype: QgsLayoutItemMap
%End

void setReferenceMap( QgsLayoutItemMap *map );

signals:

void variablesChanged();
@@ -8,6 +8,7 @@




class QgsLayoutUtils
{
%Docstring
@@ -28,6 +29,25 @@ class QgsLayoutUtils
:rtype: float
%End

static QgsRenderContext createRenderContextForMap( QgsLayoutItemMap *map, QPainter *painter, double dpi = -1 );
%Docstring
Creates a render context suitable for the specified layout ``map`` and ``painter`` destination.
This method returns a new QgsRenderContext which matches the scale and settings of the
target map. If the ``dpi`` argument is not specified then the dpi will be taken from the destinatation
painter device.
.. seealso:: createRenderContextForLayout()
:rtype: QgsRenderContext
%End

static QgsRenderContext createRenderContextForLayout( QgsLayout *layout, QPainter *painter );
%Docstring
Creates a render context suitable for the specified ``layout`` and ``painter`` destination.
This method returns a new QgsRenderContext which matches the scale and settings from the layout's
QgsLayout.referenceMap().
.. seealso:: createRenderContextForMap()
:rtype: QgsRenderContext
%End

};

/************************************************************************
@@ -93,3 +93,13 @@ QStringList QgsLayout::customProperties() const
{
return mCustomProperties.keys();
}

QgsLayoutItemMap *QgsLayout::referenceMap() const
{
return nullptr;
}

void QgsLayout::setReferenceMap( QgsLayoutItemMap *map )
{
Q_UNUSED( map );
}
@@ -21,6 +21,8 @@
#include "qgslayoutcontext.h"
#include "qgsexpressioncontextgenerator.h"

class QgsLayoutItemMap;

/**
* \ingroup core
* \class QgsLayout
@@ -182,6 +184,25 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
*/
QStringList customProperties() const;

/**
* Returns the map item which will be used to generate corresponding world files when the
* layout is exported. If no map was explicitly set via setReferenceMap(), the largest
* map in the layout will be returned (or nullptr if there are no maps in the layout).
* \see setReferenceMap()
* \see generateWorldFile()
*/
//TODO
QgsLayoutItemMap *referenceMap() const;

/**
* Sets the \a map item which will be used to generate corresponding world files when the
* layout is exported.
* \see referenceMap()
* \see setGenerateWorldFile()
*/
//TODO
void setReferenceMap( QgsLayoutItemMap *map );

signals:

/**
@@ -16,6 +16,10 @@
***************************************************************************/

#include "qgslayoututils.h"
#include "qgslayout.h"
#include "qgsrendercontext.h"
#include "qgslayoutitemmap.h"
#include <QPainter>
#include <math.h>

double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNegative )
@@ -31,3 +35,51 @@ double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNega
}
return clippedAngle;
}

QgsRenderContext QgsLayoutUtils::createRenderContextForMap( QgsLayoutItemMap *map, QPainter *painter, double dpi )
{
if ( !map )
{
QgsRenderContext context;
context.setPainter( painter );
if ( dpi < 0 && painter && painter->device() )
{
context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
}
else if ( dpi > 0 )
{
context.setScaleFactor( dpi / 25.4 );
}
else
{
context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
}
return context;
}
else
{
// default to 88 dpi if no painter specified
if ( dpi < 0 )
{
dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
}
#if 0
double dotsPerMM = dpi / 25.4;
// TODO
// get map settings from reference map
QgsRectangle extent = *( map->currentMapExtent() );
QSizeF mapSizeMM = map->rect().size();
QgsMapSettings ms = map->mapSettings( extent, mapSizeMM * dotsPerMM, dpi );
#endif
QgsRenderContext context; // = QgsRenderContext::fromMapSettings( ms );
if ( painter )
context.setPainter( painter );
return context;
}
}

QgsRenderContext QgsLayoutUtils::createRenderContextForLayout( QgsLayout *layout, QPainter *painter )
{
QgsLayoutItemMap *referenceMap = layout ? layout->referenceMap() : nullptr;
return createRenderContextForMap( referenceMap, painter );
}
@@ -19,6 +19,11 @@

#include "qgis_core.h"

class QgsRenderContext;
class QgsLayout;
class QgsLayoutItemMap;
class QPainter;

/**
* \ingroup core
* Utilities for layouts.
@@ -35,6 +40,23 @@ class CORE_EXPORT QgsLayoutUtils
*/
static double normalizedAngle( const double angle, const bool allowNegative = false );

/**
* Creates a render context suitable for the specified layout \a map and \a painter destination.
* This method returns a new QgsRenderContext which matches the scale and settings of the
* target map. If the \a dpi argument is not specified then the dpi will be taken from the destinatation
* painter device.
* \see createRenderContextForLayout()
*/
static QgsRenderContext createRenderContextForMap( QgsLayoutItemMap *map, QPainter *painter, double dpi = -1 );

/**
* Creates a render context suitable for the specified \a layout and \a painter destination.
* This method returns a new QgsRenderContext which matches the scale and settings from the layout's
* QgsLayout::referenceMap().
* \see createRenderContextForMap()
*/
static QgsRenderContext createRenderContextForLayout( QgsLayout *layout, QPainter *painter );

};

#endif //QGSLAYOUTUTILS_H
@@ -18,6 +18,7 @@
#include "qgslayout.h"
#include "qgstest.h"
#include "qgsproject.h"
#include "qgslayoutitemmap.h"

class TestQgsLayout: public QObject
{
@@ -34,6 +35,7 @@ class TestQgsLayout: public QObject
void customProperties();
void variablesEdited();
void scope();
void referenceMap();

private:
QString mReport;
@@ -213,6 +215,37 @@ void TestQgsLayout::scope()

}

void TestQgsLayout::referenceMap()
{
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsProject p;
QgsLayout l( &p );

// no maps
QVERIFY( !l.referenceMap() );
#if 0

QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
l.addComposerMap( map );
QCOMPARE( l.referenceMap(), map );
#endif
#if 0 // TODO

// add a larger map
QgsLayoutItemMap *map2 = new QgsLayoutItemMap( &l );
map2->setNewExtent( extent );
map2->setSceneRect( QRectF( 30, 60, 250, 150 ) );
l.addComposerMap( map2 );
QCOMPARE( l.referenceMap(), map2 );
// explicitly set reference map
l.setReferenceMap( map );
QCOMPARE( l.referenceMap(), map );
#endif

}


QGSTEST_MAIN( TestQgsLayout )
#include "testqgslayout.moc"
@@ -18,6 +18,9 @@
#include "qgslayout.h"
#include "qgstest.h"
#include "qgslayoututils.h"
#include "qgstestutils.h"
#include "qgsproject.h"
#include "qgslayoutitemmap.h"

class TestQgsLayoutUtils: public QObject
{
@@ -29,6 +32,8 @@ class TestQgsLayoutUtils: public QObject
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void normalizedAngle(); //test normalised angle function
void createRenderContextFromLayout();
void createRenderContextFromMap();

private:
QString mReport;
@@ -112,5 +117,116 @@ void TestQgsLayoutUtils::normalizedAngle()
}


void TestQgsLayoutUtils::createRenderContextFromLayout()
{
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.setDotsPerMeterX( 150 / 25.4 * 1000 );
testImage.setDotsPerMeterY( 150 / 25.4 * 1000 );
QPainter p( &testImage );

// no composition
QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( nullptr, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );

// no composition, no painter
rc = QgsLayoutUtils::createRenderContextForLayout( nullptr, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );

//create composition with no reference map
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsProject project;
QgsLayout l( &project );
rc = QgsLayoutUtils::createRenderContextForLayout( &l, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );

// layout, no map, no painter
rc = QgsLayoutUtils::createRenderContextForLayout( &l, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );

// add a reference map
QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
#if 0 // TODO
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
composition->addComposerMap( map );
#endif
l.setReferenceMap( map );

rc = QgsLayoutUtils::createRenderContextForLayout( &l, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QCOMPARE( rc.painter(), &p );

// layout, reference map, no painter
rc = QgsLayoutUtils::createRenderContextForLayout( &l, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QVERIFY( !rc.painter() );

p.end();
}

void TestQgsLayoutUtils::createRenderContextFromMap()
{
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.setDotsPerMeterX( 150 / 25.4 * 1000 );
testImage.setDotsPerMeterY( 150 / 25.4 * 1000 );
QPainter p( &testImage );

// no map
QgsRenderContext rc = QgsLayoutUtils::createRenderContextForMap( nullptr, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );

// no map, no painter
rc = QgsLayoutUtils::createRenderContextForMap( nullptr, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );

//create composition with no reference map
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsProject project;
QgsLayout l( &project );

#if 0 // TODO
// add a map
QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );

map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
l.addComposerMap( map );
#endif

#if 0 //TODO
rc = QgsLayoutUtils::createRenderContextForMap( map, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QCOMPARE( rc.painter(), &p );

// map, no painter
rc = QgsLayoutUtils::createRenderContextForMap( map, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QVERIFY( !rc.painter() );

// secondary map
QgsLayoutItemMap *map2 = new QgsLayoutItemMap( &l );

map2->setNewExtent( extent );
map2->setSceneRect( QRectF( 30, 60, 100, 50 ) );
composition->addComposerMap( map2 );

rc = QgsLayoutUtils::createRenderContextForMap( map2, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map2->scale(), 1000000 );
QVERIFY( rc.painter() );
#endif
p.end();
}

QGSTEST_MAIN( TestQgsLayoutUtils )
#include "testqgslayoututils.moc"

0 comments on commit c282024

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