Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include <private/boxwhiskers_p.h>
++ #include <QtGui/QPainter>
++ #include <QtWidgets/QWidget>
++ #include <QtWidgets/QGraphicsSceneMouseEvent>
++
++ QT_BEGIN_NAMESPACE
++
++ BoxWhiskers::BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent) :
++ QGraphicsObject(parent),
++ m_boxSet(set),
++ m_domain(domain),
++ m_mousePressed(false)
++ {
++ setAcceptHoverEvents(true);
++ setAcceptedMouseButtons(Qt::MouseButtonMask);
++ setFlag(QGraphicsObject::ItemIsSelectable);
++ }
++
++ BoxWhiskers::~BoxWhiskers()
++ {
++ }
++
++ void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
++ {
++ Q_UNUSED(event);
++ emit pressed(m_boxSet);
++ m_mousePressed = true;
++ }
++
++ void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
++ {
++ Q_UNUSED(event);
++ emit hovered(true, m_boxSet);
++ }
++
++ void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
++ {
++ Q_UNUSED(event);
++ emit hovered(false, m_boxSet);
++ }
++
++ void BoxWhiskers::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
++ {
++ Q_UNUSED(event);
++ emit released(m_boxSet);
++ if (m_mousePressed)
++ emit clicked(m_boxSet);
++ }
++
++ void BoxWhiskers::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
++ {
++ Q_UNUSED(event);
++ // For Box a press signal needs to be explicitly fired for mouseDoubleClickEvent
++ emit pressed(m_boxSet);
++ emit doubleClicked(m_boxSet);
++ }
++
++ void BoxWhiskers::setBrush(const QBrush &brush)
++ {
++ m_brush = brush;
++ m_outlinePen.setColor(m_brush.color());
++ update();
++ }
++
++ void BoxWhiskers::setPen(const QPen &pen)
++ {
++ qreal widthDiff = pen.widthF() - m_pen.widthF();
++ m_boundingRect.adjust(-widthDiff, -widthDiff, widthDiff, widthDiff);
++
++ m_pen = pen;
++ m_medianPen = pen;
++ m_medianPen.setCapStyle(Qt::FlatCap);
++ m_outlinePen = pen;
++ m_outlinePen.setStyle(Qt::SolidLine);
++ m_outlinePen.setColor(m_brush.color());
++
++ update();
++ }
++
++ void BoxWhiskers::setBoxWidth(const qreal width)
++ {
++ m_boxWidth = width;
++ }
++
++ void BoxWhiskers::setLayout(const BoxWhiskersData &data)
++ {
++ m_data = data;
++
++ updateGeometry(m_domain);
++ update();
++ }
++
++ QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
++ {
++ Q_UNUSED(which);
++ Q_UNUSED(constraint);
++
++ return QSizeF();
++ }
++
++ void BoxWhiskers::setGeometry(const QRectF &rect)
++ {
++ Q_UNUSED(rect);
++ }
++
++ QRectF BoxWhiskers::boundingRect() const
++ {
++ return m_boundingRect;
++ }
++
++ void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
++ {
++ Q_UNUSED(option);
++ Q_UNUSED(widget);
++
++ painter->save();
++ painter->setBrush(m_brush);
++ painter->setClipRect(parentItem()->boundingRect());
++ painter->setPen(m_pen);
++ painter->drawPath(m_boxPath);
++ if (!m_boxOutlined)
++ painter->setPen(m_outlinePen);
++ painter->drawRect(m_middleBox);
++ painter->setPen(m_medianPen);
++ qreal halfLine = m_pen.widthF() / 2.0;
++ painter->drawLine(QLineF(m_geometryLeft - halfLine, m_geometryMedian,
++ m_geometryRight + halfLine, m_geometryMedian));
++ painter->restore();
++ }
++
++ void BoxWhiskers::updateGeometry(AbstractDomain *domain)
++ {
++ m_domain = domain;
++
++ prepareGeometryChange();
++
++ QPainterPath path;
++ m_boxPath = path;
++ m_boundingRect = m_boxPath.boundingRect();
++
++ qreal columnWidth = 1.0 / m_data.m_seriesCount;
++ qreal left = ((1.0 - m_boxWidth) / 2.0) * columnWidth + columnWidth * m_data.m_seriesIndex + m_data.m_index - 0.5;
++ qreal barWidth = m_boxWidth * columnWidth;
++
++ QPointF geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_upperExtreme), m_validData);
++ if (!m_validData)
++ return;
++ m_geometryLeft = geometryPoint.x();
++ qreal geometryUpperExtreme = geometryPoint.y();
++ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left + barWidth, m_data.m_upperQuartile), m_validData);
++ if (!m_validData)
++ return;
++ m_geometryRight = geometryPoint.x();
++ qreal geometryUpperQuartile = geometryPoint.y();
++ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerQuartile), m_validData);
++ if (!m_validData)
++ return;
++ qreal geometryLowerQuartile = geometryPoint.y();
++ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerExtreme), m_validData);
++ if (!m_validData)
++ return;
++ qreal geometryLowerExtreme = geometryPoint.y();
++ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_median), m_validData);
++ if (!m_validData)
++ return;
++ m_geometryMedian = geometryPoint.y();
++
++ // Upper whisker
++ path.moveTo(m_geometryLeft, geometryUpperExtreme);
++ path.lineTo(m_geometryRight, geometryUpperExtreme);
++ path.moveTo((m_geometryLeft + m_geometryRight) / 2.0, geometryUpperExtreme);
++ path.lineTo((m_geometryLeft + m_geometryRight) / 2.0, geometryUpperQuartile);
++
++ // Middle Box
++ m_middleBox.setCoords(m_geometryLeft, geometryUpperQuartile, m_geometryRight, geometryLowerQuartile);
++
++ // Lower whisker
++ path.moveTo(m_geometryLeft, geometryLowerExtreme);
++ path.lineTo(m_geometryRight, geometryLowerExtreme);
++ path.moveTo((m_geometryLeft + m_geometryRight) / 2.0, geometryLowerQuartile);
++ path.lineTo((m_geometryLeft + m_geometryRight) / 2.0, geometryLowerExtreme);
++
++ path.closeSubpath();
++
++ m_boxPath = path;
++ m_boundingRect = m_boxPath.boundingRect();
++
++ qreal extra = m_pen.widthF();
++ m_boundingRect.adjust(-extra, -extra, extra, extra);
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_boxwhiskers_p.cpp"