Skip to content

Commit

Permalink
Port data defined item position and size
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 18, 2017
1 parent 3f0a0cb commit 6fd0698
Show file tree
Hide file tree
Showing 4 changed files with 368 additions and 11 deletions.
19 changes: 19 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -91,6 +91,7 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem
.. seealso:: minimumSize()
.. seealso:: fixedSize()
.. seealso:: attemptMove()
.. seealso:: sizeWithUnits()
%End

virtual void attemptMove( const QgsLayoutPoint &point );
Expand All @@ -102,6 +103,7 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem
as data defined item position may override the specified value.
.. seealso:: attemptResize()
.. seealso:: referencePoint()
.. seealso:: positionWithUnits()
%End

QgsLayoutPoint positionWithUnits() const;
Expand All @@ -111,9 +113,18 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem
left corner of the item.
.. seealso:: attemptMove()
.. seealso:: referencePoint()
.. seealso:: sizeWithUnits()
:rtype: QgsLayoutPoint
%End

QgsLayoutSize sizeWithUnits() const;
%Docstring
Returns the item's current size, including units.
.. seealso:: attemptResize()
.. seealso:: positionWithUnits()
:rtype: QgsLayoutSize
%End

public slots:

virtual void refresh();
Expand All @@ -123,6 +134,14 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem
recalculation of its position and size.
%End

virtual void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );
%Docstring
Refreshes a data defined ``property`` for the item by reevaluating the property's value
and redrawing the item with this new value. If ``property`` is set to
QgsLayoutObject.AllProperties then all data defined properties for the item will be
refreshed.
%End

protected:

virtual void drawDebugRect( QPainter *painter );
Expand Down
68 changes: 57 additions & 11 deletions src/core/layout/qgslayoutitem.cpp
Expand Up @@ -67,6 +67,7 @@ void QgsLayoutItem::setReferencePoint( const QgsLayoutItem::ReferencePoint &poin
//also need to adjust stored position
QPointF positionReferencePointLayoutUnits = adjustPointForReferencePosition( pos(), QSizeF( -rect().width(), -rect().height() ) );
mItemPosition = mLayout->convertFromLayoutUnits( positionReferencePointLayoutUnits, mItemPosition.units() );
refreshItemPosition();
}

void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
Expand All @@ -78,7 +79,8 @@ void QgsLayoutItem::attemptResize( const QgsLayoutSize &size )
return;
}

QSizeF targetSizeLayoutUnits = mLayout->convertToLayoutUnits( size );
QgsLayoutSize evaluatedSize = applyDataDefinedSize( size );
QSizeF targetSizeLayoutUnits = mLayout->convertToLayoutUnits( evaluatedSize );
QSizeF actualSizeLayoutUnits = applyMinimumSize( targetSizeLayoutUnits );
actualSizeLayoutUnits = applyFixedSize( actualSizeLayoutUnits );

Expand All @@ -103,27 +105,71 @@ void QgsLayoutItem::attemptMove( const QgsLayoutPoint &point )
return;
}

QPointF targetPointLayoutUnits = mLayout->convertToLayoutUnits( point );
//TODO - apply data defined position here
targetPointLayoutUnits = adjustPointForReferencePosition( targetPointLayoutUnits, rect().size() );
QPointF actualPointLayoutUnits = targetPointLayoutUnits;

if ( actualPointLayoutUnits == pos() )
QgsLayoutPoint evaluatedPoint = applyDataDefinedPosition( point );
QPointF evaluatedPointLayoutUnits = mLayout->convertToLayoutUnits( evaluatedPoint );
QPointF topLeftPointLayoutUnits = adjustPointForReferencePosition( evaluatedPointLayoutUnits, rect().size() );
if ( topLeftPointLayoutUnits == pos() && point.units() == mItemPosition.units() )
{
//TODO - add test for second condition
return;
}

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

setPos( topLeftPointLayoutUnits );
}

QgsLayoutPoint QgsLayoutItem::applyDataDefinedPosition( const QgsLayoutPoint &position )
{
if ( !mLayout )
{
return position;
}

setPos( targetPointLayoutUnits );
QgsExpressionContext context = createExpressionContext();
double evaluatedX = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PositionX, context, position.x() );
double evaluatedY = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PositionY, context, position.y() );
return QgsLayoutPoint( evaluatedX, evaluatedY, position.units() );
}

QgsLayoutSize QgsLayoutItem::applyDataDefinedSize( const QgsLayoutSize &size )
{
if ( !mLayout )
{
return size;
}

QgsExpressionContext context = createExpressionContext();
double evaluatedWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::ItemWidth, context, size.width() );
double evaluatedHeight = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::ItemHeight, context, size.height() );
return QgsLayoutSize( evaluatedWidth, evaluatedHeight, size.units() );
}

void QgsLayoutItem::refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property )
{
//update data defined properties and update item to match

//evaluate width and height first, since they may affect position if non-top-left reference point set
if ( property == QgsLayoutObject::ItemWidth || property == QgsLayoutObject::ItemHeight ||
property == QgsLayoutObject::AllProperties )
{
refreshItemSize();
}
if ( property == QgsLayoutObject::PositionX || property == QgsLayoutObject::PositionY ||
property == QgsLayoutObject::AllProperties )
{
refreshItemPosition();
}
}


void QgsLayoutItem::refresh()
{
QgsLayoutObject::refresh();
refreshItemSize();
refreshItemPosition();

refreshDataDefinedProperty();
}

void QgsLayoutItem::drawDebugRect( QPainter *painter )
Expand Down
20 changes: 20 additions & 0 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -105,6 +105,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
* \see minimumSize()
* \see fixedSize()
* \see attemptMove()
* \see sizeWithUnits()
*/
virtual void attemptResize( const QgsLayoutSize &size );

Expand All @@ -116,6 +117,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
* as data defined item position may override the specified value.
* \see attemptResize()
* \see referencePoint()
* \see positionWithUnits()
*/
virtual void attemptMove( const QgsLayoutPoint &point );

Expand All @@ -125,9 +127,17 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
* left corner of the item.
* \see attemptMove()
* \see referencePoint()
* \see sizeWithUnits()
*/
QgsLayoutPoint positionWithUnits() const { return mItemPosition; }

/**
* Returns the item's current size, including units.
* \see attemptResize()
* \see positionWithUnits()
*/
QgsLayoutSize sizeWithUnits() const { return mItemSize; }

public slots:

/**
Expand All @@ -136,6 +146,14 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void refresh() override;

/**
* Refreshes a data defined \a property for the item by reevaluating the property's value
* and redrawing the item with this new value. If \a property is set to
* QgsLayoutObject::AllProperties then all data defined properties for the item will be
* refreshed.
*/
virtual void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );

protected:

/** Draws a debugging rectangle of the item's current bounds within the specified
Expand Down Expand Up @@ -205,6 +223,8 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt

QSizeF applyMinimumSize( const QSizeF &targetSize );
QSizeF applyFixedSize( const QSizeF &targetSize );
QgsLayoutPoint applyDataDefinedPosition( const QgsLayoutPoint &position );
QgsLayoutSize applyDataDefinedSize( const QgsLayoutSize &size );

friend class TestQgsLayoutItem;
};
Expand Down

0 comments on commit 6fd0698

Please sign in to comment.