qpieseries.cpp
1002 lines
| 24.6 KiB
| text/x-c
|
CppLexer
|
r794 | /**************************************************************************** | ||
** | ||||
|
r2776 | ** Copyright (C) 2015 The Qt Company Ltd | ||
|
r794 | ** All rights reserved. | ||
|
r2776 | ** For any questions to The Qt Company, please use contact form at http://qt.io | ||
|
r794 | ** | ||
|
r2740 | ** This file is part of the Qt Charts module. | ||
|
r794 | ** | ||
|
r2740 | ** Licensees holding valid commercial license for Qt may use this file in | ||
** accordance with the Qt License Agreement provided with the Software | ||||
** or, alternatively, in accordance with the terms contained in a written | ||||
|
r2776 | ** agreement between you and The Qt Company. | ||
|
r794 | ** | ||
** If you have questions regarding the use of this file, please use | ||||
|
r2740 | ** contact form at http://qt.io | ||
|
r794 | ** | ||
****************************************************************************/ | ||||
|
r2714 | #include <QtCharts/QPieSeries> | ||
#include <private/qpieseries_p.h> | ||||
#include <QtCharts/QPieSlice> | ||||
#include <private/qpieslice_p.h> | ||||
#include <private/pieslicedata_p.h> | ||||
#include <private/chartdataset_p.h> | ||||
#include <private/charttheme_p.h> | ||||
#include <QtCharts/QAbstractAxis> | ||||
#include <private/pieanimation_p.h> | ||||
#include <private/charthelpers_p.h> | ||||
#include <QtCharts/QPieLegendMarker> | ||||
|
r2163 | |||
|
r2712 | QT_CHARTS_BEGIN_NAMESPACE | ||
|
r142 | |||
|
r320 | /*! | ||
\class QPieSeries | ||||
|
r2639 | \inmodule Qt Charts | ||
|
r2591 | \brief Pie series API for Qt Charts. | ||
|
r320 | |||
|
r952 | The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects. | ||
|
r320 | The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices. | ||
|
r386 | The actual slice size is determined by that relative value. | ||
|
r320 | |||
|
r2494 | Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0. | ||
|
r952 | These relate to the actual chart rectangle. | ||
By default the pie is defined as a full pie but it can also be a partial pie. | ||||
|
r320 | This can be done by setting a starting angle and angle span to the series. | ||
|
r952 | Full pie is 360 degrees where 0 is at 12 a'clock. | ||
|
r995 | |||
|
r1842 | See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries. | ||
|
r2750 | \image examples_piechart.png | ||
\image examples_donutchart.png | ||||
|
r320 | */ | ||
|
r1491 | /*! | ||
|
r2639 | \qmltype PieSeries | ||
\instantiates QPieSeries | ||||
|
r2712 | \inqmlmodule QtCharts | ||
|
r1504 | |||
|
r2712 | \inherits AbstractSeries | ||
\brief The PieSeries type is used for making pie charts. | ||||
The following QML shows how to create a simple pie chart. | ||||
\snippet qmlchart/qml/qmlchart/View1.qml 1 | ||||
|
r1504 | |||
|
r2712 | \beginfloatleft | ||
\image examples_qmlchart1.png | ||||
\endfloat | ||||
\clearfloat | ||||
|
r1491 | */ | ||
|
r320 | |||
|
r924 | /*! | ||
|
r928 | \property QPieSeries::horizontalPosition | ||
|
r932 | \brief Defines the horizontal position of the pie. | ||
|
r1504 | |||
|
r932 | The value is a relative value to the chart rectangle where: | ||
|
r1504 | |||
|
r932 | \list | ||
|
r2639 | \li 0.0 is the absolute left. | ||
\li 1.0 is the absolute right. | ||||
|
r932 | \endlist | ||
Default value is 0.5 (center). | ||||
|
r1491 | \sa verticalPosition | ||
*/ | ||||
|
r1504 | |||
|
r1491 | /*! | ||
\qmlproperty real PieSeries::horizontalPosition | ||||
|
r1504 | |||
Defines the horizontal position of the pie. | ||||
The value is a relative value to the chart rectangle where: | ||||
|
r1491 | \list | ||
|
r2639 | \li 0.0 is the absolute left. | ||
\li 1.0 is the absolute right. | ||||
|
r1491 | \endlist | ||
Default value is 0.5 (center). | ||||
|
r1279 | \sa verticalPosition | ||
*/ | ||||
|
r928 | /*! | ||
\property QPieSeries::verticalPosition | ||||
|
r932 | \brief Defines the vertical position of the pie. | ||
|
r1504 | |||
|
r932 | The value is a relative value to the chart rectangle where: | ||
|
r1504 | |||
|
r932 | \list | ||
|
r2639 | \li 0.0 is the absolute top. | ||
\li 1.0 is the absolute bottom. | ||||
|
r932 | \endlist | ||
Default value is 0.5 (center). | ||||
|
r1491 | \sa horizontalPosition | ||
*/ | ||||
|
r1504 | |||
|
r1491 | /*! | ||
\qmlproperty real PieSeries::verticalPosition | ||||
|
r1504 | |||
Defines the vertical position of the pie. | ||||
The value is a relative value to the chart rectangle where: | ||||
|
r1491 | \list | ||
|
r2639 | \li 0.0 is the absolute top. | ||
\li 1.0 is the absolute bottom. | ||||
|
r1491 | \endlist | ||
Default value is 0.5 (center). | ||||
|
r1279 | \sa horizontalPosition | ||
*/ | ||||
|
r928 | /*! | ||
\property QPieSeries::size | ||||
|
r932 | \brief Defines the pie size. | ||
|
r928 | |||
|
r932 | The value is a relative value to the chart rectangle where: | ||
\list | ||||
|
r2639 | \li 0.0 is the minimum size (pie not drawn). | ||
\li 1.0 is the maximum size that can fit the chart. | ||||
|
r932 | \endlist | ||
|
r1838 | When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size. | ||
|
r1741 | |||
|
r932 | Default value is 0.7. | ||
|
r928 | */ | ||
|
r1504 | /*! | ||
\qmlproperty real PieSeries::size | ||||
Defines the pie size. | ||||
The value is a relative value to the chart rectangle where: | ||||
\list | ||||
|
r2639 | \li 0.0 is the minimum size (pie not drawn). | ||
\li 1.0 is the maximum size that can fit the chart. | ||||
|
r1504 | \endlist | ||
Default value is 0.7. | ||||
*/ | ||||
|
r1731 | /*! | ||
|
r1838 | \property QPieSeries::holeSize | ||
\brief Defines the donut hole size. | ||||
|
r1731 | |||
The value is a relative value to the chart rectangle where: | ||||
\list | ||||
|
r2639 | \li 0.0 is the minimum size (full pie drawn, without any hole inside). | ||
\li 1.0 is the maximum size that can fit the chart. (donut has no width) | ||||
|
r1731 | \endlist | ||
The value is never greater then size property. | ||||
|
r1838 | Default value is 0.0. | ||
|
r1731 | */ | ||
/*! | ||||
|
r1838 | \qmlproperty real PieSeries::holeSize | ||
|
r1731 | |||
|
r1838 | Defines the donut hole size. | ||
|
r1731 | |||
The value is a relative value to the chart rectangle where: | ||||
\list | ||||
|
r2639 | \li 0.0 is the minimum size (full pie drawn, without any hole inside). | ||
\li 1.0 is the maximum size that can fit the chart. (donut has no width) | ||||
|
r1731 | \endlist | ||
|
r1741 | When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size. | ||
|
r1838 | Default value is 0.0. | ||
|
r1731 | */ | ||
|
r928 | /*! | ||
\property QPieSeries::startAngle | ||||
|
r932 | \brief Defines the starting angle of the pie. | ||
|
r928 | |||
|
r932 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||
|
r928 | |||
|
r932 | Default is value is 0. | ||
*/ | ||||
|
r928 | |||
|
r1504 | /*! | ||
\qmlproperty real PieSeries::startAngle | ||||
Defines the starting angle of the pie. | ||||
Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||||
Default is value is 0. | ||||
*/ | ||||
|
r928 | /*! | ||
\property QPieSeries::endAngle | ||||
|
r932 | \brief Defines the ending angle of the pie. | ||
|
r928 | |||
|
r932 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||
|
r928 | |||
|
r932 | Default is value is 360. | ||
*/ | ||||
|
r928 | |||
|
r1504 | /*! | ||
\qmlproperty real PieSeries::endAngle | ||||
Defines the ending angle of the pie. | ||||
Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||||
Default is value is 360. | ||||
*/ | ||||
|
r1224 | /*! | ||
\property QPieSeries::count | ||||
|
r1279 | Number of slices in the series. | ||
*/ | ||||
|
r1504 | /*! | ||
\qmlproperty int PieSeries::count | ||||
Number of slices in the series. | ||||
*/ | ||||
|
r1279 | /*! | ||
\fn void QPieSeries::countChanged() | ||||
Emitted when the slice count has changed. | ||||
\sa count | ||||
|
r1224 | */ | ||
|
r1531 | /*! | ||
\qmlsignal PieSeries::onCountChanged() | ||||
Emitted when the slice count has changed. | ||||
*/ | ||||
|
r1224 | |||
/*! | ||||
\property QPieSeries::sum | ||||
|
r1279 | |||
Sum of all slices. | ||||
|
r1224 | |||
The series keeps track of the sum of all slices it holds. | ||||
*/ | ||||
|
r1504 | /*! | ||
\qmlproperty real PieSeries::sum | ||||
Sum of all slices. | ||||
The series keeps track of the sum of all slices it holds. | ||||
*/ | ||||
|
r1279 | /*! | ||
\fn void QPieSeries::sumChanged() | ||||
Emitted when the sum of all slices has changed. | ||||
\sa sum | ||||
*/ | ||||
|
r1531 | /*! | ||
\qmlsignal PieSeries::onSumChanged() | ||||
Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you | ||||
change value of a slice. | ||||
*/ | ||||
|
r1279 | |||
/*! | ||||
\fn void QPieSeries::added(QList<QPieSlice*> slices) | ||||
This signal is emitted when \a slices have been added to the series. | ||||
\sa append(), insert() | ||||
*/ | ||||
|
r1503 | /*! | ||
|
r1531 | \qmlsignal PieSeries::onAdded(PieSlice slice) | ||
|
r1503 | Emitted when \a slice has been added to the series. | ||
*/ | ||||
|
r1279 | |||
/*! | ||||
\fn void QPieSeries::removed(QList<QPieSlice*> slices) | ||||
This signal is emitted when \a slices have been removed from the series. | ||||
\sa remove() | ||||
*/ | ||||
|
r1503 | /*! | ||
|
r1531 | \qmlsignal PieSeries::onRemoved(PieSlice slice) | ||
|
r1503 | Emitted when \a slice has been removed from the series. | ||
*/ | ||||
|
r1279 | |||
/*! | ||||
|
r2746 | \fn void QPieSeries::clicked(QPieSlice *slice) | ||
|
r1279 | This signal is emitted when a \a slice has been clicked. | ||
\sa QPieSlice::clicked() | ||||
*/ | ||||
|
r1531 | /*! | ||
\qmlsignal PieSeries::onClicked(PieSlice slice) | ||||
This signal is emitted when a \a slice has been clicked. | ||||
*/ | ||||
|
r1279 | |||
|
r2739 | /*! | ||
|
r2746 | \fn void QPieSeries::pressed(QPieSlice *slice) | ||
|
r2739 | This signal is emitted when a \a slice has been pressed. | ||
\sa QPieSlice::pressed() | ||||
*/ | ||||
/*! | ||||
\qmlsignal PieSeries::onPressed(PieSlice slice) | ||||
This signal is emitted when a \a slice has been pressed. | ||||
*/ | ||||
/*! | ||||
|
r2746 | \fn void QPieSeries::released(QPieSlice *slice) | ||
|
r2739 | This signal is emitted when a \a slice has been released. | ||
\sa QPieSlice::released() | ||||
*/ | ||||
/*! | ||||
\qmlsignal PieSeries::onReleased(PieSlice slice) | ||||
This signal is emitted when a \a slice has been released. | ||||
*/ | ||||
/*! | ||||
|
r2746 | \fn void QPieSeries::doubleClicked(QPieSlice *slice) | ||
|
r2739 | This signal is emitted when a \a slice has been doubleClicked. | ||
\sa QPieSlice::doubleClicked() | ||||
*/ | ||||
/*! | ||||
\qmlsignal PieSeries::onDoubleClicked(PieSlice slice) | ||||
This signal is emitted when a \a slice has been doubleClicked. | ||||
*/ | ||||
|
r1279 | /*! | ||
\fn void QPieSeries::hovered(QPieSlice* slice, bool state) | ||||
This signal is emitted when user has hovered over or away from the \a slice. | ||||
\a state is true when user has hovered over the slice and false when hover has moved away from the slice. | ||||
\sa QPieSlice::hovered() | ||||
*/ | ||||
|
r1531 | /*! | ||
\qmlsignal PieSeries::onHovered(PieSlice slice, bool state) | ||||
This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered | ||||
over the slice and false when hover has moved away from the slice. | ||||
*/ | ||||
|
r924 | |||
|
r1521 | /*! | ||
\qmlmethod PieSlice PieSeries::at(int index) | ||||
Returns slice at \a index. Returns null if the index is not valid. | ||||
*/ | ||||
/*! | ||||
\qmlmethod PieSlice PieSeries::find(string label) | ||||
Returns the first slice with \a label. Returns null if the index is not valid. | ||||
*/ | ||||
/*! | ||||
\qmlmethod PieSlice PieSeries::append(string label, real value) | ||||
Adds a new slice with \a label and \a value to the pie. | ||||
*/ | ||||
/*! | ||||
\qmlmethod bool PieSeries::remove(PieSlice slice) | ||||
|
r1932 | Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise. | ||
|
r1521 | */ | ||
/*! | ||||
\qmlmethod PieSeries::clear() | ||||
Removes all slices from the pie. | ||||
*/ | ||||
|
r314 | /*! | ||
Constructs a series object which is a child of \a parent. | ||||
*/ | ||||
|
r2097 | QPieSeries::QPieSeries(QObject *parent) | ||
: QAbstractSeries(*new QPieSeriesPrivate(this), parent) | ||||
|
r203 | { | ||
|
r2085 | Q_D(QPieSeries); | ||
|
r2097 | QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged())); | ||
|
r203 | } | ||
|
r174 | |||
|
r314 | /*! | ||
|
r933 | Destroys the series and its slices. | ||
|
r314 | */ | ||
|
r203 | QPieSeries::~QPieSeries() | ||
{ | ||||
|
r669 | // NOTE: d_prt destroyed by QObject | ||
|
r2475 | clear(); | ||
|
r203 | } | ||
|
r314 | /*! | ||
|
r2520 | Returns QAbstractSeries::SeriesTypePie. | ||
|
r314 | */ | ||
|
r1107 | QAbstractSeries::SeriesType QPieSeries::type() const | ||
|
r314 | { | ||
|
r988 | return QAbstractSeries::SeriesTypePie; | ||
|
r314 | } | ||
|
r1279 | /*! | ||
Appends a single \a slice to the series. | ||||
Slice ownership is passed to the series. | ||||
Returns true if append was succesfull. | ||||
*/ | ||||
|
r2104 | bool QPieSeries::append(QPieSlice *slice) | ||
|
r1279 | { | ||
|
r2104 | return append(QList<QPieSlice *>() << slice); | ||
|
r1279 | } | ||
|
r314 | /*! | ||
|
r933 | Appends an array of \a slices to the series. | ||
|
r314 | Slice ownership is passed to the series. | ||
|
r1224 | |||
|
r1932 | Returns true if append was successful. | ||
|
r314 | */ | ||
|
r2104 | bool QPieSeries::append(QList<QPieSlice *> slices) | ||
|
r203 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1104 | if (slices.count() == 0) | ||
return false; | ||||
|
r2097 | foreach (QPieSlice *s, slices) { | ||
|
r1104 | if (!s || d->m_slices.contains(s)) | ||
return false; | ||||
|
r1324 | if (s->series()) // already added to some series | ||
return false; | ||||
|
r2424 | if (!isValidValue(s->value())) | ||
return false; | ||||
|
r1104 | } | ||
|
r2097 | foreach (QPieSlice *s, slices) { | ||
|
r203 | s->setParent(this); | ||
|
r1323 | QPieSlicePrivate::fromSlice(s)->m_series = this; | ||
|
r669 | d->m_slices << s; | ||
|
r174 | } | ||
|
r157 | |||
|
r669 | d->updateDerivativeData(); | ||
|
r174 | |||
|
r2131 | foreach(QPieSlice * s, slices) { | ||
|
r1274 | connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged())); | ||
|
r1009 | connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked())); | ||
connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool))); | ||||
|
r2739 | connect(s, SIGNAL(pressed()), d, SLOT(slicePressed())); | ||
connect(s, SIGNAL(released()), d, SLOT(sliceReleased())); | ||||
connect(s, SIGNAL(doubleClicked()), d, SLOT(sliceDoubleClicked())); | ||||
|
r203 | } | ||
|
r1213 | emit added(slices); | ||
|
r1255 | emit countChanged(); | ||
|
r1104 | |||
return true; | ||||
|
r142 | } | ||
|
r415 | /*! | ||
|
r933 | Appends a single \a slice to the series and returns a reference to the series. | ||
|
r415 | Slice ownership is passed to the series. | ||
*/ | ||||
|
r2104 | QPieSeries &QPieSeries::operator << (QPieSlice *slice) | ||
|
r406 | { | ||
|
r796 | append(slice); | ||
|
r406 | return *this; | ||
} | ||||
|
r314 | |||
/*! | ||||
|
r1206 | Appends a single slice to the series with give \a value and \a label. | ||
|
r314 | Slice ownership is passed to the series. | ||
|
r2424 | Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series. | ||
|
r314 | */ | ||
|
r2104 | QPieSlice *QPieSeries::append(QString label, qreal value) | ||
|
r142 | { | ||
|
r2424 | if (isValidValue(value)) { | ||
QPieSlice *slice = new QPieSlice(label, value); | ||||
append(slice); | ||||
return slice; | ||||
} else { | ||||
return 0; | ||||
} | ||||
|
r203 | } | ||
|
r174 | |||
|
r809 | /*! | ||
Inserts a single \a slice to the series before the slice at \a index position. | ||||
Slice ownership is passed to the series. | ||||
|
r1224 | |||
|
r1932 | Returns true if insert was successful. | ||
|
r809 | */ | ||
|
r2104 | bool QPieSeries::insert(int index, QPieSlice *slice) | ||
|
r604 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1104 | |||
if (index < 0 || index > d->m_slices.count()) | ||||
return false; | ||||
if (!slice || d->m_slices.contains(slice)) | ||||
return false; | ||||
|
r1324 | if (slice->series()) // already added to some series | ||
return false; | ||||
|
r2424 | if (!isValidValue(slice->value())) | ||
return false; | ||||
|
r1204 | slice->setParent(this); | ||
|
r1323 | QPieSlicePrivate::fromSlice(slice)->m_series = this; | ||
|
r1204 | d->m_slices.insert(index, slice); | ||
|
r1195 | |||
|
r1204 | d->updateDerivativeData(); | ||
|
r604 | |||
|
r1274 | connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged())); | ||
|
r1204 | connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked())); | ||
connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool))); | ||||
|
r2739 | connect(slice, SIGNAL(pressed()), d, SLOT(slicePressed())); | ||
connect(slice, SIGNAL(released()), d, SLOT(sliceReleased())); | ||||
connect(slice, SIGNAL(doubleClicked()), d, SLOT(sliceDoubleClicked())); | ||||
|
r604 | |||
|
r2104 | emit added(QList<QPieSlice *>() << slice); | ||
|
r1255 | emit countChanged(); | ||
|
r1104 | |||
return true; | ||||
|
r604 | } | ||
|
r314 | /*! | ||
Removes a single \a slice from the series and deletes the slice. | ||||
|
r320 | |||
|
r952 | Do not reference the pointer after this call. | ||
|
r1224 | |||
|
r1932 | Returns true if remove was successful. | ||
|
r314 | */ | ||
|
r2104 | bool QPieSeries::remove(QPieSlice *slice) | ||
|
r203 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1104 | |||
if (!d->m_slices.removeOne(slice)) | ||||
return false; | ||||
|
r174 | |||
|
r669 | d->updateDerivativeData(); | ||
|
r174 | |||
|
r2104 | emit removed(QList<QPieSlice *>() << slice); | ||
|
r1255 | emit countChanged(); | ||
|
r621 | |||
|
r203 | delete slice; | ||
|
r823 | slice = 0; | ||
|
r1104 | |||
return true; | ||||
|
r142 | } | ||
|
r1798 | /*! | ||
Takes a single \a slice from the series. Does not destroy the slice object. | ||||
|
r2494 | \note The series remains as the slice's parent object. You must set the | ||
|
r1798 | parent object to take full ownership. | ||
|
r1932 | Returns true if take was successful. | ||
|
r1798 | */ | ||
|
r2104 | bool QPieSeries::take(QPieSlice *slice) | ||
|
r1798 | { | ||
Q_D(QPieSeries); | ||||
if (!d->m_slices.removeOne(slice)) | ||||
return false; | ||||
QPieSlicePrivate::fromSlice(slice)->m_series = 0; | ||||
|
r2084 | slice->disconnect(d); | ||
|
r1798 | |||
d->updateDerivativeData(); | ||||
|
r2104 | emit removed(QList<QPieSlice *>() << slice); | ||
|
r1798 | emit countChanged(); | ||
return true; | ||||
} | ||||
|
r314 | /*! | ||
Clears all slices from the series. | ||||
*/ | ||||
|
r203 | void QPieSeries::clear() | ||
|
r142 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1204 | if (d->m_slices.count() == 0) | ||
|
r203 | return; | ||
|
r174 | |||
|
r2104 | QList<QPieSlice *> slices = d->m_slices; | ||
|
r2097 | foreach (QPieSlice *s, d->m_slices) | ||
|
r1204 | d->m_slices.removeOne(s); | ||
|
r566 | |||
|
r1204 | d->updateDerivativeData(); | ||
|
r621 | |||
|
r1213 | emit removed(slices); | ||
|
r1255 | emit countChanged(); | ||
|
r2084 | |||
|
r2097 | foreach (QPieSlice *s, slices) | ||
|
r2084 | delete s; | ||
|
r142 | } | ||
|
r1279 | /*! | ||
Returns a list of slices that belong to this series. | ||||
*/ | ||||
|
r2104 | QList<QPieSlice *> QPieSeries::slices() const | ||
|
r1279 | { | ||
Q_D(const QPieSeries); | ||||
return d->m_slices; | ||||
} | ||||
|
r314 | /*! | ||
|
r933 | returns the number of the slices in this series. | ||
|
r314 | */ | ||
int QPieSeries::count() const | ||||
{ | ||||
|
r669 | Q_D(const QPieSeries); | ||
|
r1204 | return d->m_slices.count(); | ||
|
r314 | } | ||
|
r621 | /*! | ||
Returns true is the series is empty. | ||||
*/ | ||||
bool QPieSeries::isEmpty() const | ||||
{ | ||||
|
r669 | Q_D(const QPieSeries); | ||
return d->m_slices.isEmpty(); | ||||
|
r621 | } | ||
|
r314 | /*! | ||
|
r1279 | Returns the sum of all slice values in this series. | ||
\sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage() | ||||
|
r314 | */ | ||
|
r1279 | qreal QPieSeries::sum() const | ||
|
r314 | { | ||
|
r669 | Q_D(const QPieSeries); | ||
|
r1279 | return d->m_sum; | ||
|
r314 | } | ||
|
r1838 | void QPieSeries::setHoleSize(qreal holeSize) | ||
|
r1671 | { | ||
Q_D(QPieSeries); | ||||
|
r1838 | holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0); | ||
d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize)); | ||||
|
r1671 | } | ||
|
r1838 | qreal QPieSeries::holeSize() const | ||
|
r1671 | { | ||
Q_D(const QPieSeries); | ||||
|
r1838 | return d->m_holeRelativeSize; | ||
|
r1671 | } | ||
|
r884 | void QPieSeries::setHorizontalPosition(qreal relativePosition) | ||
{ | ||||
Q_D(QPieSeries); | ||||
|
r1255 | |||
if (relativePosition < 0.0) | ||||
relativePosition = 0.0; | ||||
if (relativePosition > 1.0) | ||||
relativePosition = 1.0; | ||||
|
r2242 | if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) { | ||
|
r1255 | d->m_pieRelativeHorPos = relativePosition; | ||
|
r1482 | emit d->horizontalPositionChanged(); | ||
|
r1255 | } | ||
|
r884 | } | ||
|
r454 | |||
|
r1279 | qreal QPieSeries::horizontalPosition() const | ||
{ | ||||
Q_D(const QPieSeries); | ||||
return d->m_pieRelativeHorPos; | ||||
} | ||||
|
r884 | void QPieSeries::setVerticalPosition(qreal relativePosition) | ||
|
r142 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1255 | |||
if (relativePosition < 0.0) | ||||
relativePosition = 0.0; | ||||
if (relativePosition > 1.0) | ||||
relativePosition = 1.0; | ||||
|
r2242 | if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) { | ||
|
r1255 | d->m_pieRelativeVerPos = relativePosition; | ||
|
r1482 | emit d->verticalPositionChanged(); | ||
|
r1255 | } | ||
|
r142 | } | ||
|
r884 | qreal QPieSeries::verticalPosition() const | ||
|
r314 | { | ||
|
r669 | Q_D(const QPieSeries); | ||
return d->m_pieRelativeVerPos; | ||||
|
r314 | } | ||
|
r498 | void QPieSeries::setPieSize(qreal relativeSize) | ||
|
r437 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r1779 | relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0); | ||
|
r1838 | d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize); | ||
|
r1255 | |||
|
r437 | } | ||
|
r314 | |||
|
r498 | qreal QPieSeries::pieSize() const | ||
|
r203 | { | ||
|
r669 | Q_D(const QPieSeries); | ||
return d->m_pieRelativeSize; | ||||
|
r437 | } | ||
|
r498 | void QPieSeries::setPieStartAngle(qreal angle) | ||
|
r437 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r2242 | if (qFuzzyCompare(d->m_pieStartAngle, angle)) | ||
|
r1207 | return; | ||
d->m_pieStartAngle = angle; | ||||
d->updateDerivativeData(); | ||||
|
r1482 | emit d->pieStartAngleChanged(); | ||
|
r203 | } | ||
|
r498 | qreal QPieSeries::pieStartAngle() const | ||
|
r437 | { | ||
|
r669 | Q_D(const QPieSeries); | ||
return d->m_pieStartAngle; | ||||
|
r437 | } | ||
|
r454 | /*! | ||
Sets the end angle of the pie. | ||||
Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||||
|
r498 | \a angle must be greater than start angle. | ||
|
r454 | |||
|
r498 | \sa pieEndAngle(), pieStartAngle(), setPieStartAngle() | ||
|
r454 | */ | ||
|
r498 | void QPieSeries::setPieEndAngle(qreal angle) | ||
|
r437 | { | ||
|
r669 | Q_D(QPieSeries); | ||
|
r2242 | if (qFuzzyCompare(d->m_pieEndAngle, angle)) | ||
|
r1207 | return; | ||
d->m_pieEndAngle = angle; | ||||
d->updateDerivativeData(); | ||||
|
r1482 | emit d->pieEndAngleChanged(); | ||
|
r437 | } | ||
|
r454 | /*! | ||
Returns the end angle of the pie. | ||||
Full pie is 360 degrees where 0 degrees is at 12 a'clock. | ||||
|
r498 | \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle() | ||
|
r454 | */ | ||
|
r498 | qreal QPieSeries::pieEndAngle() const | ||
|
r437 | { | ||
|
r669 | Q_D(const QPieSeries); | ||
return d->m_pieEndAngle; | ||||
|
r437 | } | ||
|
r314 | /*! | ||
Sets the all the slice labels \a visible or invisible. | ||||
|
r1279 | Note that this affects only the current slices in the series. | ||
If user adds a new slice the default label visibility is false. | ||||
|
r314 | \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible() | ||
*/ | ||||
|
r203 | void QPieSeries::setLabelsVisible(bool visible) | ||
{ | ||||
|
r669 | Q_D(QPieSeries); | ||
|
r2097 | foreach (QPieSlice *s, d->m_slices) | ||
|
r203 | s->setLabelVisible(visible); | ||
} | ||||
|
r1743 | /*! | ||
Sets the all the slice labels \a position | ||||
Note that this affects only the current slices in the series. | ||||
If user adds a new slice the default label position is LabelOutside | ||||
\sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition() | ||||
*/ | ||||
|
r1712 | void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position) | ||
{ | ||||
Q_D(QPieSeries); | ||||
|
r2097 | foreach (QPieSlice *s, d->m_slices) | ||
|
r1712 | s->setLabelPosition(position); | ||
} | ||||
|
r938 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
r988 | QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) : | ||
QAbstractSeriesPrivate(parent), | ||||
|
r938 | m_pieRelativeHorPos(0.5), | ||
m_pieRelativeVerPos(0.5), | ||||
m_pieRelativeSize(0.7), | ||||
m_pieStartAngle(0), | ||||
m_pieEndAngle(360), | ||||
|
r1670 | m_sum(0), | ||
|
r1838 | m_holeRelativeSize(0.0) | ||
|
r938 | { | ||
} | ||||
QPieSeriesPrivate::~QPieSeriesPrivate() | ||||
{ | ||||
} | ||||
void QPieSeriesPrivate::updateDerivativeData() | ||||
{ | ||||
|
r939 | // calculate sum of all slices | ||
|
r1255 | qreal sum = 0; | ||
|
r2097 | foreach (QPieSlice *s, m_slices) | ||
|
r1255 | sum += s->value(); | ||
|
r2242 | if (!qFuzzyCompare(m_sum, sum)) { | ||
|
r1255 | m_sum = sum; | ||
emit q_func()->sumChanged(); | ||||
} | ||||
|
r938 | |||
// nothing to show.. | ||||
|
r2242 | if (qFuzzyCompare(m_sum, 0)) | ||
|
r938 | return; | ||
// update slice attributes | ||||
qreal sliceAngle = m_pieStartAngle; | ||||
qreal pieSpan = m_pieEndAngle - m_pieStartAngle; | ||||
|
r2104 | QVector<QPieSlice *> changed; | ||
|
r2097 | foreach (QPieSlice *s, m_slices) { | ||
|
r1274 | QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s); | ||
d->setPercentage(s->value() / m_sum); | ||||
d->setStartAngle(sliceAngle); | ||||
d->setAngleSpan(pieSpan * s->percentage()); | ||||
sliceAngle += s->angleSpan(); | ||||
|
r938 | } | ||
|
r1274 | |||
emit calculatedDataChanged(); | ||||
|
r938 | } | ||
|
r1741 | void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize) | ||
{ | ||||
bool changed = false; | ||||
|
r2242 | if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) { | ||
|
r1838 | m_holeRelativeSize = innerSize; | ||
|
r1741 | changed = true; | ||
} | ||||
|
r2242 | if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) { | ||
|
r1741 | m_pieRelativeSize = outerSize; | ||
changed = true; | ||||
} | ||||
if (changed) | ||||
emit pieSizeChanged(); | ||||
} | ||||
|
r2104 | QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series) | ||
|
r938 | { | ||
|
r1274 | return series->d_func(); | ||
|
r938 | } | ||
|
r1274 | void QPieSeriesPrivate::sliceValueChanged() | ||
|
r938 | { | ||
|
r1009 | Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender()))); | ||
updateDerivativeData(); | ||||
|
r938 | } | ||
|
r1009 | void QPieSeriesPrivate::sliceClicked() | ||
|
r938 | { | ||
|
r2104 | QPieSlice *slice = qobject_cast<QPieSlice *>(sender()); | ||
|
r938 | Q_ASSERT(m_slices.contains(slice)); | ||
Q_Q(QPieSeries); | ||||
|
r1009 | emit q->clicked(slice); | ||
|
r938 | } | ||
|
r1009 | void QPieSeriesPrivate::sliceHovered(bool state) | ||
|
r938 | { | ||
|
r2104 | QPieSlice *slice = qobject_cast<QPieSlice *>(sender()); | ||
|
r2674 | if (!m_slices.isEmpty()) { | ||
Q_ASSERT(m_slices.contains(slice)); | ||||
Q_Q(QPieSeries); | ||||
emit q->hovered(slice, state); | ||||
} | ||||
|
r938 | } | ||
|
r2739 | void QPieSeriesPrivate::slicePressed() | ||
{ | ||||
QPieSlice *slice = qobject_cast<QPieSlice *>(sender()); | ||||
Q_ASSERT(m_slices.contains(slice)); | ||||
Q_Q(QPieSeries); | ||||
emit q->pressed(slice); | ||||
} | ||||
void QPieSeriesPrivate::sliceReleased() | ||||
{ | ||||
QPieSlice *slice = qobject_cast<QPieSlice *>(sender()); | ||||
Q_ASSERT(m_slices.contains(slice)); | ||||
Q_Q(QPieSeries); | ||||
emit q->released(slice); | ||||
} | ||||
void QPieSeriesPrivate::sliceDoubleClicked() | ||||
{ | ||||
QPieSlice *slice = qobject_cast<QPieSlice *>(sender()); | ||||
Q_ASSERT(m_slices.contains(slice)); | ||||
Q_Q(QPieSeries); | ||||
emit q->doubleClicked(slice); | ||||
} | ||||
|
r2273 | void QPieSeriesPrivate::initializeDomain() | ||
|
r943 | { | ||
|
r1191 | // does not apply to pie | ||
|
r943 | } | ||
|
r2273 | void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent) | ||
|
r943 | { | ||
Q_Q(QPieSeries); | ||||
|
r2273 | PieChartItem *pie = new PieChartItem(q,parent); | ||
m_item.reset(pie); | ||||
QAbstractSeriesPrivate::initializeGraphics(parent); | ||||
} | ||||
|
r2712 | void QPieSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options) | ||
|
r2273 | { | ||
PieChartItem *item = static_cast<PieChartItem *>(m_item.data()); | ||||
Q_ASSERT(item); | ||||
|
r2555 | if (item->animation()) | ||
item->animation()->stopAndDestroyLater(); | ||||
if (options.testFlag(QChart::SeriesAnimations)) | ||||
|
r2273 | item->setAnimation(new PieAnimation(item)); | ||
|
r2555 | else | ||
|
r2273 | item->setAnimation(0); | ||
QAbstractSeriesPrivate::initializeAnimations(options); | ||||
|
r943 | } | ||
|
r938 | |||
|
r2163 | QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend) | ||
{ | ||||
Q_Q(QPieSeries); | ||||
QList<QLegendMarker*> markers; | ||||
foreach(QPieSlice* slice, q->slices()) { | ||||
|
r2167 | QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend); | ||
|
r2163 | markers << marker; | ||
} | ||||
return markers; | ||||
} | ||||
|
r2273 | void QPieSeriesPrivate::initializeAxes() | ||
|
r1545 | { | ||
|
r2273 | |||
|
r1545 | } | ||
|
r1695 | QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const | ||
|
r1588 | { | ||
|
r1695 | Q_UNUSED(orientation); | ||
|
r1588 | return QAbstractAxis::AxisTypeNoAxis; | ||
|
r1545 | } | ||
|
r2273 | QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const | ||
{ | ||||
Q_UNUSED(orientation); | ||||
return 0; | ||||
} | ||||
void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced) | ||||
{ | ||||
|
r2277 | //Q_Q(QPieSeries); | ||
//const QList<QColor>& colors = theme->seriesColors(); | ||||
|
r2273 | const QList<QGradient>& gradients = theme->seriesGradients(); | ||
for (int i(0); i < m_slices.count(); i++) { | ||||
QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0); | ||||
// Get color for a slice from a gradient linearly, beginning from the start of the gradient | ||||
qreal pos = (qreal)(i + 1) / (qreal) m_slices.count(); | ||||
QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos); | ||||
QPieSlice *s = m_slices.at(i); | ||||
QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s); | ||||
if (forced || d->m_data.m_slicePen.isThemed()) | ||||
d->setPen(penColor, true); | ||||
if (forced || d->m_data.m_sliceBrush.isThemed()) | ||||
d->setBrush(brushColor, true); | ||||
if (forced || d->m_data.m_labelBrush.isThemed()) | ||||
d->setLabelBrush(theme->labelBrush().color(), true); | ||||
if (forced || d->m_data.m_labelFont.isThemed()) | ||||
d->setLabelFont(theme->labelFont(), true); | ||||
} | ||||
} | ||||
|
r142 | #include "moc_qpieseries.cpp" | ||
|
r938 | #include "moc_qpieseries_p.cpp" | ||
|
r142 | |||
|
r2712 | QT_CHARTS_END_NAMESPACE | ||