piechartitem.cpp
193 lines
| 5.4 KiB
| text/x-c
|
CppLexer
|
r568 | #include "piechartitem_p.h" | ||
|
r673 | #include "piesliceitem_p.h" | ||
|
r203 | #include "qpieslice.h" | ||
|
r669 | #include "qpiesliceprivate_p.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() | ||
{ | ||||
|
r669 | handleSlicesAdded(m_series->slices()); | ||
|
r621 | } | ||
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) { | ||
|
r673 | PieSliceItem* item = new PieSliceItem(this); | ||
m_slices.insert(s, item); | ||||
|
r621 | connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | ||
|
r673 | connect(item, SIGNAL(clicked()), s, SIGNAL(clicked())); | ||
connect(item, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter())); | ||||
connect(item, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave())); | ||||
|
r621 | |||
|
r668 | PieSliceData data = sliceData(s); | ||
|
r621 | |||
if (m_animator) | ||||
|
r668 | m_animator->addAnimation(this, s, data, isEmpty); | ||
|
r621 | else | ||
|
r668 | setLayout(s, data); | ||
|
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)); | ||||
|
r668 | PieSliceData data = sliceData(slice); | ||
updateLayout(slice, data); | ||||
|
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 | |||
|
r668 | PieSliceData PieChartItem::sliceData(QPieSlice *slice) | ||
|
r621 | { | ||
|
r669 | PieSliceData sliceData = slice->d_ptr->m_data; | ||
|
r673 | sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice); | ||
|
r668 | sliceData.m_radius = m_pieRadius; | ||
|
r669 | sliceData.m_angleSpan = slice->endAngle() - slice->startAngle(); | ||
|
r668 | return sliceData; | ||
|
r621 | } | ||
|
r629 | PieLayout PieChartItem::calculateLayout() | ||
|
r621 | { | ||
calculatePieLayout(); | ||||
|
r668 | 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 | ||
|
r668 | layout.insert(s, sliceData(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 | } | ||
|
r668 | void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceData &sliceData) | ||
|
r618 | { | ||
if (m_animator) | ||||
|
r668 | m_animator->updateLayout(this, slice, sliceData); | ||
|
r618 | else | ||
|
r668 | setLayout(slice, sliceData); | ||
|
r618 | } | ||
|
r629 | void PieChartItem::setLayout(const PieLayout &layout) | ||
|
r289 | { | ||
|
r629 | foreach (QPieSlice *slice, layout.keys()) { | ||
|
r673 | PieSliceItem *item = m_slices.value(slice); | ||
Q_ASSERT(item); | ||||
item->setSliceData(layout.value(slice)); | ||||
item->updateGeometry(); | ||||
item->update(); | ||||
|
r289 | } | ||
|
r618 | } | ||
|
r668 | void PieChartItem::setLayout(QPieSlice *slice, const PieSliceData &sliceData) | ||
|
r618 | { | ||
// find slice | ||||
|
r673 | PieSliceItem *item = m_slices.value(slice); | ||
Q_ASSERT(item); | ||||
item->setSliceData(sliceData); | ||||
item->updateGeometry(); | ||||
item->update(); | ||||
|
r618 | } | ||
void PieChartItem::destroySlice(QPieSlice *slice) | ||||
{ | ||||
delete m_slices.take(slice); | ||||
|
r142 | } | ||
|
r568 | #include "moc_piechartitem_p.cpp" | ||
|
r142 | |||
QTCOMMERCIALCHART_END_NAMESPACE | ||||