[FEATURE][diagrams] New diagram type "stacked bars"

Stacks bars of varying colors for each attribute on top of each other
vertically or horizontally.

Sponsored by SLYR
This commit is contained in:
Nyall Dawson 2019-11-23 06:41:45 +10:00
parent ec9e5986f5
commit 204bd47b19
21 changed files with 535 additions and 36 deletions

View File

@ -797,6 +797,7 @@
<file>themes/default/mActionShowUnplacedLabel.svg</file>
<file>themes/default/mActionHandleStoreFilterExpressionChecked.svg</file>
<file>themes/default/mActionHandleStoreFilterExpressionUnchecked.svg</file>
<file>themes/default/stacked-bar.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path fill="#fce94f" stroke="#c4a000" stroke-linecap="round" d="M4.5 15.5v-7h7v7z"/><path fill="#8ae234" stroke="#4e9a06" stroke-linecap="round" d="M4.5 7.5v-2h7v2z"/><path fill="#ef2929" stroke="#a40000" stroke-linecap="round" d="M4.5 4.5v-4h7v4z"/></svg>

After

Width:  |  Height:  |  Size: 320 B

View File

@ -20,6 +20,19 @@ Base class for all diagram types*
%End
public:
%ConvertToSubClassCode
if ( sipCpp->diagramName() == QStringLiteral( "Pie" ) )
sipType = sipType_QgsPieDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Histogram" ) )
sipType = sipType_QgsHistogramDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Text" ) )
sipType = sipType_QgsTextDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Stacked" ) )
sipType = sipType_QgsStackedBarDiagram;
else
sipType = NULL;
%End
virtual ~QgsDiagram();
virtual QgsDiagram *clone() const = 0 /Factory/;

View File

@ -0,0 +1,53 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/diagram/qgsstackedbardiagram.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsStackedBarDiagram: QgsDiagram
{
%Docstring
A stacked bar chart diagram.
.. versionadded:: 3.12
%End
%TypeHeaderCode
#include "qgsstackedbardiagram.h"
%End
public:
QgsStackedBarDiagram();
virtual QgsStackedBarDiagram *clone() const /Factory/;
virtual void renderDiagram( const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position );
virtual QSizeF diagramSize( const QgsAttributes &attributes, const QgsRenderContext &c, const QgsDiagramSettings &s );
virtual QSizeF diagramSize( const QgsFeature &feature, const QgsRenderContext &c, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is );
virtual double legendSize( double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) const;
virtual QString diagramName() const;
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/diagram/qgsstackedbardiagram.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -252,6 +252,7 @@
%Include auto_generated/diagram/qgsdiagram.sip
%Include auto_generated/diagram/qgshistogramdiagram.sip
%Include auto_generated/diagram/qgspiediagram.sip
%Include auto_generated/diagram/qgsstackedbardiagram.sip
%Include auto_generated/diagram/qgstextdiagram.sip
%Include auto_generated/dxf/qgsdxfexport.sip
%Include auto_generated/effects/qgsblureffect.sip

View File

@ -18,6 +18,7 @@
#include "diagram/qgshistogramdiagram.h"
#include "diagram/qgspiediagram.h"
#include "diagram/qgstextdiagram.h"
#include "diagram/qgsstackedbardiagram.h"
#include "qgsproject.h"
#include "qgsapplication.h"
@ -92,13 +93,15 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
mDiagramTypeComboBox->blockSignals( true );
QPixmap pix = QgsApplication::getThemePixmap( QStringLiteral( "diagramNone" ) );
mDiagramTypeComboBox->addItem( pix, tr( "No diagrams" ), "None" );
mDiagramTypeComboBox->addItem( pix, tr( "No Diagrams" ), "None" );
pix = QgsApplication::getThemePixmap( QStringLiteral( "pie-chart" ) );
mDiagramTypeComboBox->addItem( pix, tr( "Pie chart" ), DIAGRAM_NAME_PIE );
mDiagramTypeComboBox->addItem( pix, tr( "Pie Chart" ), DIAGRAM_NAME_PIE );
pix = QgsApplication::getThemePixmap( QStringLiteral( "text" ) );
mDiagramTypeComboBox->addItem( pix, tr( "Text diagram" ), DIAGRAM_NAME_TEXT );
mDiagramTypeComboBox->addItem( pix, tr( "Text Diagram" ), DIAGRAM_NAME_TEXT );
pix = QgsApplication::getThemePixmap( QStringLiteral( "histogram" ) );
mDiagramTypeComboBox->addItem( pix, tr( "Histogram" ), DIAGRAM_NAME_HISTOGRAM );
pix = QgsApplication::getThemePixmap( QStringLiteral( "stacked-bar" ) );
mDiagramTypeComboBox->addItem( pix, tr( "Stacked Bars" ), DIAGRAM_NAME_STACKED );
mDiagramTypeComboBox->blockSignals( false );
mAxisLineStyleButton->setSymbolType( QgsSymbol::Line );
@ -549,7 +552,7 @@ void QgsDiagramProperties::mDiagramTypeComboBox_currentIndexChanged( int index )
mDiagramFontButton->hide();
}
if ( DIAGRAM_NAME_HISTOGRAM == mDiagramType )
if ( DIAGRAM_NAME_HISTOGRAM == mDiagramType || DIAGRAM_NAME_STACKED == mDiagramType )
{
mBarWidthLabel->show();
mBarWidthSpinBox->show();
@ -558,9 +561,10 @@ void QgsDiagramProperties::mDiagramTypeComboBox_currentIndexChanged( int index )
mBarSpacingUnitComboBox->show();
mBarOptionsFrame->show();
mShowAxisGroupBox->show();
if ( DIAGRAM_NAME_HISTOGRAM == mDiagramType )
mAttributeBasedScalingRadio->setChecked( true );
mFixedSizeRadio->setEnabled( false );
mDiagramSizeSpinBox->setEnabled( false );
mFixedSizeRadio->setEnabled( DIAGRAM_NAME_STACKED == mDiagramType );
mDiagramSizeSpinBox->setEnabled( DIAGRAM_NAME_STACKED == mDiagramType );
mLinearlyScalingLabel->setText( tr( "Bar length: Scale linearly, so that the following value matches the specified bar length:" ) );
mSizeLabel->setText( tr( "Bar length" ) );
mFrameIncreaseSize->setVisible( false );
@ -748,7 +752,7 @@ void QgsDiagramProperties::apply()
int index = mDiagramTypeComboBox->currentIndex();
bool diagramsEnabled = ( index != 0 );
QgsDiagram *diagram = nullptr;
std::unique_ptr< QgsDiagram > diagram;
if ( diagramsEnabled && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
{
@ -760,15 +764,19 @@ void QgsDiagramProperties::apply()
if ( mDiagramType == DIAGRAM_NAME_TEXT )
{
diagram = new QgsTextDiagram();
diagram = qgis::make_unique< QgsTextDiagram >();
}
else if ( mDiagramType == DIAGRAM_NAME_PIE )
{
diagram = new QgsPieDiagram();
diagram = qgis::make_unique< QgsPieDiagram >();
}
else if ( mDiagramType == DIAGRAM_NAME_STACKED )
{
diagram = qgis::make_unique< QgsStackedBarDiagram >();
}
else // if ( diagramType == DIAGRAM_NAME_HISTOGRAM )
{
diagram = new QgsHistogramDiagram();
diagram = qgis::make_unique< QgsHistogramDiagram >();
}
QgsDiagramSettings ds;
@ -799,7 +807,7 @@ void QgsDiagramProperties::apply()
ds.lineSizeUnit = mDiagramLineUnitComboBox->unit();
ds.lineSizeScale = mDiagramLineUnitComboBox->getMapUnitScale();
ds.labelPlacementMethod = static_cast<QgsDiagramSettings::LabelPlacementMethod>( mLabelPlacementComboBox->currentData().toInt() );
ds.scaleByArea = mScaleDependencyComboBox->currentData().toBool();
ds.scaleByArea = ( mDiagramType == DIAGRAM_NAME_STACKED ) ? false : mScaleDependencyComboBox->currentData().toBool();
if ( mIncreaseSmallDiagramsCheck->isChecked() )
{
@ -865,7 +873,7 @@ void QgsDiagramProperties::apply()
renderer = dr;
}
renderer->setDiagram( diagram );
renderer->setDiagram( diagram.release() );
renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
mLayer->setDiagramRenderer( renderer );

View File

@ -76,6 +76,7 @@ SET(QGIS_CORE_SRCS
diagram/qgsdiagram.cpp
diagram/qgshistogramdiagram.cpp
diagram/qgspiediagram.cpp
diagram/qgsstackedbardiagram.cpp
diagram/qgstextdiagram.cpp
effects/qgsblureffect.cpp
@ -944,6 +945,7 @@ SET(QGIS_CORE_HDRS
diagram/qgsdiagram.h
diagram/qgshistogramdiagram.h
diagram/qgspiediagram.h
diagram/qgsstackedbardiagram.h
diagram/qgstextdiagram.h
dxf/qgsdxfexport.h

View File

@ -39,6 +39,21 @@ class CORE_EXPORT QgsDiagram
{
public:
#ifdef SIP_RUN
SIP_CONVERT_TO_SUBCLASS_CODE
if ( sipCpp->diagramName() == QStringLiteral( "Pie" ) )
sipType = sipType_QgsPieDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Histogram" ) )
sipType = sipType_QgsHistogramDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Text" ) )
sipType = sipType_QgsTextDiagram;
else if ( sipCpp->diagramName() == QStringLiteral( "Stacked" ) )
sipType = sipType_QgsStackedBarDiagram;
else
sipType = NULL;
SIP_END
#endif
virtual ~QgsDiagram() { clearCache(); }
/**

View File

@ -0,0 +1,238 @@
/***************************************************************************
qgsstackedbardiagram.cpp
---------------------
begin : November 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsstackedbardiagram.h"
#include "qgsdiagramrenderer.h"
#include "qgsrendercontext.h"
#include "qgsexpression.h"
#include <QPainter>
QgsStackedBarDiagram::QgsStackedBarDiagram()
{
mCategoryBrush.setStyle( Qt::SolidPattern );
mPen.setStyle( Qt::SolidLine );
}
QgsStackedBarDiagram *QgsStackedBarDiagram::clone() const
{
return new QgsStackedBarDiagram( *this );
}
QSizeF QgsStackedBarDiagram::diagramSize( const QgsFeature &feature, const QgsRenderContext &c, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is )
{
if ( qgsDoubleNear( is.upperValue, is.lowerValue ) )
return QSizeF(); // invalid value range => zero size
QVariant attrVal;
if ( is.classificationAttributeIsExpression )
{
QgsExpressionContext expressionContext = c.expressionContext();
if ( !feature.fields().isEmpty() )
expressionContext.setFields( feature.fields() );
expressionContext.setFeature( feature );
QgsExpression *expression = getExpression( is.classificationAttributeExpression, expressionContext );
attrVal = expression->evaluate( &expressionContext );
}
else
{
attrVal = feature.attribute( is.classificationField );
}
bool ok = false;
double value = attrVal.toDouble( &ok );
if ( !ok )
{
return QSizeF(); //zero size if attribute is missing
}
QSizeF size = sizeForValue( value, s, is );
// eh - this method returns size in unknown units ...! We'll have to fake it and use a rough estimation of
// a conversion factor to painter units...
// TODO QGIS 4.0 -- these methods should all use painter units, dependent on the render context scaling...
double painterUnitConversionScale = c.convertToPainterUnits( 1, s.sizeType );
const double spacing = c.convertToPainterUnits( s.spacing(), s.spacingUnit(), s.spacingMapUnitScale() ) / painterUnitConversionScale;
mApplySpacingAdjust = true;
switch ( s.diagramOrientation )
{
case QgsDiagramSettings::Up:
case QgsDiagramSettings::Down:
{
const double totalBarLength = size.height() + spacing * std::max( 0, s.categoryAttributes.size() - 1 );
size = QSizeF( s.barWidth, totalBarLength );
break;
}
case QgsDiagramSettings::Right:
case QgsDiagramSettings::Left:
{
const double totalBarLength = size.width() + spacing * std::max( 0, s.categoryAttributes.size() - 1 );
size = QSizeF( totalBarLength, s.barWidth );
break;
}
}
return size;
}
double QgsStackedBarDiagram::legendSize( double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) const
{
if ( qgsDoubleNear( is.upperValue, is.lowerValue ) )
return s.minimumSize; // invalid value range => zero size
// Scale, if extension is smaller than the specified minimum
if ( value < s.minimumSize )
{
value = s.minimumSize;
}
double scaleFactor = ( ( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) );
return value * scaleFactor;
}
QString QgsStackedBarDiagram::diagramName() const
{
return DIAGRAM_NAME_STACKED;
}
QSizeF QgsStackedBarDiagram::diagramSize( const QgsAttributes &attributes, const QgsRenderContext &c, const QgsDiagramSettings &s )
{
Q_UNUSED( c )
QSizeF size;
if ( attributes.isEmpty() )
{
return QSizeF(); //zero size if no attributes
}
double totalSum = 0;
for ( int i = 0; i < attributes.count(); ++i )
{
totalSum += attributes.at( i ).toDouble();
}
// eh - this method returns size in unknown units ...! We'll have to fake it and use a rough estimation of
// a conversion factor to painter units...
// TODO QGIS 4.0 -- these methods should all use painter units, dependent on the render context scaling...
double painterUnitConversionScale = c.convertToPainterUnits( 1, s.sizeType );
const double spacing = c.convertToPainterUnits( s.spacing(), s.spacingUnit(), s.spacingMapUnitScale() ) / painterUnitConversionScale;
switch ( s.diagramOrientation )
{
case QgsDiagramSettings::Up:
case QgsDiagramSettings::Down:
size.scale( s.barWidth, s.size.height() + spacing * std::max( 0, s.categoryAttributes.size() - 1 ), Qt::IgnoreAspectRatio );
break;
case QgsDiagramSettings::Right:
case QgsDiagramSettings::Left:
size.scale( s.size.width() + spacing * std::max( 0, s.categoryAttributes.size() - 1 ), s.barWidth, Qt::IgnoreAspectRatio );
break;
}
return size;
}
void QgsStackedBarDiagram::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position )
{
QPainter *p = c.painter();
if ( !p )
{
return;
}
QList<double> values;
QgsExpressionContext expressionContext = c.expressionContext();
expressionContext.setFeature( feature );
if ( !feature.fields().isEmpty() )
expressionContext.setFields( feature.fields() );
values.reserve( s.categoryAttributes.size() );
double total = 0;
for ( const QString &cat : qgis::as_const( s.categoryAttributes ) )
{
QgsExpression *expression = getExpression( cat, expressionContext );
double currentVal = expression->evaluate( &expressionContext ).toDouble();
values.push_back( currentVal );
total += currentVal;
}
const double spacing = c.convertToPainterUnits( s.spacing(), s.spacingUnit(), s.spacingMapUnitScale() );
const double totalSpacing = std::max( 0, s.categoryAttributes.size() - 1 ) * spacing;
double scaledMaxVal = 0;
switch ( s.diagramOrientation )
{
case QgsDiagramSettings::Up:
case QgsDiagramSettings::Down:
scaledMaxVal = sizePainterUnits( s.size.height(), s, c );
break;
case QgsDiagramSettings::Right:
case QgsDiagramSettings::Left:
scaledMaxVal = sizePainterUnits( s.size.width(), s, c );
break;
}
if ( mApplySpacingAdjust )
scaledMaxVal -= totalSpacing;
double currentOffset = 0;
double scaledWidth = sizePainterUnits( s.barWidth, s, c );
double baseX = position.x();
double baseY = position.y();
mPen.setColor( s.penColor );
setPenWidth( mPen, s, c );
p->setPen( mPen );
QList<double>::const_iterator valIt = values.constBegin();
QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
{
double length = *valIt / total * scaledMaxVal;
mCategoryBrush.setColor( *colIt );
p->setBrush( mCategoryBrush );
switch ( s.diagramOrientation )
{
case QgsDiagramSettings::Up:
p->drawRect( QRectF( baseX, baseY - currentOffset, scaledWidth, length * -1 ) );
break;
case QgsDiagramSettings::Down:
p->drawRect( QRectF( baseX, baseY + currentOffset - scaledMaxVal - spacing * std::max( 0, values.size() - 1 ), scaledWidth, length ) );
break;
case QgsDiagramSettings::Right:
p->drawRect( QRectF( baseX + currentOffset, baseY - scaledWidth, length, scaledWidth ) );
break;
case QgsDiagramSettings::Left:
p->drawRect( QRectF( baseX + scaledMaxVal - currentOffset + spacing * std::max( 0, values.size() - 1 ), baseY - scaledWidth, 0 - length, scaledWidth ) );
break;
}
currentOffset += length + spacing;
}
}

View File

@ -0,0 +1,64 @@
/***************************************************************************
qgsstackedbardiagram.h
---------------------
begin : November 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSSTACKEDBARDIAGRAM_H
#define QGSSTACKEDBARDIAGRAM_H
#define DIAGRAM_NAME_STACKED "Stacked"
#include "qgis_core.h"
#include "qgis.h"
#include "qgsdiagram.h"
#include <QPen>
#include <QBrush>
class QgsFeature;
class QPainter;
class QPointF;
class QgsDiagramSettings;
class QgsDiagramInterpolationSettings;
class QgsRenderContext;
/**
* \ingroup core
* \class QgsStackedBarDiagram
*
* A stacked bar chart diagram.
*
* \since QGIS 3.12
*/
class CORE_EXPORT QgsStackedBarDiagram: public QgsDiagram
{
public:
QgsStackedBarDiagram();
QgsStackedBarDiagram *clone() const override SIP_FACTORY;
void renderDiagram( const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position ) override;
QSizeF diagramSize( const QgsAttributes &attributes, const QgsRenderContext &c, const QgsDiagramSettings &s ) override;
QSizeF diagramSize( const QgsFeature &feature, const QgsRenderContext &c, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) override;
double legendSize( double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) const override;
QString diagramName() const override;
private:
QBrush mCategoryBrush;
QPen mPen;
bool mApplySpacingAdjust = false;
};
#endif // QGSSTACKEDBARDIAGRAM_H

View File

@ -19,6 +19,7 @@
#include "diagram/qgstextdiagram.h"
#include "diagram/qgspiediagram.h"
#include "diagram/qgshistogramdiagram.h"
#include "diagram/qgsstackedbardiagram.h"
#include "qgsrendercontext.h"
#include "qgslayertreemodellegendnode.h"
#include "qgsfontutils.h"
@ -300,7 +301,7 @@ void QgsDiagramSettings::readXml( const QDomElement &elem, const QgsReadWriteCon
categoryColors.append( newColor );
categoryAttributes.append( attrElem.attribute( QStringLiteral( "field" ) ) );
categoryLabels.append( attrElem.attribute( QStringLiteral( "label" ) ) );
if ( categoryLabels.back().isEmpty() )
if ( categoryLabels.constLast().isEmpty() )
{
categoryLabels.back() = categoryAttributes.back();
}
@ -556,6 +557,10 @@ void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteCo
{
mDiagram.reset( new QgsHistogramDiagram() );
}
else if ( diagramType == QLatin1String( "Stacked" ) )
{
mDiagram.reset( new QgsStackedBarDiagram() );
}
else
{
// unknown diagram type -- default to histograms

View File

@ -621,7 +621,7 @@ class CORE_EXPORT QgsDiagramSettings
private:
double mSpacing = 0;
QgsUnitTypes::RenderUnit mSpacingUnit;
QgsUnitTypes::RenderUnit mSpacingUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mSpacingMapUnitScale;
Direction mDirection = Counterclockwise;

View File

@ -24,21 +24,22 @@
//qgis includes...
// #include <qgisapp.h>
#include <diagram/qgspiediagram.h>
#include <diagram/qgstextdiagram.h>
#include <qgsdiagramrenderer.h>
#include <qgsmaplayer.h>
#include <qgsvectordataprovider.h>
#include <qgsvectorlayer.h>
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgsrenderer.h>
#include "diagram/qgspiediagram.h"
#include "diagram/qgstextdiagram.h"
#include "diagram/qgsstackedbardiagram.h"
#include "diagram/qgshistogramdiagram.h"
#include "qgsdiagramrenderer.h"
#include "qgsmaplayer.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsapplication.h"
#include "qgsproviderregistry.h"
#include "qgsrenderer.h"
#include "qgssinglesymbolrenderer.h"
//qgis test includes
#include "qgsmultirenderchecker.h"
#include "qgspallabeling.h"
#include "qgsproject.h"
#include "diagram/qgshistogramdiagram.h"
/**
* \ingroup UnitTests
@ -349,6 +350,103 @@ class TestQgsDiagram : public QObject
}
void testStackedFixSize()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << QStringLiteral( "\"Pilots\"" ) << QStringLiteral( "\"Cabin Crew\"" );
ds.minimumScale = -1;
ds.maximumScale = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 15, 15 );
ds.rotationOffset = 0;
ds.diagramOrientation = QgsDiagramSettings::Up;
ds.setSpacing( 3 );
QgsSingleCategoryDiagramRenderer *dr = new QgsSingleCategoryDiagramRenderer();
dr->setDiagram( new QgsStackedBarDiagram() );
dr->setDiagramSettings( ds );
mPointsLayer->setDiagramRenderer( dr );
QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( true );
mPointsLayer->setDiagramLayerSettings( dls );
QVERIFY( imageCheck( "stacked_up" ) );
ds.diagramOrientation = QgsDiagramSettings::Right;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_right" ) );
ds.diagramOrientation = QgsDiagramSettings::Left;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_left" ) );
ds.diagramOrientation = QgsDiagramSettings::Down;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_down" ) );
}
void testStackedVaryingFixSize()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << QStringLiteral( "\"Pilots\"" ) << QStringLiteral( "\"Cabin Crew\"" );
ds.minimumScale = -1;
ds.maximumScale = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 5, 5 );
ds.rotationOffset = 0;
ds.diagramOrientation = QgsDiagramSettings::Up;
ds.setSpacing( 3 );
QgsLinearlyInterpolatedDiagramRenderer *dr = new QgsLinearlyInterpolatedDiagramRenderer();
dr->setLowerValue( 0.0 );
dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
dr->setUpperValue( 10 );
dr->setUpperSize( QSizeF( 40, 40 ) );
dr->setClassificationField( QStringLiteral( "Staff" ) );
dr->setDiagram( new QgsStackedBarDiagram() );
dr->setDiagramSettings( ds );
mPointsLayer->setDiagramRenderer( dr );
QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( true );
mPointsLayer->setDiagramLayerSettings( dls );
QVERIFY( imageCheck( "stacked_varying_up" ) );
ds.diagramOrientation = QgsDiagramSettings::Right;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_varying_right" ) );
ds.diagramOrientation = QgsDiagramSettings::Left;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_varying_left" ) );
ds.diagramOrientation = QgsDiagramSettings::Down;
dr->setDiagramSettings( ds );
QVERIFY( imageCheck( "stacked_varying_down" ) );
}
void testPieDiagramExpression()
{
QgsDiagramSettings ds;

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB