Skip to content
Permalink
Browse files

Fix resizing items with non-top-left reference point using mouse handles

  • Loading branch information
nyalldawson committed Oct 10, 2017
1 parent 1c735d5 commit ab4e6c11ed93427c246c55b208c2898a98af2685
@@ -235,13 +235,20 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
.. seealso:: sizeWithUnits()
%End

virtual void attemptMove( const QgsLayoutPoint &point );
virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true );
%Docstring
Attempts to move the item to a specified ``point``. This method respects the item's
Attempts to move the item to a specified ``point``.

If ``useReferencePoint`` is true, this method will respect the item's
reference point, in that the item will be moved so that its current reference
point is placed at the specified target point.

If ``useReferencePoint`` is false, the item will be moved so that ``point``
falls at the top-left corner of the item.

Note that the final position of the item may not match the specified target position,
as data defined item position may override the specified value.

.. seealso:: attemptResize()
.. seealso:: referencePoint()
.. seealso:: positionWithUnits()
@@ -575,7 +582,7 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
QPointF adjustPointForReferencePosition( const QPointF &point, const QSizeF &size, const ReferencePoint &reference ) const;
%Docstring
Adjusts the specified ``point`` at which a ``reference`` position of the item
sits and returns the top left corner of the item, if reference point where placed at the specified position.
sits and returns the top left corner of the item, if reference point were placed at the specified position.
:rtype: QPointF
%End

@@ -585,6 +592,13 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
:rtype: QPointF
%End

QgsLayoutPoint topLeftToReferencePoint( const QgsLayoutPoint &point ) const;
%Docstring
Returns the position for the reference point of the item, if the top-left of the item
was placed at the specified ``point``.
:rtype: QgsLayoutPoint
%End

virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
%Docstring
Stores item state within an XML DOM element.
@@ -62,7 +62,7 @@ class QgsLayoutItemGroup: QgsLayoutItem
virtual void setVisibility( const bool visible );


virtual void attemptMove( const QgsLayoutPoint &point );
virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true );

virtual void attemptResize( const QgsLayoutSize &size );

@@ -351,7 +351,7 @@ void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
emit sizePositionChanged();
}

void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point )
void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point, bool useReferencePoint )
{
if ( !mLayout )
{
@@ -360,7 +360,13 @@ void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point )
return;
}

QgsLayoutPoint evaluatedPoint = applyDataDefinedPosition( point );
QgsLayoutPoint evaluatedPoint = point;
if ( !useReferencePoint )
{
evaluatedPoint = topLeftToReferencePoint( point );
}

evaluatedPoint = applyDataDefinedPosition( evaluatedPoint );
QPointF evaluatedPointLayoutUnits = mLayout->convertToLayoutUnits( evaluatedPoint );
QPointF topLeftPointLayoutUnits = adjustPointForReferencePosition( evaluatedPointLayoutUnits, rect().size(), mReferencePoint );
if ( topLeftPointLayoutUnits == scenePos() && point.units() == mItemPosition.units() )
@@ -737,6 +743,13 @@ QPointF QgsLayoutItem::positionAtReferencePoint( const QgsLayoutItem::ReferenceP
return mapToScene( pointWithinItem );
}

QgsLayoutPoint QgsLayoutItem::topLeftToReferencePoint( const QgsLayoutPoint &point ) const
{
QPointF topLeft = mLayout->convertToLayoutUnits( point );
QPointF refPoint = topLeft + itemPositionAtReferencePoint( mReferencePoint, rect().size() );
return mLayout->convertFromLayoutUnits( refPoint, point.units() );
}

bool QgsLayoutItem::writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
element.setAttribute( QStringLiteral( "uuid" ), mUuid );
@@ -250,16 +250,23 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
virtual void attemptResize( const QgsLayoutSize &size );

/**
* Attempts to move the item to a specified \a point. This method respects the item's
* Attempts to move the item to a specified \a point.
*
* If \a useReferencePoint is true, this method will respect the item's
* reference point, in that the item will be moved so that its current reference
* point is placed at the specified target point.
*
* If \a useReferencePoint is false, the item will be moved so that \a point
* falls at the top-left corner of the item.
*
* Note that the final position of the item may not match the specified target position,
* as data defined item position may override the specified value.
*
* \see attemptResize()
* \see referencePoint()
* \see positionWithUnits()
*/
virtual void attemptMove( const QgsLayoutPoint &point );
virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true );

/**
* Returns the item's current position, including units. The position returned
@@ -572,7 +579,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt

/**
* Adjusts the specified \a point at which a \a reference position of the item
* sits and returns the top left corner of the item, if reference point where placed at the specified position.
* sits and returns the top left corner of the item, if reference point were placed at the specified position.
*/
QPointF adjustPointForReferencePosition( const QPointF &point, const QSizeF &size, const ReferencePoint &reference ) const;

@@ -581,6 +588,12 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
QPointF positionAtReferencePoint( const ReferencePoint &reference ) const;

/**
* Returns the position for the reference point of the item, if the top-left of the item
* was placed at the specified \a point.
*/
QgsLayoutPoint topLeftToReferencePoint( const QgsLayoutPoint &point ) const;

/**
* Stores item state within an XML DOM element.
* \param element is the DOM element to store the item's properties in
@@ -127,7 +127,7 @@ void QgsLayoutItemGroup::setVisibility( const bool visible )
mLayout->undoStack()->endMacro();
}

void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point )
void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useReferencePoint )
{
if ( !mLayout )
return;
@@ -69,7 +69,7 @@ class CORE_EXPORT QgsLayoutItemGroup: public QgsLayoutItem
void setVisibility( const bool visible ) override;

//overridden to move child items
void attemptMove( const QgsLayoutPoint &point ) override;
void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true ) override;
void attemptResize( const QgsLayoutSize &size ) override;

bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const override;
@@ -657,13 +657,13 @@ void QgsLayoutMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
itemRect = itemRect.normalized();
QPointF newPos = mapToScene( itemRect.topLeft() );

// translate new position to current item units
QgsLayoutPoint itemPos = mLayout->convertFromLayoutUnits( newPos, item->positionWithUnits().units() );
item->attemptMove( itemPos );

QgsLayoutSize itemSize = mLayout->convertFromLayoutUnits( itemRect.size(), item->sizeWithUnits().units() );
item->attemptResize( itemSize );

// translate new position to current item units
QgsLayoutPoint itemPos = mLayout->convertFromLayoutUnits( newPos, item->positionWithUnits().units() );
item->attemptMove( itemPos, false );

command->saveAfterState();
mLayout->undoStack()->stack()->push( command.release() );
}
@@ -1139,7 +1139,24 @@ void TestQgsLayoutItem::move()

l.setUnits( QgsUnitTypes::LayoutMillimeters );

//TODO - reference points
//reference points
item->attemptMove( QgsLayoutPoint( 5, 9 ) );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
item->setReferencePoint( QgsLayoutItem::LowerRight );
QCOMPARE( item->positionWithUnits().x(), 9.0 );
QCOMPARE( item->positionWithUnits().y(), 15.0 );

item->attemptMove( QgsLayoutPoint( 11, 13 ) );
QCOMPARE( item->positionWithUnits().x(), 11.0 );
QCOMPARE( item->positionWithUnits().y(), 13.0 );
QCOMPARE( item->scenePos().x(), 7.0 );
QCOMPARE( item->scenePos().y(), 7.0 );

item->attemptMove( QgsLayoutPoint( 10, 12 ), false );
QCOMPARE( item->positionWithUnits().x(), 14.0 );
QCOMPARE( item->positionWithUnits().y(), 18.0 );
QCOMPARE( item->scenePos().x(), 10.0 );
QCOMPARE( item->scenePos().y(), 12.0 );
}

void TestQgsLayoutItem::rotation()

0 comments on commit ab4e6c1

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