mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -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']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsAbstractPlotSeries.__virtual_methods__ = ['categories']
|
||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
||||
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
||||
@ -25,13 +20,16 @@ try:
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsXyPlotSeries.__overridden_methods__ = ['categories']
|
||||
QgsXyPlotSeries.__group__ = ['plot']
|
||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||
Qgs2DXyPlot.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||
Qgs2DXyPlot.__group__ = ['plot']
|
||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsXyPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
|
@ -58,7 +58,6 @@ class QgsAbstractPlotSeries
|
||||
void setName( const QString &name );
|
||||
QgsSymbol *symbol() const;
|
||||
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
||||
virtual QList<QVariant> categories() const;
|
||||
|
||||
private:
|
||||
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
||||
@ -75,10 +74,7 @@ class QgsXyPlotSeries : QgsAbstractPlotSeries
|
||||
QgsXyPlotSeries();
|
||||
~QgsXyPlotSeries();
|
||||
|
||||
virtual QList<QVariant> categories() const;
|
||||
|
||||
|
||||
void append( const QVariant &x, const double &y );
|
||||
void append( const double &x, const double &y );
|
||||
void clear();
|
||||
|
||||
private:
|
||||
@ -100,6 +96,9 @@ class QgsPlotData
|
||||
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
||||
void clearSeries();
|
||||
|
||||
QStringList categories() const;
|
||||
void setCategories( const QStringList &categories );
|
||||
|
||||
};
|
||||
|
||||
class QgsPlotAxis
|
||||
|
@ -13,11 +13,6 @@ try:
|
||||
QgsPlot.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsAbstractPlotSeries.__virtual_methods__ = ['categories']
|
||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
Qgs2DPlot.__virtual_methods__ = ['render', 'renderContent', 'interiorPlotArea']
|
||||
Qgs2DPlot.__overridden_methods__ = ['writeXml', 'readXml']
|
||||
@ -25,13 +20,16 @@ try:
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsXyPlotSeries.__overridden_methods__ = ['categories']
|
||||
QgsXyPlotSeries.__group__ = ['plot']
|
||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||
Qgs2DXyPlot.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
Qgs2DXyPlot.__overridden_methods__ = ['writeXml', 'readXml', 'render', 'interiorPlotArea']
|
||||
Qgs2DXyPlot.__group__ = ['plot']
|
||||
QgsAbstractPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsXyPlotSeries.__group__ = ['plot']
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
|
@ -58,7 +58,6 @@ class QgsAbstractPlotSeries
|
||||
void setName( const QString &name );
|
||||
QgsSymbol *symbol() const;
|
||||
void setSymbol( QgsSymbol *symbol /Transfer/ );
|
||||
virtual QList<QVariant> categories() const;
|
||||
|
||||
private:
|
||||
QgsAbstractPlotSeries( const QgsAbstractPlotSeries &other );
|
||||
@ -75,10 +74,7 @@ class QgsXyPlotSeries : QgsAbstractPlotSeries
|
||||
QgsXyPlotSeries();
|
||||
~QgsXyPlotSeries();
|
||||
|
||||
virtual QList<QVariant> categories() const;
|
||||
|
||||
|
||||
void append( const QVariant &x, const double &y );
|
||||
void append( const double &x, const double &y );
|
||||
void clear();
|
||||
|
||||
private:
|
||||
@ -100,6 +96,9 @@ class QgsPlotData
|
||||
void addSeries( QgsAbstractPlotSeries *series /Transfer/ );
|
||||
void clearSeries();
|
||||
|
||||
QStringList categories() const;
|
||||
void setCategories( const QStringList &categories );
|
||||
|
||||
};
|
||||
|
||||
class QgsPlotAxis
|
||||
|
@ -30,8 +30,8 @@ void QgsBarChart::renderContent( QgsRenderContext &context, const QRectF &plotAr
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<QVariant> categories = seriesList.at( 0 )->categories();
|
||||
if ( categories.isEmpty() )
|
||||
const QStringList categories = plotData.categories();
|
||||
if ( xAxis().type() == Qgis::PlotAxisType::ValueType && categories.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -60,17 +60,17 @@ void QgsBarChart::renderContent( QgsRenderContext &context, const QRectF &plotAr
|
||||
const double barStartAdjustement = -( barsWidth / 2 ) + barWidth * seriesIndex;
|
||||
if ( const QgsXyPlotSeries *xySeries = dynamic_cast<const QgsXyPlotSeries *>( series ) )
|
||||
{
|
||||
const QList<std::pair<QVariant, double>> data = xySeries->data();
|
||||
for ( const std::pair<QVariant, double> &pair : data )
|
||||
const QList<std::pair<double, double>> data = xySeries->data();
|
||||
for ( const std::pair<double, double> &pair : data )
|
||||
{
|
||||
double x, y;
|
||||
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 )
|
||||
{
|
||||
x = ( categoriesWidth * categories.indexOf( pair.first ) ) + ( categoriesWidth / 2 ) + barStartAdjustement;
|
||||
x = ( categoriesWidth * pair.first ) + ( categoriesWidth / 2 ) + barStartAdjustement;
|
||||
}
|
||||
y = ( pair.second - yMinimum() ) * yScale;
|
||||
|
||||
@ -100,8 +100,8 @@ void QgsLineChart::renderContent( QgsRenderContext &context, const QRectF &plotA
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<QVariant> categories = seriesList.at( 0 )->categories();
|
||||
if ( categories.isEmpty() )
|
||||
const QStringList categories = plotData.categories();
|
||||
if ( xAxis().type() == Qgis::PlotAxisType::ValueType && categories.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -127,26 +127,26 @@ void QgsLineChart::renderContent( QgsRenderContext &context, const QRectF &plotA
|
||||
|
||||
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;
|
||||
QList<double> values;
|
||||
points.fill( QPointF(), xAxis().type() == Qgis::PlotAxisType::ValueType ? data.size() : categories.size() );
|
||||
int dataIndex = 0;
|
||||
for ( const std::pair<QVariant, double> &pair : data )
|
||||
for ( const std::pair<double, double> &pair : data )
|
||||
{
|
||||
double x, y;
|
||||
if ( xAxis().type() == Qgis::PlotAxisType::ValueType )
|
||||
{
|
||||
x = ( pair.first.toDouble() ) * xScale;
|
||||
x = ( pair.first - xMinimum() ) * xScale;
|
||||
}
|
||||
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;
|
||||
|
||||
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 ) );
|
||||
dataIndex++;
|
||||
}
|
||||
|
@ -335,12 +335,7 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
||||
QgsNumericFormatContext numericContext;
|
||||
|
||||
// categories
|
||||
QList<QVariant> categories;
|
||||
const QList<QgsAbstractPlotSeries *> seriesList = plotData.series();
|
||||
if ( !seriesList.isEmpty() )
|
||||
{
|
||||
categories = seriesList.at( 0 )->categories();
|
||||
}
|
||||
const QStringList categories = plotData.categories();
|
||||
|
||||
// calculate text metrics
|
||||
double maxYAxisLabelWidth = 0;
|
||||
@ -386,8 +381,7 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
||||
{
|
||||
for ( int i = 0; i < categories.size(); i++ )
|
||||
{
|
||||
const QString text = categories.at( i ).toString();
|
||||
maxYAxisLabelWidth = std::max( maxYAxisLabelWidth, QgsTextRenderer::textWidth( context, mYAxis.textFormat(), { text } ) );
|
||||
maxYAxisLabelWidth = std::max( maxYAxisLabelWidth, QgsTextRenderer::textWidth( context, mYAxis.textFormat(), { categories.at( i ) } ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,9 +515,8 @@ void Qgs2DXyPlot::render( QgsRenderContext &context, const QgsPlotData &plotData
|
||||
{
|
||||
const double currentX = ( i * categoryWidth ) + categoryWidth / 2.0;
|
||||
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 ) ),
|
||||
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;
|
||||
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(), { text } );
|
||||
const double height = QgsTextRenderer::textHeight( context, mYAxis.textFormat(), { categories.at( i ) } );
|
||||
QgsTextRenderer::drawText( QPointF(
|
||||
maxYAxisLabelWidth + context.convertToPainterUnits( mMargins.left(), Qgis::RenderUnit::Millimeters ),
|
||||
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();
|
||||
}
|
||||
|
||||
QStringList QgsPlotData::categories() const
|
||||
{
|
||||
return mCategories;
|
||||
}
|
||||
|
||||
void QgsPlotData::setCategories( const QStringList &categories )
|
||||
{
|
||||
mCategories = categories;
|
||||
}
|
||||
|
||||
//
|
||||
// QgsAbstractPlotSeries
|
||||
//
|
||||
@ -971,31 +973,16 @@ void QgsAbstractPlotSeries::setSymbol( QgsSymbol *symbol )
|
||||
mSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
QList<QVariant> QgsAbstractPlotSeries::categories() const
|
||||
{
|
||||
return QList<QVariant>();
|
||||
}
|
||||
|
||||
//
|
||||
// QgsXyPlotSeries
|
||||
//
|
||||
|
||||
QList<QVariant> QgsXyPlotSeries::categories() 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
|
||||
QList<std::pair<double, double>> QgsXyPlotSeries::data() const
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -74,7 +74,6 @@ class CORE_EXPORT QgsAbstractPlotSeries
|
||||
void setName( const QString &name );
|
||||
QgsSymbol *symbol() const;
|
||||
void setSymbol( QgsSymbol *symbol SIP_TRANSFER );
|
||||
virtual QList<QVariant> categories() const;
|
||||
|
||||
private:
|
||||
#ifdef SIP_RUN
|
||||
@ -92,10 +91,8 @@ class CORE_EXPORT QgsXyPlotSeries : public QgsAbstractPlotSeries
|
||||
QgsXyPlotSeries() = default;
|
||||
~QgsXyPlotSeries() = default;
|
||||
|
||||
QList<QVariant> categories() const override;
|
||||
|
||||
QList<std::pair<QVariant, double>> data() const SIP_SKIP;
|
||||
void append( const QVariant &x, const double &y );
|
||||
QList<std::pair<double, double>> data() const SIP_SKIP;
|
||||
void append( const double &x, const double &y );
|
||||
void clear();
|
||||
|
||||
private:
|
||||
@ -103,7 +100,7 @@ class CORE_EXPORT QgsXyPlotSeries : public QgsAbstractPlotSeries
|
||||
QgsXyPlotSeries( const QgsXyPlotSeries &other );
|
||||
#endif
|
||||
|
||||
QList<std::pair<QVariant, double>> mData;
|
||||
QList<std::pair<double, double>> mData;
|
||||
};
|
||||
|
||||
class CORE_EXPORT QgsPlotData
|
||||
@ -117,9 +114,13 @@ class CORE_EXPORT QgsPlotData
|
||||
void addSeries( QgsAbstractPlotSeries *series SIP_TRANSFER );
|
||||
void clearSeries();
|
||||
|
||||
QStringList categories() const;
|
||||
void setCategories( const QStringList &categories );
|
||||
|
||||
private:
|
||||
|
||||
QList<QgsAbstractPlotSeries *> mSeries;
|
||||
QStringList mCategories;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user