piechartitem.cpp
185 lines
| 5.1 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r568 | #include "piechartitem_p.h" | ||
Jani Honkonen
|
r353 | #include "pieslice_p.h" | ||
Jani Honkonen
|
r203 | #include "qpieslice.h" | ||
Jani Honkonen
|
r289 | #include "qpieseries.h" | ||
Tero Ahola
|
r490 | #include "chartpresenter_p.h" | ||
Jani Honkonen
|
r618 | #include "chartanimator_p.h" | ||
Jani Honkonen
|
r142 | #include <QDebug> | ||
Jani Honkonen
|
r437 | #include <QPainter> | ||
Jani Honkonen
|
r289 | |||
Jani Honkonen
|
r142 | |||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
Jani Honkonen
|
r568 | PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series) | ||
Jani Honkonen
|
r174 | :ChartItem(parent), | ||
m_series(series) | ||||
Jani Honkonen
|
r142 | { | ||
Q_ASSERT(series); | ||||
Jani Honkonen
|
r566 | connect(series, SIGNAL(changed()), this, SLOT(handleSeriesChanged())); | ||
Tero Ahola
|
r490 | |||
// Note: the following does not affect as long as the item does not have anything to paint | ||||
setZValue(ChartPresenter::PieSeriesZValue); | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r568 | PieChartItem::~PieChartItem() | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r174 | // slices deleted automatically through QGraphicsItem | ||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r568 | void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) | ||
Jani Honkonen
|
r142 | { | ||
Tero Ahola
|
r611 | Q_UNUSED(painter) | ||
Jani Honkonen
|
r174 | // TODO: paint shadows for all components | ||
// - get paths from items & merge & offset and draw with shadow color? | ||||
Jani Honkonen
|
r437 | //painter->setBrush(QBrush(Qt::red)); | ||
//painter->drawRect(m_debugRect); | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r568 | void PieChartItem::handleSeriesChanged() | ||
Jani Honkonen
|
r174 | { | ||
Jani Honkonen
|
r618 | QVector<PieSliceLayout> layout = calculateLayout(); | ||
applyLayout(layout); | ||||
Jani Honkonen
|
r566 | update(); | ||
} | ||||
Jani Honkonen
|
r142 | |||
Jani Honkonen
|
r568 | void PieChartItem::handleSliceChanged() | ||
Jani Honkonen
|
r566 | { | ||
Jani Honkonen
|
r618 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); | ||
Q_ASSERT(m_slices.contains(slice)); | ||||
//qDebug() << "PieChartItem::handleSliceChanged" << slice->label(); | ||||
// TODO: Optimize. No need to calculate everything. | ||||
QVector<PieSliceLayout> layout = calculateLayout(); | ||||
foreach (PieSliceLayout sl, layout) { | ||||
if (sl.m_data == slice) | ||||
updateLayout(sl); | ||||
} | ||||
Jani Honkonen
|
r566 | update(); | ||
Jani Honkonen
|
r203 | } | ||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r568 | void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal) | ||
Jani Honkonen
|
r203 | { | ||
// TODO | ||||
} | ||||
Jani Honkonen
|
r568 | void PieChartItem::handleGeometryChanged(const QRectF& rect) | ||
Jani Honkonen
|
r203 | { | ||
Jani Honkonen
|
r289 | prepareGeometryChange(); | ||
Jani Honkonen
|
r566 | m_rect = rect; | ||
QVector<PieSliceLayout> sliceLayout = calculateLayout(); | ||||
applyLayout(sliceLayout); | ||||
update(); | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r157 | |||
Jani Honkonen
|
r568 | QVector<PieSliceLayout> PieChartItem::calculateLayout() | ||
Jani Honkonen
|
r566 | { | ||
Jani Honkonen
|
r454 | // find pie center coordinates | ||
QPointF center; | ||||
Jani Honkonen
|
r498 | center.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition())); | ||
center.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition())); | ||||
Jani Honkonen
|
r437 | |||
Jani Honkonen
|
r454 | // find maximum radius for pie | ||
qreal radius = m_rect.height() / 2; | ||||
if (m_rect.width() < m_rect.height()) | ||||
radius = m_rect.width() / 2; | ||||
Jani Honkonen
|
r437 | |||
Jani Honkonen
|
r454 | // apply size factor | ||
Jani Honkonen
|
r498 | radius *= m_series->pieSize(); | ||
Jani Honkonen
|
r437 | |||
Jani Honkonen
|
r566 | QVector<PieSliceLayout> layout; | ||
foreach (QPieSlice* s, m_series->slices()) { | ||||
PieSliceLayout sliceLayout; | ||||
sliceLayout.m_data = s; | ||||
sliceLayout.m_center = PieSlice::sliceCenter(center, radius, s); | ||||
sliceLayout.m_radius = radius; | ||||
sliceLayout.m_startAngle = s->startAngle(); | ||||
sliceLayout.m_angleSpan = s->m_angleSpan; | ||||
layout << sliceLayout; | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r437 | |||
Jani Honkonen
|
r566 | return layout; | ||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r618 | void PieChartItem::applyLayout(QVector<PieSliceLayout> &layout) | ||
Jani Honkonen
|
r142 | { | ||
Jani Honkonen
|
r618 | if (m_animator) | ||
m_animator->applyLayout(this, layout); | ||||
else | ||||
setLayout(layout); | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r618 | void PieChartItem::updateLayout(PieSliceLayout &layout) | ||
{ | ||||
if (m_animator) | ||||
m_animator->updateLayout(this, layout); | ||||
else | ||||
setLayout(layout); | ||||
} | ||||
void PieChartItem::setLayout(QVector<PieSliceLayout> &layout) | ||||
Jani Honkonen
|
r289 | { | ||
Jani Honkonen
|
r566 | foreach (PieSliceLayout l, layout) { | ||
// find slice | ||||
PieSlice *slice = m_slices.value(l.m_data); | ||||
if (!slice) { | ||||
// add a new slice | ||||
slice = new PieSlice(this); | ||||
m_slices.insert(l.m_data, slice); | ||||
// connect signals | ||||
connect(l.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | ||||
connect(slice, SIGNAL(clicked()), l.m_data, SIGNAL(clicked())); | ||||
connect(slice, SIGNAL(hoverEnter()), l.m_data, SIGNAL(hoverEnter())); | ||||
connect(slice, SIGNAL(hoverLeave()), l.m_data, SIGNAL(hoverLeave())); | ||||
} | ||||
Jani Honkonen
|
r289 | |||
Jani Honkonen
|
r566 | // update | ||
slice->setLayout(l); | ||||
slice->updateGeometry(); | ||||
slice->update(); | ||||
Jani Honkonen
|
r289 | } | ||
Jani Honkonen
|
r566 | // delete slices | ||
foreach (QPieSlice *s, m_slices.keys()) { | ||||
Jani Honkonen
|
r289 | |||
Jani Honkonen
|
r566 | bool found = false; | ||
foreach (PieSliceLayout l, layout) { | ||||
if (l.m_data == s) | ||||
found = true; | ||||
} | ||||
Jani Honkonen
|
r174 | |||
Jani Honkonen
|
r566 | if (!found) | ||
Jani Honkonen
|
r618 | destroySlice(s); | ||
} | ||||
} | ||||
void PieChartItem::setLayout(PieSliceLayout &layout) | ||||
{ | ||||
// find slice | ||||
PieSlice *slice = m_slices.value(layout.m_data); | ||||
if (!slice) { | ||||
slice = new PieSlice(this); | ||||
m_slices.insert(layout.m_data, slice); | ||||
connect(layout.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | ||||
connect(slice, SIGNAL(clicked()), layout.m_data, SIGNAL(clicked())); | ||||
connect(slice, SIGNAL(hoverEnter()), layout.m_data, SIGNAL(hoverEnter())); | ||||
connect(slice, SIGNAL(hoverLeave()), layout.m_data, SIGNAL(hoverLeave())); | ||||
Jani Honkonen
|
r174 | } | ||
Jani Honkonen
|
r618 | slice->setLayout(layout); | ||
if (m_series->m_slices.contains(layout.m_data)) // Slice has been deleted if not found. Animations ongoing... | ||||
slice->updateData(layout.m_data); | ||||
slice->updateGeometry(); | ||||
slice->update(); | ||||
} | ||||
void PieChartItem::destroySlice(QPieSlice *slice) | ||||
{ | ||||
delete m_slices.take(slice); | ||||
Jani Honkonen
|
r142 | } | ||
Jani Honkonen
|
r568 | #include "moc_piechartitem_p.cpp" | ||
Jani Honkonen
|
r142 | |||
QTCOMMERCIALCHART_END_NAMESPACE | ||||