#include "KChartEnums.h"
/**
* @brief base class for prerendered elements like labels, pixmaps, markers, etc.
*/
class PrerenderedElement {
public:
PrerenderedElement();
virtual ~PrerenderedElement() {}
/** Returns the rendered element.
If any of the properties have change, the element will be
regenerated. */
virtual const QPixmap& pixmap() const = 0;
/** Return the location of the reference point relatively to the
pixmap's origin. */
virtual QPointF referencePointLocation( KChartEnums::PositionValue ) const = 0;
/** Set the position of the element. */
void setPosition( const QPointF& position );
/** Get the position of the element. */
const QPointF& position() const;
/** Set the reference point of the element.
Every element has nine possible reference points (all compass
directions, plus the center.
*/
void setReferencePoint( KChartEnums::PositionValue );
/** Get the reference point of the element. */
KChartEnums::PositionValue referencePoint() const;
protected:
/** invalidate() needs to be called if any of the properties that
determine the visual appearance of the prerendered element
change.
It can be called for a const object, as objects may need to
force recalculation of the pixmap.
*/
virtual void invalidate() const = 0;
private:
QPointF m_position;
KChartEnums::PositionValue m_referencePoint;
};
-/**
+/**
@brief PrerenderedLabel is an internal KChart class that simplifies creation
and caching of cached text labels.
-
+
It provides referenze points to anchor the text to other
elements. Reference points use the positions defined in
KChartEnums.
Usage:
qreal angle = 90.0;
CachedLabel label;
label.paint( font, tr("Label"), angle );
*/
// FIXME this is merely a prototype
// FIXME caching could be done by a second layer that can be used to,
// e.g., query for a prerendered element by id or name, or by changing
// the pixmap() method to do lazy evaluation.
class PrerenderedLabel : public PrerenderedElement
{
public:
PrerenderedLabel();
~PrerenderedLabel();
+
+ /**
+ * Sets the label's font to \a font.
+ */
void setFont( const QFont& font );
+
+ /**
+ * @return the label's font.
+ */
const QFont& font() const;
+
+ /**
+ * Sets the label's text to \a text
+ */
void setText( const QString& text );
+
+ /**
+ * @return the label's text
+ */
const QString& text() const;
+
+ /**
+ * Sets the label's brush to \a brush
+ */
void setBrush( const QBrush& brush );
+
+ /**
+ * @return the label's brush
+ */
const QBrush& brush() const;
void setPen( const QPen& );
const QPen& pen() const;
+
+ /**
+ * Sets the angle of the label to \a angle degrees
+ */
void setAngle( qreal angle );
+
+ /**
+ * @return the label's angle in degrees
+ */
qreal angle() const;
// reimpl PrerenderedElement:
const QPixmap& pixmap() const override;
QPointF referencePointLocation( KChartEnums::PositionValue position ) const override;
// overload: return location of referencePoint():
QPointF referencePointLocation() const;
protected:
+
+ /**
+ * Invalidates the preredendered data, forces re-rendering.
+ */
void invalidate() const override;
private:
/** Create a label with the given text and the given rotation
angle. Needs to be const, otherwise the pixmap() method cannot
update when needed. */
void paint() const;
// store the settings (these are used for the painting):
mutable bool m_dirty;
QFont m_font;
QString m_text;
QBrush m_brush;
QPen m_pen;
qreal m_angle;
// these are valid once the label has been rendered:
mutable QPixmap m_pixmap;
mutable QPointF m_referenceBottomLeft;
mutable QPointF m_textBaseLineVector;
mutable QPointF m_textAscendVector;
};
#endif
diff --git a/src/KChart/KChartWidget.cpp b/src/KChart/KChartWidget.cpp
index 6bd11cd..c1e7d48 100644
--- a/src/KChart/KChartWidget.cpp
+++ b/src/KChart/KChartWidget.cpp
@@ -1,625 +1,551 @@
/*
* Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
*
* This file is part of the KD Chart library.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "KChartMath_p.h"
#include
#define d d_func()
using namespace KChart;
Widget::Private::Private( Widget * qq )
: q( qq ),
layout( q ),
m_model( q ),
m_chart( q ),
m_cartPlane( &m_chart ),
m_polPlane( &m_chart ),
usedDatasetWidth( 0 )
{
KDAB_SET_OBJECT_NAME( layout );
KDAB_SET_OBJECT_NAME( m_model );
KDAB_SET_OBJECT_NAME( m_chart );
layout.addWidget( &m_chart );
}
Widget::Private::~Private() {}
-/**
-* \class Widget KChartWidget.h
-* \brief The KChart widget for usage without Interwiev.
-*
-* If you want to use KChart with Interview, use KChart::Chart instead.
-*/
-
-/**
- * Constructor. Creates a new widget with all data initialized empty.
- *
- * \param parent the widget parent; passed on to QWidget
- */
+
Widget::Widget( QWidget* parent ) :
QWidget(parent), _d( new Private( this ) )
{
// as default we have a cartesian coordinate plane ...
// ... and a line diagram
setType( Line );
}
-/**
- * Destructor.
- */
Widget::~Widget()
{
delete _d; _d = nullptr;
}
void Widget::init()
{
}
void Widget::setDataset( int column, const QVector< qreal > & data, const QString& title )
{
if ( ! checkDatasetWidth( 1 ) )
return;
QStandardItemModel & model = d->m_model;
justifyModelSize( data.size(), column + 1 );
for ( int i = 0; i < data.size(); ++i )
{
const QModelIndex index = model.index( i, column );
model.setData( index, QVariant( data[i] ), Qt::DisplayRole );
}
if ( ! title.isEmpty() )
model.setHeaderData( column, Qt::Horizontal, QVariant( title ) );
}
void Widget::setDataset( int column, const QVector< QPair< qreal, qreal > > & data, const QString& title )
{
if ( ! checkDatasetWidth( 2 ))
return;
QStandardItemModel & model = d->m_model;
justifyModelSize( data.size(), (column + 1) * 2 );
for ( int i = 0; i < data.size(); ++i )
{
QModelIndex index = model.index( i, column * 2 );
model.setData( index, QVariant( data[i].first ), Qt::DisplayRole );
index = model.index( i, column * 2 + 1 );
model.setData( index, QVariant( data[i].second ), Qt::DisplayRole );
}
if ( ! title.isEmpty() ) {
model.setHeaderData( column, Qt::Horizontal, QVariant( title ) );
}
}
void Widget::setDataCell( int row, int column, qreal data )
{
if ( ! checkDatasetWidth( 1 ) )
return;
QStandardItemModel & model = d->m_model;
justifyModelSize( row + 1, column + 1 );
const QModelIndex index = model.index( row, column );
model.setData( index, QVariant( data ), Qt::DisplayRole );
}
void Widget::setDataCell( int row, int column, QPair< qreal, qreal > data )
{
if ( ! checkDatasetWidth( 2 ))
return;
QStandardItemModel & model = d->m_model;
justifyModelSize( row + 1, (column + 1) * 2 );
QModelIndex index = model.index( row, column * 2 );
model.setData( index, QVariant( data.first ), Qt::DisplayRole );
index = model.index( row, column * 2 + 1 );
model.setData( index, QVariant( data.second ), Qt::DisplayRole );
}
/*
* Resets all data.
*/
void Widget::resetData()
{
d->m_model.clear();
d->usedDatasetWidth = 0;
}
-/**
- * Sets all global leadings (borders).
- */
void Widget::setGlobalLeading( int left, int top, int right, int bottom )
{
d->m_chart.setGlobalLeading( left, top, right, bottom );
}
-/**
- * Sets the left leading (border).
- */
void Widget::setGlobalLeadingLeft( int leading )
{
d->m_chart.setGlobalLeadingLeft( leading );
}
-/**
- * Returns the left leading (border).
- */
int Widget::globalLeadingLeft() const
{
return d->m_chart.globalLeadingLeft();
}
-/**
- * Sets the top leading (border).
- */
void Widget::setGlobalLeadingTop( int leading )
{
d->m_chart.setGlobalLeadingTop( leading );
}
-/**
- * Returns the top leading (border).
- */
int Widget::globalLeadingTop() const
{
return d->m_chart.globalLeadingTop();
}
-/**
- * Sets the right leading (border).
- */
void Widget::setGlobalLeadingRight( int leading )
{
d->m_chart.setGlobalLeadingRight( leading );
}
-/**
- * Returns the right leading (border).
- */
int Widget::globalLeadingRight() const
{
return d->m_chart.globalLeadingRight();
}
-/**
- * Sets the bottom leading (border).
- */
void Widget::setGlobalLeadingBottom( int leading )
{
d->m_chart.setGlobalLeadingBottom( leading );
}
-/**
- * Returns the bottom leading (border).
- */
int Widget::globalLeadingBottom() const
{
return d->m_chart.globalLeadingBottom();
}
-/**
- * Returns the first of all headers.
- */
KChart::HeaderFooter* Widget::firstHeaderFooter()
{
return d->m_chart.headerFooter();
}
-/**
- * Returns a list with all headers.
- */
QList Widget::allHeadersFooters()
{
return d->m_chart.headerFooters();
}
-/**
- * Adds a new header/footer with the given text to the position.
- */
void Widget::addHeaderFooter( const QString& text,
HeaderFooter::HeaderFooterType type,
Position position)
{
HeaderFooter* newHeader = new HeaderFooter( &d->m_chart );
newHeader->setType( type );
newHeader->setPosition( position );
newHeader->setText( text );
d->m_chart.addHeaderFooter( newHeader ); // we need this explicit call !
}
-/**
- * Adds an existing header / footer object.
- */
void Widget::addHeaderFooter( HeaderFooter* header )
{
header->setParent( &d->m_chart );
d->m_chart.addHeaderFooter( header ); // we need this explicit call !
}
void Widget::replaceHeaderFooter( HeaderFooter* header, HeaderFooter* oldHeader )
{
header->setParent( &d->m_chart );
d->m_chart.replaceHeaderFooter( header, oldHeader );
}
void Widget::takeHeaderFooter( HeaderFooter* header )
{
d->m_chart.takeHeaderFooter( header );
}
-/**
- * Returns the first of all legends.
- */
KChart::Legend* Widget::legend()
{
return d->m_chart.legend();
}
-/**
- * Returns a list with all legends.
- */
QList Widget::allLegends()
{
return d->m_chart.legends();
}
-/**
- * Adds an empty legend on the given position.
- */
void Widget::addLegend( Position position )
{
Legend* legend = new Legend( diagram(), &d->m_chart );
legend->setPosition( position );
d->m_chart.addLegend( legend );
}
-/**
- * Adds a new, already existing, legend.
- */
void Widget::addLegend( Legend* legend )
{
legend->setDiagram( diagram() );
legend->setParent( &d->m_chart );
d->m_chart.addLegend( legend );
}
void Widget::replaceLegend( Legend* legend, Legend* oldLegend )
{
legend->setDiagram( diagram() );
legend->setParent( &d->m_chart );
d->m_chart.replaceLegend( legend, oldLegend );
}
void Widget::takeLegend( Legend* legend )
{
d->m_chart.takeLegend( legend );
}
AbstractDiagram* Widget::diagram()
{
if ( coordinatePlane() == nullptr )
qDebug() << "diagram(): coordinatePlane() was NULL";
return coordinatePlane()->diagram();
}
BarDiagram* Widget::barDiagram()
{
return dynamic_cast( diagram() );
}
LineDiagram* Widget::lineDiagram()
{
return dynamic_cast( diagram() );
}
Plotter* Widget::plotter()
{
return dynamic_cast( diagram() );
}
PieDiagram* Widget::pieDiagram()
{
return dynamic_cast( diagram() );
}
RingDiagram* Widget::ringDiagram()
{
return dynamic_cast( diagram() );
}
PolarDiagram* Widget::polarDiagram()
{
return dynamic_cast( diagram() );
}
AbstractCoordinatePlane* Widget::coordinatePlane()
{
return d->m_chart.coordinatePlane();
}
static bool isCartesian( KChart::Widget::ChartType type )
{
return (type == KChart::Widget::Bar) || (type == KChart::Widget::Line);
}
static bool isPolar( KChart::Widget::ChartType type )
{
return (type == KChart::Widget::Pie)
|| (type == KChart::Widget::Ring)
|| (type == KChart::Widget::Polar);
}
void Widget::setType( ChartType chartType, SubType chartSubType )
{
AbstractDiagram* diag = nullptr;
const ChartType oldType = type();
if ( chartType != oldType ) {
if ( chartType != NoType ) {
if ( isCartesian( chartType ) && ! isCartesian( oldType ) )
{
if ( coordinatePlane() == &d->m_polPlane ) {
d->m_chart.takeCoordinatePlane( &d->m_polPlane );
d->m_chart.addCoordinatePlane( &d->m_cartPlane );
} else {
d->m_chart.replaceCoordinatePlane( &d->m_cartPlane );
}
}
else if ( isPolar( chartType ) && ! isPolar( oldType ) )
{
if ( coordinatePlane() == &d->m_cartPlane ) {
d->m_chart.takeCoordinatePlane( &d->m_cartPlane );
d->m_chart.addCoordinatePlane( &d->m_polPlane );
} else {
d->m_chart.replaceCoordinatePlane( &d->m_polPlane );
}
}
}
switch ( chartType ) {
case Bar:
diag = new BarDiagram( &d->m_chart, &d->m_cartPlane );
break;
case Line:
diag = new LineDiagram( &d->m_chart, &d->m_cartPlane );
break;
case Plot:
diag = new Plotter( &d->m_chart, &d->m_cartPlane );
break;
case Pie:
diag = new PieDiagram( &d->m_chart, &d->m_polPlane );
break;
case Polar:
diag = new PolarDiagram( &d->m_chart, &d->m_polPlane );
break;
case Ring:
diag = new RingDiagram( &d->m_chart, &d->m_polPlane );
break;
case NoType:
break;
}
if ( diag != nullptr ) {
if ( isCartesian( oldType ) && isCartesian( chartType ) ) {
AbstractCartesianDiagram *oldDiag =
qobject_cast( coordinatePlane()->diagram() );
AbstractCartesianDiagram *newDiag =
qobject_cast( diag );
Q_FOREACH( CartesianAxis* axis, oldDiag->axes() ) {
oldDiag->takeAxis( axis );
newDiag->addAxis ( axis );
}
}
Q_FOREACH( Legend* l, d->m_chart.legends() ) {
l->setDiagram( diag );
}
diag->setModel( &d->m_model );
coordinatePlane()->replaceDiagram( diag );
//checkDatasetWidth( d->usedDatasetWidth );
}
//coordinatePlane()->setGridNeedsRecalculate();
}
if ( chartType != NoType ) {
if ( chartType != oldType || chartSubType != subType() )
setSubType( chartSubType );
d->m_chart.resize( size() ); // triggering immediate update
}
}
template< class DiagramType, class Subtype >
void setSubtype( AbstractDiagram *_dia, Subtype st)
{
if ( DiagramType *dia = qobject_cast< DiagramType * >( _dia ) ) {
dia->setType( st );
}
}
void Widget::setSubType( SubType subType )
{
// ### at least PieDiagram, PolarDiagram and RingDiagram are unhandled here
AbstractDiagram *dia = diagram();
switch ( subType ) {
case Normal:
setSubtype< BarDiagram >( dia, BarDiagram::Normal );
setSubtype< LineDiagram >( dia, LineDiagram::Normal );
setSubtype< Plotter >( dia, Plotter::Normal );
break;
case Stacked:
setSubtype< BarDiagram >( dia, BarDiagram::Stacked );
setSubtype< LineDiagram >( dia, LineDiagram::Stacked );
// setSubtype< Plotter >( dia, Plotter::Stacked );
break;
case Percent:
setSubtype< BarDiagram >( dia, BarDiagram::Percent );
setSubtype< LineDiagram >( dia, LineDiagram::Percent );
setSubtype< Plotter >( dia, Plotter::Percent );
break;
case Rows:
setSubtype< BarDiagram >( dia, BarDiagram::Rows );
break;
default:
Q_ASSERT_X ( false, "Widget::setSubType", "Sub-type not supported!" );
break;
}
}
-/**
- * Returns the type of the chart.
- */
Widget::ChartType Widget::type() const
{
// PENDING(christoph) save the type out-of-band:
AbstractDiagram * const dia = const_cast( this )->diagram();
if ( qobject_cast< BarDiagram* >( dia ) )
return Bar;
else if ( qobject_cast< LineDiagram* >( dia ) )
return Line;
else if ( qobject_cast< Plotter* >( dia ) )
return Plot;
else if ( qobject_cast< PieDiagram* >( dia ) )
return Pie;
else if ( qobject_cast< PolarDiagram* >( dia ) )
return Polar;
else if ( qobject_cast< RingDiagram* >( dia ) )
return Ring;
else
return NoType;
}
Widget::SubType Widget::subType() const
{
// PENDING(christoph) save the type out-of-band:
Widget::SubType retVal = Normal;
AbstractDiagram * const dia = const_cast( this )->diagram();
BarDiagram* barDia = qobject_cast< BarDiagram* >( dia );
LineDiagram* lineDia = qobject_cast< LineDiagram* >( dia );
Plotter* plotterDia = qobject_cast< Plotter* >( dia );
//FIXME(khz): Add the impl for these chart types - or remove them from here:
// PieDiagram* pieDia = qobject_cast< PieDiagram* >( diagram() );
// PolarDiagram* polarDia = qobject_cast< PolarDiagram* >( diagram() );
// RingDiagram* ringDia = qobject_cast< RingDiagram* >( diagram() );
#define TEST_SUB_TYPE(DIAGRAM, INTERNALSUBTYPE, SUBTYPE) \
{ \
if ( DIAGRAM && DIAGRAM->type() == INTERNALSUBTYPE ) \
retVal = SUBTYPE; \
}
const Widget::ChartType mainType = type();
switch ( mainType )
{
case Bar:
TEST_SUB_TYPE( barDia, BarDiagram::Normal, Normal );
TEST_SUB_TYPE( barDia, BarDiagram::Stacked, Stacked );
TEST_SUB_TYPE( barDia, BarDiagram::Percent, Percent );
TEST_SUB_TYPE( barDia, BarDiagram::Rows, Rows );
break;
case Line:
TEST_SUB_TYPE( lineDia, LineDiagram::Normal, Normal );
TEST_SUB_TYPE( lineDia, LineDiagram::Stacked, Stacked );
TEST_SUB_TYPE( lineDia, LineDiagram::Percent, Percent );
break;
case Plot:
TEST_SUB_TYPE( plotterDia, Plotter::Normal, Normal );
TEST_SUB_TYPE( plotterDia, Plotter::Percent, Percent );
break;
case Pie:
// no impl. yet
break;
case Polar:
// no impl. yet
break;
case Ring:
// no impl. yet
break;
default:
Q_ASSERT_X ( false,
"Widget::subType", "Chart type not supported!" );
break;
}
return retVal;
}
-/**
- * Checks whether the given width matches with the one used until now.
- */
bool Widget::checkDatasetWidth( int width )
{
if ( width == diagram()->datasetDimension() )
{
d->usedDatasetWidth = width;
return true;
}
qDebug() << "The current diagram type doesn't support this data dimension.";
return false;
/* if ( d->usedDatasetWidth == width || d->usedDatasetWidth == 0 ) {
d->usedDatasetWidth = width;
diagram()->setDatasetDimension( width );
return true;
}
qDebug() << "It's impossible to mix up the different setDataset() methods on the same widget.";
return false;*/
}
-/**
- * Justifies the model, so that the given rows and columns fit into it.
- */
void Widget::justifyModelSize( int rows, int columns )
{
QAbstractItemModel & model = d->m_model;
const int currentRows = model.rowCount();
const int currentCols = model.columnCount();
if ( currentCols < columns )
if ( ! model.insertColumns( currentCols, columns - currentCols ))
qDebug() << "justifyModelSize: could not increase model size.";
if ( currentRows < rows )
if ( ! model.insertRows( currentRows, rows - currentRows ))
qDebug() << "justifyModelSize: could not increase model size.";
Q_ASSERT( model.rowCount() >= rows );
Q_ASSERT( model.columnCount() >= columns );
}
diff --git a/src/KChart/KChartWidget.h b/src/KChart/KChartWidget.h
index fe3f255..6472050 100644
--- a/src/KChart/KChartWidget.h
+++ b/src/KChart/KChartWidget.h
@@ -1,239 +1,239 @@
/*
* Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
*
* This file is part of the KD Chart library.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef __KCHARTWIDGET_H__
#define __KCHARTWIDGET_H__
#include "KChartGlobal.h"
#include
#include "KChartEnums.h"
#include "KChartHeaderFooter.h"
QT_BEGIN_NAMESPACE
template class QVector;
template struct QPair;
QT_END_NAMESPACE
namespace KChart {
// some forward declarations
class AbstractDiagram;
class Chart;
class AbstractCoordinatePlane;
class TableModel;
class BarDiagram;
class LineDiagram;
class Plotter;
class PieDiagram;
class RingDiagram;
class PolarDiagram;
class Legend;
class Position;
/**
- * \class Widget KChartWidget.h
- * \brief The KChart widget for usage without Model/View.
- *
- * If you want to use KChart with Model/View, use KChart::Chart instead.
- */
- class KCHART_EXPORT Widget : public QWidget
+ * \class Widget KChartWidget.h
+ * \brief The KChart widget for usage without Interwiev.
+ *
+ * If you want to use KChart with Interview, use KChart::Chart instead.
+ */
+ class KCHART_EXPORT Widget : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY( Widget )
KCHART_DECLARE_PRIVATE_BASE_POLYMORPHIC_QWIDGET( Widget )
public:
/**
* Standard Qt-style Constructor
*
* Creates a new widget with all data initialized empty.
*
* \param parent the widget parent; passed on to QWidget
*/
- explicit Widget( QWidget* parent = nullptr );
+ explicit Widget( QWidget* parent = nullptr );
/** Destructor. */
- ~Widget();
+ ~Widget();
/** Sets the data in the given column using a QVector of qreal for the Y values. */
void setDataset( int column, const QVector< qreal > & data, const QString& title = QString() );
/** Sets the data in the given column using a QVector of QPairs
* of qreal for the (X, Y) values. */
void setDataset( int column, const QVector< QPair< qreal, qreal > > & data, const QString& title = QString() );
/** Sets the Y value data for a given cell. */
void setDataCell( int row, int column, qreal data );
/** Sets the data for a given column using an (X, Y) QPair of qreals. */
void setDataCell( int row, int column, QPair< qreal, qreal > data );
/** Resets all data. */
void resetData();
public Q_SLOTS:
/** Sets all global leadings (borders). */
void setGlobalLeading( int left, int top, int right, int bottom );
/** Sets the left leading (border). */
- void setGlobalLeadingLeft( int leading );
+ void setGlobalLeadingLeft( int leading );
/** Sets the top leading (border). */
- void setGlobalLeadingTop( int leading );
+ void setGlobalLeadingTop( int leading );
/** Sets the right leading (border). */
- void setGlobalLeadingRight( int leading );
+ void setGlobalLeadingRight( int leading );
/** Sets the bottom leading (border). */
- void setGlobalLeadingBottom( int leading );
+ void setGlobalLeadingBottom( int leading );
public:
/** Returns the left leading (border). */
int globalLeadingLeft() const;
/** Returns the top leading (border). */
int globalLeadingTop() const;
/** Returns the right leading (border). */
int globalLeadingRight() const;
/** Returns the bottom leading (border). */
int globalLeadingBottom() const;
/** Returns the first of all headers. */
HeaderFooter* firstHeaderFooter();
/** Returns a list with all headers. */
QList allHeadersFooters();
/** Adds a new header/footer with the given text to the position. */
void addHeaderFooter( const QString& text,
HeaderFooter::HeaderFooterType type,
Position position );
/**
* Adds the existing header / footer object \a header.
* \sa replaceHeaderFooter, takeHeaderFooter
*/
void addHeaderFooter( HeaderFooter* header );
/**
* Replaces the old header (or footer, resp.), or appends the
* new header or footer, it there is none yet.
*
* @param header The header or footer to be used instead of the old one.
* This parameter must not be zero, or the method will do nothing.
*
* @param oldHeader The header or footer to be removed by the new one. This
* header or footer will be deleted automatically. If the parameter is omitted,
* the very first header or footer will be replaced. In case, there was no
* header and no footer yet, the new header or footer will just be added.
*
* \note If you want to re-use the old header or footer, call takeHeaderFooter and
* addHeaderFooter, instead of using replaceHeaderFooter.
*
* \sa addHeaderFooter, takeHeaderFooter
*/
void replaceHeaderFooter( HeaderFooter* header,
HeaderFooter* oldHeader = nullptr );
/** Remove the header (or footer, resp.) from the widget,
* without deleting it.
* The chart no longer owns the header or footer, so it is
* the caller's responsibility to delete the header or footer.
*
* \sa addHeaderFooter, replaceHeaderFooter
*/
void takeHeaderFooter( HeaderFooter* header );
/** Returns the first of all legends. */
Legend* legend();
/** Returns a list with all legends. */
QList