28#include <QDomDocument>
32#include "moc_qgslayoutitemchart.cpp"
42 mGathererTimer.setInterval( 10 );
43 mGathererTimer.setSingleShot(
true );
44 connect( &mGathererTimer, &QTimer::timeout,
this, &QgsLayoutItemChart::gatherData );
72 bool requireRefresh = !mPlot || !
plot;
75 if ( mPlot->type() !=
plot->type() )
77 requireRefresh =
true;
83 if ( oldPlot2dXy && newPlot2dXy && oldPlot2dXy->
xAxis().
type() == newPlot2dXy->
xAxis().
type() )
86 requireRefresh =
false;
90 requireRefresh =
true;
95 mPlot.reset( plot2d );
106 if ( layer == mVectorLayer.get() )
111 mVectorLayer.setLayer( layer );
120 if ( mSortFeatures == sorted )
125 mSortFeatures = sorted;
133 if ( mSortAscending == ascending )
138 mSortAscending = ascending;
146 if ( mSortExpression == expression )
151 mSortExpression = expression;
176 if ( !
mLayout || !painter || !painter->device() )
189 QPaintDevice *paintDevice = painter->device();
193 QRectF thisPaintRect = rect();
197 if (
mLayout->renderContext().isPreviewRender() )
199 if ( mNeedsGathering || mIsGathering )
201 if ( mNeedsGathering )
203 mNeedsGathering =
false;
208 painter->setClipRect( thisPaintRect );
210 painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
211 painter->drawRect( thisPaintRect );
212 painter->setBrush( Qt::NoBrush );
214 messageFont.setPointSize( 12 );
215 painter->setFont( messageFont );
216 painter->setPen( QColor( 255, 255, 255, 255 ) );
217 painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr(
"Rendering chart" ) );
223 if ( mNeedsGathering )
225 mNeedsGathering =
false;
230 mGatherer->waitForFinished( 60000 );
237 if ( size.width() == 0 || size.height() == 0 )
240 mPlot->setSize( size );
244 painter->scale( 1 / scaleFactor, 1 / scaleFactor );
251 mPlot->render( renderContext, plotRenderContext, mPlotData );
254 if ( mSeriesList.isEmpty() )
257 messageFont.setPointSize( 8 );
258 painter->setFont( messageFont );
259 painter->setPen( QColor( 125, 125, 125, 125 ) );
260 painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr(
"Missing chart data" ) );
267 if ( mVectorLayer && !mSeriesList.isEmpty() )
269 mNeedsGathering =
true;
273void QgsLayoutItemChart::refreshData()
275 mGathererTimer.start();
278void QgsLayoutItemChart::gatherData()
290void QgsLayoutItemChart::prepareGatherer()
299 if ( !mVectorLayer || !mPlot || mSeriesList.isEmpty() )
301 mPlotData.clearSeries();
302 mIsGathering =
false;
309 mPlotData.clearSeries();
310 mIsGathering =
false;
323 mPlotData.clearSeries();
324 mIsGathering =
false;
328 if ( QgsVectorLayerXyPlotDataGatherer *xyGatherer =
dynamic_cast<QgsVectorLayerXyPlotDataGatherer *
>( mGatherer.data() ) )
330 QList<QgsVectorLayerXyPlotDataGatherer::XySeriesDetails> xYSeriesList;
333 xYSeriesList << QgsVectorLayerXyPlotDataGatherer::XySeriesDetails( series.xExpression(), series.yExpression(), series.filterExpression() );
336 QgsFeatureRequest request;
337 for ( QgsLayoutItemChart::SeriesDetails &series : mSeriesList )
339 if ( series.filterExpression().isEmpty() )
341 request = QgsFeatureRequest();
348 if ( mSortFeatures && !mSortExpression.isEmpty() )
350 request.
addOrderBy( mSortExpression, mSortAscending );
353 QgsFeatureIterator featureIterator = mVectorLayer->getFeatures( request );
355 xyGatherer->setFeatureIterator( featureIterator );
357 xyGatherer->setSeriesDetails( xYSeriesList );
363void QgsLayoutItemChart::processData()
365 mPlotData = mGatherer->data();
368 mIsGathering =
false;
376 QDomElement plotElement = document.createElement( QStringLiteral(
"plot" ) );
377 mPlot->writeXml( plotElement, document, context );
378 element.appendChild( plotElement );
381 QDomElement seriesListElement = document.createElement( QStringLiteral(
"seriesList" ) );
384 QDomElement seriesElement = document.createElement( QStringLiteral(
"series" ) );
385 seriesElement.setAttribute( QStringLiteral(
"name" ), series.name() );
386 seriesElement.setAttribute( QStringLiteral(
"xExpression" ), series.xExpression() );
387 seriesElement.setAttribute( QStringLiteral(
"yExpression" ), series.yExpression() );
388 seriesElement.setAttribute( QStringLiteral(
"filterExpression" ), series.filterExpression() );
389 seriesListElement.appendChild( seriesElement );
391 element.appendChild( seriesListElement );
395 element.setAttribute( QStringLiteral(
"vectorLayer" ), mVectorLayer.layerId );
396 element.setAttribute( QStringLiteral(
"vectorLayerName" ), mVectorLayer.name );
397 element.setAttribute( QStringLiteral(
"vectorLayerSource" ), mVectorLayer.source );
398 element.setAttribute( QStringLiteral(
"vectorLayerProvider" ), mVectorLayer.provider );
401 element.setAttribute( QStringLiteral(
"sortFeatures" ), mSortFeatures ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
402 element.setAttribute( QStringLiteral(
"sortAscending" ), mSortAscending ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
403 element.setAttribute( QStringLiteral(
"sortExpression" ), mSortExpression );
405 element.setAttribute( QStringLiteral(
"sortExpression" ), mSortExpression );
412 QDomElement plotElement = element.firstChildElement( QStringLiteral(
"plot" ) );
413 if ( !plotElement.isNull() )
418 mPlot->readXml( plotElement, context );
423 const QDomNodeList seriesNodeList = element.firstChildElement( QStringLiteral(
"seriesList" ) ).childNodes();
424 for (
int i = 0; i < seriesNodeList.count(); i++ )
426 const QDomElement seriesElement = seriesNodeList.at( i ).toElement();
428 series.
setXExpression( seriesElement.attribute(
"xExpression" ) );
429 series.
setYExpression( seriesElement.attribute(
"yExpression" ) );
431 mSeriesList << series;
434 QString layerId = element.attribute( QStringLiteral(
"vectorLayer" ) );
435 QString layerName = element.attribute( QStringLiteral(
"vectorLayerName" ) );
436 QString layerSource = element.attribute( QStringLiteral(
"vectorLayerSource" ) );
437 QString layerProvider = element.attribute( QStringLiteral(
"vectorLayerProvider" ) );
438 mVectorLayer =
QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
439 mVectorLayer.resolveWeakly(
mLayout->project() );
441 mSortFeatures = element.attribute( QStringLiteral(
"sortFeatures" ), QStringLiteral(
"0" ) ).toInt();
442 mSortAscending = element.attribute( QStringLiteral(
"sortAscending" ), QStringLiteral(
"1" ) ).toInt();
443 mSortExpression = element.attribute( QStringLiteral(
"sortExpression" ) );
445 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