Skip to content
Permalink
Browse files

Fix resizing with mouse handles acts strangely when items have frames

  • Loading branch information
nyalldawson committed Oct 13, 2017
1 parent 8629225 commit 625eef80ebc5e7c24ad3c24bf26663fd7f2f5967
@@ -223,19 +223,23 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
:rtype: QgsLayoutSize
%End

virtual void attemptResize( const QgsLayoutSize &size );
virtual void attemptResize( const QgsLayoutSize &size, bool includesFrame = false );
%Docstring
Attempts to resize the item to a specified target ``size``. Note that the final size of the
item may not match the specified target size, as items with a fixed or minimum
size will place restrictions on the allowed item size. Data defined item size overrides
will also override the specified target size.

If ``includesFrame`` is true, then the size specified by ``size`` includes the
item's frame.

.. seealso:: minimumSize()
.. seealso:: fixedSize()
.. seealso:: attemptMove()
.. seealso:: sizeWithUnits()
%End

virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true );
virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true, bool includesFrame = false );
%Docstring
Attempts to move the item to a specified ``point``.

@@ -246,6 +250,9 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
If ``useReferencePoint`` is false, the item will be moved so that ``point``
falls at the top-left corner of the item.

If ``includesFrame`` is true, then the position specified by ``point`` represents the
point at which to place the outside of the item's frame.

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.

@@ -62,9 +62,9 @@ class QgsLayoutItemGroup: QgsLayoutItem
virtual void setVisibility( const bool visible );


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

virtual void attemptResize( const QgsLayoutSize &size );
virtual void attemptResize( const QgsLayoutSize &size, bool includesFrame = false );


virtual bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;
@@ -87,7 +87,7 @@ class QgsLayoutItemPage : QgsLayoutItem
:rtype: QgsLayoutItemPage.Orientation
%End

virtual void attemptResize( const QgsLayoutSize &size );
virtual void attemptResize( const QgsLayoutSize &size, bool includesFrame = false );


virtual QgsAbstractLayoutUndoCommand *createCommand( const QString &text, int id, QUndoCommand *parent = 0 ) /Factory/;
@@ -338,15 +338,25 @@ void QgsLayoutItem::setReferencePoint( const QgsLayoutItem::ReferencePoint &poin
refreshItemPosition();
}

void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
void QgsLayoutItem::attemptResize( const QgsLayoutSize &s, bool includesFrame )
{
if ( !mLayout )
{
mItemSize = size;
setRect( 0, 0, size.width(), size.height() );
mItemSize = s;
setRect( 0, 0, s.width(), s.height() );
return;
}

QgsLayoutSize size = s;

if ( includesFrame )
{
//adjust position to account for frame size
double bleed = mLayout->convertFromLayoutUnits( estimatedFrameBleed(), size.units() ).length();
size.setWidth( size.width() - 2 * bleed );
size.setHeight( size.height() - 2 * bleed );
}

QgsLayoutSize evaluatedSize = applyDataDefinedSize( size );
QSizeF targetSizeLayoutUnits = mLayout->convertToLayoutUnits( evaluatedSize );
QSizeF actualSizeLayoutUnits = applyMinimumSize( targetSizeLayoutUnits );
@@ -365,15 +375,25 @@ void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
emit sizePositionChanged();
}

void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point, bool useReferencePoint )
void QgsLayoutItem::attemptMove( const QgsLayoutPoint &p, bool useReferencePoint, bool includesFrame )
{
if ( !mLayout )
{
mItemPosition = point;
setPos( point.toQPointF() );
mItemPosition = p;
setPos( p.toQPointF() );
return;
}

QgsLayoutPoint point = p;

if ( includesFrame )
{
//adjust position to account for frame size
double bleed = mLayout->convertFromLayoutUnits( estimatedFrameBleed(), point.units() ).length();
point.setX( point.x() + bleed );
point.setY( point.y() + bleed );
}

QgsLayoutPoint evaluatedPoint = point;
if ( !useReferencePoint )
{
@@ -244,12 +244,16 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
* item may not match the specified target size, as items with a fixed or minimum
* size will place restrictions on the allowed item size. Data defined item size overrides
* will also override the specified target size.
*
* If \a includesFrame is true, then the size specified by \a size includes the
* item's frame.
*
* \see minimumSize()
* \see fixedSize()
* \see attemptMove()
* \see sizeWithUnits()
*/
virtual void attemptResize( const QgsLayoutSize &size );
virtual void attemptResize( const QgsLayoutSize &size, bool includesFrame = false );

/**
* Attempts to move the item to a specified \a point.
@@ -261,14 +265,17 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
* If \a useReferencePoint is false, the item will be moved so that \a point
* falls at the top-left corner of the item.
*
* If \a includesFrame is true, then the position specified by \a point represents the
* point at which to place the outside of the item's frame.
*
* 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, bool useReferencePoint = true );
virtual void attemptMove( const QgsLayoutPoint &point, bool useReferencePoint = true, bool includesFrame = false );

/**
* Returns the item's current position, including units. The position returned
@@ -127,7 +127,7 @@ void QgsLayoutItemGroup::setVisibility( const bool visible )
mLayout->undoStack()->endMacro();
}

void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useReferencePoint )
void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useReferencePoint, bool includesFrame )
{
Q_UNUSED( useReferencePoint ); //groups should always have reference point in top left
if ( !mLayout )
@@ -158,7 +158,7 @@ void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useRefer
QgsLayoutPoint deltaPos = mLayout->convertFromLayoutUnits( QPointF( deltaX, deltaY ), itemPos.units() );
itemPos.setX( itemPos.x() + deltaPos.x() );
itemPos.setY( itemPos.y() + deltaPos.y() );
item->attemptMove( itemPos );
item->attemptMove( itemPos, includesFrame );

if ( command )
{
@@ -167,13 +167,13 @@ void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useRefer
}
}
//lastly move group item itself
QgsLayoutItem::attemptMove( point );
QgsLayoutItem::attemptMove( point, includesFrame );
if ( !shouldBlockUndoCommands() )
mLayout->undoStack()->endMacro();
resetBoundingRect();
}

void QgsLayoutItemGroup::attemptResize( const QgsLayoutSize &size )
void QgsLayoutItemGroup::attemptResize( const QgsLayoutSize &size, bool includesFrame )
{
if ( !mLayout )
return;
@@ -206,7 +206,7 @@ void QgsLayoutItemGroup::attemptResize( const QgsLayoutSize &size )
QPointF newPos = mapToScene( itemRect.topLeft() );

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

// translate new position to current item units
QgsLayoutPoint itemPos = mLayout->convertFromLayoutUnits( newPos, item->positionWithUnits().units() );
@@ -69,8 +69,8 @@ class CORE_EXPORT QgsLayoutItemGroup: public QgsLayoutItem
void setVisibility( const bool visible ) override;

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

bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const override;
bool readXml( const QDomElement &itemElement, const QDomDocument &document, const QgsReadWriteContext &context ) override;
@@ -117,9 +117,9 @@ QgsLayoutItemPage::Orientation QgsLayoutItemPage::decodePageOrientation( const Q
return Landscape;
}

void QgsLayoutItemPage::attemptResize( const QgsLayoutSize &size )
void QgsLayoutItemPage::attemptResize( const QgsLayoutSize &size, bool includesFrame )
{
QgsLayoutItem::attemptResize( size );
QgsLayoutItem::attemptResize( size, includesFrame );
//update size of attached grid to reflect new page size and position
mGrid->setRect( 0, 0, rect().width(), rect().height() );

@@ -117,7 +117,7 @@ class CORE_EXPORT QgsLayoutItemPage : public QgsLayoutItem
*/
static QgsLayoutItemPage::Orientation decodePageOrientation( const QString &string, bool *ok SIP_OUT = nullptr );

void attemptResize( const QgsLayoutSize &size ) override;
void attemptResize( const QgsLayoutSize &size, bool includesFrame = false ) override;

QgsAbstractLayoutUndoCommand *createCommand( const QString &text, int id, QUndoCommand *parent = nullptr ) override SIP_FACTORY;

@@ -658,11 +658,11 @@ void QgsLayoutMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
QPointF newPos = mapToScene( itemRect.topLeft() );

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

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

command->saveAfterState();
mLayout->undoStack()->stack()->push( command.release() );
@@ -881,6 +881,20 @@ void TestQgsLayoutItem::referencePoint()
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->scenePos().x(), 2.0 );
QCOMPARE( item->scenePos().y(), 1.0 );

item.reset( new TestItem( &l ) );

//item with frame
item->attemptResize( QgsLayoutSize( 2, 4 ) );
item->attemptMove( QgsLayoutPoint( 1, 2 ) );
item->setFrameEnabled( true );
item->setFrameStrokeWidth( QgsLayoutMeasurement( 1 ) );
item->attemptResize( QgsLayoutSize( 4, 6 ) );
QCOMPARE( item->sizeWithUnits().width(), 4.0 );
QCOMPARE( item->sizeWithUnits().height(), 6.0 );
item->attemptResize( QgsLayoutSize( 4, 6 ), true );
QCOMPARE( item->sizeWithUnits().width(), 3.0 );
QCOMPARE( item->sizeWithUnits().height(), 5.0 );
}

void TestQgsLayoutItem::itemPositionReferencePoint()
@@ -1161,6 +1175,19 @@ void TestQgsLayoutItem::move()
QCOMPARE( item->positionWithUnits().y(), 18.0 );
QCOMPARE( item->scenePos().x(), 10.0 );
QCOMPARE( item->scenePos().y(), 12.0 );

//item with frame
item.reset( new TestItem( &l ) );
item->attemptResize( QgsLayoutSize( 2, 4 ) );
item->attemptMove( QgsLayoutPoint( 1, 2 ) );
item->setFrameEnabled( true );
item->setFrameStrokeWidth( QgsLayoutMeasurement( 1 ) );
item->attemptMove( QgsLayoutPoint( 1, 3 ) );
QCOMPARE( item->positionWithUnits().x(), 1.0 );
QCOMPARE( item->positionWithUnits().y(), 3.0 );
item->attemptMove( QgsLayoutPoint( 4, 6 ), false, true );
QCOMPARE( item->positionWithUnits().x(), 4.5 );
QCOMPARE( item->positionWithUnits().y(), 6.5 );
}

void TestQgsLayoutItem::rotation()

0 comments on commit 625eef8

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