Skip to content
Permalink
Browse files
[composer] Respect reference point when resizing scalebar and legend
Previously, the reference point (and data defined position/size) were
ignored when scalebars or legends resized themselves.

Fix #11321, #11380
  • Loading branch information
nyalldawson committed Oct 21, 2014
1 parent ba8a60f commit 5b9210b91dc891d8043c289446f84b699989e735
@@ -761,8 +761,17 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
void deleteVAlignSnapItem();
void deleteAlignItems();

/**Update an item rect to consider data defined position and size of item*/
QRectF evalItemRect( const QRectF &newRect );
/**Evaluates an item's bounding rect to consider data defined position and size of item
* and reference point
* @param newRect target bouding rect for item
* @param resizeOnly set to true if the item is only being resized. If true then
* the position of the returned rect will be adjusted to account for the item's
* position mode
* @returns bounding box rectangle for item after data defined size and position have been
* set and position mode has been accounted for
* @note added in QGIS 2.5
*/
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false );

/**Returns whether the item should be drawn in the current context
* @returns true if item should be drawn
@@ -708,7 +708,7 @@ void QgsComposerItem::setSceneRect( const QRectF& rectangle )
emit sizeChanged();
}

QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOnly )
{
QRectF result = newRect;

@@ -737,14 +737,29 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
}

double x = result.left();
//initially adjust for position mode to get top-left coordinate
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
//initially adjust for position mode to get x coordinate
if ( !resizeOnly )
{
x += newRect.width() / 2.0;
//adjust x-coordinate if placement is not done to a left point
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
{
x += newRect.width() / 2.0;
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
{
x += newRect.width();
}
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
else
{
x += newRect.width();
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
{
x += rect().width() / 2.0;
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
{
x += rect().width();
}
}
if ( dataDefinedEvaluate( QgsComposerObject::PositionX, exprVal ) )
{
@@ -758,16 +773,30 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
}

double y = result.top();
//adjust y-coordinate if placement is not done to an upper point
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
//initially adjust for position mode to get y coordinate
if ( !resizeOnly )
{
y += newRect.height() / 2.0;
//adjust y-coordinate if placement is not done to an upper point
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
{
y += newRect.height() / 2.0;
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
{
y += newRect.height();
}
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
else
{
y += newRect.height();
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
{
y += rect().height() / 2.0;
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
{
y += rect().height();
}
}

if ( dataDefinedEvaluate( QgsComposerObject::PositionY, exprVal ) )
{
bool ok;
@@ -774,8 +774,17 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
void deleteVAlignSnapItem();
void deleteAlignItems();

/**Update an item rect to consider data defined position and size of item*/
QRectF evalItemRect( const QRectF &newRect );
/**Evaluates an item's bounding rect to consider data defined position and size of item
* and reference point
* @param newRect target bouding rect for item
* @param resizeOnly set to true if the item is only being resized. If true then
* the position of the returned rect will be adjusted to account for the item's
* position mode
* @returns bounding box rectangle for item after data defined size and position have been
* set and position mode has been accounted for
* @note added in QGIS 2.5
*/
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false );

/**Returns whether the item should be drawn in the current context
* @returns true if item should be drawn
@@ -103,10 +103,18 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem

//adjust box if width or height is too small
QSizeF size = legendRenderer.minimumSize();
if ( size.height() > rect().height() )
setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), size.height() ) );
if ( size.width() > rect().width() )
setSceneRect( QRectF( pos().x(), pos().y(), size.width(), rect().height() ) );
if ( size.height() > rect().height() || size.width() > rect().width() )
{
//need to resize box
QRectF targetRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
if ( size.height() > targetRect.height() )
targetRect.setHeight( size.height() );
if ( size.width() > rect().width() )
targetRect.setWidth( size.width() );

//set new rect, respecting position mode and data defined size/position
setSceneRect( evalItemRect( targetRect, true ) );
}

legendRenderer.drawLegend( painter );

@@ -137,7 +145,9 @@ void QgsComposerLegend::adjustBoxSize()
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
if ( size.isValid() )
{
setSceneRect( QRectF( pos().x(), pos().y(), size.width(), size.height() ) );
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
//set new rect, respecting position mode and data defined size/position
setSceneRect( evalItemRect( targetRect, true ) );
}
}

@@ -389,7 +389,7 @@ void QgsComposerScaleBar::adjustBoxSize()
QRectF box = mStyle->calculateBoxSize();

//update rect for data defined size and position
QRectF newRect = evalItemRect( box );
QRectF newRect = evalItemRect( box, true );

//scale bars have a minimum size, respect that regardless of data defined settings
if ( newRect.width() < box.width() )

2 comments on commit 5b9210b

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn replied Oct 21, 2014

Very, very good.

I assume it's already the case for other items, like labels, right?

@nyalldawson

This comment has been minimized.

Copy link
Collaborator Author

@nyalldawson nyalldawson replied Oct 21, 2014

@nirvn that should already be the case. Can you please file issues if you run into any other circumstances where the reference point is not respected?

Please sign in to comment.