scatterchartitem.cpp
206 lines
| 5.7 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r794 | /**************************************************************************** | ||
Michal Klocek
|
r1218 | ** | ||
** Copyright (C) 2012 Digia Plc | ||||
** All rights reserved. | ||||
** For any questions to Digia, please use contact form at http://qt.digia.com | ||||
** | ||||
** This file is part of the Qt Commercial Charts Add-on. | ||||
** | ||||
** $QT_BEGIN_LICENSE$ | ||||
** Licensees holding valid Qt Commercial licenses may use this file in | ||||
** accordance with the Qt Commercial License Agreement provided with the | ||||
** 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$ | ||||
** | ||||
****************************************************************************/ | ||||
Jani Honkonen
|
r794 | |||
Michal Klocek
|
r470 | #include "scatterchartitem_p.h" | ||
#include "qscatterseries.h" | ||||
Michal Klocek
|
r938 | #include "qscatterseries_p.h" | ||
Michal Klocek
|
r470 | #include "chartpresenter_p.h" | ||
#include <QPainter> | ||||
#include <QGraphicsScene> | ||||
Michal Klocek
|
r996 | #include <QDebug> | ||
Michal Klocek
|
r1218 | #include <QGraphicsSceneMouseEvent> | ||
Michal Klocek
|
r470 | |||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
Michal Klocek
|
r677 | ScatterChartItem::ScatterChartItem(QScatterSeries *series, ChartPresenter *presenter) : | ||
Tero Ahola
|
r1342 | XYChart(series,presenter), | ||
QGraphicsItem(presenter ? presenter->rootItem() : 0), | ||||
m_series(series), | ||||
m_items(this), | ||||
Tero Ahola
|
r1346 | m_visible(true), | ||
Tero Ahola
|
r1342 | m_shape(QScatterSeries::MarkerShapeRectangle), | ||
m_size(15) | ||||
Michal Klocek
|
r470 | { | ||
Michal Klocek
|
r938 | QObject::connect(m_series->d_func(),SIGNAL(updated()), this, SLOT(handleUpdated())); | ||
Tero Ahola
|
r1349 | QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated())); | ||
Michal Klocek
|
r470 | |||
setZValue(ChartPresenter::ScatterSeriesZValue); | ||||
setFlags(QGraphicsItem::ItemClipsChildrenToShape); | ||||
handleUpdated(); | ||||
Michal Klocek
|
r541 | m_items.setHandlesChildEvents(false); | ||
Michal Klocek
|
r470 | // TODO: how to draw a drop shadow? | ||
// QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect(); | ||||
// dropShadow->setOffset(2.0); | ||||
// dropShadow->setBlurRadius(2.0); | ||||
// setGraphicsEffect(dropShadow); | ||||
} | ||||
QRectF ScatterChartItem::boundingRect() const | ||||
{ | ||||
return m_rect; | ||||
} | ||||
void ScatterChartItem::createPoints(int count) | ||||
{ | ||||
for (int i = 0; i < count; ++i) { | ||||
Michal Klocek
|
r689 | QGraphicsItem *item = 0; | ||
Michal Klocek
|
r470 | |||
switch (m_shape) { | ||||
Michal Klocek
|
r1218 | case QScatterSeries::MarkerShapeCircle: { | ||
Michal Klocek
|
r1747 | QGraphicsEllipseItem* i = new QGraphicsEllipseItem(0,0,m_size,m_size,this); | ||
Michal Klocek
|
r1218 | const QRectF& rect = i->boundingRect(); | ||
i->setPos(-rect.width()/2,-rect.height()/2); | ||||
item = new Marker(i,this); | ||||
break; | ||||
} | ||||
case QScatterSeries::MarkerShapeRectangle: { | ||||
Michal Klocek
|
r1747 | QGraphicsRectItem* i = new QGraphicsRectItem(0,0,m_size,m_size,this); | ||
Michal Klocek
|
r1218 | i->setPos(-m_size/2,-m_size/2); | ||
item = new Marker(i,this); | ||||
break; | ||||
} | ||||
default: | ||||
qWarning()<<"Unsupported marker type"; | ||||
break; | ||||
Michal Klocek
|
r541 | |||
Michal Klocek
|
r470 | } | ||
m_items.addToGroup(item); | ||||
} | ||||
} | ||||
void ScatterChartItem::deletePoints(int count) | ||||
{ | ||||
QList<QGraphicsItem *> items = m_items.childItems(); | ||||
for (int i = 0; i < count; ++i) { | ||||
delete(items.takeLast()); | ||||
} | ||||
} | ||||
sauimone
|
r743 | void ScatterChartItem::markerSelected(Marker *marker) | ||
Michal Klocek
|
r470 | { | ||
Tero Ahola
|
r1410 | emit XYChart::clicked(calculateDomainPoint(marker->point())); | ||
Michal Klocek
|
r470 | } | ||
Michal Klocek
|
r1217 | void ScatterChartItem::updateGeometry() | ||
Michal Klocek
|
r470 | { | ||
Michal Klocek
|
r1217 | |||
const QVector<QPointF>& points = geometryPoints(); | ||||
Marek Rosa
|
r545 | if(points.size()==0) | ||
{ | ||||
Marek Rosa
|
r1085 | deletePoints(m_items.childItems().count()); | ||
Marek Rosa
|
r545 | return; | ||
} | ||||
Michal Klocek
|
r470 | |||
Michal Klocek
|
r869 | int diff = m_items.childItems().size() - points.size(); | ||
Michal Klocek
|
r470 | |||
if(diff>0) { | ||||
deletePoints(diff); | ||||
} | ||||
else if(diff<0) { | ||||
createPoints(-diff); | ||||
} | ||||
if(diff!=0) handleUpdated(); | ||||
QList<QGraphicsItem*> items = m_items.childItems(); | ||||
Tero Ahola
|
r847 | for (int i = 0; i < points.size(); i++) { | ||
Michal Klocek
|
r541 | Marker* item = static_cast<Marker*>(items.at(i)); | ||
Michal Klocek
|
r470 | const QPointF& point = points.at(i); | ||
Michal Klocek
|
r536 | const QRectF& rect = item->boundingRect(); | ||
Michal Klocek
|
r1057 | item->setPoint(point); | ||
Michal Klocek
|
r536 | item->setPos(point.x()-rect.width()/2,point.y()-rect.height()/2); | ||
Tero Ahola
|
r1346 | if(!m_visible || !clipRect().contains(point)) { | ||
Michal Klocek
|
r470 | item->setVisible(false); | ||
} | ||||
else { | ||||
item->setVisible(true); | ||||
} | ||||
} | ||||
prepareGeometryChange(); | ||||
m_rect = clipRect(); | ||||
Michal Klocek
|
r1218 | setPos(origin()); | ||
Michal Klocek
|
r470 | } | ||
void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | ||||
{ | ||||
Tero Ahola
|
r611 | Q_UNUSED(painter) | ||
Q_UNUSED(option) | ||||
Q_UNUSED(widget) | ||||
Michal Klocek
|
r470 | } | ||
void ScatterChartItem::setPen(const QPen& pen) | ||||
{ | ||||
foreach(QGraphicsItem* item , m_items.childItems()) { | ||||
Michal Klocek
|
r1218 | static_cast<Marker*>(item)->setPen(pen); | ||
Michal Klocek
|
r470 | } | ||
} | ||||
void ScatterChartItem::setBrush(const QBrush& brush) | ||||
{ | ||||
foreach(QGraphicsItem* item , m_items.childItems()) { | ||||
Michal Klocek
|
r1218 | static_cast<Marker*>(item)->setBrush(brush); | ||
} | ||||
Michal Klocek
|
r470 | } | ||
void ScatterChartItem::handleUpdated() | ||||
{ | ||||
int count = m_items.childItems().count(); | ||||
if(count==0) return; | ||||
Tero Ahola
|
r1346 | bool recreate = m_visible != m_series->isVisible() | ||
|| m_size != m_series->markerSize() | ||||
|| m_shape != m_series->markerShape(); | ||||
Michal Klocek
|
r470 | |||
Tero Ahola
|
r1346 | m_visible = m_series->isVisible(); | ||
Tero Ahola
|
r1276 | m_size = m_series->markerSize(); | ||
m_shape = m_series->markerShape(); | ||||
Michal Klocek
|
r470 | |||
Michal Klocek
|
r1218 | if(recreate) { | ||
Tero Ahola
|
r1276 | // TODO: optimize handleUpdate to recreate points only in case shape changed | ||
Michal Klocek
|
r470 | deletePoints(count); | ||
createPoints(count); | ||||
Tero Ahola
|
r1276 | |||
// Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points | ||||
updateGeometry(); | ||||
Michal Klocek
|
r470 | } | ||
setPen(m_series->pen()); | ||||
setBrush(m_series->brush()); | ||||
Tero Ahola
|
r1305 | update(); | ||
Michal Klocek
|
r470 | } | ||
Michal Klocek
|
r1218 | void ScatterChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event) | ||
{ | ||||
emit XYChart::clicked(calculateDomainPoint(event->pos())); | ||||
Michal Klocek
|
r1747 | QGraphicsItem::mousePressEvent(event); | ||
Michal Klocek
|
r1218 | } | ||
Michal Klocek
|
r470 | #include "moc_scatterchartitem_p.cpp" | ||
QTCOMMERCIALCHART_END_NAMESPACE | ||||