Skip to content
Permalink
Browse files
More shape porting
  • Loading branch information
nyalldawson committed Nov 7, 2017
1 parent cf7714b commit f524c80b11f75cdb7d38d44a6a539c6a1945d6af
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 0 deletions.
@@ -34,6 +34,9 @@ class QgsLayoutItemShape : QgsLayoutItem
:rtype: QgsFillSymbol
%End

virtual QRectF boundingRect() const;


protected:

explicit QgsLayoutItemShape( QgsLayout *layout );
@@ -17,6 +17,7 @@
#include "qgslayoutitemshape.h"
#include "qgslayout.h"
#include "qgslayoututils.h"
#include "qgssymbollayerutils.h"

#include <QPainter>

@@ -33,6 +34,38 @@ QgsLayoutItemShape::QgsLayoutItemShape( QgsLayout *layout )
properties.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) );
properties.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
mShapeStyleSymbol.reset( QgsFillSymbol::createSimple( properties ) );
refreshSymbol();

connect( this, &QgsLayoutItemShape::sizePositionChanged, this, [ = ]
{
updateBoundingRect();
update();
} );
}

void QgsLayoutItemShape::refreshSymbol()
{
if ( layout() )
{
QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( layout(), nullptr, layout()->context().dpi() );
mMaxSymbolBleed = ( 25.4 / layout()->context().dpi() ) * QgsSymbolLayerUtils::estimateMaxSymbolBleed( mShapeStyleSymbol.get(), rc );
}

updateBoundingRect();

update();
emit frameChanged();
}

void QgsLayoutItemShape::updateBoundingRect()
{
QRectF rectangle = rect();
rectangle.adjust( -mMaxSymbolBleed, -mMaxSymbolBleed, mMaxSymbolBleed, mMaxSymbolBleed );
if ( rectangle != mCurrentRectangle )
{
prepareGeometryChange();
mCurrentRectangle = rectangle;
}
}

void QgsLayoutItemShape::setSymbol( QgsFillSymbol *symbol )
@@ -41,6 +74,12 @@ void QgsLayoutItemShape::setSymbol( QgsFillSymbol *symbol )
return;

mShapeStyleSymbol.reset( symbol->clone() );
refreshSymbol();
}

QRectF QgsLayoutItemShape::boundingRect() const
{
return mCurrentRectangle;
}

//
@@ -48,15 +48,35 @@ class CORE_EXPORT QgsLayoutItemShape : public QgsLayoutItem
*/
QgsFillSymbol *symbol() { return mShapeStyleSymbol.get(); }

// Depending on the symbol style, the bounding rectangle can be larger than the shape
QRectF boundingRect() const override;

protected:

/**
* Constructor for QgsLayoutItemShape, with the specified parent \a layout.
*/
explicit QgsLayoutItemShape( QgsLayout *layout );

private slots:

/**
* Should be called after the shape's symbol is changed. Redraws the shape and recalculates
* its selection bounds.
*/
void refreshSymbol();

//! Updates the bounding rect of this item
void updateBoundingRect();

private:
std::unique_ptr< QgsFillSymbol > mShapeStyleSymbol;

double mMaxSymbolBleed = 0.0;
//! Current bounding rectangle of shape
QRectF mCurrentRectangle;


};


@@ -138,6 +138,7 @@ SET(TESTS
testqgslayoutmodel.cpp
testqgslayoutobject.cpp
testqgslayoutpage.cpp
testqgslayoutshapes.cpp
testqgslayoutunits.cpp
testqgslayoututils.cpp
testqgslegendrenderer.cpp
@@ -0,0 +1,221 @@
/***************************************************************************
testqgslayoutshapes.cpp
----------------------
begin : October 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail.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 "qgsapplication.h"
#include "qgslayout.h"
#include "qgsmultirenderchecker.h"
#include "qgslayoutitemshape.h"
#include "qgsmapsettings.h"
#include "qgsproject.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsfillsymbollayer.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>

class TestQgsLayoutShapes : public QObject
{
Q_OBJECT

public:
TestQgsLayoutShapes() = default;

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 rectangle(); //test if rectangle shape is functioning
void triangle(); //test if triange shape is functioning
void ellipse(); //test if ellipse shape is functioning
void roundedRectangle(); //test if rounded rectangle shape is functioning
void symbol(); //test is styling shapes via symbol is working

private:

QString mReport;
};

void TestQgsLayoutShapes::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();

mReport = QStringLiteral( "<h1>Composer Shape Tests</h1>\n" );
}

void TestQgsLayoutShapes::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}

void TestQgsLayoutShapes::init()
{

}

void TestQgsLayoutShapes::cleanup()
{

}

void TestQgsLayoutShapes::rectangle()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();

QgsLayoutItemRectangularShape *shape = new QgsLayoutItemRectangularShape( &l );
shape->attemptMove( QgsLayoutPoint( 20, 20 ) );
shape->attemptResize( QgsLayoutSize( 150, 100 ) );


QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() );
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( QColor( 0, 0, 0 ) );
simpleFill->setStrokeWidth( 0.3 );
simpleFill->setPenJoinStyle( Qt::MiterJoin );
shape->setSymbol( fillSymbol.get() );

l.addLayoutItem( shape );

QgsLayoutChecker checker( QStringLiteral( "composershapes_rectangle" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testLayout( mReport ) );
}

void TestQgsLayoutShapes::triangle()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();

QgsLayoutItemTriangleShape *shape = new QgsLayoutItemTriangleShape( &l );
shape->attemptMove( QgsLayoutPoint( 20, 20 ) );
shape->attemptResize( QgsLayoutSize( 150, 100 ) );


QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() );
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( QColor( 0, 0, 0 ) );
simpleFill->setStrokeWidth( 0.3 );
simpleFill->setPenJoinStyle( Qt::MiterJoin );
shape->setSymbol( fillSymbol.get() );

l.addLayoutItem( shape );

QgsLayoutChecker checker( QStringLiteral( "composershapes_triangle" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testLayout( mReport ) );
}

void TestQgsLayoutShapes::ellipse()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();

QgsLayoutItemEllipseShape *shape = new QgsLayoutItemEllipseShape( &l );
shape->attemptMove( QgsLayoutPoint( 20, 20 ) );
shape->attemptResize( QgsLayoutSize( 150, 100 ) );

QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() );
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( QColor( 0, 0, 0 ) );
simpleFill->setStrokeWidth( 0.3 );
simpleFill->setPenJoinStyle( Qt::MiterJoin );
shape->setSymbol( fillSymbol.get() );

l.addLayoutItem( shape );

QgsLayoutChecker checker( QStringLiteral( "composershapes_ellipse" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testLayout( mReport ) );
}

void TestQgsLayoutShapes::roundedRectangle()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();

QgsLayoutItemRectangularShape *shape = new QgsLayoutItemRectangularShape( &l );
shape->attemptMove( QgsLayoutPoint( 20, 20 ) );
shape->attemptResize( QgsLayoutSize( 150, 100 ) );

QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() );
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( QColor( 0, 0, 0 ) );
simpleFill->setStrokeWidth( 0.3 );
simpleFill->setPenJoinStyle( Qt::MiterJoin );
shape->setSymbol( fillSymbol.get() );

l.addLayoutItem( shape );

shape->setCornerRadius( QgsLayoutMeasurement( 30 ) );

QgsLayoutChecker checker( QStringLiteral( "composershapes_roundedrect" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testLayout( mReport ) );
}

void TestQgsLayoutShapes::symbol()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();

QgsLayoutItemRectangularShape *shape = new QgsLayoutItemRectangularShape( &l );
shape->attemptMove( QgsLayoutPoint( 20, 20 ) );
shape->attemptResize( QgsLayoutSize( 150, 100 ) );

//setup simple fill
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::green );
simpleFill->setStrokeColor( Qt::yellow );
simpleFill->setStrokeWidth( 6 );
shape->setSymbol( fillSymbol );
delete fillSymbol;

l.addLayoutItem( shape );
QgsLayoutChecker checker( QStringLiteral( "composershapes_symbol" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testLayout( mReport ) );
}

QGSTEST_MAIN( TestQgsLayoutShapes )
#include "testqgslayoutshapes.moc"
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f524c80

Please sign in to comment.