mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE][composer] Data defined item rotation. Funded by Canton of Neuchâtel, Switzerland
This commit is contained in:
parent
a3c8289942
commit
0fd99d2820
@ -163,6 +163,16 @@ class QgsComposerItem : QObject, QGraphicsRectItem
|
||||
MapYMax /*< map extent y maximum */
|
||||
};
|
||||
|
||||
/** Specifies whether the value returned by a function should be the original, user
|
||||
* set value, or the current evaluated value for the property. This may differ if
|
||||
* a property has a data defined expression active.
|
||||
*/
|
||||
enum PropertyValueType
|
||||
{
|
||||
EvaluatedValue = 0, /*< return the current evaluated value for the property */
|
||||
OriginalValue /*< return the original, user set value */
|
||||
};
|
||||
|
||||
/**Constructor
|
||||
@param composition parent composition
|
||||
@param manageZValue true if the z-Value of this object should be managed by mComposition*/
|
||||
@ -458,9 +468,14 @@ class QgsComposerItem : QObject, QGraphicsRectItem
|
||||
@note this method was added in version 1.2*/
|
||||
bool positionLock() const;
|
||||
|
||||
/**Returns the rotation for the composer item
|
||||
@note this method was added in version 2.1*/
|
||||
double itemRotation() const;
|
||||
/**Returns the current rotation for the composer item.
|
||||
* @returns rotation for composer item
|
||||
* @param valueType controls whether the returned value is the user specified rotation,
|
||||
* or the current evaluated rotation (which may be affected by data driven rotation
|
||||
* settings).
|
||||
* @note this method was added in version 2.1
|
||||
*/
|
||||
double itemRotation( PropertyValueType valueType = EvaluatedValue ) const;
|
||||
|
||||
/**Returns the rotation for the composer item
|
||||
* @deprecated Use itemRotation()
|
||||
|
@ -470,8 +470,9 @@ class QgsComposition : QGraphicsScene
|
||||
|
||||
/**Forces items in the composition to refresh. For instance, this causes maps to redraw
|
||||
* and rebuild cached images, html items to reload their source url, and attribute tables
|
||||
* to refresh their contents.
|
||||
@note added in version 2.3*/
|
||||
* to refresh their contents. Calling this also triggers a recalculation of all data defined
|
||||
* attributes within the composition.
|
||||
* @note added in version 2.3*/
|
||||
void refreshItems();
|
||||
|
||||
/**Clears any selected items and sets an item as the current selection.
|
||||
|
@ -150,6 +150,10 @@ QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem*
|
||||
}
|
||||
|
||||
//connect data defined buttons
|
||||
connect( mItemRotationDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
|
||||
connect( mItemRotationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
|
||||
connect( mItemRotationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mItemRotationSpinBox, SLOT( setDisabled( bool ) ) );
|
||||
|
||||
connect( mTransparencyDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
|
||||
connect( mTransparencyDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
|
||||
connect( mTransparencyDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mTransparencySlider, SLOT( setDisabled( bool ) ) );
|
||||
@ -494,7 +498,7 @@ void QgsComposerItemWidget::setValuesForGuiNonPositionElements()
|
||||
mBlendModeCombo->setBlendMode( mItem->blendMode() );
|
||||
mTransparencySlider->setValue( mItem->transparency() );
|
||||
mTransparencySpnBx->setValue( mItem->transparency() );
|
||||
mItemRotationSpinBox->setValue( mItem->itemRotation() );
|
||||
mItemRotationSpinBox->setValue( mItem->itemRotation( QgsComposerItem::OriginalValue ) );
|
||||
|
||||
mBackgroundColorButton->blockSignals( false );
|
||||
mFrameColorButton->blockSignals( false );
|
||||
@ -514,28 +518,37 @@ void QgsComposerItemWidget::populateDataDefinedButtons()
|
||||
QgsVectorLayer* vl = atlasCoverageLayer();
|
||||
|
||||
//block signals from data defined buttons
|
||||
mItemRotationDDBtn->blockSignals( true );
|
||||
mTransparencyDDBtn->blockSignals( true );
|
||||
mBlendModeDDBtn->blockSignals( true );
|
||||
|
||||
//initialise buttons to use atlas coverage layer
|
||||
mItemRotationDDBtn->init( vl, mItem->dataDefinedProperty( QgsComposerItem::ItemRotation ),
|
||||
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
|
||||
mTransparencyDDBtn->init( vl, mItem->dataDefinedProperty( QgsComposerItem::Transparency ),
|
||||
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
|
||||
mBlendModeDDBtn->init( vl, mItem->dataDefinedProperty( QgsComposerItem::BlendMode ),
|
||||
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
|
||||
|
||||
//initial state of controls - disable related controls when dd buttons are active
|
||||
mItemRotationSpinBox->setEnabled( !mItemRotationDDBtn->isActive() );
|
||||
mTransparencySlider->setEnabled( !mTransparencyDDBtn->isActive() );
|
||||
mTransparencySpnBx->setEnabled( !mTransparencyDDBtn->isActive() );
|
||||
mBlendModeCombo->setEnabled( !mBlendModeDDBtn->isActive() );
|
||||
|
||||
//unblock signals from data defined buttons
|
||||
mItemRotationDDBtn->blockSignals( false );
|
||||
mTransparencyDDBtn->blockSignals( false );
|
||||
mBlendModeDDBtn->blockSignals( false );
|
||||
}
|
||||
|
||||
QgsComposerItem::DataDefinedProperty QgsComposerItemWidget::ddPropertyForWidget( QgsDataDefinedButton* widget )
|
||||
{
|
||||
if ( widget == mTransparencyDDBtn )
|
||||
if ( widget == mItemRotationDDBtn )
|
||||
{
|
||||
return QgsComposerItem::ItemRotation;
|
||||
}
|
||||
else if ( widget == mTransparencyDDBtn )
|
||||
{
|
||||
return QgsComposerItem::Transparency;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue
|
||||
, mItemPositionLocked( false )
|
||||
, mLastValidViewScaleFactor( -1 )
|
||||
, mItemRotation( 0 )
|
||||
, mEvaluatedItemRotation( 0 )
|
||||
, mBlendMode( QPainter::CompositionMode_SourceOver )
|
||||
, mEffectsEnabled( true )
|
||||
, mTransparency( 0 )
|
||||
@ -87,6 +88,7 @@ QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, Q
|
||||
, mItemPositionLocked( false )
|
||||
, mLastValidViewScaleFactor( -1 )
|
||||
, mItemRotation( 0 )
|
||||
, mEvaluatedItemRotation( 0 )
|
||||
, mBlendMode( QPainter::CompositionMode_SourceOver )
|
||||
, mEffectsEnabled( true )
|
||||
, mTransparency( 0 )
|
||||
@ -120,6 +122,7 @@ void QgsComposerItem::init( bool manageZValue )
|
||||
setGraphicsEffect( mEffect );
|
||||
|
||||
// data defined strings
|
||||
mDataDefinedNames.insert( ItemRotation, QString( "dataDefinedRotation" ) );
|
||||
mDataDefinedNames.insert( Transparency, QString( "dataDefinedTransparency" ) );
|
||||
mDataDefinedNames.insert( BlendMode, QString( "dataDefinedBlendMode" ) );
|
||||
|
||||
@ -531,6 +534,11 @@ void QgsComposerItem::setPositionLock( bool lock )
|
||||
mItemPositionLocked = lock;
|
||||
}
|
||||
|
||||
double QgsComposerItem::itemRotation( PropertyValueType valueType ) const
|
||||
{
|
||||
return valueType == EvaluatedValue ? mEvaluatedItemRotation : mItemRotation;
|
||||
}
|
||||
|
||||
void QgsComposerItem::move( double dx, double dy )
|
||||
{
|
||||
QRectF newSceneRect( pos().x() + dx, pos().y() + dy, rect().width(), rect().height() );
|
||||
@ -612,7 +620,7 @@ void QgsComposerItem::setItemPosition( double x, double y, double width, double
|
||||
{
|
||||
//adjust position to account for frame size
|
||||
|
||||
if ( mItemRotation == 0 )
|
||||
if ( mEvaluatedItemRotation == 0 )
|
||||
{
|
||||
upperLeftX += estimatedFrameBleed();
|
||||
upperLeftY += estimatedFrameBleed();
|
||||
@ -621,7 +629,7 @@ void QgsComposerItem::setItemPosition( double x, double y, double width, double
|
||||
{
|
||||
//adjust position for item rotation
|
||||
QLineF lineToItemOrigin = QLineF( 0, 0, estimatedFrameBleed(), estimatedFrameBleed() );
|
||||
lineToItemOrigin.setAngle( -45 - mItemRotation );
|
||||
lineToItemOrigin.setAngle( -45 - mEvaluatedItemRotation );
|
||||
upperLeftX += lineToItemOrigin.x2();
|
||||
upperLeftY += lineToItemOrigin.y2();
|
||||
}
|
||||
@ -935,20 +943,7 @@ void QgsComposerItem::setRotation( double r )
|
||||
|
||||
void QgsComposerItem::setItemRotation( double r, bool adjustPosition )
|
||||
{
|
||||
if ( adjustPosition )
|
||||
{
|
||||
//adjustPosition set, so shift the position of the item so that rotation occurs around item center
|
||||
//create a line from the centrepoint of the rect() to its origin, in scene coordinates
|
||||
QLineF refLine = QLineF( mapToScene( QPointF( rect().width() / 2.0, rect().height() / 2.0 ) ) , mapToScene( QPointF( 0 , 0 ) ) );
|
||||
//rotate this line by the current rotation angle
|
||||
refLine.setAngle( refLine.angle() - r + mItemRotation );
|
||||
//get new end point of line - this is the new item position
|
||||
QPointF rotatedReferencePoint = refLine.p2();
|
||||
setPos( rotatedReferencePoint );
|
||||
emit sizeChanged();
|
||||
}
|
||||
|
||||
if ( r > 360 )
|
||||
if ( r >= 360 )
|
||||
{
|
||||
mItemRotation = (( int )r ) % 360;
|
||||
}
|
||||
@ -957,17 +952,59 @@ void QgsComposerItem::setItemRotation( double r, bool adjustPosition )
|
||||
mItemRotation = r;
|
||||
}
|
||||
|
||||
setTransformOriginPoint( 0, 0 );
|
||||
QGraphicsItem::setRotation( mItemRotation );
|
||||
refreshRotation( true, adjustPosition );
|
||||
}
|
||||
|
||||
emit itemRotationChanged( r );
|
||||
update();
|
||||
void QgsComposerItem::refreshRotation( bool updateItem , bool adjustPosition )
|
||||
{
|
||||
double rotation = mItemRotation;
|
||||
|
||||
//data defined rotation set?
|
||||
QVariant exprVal;
|
||||
if ( dataDefinedEvaluate( QgsComposerItem::ItemRotation, exprVal ) )
|
||||
{
|
||||
bool ok;
|
||||
double rotD = exprVal.toDouble( &ok );
|
||||
QgsDebugMsg( QString( "exprVal Rotation:%1" ).arg( rotD ) );
|
||||
if ( ok )
|
||||
{
|
||||
rotation = rotD;
|
||||
}
|
||||
}
|
||||
|
||||
if ( adjustPosition )
|
||||
{
|
||||
//adjustPosition set, so shift the position of the item so that rotation occurs around item center
|
||||
//create a line from the centrepoint of the rect() to its origin, in scene coordinates
|
||||
QLineF refLine = QLineF( mapToScene( QPointF( rect().width() / 2.0, rect().height() / 2.0 ) ) , mapToScene( QPointF( 0 , 0 ) ) );
|
||||
//rotate this line by the current rotation angle
|
||||
refLine.setAngle( refLine.angle() - rotation + mEvaluatedItemRotation );
|
||||
//get new end point of line - this is the new item position
|
||||
QPointF rotatedReferencePoint = refLine.p2();
|
||||
setPos( rotatedReferencePoint );
|
||||
emit sizeChanged();
|
||||
}
|
||||
|
||||
setTransformOriginPoint( 0, 0 );
|
||||
QGraphicsItem::setRotation( rotation );
|
||||
|
||||
mEvaluatedItemRotation = rotation;
|
||||
|
||||
emit itemRotationChanged( rotation );
|
||||
|
||||
//update bounds of scene, since rotation may affect this
|
||||
mComposition->updateBounds();
|
||||
|
||||
if ( updateItem )
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
|
||||
{
|
||||
//kept for api compatibility with QGIS 2.0, use item rotation
|
||||
return imageSizeConsideringRotation( width, height, mItemRotation );
|
||||
return imageSizeConsideringRotation( width, height, mEvaluatedItemRotation );
|
||||
}
|
||||
|
||||
QRectF QgsComposerItem::largestRotatedRectWithinBounds( QRectF originalRect, QRectF boundsRect, double rotation ) const
|
||||
@ -1108,7 +1145,7 @@ bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& heigh
|
||||
bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
|
||||
{
|
||||
//kept for api compatibility with QGIS 2.0, use item rotation
|
||||
return cornerPointOnRotatedAndScaledRect( x, y, width, height, mItemRotation );
|
||||
return cornerPointOnRotatedAndScaledRect( x, y, width, height, mEvaluatedItemRotation );
|
||||
}
|
||||
|
||||
bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height, double rotation ) const
|
||||
@ -1151,7 +1188,7 @@ bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, d
|
||||
void QgsComposerItem::sizeChangedByRotation( double& width, double& height )
|
||||
{
|
||||
//kept for api compatibility with QGIS 2.0, use item rotation
|
||||
return sizeChangedByRotation( width, height, mItemRotation );
|
||||
return sizeChangedByRotation( width, height, mEvaluatedItemRotation );
|
||||
}
|
||||
|
||||
void QgsComposerItem::sizeChangedByRotation( double& width, double& height, double rotation )
|
||||
@ -1289,6 +1326,10 @@ void QgsComposerItem::repaint()
|
||||
void QgsComposerItem::refreshDataDefinedProperty( QgsComposerItem::DataDefinedProperty property )
|
||||
{
|
||||
//update data defined properties and redraw item to match
|
||||
if ( property == QgsComposerItem::ItemRotation || property == QgsComposerItem::AllProperties )
|
||||
{
|
||||
refreshRotation( false, true );
|
||||
}
|
||||
if ( property == QgsComposerItem::Transparency || property == QgsComposerItem::AllProperties )
|
||||
{
|
||||
refreshTransparency( false );
|
||||
|
@ -118,6 +118,16 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
MapYMax /*< map extent y maximum */
|
||||
};
|
||||
|
||||
/** Specifies whether the value returned by a function should be the original, user
|
||||
* set value, or the current evaluated value for the property. This may differ if
|
||||
* a property has a data defined expression active.
|
||||
*/
|
||||
enum PropertyValueType
|
||||
{
|
||||
EvaluatedValue = 0, /*< return the current evaluated value for the property */
|
||||
OriginalValue /*< return the original, user set value */
|
||||
};
|
||||
|
||||
/**Constructor
|
||||
@param composition parent composition
|
||||
@param manageZValue true if the z-Value of this object should be managed by mComposition*/
|
||||
@ -139,7 +149,7 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
virtual void setSelected( bool s );
|
||||
|
||||
/** \brief Is selected */
|
||||
virtual bool selected() const {return QGraphicsRectItem::isSelected();};
|
||||
virtual bool selected() const { return QGraphicsRectItem::isSelected(); }
|
||||
|
||||
/** stores state in project */
|
||||
virtual bool writeSettings();
|
||||
@ -414,15 +424,20 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
@note this method was added in version 1.2*/
|
||||
bool positionLock() const { return mItemPositionLocked; }
|
||||
|
||||
/**Returns the rotation for the composer item
|
||||
@note this method was added in version 2.1*/
|
||||
double itemRotation() const { return mItemRotation; }
|
||||
/**Returns the current rotation for the composer item.
|
||||
* @returns rotation for composer item
|
||||
* @param valueType controls whether the returned value is the user specified rotation,
|
||||
* or the current evaluated rotation (which may be affected by data driven rotation
|
||||
* settings).
|
||||
* @note this method was added in version 2.1
|
||||
*/
|
||||
double itemRotation( PropertyValueType valueType = EvaluatedValue ) const;
|
||||
|
||||
/**Returns the rotation for the composer item
|
||||
* @deprecated Use itemRotation()
|
||||
* instead
|
||||
*/
|
||||
Q_DECL_DEPRECATED double rotation() const { return mItemRotation; }
|
||||
Q_DECL_DEPRECATED double rotation() const { return mEvaluatedItemRotation; }
|
||||
|
||||
/**Updates item, with the possibility to do custom update for subclasses*/
|
||||
virtual void updateItem() { QGraphicsRectItem::update(); }
|
||||
@ -541,6 +556,10 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
|
||||
/**Item rotation in degrees, clockwise*/
|
||||
double mItemRotation;
|
||||
/**Temporary evaluated item rotation in degrees, clockwise. Data defined rotation may mean
|
||||
* this value differs from mItemRotation.
|
||||
*/
|
||||
double mEvaluatedItemRotation;
|
||||
|
||||
/**Composition blend mode for item*/
|
||||
QPainter::CompositionMode mBlendMode;
|
||||
@ -678,13 +697,24 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
/**Map of current data defined properties*/
|
||||
QMap< QgsComposerItem::DataDefinedProperty, QgsDataDefined* > mDataDefinedProperties;
|
||||
|
||||
/**Refresh item's rotation, considering data defined rotation setting
|
||||
*@param updateItem set to false to prevent the item being automatically updated
|
||||
*@param rotateAroundCenter set to true to rotate the item around its center rather
|
||||
* than its origin
|
||||
* @note this method was added in version 2.5
|
||||
*/
|
||||
void refreshRotation( bool updateItem = true, bool rotateAroundCenter = false );
|
||||
|
||||
/**Refresh item's transparency, considering data defined transparency
|
||||
*@param updateItem set to false to prevent the item being automatically updated
|
||||
* after the transparency is set
|
||||
* @note this method was added in version 2.5
|
||||
*/
|
||||
void refreshTransparency( bool updateItem = true );
|
||||
|
||||
/**Refresh item's blend mode, considering data defined blend mode*/
|
||||
/**Refresh item's blend mode, considering data defined blend mode
|
||||
* @note this method was added in version 2.5
|
||||
*/
|
||||
void refreshBlendMode();
|
||||
|
||||
void init( bool manageZValue );
|
||||
|
@ -531,8 +531,9 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
|
||||
|
||||
/**Forces items in the composition to refresh. For instance, this causes maps to redraw
|
||||
* and rebuild cached images, html items to reload their source url, and attribute tables
|
||||
* to refresh their contents.
|
||||
@note added in version 2.3*/
|
||||
* to refresh their contents. Calling this also triggers a recalculation of all data defined
|
||||
* attributes within the composition.
|
||||
* @note added in version 2.3*/
|
||||
void refreshItems();
|
||||
|
||||
/**Clears any selected items and sets an item as the current selection.
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>376</width>
|
||||
<height>693</height>
|
||||
<height>695</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -251,20 +251,31 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mItemRotationSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> °</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="mItemRotationSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> °</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDataDefinedButton" name="mItemRotationDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
Loading…
x
Reference in New Issue
Block a user