#include "piechartitem_p.h" #include "piesliceitem_p.h" #include "qpieslice.h" #include "qpiesliceprivate_p.h" #include "qpieseries.h" #include "chartpresenter_p.h" #include "chartdataset_p.h" #include "chartanimator_p.h" #include #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter) :ChartItem(presenter), m_series(series) { Q_ASSERT(series); connect(series, SIGNAL(added(QList)), this, SLOT(handleSlicesAdded(QList))); connect(series, SIGNAL(removed(QList)), this, SLOT(handleSlicesRemoved(QList))); connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged())); connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged())); QTimer::singleShot(0, this, SLOT(initialize())); // Note: the following does not affect as long as the item does not have anything to paint setZValue(ChartPresenter::PieSeriesZValue); } PieChartItem::~PieChartItem() { // slices deleted automatically through QGraphicsItem } void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { Q_UNUSED(painter) // TODO: paint shadows for all components // - get paths from items & merge & offset and draw with shadow color? //painter->setBrush(QBrush(Qt::red)); //painter->drawRect(m_debugRect); } void PieChartItem::initialize() { handleSlicesAdded(m_series->slices()); } void PieChartItem::handleSlicesAdded(QList slices) { bool isEmpty = m_slices.isEmpty(); presenter()->theme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false); foreach (QPieSlice *s, slices) { PieSliceItem* item = new PieSliceItem(this); m_slices.insert(s, item); connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged())); connect(item, SIGNAL(clicked()), s, SIGNAL(clicked())); connect(item, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter())); connect(item, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave())); PieSliceData data = sliceData(s); if (animator()) animator()->addAnimation(this, s, data, isEmpty); else setLayout(s, data); } } void PieChartItem::handleSlicesRemoved(QList slices) { presenter()->theme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false); foreach (QPieSlice *s, slices) { if (animator()) animator()->removeAnimation(this, s); else destroySlice(s); } } void PieChartItem::handlePieLayoutChanged() { PieLayout layout = calculateLayout(); applyLayout(layout); update(); } void PieChartItem::handleSliceChanged() { QPieSlice* slice = qobject_cast(sender()); Q_ASSERT(m_slices.contains(slice)); PieSliceData data = sliceData(slice); updateLayout(slice, data); update(); } void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal) { // TODO } void PieChartItem::handleGeometryChanged(const QRectF& rect) { prepareGeometryChange(); m_rect = rect; handlePieLayoutChanged(); } void PieChartItem::calculatePieLayout() { // find pie center coordinates m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition())); m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition())); // find maximum radius for pie m_pieRadius = m_rect.height() / 2; if (m_rect.width() < m_rect.height()) m_pieRadius = m_rect.width() / 2; // apply size factor m_pieRadius *= m_series->pieSize(); } PieSliceData PieChartItem::sliceData(QPieSlice *slice) { PieSliceData sliceData = slice->data_ptr()->m_data; sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice); sliceData.m_radius = m_pieRadius; return sliceData; } PieLayout PieChartItem::calculateLayout() { calculatePieLayout(); PieLayout layout; foreach (QPieSlice* s, m_series->slices()) { if (m_slices.contains(s)) // calculate layout only for those slices that are already visible layout.insert(s, sliceData(s)); } return layout; } void PieChartItem::applyLayout(const PieLayout &layout) { if (animator()) animator()->updateLayout(this, layout); else setLayout(layout); } void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceData &sliceData) { if (animator()) animator()->updateLayout(this, slice, sliceData); else setLayout(slice, sliceData); } void PieChartItem::setLayout(const PieLayout &layout) { foreach (QPieSlice *slice, layout.keys()) { PieSliceItem *item = m_slices.value(slice); Q_ASSERT(item); item->setSliceData(layout.value(slice)); item->updateGeometry(); item->update(); } } void PieChartItem::setLayout(QPieSlice *slice, const PieSliceData &sliceData) { // find slice PieSliceItem *item = m_slices.value(slice); Q_ASSERT(item); item->setSliceData(sliceData); item->updateGeometry(); item->update(); } void PieChartItem::destroySlice(QPieSlice *slice) { delete m_slices.take(slice); } #include "moc_piechartitem_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE