areachartitem.cpp
198 lines
| 6.5 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r794 | /**************************************************************************** | ||
** | ||||
Miikka Heikkinen
|
r2432 | ** Copyright (C) 2013 Digia Plc | ||
Jani Honkonen
|
r794 | ** All rights reserved. | ||
** For any questions to Digia, please use contact form at http://qt.digia.com | ||||
** | ||||
Miikka Heikkinen
|
r2574 | ** This file is part of the Qt Enterprise Charts Add-on. | ||
Jani Honkonen
|
r794 | ** | ||
** $QT_BEGIN_LICENSE$ | ||||
Miikka Heikkinen
|
r2574 | ** Licensees holding valid Qt Enterprise licenses may use this file in | ||
** accordance with the Qt Enterprise License Agreement provided with the | ||||
Jani Honkonen
|
r794 | ** Software or, alternatively, in accordance with the terms contained in | ||
** a written agreement between you and Digia. | ||||
** | ||||
** If you have questions regarding the use of this file, please use | ||||
** contact form at http://qt.digia.com | ||||
** $QT_END_LICENSE$ | ||||
** | ||||
****************************************************************************/ | ||||
Michal Klocek
|
r421 | #include "areachartitem_p.h" | ||
#include "qareaseries.h" | ||||
Michal Klocek
|
r938 | #include "qareaseries_p.h" | ||
Michal Klocek
|
r421 | #include "qlineseries.h" | ||
Michal Klocek
|
r564 | #include "chartpresenter_p.h" | ||
Marek Rosa
|
r2275 | #include "abstractdomain_p.h" | ||
Michal Klocek
|
r421 | #include <QPainter> | ||
Michal Klocek
|
r571 | #include <QGraphicsSceneMouseEvent> | ||
Michal Klocek
|
r1241 | #include <QDebug> | ||
Michal Klocek
|
r421 | |||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
Michal Klocek
|
r2273 | AreaChartItem::AreaChartItem(QAreaSeries *areaSeries, QGraphicsItem* item) | ||
Miikka Heikkinen
|
r2439 | : ChartItem(areaSeries->d_func(),item), | ||
Jani Honkonen
|
r2097 | m_series(areaSeries), | ||
m_upper(0), | ||||
m_lower(0), | ||||
m_pointsVisible(false) | ||||
Michal Klocek
|
r421 | { | ||
Marek Rosa
|
r2264 | setAcceptHoverEvents(true); | ||
Michal Klocek
|
r564 | setZValue(ChartPresenter::LineChartZValue); | ||
Titta Heikkala
|
r2601 | if (m_series->upperSeries()) | ||
m_upper = new AreaBoundItem(this, m_series->upperSeries()); | ||||
Jani Honkonen
|
r2097 | if (m_series->lowerSeries()) | ||
Michal Klocek
|
r2273 | m_lower = new AreaBoundItem(this, m_series->lowerSeries()); | ||
Michal Klocek
|
r421 | |||
Jani Honkonen
|
r2097 | QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated())); | ||
Tero Ahola
|
r1342 | QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated())); | ||
Tero Ahola
|
r2067 | QObject::connect(m_series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated())); | ||
Jani Honkonen
|
r2097 | QObject::connect(this, SIGNAL(clicked(QPointF)), areaSeries, SIGNAL(clicked(QPointF))); | ||
Marek Rosa
|
r2264 | QObject::connect(this, SIGNAL(hovered(QPointF,bool)), areaSeries, SIGNAL(hovered(QPointF,bool))); | ||
Michal Klocek
|
r421 | |||
handleUpdated(); | ||||
} | ||||
AreaChartItem::~AreaChartItem() | ||||
{ | ||||
delete m_upper; | ||||
delete m_lower; | ||||
Tero Ahola
|
r761 | } | ||
Michal Klocek
|
r421 | |||
Michal Klocek
|
r2273 | void AreaChartItem::setPresenter(ChartPresenter *presenter) | ||
{ | ||||
Titta Heikkala
|
r2601 | if (m_upper) | ||
m_upper->setPresenter(presenter); | ||||
Michal Klocek
|
r2273 | if (m_lower) { | ||
m_lower->setPresenter(presenter); | ||||
} | ||||
ChartItem::setPresenter(presenter); | ||||
} | ||||
Michal Klocek
|
r421 | QRectF AreaChartItem::boundingRect() const | ||
{ | ||||
return m_rect; | ||||
} | ||||
QPainterPath AreaChartItem::shape() const | ||||
{ | ||||
return m_path; | ||||
} | ||||
void AreaChartItem::updatePath() | ||||
{ | ||||
QPainterPath path; | ||||
Michal Klocek
|
r2273 | QRectF rect(QPointF(0,0),domain()->size()); | ||
Michal Klocek
|
r421 | |||
Tero Ahola
|
r1792 | path = m_upper->path(); | ||
Michal Klocek
|
r690 | |||
sauimone
|
r743 | if (m_lower) { | ||
Miikka Heikkinen
|
r2483 | // Note: Polarcharts always draw area correctly only when both series have equal width or are | ||
// fully displayed. If one series is partally off-chart, the connecting line between | ||||
// the series does not attach to the end of the partially hidden series but to the point | ||||
// where it intersects the axis line. The problem is especially noticeable when one of the series | ||||
// is entirely off-chart, in which case the connecting line connects two ends of the | ||||
// visible series. | ||||
// This happens because we get the paths from linechart, which omits off-chart segments. | ||||
// To properly fix, linechart would need to provide true full path, in right, left, and the rest | ||||
// portions to enable proper clipping. However, combining those to single visually unified area | ||||
// would be a nightmare, since they would have to be painted separately. | ||||
Tero Ahola
|
r1792 | path.connectPath(m_lower->path().toReversed()); | ||
sauimone
|
r743 | } else { | ||
Michal Klocek
|
r421 | QPointF first = path.pointAtPercent(0); | ||
QPointF last = path.pointAtPercent(1); | ||||
Miikka Heikkinen
|
r2483 | if (presenter()->chartType() == QChart::ChartTypeCartesian) { | ||
path.lineTo(last.x(), rect.bottom()); | ||||
path.lineTo(first.x(), rect.bottom()); | ||||
} else { // polar | ||||
path.lineTo(rect.center()); | ||||
} | ||||
Michal Klocek
|
r421 | } | ||
path.closeSubpath(); | ||||
Titta Heikkala
|
r2603 | |||
// Only zoom in if the bounding rect of the path fits inside int limits. QWidget::update() uses | ||||
// a region that has to be compatible with QRect. | ||||
if (path.boundingRect().height() <= INT_MAX | ||||
&& path.boundingRect().width() <= INT_MAX) { | ||||
prepareGeometryChange(); | ||||
m_path = path; | ||||
m_rect = path.boundingRect(); | ||||
update(); | ||||
} | ||||
Michal Klocek
|
r421 | } | ||
void AreaChartItem::handleUpdated() | ||||
{ | ||||
Tero Ahola
|
r1346 | setVisible(m_series->isVisible()); | ||
Michal Klocek
|
r563 | m_pointsVisible = m_series->pointsVisible(); | ||
m_linePen = m_series->pen(); | ||||
Michal Klocek
|
r557 | m_brush = m_series->brush(); | ||
Michal Klocek
|
r563 | m_pointPen = m_series->pen(); | ||
Tero Ahola
|
r761 | m_pointPen.setWidthF(2 * m_pointPen.width()); | ||
Tero Ahola
|
r2067 | setOpacity(m_series->opacity()); | ||
Michal Klocek
|
r421 | update(); | ||
} | ||||
Michal Klocek
|
r1698 | void AreaChartItem::handleDomainUpdated() | ||
Michal Klocek
|
r421 | { | ||
Titta Heikkala
|
r2601 | if (m_upper) { | ||
AbstractDomain* d = m_upper->domain(); | ||||
d->setSize(domain()->size()); | ||||
d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY()); | ||||
m_upper->handleDomainUpdated(); | ||||
} | ||||
Michal Klocek
|
r2273 | |||
Jani Honkonen
|
r2097 | if (m_lower) { | ||
Michal Klocek
|
r2285 | AbstractDomain* d = m_lower->domain(); | ||
Michal Klocek
|
r2273 | d->setSize(domain()->size()); | ||
d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY()); | ||||
m_lower->handleDomainUpdated(); | ||||
Michal Klocek
|
r1698 | } | ||
Michal Klocek
|
r421 | } | ||
void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | ||||
{ | ||||
Tero Ahola
|
r611 | Q_UNUSED(widget) | ||
Q_UNUSED(option) | ||||
Tero Ahola
|
r1346 | painter->save(); | ||
painter->setPen(m_linePen); | ||||
painter->setBrush(m_brush); | ||||
Miikka Heikkinen
|
r2483 | QRectF clipRect = QRectF(QPointF(0, 0), domain()->size()); | ||
if (presenter()->chartType() == QChart::ChartTypePolar) | ||||
painter->setClipRegion(QRegion(clipRect.toRect(), QRegion::Ellipse)); | ||||
else | ||||
painter->setClipRect(clipRect); | ||||
Tero Ahola
|
r1346 | painter->drawPath(m_path); | ||
if (m_pointsVisible) { | ||||
Jani Honkonen
|
r2097 | painter->setPen(m_pointPen); | ||
painter->drawPoints(m_upper->geometryPoints()); | ||||
if (m_lower) | ||||
painter->drawPoints(m_lower->geometryPoints()); | ||||
Michal Klocek
|
r563 | } | ||
Tero Ahola
|
r1346 | painter->restore(); | ||
Michal Klocek
|
r421 | } | ||
sauimone
|
r743 | void AreaChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event) | ||
Michal Klocek
|
r571 | { | ||
Michal Klocek
|
r2273 | emit clicked(m_upper->domain()->calculateDomainPoint(event->pos())); | ||
Michal Klocek
|
r1747 | ChartItem::mousePressEvent(event); | ||
Michal Klocek
|
r571 | } | ||
Marek Rosa
|
r2264 | void AreaChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) | ||
{ | ||||
Michal Klocek
|
r2273 | emit hovered(domain()->calculateDomainPoint(event->pos()), true); | ||
Marek Rosa
|
r2264 | event->accept(); | ||
// QGraphicsItem::hoverEnterEvent(event); | ||||
} | ||||
void AreaChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) | ||||
{ | ||||
Michal Klocek
|
r2273 | emit hovered(domain()->calculateDomainPoint(event->pos()), false); | ||
Marek Rosa
|
r2264 | event->accept(); | ||
// QGraphicsItem::hoverEnterEvent(event); | ||||
} | ||||
Michal Klocek
|
r421 | #include "moc_areachartitem_p.cpp" | ||
QTCOMMERCIALCHART_END_NAMESPACE | ||||