Skip to content

Commit

Permalink
Ensure that moving/resizing items respects reference point
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 18, 2017
1 parent d0c844e commit 3f0a0cb
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 1 deletion.
10 changes: 10 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -104,6 +104,16 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem
.. seealso:: referencePoint()
%End

QgsLayoutPoint positionWithUnits() const;
%Docstring
Returns the item's current position, including units. The position returned
is the position of the item's reference point, which may not necessarily be the top
left corner of the item.
.. seealso:: attemptMove()
.. seealso:: referencePoint()
:rtype: QgsLayoutPoint
%End

public slots:

virtual void refresh();
Expand Down
15 changes: 15 additions & 0 deletions src/core/layout/qgslayoutitem.cpp
Expand Up @@ -57,7 +57,16 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it

void QgsLayoutItem::setReferencePoint( const QgsLayoutItem::ReferencePoint &point )
{
if ( point == mReferencePoint )
{
return;
}

mReferencePoint = point;

//also need to adjust stored position
QPointF positionReferencePointLayoutUnits = adjustPointForReferencePosition( pos(), QSizeF( -rect().width(), -rect().height() ) );
mItemPosition = mLayout->convertFromLayoutUnits( positionReferencePointLayoutUnits, mItemPosition.units() );
}

void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
Expand All @@ -82,6 +91,7 @@ void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
mItemSize = actualSizeTargetUnits;

setRect( 0, 0, actualSizeLayoutUnits.width(), actualSizeLayoutUnits.height() );
refreshItemPosition();
}

void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point )
Expand All @@ -98,6 +108,11 @@ void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point )
targetPointLayoutUnits = adjustPointForReferencePosition( targetPointLayoutUnits, rect().size() );
QPointF actualPointLayoutUnits = targetPointLayoutUnits;

if ( actualPointLayoutUnits == pos() )
{
return;
}

QgsLayoutPoint actualPointTargetUnits = mLayout->convertFromLayoutUnits( actualPointLayoutUnits, point.units() );
mItemPosition = actualPointTargetUnits;

Expand Down
9 changes: 9 additions & 0 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -119,6 +119,15 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
virtual void attemptMove( const QgsLayoutPoint &point );

/**
* Returns the item's current position, including units. The position returned
* is the position of the item's reference point, which may not necessarily be the top
* left corner of the item.
* \see attemptMove()
* \see referencePoint()
*/
QgsLayoutPoint positionWithUnits() const { return mItemPosition; }

public slots:

/**
Expand Down
142 changes: 141 additions & 1 deletion tests/src/core/testqgslayoutitem.cpp
Expand Up @@ -44,9 +44,11 @@ class TestQgsLayoutItem: public QObject
void draw();
void resize();
void referencePoint();
void adjustPointForReference();
void fixedSize();
void minSize();
void move();
void positionWithUnits();

private:

Expand Down Expand Up @@ -316,6 +318,22 @@ bool TestQgsLayoutItem::renderCheck( QString testName, QImage &image, int mismat
return myResultFlag;
}

void TestQgsLayoutItem::positionWithUnits()
{
QgsProject p;
QgsLayout l( &p );

TestItem *item = new TestItem( &l );
item->attemptMove( QgsLayoutPoint( 60.0, 15.0, QgsUnitTypes::LayoutMillimeters ) );
QCOMPARE( item->positionWithUnits().x(), 60.0 );
QCOMPARE( item->positionWithUnits().y(), 15.0 );
QCOMPARE( item->positionWithUnits().units(), QgsUnitTypes::LayoutMillimeters );
item->attemptMove( QgsLayoutPoint( 50.0, 100.0, QgsUnitTypes::LayoutPixels ) );
QCOMPARE( item->positionWithUnits().x(), 50.0 );
QCOMPARE( item->positionWithUnits().y(), 100.0 );
QCOMPARE( item->positionWithUnits().units(), QgsUnitTypes::LayoutPixels );
}

void TestQgsLayoutItem::resize()
{
QgsProject p;
Expand All @@ -325,7 +343,7 @@ void TestQgsLayoutItem::resize()
l.setUnits( QgsUnitTypes::LayoutMillimeters );
TestItem *item = new TestItem( &l );
item->setRect( 0, 0, 55, 45 );
item->setPos( 27, 29 );
item->attemptMove( QgsLayoutPoint( 27, 29 ) );
item->attemptResize( QgsLayoutSize( 100.0, 200.0, QgsUnitTypes::LayoutMillimeters ) );
QCOMPARE( item->rect().width(), 100.0 );
QCOMPARE( item->rect().height(), 200.0 );
Expand Down Expand Up @@ -380,6 +398,44 @@ void TestQgsLayoutItem::referencePoint()
item->setReferencePoint( QgsLayoutItem::LowerMiddle );
QCOMPARE( item->referencePoint(), QgsLayoutItem::LowerMiddle );

//test that setting reference point results in positionWithUnits returning position at new reference
//point
item->setReferencePoint( QgsLayoutItem::UpperLeft );
item->attemptResize( QgsLayoutSize( 2, 4 ) );
item->attemptMove( QgsLayoutPoint( 1, 2 ) );
QCOMPARE( item->positionWithUnits().x(), 1.0 );
QCOMPARE( item->positionWithUnits().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::UpperLeft );
QCOMPARE( item->positionWithUnits().x(), 1.0 );
QCOMPARE( item->positionWithUnits().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::UpperMiddle );
QCOMPARE( item->positionWithUnits().x(), 2.0 );
QCOMPARE( item->positionWithUnits().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::UpperRight );
QCOMPARE( item->positionWithUnits().x(), 3.0 );
QCOMPARE( item->positionWithUnits().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::MiddleLeft );
QCOMPARE( item->positionWithUnits().x(), 1.0 );
QCOMPARE( item->positionWithUnits().y(), 4.0 );
item->setReferencePoint( QgsLayoutItem::Middle );
QCOMPARE( item->positionWithUnits().x(), 2.0 );
QCOMPARE( item->positionWithUnits().y(), 4.0 );
item->setReferencePoint( QgsLayoutItem::MiddleRight );
QCOMPARE( item->positionWithUnits().x(), 3.0 );
QCOMPARE( item->positionWithUnits().y(), 4.0 );
item->setReferencePoint( QgsLayoutItem::LowerLeft );
QCOMPARE( item->positionWithUnits().x(), 1.0 );
QCOMPARE( item->positionWithUnits().y(), 6.0 );
item->setReferencePoint( QgsLayoutItem::LowerMiddle );
QCOMPARE( item->positionWithUnits().x(), 2.0 );
QCOMPARE( item->positionWithUnits().y(), 6.0 );
item->setReferencePoint( QgsLayoutItem::LowerRight );
QCOMPARE( item->positionWithUnits().x(), 3.0 );
QCOMPARE( item->positionWithUnits().y(), 6.0 );

delete item;
item = new TestItem( &l );

//test that setting item position is done relative to reference point
l.setUnits( QgsUnitTypes::LayoutMillimeters );
item->attemptResize( QgsLayoutSize( 2, 4 ) );
Expand Down Expand Up @@ -420,8 +476,92 @@ void TestQgsLayoutItem::referencePoint()
QCOMPARE( item->pos().x(), -1.0 );
QCOMPARE( item->pos().y(), -2.0 );

delete item;
item = new TestItem( &l );

//test that resizing is done relative to reference point
item->attemptResize( QgsLayoutSize( 2, 4 ) );
item->setReferencePoint( QgsLayoutItem::UpperLeft );
item->attemptMove( QgsLayoutPoint( 1, 2 ) );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->pos().x(), 1.0 );
QCOMPARE( item->pos().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::UpperMiddle );
item->attemptResize( QgsLayoutSize( 6, 4 ) );
QCOMPARE( item->pos().x(), 0.0 );
QCOMPARE( item->pos().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::UpperRight );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->pos().x(), 2.0 );
QCOMPARE( item->pos().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::MiddleLeft );
item->attemptResize( QgsLayoutSize( 6, 4 ) );
QCOMPARE( item->pos().x(), 2.0 );
QCOMPARE( item->pos().y(), 3.0 );
item->setReferencePoint( QgsLayoutItem::Middle );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->pos().x(), 3.0 );
QCOMPARE( item->pos().y(), 2.0 );
item->setReferencePoint( QgsLayoutItem::MiddleRight );
item->attemptResize( QgsLayoutSize( 6, 4 ) );
QCOMPARE( item->pos().x(), 1.0 );
QCOMPARE( item->pos().y(), 3.0 );
item->setReferencePoint( QgsLayoutItem::LowerLeft );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->pos().x(), 1.0 );
QCOMPARE( item->pos().y(), 1.0 );
item->setReferencePoint( QgsLayoutItem::LowerMiddle );
item->attemptResize( QgsLayoutSize( 6, 4 ) );
QCOMPARE( item->pos().x(), 0.0 );
QCOMPARE( item->pos().y(), 3.0 );
item->setReferencePoint( QgsLayoutItem::LowerRight );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->pos().x(), 2.0 );
QCOMPARE( item->pos().y(), 1.0 );
}

void TestQgsLayoutItem::adjustPointForReference()
{
QgsProject p;
QgsLayout l( &p );

TestItem *item = new TestItem( &l );
item->setReferencePoint( QgsLayoutItem::UpperLeft );
QPointF result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 5.0 );
QCOMPARE( result.y(), 7.0 );
item->setReferencePoint( QgsLayoutItem::UpperMiddle );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 4.0 );
QCOMPARE( result.y(), 7.0 );
item->setReferencePoint( QgsLayoutItem::UpperRight );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 3.0 );
QCOMPARE( result.y(), 7.0 );
item->setReferencePoint( QgsLayoutItem::MiddleLeft );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 5.0 );
QCOMPARE( result.y(), 5.0 );
item->setReferencePoint( QgsLayoutItem::Middle );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 4.0 );
QCOMPARE( result.y(), 5.0 );
item->setReferencePoint( QgsLayoutItem::MiddleRight );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 3.0 );
QCOMPARE( result.y(), 5.0 );
item->setReferencePoint( QgsLayoutItem::LowerLeft );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 5.0 );
QCOMPARE( result.y(), 3.0 );
item->setReferencePoint( QgsLayoutItem::LowerMiddle );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 4.0 );
QCOMPARE( result.y(), 3.0 );
item->setReferencePoint( QgsLayoutItem::LowerRight );
result = item->adjustPointForReferencePosition( QPointF( 5, 7 ), QSizeF( 2, 4 ) );
QCOMPARE( result.x(), 3.0 );
QCOMPARE( result.y(), 3.0 );
}

void TestQgsLayoutItem::fixedSize()
Expand Down

0 comments on commit 3f0a0cb

Please sign in to comment.