qpieseries.cpp
308 lines
| 6.6 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r142 | #include "qpieseries.h" | ||
Jani Honkonen
|
r203 | #include "qpieslice.h" | ||
Jani Honkonen
|
r146 | #include "piepresenter.h" | ||
Jani Honkonen
|
r142 | #include "pieslice.h" | ||
Jani Honkonen
|
r289 | #include <QFontMetrics> | ||
Jani Honkonen
|
r142 | #include <QDebug> | ||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
Jani Honkonen
|
r203 | void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | if (!m_added.contains(slice)) | ||
m_added << slice; | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r289 | void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices) | ||
{ | ||||
foreach (QPieSlice* s, slices) | ||||
appendAdded(s); | ||||
} | ||||
Jani Honkonen
|
r203 | void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | if (!m_changed.contains(slice)) | ||
m_changed << slice; | ||||
} | ||||
Jani Honkonen
|
r142 | |||
Jani Honkonen
|
r203 | void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice) | ||
{ | ||||
if (!m_removed.contains(slice)) | ||||
m_removed << slice; | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | QList<QPieSlice*> QPieSeries::ChangeSet::added() const | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | return m_added; | ||
Jani Honkonen
|
r163 | } | ||
Jani Honkonen
|
r203 | QList<QPieSlice*> QPieSeries::ChangeSet::changed() const | ||
Jani Honkonen
|
r163 | { | ||
Jani Honkonen
|
r203 | return m_changed; | ||
} | ||||
Jani Honkonen
|
r163 | |||
Jani Honkonen
|
r203 | QList<QPieSlice*> QPieSeries::ChangeSet::removed() const | ||
{ | ||||
return m_removed; | ||||
} | ||||
Jani Honkonen
|
r157 | |||
Jani Honkonen
|
r203 | bool QPieSeries::ChangeSet::isEmpty() const | ||
{ | ||||
if (m_added.count() || m_changed.count() || m_removed.count()) | ||||
return false; | ||||
return true; | ||||
} | ||||
Jani Honkonen
|
r157 | |||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r203 | QPieSeries::QPieSeries(QObject *parent) : | ||
QChartSeries(parent), | ||||
m_sizeFactor(1.0), | ||||
m_position(PiePositionMaximized), | ||||
m_pieStartAngle(0), | ||||
m_pieSpan(360) | ||||
{ | ||||
Jani Honkonen
|
r157 | |||
Jani Honkonen
|
r203 | } | ||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r203 | QPieSeries::~QPieSeries() | ||
{ | ||||
Jani Honkonen
|
r204 | |||
Jani Honkonen
|
r203 | } | ||
bool QPieSeries::setData(QList<qreal> data) | ||||
{ | ||||
// TODO: remove this function | ||||
QList<QPieSlice*> slices; | ||||
Tero Ahola
|
r278 | foreach (qreal value, data) | ||
Jani Honkonen
|
r203 | slices << new QPieSlice(value, QString::number(value)); | ||
set(slices); | ||||
Jani Honkonen
|
r163 | return true; | ||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | void QPieSeries::set(QList<QPieSlice*> slices) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | clear(); | ||
add(slices); | ||||
} | ||||
Jani Honkonen
|
r163 | |||
Jani Honkonen
|
r203 | void QPieSeries::add(QList<QPieSlice*> slices) | ||
{ | ||||
Jani Honkonen
|
r174 | ChangeSet changeSet; | ||
Jani Honkonen
|
r203 | foreach (QPieSlice* s, slices) { | ||
s->setParent(this); | ||||
m_slices << s; | ||||
changeSet.appendAdded(s); | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r157 | |||
Jani Honkonen
|
r174 | updateDerivativeData(); | ||
Jani Honkonen
|
r203 | 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); | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | void QPieSeries::add(QPieSlice* slice) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | add(QList<QPieSlice*>() << slice); | ||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | QPieSlice* QPieSeries::add(qreal value, QString name) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | QPieSlice* slice = new QPieSlice(value, name); | ||
add(slice); | ||||
return slice; | ||||
} | ||||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r203 | void QPieSeries::remove(QPieSlice* slice) | ||
{ | ||||
if (!m_slices.removeOne(slice)) { | ||||
Jani Honkonen
|
r289 | Q_ASSERT(0); // TODO: how should this be reported? | ||
Jani Honkonen
|
r203 | return; | ||
} | ||||
Jani Honkonen
|
r174 | |||
ChangeSet changeSet; | ||||
Jani Honkonen
|
r203 | changeSet.appendRemoved(slice); | ||
Jani Honkonen
|
r174 | emit changed(changeSet); | ||
Jani Honkonen
|
r203 | delete slice; | ||
slice = NULL; | ||||
updateDerivativeData(); | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | void QPieSeries::clear() | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r203 | if (m_slices.count() == 0) | ||
return; | ||||
Jani Honkonen
|
r174 | |||
ChangeSet changeSet; | ||||
Jani Honkonen
|
r203 | foreach (QPieSlice* s, m_slices) { | ||
changeSet.appendRemoved(s); | ||||
m_slices.removeOne(s); | ||||
delete s; | ||||
} | ||||
Jani Honkonen
|
r174 | emit changed(changeSet); | ||
Jani Honkonen
|
r203 | updateDerivativeData(); | ||
Jani Honkonen
|
r142 | } | ||
void QPieSeries::setSizeFactor(qreal factor) | ||||
{ | ||||
Jani Honkonen
|
r163 | if (factor < 0.0) | ||
return; | ||||
if (m_sizeFactor != factor) { | ||||
Jani Honkonen
|
r142 | m_sizeFactor = factor; | ||
Jani Honkonen
|
r163 | emit sizeFactorChanged(); | ||
} | ||||
Jani Honkonen
|
r142 | } | ||
void QPieSeries::setPosition(PiePosition position) | ||||
{ | ||||
Jani Honkonen
|
r163 | if (m_position != position) { | ||
m_position = position; | ||||
emit positionChanged(); | ||||
} | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r203 | 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() | ||||
Jani Honkonen
|
r174 | { | ||
Jani Honkonen
|
r203 | 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); | ||||
Jani Honkonen
|
r294 | slice->setLabelVisible(true); | ||
Jani Honkonen
|
r203 | } | ||
void QPieSeries::highlightOff(QPieSlice* slice) | ||||
{ | ||||
Q_ASSERT(slice); | ||||
QColor c = slice->brush().color().darker(150); | ||||
slice->setBrush(c); | ||||
Jani Honkonen
|
r294 | slice->setLabelVisible(false); | ||
Jani Honkonen
|
r174 | } | ||
void QPieSeries::updateDerivativeData() | ||||
{ | ||||
m_total = 0; | ||||
Jani Honkonen
|
r203 | // 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 | ||||
Jani Honkonen
|
r289 | Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this? | ||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r203 | // 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; | ||||
Jani Honkonen
|
r289 | if (s->m_angleSpan != sliceSpan) { | ||
s->m_angleSpan = sliceSpan; | ||||
Jani Honkonen
|
r203 | changed = true; | ||
} | ||||
if (s->m_angle != sliceAngle) { | ||||
s->m_angle = sliceAngle; | ||||
changed = true; | ||||
} | ||||
sliceAngle += sliceSpan; | ||||
if (changed) | ||||
emit s->changed(); | ||||
} | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r142 | #include "moc_qpieseries.cpp" | ||
QTCOMMERCIALCHART_END_NAMESPACE | ||||