piechartitem.cpp
198 lines
| 5.6 KiB
| text/x-c
|
CppLexer
|
r568 | #include "piechartitem_p.h" | ||
|
r353 | #include "pieslice_p.h" | ||
|
r203 | #include "qpieslice.h" | ||
|
r289 | #include "qpieseries.h" | ||
|
r490 | #include "chartpresenter_p.h" | ||
|
r659 | #include "chartdataset_p.h" | ||
|
r618 | #include "chartanimator_p.h" | ||
|
r142 | #include <QDebug> | ||
|
r437 | #include <QPainter> | ||
|
r621 | #include <QTimer> | ||
|
r142 | |||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
|
r659 | PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter *presenter, QGraphicsItem *parent) | ||
|
r174 | :ChartItem(parent), | ||
|
r659 | m_series(series), | ||
m_presenter(presenter) | ||||
|
r142 | { | ||
Q_ASSERT(series); | ||||
|
r621 | connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>))); | ||
connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>))); | ||||
connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged())); | ||||
connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged())); | ||||
QTimer::singleShot(0, this, SLOT(initialize())); | ||||
|
r490 | |||
// Note: the following does not affect as long as the item does not have anything to paint | ||||
setZValue(ChartPresenter::PieSeriesZValue); | ||||
|
r142 | } | ||
|
r568 | PieChartItem::~PieChartItem() | ||
|
r142 | { | ||
|
r174 | // slices deleted automatically through QGraphicsItem | ||
|
r142 | } | ||
|
r568 | void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) | ||
|
r142 | { | ||
|
r611 | Q_UNUSED(painter) | ||
|
r174 | // TODO: paint shadows for all components | ||
// - get paths from items & merge & offset and draw with shadow color? | ||||
|
r437 | //painter->setBrush(QBrush(Qt::red)); | ||
//painter->drawRect(m_debugRect); | ||||
|
r174 | } | ||
|
r621 | void PieChartItem::initialize() | ||
{ | ||||
handleSlicesAdded(m_series->m_slices); | ||||
} | ||||
void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices) | ||||
{ | ||||
|
r634 | bool isEmpty = m_slices.isEmpty(); | ||
|
r659 | m_presenter->theme()->decorate(m_series, m_presenter->dataSet()->seriesIndex(m_series)); | ||
|
r621 | foreach (QPieSlice *s, slices) { | ||
PieSlice* slice = new PieSlice(this); | ||||
m_slices.insert(s, slice); | ||||
connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | ||||
connect(slice, SIGNAL(clicked()), s, SIGNAL(clicked())); | ||||
connect(slice, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter())); | ||||
connect(slice, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave())); | ||||
PieSliceLayout layout = calculateSliceLayout(s); | ||||
if (m_animator) | ||||
|
r634 | m_animator->addAnimation(this, s, layout, isEmpty); | ||
|
r621 | else | ||
|
r629 | setLayout(s, layout); | ||
|
r621 | } | ||
} | ||||
void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices) | ||||
{ | ||||
|
r659 | m_presenter->theme()->decorate(m_series, m_presenter->dataSet()->seriesIndex(m_series)); | ||
|
r621 | foreach (QPieSlice *s, slices) { | ||
if (m_animator) | ||||
m_animator->removeAnimation(this, s); | ||||
else | ||||
destroySlice(s); | ||||
} | ||||
} | ||||
void PieChartItem::handlePieLayoutChanged() | ||||
|
r174 | { | ||
|
r629 | PieLayout layout = calculateLayout(); | ||
|
r618 | applyLayout(layout); | ||
|
r566 | update(); | ||
} | ||||
|
r142 | |||
|
r568 | void PieChartItem::handleSliceChanged() | ||
|
r566 | { | ||
|
r618 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); | ||
Q_ASSERT(m_slices.contains(slice)); | ||||
|
r621 | PieSliceLayout layout = calculateSliceLayout(slice); | ||
|
r629 | updateLayout(slice, layout); | ||
|
r566 | update(); | ||
|
r203 | } | ||
|
r174 | |||
|
r568 | void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal) | ||
|
r203 | { | ||
// TODO | ||||
} | ||||
|
r568 | void PieChartItem::handleGeometryChanged(const QRectF& rect) | ||
|
r203 | { | ||
|
r289 | prepareGeometryChange(); | ||
|
r566 | m_rect = rect; | ||
|
r621 | handlePieLayoutChanged(); | ||
|
r142 | } | ||
|
r621 | void PieChartItem::calculatePieLayout() | ||
|
r566 | { | ||
|
r454 | // find pie center coordinates | ||
|
r621 | m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition())); | ||
m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition())); | ||||
|
r437 | |||
|
r454 | // find maximum radius for pie | ||
|
r621 | m_pieRadius = m_rect.height() / 2; | ||
|
r454 | if (m_rect.width() < m_rect.height()) | ||
|
r621 | m_pieRadius = m_rect.width() / 2; | ||
|
r437 | |||
|
r454 | // apply size factor | ||
|
r621 | m_pieRadius *= m_series->pieSize(); | ||
} | ||||
|
r437 | |||
|
r621 | PieSliceLayout PieChartItem::calculateSliceLayout(QPieSlice *slice) | ||
{ | ||||
PieSliceLayout sliceLayout; | ||||
sliceLayout.m_center = PieSlice::sliceCenter(m_pieCenter, m_pieRadius, slice); | ||||
sliceLayout.m_radius = m_pieRadius; | ||||
sliceLayout.m_startAngle = slice->startAngle(); | ||||
sliceLayout.m_angleSpan = slice->m_angleSpan; | ||||
|
r659 | sliceLayout.m_pen = slice->m_slicePen; | ||
sliceLayout.m_brush = slice->m_sliceBrush; | ||||
|
r621 | return sliceLayout; | ||
} | ||||
|
r629 | PieLayout PieChartItem::calculateLayout() | ||
|
r621 | { | ||
calculatePieLayout(); | ||||
|
r629 | PieLayout layout; | ||
|
r566 | foreach (QPieSlice* s, m_series->slices()) { | ||
|
r621 | if (m_slices.contains(s)) // calculate layout only for those slices that are already visible | ||
|
r629 | layout.insert(s, calculateSliceLayout(s)); | ||
|
r174 | } | ||
|
r566 | return layout; | ||
|
r142 | } | ||
|
r629 | void PieChartItem::applyLayout(const PieLayout &layout) | ||
|
r142 | { | ||
|
r618 | if (m_animator) | ||
|
r621 | m_animator->updateLayout(this, layout); | ||
|
r618 | else | ||
setLayout(layout); | ||||
|
r174 | } | ||
|
r629 | void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceLayout &layout) | ||
|
r618 | { | ||
if (m_animator) | ||||
|
r629 | m_animator->updateLayout(this, slice, layout); | ||
|
r618 | else | ||
|
r629 | setLayout(slice, layout); | ||
|
r618 | } | ||
|
r629 | void PieChartItem::setLayout(const PieLayout &layout) | ||
|
r289 | { | ||
|
r629 | foreach (QPieSlice *slice, layout.keys()) { | ||
PieSlice *s = m_slices.value(slice); | ||||
Q_ASSERT(s); | ||||
s->setLayout(layout.value(slice)); | ||||
s->updateData(slice); | ||||
s->updateGeometry(); | ||||
s->update(); | ||||
|
r289 | } | ||
|
r618 | } | ||
|
r629 | void PieChartItem::setLayout(QPieSlice *slice, const PieSliceLayout &layout) | ||
|
r618 | { | ||
// find slice | ||||
|
r629 | PieSlice *s = m_slices.value(slice); | ||
Q_ASSERT(s); | ||||
s->setLayout(layout); | ||||
if (m_series->m_slices.contains(slice)) // Slice has been deleted if not found. Animations ongoing... | ||||
s->updateData(slice); | ||||
s->updateGeometry(); | ||||
s->update(); | ||||
|
r618 | } | ||
void PieChartItem::destroySlice(QPieSlice *slice) | ||||
{ | ||||
delete m_slices.take(slice); | ||||
|
r142 | } | ||
|
r568 | #include "moc_piechartitem_p.cpp" | ||
|
r142 | |||
QTCOMMERCIALCHART_END_NAMESPACE | ||||