mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Rework categories handling, move it into the QgsPlotData to increase logic robustness and simplicity
This commit is contained in:
parent
a0c45d9380
commit
b0a73b65e3
@ -13,11 +13,6 @@ try:
|
|||||||
QgsPlot.__group__ = ['plot']
|
QgsPlot.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
|
||||||
QgsAbstractPlotSeries.__virtual_methods__ = ['categories']
|
|
||||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
|
||||||
except (NameError, AttributeError):
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
||||||
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
||||||
@ -25,13 +20,16 @@ try:
|
|||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
QgsXyPlotSeries.__overridden_methods__ = ['categories']
|
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||||
QgsXyPlotSeries.__group__ = ['plot']
|
Qgs2DXyPlot.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||||
Qgs2DXyPlot.__group__ = ['plot']
|
except (NameError, AttributeError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
QgsXyPlotSeries.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
|
@ -58,7 +58,6 @@ class QgsAbstractPlotSeries
|
|||||||
void setName( const QString &name );
|
void setName( const QString &name );
|
||||||
QgsSymbol *symbol() const;
|
QgsSymbol *symbol() const;
|
||||||
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
||||||
virtual QList<QVariant> categories() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
||||||
@ -75,10 +74,7 @@ class QgsXyPlotSeries : QgsAbstractPlotSeries
|
|||||||
QgsXyPlotSeries();
|
QgsXyPlotSeries();
|
||||||
~QgsXyPlotSeries();
|
~QgsXyPlotSeries();
|
||||||
|
|
||||||
virtual QList<QVariant> categories() const;
|
void append( const double &x, const double &y );
|
||||||
|
|
||||||
|
|
||||||
void append( const QVariant &x, const double &y );
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -100,6 +96,9 @@ class QgsPlotData
|
|||||||
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
||||||
void clearSeries();
|
void clearSeries();
|
||||||
|
|
||||||
|
QStringList categories() const;
|
||||||
|
void setCategories( const QStringList &categories );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QgsPlotAxis
|
class QgsPlotAxis
|
||||||
|
@ -13,11 +13,6 @@ try:
|
|||||||
QgsPlot.__group__ = ['plot']
|
QgsPlot.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
|
||||||
QgsAbstractPlotSeries.__virtual_methods__ = ['categories']
|
|
||||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
|
||||||
except (NameError, AttributeError):
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
||||||
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
||||||
@ -25,13 +20,16 @@ try:
|
|||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
QgsXyPlotSeries.__overridden_methods__ = ['categories']
|
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||||
QgsXyPlotSeries.__group__ = ['plot']
|
Qgs2DXyPlot.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||||
Qgs2DXyPlot.__group__ = ['plot']
|
except (NameError, AttributeError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
QgsXyPlotSeries.__group__ = ['plot']
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
|
@ -58,7 +58,6 @@ class QgsAbstractPlotSeries
|
|||||||
void setName( const QString &name );
|
void setName( const QString &name );
|
||||||
QgsSymbol *symbol() const;
|
QgsSymbol *symbol() const;
|
||||||
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
||||||
virtual QList<QVariant> categories() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
||||||
@ -75,10 +74,7 @@ class QgsXyPlotSeries : QgsAbstractPlotSeries
|
|||||||
QgsXyPlotSeries();
|
QgsXyPlotSeries();
|
||||||
~QgsXyPlotSeries();
|
~QgsXyPlotSeries();
|
||||||
|
|
||||||
virtual QList<QVariant> categories() const;
|
void append( const double &x, const double &y );
|
||||||
|
|
||||||
|
|
||||||
void append( const QVariant &x, const double &y );
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -100,6 +96,9 @@ class QgsPlotData
|
|||||||
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
||||||
void clearSeries();
|
void clearSeries();
|
||||||
|
|
||||||
|
QStringList categories() const;
|
||||||
|
void setCategories( const QStringList &categories );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QgsPlotAxis
|
class QgsPlotAxis
|
||||||
|
@ -30,8 +30,8 @@ void QgsBarChart::renderContent( QgsRenderContext &context, const QRectF &plotAr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<QVariant> categories = seriesList.at( 0 )->categories();
|
const QStringList categories = plotData.categories();
|
||||||
if ( categories.isEmpty() )
|
if ( xAxis().type() == Qgis::PlotAxisType::ValueType && categories.isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -60,17 +60,17 @@ void QgsBarChart::renderContent( QgsRenderContext &context, const QRectF &plotAr
|
|||||||
const double barStartAdjustement = -( barsWidth / 2 ) + barWidth * seriesIndex;
|
const double barStartAdjustement = -( barsWidth / 2 ) + barWidth * seriesIndex;
|
||||||
if ( const QgsXyPlotSeries *xySeries = dynamic_cast<const QgsXyPlotSeries *>( series ) )
|
if ( const QgsXyPlotSeries *xySeries = dynamic_cast<const QgsXyPlotSeries *>( series ) )
|
||||||
{
|
{
|
||||||
const QList<std::pair<QVariant, double>> data = xySeries->data();
|
const QList<std::pair<double, double>> data = xySeries->data();
|
||||||
for ( const std::pair<QVariant, double> &pair : data )
|
for ( const std::pair<double, double> &pair : data )
|
||||||
{
|
{
|
||||||
double x, y;
|
double x, y;
|
||||||
if ( xAxis().type() == Qgis::PlotAxisType::ValueType )
|
if ( xAxis().type() == Qgis::PlotAxisType::ValueType )
|
||||||
{
|
{
|
||||||
x = ( pair.first.toDouble() ) * xScale + barStartAdjustement;
|
x = ( pair.first - xMinimum() ) * xScale + barStartAdjustement;
|
||||||
}
|
}
|
||||||
else if ( xAxis().type() == Qgis::PlotAxisType::CategoryType )
|
else if ( xAxis().type() == Qgis::PlotAxisType::CategoryType )
|
||||||
{
|
{
|
||||||
x = ( categoriesWidth * categories.indexOf( pair.first ) ) + ( categoriesWidth / 2 ) + barStartAdjustement;
|
x = ( categoriesWidth * pair.first ) + ( categoriesWidth / 2 ) + barStartAdjustement;
|
||||||
}
|
}
|
||||||
y = ( pair.second - yMinimum() ) * yScale;
|
y = ( pair.second - yMinimum() ) * yScale;
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ void QgsLineChart::renderContent( QgsRenderContext &context, const QRectF &plotA
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<QVariant> categories = seriesList.at( 0 )->categories();
|
const QStringList categories = plotData.categories();
|
||||||
if ( categories.isEmpty() )
|
if ( xAxis().type() == Qgis::PlotAxisType::ValueType && categories.isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -127,26 +127,26 @@ void QgsLineChart::renderContent( QgsRenderContext &context, const QRectF &plotA
|
|||||||
|
|
||||||
if ( const QgsXyPlotSeries *xySeries = dynamic_cast<const QgsXyPlotSeries *>( series ) )
|
if ( const QgsXyPlotSeries *xySeries = dynamic_cast<const QgsXyPlotSeries *>( series ) )
|
||||||
{
|
{
|
||||||
const QList<std::pair<QVariant, double>> data = xySeries->data();
|
const QList<std::pair<double, double>> data = xySeries->data();
|
||||||
QVector<QPointF> points;
|
QVector<QPointF> points;
|
||||||
QList<double> values;
|
QList<double> values;
|
||||||
points.fill( QPointF(), xAxis().type() == Qgis::PlotAxisType::ValueType ? data.size() : categories.size() );
|
points.fill( QPointF(), xAxis().type() == Qgis::PlotAxisType::ValueType ? data.size() : categories.size() );
|
||||||
int dataIndex = 0;
|
int dataIndex = 0;
|
||||||
for ( const std::pair<QVariant, double> &pair : data )
|
for ( const std::pair<double, double> &pair : data )
|
||||||
{
|
{
|
||||||
double x, y;
|
double x, y;
|
||||||
if ( xAxis().type() == Qgis::PlotAxisType::ValueType )
|
if ( xAxis().type() == Qgis::PlotAxisType::ValueType )
|
||||||
{
|
{
|
||||||
x = ( pair.first.toDouble() ) * xScale;
|
x = ( pair.first - xMinimum() ) * xScale;
|
||||||
}
|
}
|
||||||
else if ( xAxis().type() == Qgis::PlotAxisType::CategoryType )
|
else if ( xAxis().type() == Qgis::PlotAxisType::CategoryType )
|
||||||
{
|
{
|
||||||
x = ( categoriesWidth * categories.indexOf( pair.first ) ) + ( categoriesWidth / 2 );
|
x = ( categoriesWidth * pair.first ) + ( categoriesWidth / 2 );
|
||||||
}
|
}
|
||||||
y = ( pair.second - yMinimum() ) * yScale;
|
y = ( pair.second - yMinimum() ) * yScale;
|
||||||
|
|
||||||
values << pair.second;
|
values << pair.second;
|
||||||
points.replace( xAxis().type() == Qgis::PlotAxisType::ValueType ? dataIndex : categories.indexOf( pair.first ), QPointF( plotArea.x() + x,
|
points.replace( xAxis().type() == Qgis::PlotAxisType::ValueType ? dataIndex : pair.first, QPointF( plotArea.x() + x,
|
||||||
plotArea.y() + plotArea.height() - y ) );
|
plotArea.y() + plotArea.height() - y ) );
|
||||||
dataIndex++;
|
dataIndex++;
|
||||||
}
|
}
|
||||||
|
@ -335,12 +335,7 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
|||||||
QgsNumericFormatContext numericContext;
|
QgsNumericFormatContext numericContext;
|
||||||
|
|
||||||
// categories
|
// categories
|
||||||
QList<QVariant> categories;
|
const QStringList categories = plotData.categories();
|
||||||
const QList<QgsAbstractPlotSeries *> seriesList = plotData.series();
|
|
||||||
if ( !seriesList.isEmpty() )
|
|
||||||
{
|
|
||||||
categories = seriesList.at( 0 )->categories();
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate text metrics
|
// calculate text metrics
|
||||||
double maxYAxisLabelWidth = 0;
|
double maxYAxisLabelWidth = 0;
|
||||||
@ -386,8 +381,7 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
|||||||
{
|
{
|
||||||
for ( int i = 0; i < categories.size(); i++ )
|
for ( int i = 0; i < categories.size(); i++ )
|
||||||
{
|
{
|
||||||
const QString text = categories.at( i ).toString();
|
maxYAxisLabelWidth = std::max( maxYAxisLabelWidth, QgsTextRenderer::textWidth( context, mYAxis.textFormat(), { categories.at( i ) } ) );
|
||||||
maxYAxisLabelWidth = std::max( maxYAxisLabelWidth, QgsTextRenderer::textWidth( context, mYAxis.textFormat(), { text } ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,9 +515,8 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
|||||||
{
|
{
|
||||||
const double currentX = ( i * categoryWidth ) + categoryWidth / 2.0;
|
const double currentX = ( i * categoryWidth ) + categoryWidth / 2.0;
|
||||||
plotScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "plot_axis_value" ), categories.at( i ), true ) );
|
plotScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "plot_axis_value" ), categories.at( i ), true ) );
|
||||||
const QString text = categories.at( i ).toString();
|
|
||||||
QgsTextRenderer::drawText( QPointF( currentX + chartAreaLeft, mSize.height() - context.convertToPainterUnits( mMargins.bottom(), Qgis::RenderUnit::Millimeters ) ),
|
QgsTextRenderer::drawText( QPointF( currentX + chartAreaLeft, mSize.height() - context.convertToPainterUnits( mMargins.bottom(), Qgis::RenderUnit::Millimeters ) ),
|
||||||
0, Qgis::TextHorizontalAlignment::Center, { text }, context, mXAxis.textFormat() );
|
0, Qgis::TextHorizontalAlignment::Center, { categories.at( i ) }, context, mXAxis.textFormat() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,12 +575,11 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
|||||||
{
|
{
|
||||||
const double currentY = ( i * categoryHeight ) + categoryHeight / 2.0;
|
const double currentY = ( i * categoryHeight ) + categoryHeight / 2.0;
|
||||||
plotScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "plot_axis_value" ), categories.at( i ), true ) );
|
plotScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "plot_axis_value" ), categories.at( i ), true ) );
|
||||||
const QString text = categories.at( i ).toString();
|
const double height = QgsTextRenderer::textHeight( context, mYAxis.textFormat(), { categories.at( i ) } );
|
||||||
const double height = QgsTextRenderer::textHeight( context, mYAxis.textFormat(), { text } );
|
|
||||||
QgsTextRenderer::drawText( QPointF(
|
QgsTextRenderer::drawText( QPointF(
|
||||||
maxYAxisLabelWidth + context.convertToPainterUnits( mMargins.left(), Qgis::RenderUnit::Millimeters ),
|
maxYAxisLabelWidth + context.convertToPainterUnits( mMargins.left(), Qgis::RenderUnit::Millimeters ),
|
||||||
chartAreaBottom - currentY + height / 2 ),
|
chartAreaBottom - currentY + height / 2 ),
|
||||||
0, Qgis::TextHorizontalAlignment::Right, { text }, context, mYAxis.textFormat(), false );
|
0, Qgis::TextHorizontalAlignment::Right, { categories.at( i ) }, context, mYAxis.textFormat(), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,6 +939,16 @@ void QgsPlotData::clearSeries()
|
|||||||
mSeries.clear();
|
mSeries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QgsPlotData::categories() const
|
||||||
|
{
|
||||||
|
return mCategories;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsPlotData::setCategories( const QStringList &categories )
|
||||||
|
{
|
||||||
|
mCategories = categories;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// QgsAbstractPlotSeries
|
// QgsAbstractPlotSeries
|
||||||
//
|
//
|
||||||
@ -971,31 +973,16 @@ void QgsAbstractPlotSeries::setSymbol( QgsSymbol *symbol )
|
|||||||
mSymbol.reset( symbol );
|
mSymbol.reset( symbol );
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QVariant> QgsAbstractPlotSeries::categories() const
|
|
||||||
{
|
|
||||||
return QList<QVariant>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// QgsXyPlotSeries
|
// QgsXyPlotSeries
|
||||||
//
|
//
|
||||||
|
|
||||||
QList<QVariant> QgsXyPlotSeries::categories() const
|
QList<std::pair<double, double>> QgsXyPlotSeries::data() const
|
||||||
{
|
|
||||||
QList<QVariant> categories;
|
|
||||||
for ( const std::pair<QVariant, double> &pair : std::as_const( mData ) )
|
|
||||||
{
|
|
||||||
categories << pair.first;
|
|
||||||
}
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<std::pair<QVariant, double>> QgsXyPlotSeries::data() const
|
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsXyPlotSeries::append( const QVariant &x, const double &y )
|
void QgsXyPlotSeries::append( const double &x, const double &y )
|
||||||
{
|
{
|
||||||
mData << std::make_pair( x, y );
|
mData << std::make_pair( x, y );
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,6 @@ class CORE_EXPORT QgsAbstractPlotSeries
|
|||||||
void setName( const QString &name );
|
void setName( const QString &name );
|
||||||
QgsSymbol *symbol() const;
|
QgsSymbol *symbol() const;
|
||||||
void setSymbol( QgsSymbol *symbol SIP_TRANSFER );
|
void setSymbol( QgsSymbol *symbol SIP_TRANSFER );
|
||||||
virtual QList<QVariant> categories() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef SIP_RUN
|
#ifdef SIP_RUN
|
||||||
@ -92,10 +91,8 @@ class CORE_EXPORT QgsXyPlotSeries : public QgsAbstractPlotSeries
|
|||||||
QgsXyPlotSeries() = default;
|
QgsXyPlotSeries() = default;
|
||||||
~QgsXyPlotSeries() = default;
|
~QgsXyPlotSeries() = default;
|
||||||
|
|
||||||
QList<QVariant> categories() const override;
|
QList<std::pair<double, double>> data() const SIP_SKIP;
|
||||||
|
void append( const double &x, const double &y );
|
||||||
QList<std::pair<QVariant, double>> data() const SIP_SKIP;
|
|
||||||
void append( const QVariant &x, const double &y );
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -103,7 +100,7 @@ class CORE_EXPORT QgsXyPlotSeries : public QgsAbstractPlotSeries
|
|||||||
QgsXyPlotSeries( const QgsXyPlotSeries &other );
|
QgsXyPlotSeries( const QgsXyPlotSeries &other );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QList<std::pair<QVariant, double>> mData;
|
QList<std::pair<double, double>> mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CORE_EXPORT QgsPlotData
|
class CORE_EXPORT QgsPlotData
|
||||||
@ -117,9 +114,13 @@ class CORE_EXPORT QgsPlotData
|
|||||||
void addSeries( QgsAbstractPlotSeries *series SIP_TRANSFER );
|
void addSeries( QgsAbstractPlotSeries *series SIP_TRANSFER );
|
||||||
void clearSeries();
|
void clearSeries();
|
||||||
|
|
||||||
|
QStringList categories() const;
|
||||||
|
void setCategories( const QStringList &categories );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QList<QgsAbstractPlotSeries *> mSeries;
|
QList<QgsAbstractPlotSeries *> mSeries;
|
||||||
|
QStringList mCategories;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user