##// END OF EJS Templates
Documentation for bar charts
Documentation for bar charts

File last commit:

r294:bf1f84426ed8
r313:625c56c7d323
Show More
qpieseries.cpp
308 lines | 6.6 KiB | text/x-c | CppLexer
#include "qpieseries.h"
#include "qpieslice.h"
#include "piepresenter.h"
#include "pieslice.h"
#include <QFontMetrics>
#include <QDebug>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
{
if (!m_added.contains(slice))
m_added << slice;
}
void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices)
{
foreach (QPieSlice* s, slices)
appendAdded(s);
}
void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
{
if (!m_changed.contains(slice))
m_changed << slice;
}
void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
{
if (!m_removed.contains(slice))
m_removed << slice;
}
QList<QPieSlice*> QPieSeries::ChangeSet::added() const
{
return m_added;
}
QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
{
return m_changed;
}
QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
{
return m_removed;
}
bool QPieSeries::ChangeSet::isEmpty() const
{
if (m_added.count() || m_changed.count() || m_removed.count())
return false;
return true;
}
QPieSeries::QPieSeries(QObject *parent) :
QChartSeries(parent),
m_sizeFactor(1.0),
m_position(PiePositionMaximized),
m_pieStartAngle(0),
m_pieSpan(360)
{
}
QPieSeries::~QPieSeries()
{
}
bool QPieSeries::setData(QList<qreal> data)
{
// TODO: remove this function
QList<QPieSlice*> slices;
foreach (qreal value, data)
slices << new QPieSlice(value, QString::number(value));
set(slices);
return true;
}
void QPieSeries::set(QList<QPieSlice*> slices)
{
clear();
add(slices);
}
void QPieSeries::add(QList<QPieSlice*> slices)
{
ChangeSet changeSet;
foreach (QPieSlice* s, slices) {
s->setParent(this);
m_slices << s;
changeSet.appendAdded(s);
}
updateDerivativeData();
foreach (QPieSlice* s, slices) {
connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
}
emit changed(changeSet);
}
void QPieSeries::add(QPieSlice* slice)
{
add(QList<QPieSlice*>() << slice);
}
QPieSlice* QPieSeries::add(qreal value, QString name)
{
QPieSlice* slice = new QPieSlice(value, name);
add(slice);
return slice;
}
void QPieSeries::remove(QPieSlice* slice)
{
if (!m_slices.removeOne(slice)) {
Q_ASSERT(0); // TODO: how should this be reported?
return;
}
ChangeSet changeSet;
changeSet.appendRemoved(slice);
emit changed(changeSet);
delete slice;
slice = NULL;
updateDerivativeData();
}
void QPieSeries::clear()
{
if (m_slices.count() == 0)
return;
ChangeSet changeSet;
foreach (QPieSlice* s, m_slices) {
changeSet.appendRemoved(s);
m_slices.removeOne(s);
delete s;
}
emit changed(changeSet);
updateDerivativeData();
}
void QPieSeries::setSizeFactor(qreal factor)
{
if (factor < 0.0)
return;
if (m_sizeFactor != factor) {
m_sizeFactor = factor;
emit sizeFactorChanged();
}
}
void QPieSeries::setPosition(PiePosition position)
{
if (m_position != position) {
m_position = position;
emit positionChanged();
}
}
void QPieSeries::setSpan(qreal startAngle, qreal span)
{
if (startAngle >= 0 && startAngle < 360 &&
span > 0 && span <= 360) {
m_pieStartAngle = startAngle;
m_pieSpan = span;
updateDerivativeData();
}
}
void QPieSeries::setLabelsVisible(bool visible)
{
foreach (QPieSlice* s, m_slices)
s->setLabelVisible(visible);
}
void QPieSeries::enableClickExplodes(bool enable)
{
if (enable)
connect(this, SIGNAL(clicked(QPieSlice*)), this, SLOT(toggleExploded(QPieSlice*)));
else
disconnect(this, SLOT(toggleExploded(QPieSlice*)));
}
void QPieSeries::enableHoverHighlight(bool enable)
{
if (enable) {
connect(this, SIGNAL(hoverEnter(QPieSlice*)), this, SLOT(highlightOn(QPieSlice*)));
connect(this, SIGNAL(hoverLeave(QPieSlice*)), this, SLOT(highlightOff(QPieSlice*)));
} else {
disconnect(this, SLOT(hoverEnter(QPieSlice*)));
disconnect(this, SLOT(hoverLeave(QPieSlice*)));
}
}
void QPieSeries::sliceChanged()
{
QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
Q_ASSERT(m_slices.contains(slice));
ChangeSet changeSet;
changeSet.appendChanged(slice);
emit changed(changeSet);
updateDerivativeData();
}
void QPieSeries::sliceClicked()
{
QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
Q_ASSERT(m_slices.contains(slice));
emit clicked(slice);
}
void QPieSeries::sliceHoverEnter()
{
QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
Q_ASSERT(m_slices.contains(slice));
emit hoverEnter(slice);
}
void QPieSeries::sliceHoverLeave()
{
QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
Q_ASSERT(m_slices.contains(slice));
emit hoverLeave(slice);
}
void QPieSeries::toggleExploded(QPieSlice* slice)
{
Q_ASSERT(slice);
slice->setExploded(!slice->isExploded());
}
void QPieSeries::highlightOn(QPieSlice* slice)
{
Q_ASSERT(slice);
QColor c = slice->brush().color().lighter();
slice->setBrush(c);
slice->setLabelVisible(true);
}
void QPieSeries::highlightOff(QPieSlice* slice)
{
Q_ASSERT(slice);
QColor c = slice->brush().color().darker(150);
slice->setBrush(c);
slice->setLabelVisible(false);
}
void QPieSeries::updateDerivativeData()
{
m_total = 0;
// nothing to do?
if (m_slices.count() == 0)
return;
// calculate total
foreach (QPieSlice* s, m_slices)
m_total += s->value();
// we must have some values
Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
// update slice attributes
qreal sliceAngle = m_pieStartAngle;
foreach (QPieSlice* s, m_slices) {
bool changed = false;
qreal percentage = s->value() / m_total;
if (s->m_percentage != percentage) {
s->m_percentage = percentage;
changed = true;
}
qreal sliceSpan = m_pieSpan * percentage;
if (s->m_angleSpan != sliceSpan) {
s->m_angleSpan = sliceSpan;
changed = true;
}
if (s->m_angle != sliceAngle) {
s->m_angle = sliceAngle;
changed = true;
}
sliceAngle += sliceSpan;
if (changed)
emit s->changed();
}
}
#include "moc_qpieseries.cpp"
QTCOMMERCIALCHART_END_NAMESPACE