Skip to content

Commit

Permalink
[FEATURE][composer] Data definable item frame and background colors
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jan 23, 2017
1 parent ad23240 commit d6c7569
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 31 deletions.
2 changes: 2 additions & 0 deletions python/core/composer/qgscomposerobject.sip
Expand Up @@ -32,6 +32,8 @@ class QgsComposerObject : QObject, QgsExpressionContextGenerator
Transparency, /*!< item transparency */
BlendMode, /*!< item blend mode */
ExcludeFromExports, /*!< exclude item from exports */
FrameColor, //!< Item frame color
BackgroundColor, //!< Item background color
//composer map
MapRotation, /*!< map rotation */
MapScale, /*!< map scale */
Expand Down
4 changes: 4 additions & 0 deletions src/app/composer/qgscomposeritemwidget.cpp
Expand Up @@ -541,6 +541,10 @@ void QgsComposerItemWidget::populateDataDefinedButtons()
QgsDataDefinedButtonV2::String, QgsDataDefinedButtonV2::blendModesDesc() );
mConfigObject->registerDataDefinedButton( mExcludePrintsDDBtn, QgsComposerObject::ExcludeFromExports,
QgsDataDefinedButtonV2::String, QgsDataDefinedButtonV2::boolDesc() );
mConfigObject->registerDataDefinedButton( mItemFrameColorDDBtn, QgsComposerObject::FrameColor,
QgsDataDefinedButtonV2::String, QgsDataDefinedButtonV2::colorAlphaDesc() );
mConfigObject->registerDataDefinedButton( mItemBackgroundColorDDBtn, QgsComposerObject::BackgroundColor,
QgsDataDefinedButtonV2::String, QgsDataDefinedButtonV2::colorAlphaDesc() );
}

void QgsComposerItemWidget::setValuesForGuiElements()
Expand Down
115 changes: 89 additions & 26 deletions src/core/composer/qgscomposeritem.cpp
Expand Up @@ -54,7 +54,6 @@ QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue
, mFrame( false )
, mBackground( true )
, mBackgroundColor( QColor( 255, 255, 255, 255 ) )
, mFrameJoinStyle( Qt::MiterJoin )
, mItemPositionLocked( false )
, mLastValidViewScaleFactor( -1 )
, mItemRotation( 0 )
Expand All @@ -81,9 +80,9 @@ QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, Q
, mHAlignSnapItem( nullptr )
, mVAlignSnapItem( nullptr )
, mFrame( false )
, mFrameColor( QColor( 0, 0, 0 ) )
, mBackground( true )
, mBackgroundColor( QColor( 255, 255, 255, 255 ) )
, mFrameJoinStyle( Qt::MiterJoin )
, mItemPositionLocked( false )
, mLastValidViewScaleFactor( -1 )
, mItemRotation( 0 )
Expand All @@ -107,9 +106,9 @@ void QgsComposerItem::init( const bool manageZValue )
{
setFlag( QGraphicsItem::ItemIsSelectable, true );
//set default pen and brush
setBrush( QBrush( QColor( 255, 255, 255, 255 ) ) );
QPen defaultPen( QColor( 0, 0, 0 ) );
defaultPen.setWidthF( 0.3 );
setBrush( mBackgroundColor );
QPen defaultPen( mFrameColor );
defaultPen.setWidthF( mFrameWidth );
defaultPen.setJoinStyle( mFrameJoinStyle );
setPen( defaultPen );
//let z-Value be managed by composition
Expand Down Expand Up @@ -192,7 +191,7 @@ bool QgsComposerItem::_writeXml( QDomElement& itemElem, QDomDocument& doc ) cons
composerItemElem.setAttribute( QStringLiteral( "height" ), QString::number( rect().height() ) );
composerItemElem.setAttribute( QStringLiteral( "positionMode" ), QString::number( static_cast< int >( mLastUsedPositionMode ) ) );
composerItemElem.setAttribute( QStringLiteral( "zValue" ), QString::number( zValue() ) );
composerItemElem.setAttribute( QStringLiteral( "outlineWidth" ), QString::number( pen().widthF() ) );
composerItemElem.setAttribute( QStringLiteral( "outlineWidth" ), QString::number( mFrameWidth ) );
composerItemElem.setAttribute( QStringLiteral( "frameJoinStyle" ), QgsSymbolLayerUtils::encodePenJoinStyle( mFrameJoinStyle ) );
composerItemElem.setAttribute( QStringLiteral( "itemRotation" ), QString::number( mItemRotation ) );
composerItemElem.setAttribute( QStringLiteral( "uuid" ), mUuid );
Expand All @@ -212,20 +211,18 @@ bool QgsComposerItem::_writeXml( QDomElement& itemElem, QDomDocument& doc ) cons

//frame color
QDomElement frameColorElem = doc.createElement( QStringLiteral( "FrameColor" ) );
QColor frameColor = pen().color();
frameColorElem.setAttribute( QStringLiteral( "red" ), QString::number( frameColor.red() ) );
frameColorElem.setAttribute( QStringLiteral( "green" ), QString::number( frameColor.green() ) );
frameColorElem.setAttribute( QStringLiteral( "blue" ), QString::number( frameColor.blue() ) );
frameColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( frameColor.alpha() ) );
frameColorElem.setAttribute( QStringLiteral( "red" ), QString::number( mFrameColor.red() ) );
frameColorElem.setAttribute( QStringLiteral( "green" ), QString::number( mFrameColor.green() ) );
frameColorElem.setAttribute( QStringLiteral( "blue" ), QString::number( mFrameColor.blue() ) );
frameColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( mFrameColor.alpha() ) );
composerItemElem.appendChild( frameColorElem );

//background color
QDomElement bgColorElem = doc.createElement( QStringLiteral( "BackgroundColor" ) );
QColor bgColor = brush().color();
bgColorElem.setAttribute( QStringLiteral( "red" ), QString::number( bgColor.red() ) );
bgColorElem.setAttribute( QStringLiteral( "green" ), QString::number( bgColor.green() ) );
bgColorElem.setAttribute( QStringLiteral( "blue" ), QString::number( bgColor.blue() ) );
bgColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( bgColor.alpha() ) );
bgColorElem.setAttribute( QStringLiteral( "red" ), QString::number( mBackgroundColor.red() ) );
bgColorElem.setAttribute( QStringLiteral( "green" ), QString::number( mBackgroundColor.green() ) );
bgColorElem.setAttribute( QStringLiteral( "blue" ), QString::number( mBackgroundColor.blue() ) );
bgColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( mBackgroundColor.alpha() ) );
composerItemElem.appendChild( bgColorElem );

//blend mode
Expand Down Expand Up @@ -335,6 +332,8 @@ bool QgsComposerItem::_readXml( const QDomElement& itemElem, const QDomDocument&

setZValue( itemElem.attribute( QStringLiteral( "zValue" ) ).toDouble() );

QgsExpressionContext context = createExpressionContext();

//pen
QDomNodeList frameColorList = itemElem.elementsByTagName( QStringLiteral( "FrameColor" ) );
if ( !frameColorList.isEmpty() )
Expand All @@ -353,10 +352,14 @@ bool QgsComposerItem::_readXml( const QDomElement& itemElem, const QDomDocument&

if ( redOk && greenOk && blueOk && alphaOk && widthOk )
{
QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
framePen.setWidthF( penWidth );
mFrameColor = QColor( penRed, penGreen, penBlue, penAlpha );
mFrameWidth = penWidth;
QPen framePen( mFrameColor );
framePen.setWidthF( mFrameWidth );
framePen.setJoinStyle( mFrameJoinStyle );
setPen( framePen );
//apply any data defined settings
refreshFrameColor( false, context );
}
}

Expand All @@ -373,9 +376,11 @@ bool QgsComposerItem::_readXml( const QDomElement& itemElem, const QDomDocument&
bgAlpha = bgColorElem.attribute( QStringLiteral( "alpha" ) ).toDouble( &alphaOk );
if ( redOk && greenOk && blueOk && alphaOk )
{
QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
setBackgroundColor( brushColor );
mBackgroundColor = QColor( bgRed, bgGreen, bgBlue, bgAlpha );
setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
}
//apply any data defined settings
refreshBackgroundColor( false, context );
}

//blend mode
Expand Down Expand Up @@ -407,26 +412,31 @@ void QgsComposerItem::setFrameEnabled( const bool drawFrame )

void QgsComposerItem::setFrameOutlineColor( const QColor &color )
{
QPen itemPen = pen();
if ( itemPen.color() == color )
if ( mFrameColor == color )
{
//no change
return;
}
itemPen.setColor( color );
mFrameColor = color;
QPen itemPen = pen();
itemPen.setColor( mFrameColor );
setPen( itemPen );
// apply any datadefined overrides
QgsExpressionContext context = createExpressionContext();
refreshFrameColor( true, context );
emit frameChanged();
}

void QgsComposerItem::setFrameOutlineWidth( const double outlineWidth )
{
QPen itemPen = pen();
if ( qgsDoubleNear( itemPen.widthF(), outlineWidth ) )
if ( qgsDoubleNear( mFrameWidth, outlineWidth ) )
{
//no change
return;
}
itemPen.setWidthF( outlineWidth );
mFrameWidth = outlineWidth;
QPen itemPen = pen();
itemPen.setWidthF( mFrameWidth );
setPen( itemPen );
emit frameChanged();
}
Expand Down Expand Up @@ -844,6 +854,9 @@ void QgsComposerItem::setBackgroundColor( const QColor& backgroundColor )
{
mBackgroundColor = backgroundColor;
setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
// apply any datadefined overrides
QgsExpressionContext context = createExpressionContext();
refreshBackgroundColor( true, context );
}

void QgsComposerItem::setBlendMode( const QPainter::CompositionMode blendMode )
Expand Down Expand Up @@ -897,6 +910,48 @@ void QgsComposerItem::refreshTransparency( const bool updateItem, const QgsExpre
}
}

void QgsComposerItem::refreshFrameColor( const bool updateItem, const QgsExpressionContext& context )
{
//data defined outline color set?
bool ok = false;
QColor frameColor = mProperties.valueAsColor( QgsComposerObject::FrameColor, context, mFrameColor, &ok );
if ( ok )
{
QPen itemPen = pen();
itemPen.setColor( frameColor );
setPen( itemPen );
}
else
{
QPen itemPen = pen();
itemPen.setColor( mFrameColor );
setPen( itemPen );
}
if ( updateItem )
{
update();
}
}

void QgsComposerItem::refreshBackgroundColor( const bool updateItem, const QgsExpressionContext& context )
{
//data defined color set?
bool ok = false;
QColor backgroundColor = mProperties.valueAsColor( QgsComposerObject::BackgroundColor, context, mBackgroundColor, &ok );
if ( ok )
{
setBrush( QBrush( backgroundColor, Qt::SolidPattern ) );
}
else
{
setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
}
if ( updateItem )
{
update();
}
}

void QgsComposerItem::setEffectsEnabled( const bool effectsEnabled )
{
//enable or disable the QgsComposerEffect applied to this item
Expand Down Expand Up @@ -1087,6 +1142,14 @@ void QgsComposerItem::refreshDataDefinedProperty( const QgsComposerObject::DataD
{
refreshBlendMode( *evalContext );
}
if ( property == QgsComposerObject::FrameColor || property == QgsComposerObject::AllProperties )
{
refreshFrameColor( false, *evalContext );
}
if ( property == QgsComposerObject::BackgroundColor || property == QgsComposerObject::AllProperties )
{
refreshBackgroundColor( false, *evalContext );
}
if ( property == QgsComposerObject::ExcludeFromExports || property == QgsComposerObject::AllProperties )
{
bool exclude = mExcludeFromExports;
Expand Down
27 changes: 23 additions & 4 deletions src/core/composer/qgscomposeritem.h
Expand Up @@ -260,7 +260,7 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
* @see frameJoinStyle
* @see setFrameOutlineColor
*/
QColor frameOutlineColor() const { return pen().color(); }
QColor frameOutlineColor() const { return mFrameColor; }

/** Sets frame outline width
* @param outlineWidth new width for outline frame
Expand All @@ -280,7 +280,7 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
* @see frameJoinStyle
* @see frameOutlineColor
*/
double frameOutlineWidth() const { return pen().widthF(); }
double frameOutlineWidth() const { return mFrameWidth; }

/** Returns the join style used for drawing the item's frame
* @returns Join style for outline frame
Expand Down Expand Up @@ -564,12 +564,17 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec

//! True if item fram needs to be painted
bool mFrame;
//! Item frame color
QColor mFrameColor;
//! Item frame width
double mFrameWidth = 0.3;
//! Frame join style
Qt::PenJoinStyle mFrameJoinStyle = Qt::MiterJoin;

//! True if item background needs to be painted
bool mBackground;
//! Background color
QColor mBackgroundColor;
//! Frame join style
Qt::PenJoinStyle mFrameJoinStyle;

/** True if item position and size cannot be changed with mouse move
*/
Expand Down Expand Up @@ -706,6 +711,20 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
*/
void refreshTransparency( const bool updateItem = true, const QgsExpressionContext &context = QgsExpressionContext() );

/** Refresh item's frame color, considering data defined transparency
* @param updateItem set to false to prevent the item being automatically updated
* after the frame color is set
* @param context expression context for evaulating data defined transparency
*/
void refreshFrameColor( const bool updateItem = true, const QgsExpressionContext &context = QgsExpressionContext() );

/** Refresh item's transparency, considering data defined transparency
* @param updateItem set to false to prevent the item being automatically updated
* after the background color is set
* @param context expression context for evaulating data defined transparency
*/
void refreshBackgroundColor( const bool updateItem = true, const QgsExpressionContext &context = QgsExpressionContext() );

/** Refresh item's blend mode, considering data defined blend mode
* @note this method was added in version 2.5
*/
Expand Down
2 changes: 2 additions & 0 deletions src/core/composer/qgscomposerobject.cpp
Expand Up @@ -40,6 +40,8 @@ const QgsPropertyDefinition QgsComposerObject::sPropertyNameMap
{ QgsComposerObject::Transparency, "dataDefinedTransparency" },
{ QgsComposerObject::BlendMode, "dataDefinedBlendMode" },
{ QgsComposerObject::ExcludeFromExports, "dataDefinedExcludeExports"},
{ QgsComposerObject::FrameColor, "dataDefinedFrameColor"},
{ QgsComposerObject::BackgroundColor, "dataDefinedBackgroundColor"},
{ QgsComposerObject::MapRotation, "dataDefinedMapRotation" },
{ QgsComposerObject::MapScale, "dataDefinedMapScale" },
{ QgsComposerObject::MapXMin, "dataDefinedMapXMin" },
Expand Down
2 changes: 2 additions & 0 deletions src/core/composer/qgscomposerobject.h
Expand Up @@ -59,6 +59,8 @@ class CORE_EXPORT QgsComposerObject: public QObject, public QgsExpressionContext
Transparency, //!< Item transparency
BlendMode, //!< Item blend mode
ExcludeFromExports, //!< Exclude item from exports
FrameColor, //!< Item frame color
BackgroundColor, //!< Item background color
//composer map
MapRotation, //!< Map rotation
MapScale, //!< Map scale
Expand Down
18 changes: 17 additions & 1 deletion src/ui/composer/qgscomposeritemwidgetbase.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>290</width>
<height>847</height>
<height>1017</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -453,6 +453,13 @@
</property>
</spacer>
</item>
<item>
<widget class="QgsDataDefinedButtonV2" name="mItemFrameColorDDBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
Expand Down Expand Up @@ -572,6 +579,13 @@
</property>
</spacer>
</item>
<item>
<widget class="QgsDataDefinedButtonV2" name="mItemBackgroundColorDDBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
Expand Down Expand Up @@ -816,10 +830,12 @@
<tabstop>mItemRotationDDBtn</tabstop>
<tabstop>mFrameGroupBox</tabstop>
<tabstop>mFrameColorButton</tabstop>
<tabstop>mItemFrameColorDDBtn</tabstop>
<tabstop>mOutlineWidthSpinBox</tabstop>
<tabstop>mFrameJoinStyleCombo</tabstop>
<tabstop>mBackgroundGroupBox</tabstop>
<tabstop>mBackgroundColorButton</tabstop>
<tabstop>mItemBackgroundColorDDBtn</tabstop>
<tabstop>groupBox</tabstop>
<tabstop>mItemIdLineEdit</tabstop>
<tabstop>groupRendering</tabstop>
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -25,6 +25,7 @@ ADD_PYTHON_TEST(PyQgsColorScheme test_qgscolorscheme.py)
ADD_PYTHON_TEST(PyQgsColorSchemeRegistry test_qgscolorschemeregistry.py)
ADD_PYTHON_TEST(PyQgsComposerEffects test_qgscomposereffects.py)
ADD_PYTHON_TEST(PyQgsComposerHtml test_qgscomposerhtml.py)
ADD_PYTHON_TEST(PyQgsComposerItem test_qgscomposeritem.py)
ADD_PYTHON_TEST(PyQgsComposerLabel test_qgscomposerlabel.py)
ADD_PYTHON_TEST(PyQgsComposerLegend test_qgscomposerlegend.py)
ADD_PYTHON_TEST(PyQgsComposerMap test_qgscomposermap.py)
Expand Down

0 comments on commit d6c7569

Please sign in to comment.