| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Charts module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #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_CHARTS_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 {Candlestick Chart Example} {candlestick chart example} to learn how to create |
| a candlestick chart. |
| \image examples_candlestickchart.png |
| |
| \sa QCandlestickSet, QBarCategoryAxis, QDateTimeAxis, QValueAxis |
| */ |
| |
| /*! |
| \qmltype CandlestickSeries |
| \since QtCharts 2.2 |
| \instantiates 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 |
| \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 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 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 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(); |
| foreach (QCandlestickSet *set, sets) |
| delete set; |
| } |
| |
| return success; |
| } |
| |
| /*! |
| \qmlmethod 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 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(); |
| foreach (QCandlestickSet *set, 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().count(); |
| } |
| |
| /*! |
| 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.count()) { |
| QCandlestickSet *set = m_sets.first(); |
| minX = set->timestamp(); |
| maxX = set->timestamp(); |
| minY = set->low(); |
| maxY = set->high(); |
| for (int i = 1; i < m_sets.count(); ++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.count() / 2; |
| minX = minX - extra; |
| maxX = maxX + extra; |
| } |
| |
| domain()->setRange(minX, maxX, minY, maxY); |
| } |
| |
| void QCandlestickSeriesPrivate::initializeAxes() |
| { |
| foreach (QAbstractAxis* axis, 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.data()); |
| 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) |
| { |
| foreach (QCandlestickSet *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. |
| } |
| |
| foreach (QCandlestickSet *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.count() == 0) |
| return false; |
| |
| foreach (QCandlestickSet *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. |
| } |
| |
| foreach (QCandlestickSet *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.data()); |
| 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.data()); |
| if (item) |
| item->handleCandlestickSeriesChange(); |
| } |
| } |
| |
| void QCandlestickSeriesPrivate::populateBarCategories(QBarCategoryAxis *axis) |
| { |
| if (axis->categories().isEmpty()) { |
| QStringList categories; |
| for (int i = 0; i < m_sets.count(); ++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_CHARTS_END_NAMESPACE |
| |
| #include "moc_qcandlestickseries.cpp" |
| #include "moc_qcandlestickseries_p.cpp" |