Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
++
++ #include <QtCharts/QBarCategoryAxis>
++ #include <QtCharts/QCandlestickLegendMarker>
++ #include <QtCharts/QCandlestickSeries>
++ #include <QtCharts/QCandlestickSet>
++ #include <QtCharts/QValueAxis>
++ #include <QtCore/QDateTime>
++ #include <private/candlestickanimation_p.h>
++ #include <private/candlestickchartitem_p.h>
++ #include <private/chartdataset_p.h>
++ #include <private/charttheme_p.h>
++ #include <private/qcandlestickseries_p.h>
++ #include <private/qcandlestickset_p.h>
++ #include <private/qchart_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \class QCandlestickSeries
++ \since 5.8
++ \inmodule QtCharts
++ \brief The QCandlestickSeries class presents data as candlesticks.
++
++ This class acts as a container for single candlestick items. Each item is drawn to its own category
++ when using QBarCategoryAxis. QDateTimeAxis and QValueAxis can be used as alternatives to
++ QBarCategoryAxis. In this case, each candlestick item is drawn according to its timestamp value.
++
++ \note The timestamps must be unique within a QCandlestickSeries. When using QBarCategoryAxis,
++ only the first one of the candlestick items sharing a timestamp is drawn. If the chart includes
++ multiple instances of QCandlestickSeries, items from different series sharing a timestamp are
++ drawn to the same category. When using QValueAxis or QDateTimeAxis, candlestick items sharing a
++ timestamp will overlap each other.
++
++ See the \l {Charts with Widgets Gallery} to learn how to create
++ a candlestick chart.
++ \image examples_candlestickchart.png {Candlestick chart of daily stock
++ data with green rising and red falling candles over a month}
++
++ \sa QCandlestickSet, QBarCategoryAxis, QDateTimeAxis, QValueAxis
++ */
++
++ /*!
++ \qmltype CandlestickSeries
++ \since QtCharts 2.2
++ \nativetype QCandlestickSeries
++ \inqmlmodule QtCharts
++ \inherits AbstractSeries
++ \brief Represents a series of data as candlesticks.
++
++ The CandlestickSeries type acts as a container for single candlestick items.
++ Each item is drawn to its own category
++ when using BarCategoryAxis. DateTimeAxis and ValueAxis can be used as an alternative to
++ BarCategoryAxis. In this case, each candlestick item is drawn according to its timestamp value.
++
++ \note The timestamps must be unique within a CandlestickSeries. When using BarCategoryAxis, only
++ the first one of the candlestick items sharing a timestamp is drawn. If the chart includes
++ multiple instances of CandlestickSeries, items from different series sharing a timestamp are
++ drawn to the same category. When using ValueAxis or DateTimeAxis, candlestick items sharing a
++ timestamp will overlap each other.
++
++ The following QML shows how to create a simple candlestick chart:
++ \code
++ import QtQuick 2.5
++ import QtCharts 2.2
++
++ ChartView {
++ title: "Candlestick Series"
++ width: 400
++ height: 300
++
++ CandlestickSeries {
++ name: "Acme Ltd."
++ increasingColor: "green"
++ decreasingColor: "red"
++
++ CandlestickSet { timestamp: 1435708800000; open: 690; high: 694; low: 599; close: 660 }
++ CandlestickSet { timestamp: 1435795200000; open: 669; high: 669; low: 669; close: 669 }
++ CandlestickSet { timestamp: 1436140800000; open: 485; high: 623; low: 485; close: 600 }
++ CandlestickSet { timestamp: 1436227200000; open: 589; high: 615; low: 377; close: 569 }
++ CandlestickSet { timestamp: 1436313600000; open: 464; high: 464; low: 254; close: 254 }
++ }
++ }
++ \endcode
++
++ \beginfloatleft
++ \image examples_qmlcandlestick.png {Screenshot showing a candlestick
++ series example with the x axis describing date times}
++ \endfloat
++ \clearfloat
++
++ \sa CandlestickSet, BarCategoryAxis, DateTimeAxis, ValueAxis
++ */
++
++ /*!
++ \qmlproperty AbstractAxis CandlestickSeries::axisX
++ The x-axis used for the series. If you leave both axisX and axisXTop
++ undefined, a value axis is created for the series.
++ \sa axisXTop, ValueAxis
++ */
++
++ /*!
++ \qmlproperty AbstractAxis CandlestickSeries::axisY
++ The y-axis used for the series. If you leave both axisY and axisYRight
++ undefined, a value axis is created for the series.
++ \sa axisYRight, ValueAxis
++ */
++
++ /*!
++ \qmlproperty AbstractAxis CandlestickSeries::axisXTop
++ The x-axis used for the series, drawn on top of the chart view.
++
++ \note You can only provide either axisX or axisXTop, not both.
++ \sa axisX
++ */
++
++ /*!
++ \qmlproperty AbstractAxis CandlestickSeries::axisYRight
++ The y-axis used for the series, drawn to the right on the chart view.
++
++ \note You can only provide either axisY or axisYRight, not both.
++ \sa axisY
++ */
++
++ /*!
++ \property QCandlestickSeries::count
++ \brief The number of candlestick items in a series.
++ */
++
++ /*!
++ \qmlproperty int CandlestickSeries::count
++ The number of candlestick items in a series.
++ */
++
++ /*!
++ \property QCandlestickSeries::maximumColumnWidth
++ \brief The maximum width of the candlestick items in pixels. Setting a negative value means
++ there is no maximum width. All negative values are converted to -1.0.
++ */
++
++ /*!
++ \qmlproperty real CandlestickSeries::maximumColumnWidth
++ The maximum width of the candlestick items in pixels. Setting a negative value means
++ there is no maximum width. All negative values are converted to -1.0.
++ */
++
++ /*!
++ \property QCandlestickSeries::minimumColumnWidth
++ \brief The minimum width of the candlestick items in pixels. Setting a negative value means
++ there is no minimum width. All negative values are converted to -1.0.
++ */
++
++ /*!
++ \qmlproperty real CandlestickSeries::minimumColumnWidth
++ The minimum width of the candlestick items in pixels. Setting a negative value means
++ there is no minimum width. All negative values are converted to -1.0.
++ */
++
++ /*!
++ \property QCandlestickSeries::bodyWidth
++ \brief The relative width of the candlestick item within its own slot, in the range
++ from 0.0 to 1.0.
++
++ Values outside this range are clamped to 0.0 or 1.0.
++ */
++
++ /*!
++ \qmlproperty real CandlestickSeries::bodyWidth
++ The relative width of the candlestick item within its own slot, in the range
++ from 0.0 to 1.0. Values outside this range are clamped to 0.0 or 1.0.
++ */
++
++ /*!
++ \property QCandlestickSeries::bodyOutlineVisible
++ \brief The visibility of the candlestick body outline.
++ */
++
++ /*!
++ \qmlproperty bool CandlestickSeries::bodyOutlineVisible
++ The visibility of the candlestick body outlines.
++ */
++
++ /*!
++ \property QCandlestickSeries::capsWidth
++ \brief The relative width of the caps within a candlestick, in the range from 0.0
++ to 1.0.
++
++ Values outside this range are clamped to 0.0 or 1.0.
++ */
++
++ /*!
++ \qmlproperty real CandlestickSeries::capsWidth
++ The relative width of the caps within a candlestick, in the range from 0.0
++ to 1.0. Values outside this range are clamped to 0.0 or 1.0.
++ */
++
++ /*!
++ \property QCandlestickSeries::capsVisible
++ \brief The visibility of the caps.
++ */
++
++ /*!
++ \qmlproperty bool CandlestickSeries::capsVisible
++ The visibility of the caps.
++ */
++
++ /*!
++ \property QCandlestickSeries::increasingColor
++ \brief The color of the increasing candlestick item body.
++
++ A candlestick is \e increasing when its close value is higher than the open
++ value. By default, this property is set to the brush color. The default
++ color is used also when the property is set to an invalid color value.
++ */
++
++ /*!
++ \qmlproperty color CandlestickSeries::increasingColor
++ The color of the increasing candlestick item body.
++ A candlestick is \e increasing when its close value is higher than the open
++ value. By default, this property is set to the brush color. The default
++ color is used also when the property is set to an invalid color value.
++ */
++
++ /*!
++ \property QCandlestickSeries::decreasingColor
++ \brief The color of the decreasing candlestick item body.
++
++ A candlestick is \e decreasing when its open value is higher than the close
++ value. By default, this property is set to the brush color with the alpha
++ channel set to 128. The default color is used also when the property is set
++ to an invalid color value.
++ */
++
++ /*!
++ \qmlproperty color CandlestickSeries::decreasingColor
++ The color of the decreasing candlestick item body.
++ A candlestick is \e decreasing when its open value is higher than the close
++ value. By default, this property is set to the brush color with the alpha
++ channel set to 128. The default color is used also when the property is set
++ to an invalid color value.
++ */
++
++ /*!
++ \property QCandlestickSeries::brush
++ \brief The brush used to fill the candlestick items.
++ */
++
++ /*!
++ \property QCandlestickSeries::pen
++ \brief The pen used to draw the lines of the candlestick items.
++ */
++
++ /*!
++ \qmlproperty string CandlestickSeries::brushFilename
++ The name of the file used as a brush image for the series.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::clicked(QCandlestickSet *set)
++ This signal is emitted when the candlestick item specified by \a set
++ is clicked on the chart.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::clicked(CandlestickSet set)
++ This signal is emitted when the candlestick item specified by \a set
++ is clicked on the chart.
++
++ The corresponding signal handler is \c {onClicked}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::hovered(bool status, QCandlestickSet *set)
++ This signal is emitted when a mouse is hovered over the candlestick
++ item specified by \a set in a chart.
++
++ When the mouse moves over the item, \a status turns \c true, and when the
++ mouse moves away again, it turns \c false.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::hovered(bool status, CandlestickSet set)
++ This signal is emitted when a mouse is hovered over the candlestick
++ item specified by \a set in a chart.
++
++ When the mouse moves over the item, \a status turns \c true, and when the
++ mouse moves away again, it turns \c false.
++
++ The corresponding signal handler is \c {onHovered}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::pressed(QCandlestickSet *set)
++ This signal is emitted when the user clicks the candlestick item
++ specified by \a set and holds down the mouse button.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::pressed(CandlestickSet set)
++ This signal is emitted when the user clicks the candlestick item
++ specified by \a set and holds down the mouse button.
++
++ The corresponding signal handler is \c {onPressed}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::released(QCandlestickSet *set)
++ This signal is emitted when the user releases the mouse press on the
++ candlestick item specified by \a set.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::released(CandlestickSet set)
++ This signal is emitted when the user releases the mouse press on the
++ candlestick item specified by \a set.
++
++ The corresponding signal handler is \c {onReleased}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::doubleClicked(QCandlestickSet *set)
++ This signal is emitted when the candlestick item specified by \a set
++ is double-clicked on the chart.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::doubleClicked(CandlestickSet set)
++ This signal is emitted when the candlestick item specified by \a set
++ is double-clicked on the chart.
++
++ The corresponding signal handler is \c {onDoubleClicked}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::candlestickSetsAdded(const QList<QCandlestickSet *> &sets)
++ This signal is emitted when the candlestick items specified by \a
++ sets are added to the series.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::candlestickSetsAdded(list<CandlestickSet> sets)
++ This signal is emitted when the candlestick items specified by
++ \a sets are added to the series.
++
++ The corresponding signal handler is \c {onCandlestickSetsAdded}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::candlestickSetsRemoved(const QList<QCandlestickSet *> &sets)
++ This signal is emitted when the candlestick items specified by
++ \a sets are removed from the series.
++ */
++
++ /*!
++ \qmlsignal CandlestickSeries::candlestickSetsRemoved(list<CandlestickSet> sets)
++ This signal is emitted when the candlestick items specified by
++ \a sets are removed from the series.
++
++ The corresponding signal handler is \c {onCandlestickSetsRemoved}.
++ */
++
++ /*!
++ \fn void QCandlestickSeries::countChanged()
++ This signal is emitted when the number of candlestick items in the
++ series changes.
++ \sa count
++ */
++
++ /*!
++ \fn void QCandlestickSeries::maximumColumnWidthChanged()
++ This signal is emitted when there is a change in the maximum column width of candlestick items.
++ \sa maximumColumnWidth
++ */
++
++ /*!
++ \fn void QCandlestickSeries::minimumColumnWidthChanged()
++ This signal is emitted when there is a change in the minimum column width of candlestick items.
++ \sa minimumColumnWidth
++ */
++
++ /*!
++ \fn void QCandlestickSeries::bodyWidthChanged()
++ This signal is emitted when the candlestick item width changes.
++ \sa bodyWidth
++ */
++
++ /*!
++ \fn void QCandlestickSeries::bodyOutlineVisibilityChanged()
++ This signal is emitted when the visibility of the candlestick item body outline changes.
++ \sa bodyOutlineVisible
++ */
++
++ /*!
++ \fn void QCandlestickSeries::capsWidthChanged()
++ This signal is emitted when the candlestick item caps width changes.
++ \sa capsWidth
++ */
++
++ /*!
++ \fn void QCandlestickSeries::capsVisibilityChanged()
++ This signal is emitted when the visibility of the candlestick item caps changes.
++ \sa capsVisible
++ */
++
++ /*!
++ \fn void QCandlestickSeries::increasingColorChanged()
++ This signal is emitted when the candlestick item increasing color changes.
++ \sa increasingColor
++ */
++
++ /*!
++ \fn void QCandlestickSeries::decreasingColorChanged()
++ This signal is emitted when the candlestick item decreasing color changes.
++ \sa decreasingColor
++ */
++
++ /*!
++ \fn void QCandlestickSeries::brushChanged()
++ This signal is emitted when the candlestick item brush changes.
++
++ \sa brush
++ */
++
++ /*!
++ \fn void QCandlestickSeries::penChanged()
++ This signal is emitted when the candlestick item pen changes.
++
++ \sa pen
++ */
++
++ /*!
++ \qmlmethod CandlestickSet CandlestickSeries::at(int index)
++ Returns the candlestick item at the position specified by \a index. Returns
++ null if the index is not valid.
++ */
++
++ /*!
++ Constructs an empty QCandlestickSeries. The \a parent is optional.
++ */
++ QCandlestickSeries::QCandlestickSeries(QObject *parent)
++ : QAbstractSeries(*new QCandlestickSeriesPrivate(this), parent)
++ {
++ }
++
++ /*!
++ Destroys the series. Removes the series from the chart.
++ */
++ QCandlestickSeries::~QCandlestickSeries()
++ {
++ Q_D(QCandlestickSeries);
++ if (d->m_chart)
++ d->m_chart->removeSeries(this);
++ }
++
++ /*!
++ \qmlmethod bool CandlestickSeries::append(CandlestickSet set)
++ Adds a single candlestick item specified by \a set to the series and takes
++ ownership of it. If the item is null or it is already in the series, it
++ is not appended.
++
++ Returns \c true if appending succeeded, \c false otherwise.
++ */
++
++ /*!
++ Adds a single candlestick item specified by \a set to the series and takes
++ ownership of it. If the item is null or it is already in the series, it
++ is not appended.
++ Returns \c true if appending succeeded, \c false otherwise.
++ */
++ bool QCandlestickSeries::append(QCandlestickSet *set)
++ {
++ QList<QCandlestickSet *> sets;
++ sets.append(set);
++
++ return append(sets);
++ }
++
++ /*!
++ \qmlmethod bool CandlestickSeries::remove(CandlestickSet set)
++ Removes a single candlestick item, specified by \a set, from the series.
++
++ Returns \c true if the item is successfully deleted, \c false otherwise.
++ */
++
++ /*!
++ Removes a single candlestick item, specified by \a set, from the series.
++ Returns \c true if the item is successfully deleted, \c false otherwise.
++ */
++ bool QCandlestickSeries::remove(QCandlestickSet *set)
++ {
++ QList<QCandlestickSet *> sets;
++ sets.append(set);
++
++ return remove(sets);
++ }
++
++ /*!
++ Adds a list of candlestick items specified by \a sets to the series and
++ takes ownership of it. If any of the items are null, already belong to
++ the series, or appear in the list more than once, nothing is appended.
++ Returns \c true if all items were appended successfully, \c false otherwise.
++ */
++ bool QCandlestickSeries::append(const QList<QCandlestickSet *> &sets)
++ {
++ Q_D(QCandlestickSeries);
++
++ bool success = d->append(sets);
++ if (success) {
++ emit candlestickSetsAdded(sets);
++ emit countChanged();
++ }
++
++ return success;
++ }
++
++ /*!
++ Removes a list of candlestick items specified by \a sets from the series. If
++ any of the items are null, were already removed from the series, or appear
++ in the list more than once, nothing is removed. Returns \c true if all items
++ were removed successfully, \c false otherwise.
++ */
++ bool QCandlestickSeries::remove(const QList<QCandlestickSet *> &sets)
++ {
++ Q_D(QCandlestickSeries);
++
++ bool success = d->remove(sets);
++ if (success) {
++ emit candlestickSetsRemoved(sets);
++ emit countChanged();
++ for (auto set : sets)
++ delete set;
++ }
++
++ return success;
++ }
++
++ /*!
++ \qmlmethod bool CandlestickSeries::insert(int index, CandlestickSet set)
++ Inserts the candlestick item specified by \a set to the series at the
++ position specified by \a index. Takes ownership of the item. If the
++ item is null or already belongs to the series, it is not inserted.
++
++ Returns \c true if inserting succeeded, \c false otherwise.
++ */
++
++ /*!
++ Inserts the candlestick item specified by \a set to the series at the
++ position specified by \a index. Takes ownership of the item. If the
++ item is null or already belongs to the series, it is not inserted.
++ Returns \c true if inserting succeeded, \c false otherwise.
++ */
++ bool QCandlestickSeries::insert(int index, QCandlestickSet *set)
++ {
++ Q_D(QCandlestickSeries);
++
++ bool success = d->insert(index, set);
++ if (success) {
++ QList<QCandlestickSet *> sets;
++ sets.append(set);
++ emit candlestickSetsAdded(sets);
++ emit countChanged();
++ }
++
++ return success;
++ }
++
++ /*!
++ Takes a single candlestick item, specified by \a set, from the series. Does
++ not delete the item. Returns \c true if the take operation was successful, \c false otherwise.
++ \note The series remains the item's parent object. You must set the parent
++ object to take full ownership.
++ */
++ bool QCandlestickSeries::take(QCandlestickSet *set)
++ {
++ Q_D(QCandlestickSeries);
++
++ QList<QCandlestickSet *> sets;
++ sets.append(set);
++
++ bool success = d->remove(sets);
++ if (success) {
++ emit candlestickSetsRemoved(sets);
++ emit countChanged();
++ }
++
++ return success;
++ }
++
++ /*!
++ \qmlmethod void CandlestickSeries::clear()
++ Removes all candlestick items from the series and permanently deletes them.
++ */
++
++ /*!
++ Removes all candlestick items from the series and permanently deletes them.
++ */
++ void QCandlestickSeries::clear()
++ {
++ Q_D(QCandlestickSeries);
++
++ QList<QCandlestickSet *> sets = this->sets();
++
++ bool success = d->remove(sets);
++ if (success) {
++ emit candlestickSetsRemoved(sets);
++ emit countChanged();
++ for (auto set : std::as_const(sets))
++ delete set;
++ }
++ }
++
++ /*!
++ Returns the list of candlestick items in the series. Ownership of the
++ items does not change.
++ */
++ QList<QCandlestickSet *> QCandlestickSeries::sets() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_sets;
++ }
++
++ /*!
++ Returns the number of the candlestick items in the series.
++ */
++ int QCandlestickSeries::count() const
++ {
++ return sets().size();
++ }
++
++ /*!
++ Returns the type of the series (QAbstractSeries::SeriesTypeCandlestick).
++ */
++ QAbstractSeries::SeriesType QCandlestickSeries::type() const
++ {
++ return QAbstractSeries::SeriesTypeCandlestick;
++ }
++
++ void QCandlestickSeries::setMaximumColumnWidth(qreal maximumColumnWidth)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (maximumColumnWidth < 0.0 && maximumColumnWidth != -1.0)
++ maximumColumnWidth = -1.0;
++
++ if (d->m_maximumColumnWidth == maximumColumnWidth)
++ return;
++
++ d->m_maximumColumnWidth = maximumColumnWidth;
++
++ emit d->updatedLayout();
++ emit maximumColumnWidthChanged();
++ }
++
++ qreal QCandlestickSeries::maximumColumnWidth() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_maximumColumnWidth;
++ }
++
++ void QCandlestickSeries::setMinimumColumnWidth(qreal minimumColumnWidth)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (minimumColumnWidth < 0.0 && minimumColumnWidth != -1.0)
++ minimumColumnWidth = -1.0;
++
++ if (d->m_minimumColumnWidth == minimumColumnWidth)
++ return;
++
++ d->m_minimumColumnWidth = minimumColumnWidth;
++
++ d->updatedLayout();
++ emit minimumColumnWidthChanged();
++ }
++
++ qreal QCandlestickSeries::minimumColumnWidth() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_minimumColumnWidth;
++ }
++
++ void QCandlestickSeries::setBodyWidth(qreal bodyWidth)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (bodyWidth < 0.0)
++ bodyWidth = 0.0;
++ else if (bodyWidth > 1.0)
++ bodyWidth = 1.0;
++
++ if (d->m_bodyWidth == bodyWidth)
++ return;
++
++ d->m_bodyWidth = bodyWidth;
++
++ emit d->updatedLayout();
++ emit bodyWidthChanged();
++ }
++
++ qreal QCandlestickSeries::bodyWidth() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_bodyWidth;
++ }
++
++ void QCandlestickSeries::setBodyOutlineVisible(bool bodyOutlineVisible)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (d->m_bodyOutlineVisible == bodyOutlineVisible)
++ return;
++
++ d->m_bodyOutlineVisible = bodyOutlineVisible;
++
++ emit d->updated();
++ emit bodyOutlineVisibilityChanged();
++ }
++
++ bool QCandlestickSeries::bodyOutlineVisible() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_bodyOutlineVisible;
++ }
++
++ void QCandlestickSeries::setCapsWidth(qreal capsWidth)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (capsWidth < 0.0)
++ capsWidth = 0.0;
++ else if (capsWidth > 1.0)
++ capsWidth = 1.0;
++
++ if (d->m_capsWidth == capsWidth)
++ return;
++
++ d->m_capsWidth = capsWidth;
++
++ emit d->updatedLayout();
++ emit capsWidthChanged();
++ }
++
++ qreal QCandlestickSeries::capsWidth() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_capsWidth;
++ }
++
++ void QCandlestickSeries::setCapsVisible(bool capsVisible)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (d->m_capsVisible == capsVisible)
++ return;
++
++ d->m_capsVisible = capsVisible;
++
++ emit d->updated();
++ emit capsVisibilityChanged();
++ }
++
++ bool QCandlestickSeries::capsVisible() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_capsVisible;
++ }
++
++ void QCandlestickSeries::setIncreasingColor(const QColor &increasingColor)
++ {
++ Q_D(QCandlestickSeries);
++
++ QColor color;
++ if (increasingColor.isValid()) {
++ color = increasingColor;
++ d->m_customIncreasingColor = true;
++ } else {
++ color = d->m_brush.color();
++ color.setAlpha(128);
++ d->m_customIncreasingColor = false;
++ }
++
++ if (d->m_increasingColor == color)
++ return;
++
++ d->m_increasingColor = color;
++
++ emit d->updated();
++ emit increasingColorChanged();
++ }
++
++ QColor QCandlestickSeries::increasingColor() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_increasingColor;
++ }
++
++ void QCandlestickSeries::setDecreasingColor(const QColor &decreasingColor)
++ {
++ Q_D(QCandlestickSeries);
++
++ QColor color;
++ if (decreasingColor.isValid()) {
++ color = decreasingColor;
++ d->m_customDecreasingColor = true;
++ } else {
++ color = d->m_brush.color();
++ d->m_customDecreasingColor = false;
++ }
++
++ if (d->m_decreasingColor == color)
++ return;
++
++ d->m_decreasingColor = color;
++
++ emit d->updated();
++ emit decreasingColorChanged();
++ }
++
++ QColor QCandlestickSeries::decreasingColor() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_decreasingColor;
++ }
++
++ void QCandlestickSeries::setBrush(const QBrush &brush)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (d->m_brush == brush)
++ return;
++
++ d->m_brush = brush;
++ if (!d->m_customIncreasingColor) {
++ QColor color = d->m_brush.color();
++ color.setAlpha(128);
++ if (d->m_increasingColor != color) {
++ d->m_increasingColor = color;
++ emit increasingColorChanged();
++ }
++ }
++ if (!d->m_customDecreasingColor && d->m_decreasingColor != d->m_brush.color()) {
++ d->m_decreasingColor = d->m_brush.color();
++ emit decreasingColorChanged();
++ }
++
++ emit d->updated();
++ emit brushChanged();
++ }
++
++ QBrush QCandlestickSeries::brush() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_brush;
++ }
++
++ void QCandlestickSeries::setPen(const QPen &pen)
++ {
++ Q_D(QCandlestickSeries);
++
++ if (d->m_pen == pen)
++ return;
++
++ d->m_pen = pen;
++
++ emit d->updated();
++ emit penChanged();
++ }
++
++ QPen QCandlestickSeries::pen() const
++ {
++ Q_D(const QCandlestickSeries);
++
++ return d->m_pen;
++ }
++
++ ////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ QCandlestickSeriesPrivate::QCandlestickSeriesPrivate(QCandlestickSeries *q)
++ : QAbstractSeriesPrivate(q),
++ m_maximumColumnWidth(-1.0),
++ m_minimumColumnWidth(5.0),
++ m_bodyWidth(0.5),
++ m_bodyOutlineVisible(true),
++ m_capsWidth(0.5),
++ m_capsVisible(false),
++ m_increasingColor(QColor(Qt::transparent)),
++ m_decreasingColor(QChartPrivate::defaultBrush().color()),
++ m_customIncreasingColor(false),
++ m_customDecreasingColor(false),
++ m_brush(QChartPrivate::defaultBrush()),
++ m_pen(QChartPrivate::defaultPen()),
++ m_animation(nullptr)
++ {
++ }
++
++ QCandlestickSeriesPrivate::~QCandlestickSeriesPrivate()
++ {
++ disconnect(this, 0, 0, 0);
++ qDeleteAll(m_sets);
++ }
++
++ void QCandlestickSeriesPrivate::initializeDomain()
++ {
++ qreal minX(domain()->minX());
++ qreal maxX(domain()->maxX());
++ qreal minY(domain()->minY());
++ qreal maxY(domain()->maxY());
++
++ if (m_sets.size()) {
++ QCandlestickSet *set = m_sets.first();
++ minX = set->timestamp();
++ maxX = set->timestamp();
++ minY = set->low();
++ maxY = set->high();
++ for (int i = 1; i < m_sets.size(); ++i) {
++ set = m_sets.at(i);
++ minX = qMin(minX, qreal(set->timestamp()));
++ maxX = qMax(maxX, qreal(set->timestamp()));
++ minY = qMin(minY, set->low());
++ maxY = qMax(maxY, set->high());
++ }
++ qreal extra = (maxX - minX) / m_sets.size() / 2;
++ minX = minX - extra;
++ maxX = maxX + extra;
++ }
++
++ domain()->setRange(minX, maxX, minY, maxY);
++ }
++
++ void QCandlestickSeriesPrivate::initializeAxes()
++ {
++ for (auto axis : std::as_const(m_axes)) {
++ if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
++ if (axis->orientation() == Qt::Horizontal)
++ populateBarCategories(qobject_cast<QBarCategoryAxis *>(axis));
++ }
++ }
++ }
++
++ void QCandlestickSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
++ {
++ Q_Q(QCandlestickSeries);
++
++ if (forced || QChartPrivate::defaultBrush() == m_brush) {
++ const QList<QGradient> gradients = theme->seriesGradients();
++ const QGradient gradient = gradients.at(index % gradients.size());
++ const QBrush brush(ChartThemeManager::colorAt(gradient, 0.5));
++ q->setBrush(brush);
++ }
++
++ if (forced || QChartPrivate::defaultPen() == m_pen) {
++ QPen pen = theme->outlinePen();
++ pen.setCosmetic(true);
++ q->setPen(pen);
++ }
++ }
++
++ void QCandlestickSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
++ {
++ Q_Q(QCandlestickSeries);
++
++ CandlestickChartItem *item = new CandlestickChartItem(q, parent);
++ m_item.reset(item);
++ QAbstractSeriesPrivate::initializeGraphics(parent);
++
++ if (m_chart) {
++ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)),
++ this, SLOT(handleSeriesChange(QAbstractSeries*)));
++ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)),
++ this, SLOT(handleSeriesRemove(QAbstractSeries*)));
++
++ item->handleCandlestickSeriesChange();
++ }
++ }
++
++ void QCandlestickSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
++ QEasingCurve &curve)
++ {
++ CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.get());
++ Q_ASSERT(item);
++
++ if (item->animation())
++ item->animation()->stopAndDestroyLater();
++
++ if (options.testFlag(QChart::SeriesAnimations))
++ m_animation = new CandlestickAnimation(item, duration, curve);
++ else
++ m_animation = nullptr;
++ item->setAnimation(m_animation);
++
++ QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
++ }
++
++ QList<QLegendMarker *> QCandlestickSeriesPrivate::createLegendMarkers(QLegend *legend)
++ {
++ Q_Q(QCandlestickSeries);
++
++ QList<QLegendMarker *> list;
++
++ return list << new QCandlestickLegendMarker(q, legend);
++ }
++
++ QAbstractAxis::AxisType QCandlestickSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
++ {
++ if (orientation == Qt::Horizontal)
++ return QAbstractAxis::AxisTypeBarCategory;
++
++ if (orientation == Qt::Vertical)
++ return QAbstractAxis::AxisTypeValue;
++
++ return QAbstractAxis::AxisTypeNoAxis;
++ }
++
++ QAbstractAxis* QCandlestickSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
++ {
++ const QAbstractAxis::AxisType axisType = defaultAxisType(orientation);
++
++ if (axisType == QAbstractAxis::AxisTypeBarCategory)
++ return new QBarCategoryAxis;
++
++ if (axisType == QAbstractAxis::AxisTypeValue)
++ return new QValueAxis;
++
++ return 0; // axisType == QAbstractAxis::AxisTypeNoAxis
++ }
++
++ bool QCandlestickSeriesPrivate::append(const QList<QCandlestickSet *> &sets)
++ {
++ for (auto set : sets) {
++ if ((set == 0) || m_sets.contains(set) || set->d_ptr->m_series)
++ return false; // Fail if any of the sets is null or is already appended.
++ if (sets.count(set) != 1)
++ return false; // Also fail if the same set occurs more than once in the given list.
++ }
++
++ for (auto set : sets) {
++ m_sets.append(set);
++ connect(set->d_func(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
++ connect(set->d_func(), SIGNAL(updatedCandlestick()), this, SIGNAL(updatedCandlesticks()));
++ set->d_ptr->m_series = this;
++ }
++
++ return true;
++ }
++
++ bool QCandlestickSeriesPrivate::remove(const QList<QCandlestickSet *> &sets)
++ {
++ if (sets.size() == 0)
++ return false;
++
++ for (auto set : sets) {
++ if ((set == 0) || (!m_sets.contains(set)))
++ return false; // Fail if any of the sets is null or is not in series.
++ if (sets.count(set) != 1)
++ return false; // Also fail if the same set occurs more than once in the given list.
++ }
++
++ for (auto set : sets) {
++ set->d_ptr->m_series = nullptr;
++ m_sets.removeOne(set);
++ disconnect(set->d_func(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
++ disconnect(set->d_func(), SIGNAL(updatedCandlestick()),this, SIGNAL(updatedCandlesticks()));
++ }
++
++ return true;
++ }
++
++ bool QCandlestickSeriesPrivate::insert(int index, QCandlestickSet *set)
++ {
++ if ((m_sets.contains(set)) || (set == 0) || set->d_ptr->m_series)
++ return false; // Fail if set is already in list or set is null.
++
++ m_sets.insert(index, set);
++ connect(set->d_func(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
++ connect(set->d_func(), SIGNAL(updatedCandlestick()), this, SIGNAL(updatedCandlesticks()));
++ set->d_ptr->m_series = this;
++
++ return true;
++ }
++
++ void QCandlestickSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
++ {
++ Q_UNUSED(series);
++
++ if (m_chart) {
++ CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.get());
++ if (item)
++ item->handleCandlestickSeriesChange();
++ }
++ }
++
++ void QCandlestickSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
++ {
++ Q_Q(const QCandlestickSeries);
++
++ QCandlestickSeries *removedSeries = static_cast<QCandlestickSeries *>(series);
++
++ if (q == removedSeries && m_animation) {
++ m_animation->stopAll();
++ disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
++ }
++
++ if (q != removedSeries) {
++ CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.get());
++ if (item)
++ item->handleCandlestickSeriesChange();
++ }
++ }
++
++ void QCandlestickSeriesPrivate::populateBarCategories(QBarCategoryAxis *axis)
++ {
++ if (axis->categories().isEmpty()) {
++ QStringList categories;
++ for (int i = 0; i < m_sets.size(); ++i) {
++ const qint64 timestamp = qRound64(m_sets.at(i)->timestamp());
++ const QString timestampFormat = m_chart->locale().dateTimeFormat(QLocale::ShortFormat);
++ categories << QDateTime::fromMSecsSinceEpoch(timestamp).toString(timestampFormat);
++ }
++ axis->append(categories);
++ }
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qcandlestickseries.cpp"
++ #include "moc_qcandlestickseries_p.cpp"