#include "qpieseries.h" #include "qpieslice.h" #include "piepresenter.h" #include "pieslice.h" #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice) { if (!m_added.contains(slice)) m_added << slice; } void QPieSeries::ChangeSet::appendAdded(QList 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 QPieSeries::ChangeSet::added() const { return m_added; } QList QPieSeries::ChangeSet::changed() const { return m_changed; } QList 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 data) { // TODO: remove this function QList slices; foreach (qreal value, data) slices << new QPieSlice(value, QString::number(value)); set(slices); return true; } void QPieSeries::set(QList slices) { clear(); add(slices); } void QPieSeries::add(QList 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() << 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(sender()); Q_ASSERT(m_slices.contains(slice)); ChangeSet changeSet; changeSet.appendChanged(slice); emit changed(changeSet); updateDerivativeData(); } void QPieSeries::sliceClicked() { QPieSlice* slice = qobject_cast(sender()); Q_ASSERT(m_slices.contains(slice)); emit clicked(slice); } void QPieSeries::sliceHoverEnter() { QPieSlice* slice = qobject_cast(sender()); Q_ASSERT(m_slices.contains(slice)); emit hoverEnter(slice); } void QPieSeries::sliceHoverLeave() { QPieSlice* slice = qobject_cast(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