28#include <QDomDocument>
33#include "moc_qgslayoutitemchart.cpp"
35using namespace Qt::StringLiterals;
45 mGathererTimer.setInterval( 10 );
46 mGathererTimer.setSingleShot(
true );
47 connect( &mGathererTimer, &QTimer::timeout,
this, &QgsLayoutItemChart::gatherData );
75 bool requireRefresh = !mPlot || !
plot;
78 if ( mPlot->type() !=
plot->type() )
80 requireRefresh =
true;
86 if ( oldPlot2dXy && newPlot2dXy && oldPlot2dXy->
xAxis().
type() == newPlot2dXy->
xAxis().
type() )
89 requireRefresh =
false;
93 requireRefresh =
true;
98 mPlot.reset( plot2d );
109 if ( layer == mVectorLayer.get() )
114 mVectorLayer.setLayer( layer );
123 if ( mSortFeatures == sorted )
128 mSortFeatures = sorted;
136 if ( mSortAscending == ascending )
141 mSortAscending = ascending;
149 if ( mSortExpression == expression )
154 mSortExpression = expression;
179 if ( !
mLayout || !painter || !painter->device() )
192 QPaintDevice *paintDevice = painter->device();
196 QRectF thisPaintRect = rect();
200 if (
mLayout->renderContext().isPreviewRender() )
202 if ( mNeedsGathering || mIsGathering )
204 if ( mNeedsGathering )
206 mNeedsGathering =
false;
211 painter->setClipRect( thisPaintRect );
213 painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
214 painter->drawRect( thisPaintRect );
215 painter->setBrush( Qt::NoBrush );
217 messageFont.setPointSize( 12 );
218 painter->setFont( messageFont );
219 painter->setPen( QColor( 255, 255, 255, 255 ) );
220 painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr(
"Rendering chart" ) );
226 if ( mNeedsGathering )
228 mNeedsGathering =
false;
233 mGatherer->waitForFinished( 60000 );
240 if ( size.width() == 0 || size.height() == 0 )
243 mPlot->setSize( size );
247 painter->scale( 1 / scaleFactor, 1 / scaleFactor );
254 mPlot->render( renderContext, plotRenderContext, mPlotData );
257 if ( mSeriesList.isEmpty() )
260 messageFont.setPointSize( 8 );
261 painter->setFont( messageFont );
262 painter->setPen( QColor( 125, 125, 125, 125 ) );
263 painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr(
"Missing chart data" ) );
270 if ( mVectorLayer && !mSeriesList.isEmpty() )
272 mNeedsGathering =
true;
276void QgsLayoutItemChart::refreshData()
278 mGathererTimer.start();
281void QgsLayoutItemChart::gatherData()
293void QgsLayoutItemChart::prepareGatherer()
302 if ( !mVectorLayer || !mPlot || mSeriesList.isEmpty() )
304 mPlotData.clearSeries();
305 mIsGathering =
false;
312 mPlotData.clearSeries();
313 mIsGathering =
false;
326 mPlotData.clearSeries();
327 mIsGathering =
false;
331 if ( QgsVectorLayerXyPlotDataGatherer *xyGatherer =
dynamic_cast<QgsVectorLayerXyPlotDataGatherer *
>( mGatherer.data() ) )
333 QList<QgsVectorLayerXyPlotDataGatherer::XySeriesDetails> xYSeriesList;
336 xYSeriesList << QgsVectorLayerXyPlotDataGatherer::XySeriesDetails( series.xExpression(), series.yExpression(), series.filterExpression() );
339 QgsFeatureRequest request;
340 for ( QgsLayoutItemChart::SeriesDetails &series : mSeriesList )
342 if ( series.filterExpression().isEmpty() )
344 request = QgsFeatureRequest();
351 if ( mSortFeatures && !mSortExpression.isEmpty() )
353 request.
addOrderBy( mSortExpression, mSortAscending );
356 QgsFeatureIterator featureIterator = mVectorLayer->getFeatures( request );
358 xyGatherer->setFeatureIterator( featureIterator );
360 xyGatherer->setSeriesDetails( xYSeriesList );
366void QgsLayoutItemChart::processData()
368 mPlotData = mGatherer->data();
371 mIsGathering =
false;
379 QDomElement plotElement = document.createElement( u
"plot"_s );
380 mPlot->writeXml( plotElement, document, context );
381 element.appendChild( plotElement );
384 QDomElement seriesListElement = document.createElement( u
"seriesList"_s );
387 QDomElement seriesElement = document.createElement( u
"series"_s );
388 seriesElement.setAttribute( u
"name"_s, series.name() );
389 seriesElement.setAttribute( u
"xExpression"_s, series.xExpression() );
390 seriesElement.setAttribute( u
"yExpression"_s, series.yExpression() );
391 seriesElement.setAttribute( u
"filterExpression"_s, series.filterExpression() );
392 seriesListElement.appendChild( seriesElement );
394 element.appendChild( seriesListElement );
398 element.setAttribute( u
"vectorLayer"_s, mVectorLayer.layerId );
399 element.setAttribute( u
"vectorLayerName"_s, mVectorLayer.name );
400 element.setAttribute( u
"vectorLayerSource"_s, mVectorLayer.source );
401 element.setAttribute( u
"vectorLayerProvider"_s, mVectorLayer.provider );
404 element.setAttribute( u
"sortFeatures"_s, mSortFeatures ? u
"1"_s : u
"0"_s );
405 element.setAttribute( u
"sortAscending"_s, mSortAscending ? u
"1"_s : u
"0"_s );
406 element.setAttribute( u
"sortExpression"_s, mSortExpression );
408 element.setAttribute( u
"sortExpression"_s, mSortExpression );
415 QDomElement plotElement = element.firstChildElement( u
"plot"_s );
416 if ( !plotElement.isNull() )
421 mPlot->readXml( plotElement, context );
426 const QDomNodeList seriesNodeList = element.firstChildElement( u
"seriesList"_s ).childNodes();
427 for (
int i = 0; i < seriesNodeList.count(); i++ )
429 const QDomElement seriesElement = seriesNodeList.at( i ).toElement();
431 series.
setXExpression( seriesElement.attribute(
"xExpression" ) );
432 series.
setYExpression( seriesElement.attribute(
"yExpression" ) );
434 mSeriesList << series;
437 QString layerId = element.attribute( u
"vectorLayer"_s );
438 QString layerName = element.attribute( u
"vectorLayerName"_s );
439 QString layerSource = element.attribute( u
"vectorLayerSource"_s );
440 QString layerProvider = element.attribute( u
"vectorLayerProvider"_s );
441 mVectorLayer =
QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
442 mVectorLayer.resolveWeakly(
mLayout->project() );
444 mSortFeatures = element.attribute( u
"sortFeatures"_s, u
"0"_s ).toInt();
445 mSortAscending = element.attribute( u
"sortAscending"_s, u
"1"_s ).toInt();
446 mSortExpression = element.attribute( u
"sortExpression"_s );
448 mNeedsGathering =
true;
Base class for 2-dimensional plot/chart/graphs.
Base class for 2-dimensional plot/chart/graphs with an X and Y axes.
QgsPlotAxis & xAxis()
Returns a reference to the plot's x axis.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
static QgsPlotRegistry * plotRegistry()
Returns the application's plot registry, used for plot types.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
Chart series details covering all supported series types.
void setFilterExpression(const QString &filterExpression)
Sets the filter expression used to generate a series against a subset of the source layer.
void setXExpression(const QString &xExpression)
Sets the expression used to generate X-axis values.
void setYExpression(const QString &yExpression)
Sets the expression used to generate Y-axis values.
QgsPlot * plot()
Returns the plot used to render the chart.
void setSortFeatures(bool sorted)
Sets whether features should be sorted when iterating through the vector layer from which the plot da...
int type() const override
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
static QgsLayoutItemChart * create(QgsLayout *layout)
Returns a new chart item for the specified layout.
void setSortAscending(bool ascending)
Sets whether features should be sorted in an ascending order when iterating through the vector layer ...
void setSeriesList(const QList< QgsLayoutItemChart::SeriesDetails > &seriesList)
Sets the plot series details used to generate the plot data.
void setSourceLayer(QgsVectorLayer *layer)
Sets the source vector layer from which the plot data will be gathered from.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
QgsLayoutItemChart(QgsLayout *layout)
Constructor for QgsLayoutItemChart, with the specified parent layout.
void setPlot(QgsPlot *plot)
Sets the plot used to render the chart.
QList< QgsLayoutItemChart::SeriesDetails > seriesList() const
Returns the plot series details used to generate the plot data.
void setSortExpression(const QString &expression)
Sets the expression used to sort features when iterating through the vector layer from which the plot...
QIcon icon() const override
Returns the item's icon.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
QgsLayoutItem(QgsLayout *layout, bool manageZValue=true)
Constructor for QgsLayoutItem, with the specified parent layout.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
QPointer< QgsLayout > mLayout
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static Q_DECL_DEPRECATED double scaleFactorFromItemStyle(const QStyleOptionGraphicsItem *style)
Extracts the scale factor from an item style.
Qgis::PlotAxisType type() const
Returns the axis type.
QgsPlotAbstractMetadata * plotMetadata(const QString &type) const
Returns the metadata for the specified plot type.
Contains information about the context of a plot rendering operation.
Base class for plot/chart/graphs.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Scoped object for saving and restoring a QPainter object's state.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
Represents a vector layer which manages a vector based dataset.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define QgsDebugError(str)
_LayerRef< QgsVectorLayer > QgsVectorLayerRef