Ensure that moving/resizing items respects reference point

This commit is contained in:
Nyall Dawson 2017-07-10 13:14:34 +10:00
parent d0c844ed67
commit 3f0a0cb063
4 changed files with 176 additions and 2 deletions

View File

@ -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();

View File

@ -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 )
@ -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 )
@ -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;

View File

@ -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:
/**

View File

@ -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:
@ -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;
@ -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 );
@ -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 ) );
@ -420,8 +476,92 @@ void TestQgsLayoutItem::referencePoint()
QCOMPARE( item->pos().x(), -1.0 );
QCOMPARE( item->pos().y(), -2.0 );
//test that resizing is done relative to reference point
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()