Skip to content
Permalink
Browse files

Port item opacity handling from composer

  • Loading branch information
nyalldawson committed Oct 10, 2017
1 parent 75898d8 commit 3678f01e54851b18eae9cc01386ebde0f051f987
@@ -425,6 +425,25 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
%Docstring
Sets the item's composition blending ``mode``.
.. seealso:: blendMode()
%End

double itemOpacity() const;
%Docstring
Returns the item's opacity. This method should be used instead of
QGraphicsItem.opacity() as any data defined overrides will be
respected.
:return: opacity as double between 1.0 (opaque) and 0 (transparent).
.. seealso:: setItemOpacity()
:rtype: float
%End

void setItemOpacity( double opacity );
%Docstring
Sets the item's ``opacity``. This method should be used instead of
QGraphicsItem.setOpacity() as any data defined overrides will be
respected.
\param opacity double between 1.0 (opaque) and 0 (transparent).
.. seealso:: itemOpacity()
%End

bool excludeFromExports() const;
@@ -591,6 +610,13 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
.. seealso:: refreshItemPosition()
%End

void refreshOpacity( bool updateItem = true );
%Docstring
Refresh item's opacity, considering data defined opacity.
If ``updateItem`` is set to false the item will not be automatically
updated after the opacity is set and a later call to update() must be made.
%End

void refreshFrame( bool updateItem = true );
%Docstring
Refresh item's frame, considering data defined colors and frame size.
@@ -532,6 +532,12 @@ void QgsLayoutItem::setBlendMode( const QPainter::CompositionMode mode )
refreshBlendMode();
}

void QgsLayoutItem::setItemOpacity( double opacity )
{
mOpacity = opacity;
refreshOpacity( true );
}

bool QgsLayoutItem::excludeFromExports() const
{
return mExcludeFromExports;
@@ -630,6 +636,10 @@ void QgsLayoutItem::refreshDataDefinedProperty( const QgsLayoutObject::DataDefin
{
refreshItemRotation();
}
if ( property == QgsLayoutObject::Opacity || property == QgsLayoutObject::AllProperties )
{
refreshOpacity( false );
}
if ( property == QgsLayoutObject::FrameColor || property == QgsLayoutObject::AllProperties )
{
refreshFrame( false );
@@ -871,11 +881,8 @@ bool QgsLayoutItem::writePropertiesToElement( QDomElement &element, QDomDocument
//blend mode
element.setAttribute( "blendMode", QgsPainting::getBlendModeEnum( mBlendMode ) );

//TODO
#if 0
//transparency
// composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );
#endif
//opacity
element.setAttribute( QStringLiteral( "opacity" ), QString::number( mOpacity ) );

element.setAttribute( "excludeFromExports", mExcludeFromExports );

@@ -998,10 +1005,16 @@ bool QgsLayoutItem::readPropertiesFromElement( const QDomElement &element, const
//blend mode
setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( element.attribute( QStringLiteral( "blendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );

#if 0 //TODO
//transparency
setTransparency( itemElem.attribute( "transparency", "0" ).toInt() );
#endif
//opacity
if ( element.hasAttribute( QStringLiteral( "opacity" ) ) )
{
setItemOpacity( element.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1" ) ).toDouble() );
}
else
{
setItemOpacity( 1.0 - element.attribute( QStringLiteral( "transparency" ), QStringLiteral( "0" ) ).toInt() / 100.0 );
}

mExcludeFromExports = element.attribute( QStringLiteral( "excludeFromExports" ), QStringLiteral( "0" ) ).toInt();
mEvaluatedExcludeFromExports = mExcludeFromExports;

@@ -1065,6 +1078,20 @@ void QgsLayoutItem::refreshItemRotation()
setItemRotation( itemRotation() );
}

void QgsLayoutItem::refreshOpacity( bool updateItem )
{
//data defined opacity set?
double opacity = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::Opacity, createExpressionContext(), mOpacity * 100.0 );

// Set the QGraphicItem's opacity
setOpacity( opacity / 100.0 );

if ( updateItem )
{
update();
}
}

void QgsLayoutItem::refreshFrame( bool updateItem )
{
if ( !mFrame )
@@ -429,6 +429,24 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void setBlendMode( const QPainter::CompositionMode mode );

/**
* Returns the item's opacity. This method should be used instead of
* QGraphicsItem::opacity() as any data defined overrides will be
* respected.
* \returns opacity as double between 1.0 (opaque) and 0 (transparent).
* \see setItemOpacity()
*/
double itemOpacity() const { return mOpacity; }

/**
* Sets the item's \a opacity. This method should be used instead of
* QGraphicsItem::setOpacity() as any data defined overrides will be
* respected.
* \param opacity double between 1.0 (opaque) and 0 (transparent).
* \see itemOpacity()
*/
void setItemOpacity( double opacity );

/**
* Returns whether the item should be excluded from layout exports and prints.
* \see setExcludeFromExports()
@@ -589,6 +607,13 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void refreshItemRotation();

/**
* Refresh item's opacity, considering data defined opacity.
* If \a updateItem is set to false the item will not be automatically
* updated after the opacity is set and a later call to update() must be made.
*/
void refreshOpacity( bool updateItem = true );

/**
* Refresh item's frame, considering data defined colors and frame size.
* If \a updateItem is set to false, the item will not be automatically updated
@@ -682,6 +707,9 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
QPainter::CompositionMode mBlendMode = QPainter::CompositionMode_SourceOver;
std::unique_ptr< QgsLayoutEffect > mEffect;

//! Item opacity, between 0 and 1
double mOpacity = 1.0;

QImage mItemCachedImage;
double mItemCacheDpi = -1;

@@ -641,8 +641,9 @@ void QgsLayoutItemPropertiesWidget::setValuesForGuiNonPositionElements()
mFrameGroupBox->setChecked( mItem->hasFrame() );
mBackgroundGroupBox->setChecked( mItem->hasBackground() );
mBlendModeCombo->setBlendMode( mItem->blendMode() );
#if 0//TODO
mOpacityWidget->setOpacity( mItem->itemOpacity() );

#if 0//TODO
mItemRotationSpinBox->setValue( mItem->itemRotation( QgsComposerObject::OriginalValue ) );
#endif
mExcludeFromPrintsCheckBox->setChecked( mItem->excludeFromExports() );
@@ -708,9 +709,7 @@ void QgsLayoutItemPropertiesWidget::opacityChanged( double value )
if ( mItem )
{
mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Opacity" ), QgsLayoutItem::UndoOpacity );
#if 0 //TODO
mItem->setItemOpacity( value );
#endif
mItem->layout()->undoStack()->endCommand();
}
}
@@ -152,6 +152,7 @@ class TestQgsLayoutItem: public QObject
void multiItemUndo();
void overlappingUndo();
void blendMode();
void opacity();
void excludeFromExports();

private:
@@ -1357,6 +1358,7 @@ void TestQgsLayoutItem::writeReadXmlProperties()
original->setBackgroundColor( QColor( 200, 150, 100 ) );
original->setBlendMode( QPainter::CompositionMode_Darken );
original->setExcludeFromExports( true );
original->setItemOpacity( 0.75 );

QgsLayoutItem *copy = createCopyViaXml( &l, original );

@@ -1381,6 +1383,7 @@ void TestQgsLayoutItem::writeReadXmlProperties()
QCOMPARE( copy->backgroundColor(), QColor( 200, 150, 100 ) );
QCOMPARE( copy->blendMode(), QPainter::CompositionMode_Darken );
QVERIFY( copy->excludeFromExports( ) );
QCOMPARE( copy->itemOpacity(), 0.75 );

delete copy;
delete original;
@@ -1559,6 +1562,24 @@ void TestQgsLayoutItem::blendMode()
QCOMPARE( item->mEffect->compositionMode(), QPainter::CompositionMode_Lighten );
}

void TestQgsLayoutItem::opacity()
{
QgsProject proj;
QgsLayout l( &proj );

QgsLayoutItemRectangularShape *item = new QgsLayoutItemRectangularShape( &l );
l.addLayoutItem( item );

item->setItemOpacity( 0.75 );
QCOMPARE( item->itemOpacity(), 0.75 );
QCOMPARE( item->opacity(), 0.75 );

item->dataDefinedProperties().setProperty( QgsLayoutObject::Opacity, QgsProperty::fromExpression( "35" ) );
item->refreshDataDefinedProperty();
QCOMPARE( item->itemOpacity(), 0.75 ); // should not change
QCOMPARE( item->opacity(), 0.35 );
}

void TestQgsLayoutItem::excludeFromExports()
{
QgsProject proj;

0 comments on commit 3678f01

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