summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Mishin <apmishin@yandex.com>2016-02-09 21:49:53 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2016-05-25 11:47:43 +0000
commitfacc2941efbfb8c9f40e363f0ea881653f6b4393 (patch)
treeae5ef712e4abbe47d60704fd0978f7533c7edbdd
parente9a2e2a5e9c023c872e39e39fb2a8b0a31820577 (diff)
Added candlestick chart type
- added QCandlestickSeries - added QCandlestickSet - added QCandlestickLegendMarker - added model mappers - added Candlestick, CandlestickChartItem, CandlestickData - added SeriesTypeCandlestick to SeriesType enum - added LegendMarkerTypeCandlestick to LegendMarkerType enum - added candlestick chart example - added QML candlestick chart example - added candlestick tester - added autotests - added documentation [ChangeLog][CandlestickChart] Added new chart type: Candlestick Chart. Task-number: QTBUG-50544 Change-Id: I17d18dfa23e0ea209bf51ab1e349585b9cb50a8f Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--examples/charts/candlestickchart/acme_data.txt24
-rw-r--r--examples/charts/candlestickchart/candlestickchart.pro14
-rw-r--r--examples/charts/candlestickchart/candlestickdata.qrc5
-rw-r--r--examples/charts/candlestickchart/candlestickdatareader.cpp77
-rw-r--r--examples/charts/candlestickchart/candlestickdatareader.h48
-rw-r--r--examples/charts/candlestickchart/main.cpp106
-rw-r--r--examples/charts/charts.pro2
-rw-r--r--examples/charts/qmlcandlestick/main.cpp59
-rw-r--r--examples/charts/qmlcandlestick/qml/qmlcandlestick/main.qml52
-rw-r--r--examples/charts/qmlcandlestick/qmlcandlestick.pro10
-rw-r--r--examples/charts/qmlcandlestick/resources.qrc5
-rw-r--r--src/charts/animations/animations.pri6
-rw-r--r--src/charts/animations/candlestickanimation.cpp116
-rw-r--r--src/charts/animations/candlestickanimation_p.h75
-rw-r--r--src/charts/animations/candlestickbodywicksanimation.cpp112
-rw-r--r--src/charts/animations/candlestickbodywicksanimation_p.h77
-rw-r--r--src/charts/barchart/qabstractbarseries.cpp2
-rw-r--r--src/charts/candlestickchart/candlestick.cpp351
-rw-r--r--src/charts/candlestickchart/candlestick_p.h121
-rw-r--r--src/charts/candlestickchart/candlestickchart.pri26
-rw-r--r--src/charts/candlestickchart/candlestickchartitem.cpp347
-rw-r--r--src/charts/candlestickchart/candlestickchartitem_p.h96
-rw-r--r--src/charts/candlestickchart/candlestickdata_p.h88
-rw-r--r--src/charts/candlestickchart/qcandlestickmodelmapper.cpp706
-rw-r--r--src/charts/candlestickchart/qcandlestickmodelmapper.h95
-rw-r--r--src/charts/candlestickchart/qcandlestickmodelmapper_p.h116
-rw-r--r--src/charts/candlestickchart/qcandlestickseries.cpp1138
-rw-r--r--src/charts/candlestickchart/qcandlestickseries.h131
-rw-r--r--src/charts/candlestickchart/qcandlestickseries_p.h113
-rw-r--r--src/charts/candlestickchart/qcandlestickset.cpp487
-rw-r--r--src/charts/candlestickchart/qcandlestickset.h102
-rw-r--r--src/charts/candlestickchart/qcandlestickset_p.h83
-rw-r--r--src/charts/candlestickchart/qhcandlestickmodelmapper.cpp322
-rw-r--r--src/charts/candlestickchart/qhcandlestickmodelmapper.h86
-rw-r--r--src/charts/candlestickchart/qvcandlestickmodelmapper.cpp323
-rw-r--r--src/charts/candlestickchart/qvcandlestickmodelmapper.h86
-rw-r--r--src/charts/chartdataset.cpp9
-rw-r--r--src/charts/chartpresenter_p.h1
-rw-r--r--src/charts/charts.pro1
-rw-r--r--src/charts/common.pri1
-rw-r--r--src/charts/doc/images/examples_candlestickchart.pngbin0 -> 21063 bytes
-rwxr-xr-xsrc/charts/doc/images/examples_qmlcandlestick.pngbin0 -> 9494 bytes
-rw-r--r--src/charts/doc/snippets/doc_src_qmlcharts.cpp2
-rw-r--r--src/charts/doc/src/examples-candlestickchart.qdoc99
-rw-r--r--src/charts/doc/src/qtcharts.qdoc2
-rw-r--r--src/charts/legend/legend.pri14
-rw-r--r--src/charts/legend/legendmarkeritem.cpp13
-rw-r--r--src/charts/legend/legendmarkeritem_p.h9
-rw-r--r--src/charts/legend/qcandlesticklegendmarker.cpp125
-rw-r--r--src/charts/legend/qcandlesticklegendmarker.h61
-rw-r--r--src/charts/legend/qcandlesticklegendmarker_p.h72
-rw-r--r--src/charts/legend/qlegendmarker.cpp1
-rw-r--r--src/charts/legend/qlegendmarker.h3
-rw-r--r--src/charts/qabstractseries.cpp1
-rw-r--r--src/charts/qabstractseries.h5
-rw-r--r--src/charts/qchart.h1
-rw-r--r--src/chartsqml2/chartsqml2.pro6
-rw-r--r--src/chartsqml2/chartsqml2_plugin.cpp17
-rw-r--r--src/chartsqml2/declarativecandlestickseries.cpp244
-rw-r--r--src/chartsqml2/declarativecandlestickseries.h136
-rw-r--r--src/chartsqml2/declarativechart.cpp6
-rw-r--r--src/chartsqml2/declarativechart.h1
-rw-r--r--tests/auto/auto.pro5
-rw-r--r--tests/auto/qcandlestickmodelmapper/qcandlestickmodelmapper.pro5
-rw-r--r--tests/auto/qcandlestickmodelmapper/tst_qcandlestickmodelmapper.cpp632
-rw-r--r--tests/auto/qcandlestickseries/qcandlestickseries.pro5
-rw-r--r--tests/auto/qcandlestickseries/tst_qcandlestickseries.cpp936
-rw-r--r--tests/auto/qcandlestickset/qcandlestickset.pro5
-rw-r--r--tests/auto/qcandlestickset/tst_qcandlestickset.cpp284
-rw-r--r--tests/manual/candlesticktester/candlesticktester.pro13
-rw-r--r--tests/manual/candlesticktester/customtablemodel.cpp160
-rw-r--r--tests/manual/candlesticktester/customtablemodel.h73
-rw-r--r--tests/manual/candlesticktester/main.cpp43
-rw-r--r--tests/manual/candlesticktester/mainwidget.cpp691
-rw-r--r--tests/manual/candlesticktester/mainwidget.h108
-rw-r--r--tests/manual/manual.pro3
76 files changed, 9376 insertions, 24 deletions
diff --git a/examples/charts/candlestickchart/acme_data.txt b/examples/charts/candlestickchart/acme_data.txt
new file mode 100644
index 00000000..eaac318c
--- /dev/null
+++ b/examples/charts/candlestickchart/acme_data.txt
@@ -0,0 +1,24 @@
+# Acme Ltd Historical Data (July 2015)
+# timestamp, open, high, low, close
+1435708800000 126.90 126.94 125.99 126.60
+1435795200000 126.69 126.69 126.69 126.69
+1436140800000 124.85 126.23 124.85 126.00
+1436227200000 125.89 126.15 123.77 125.69
+1436313600000 124.64 124.64 122.54 122.54
+1436400000000 123.85 124.06 119.22 120.07
+1436486400000 121.94 123.85 121.21 123.28
+1436745600000 125.03 125.76 124.32 125.66
+1436832000000 126.04 126.37 125.04 125.61
+1436918400000 125.72 127.15 125.58 126.82
+1437004800000 127.74 128.57 127.35 128.51
+1437091200000 129.08 129.62 128.31 129.62
+1437350400000 130.97 132.97 130.70 132.07
+1437436800000 132.85 132.92 130.32 130.75
+1437523200000 121.99 125.50 121.99 125.22
+1437609600000 126.20 127.09 125.06 125.16
+1437696000000 125.32 125.74 123.90 124.50
+1437955200000 123.09 123.61 122.12 122.77
+1438041600000 123.38 123.91 122.55 123.38
+1438128000000 123.15 123.50 122.27 122.99
+1438214400000 122.32 122.57 121.71 122.37
+1438300800000 122.60 122.64 120.91 121.30
diff --git a/examples/charts/candlestickchart/candlestickchart.pro b/examples/charts/candlestickchart/candlestickchart.pro
new file mode 100644
index 00000000..9a334bd6
--- /dev/null
+++ b/examples/charts/candlestickchart/candlestickchart.pro
@@ -0,0 +1,14 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+TARGET = candlestickchart
+
+SOURCES += main.cpp \
+ candlestickdatareader.cpp
+
+HEADERS += \
+ candlestickdatareader.h
+
+RESOURCES += \
+ candlestickdata.qrc
diff --git a/examples/charts/candlestickchart/candlestickdata.qrc b/examples/charts/candlestickchart/candlestickdata.qrc
new file mode 100644
index 00000000..e311cadb
--- /dev/null
+++ b/examples/charts/candlestickchart/candlestickdata.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="acme">acme_data.txt</file>
+ </qresource>
+</RCC>
diff --git a/examples/charts/candlestickchart/candlestickdatareader.cpp b/examples/charts/candlestickchart/candlestickdatareader.cpp
new file mode 100644
index 00000000..83228efd
--- /dev/null
+++ b/examples/charts/candlestickchart/candlestickdatareader.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 "candlestickdatareader.h"
+
+CandlestickDataReader::CandlestickDataReader(QIODevice *device)
+ : QTextStream(device)
+{
+}
+
+CandlestickDataReader::~CandlestickDataReader()
+{
+}
+
+void CandlestickDataReader::readFile(QIODevice *device)
+{
+ QTextStream::setDevice(device);
+}
+
+QCandlestickSet *CandlestickDataReader::readCandlestickSet()
+{
+ //! [1]
+ QString line = readLine();
+ if (line.startsWith("#") || line.isEmpty())
+ return 0;
+ //! [1]
+
+ //! [2]
+ QStringList strList = line.split(" ", QString::SkipEmptyParts);
+ if (strList.count() != 5)
+ return 0;
+ //! [2]
+
+ //! [3]
+ const qreal timestamp = strList.at(0).toDouble();
+ const qreal open = strList.at(1).toDouble();
+ const qreal high = strList.at(2).toDouble();
+ const qreal low = strList.at(3).toDouble();
+ const qreal close = strList.at(4).toDouble();
+ //! [3]
+
+ //! [4]
+ QCandlestickSet *candlestickSet = new QCandlestickSet(timestamp);
+ candlestickSet->setOpen(open);
+ candlestickSet->setHigh(high);
+ candlestickSet->setLow(low);
+ candlestickSet->setClose(close);
+ //! [4]
+
+ return candlestickSet;
+}
diff --git a/examples/charts/candlestickchart/candlestickdatareader.h b/examples/charts/candlestickchart/candlestickdatareader.h
new file mode 100644
index 00000000..aaa83bf2
--- /dev/null
+++ b/examples/charts/candlestickchart/candlestickdatareader.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef CANDLESTICKDATAREADER_H
+#define CANDLESTICKDATAREADER_H
+
+#include <QtCharts/QCandlestickSet>
+#include <QtCore/QTextStream>
+
+QT_CHARTS_USE_NAMESPACE
+
+class CandlestickDataReader : public QTextStream
+{
+public:
+ explicit CandlestickDataReader(QIODevice *device);
+ ~CandlestickDataReader();
+
+ void readFile(QIODevice *device);
+ QCandlestickSet *readCandlestickSet();
+};
+
+#endif // CANDLESTICKDATAREADER_H
diff --git a/examples/charts/candlestickchart/main.cpp b/examples/charts/candlestickchart/main.cpp
new file mode 100644
index 00000000..243b0f61
--- /dev/null
+++ b/examples/charts/candlestickchart/main.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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/QCandlestickSeries>
+#include <QtCharts/QChartView>
+#include <QtCharts/QValueAxis>
+#include <QtCore/QDateTime>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QMainWindow>
+
+#include "candlestickdatareader.h"
+
+QT_CHARTS_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ //! [1]
+ QCandlestickSeries *acmeSeries = new QCandlestickSeries();
+ acmeSeries->setName("Acme Ltd");
+ acmeSeries->setIncreasingColor(QColor(Qt::green));
+ acmeSeries->setDecreasingColor(QColor(Qt::red));
+ //! [1]
+
+ //! [2]
+ QFile acmeData(":acme");
+ if (!acmeData.open(QIODevice::ReadOnly | QIODevice::Text))
+ return 1;
+
+ QStringList categories;
+
+ CandlestickDataReader dataReader(&acmeData);
+ while (!dataReader.atEnd()) {
+ QCandlestickSet *set = dataReader.readCandlestickSet();
+ if (set) {
+ acmeSeries->append(set);
+ categories << QDateTime::fromMSecsSinceEpoch(set->timestamp()).toString("dd");
+ }
+ }
+ //! [2]
+
+ //! [3]
+ QChart *chart = new QChart();
+ chart->addSeries(acmeSeries);
+ chart->setTitle("Acme Ltd Historical Data (July 2015)");
+ chart->setAnimationOptions(QChart::SeriesAnimations);
+ //! [3]
+
+ //! [4]
+ chart->createDefaultAxes();
+
+ QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis *>(chart->axes(Qt::Horizontal).at(0));
+ axisX->setCategories(categories);
+
+ QValueAxis *axisY = qobject_cast<QValueAxis *>(chart->axes(Qt::Vertical).at(0));
+ axisY->setMax(axisY->max() * 1.01);
+ axisY->setMin(axisY->min() * 0.99);
+ //! [4]
+
+ //! [5]
+ chart->legend()->setVisible(true);
+ chart->legend()->setAlignment(Qt::AlignBottom);
+ //! [5]
+
+ //! [6]
+ QChartView *chartView = new QChartView(chart);
+ chartView->setRenderHint(QPainter::Antialiasing);
+ //! [6]
+
+ //! [7]
+ QMainWindow window;
+ window.setCentralWidget(chartView);
+ window.resize(800, 600);
+ window.show();
+ //! [7]
+
+ return a.exec();
+}
diff --git a/examples/charts/charts.pro b/examples/charts/charts.pro
index 5caa03c6..704d9cc0 100644
--- a/examples/charts/charts.pro
+++ b/examples/charts/charts.pro
@@ -14,6 +14,7 @@ SUBDIRS += areachart \
modeldata \
barchart \
boxplotchart \
+ candlestickchart \
legend \
barmodelmapper \
lineandbar \
@@ -36,6 +37,7 @@ SUBDIRS += areachart \
qtHaveModule(quick) {
SUBDIRS += qmlboxplot \
+ qmlcandlestick \
qmlpiechart \
qmlweather \
qmlf1legends \
diff --git a/examples/charts/qmlcandlestick/main.cpp b/examples/charts/qmlcandlestick/main.cpp
new file mode 100644
index 00000000..b399e15c
--- /dev/null
+++ b/examples/charts/qmlcandlestick/main.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 <QtCore/QDir>
+#include <QtQml/QQmlEngine>
+#include <QtQuick/QQuickView>
+#include <QtWidgets/QApplication>
+
+int main(int argc, char *argv[])
+{
+ // Qt Charts uses Qt Graphics View Framework for drawing, therefore QApplication must be used.
+ QApplication app(argc, argv);
+
+ QQuickView viewer;
+
+ // The following are needed to make examples run without having to install the module
+ // in desktop environments.
+#ifdef Q_OS_WIN
+ QString extraImportPath(QStringLiteral("%1/../../../../%2"));
+#else
+ QString extraImportPath(QStringLiteral("%1/../../../%2"));
+#endif
+ viewer.engine()->addImportPath(extraImportPath.arg(QApplication::applicationDirPath(),
+ QString::fromLatin1("qml")));
+ QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);
+
+ viewer.setTitle(QStringLiteral("QML Candlestick"));
+ viewer.setSource(QUrl("qrc:/qml/qmlcandlestick/main.qml"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/examples/charts/qmlcandlestick/qml/qmlcandlestick/main.qml b/examples/charts/qmlcandlestick/qml/qmlcandlestick/main.qml
new file mode 100644
index 00000000..18fca4fe
--- /dev/null
+++ b/examples/charts/qmlcandlestick/qml/qmlcandlestick/main.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtCharts 2.2
+
+ChartView {
+ title: "Candlestick series"
+ width: 800
+ height: 600
+ theme: ChartView.ChartThemeLight
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+ CandlestickSeries {
+ name: "Acme Ltd."
+ increasingColor: "green"
+ decreasingColor: "red"
+
+ CandlestickSet { timestamp: 1435708800000; open: 6.90; high: 6.94; low: 5.99; close: 6.60 }
+ CandlestickSet { timestamp: 1435795200000; open: 6.69; high: 6.69; low: 6.69; close: 6.69 }
+ CandlestickSet { timestamp: 1436140800000; open: 4.85; high: 6.23; low: 4.85; close: 6.00 }
+ CandlestickSet { timestamp: 1436227200000; open: 5.89; high: 6.15; low: 3.77; close: 5.69 }
+ CandlestickSet { timestamp: 1436313600000; open: 4.64; high: 4.64; low: 2.54; close: 2.54 }
+ }
+}
diff --git a/examples/charts/qmlcandlestick/qmlcandlestick.pro b/examples/charts/qmlcandlestick/qmlcandlestick.pro
new file mode 100644
index 00000000..58e63037
--- /dev/null
+++ b/examples/charts/qmlcandlestick/qmlcandlestick.pro
@@ -0,0 +1,10 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+RESOURCES += resources.qrc
+
+SOURCES += main.cpp
+
+OTHER_FILES += \
+ qml/qmlcandlestick/main.qml
diff --git a/examples/charts/qmlcandlestick/resources.qrc b/examples/charts/qmlcandlestick/resources.qrc
new file mode 100644
index 00000000..ccfab44e
--- /dev/null
+++ b/examples/charts/qmlcandlestick/resources.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/qmlcandlestick/main.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/charts/animations/animations.pri b/src/charts/animations/animations.pri
index 28b6db1e..9a5c86e8 100644
--- a/src/charts/animations/animations.pri
+++ b/src/charts/animations/animations.pri
@@ -11,6 +11,8 @@ SOURCES += \
$$PWD/scatteranimation.cpp \
$$PWD/boxplotanimation.cpp \
$$PWD/boxwhiskersanimation.cpp \
+ $$PWD/candlestickanimation.cpp \
+ $$PWD/candlestickbodywicksanimation.cpp \
$$PWD/chartanimation.cpp
PRIVATE_HEADERS += \
@@ -23,4 +25,6 @@ PRIVATE_HEADERS += \
$$PWD/baranimation_p.h \
$$PWD/scatteranimation_p.h \
$$PWD/boxplotanimation_p.h \
- $$PWD/boxwhiskersanimation_p.h
+ $$PWD/boxwhiskersanimation_p.h \
+ $$PWD/candlestickanimation_p.h \
+ $$PWD/candlestickbodywicksanimation_p.h
diff --git a/src/charts/animations/candlestickanimation.cpp b/src/charts/animations/candlestickanimation.cpp
new file mode 100644
index 00000000..5e141943
--- /dev/null
+++ b/src/charts/animations/candlestickanimation.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 <private/candlestick_p.h>
+#include <private/candlestickanimation_p.h>
+#include <private/candlestickbodywicksanimation_p.h>
+#include <private/candlestickchartitem_p.h>
+#include <private/candlestickdata_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+CandlestickAnimation::CandlestickAnimation(CandlestickChartItem *item, int duration,
+ QEasingCurve &curve)
+ : QObject(item),
+ m_item(item),
+ m_animationDuration(duration),
+ m_animationCurve(curve)
+{
+}
+
+CandlestickAnimation::~CandlestickAnimation()
+{
+}
+
+void CandlestickAnimation::addCandlestick(Candlestick *candlestick)
+{
+ CandlestickBodyWicksAnimation *animation = m_animations.value(candlestick, 0);
+ if (!animation) {
+ animation = new CandlestickBodyWicksAnimation(candlestick, this, m_animationDuration,
+ m_animationCurve);
+ m_animations.insert(candlestick, animation);
+
+ qreal median = (candlestick->m_data.m_open + candlestick->m_data.m_close) / 2;
+ CandlestickData start;
+ start.m_open = median;
+ start.m_high = median;
+ start.m_low = median;
+ start.m_close = median;
+ animation->setup(start, candlestick->m_data);
+ } else {
+ animation->stop();
+ animation->setEndData(candlestick->m_data);
+ }
+}
+
+ChartAnimation *CandlestickAnimation::candlestickAnimation(Candlestick *candlestick)
+{
+ CandlestickBodyWicksAnimation *animation = m_animations.value(candlestick, 0);
+ if (animation)
+ animation->m_changeAnimation = false;
+
+ return animation;
+}
+
+ChartAnimation *CandlestickAnimation::candlestickChangeAnimation(Candlestick *candlestick)
+{
+ CandlestickBodyWicksAnimation *animation = m_animations.value(candlestick, 0);
+ if (animation) {
+ animation->m_changeAnimation = true;
+ animation->setEndData(candlestick->m_data);
+ }
+
+ return animation;
+}
+
+void CandlestickAnimation::setAnimationStart(Candlestick *candlestick)
+{
+ CandlestickBodyWicksAnimation *animation = m_animations.value(candlestick, 0);
+ if (animation)
+ animation->setStartData(candlestick->m_data);
+}
+
+void CandlestickAnimation::stopAll()
+{
+ foreach (Candlestick *candlestick, m_animations.keys()) {
+ CandlestickBodyWicksAnimation *animation = m_animations.value(candlestick, 0);
+ if (animation)
+ animation->stopAndDestroyLater();
+ m_animations.remove(candlestick);
+ }
+}
+
+void CandlestickAnimation::removeCandlestickAnimation(Candlestick *candlestick)
+{
+ m_animations.remove(candlestick);
+}
+
+#include "moc_candlestickanimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/candlestickanimation_p.h b/src/charts/animations/candlestickanimation_p.h
new file mode 100644
index 00000000..cb894cd7
--- /dev/null
+++ b/src/charts/animations/candlestickanimation_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CANDLESTICKANIMATION_P_H
+#define CANDLESTICKANIMATION_P_H
+
+#include <private/chartanimation_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class Candlestick;
+class CandlestickChartItem;
+class CandlestickBodyWicksAnimation;
+
+class CandlestickAnimation : public QObject
+{
+ Q_OBJECT
+
+public:
+ CandlestickAnimation(CandlestickChartItem *item, int duration, QEasingCurve &curve);
+ ~CandlestickAnimation();
+
+ void addCandlestick(Candlestick *candlestick);
+ ChartAnimation *candlestickAnimation(Candlestick *candlestick);
+ ChartAnimation *candlestickChangeAnimation(Candlestick *candlestick);
+
+ void setAnimationStart(Candlestick *candlestick);
+ void stopAll();
+ void removeCandlestickAnimation(Candlestick *candlestick);
+
+protected:
+ QHash<Candlestick *, CandlestickBodyWicksAnimation *> m_animations;
+ CandlestickChartItem *m_item;
+ int m_animationDuration;
+ QEasingCurve m_animationCurve;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CANDLESTICKANIMATION_P_H
diff --git a/src/charts/animations/candlestickbodywicksanimation.cpp b/src/charts/animations/candlestickbodywicksanimation.cpp
new file mode 100644
index 00000000..615f43c3
--- /dev/null
+++ b/src/charts/animations/candlestickbodywicksanimation.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 <private/candlestick_p.h>
+#include <private/candlestickanimation_p.h>
+#include <private/candlestickbodywicksanimation_p.h>
+
+Q_DECLARE_METATYPE(QVector<QRectF>)
+Q_DECLARE_METATYPE(QT_CHARTS_NAMESPACE::CandlestickData)
+Q_DECLARE_METATYPE(qreal)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+CandlestickBodyWicksAnimation::CandlestickBodyWicksAnimation(Candlestick *candlestick,
+ CandlestickAnimation *animation,
+ int duration, QEasingCurve &curve)
+ : ChartAnimation(candlestick),
+ m_candlestick(candlestick),
+ m_candlestickAnimation(animation),
+ m_changeAnimation(false)
+{
+ setDuration(duration);
+ setEasingCurve(curve);
+}
+
+CandlestickBodyWicksAnimation::~CandlestickBodyWicksAnimation()
+{
+ if (m_candlestickAnimation)
+ m_candlestickAnimation->removeCandlestickAnimation(m_candlestick);
+}
+
+void CandlestickBodyWicksAnimation::setup(const CandlestickData &startData,
+ const CandlestickData &endData)
+{
+ setKeyValueAt(0.0, qVariantFromValue(startData));
+ setKeyValueAt(1.0, qVariantFromValue(endData));
+}
+
+void CandlestickBodyWicksAnimation::setStartData(const CandlestickData &startData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setStartValue(qVariantFromValue(startData));
+}
+
+void CandlestickBodyWicksAnimation::setEndData(const CandlestickData &endData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setEndValue(qVariantFromValue(endData));
+}
+
+void CandlestickBodyWicksAnimation::updateCurrentValue(const QVariant &value)
+{
+ CandlestickData data = qvariant_cast<CandlestickData>(value);
+ m_candlestick->setLayout(data);
+}
+
+QVariant CandlestickBodyWicksAnimation::interpolated(const QVariant &from, const QVariant &to,
+ qreal progress) const
+{
+ CandlestickData startData = qvariant_cast<CandlestickData>(from);
+ CandlestickData endData = qvariant_cast<CandlestickData>(to);
+ CandlestickData result = endData;
+
+ if (m_changeAnimation) {
+ result.m_open = startData.m_open + progress * (endData.m_open - startData.m_open);
+ result.m_high = startData.m_high + progress * (endData.m_high - startData.m_high);
+ result.m_low = startData.m_low + progress * (endData.m_low - startData.m_low);
+ result.m_close = startData.m_close + progress * (endData.m_close - startData.m_close);
+ } else {
+ const qreal median = (endData.m_open + endData.m_close) / 2;
+ result.m_low = median + progress * (endData.m_low - median);
+ result.m_close = median + progress * (endData.m_close - median);
+ result.m_open = median + progress * (endData.m_open - median);
+ result.m_high = median + progress * (endData.m_high - median);
+ }
+
+ return qVariantFromValue(result);
+}
+
+#include "moc_candlestickbodywicksanimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/candlestickbodywicksanimation_p.h b/src/charts/animations/candlestickbodywicksanimation_p.h
new file mode 100644
index 00000000..a8d30f04
--- /dev/null
+++ b/src/charts/animations/candlestickbodywicksanimation_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CANDLESTICKBODYWICKSANIMATION_P_H
+#define CANDLESTICKBODYWICKSANIMATION_P_H
+
+#include <private/candlestickdata_p.h>
+#include <private/chartanimation_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class Candlestick;
+class CandlestickAnimation;
+
+class CandlestickBodyWicksAnimation : public ChartAnimation
+{
+ Q_OBJECT
+
+public:
+ CandlestickBodyWicksAnimation(Candlestick *candlestick, CandlestickAnimation *animation,
+ int duration, QEasingCurve &curve);
+ ~CandlestickBodyWicksAnimation();
+
+ void setup(const CandlestickData &startData, const CandlestickData &endData);
+ void setStartData(const CandlestickData &startData);
+ void setEndData(const CandlestickData &endData);
+
+ // from QVariantAnimation
+ virtual void updateCurrentValue(const QVariant &value);
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+
+protected:
+ Candlestick *m_candlestick;
+ CandlestickAnimation *m_candlestickAnimation;
+ bool m_changeAnimation;
+
+ friend class CandlestickAnimation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CANDLESTICKBODYWICKSANIMATION_P_H
diff --git a/src/charts/barchart/qabstractbarseries.cpp b/src/charts/barchart/qabstractbarseries.cpp
index 027ae8d0..844b21e3 100644
--- a/src/charts/barchart/qabstractbarseries.cpp
+++ b/src/charts/barchart/qabstractbarseries.cpp
@@ -983,6 +983,7 @@ void QAbstractBarSeriesPrivate::initializeAxes()
case QAbstractSeries::SeriesTypePercentBar:
case QAbstractSeries::SeriesTypeStackedBar:
case QAbstractSeries::SeriesTypeBoxPlot:
+ case QAbstractSeries::SeriesTypeCandlestick:
if (axis->orientation() == Qt::Horizontal)
populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
break;
@@ -1009,6 +1010,7 @@ QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientati
case QAbstractSeries::SeriesTypePercentBar:
case QAbstractSeries::SeriesTypeStackedBar:
case QAbstractSeries::SeriesTypeBoxPlot:
+ case QAbstractSeries::SeriesTypeCandlestick:
if (orientation == Qt::Horizontal)
return QAbstractAxis::AxisTypeBarCategory;
break;
diff --git a/src/charts/candlestickchart/candlestick.cpp b/src/charts/candlestickchart/candlestick.cpp
new file mode 100644
index 00000000..9e8d8fa0
--- /dev/null
+++ b/src/charts/candlestickchart/candlestick.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** 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/QCandlestickSet>
+#include <QtGui/QPainter>
+#include <private/abstractdomain_p.h>
+#include <private/candlestick_p.h>
+#include <private/qchart_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+Candlestick::Candlestick(QCandlestickSet *set, AbstractDomain *domain, QGraphicsObject *parent)
+ : QGraphicsObject(parent),
+ m_set(set),
+ m_domain(domain),
+ m_timePeriod(0.0),
+ m_maximumColumnWidth(-1.0), // no maximum column width by default
+ m_minimumColumnWidth(-1.0), // no minimum column width by default
+ m_bodyWidth(0.5),
+ m_bodyOutlineVisible(true),
+ m_capsWidth(0.5),
+ m_capsVisible(false),
+ m_brush(QChartPrivate::defaultBrush()),
+ m_pen(QChartPrivate::defaultPen()),
+ m_hovering(false),
+ m_mousePressed(false)
+{
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::MouseButtonMask);
+ setFlag(QGraphicsObject::ItemIsSelectable);
+}
+
+Candlestick::~Candlestick()
+{
+ // End hover event, if candlestick is deleted during it.
+ if (m_hovering)
+ emit hovered(false, m_set);
+}
+
+void Candlestick::setTimePeriod(qreal timePeriod)
+{
+ m_timePeriod = timePeriod;
+}
+
+void Candlestick::setMaximumColumnWidth(qreal maximumColumnWidth)
+{
+ m_maximumColumnWidth = maximumColumnWidth;
+}
+
+void Candlestick::setMinimumColumnWidth(qreal minimumColumnWidth)
+{
+ m_minimumColumnWidth = minimumColumnWidth;
+}
+
+void Candlestick::setBodyWidth(qreal bodyWidth)
+{
+ m_bodyWidth = bodyWidth;
+}
+
+void Candlestick::setBodyOutlineVisible(bool bodyOutlineVisible)
+{
+ m_bodyOutlineVisible = bodyOutlineVisible;
+}
+
+void Candlestick::setCapsWidth(qreal capsWidth)
+{
+ m_capsWidth = capsWidth;
+}
+
+void Candlestick::setCapsVisible(bool capsVisible)
+{
+ m_capsVisible = capsVisible;
+}
+
+void Candlestick::setIncreasingColor(const QColor &color)
+{
+ m_increasingColor = color;
+
+ update();
+}
+
+void Candlestick::setDecreasingColor(const QColor &color)
+{
+ m_decreasingColor = color;
+
+ update();
+}
+
+void Candlestick::setBrush(const QBrush &brush)
+{
+ m_brush = brush;
+
+ update();
+}
+
+void Candlestick::setPen(const QPen &pen)
+{
+ qreal widthDiff = pen.widthF() - m_pen.widthF();
+ m_boundingRect.adjust(-widthDiff, -widthDiff, widthDiff, widthDiff);
+
+ m_pen = pen;
+
+ update();
+}
+
+void Candlestick::setLayout(const CandlestickData &data)
+{
+ m_data = data;
+
+ updateGeometry(m_domain);
+ update();
+}
+
+void Candlestick::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ m_mousePressed = true;
+ emit pressed(m_set);
+ QGraphicsItem::mousePressEvent(event);
+}
+
+void Candlestick::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+
+ m_hovering = true;
+ emit hovered(m_hovering, m_set);
+}
+
+void Candlestick::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+
+ m_hovering = false;
+ emit hovered(m_hovering, m_set);
+}
+
+void Candlestick::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit released(m_set);
+ if (m_mousePressed)
+ emit clicked(m_set);
+ m_mousePressed = false;
+ QGraphicsItem::mouseReleaseEvent(event);
+}
+
+void Candlestick::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ // For candlestick a pressed signal needs to be explicitly fired for mouseDoubleClickEvent.
+ emit pressed(m_set);
+ emit doubleClicked(m_set);
+ QGraphicsItem::mouseDoubleClickEvent(event);
+}
+
+QRectF Candlestick::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void Candlestick::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+
+ bool increasingTrend = (m_data.m_open < m_data.m_close);
+ QColor color = increasingTrend ? m_increasingColor : m_decreasingColor;
+
+ QBrush brush(m_brush);
+ brush.setColor(color);
+
+ painter->save();
+ painter->setBrush(brush);
+ painter->setPen(m_pen);
+ painter->setClipRect(m_boundingRect);
+ if (m_capsVisible)
+ painter->drawPath(m_capsPath);
+ painter->drawPath(m_wicksPath);
+ if (!m_bodyOutlineVisible)
+ painter->setPen(QColor(Qt::transparent));
+ painter->drawRect(m_bodyRect);
+ painter->restore();
+}
+
+void Candlestick::updateGeometry(AbstractDomain *domain)
+{
+ m_domain = domain;
+
+ prepareGeometryChange();
+
+ m_capsPath = QPainterPath();
+ m_wicksPath = QPainterPath();
+ m_boundingRect = QRectF();
+
+ if (!m_data.m_series->chart())
+ return;
+
+ QList<QAbstractAxis *> axes = m_data.m_series->chart()->axes(Qt::Horizontal, m_data.m_series);
+ if (axes.isEmpty())
+ return;
+
+ QAbstractAxis *axisX = axes.value(0);
+ if (!axisX)
+ return;
+
+ qreal columnWidth = 0.0;
+ qreal columnCenter = 0.0;
+ switch (axisX->type()) {
+ case QAbstractAxis::AxisTypeBarCategory:
+ columnWidth = 1.0 / m_data.m_seriesCount;
+ columnCenter = m_data.m_index - 0.5
+ + m_data.m_seriesIndex * columnWidth
+ + columnWidth / 2.0;
+ break;
+ case QAbstractAxis::AxisTypeDateTime:
+ case QAbstractAxis::AxisTypeValue:
+ columnWidth = m_timePeriod;
+ columnCenter = m_data.m_timestamp;
+ break;
+ default:
+ qWarning() << "Unexpected axis type";
+ return;
+ }
+
+ const qreal bodyWidth = m_bodyWidth * columnWidth;
+ const qreal bodyLeft = columnCenter - (bodyWidth / 2.0);
+ const qreal bodyRight = bodyLeft + bodyWidth;
+
+ const qreal upperBody = qMax(m_data.m_open, m_data.m_close);
+ const qreal lowerBody = qMin(m_data.m_open, m_data.m_close);
+ const bool upperWickVisible = (m_data.m_high > upperBody);
+ const bool lowerWickVisible = (m_data.m_low < lowerBody);
+
+ QPointF geometryPoint;
+ bool validData;
+
+ // upper extreme
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(bodyLeft, m_data.m_high), validData);
+ if (!validData)
+ return;
+ const qreal geometryUpperExtreme = geometryPoint.y();
+ // upper body
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(bodyLeft, upperBody), validData);
+ if (!validData)
+ return;
+ const qreal geometryBodyLeft = geometryPoint.x();
+ const qreal geometryUpperBody = geometryPoint.y();
+ // lower body
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(bodyRight, lowerBody), validData);
+ if (!validData)
+ return;
+ const qreal geometryBodyRight = geometryPoint.x();
+ const qreal geometryLowerBody = geometryPoint.y();
+ // lower extreme
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(bodyRight, m_data.m_low), validData);
+ if (!validData)
+ return;
+ const qreal geometryLowerExtreme = geometryPoint.y();
+
+ // Real Body
+ m_bodyRect.setCoords(geometryBodyLeft, geometryUpperBody, geometryBodyRight, geometryLowerBody);
+ if (m_maximumColumnWidth != -1.0) {
+ if (m_bodyRect.width() > m_maximumColumnWidth) {
+ qreal extra = (m_bodyRect.width() - m_maximumColumnWidth) / 2.0;
+ m_bodyRect.adjust(extra, 0.0, 0.0, 0.0);
+ m_bodyRect.setWidth(m_maximumColumnWidth);
+ }
+ }
+ if (m_minimumColumnWidth != -1.0) {
+ if (m_bodyRect.width() < m_minimumColumnWidth) {
+ qreal extra = (m_minimumColumnWidth - m_bodyRect.width()) / 2.0;
+ m_bodyRect.adjust(-extra, 0.0, 0.0, 0.0);
+ m_bodyRect.setWidth(m_minimumColumnWidth);
+ }
+ }
+
+ const qreal geometryCapsExtra = (m_bodyRect.width() - (m_bodyRect.width() * m_capsWidth)) /2.0;
+ const qreal geometryCapsLeft = m_bodyRect.left() + geometryCapsExtra;
+ const qreal geometryCapsRight = m_bodyRect.right() - geometryCapsExtra;
+
+ // Upper Wick and Cap
+ if (upperWickVisible) {
+ m_capsPath.moveTo(geometryCapsLeft, geometryUpperExtreme);
+ m_capsPath.lineTo(geometryCapsRight, geometryUpperExtreme);
+ m_wicksPath.moveTo((geometryCapsLeft + geometryCapsRight) / 2.0, geometryUpperExtreme);
+ m_wicksPath.lineTo((geometryCapsLeft + geometryCapsRight) / 2.0, geometryUpperBody);
+ }
+ // Lower Wick and Cap
+ if (lowerWickVisible) {
+ m_capsPath.moveTo(geometryCapsLeft, geometryLowerExtreme);
+ m_capsPath.lineTo(geometryCapsRight, geometryLowerExtreme);
+ m_wicksPath.moveTo((geometryCapsLeft + geometryCapsRight) / 2.0, geometryLowerBody);
+ m_wicksPath.lineTo((geometryCapsLeft + geometryCapsRight) / 2.0, geometryLowerExtreme);
+ }
+ m_wicksPath.closeSubpath();
+
+ // bounding rectangle top
+ qreal boundingRectTop;
+ if (upperWickVisible)
+ boundingRectTop = m_wicksPath.boundingRect().top();
+ else
+ boundingRectTop = m_bodyRect.top();
+ boundingRectTop = qMax(boundingRectTop, parentItem()->boundingRect().top());
+ // bounding rectangle right
+ qreal boundingRectRight = qMin(m_bodyRect.right(), parentItem()->boundingRect().right());
+ // bounding rectangle bottom
+ qreal boundingRectBottom;
+ if (lowerWickVisible)
+ boundingRectBottom = m_wicksPath.boundingRect().bottom();
+ else
+ boundingRectBottom = m_bodyRect.bottom();
+ boundingRectBottom = qMin(boundingRectBottom, parentItem()->boundingRect().bottom());
+ // bounding rectangle left
+ qreal boundingRectLeft = qMax(m_bodyRect.left(), parentItem()->boundingRect().left());
+
+ m_boundingRect.setTop(boundingRectTop);
+ m_boundingRect.setRight(boundingRectRight);
+ m_boundingRect.setBottom(boundingRectBottom);
+ m_boundingRect.setLeft(boundingRectLeft);
+
+ qreal extra = m_pen.widthF();
+ m_boundingRect.adjust(-extra, -extra, extra, extra);
+}
+
+#include "moc_candlestick_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/candlestick_p.h b/src/charts/candlestickchart/candlestick_p.h
new file mode 100644
index 00000000..fb39bbfa
--- /dev/null
+++ b/src/charts/candlestickchart/candlestick_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CANDLESTICK_P_H
+#define CANDLESTICK_P_H
+
+#include <QtGui/QBrush>
+#include <QtGui/QPainterPath>
+#include <QtGui/QPen>
+#include <QtWidgets/QGraphicsObject>
+#include <private/candlestickdata_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class AbstractDomain;
+class QCandlestickSet;
+
+class Candlestick : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ Candlestick(QCandlestickSet *set, AbstractDomain *domain, QGraphicsObject *parent);
+ ~Candlestick();
+
+ void setTimePeriod(qreal timePeriod);
+ void setMaximumColumnWidth(qreal maximumColumnWidth);
+ void setMinimumColumnWidth(qreal minimumColumnWidth);
+ void setBodyWidth(qreal bodyWidth);
+ void setBodyOutlineVisible(bool bodyOutlineVisible);
+ void setCapsWidth(qreal capsWidth);
+ void setCapsVisible(bool capsVisible);
+ void setIncreasingColor(const QColor &color);
+ void setDecreasingColor(const QColor &color);
+ void setBrush(const QBrush &brush);
+ void setPen(const QPen &pen);
+ void setLayout(const CandlestickData &data);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget = nullptr);
+
+Q_SIGNALS:
+ void clicked(QCandlestickSet *set);
+ void hovered(bool status, QCandlestickSet *set);
+ void pressed(QCandlestickSet *set);
+ void released(QCandlestickSet *set);
+ void doubleClicked(QCandlestickSet *set);
+
+private:
+ void updateGeometry(AbstractDomain *domain);
+
+private:
+ QCandlestickSet *m_set;
+ AbstractDomain *m_domain;
+ qreal m_timePeriod;
+ qreal m_maximumColumnWidth;
+ qreal m_minimumColumnWidth;
+ qreal m_bodyWidth;
+ bool m_bodyOutlineVisible;
+ qreal m_capsWidth;
+ bool m_capsVisible;
+ QColor m_increasingColor;
+ QColor m_decreasingColor;
+ QBrush m_brush;
+ QPen m_pen;
+ CandlestickData m_data;
+ bool m_hovering;
+ bool m_mousePressed;
+ QRectF m_boundingRect;
+ QRectF m_bodyRect;
+ QPainterPath m_wicksPath;
+ QPainterPath m_capsPath;
+
+ friend class CandlestickAnimation;
+ friend class CandlestickChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CANDLESTICK_P_H
diff --git a/src/charts/candlestickchart/candlestickchart.pri b/src/charts/candlestickchart/candlestickchart.pri
new file mode 100644
index 00000000..35cdd37a
--- /dev/null
+++ b/src/charts/candlestickchart/candlestickchart.pri
@@ -0,0 +1,26 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/candlestick.cpp \
+ $$PWD/candlestickchartitem.cpp \
+ $$PWD/qcandlestickseries.cpp \
+ $$PWD/qcandlestickset.cpp \
+ $$PWD/qcandlestickmodelmapper.cpp \
+ $$PWD/qhcandlestickmodelmapper.cpp \
+ $$PWD/qvcandlestickmodelmapper.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/candlestick_p.h \
+ $$PWD/candlestickchartitem_p.h \
+ $$PWD/candlestickdata_p.h \
+ $$PWD/qcandlestickseries_p.h \
+ $$PWD/qcandlestickset_p.h \
+ $$PWD/qcandlestickmodelmapper_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qcandlestickseries.h \
+ $$PWD/qcandlestickset.h \
+ $$PWD/qcandlestickmodelmapper.h \
+ $$PWD/qhcandlestickmodelmapper.h \
+ $$PWD/qvcandlestickmodelmapper.h
diff --git a/src/charts/candlestickchart/candlestickchartitem.cpp b/src/charts/candlestickchart/candlestickchartitem.cpp
new file mode 100644
index 00000000..ad64dd13
--- /dev/null
+++ b/src/charts/candlestickchart/candlestickchartitem.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** 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/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <private/candlestickchartitem_p.h>
+#include <private/candlestick_p.h>
+#include <private/candlestickdata_p.h>
+#include <private/qcandlestickseries_p.h>
+#include <private/candlestickanimation_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+CandlestickChartItem::CandlestickChartItem(QCandlestickSeries *series, QGraphicsItem *item)
+ : ChartItem(series->d_func(), item),
+ m_series(series),
+ m_seriesIndex(0),
+ m_seriesCount(0),
+ m_timePeriod(0.0),
+ m_animation(nullptr)
+{
+ connect(series, SIGNAL(candlestickSetsAdded(QList<QCandlestickSet *>)),
+ this, SLOT(handleCandlestickSetsAdd(QList<QCandlestickSet *>)));
+ connect(series, SIGNAL(candlestickSetsRemoved(QList<QCandlestickSet *>)),
+ this, SLOT(handleCandlestickSetsRemove(QList<QCandlestickSet *>)));
+
+ connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleCandlesticksUpdated()));
+ connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutUpdated()));
+ connect(series->d_func(), SIGNAL(updatedCandlesticks()),
+ this, SLOT(handleCandlesticksUpdated()));
+
+ setZValue(ChartPresenter::CandlestickSeriesZValue);
+
+ handleCandlestickSetsAdd(m_series->candlestickSets());
+}
+
+CandlestickChartItem::~CandlestickChartItem()
+{
+}
+
+void CandlestickChartItem::setAnimation(CandlestickAnimation *animation)
+{
+ m_animation = animation;
+
+ if (m_animation) {
+ foreach (Candlestick *item, m_candlesticks.values())
+ m_animation->addCandlestick(item);
+
+ handleDomainUpdated();
+ }
+}
+
+QRectF CandlestickChartItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void CandlestickChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+void CandlestickChartItem::handleDomainUpdated()
+{
+ if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
+ return;
+
+ // Set bounding rectangle to same as domain size. Add one pixel at the top (-1.0) and the bottom
+ // as 0.0 would snip a bit off from the wick at the grid line.
+ m_boundingRect.setRect(0.0, -1.0, domain()->size().width(), domain()->size().height() + 1.0);
+
+ foreach (Candlestick *item, m_candlesticks.values()) {
+ item->updateGeometry(domain());
+
+ if (m_animation)
+ presenter()->startAnimation(m_animation->candlestickAnimation(item));
+ }
+}
+
+void CandlestickChartItem::handleLayoutUpdated()
+{
+ bool timestampChanged = false;
+ foreach (QCandlestickSet *set, m_candlesticks.keys()) {
+ qreal oldTimestamp = m_candlesticks.value(set)->m_data.m_timestamp;
+ qreal newTimestamp = set->timestamp();
+ if (Q_UNLIKELY(oldTimestamp != newTimestamp)) {
+ removeTimestamp(oldTimestamp);
+ addTimestamp(newTimestamp);
+ timestampChanged = true;
+ }
+ }
+ if (timestampChanged)
+ updateTimePeriod();
+
+ foreach (Candlestick *item, m_candlesticks.values()) {
+ if (m_animation)
+ m_animation->setAnimationStart(item);
+
+ item->setTimePeriod(m_timePeriod);
+ item->setMaximumColumnWidth(m_series->maximumColumnWidth());
+ item->setMinimumColumnWidth(m_series->minimumColumnWidth());
+ item->setBodyWidth(m_series->bodyWidth());
+ item->setCapsWidth(m_series->capsWidth());
+
+ bool dirty = updateCandlestickGeometry(item, item->m_data.m_index);
+ if (dirty && m_animation)
+ presenter()->startAnimation(m_animation->candlestickChangeAnimation(item));
+ else
+ item->updateGeometry(domain());
+ }
+}
+
+void CandlestickChartItem::handleCandlesticksUpdated()
+{
+ foreach (QCandlestickSet *set, m_candlesticks.keys())
+ updateCandlestickAppearance(m_candlesticks.value(set), set);
+}
+
+void CandlestickChartItem::handleCandlestickSeriesChange()
+{
+ int seriesIndex = 0;
+ int seriesCount = 0;
+
+ int index = 0;
+ foreach (QAbstractSeries *series, m_series->chart()->series()) {
+ if (series->type() == QAbstractSeries::SeriesTypeCandlestick) {
+ if (m_series == static_cast<QCandlestickSeries *>(series))
+ seriesIndex = index;
+ index++;
+ }
+ }
+ seriesCount = index;
+
+ bool changed;
+ if ((m_seriesIndex != seriesIndex) || (m_seriesCount != seriesCount))
+ changed = true;
+ else
+ changed = false;
+
+ if (changed) {
+ m_seriesIndex = seriesIndex;
+ m_seriesCount = seriesCount;
+ handleDataStructureChanged();
+ }
+}
+
+void CandlestickChartItem::handleCandlestickSetsAdd(const QList<QCandlestickSet *> &sets)
+{
+ foreach (QCandlestickSet *set, sets) {
+ Candlestick *item = m_candlesticks.value(set, 0);
+ if (item) {
+ qWarning() << "There is already a candlestick for this set in the hash";
+ continue;
+ }
+
+ item = new Candlestick(set, domain(), this);
+ m_candlesticks.insert(set, item);
+ addTimestamp(set->timestamp());
+
+ connect(item, SIGNAL(clicked(QCandlestickSet *)),
+ m_series, SIGNAL(clicked(QCandlestickSet *)));
+ connect(item, SIGNAL(hovered(bool, QCandlestickSet *)),
+ m_series, SIGNAL(hovered(bool, QCandlestickSet *)));
+ connect(item, SIGNAL(pressed(QCandlestickSet *)),
+ m_series, SIGNAL(pressed(QCandlestickSet *)));
+ connect(item, SIGNAL(released(QCandlestickSet *)),
+ m_series, SIGNAL(released(QCandlestickSet *)));
+ connect(item, SIGNAL(doubleClicked(QCandlestickSet *)),
+ m_series, SIGNAL(doubleClicked(QCandlestickSet *)));
+ connect(item, SIGNAL(clicked(QCandlestickSet *)), set, SIGNAL(clicked()));
+ connect(item, SIGNAL(hovered(bool, QCandlestickSet *)), set, SIGNAL(hovered(bool)));
+ connect(item, SIGNAL(pressed(QCandlestickSet *)), set, SIGNAL(pressed()));
+ connect(item, SIGNAL(released(QCandlestickSet *)), set, SIGNAL(released()));
+ connect(item, SIGNAL(doubleClicked(QCandlestickSet *)), set, SIGNAL(doubleClicked()));
+ }
+
+ handleDataStructureChanged();
+}
+
+void CandlestickChartItem::handleCandlestickSetsRemove(const QList<QCandlestickSet *> &sets)
+{
+ foreach (QCandlestickSet *set, sets) {
+ Candlestick *item = m_candlesticks.value(set);
+
+ m_candlesticks.remove(set);
+ removeTimestamp(set->timestamp());
+
+ if (m_animation) {
+ ChartAnimation *animation = m_animation->candlestickAnimation(item);
+ if (animation) {
+ animation->stop();
+ delete animation;
+ }
+ }
+
+ delete item;
+ }
+
+ handleDataStructureChanged();
+}
+
+void CandlestickChartItem::handleDataStructureChanged()
+{
+ updateTimePeriod();
+
+ for (int i = 0; i < m_series->count(); ++i) {
+ QCandlestickSet *set = m_series->candlestickSets().at(i);
+ Candlestick *item = m_candlesticks.value(set);
+
+ updateCandlestickGeometry(item, i);
+ updateCandlestickAppearance(item, set);
+
+ item->updateGeometry(domain());
+
+ if (m_animation)
+ m_animation->addCandlestick(item);
+ }
+
+ handleDomainUpdated();
+}
+
+bool CandlestickChartItem::updateCandlestickGeometry(Candlestick *item, int index)
+{
+ bool changed = false;
+
+ QCandlestickSet *set = m_series->candlestickSets().at(index);
+ CandlestickData &data = item->m_data;
+
+ if ((data.m_open != set->open())
+ || (data.m_high != set->high())
+ || (data.m_low != set->low())
+ || (data.m_close != set->close())) {
+ changed = true;
+ }
+
+ data.m_timestamp = set->timestamp();
+ data.m_open = set->open();
+ data.m_high = set->high();
+ data.m_low = set->low();
+ data.m_close = set->close();
+ data.m_index = index;
+
+ data.m_maxX = domain()->maxX();
+ data.m_minX = domain()->minX();
+ data.m_maxY = domain()->maxY();
+ data.m_minY = domain()->minY();
+
+ data.m_series = m_series;
+ data.m_seriesIndex = m_seriesIndex;
+ data.m_seriesCount = m_seriesCount;
+
+ return changed;
+}
+
+void CandlestickChartItem::updateCandlestickAppearance(Candlestick *item, QCandlestickSet *set)
+{
+ item->setTimePeriod(m_timePeriod);
+ item->setMaximumColumnWidth(m_series->maximumColumnWidth());
+ item->setMinimumColumnWidth(m_series->minimumColumnWidth());
+ item->setBodyWidth(m_series->bodyWidth());
+ item->setBodyOutlineVisible(m_series->bodyOutlineVisible());
+ item->setCapsWidth(m_series->capsWidth());
+ item->setCapsVisible(m_series->capsVisible());
+ item->setIncreasingColor(m_series->increasingColor());
+ item->setDecreasingColor(m_series->decreasingColor());
+
+ // Set the decorative issues for the candlestick so that
+ // the brush and pen already defined for the set are kept.
+ if (set->brush() == Qt::NoBrush)
+ item->setBrush(m_series->brush());
+ else
+ item->setBrush(set->brush());
+
+ if (set->pen() == Qt::NoPen)
+ item->setPen(m_series->pen());
+ else
+ item->setPen(set->pen());
+}
+
+void CandlestickChartItem::addTimestamp(qreal timestamp)
+{
+ int index = 0;
+ for (int i = m_timestamps.count() - 1; i >= 0; --i) {
+ if (timestamp > m_timestamps.at(i)) {
+ index = i + 1;
+ break;
+ }
+ }
+ m_timestamps.insert(index, timestamp);
+}
+
+void CandlestickChartItem::removeTimestamp(qreal timestamp)
+{
+ m_timestamps.removeOne(timestamp);
+}
+
+void CandlestickChartItem::updateTimePeriod()
+{
+ if (m_timestamps.count() == 0) {
+ m_timePeriod = 0;
+ return;
+ }
+
+ if (m_timestamps.count() == 1) {
+ m_timePeriod = qAbs(domain()->maxX() - domain()->minX());
+ return;
+ }
+
+ qreal timePeriod = qAbs(m_timestamps.at(1) - m_timestamps.at(0));
+ for (int i = 1; i < m_timestamps.count(); ++i) {
+ timePeriod = qMin(timePeriod, qAbs(m_timestamps.at(i) - m_timestamps.at(i - 1)));
+ }
+ m_timePeriod = timePeriod;
+}
+
+#include "moc_candlestickchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/candlestickchartitem_p.h b/src/charts/candlestickchart/candlestickchartitem_p.h
new file mode 100644
index 00000000..ee3b1f71
--- /dev/null
+++ b/src/charts/candlestickchart/candlestickchartitem_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CANDLESTICKCHARTITEM_P_H
+#define CANDLESTICKCHARTITEM_P_H
+
+#include <private/chartitem_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class Candlestick;
+class CandlestickAnimation;
+class QCandlestickSeries;
+class QCandlestickSet;
+
+class CandlestickChartItem : public ChartItem
+{
+ Q_OBJECT
+
+public:
+ CandlestickChartItem(QCandlestickSeries *series, QGraphicsItem *item = nullptr);
+ ~CandlestickChartItem();
+
+ void setAnimation(CandlestickAnimation *animation);
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+public Q_SLOTS:
+ void handleDomainUpdated();
+ void handleLayoutUpdated();
+ void handleCandlesticksUpdated();
+ void handleCandlestickSeriesChange();
+
+private Q_SLOTS:
+ void handleCandlestickSetsAdd(const QList<QCandlestickSet *> &sets);
+ void handleCandlestickSetsRemove(const QList<QCandlestickSet *> &sets);
+ void handleDataStructureChanged();
+
+private:
+ bool updateCandlestickGeometry(Candlestick *item, int index);
+ void updateCandlestickAppearance(Candlestick *item, QCandlestickSet *set);
+
+ void addTimestamp(qreal timestamp);
+ void removeTimestamp(qreal timestamp);
+ void updateTimePeriod();
+
+protected:
+ QRectF m_boundingRect;
+ QCandlestickSeries *m_series; // Not owned.
+ int m_seriesIndex;
+ int m_seriesCount;
+ QHash<QCandlestickSet *, Candlestick *> m_candlesticks;
+ QList<qreal> m_timestamps;
+ qreal m_timePeriod;
+ CandlestickAnimation *m_animation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CANDLESTICKCHARTITEM_P_H
diff --git a/src/charts/candlestickchart/candlestickdata_p.h b/src/charts/candlestickchart/candlestickdata_p.h
new file mode 100644
index 00000000..8cb1ab8c
--- /dev/null
+++ b/src/charts/candlestickchart/candlestickdata_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CANDLESTICKDATA_P_H
+#define CANDLESTICKDATA_P_H
+
+#include <QtCharts/QCandlestickSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class CandlestickData
+{
+public:
+ CandlestickData() :
+ m_timestamp(0.0),
+ m_open(0.0),
+ m_high(0.0),
+ m_low(0.0),
+ m_close(0.0),
+ m_index(0),
+ m_maxX(0.0),
+ m_minX(0.0),
+ m_maxY(0.0),
+ m_minY(0.0),
+ m_series(nullptr),
+ m_seriesIndex(0),
+ m_seriesCount(0)
+ {
+ }
+
+ // Candlestick related statistics
+ qreal m_timestamp;
+ qreal m_open;
+ qreal m_high;
+ qreal m_low;
+ qreal m_close;
+ int m_index;
+
+ // Domain boundaries
+ qreal m_maxX;
+ qreal m_minX;
+ qreal m_maxY;
+ qreal m_minY;
+
+ // Series related data
+ QCandlestickSeries *m_series;
+ int m_seriesIndex;
+ int m_seriesCount;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CANDLESTICKDATA_P_H
diff --git a/src/charts/candlestickchart/qcandlestickmodelmapper.cpp b/src/charts/candlestickchart/qcandlestickmodelmapper.cpp
new file mode 100644
index 00000000..a66e82ab
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickmodelmapper.cpp
@@ -0,0 +1,706 @@
+/****************************************************************************
+**
+** 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/QCandlestickModelMapper>
+#include <QtCharts/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <QtCore/QAbstractItemModel>
+#include <private/qcandlestickmodelmapper_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QCandlestickModelMapper
+ \since 5.8
+ \inmodule Qt Charts
+ \brief Abstract model mapper class for candlestick series.
+
+ Model mappers allow the use of a QAbstractItemModel-derived model as a data source for a chart
+ series, creating a connection between a QCandlestickSeries and the model object. A model mapper
+ maintains an equal size across all \l {QCandlestickSet} {QCandlestickSets}.
+
+ \note The model used must support adding and removing rows/columns and modifying the data of the
+ cells.
+*/
+
+/*!
+ \property QCandlestickModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+
+/*!
+ \property QCandlestickModelMapper::series
+ \brief Defines the QCandlestickSeries object that is used by the mapper.
+
+ \note All data in the series is discarded when it is set to the mapper. When a new series is
+ specified, the old series is disconnected (preserving its data).
+*/
+
+/*!
+ \fn Qt::Orientation QCandlestickModelMapper::orientation() const
+ Returns the orientation that is used when QCandlestickModelMapper accesses the model. This
+ determines whether the consecutive values of the set are read from rows (Qt::Horizontal) or from
+ columns (Qt::Vertical).
+*/
+
+/*!
+ \fn void QCandlestickModelMapper::modelReplaced()
+ \brief Emitted when the model, to which the mapper is connected, has changed.
+ \sa model
+*/
+
+/*!
+ \fn void QCandlestickModelMapper::seriesReplaced()
+ \brief Emitted when the series to which mapper is connected to has changed.
+ \sa series
+*/
+
+/*!
+ Constructs a model mapper object as a child of \a parent.
+*/
+QCandlestickModelMapper::QCandlestickModelMapper(QObject *parent)
+ : QObject(parent),
+ d_ptr(new QCandlestickModelMapperPrivate(this))
+{
+}
+
+void QCandlestickModelMapper::setModel(QAbstractItemModel *model)
+{
+ Q_D(QCandlestickModelMapper);
+
+ if (d->m_model == model)
+ return;
+
+ if (d->m_model)
+ disconnect(d->m_model, 0, d, 0);
+
+ d->m_model = model;
+ emit modelReplaced();
+
+ if (!d->m_model)
+ return;
+
+ d->initializeCandlestickFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(modelReset()), d, SLOT(initializeCandlestickFromModel()));
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
+ d, SLOT(modelDataUpdated(QModelIndex, QModelIndex)));
+ connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
+ d, SLOT(modelHeaderDataUpdated(Qt::Orientation, int, int)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ d, SLOT(modelRowsInserted(QModelIndex, int, int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ d, SLOT(modelRowsRemoved(QModelIndex, int, int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex, int, int)),
+ d, SLOT(modelColumnsInserted(QModelIndex, int, int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)),
+ d, SLOT(modelColumnsRemoved(QModelIndex, int, int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(modelDestroyed()));
+}
+
+QAbstractItemModel *QCandlestickModelMapper::model() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_model;
+}
+
+void QCandlestickModelMapper::setSeries(QCandlestickSeries *series)
+{
+ Q_D(QCandlestickModelMapper);
+
+ if (d->m_series == series)
+ return;
+
+ if (d->m_series)
+ disconnect(d->m_series, 0, d, 0);
+
+ d->m_series = series;
+ emit seriesReplaced();
+
+ if (!d->m_series)
+ return;
+
+ d->initializeCandlestickFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(candlestickSetsAdded(QList<QCandlestickSet *>)),
+ d, SLOT(candlestickSetsAdded(QList<QCandlestickSet *>)));
+ connect(d->m_series, SIGNAL(candlestickSetsRemoved(QList<QCandlestickSet*>)),
+ d, SLOT(candlestickSetsRemoved(QList<QCandlestickSet *>)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(seriesDestroyed()));
+}
+
+QCandlestickSeries *QCandlestickModelMapper::series() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_series;
+}
+
+/*!
+ Sets the row/column of the model that contains the \a timestamp values of the sets in the
+ series. Default value is -1 (invalid mapping).
+*/
+void QCandlestickModelMapper::setTimestamp(int timestamp)
+{
+ Q_D(QCandlestickModelMapper);
+
+ timestamp = qMax(timestamp, -1);
+
+ if (d->m_timestamp == timestamp)
+ return;
+
+ d->m_timestamp = timestamp;
+ emit d->timestampChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the row/column of the model that contains the timestamp values of the sets in the
+ series. Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::timestamp() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_timestamp;
+}
+
+/*!
+ Sets the row/column of the model that contains the \a open values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+void QCandlestickModelMapper::setOpen(int open)
+{
+ Q_D(QCandlestickModelMapper);
+
+ open = qMax(open, -1);
+
+ if (d->m_open == open)
+ return;
+
+ d->m_open = open;
+ emit d->openChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the row/column of the model that contains the open values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::open() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_open;
+}
+
+/*!
+ Sets the row/column of the model that contains the \a high values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+void QCandlestickModelMapper::setHigh(int high)
+{
+ Q_D(QCandlestickModelMapper);
+
+ high = qMax(high, -1);
+
+ if (d->m_high == high)
+ return;
+
+ d->m_high = high;
+ emit d->highChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the row/column of the model that contains the high values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::high() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_high;
+}
+
+/*!
+ Sets the row/column of the model that contains the \a low values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+void QCandlestickModelMapper::setLow(int low)
+{
+ Q_D(QCandlestickModelMapper);
+
+ low = qMax(low, -1);
+
+ if (d->m_low == low)
+ return;
+
+ d->m_low = low;
+ emit d->lowChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the row/column of the model that contains the low values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::low() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_low;
+}
+
+/*!
+ Sets the row/column of the model that contains the \a close values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+void QCandlestickModelMapper::setClose(int close)
+{
+ Q_D(QCandlestickModelMapper);
+
+ close = qMax(close, -1);
+
+ if (d->m_close == close)
+ return;
+
+ d->m_close = close;
+ emit d->closeChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the row/column of the model that contains the close values of the sets in the series.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::close() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_close;
+}
+
+/*!
+ Sets the section of the model that is used as the data source for the first candlestick set.
+ Parameter \a firstCandlestickSetSection specifies the section of the model. Default value is -1.
+*/
+void QCandlestickModelMapper::setFirstCandlestickSetSection(int firstCandlestickSetSection)
+{
+ Q_D(QCandlestickModelMapper);
+
+ firstCandlestickSetSection = qMax(firstCandlestickSetSection, -1);
+
+ if (d->m_firstCandlestickSetSection == firstCandlestickSetSection)
+ return;
+
+ d->m_firstCandlestickSetSection = firstCandlestickSetSection;
+ emit d->firstCandlestickSetSectionChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the section of the model that is used as the data source for the first candlestick set.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::firstCandlestickSetSection() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_firstCandlestickSetSection;
+}
+
+/*!
+ Sets the section of the model that is used as the data source for the last candlestick set.
+ Parameter \a lastCandlestickSetSection specifies the section of the model. Default value is -1.
+*/
+void QCandlestickModelMapper::setLastCandlestickSetSection(int lastCandlestickSetSection)
+{
+ Q_D(QCandlestickModelMapper);
+
+ lastCandlestickSetSection = qMax(lastCandlestickSetSection, -1);
+
+ if (d->m_lastCandlestickSetSection == lastCandlestickSetSection)
+ return;
+
+ d->m_lastCandlestickSetSection = lastCandlestickSetSection;
+ emit d->lastCandlestickSetSectionChanged();
+ d->initializeCandlestickFromModel();
+}
+
+/*!
+ Returns the section of the model that is used as the data source for the last candlestick set.
+ Default value is -1 (invalid mapping).
+*/
+int QCandlestickModelMapper::lastCandlestickSetSection() const
+{
+ Q_D(const QCandlestickModelMapper);
+
+ return d->m_lastCandlestickSetSection;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QCandlestickModelMapperPrivate::QCandlestickModelMapperPrivate(QCandlestickModelMapper *q)
+ : QObject(q),
+ m_model(nullptr),
+ m_series(nullptr),
+ m_timestamp(-1),
+ m_open(-1),
+ m_high(-1),
+ m_low(-1),
+ m_close(-1),
+ m_firstCandlestickSetSection(-1),
+ m_lastCandlestickSetSection(-1),
+ m_modelSignalsBlock(false),
+ m_seriesSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QCandlestickModelMapperPrivate::initializeCandlestickFromModel()
+{
+ if (!m_model || !m_series)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+ m_candlestickSets.clear();
+
+ // create the initial candlestick sets
+ QList<QCandlestickSet *> candlestickSets;
+ for (int i = m_firstCandlestickSetSection; i <= m_lastCandlestickSetSection; ++i) {
+ QModelIndex timestampIndex = candlestickModelIndex(i, m_timestamp);
+ QModelIndex openIndex = candlestickModelIndex(i, m_open);
+ QModelIndex highIndex = candlestickModelIndex(i, m_high);
+ QModelIndex lowIndex = candlestickModelIndex(i, m_low);
+ QModelIndex closeIndex = candlestickModelIndex(i, m_close);
+ if (timestampIndex.isValid()
+ && openIndex.isValid()
+ && highIndex.isValid()
+ && lowIndex.isValid()
+ && closeIndex.isValid()) {
+ QCandlestickSet *set = new QCandlestickSet();
+ set->setTimestamp(m_model->data(timestampIndex, Qt::DisplayRole).toReal());
+ set->setOpen(m_model->data(openIndex, Qt::DisplayRole).toReal());
+ set->setHigh(m_model->data(highIndex, Qt::DisplayRole).toReal());
+ set->setLow(m_model->data(lowIndex, Qt::DisplayRole).toReal());
+ set->setClose(m_model->data(closeIndex, Qt::DisplayRole).toReal());
+
+ connect(set, SIGNAL(timestampChanged()), this, SLOT(candlestickSetChanged()));
+ connect(set, SIGNAL(openChanged()), this, SLOT(candlestickSetChanged()));
+ connect(set, SIGNAL(highChanged()), this, SLOT(candlestickSetChanged()));
+ connect(set, SIGNAL(lowChanged()), this, SLOT(candlestickSetChanged()));
+ connect(set, SIGNAL(closeChanged()), this, SLOT(candlestickSetChanged()));
+
+ candlestickSets.append(set);
+ } else {
+ break;
+ }
+ }
+ m_series->append(candlestickSets);
+ m_candlestickSets.append(candlestickSets);
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelDataUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ Q_Q(QCandlestickModelMapper);
+
+ if (!m_model || !m_series)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); ++column) {
+ index = topLeft.sibling(row, column);
+ QCandlestickSet *set = candlestickSet(index);
+ if (set) {
+ int pos = (q->orientation() == Qt::Vertical) ? row : column;
+ if (pos == m_timestamp)
+ set->setTimestamp(m_model->data(index).toReal());
+ else if (pos == m_open)
+ set->setOpen(m_model->data(index).toReal());
+ else if (pos == m_high)
+ set->setHigh(m_model->data(index).toReal());
+ else if (pos == m_low)
+ set->setLow(m_model->data(index).toReal());
+ else if (pos == m_close)
+ set->setClose(m_model->data(index).toReal());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first,
+ int last)
+{
+ Q_UNUSED(orientation);
+ Q_UNUSED(first);
+ Q_UNUSED(last);
+}
+
+void QCandlestickModelMapperPrivate::modelRowsInserted(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (q->orientation() == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_firstCandlestickSetSection || start <= m_lastCandlestickSetSection)
+ initializeCandlestickFromModel(); // if the changes affect the map - reinitialize
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (q->orientation() == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_firstCandlestickSetSection || start <= m_lastCandlestickSetSection)
+ initializeCandlestickFromModel(); // if the changes affect the map - reinitialize
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelColumnsInserted(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (q->orientation() == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_firstCandlestickSetSection || start <= m_lastCandlestickSetSection)
+ initializeCandlestickFromModel(); // if the changes affect the map - reinitialize
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (q->orientation() == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_firstCandlestickSetSection || start <= m_lastCandlestickSetSection)
+ initializeCandlestickFromModel(); // if the changes affect the map - reinitialize
+ blockSeriesSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::modelDestroyed()
+{
+ m_model = 0;
+}
+
+void QCandlestickModelMapperPrivate::candlestickSetsAdded(const QList<QCandlestickSet *> &sets)
+{
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.isEmpty())
+ return;
+
+ int firstIndex = m_series->candlestickSets().indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ m_lastCandlestickSetSection += sets.count();
+
+ blockModelSignals();
+ if (q->orientation() == Qt::Vertical)
+ m_model->insertColumns(firstIndex + m_firstCandlestickSetSection, sets.count());
+ else
+ m_model->insertRows(firstIndex + m_firstCandlestickSetSection, sets.count());
+
+ for (int i = 0; i < sets.count(); ++i) {
+ int section = i + firstIndex + m_firstCandlestickSetSection;
+ m_model->setData(candlestickModelIndex(section, m_timestamp), sets.at(i)->timestamp());
+ m_model->setData(candlestickModelIndex(section, m_open), sets.at(i)->open());
+ m_model->setData(candlestickModelIndex(section, m_high), sets.at(i)->high());
+ m_model->setData(candlestickModelIndex(section, m_low), sets.at(i)->low());
+ m_model->setData(candlestickModelIndex(section, m_close), sets.at(i)->close());
+ }
+ blockModelSignals(false);
+ initializeCandlestickFromModel();
+}
+
+void QCandlestickModelMapperPrivate::candlestickSetsRemoved(const QList<QCandlestickSet *> &sets)
+{
+ Q_Q(QCandlestickModelMapper);
+
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.isEmpty())
+ return;
+
+ int firstIndex = m_candlestickSets.indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ m_lastCandlestickSetSection -= sets.count();
+
+ for (int i = firstIndex + sets.count() - 1; i >= firstIndex; --i)
+ m_candlestickSets.removeAt(i);
+
+ blockModelSignals();
+ if (q->orientation() == Qt::Vertical)
+ m_model->removeColumns(firstIndex + m_firstCandlestickSetSection, sets.count());
+ else
+ m_model->removeRows(firstIndex + m_firstCandlestickSetSection, sets.count());
+ blockModelSignals(false);
+ initializeCandlestickFromModel();
+}
+
+void QCandlestickModelMapperPrivate::candlestickSetChanged()
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ QCandlestickSet *set = qobject_cast<QCandlestickSet *>(QObject::sender());
+ if (!set)
+ return;
+
+ int section = m_series->candlestickSets().indexOf(set);
+ if (section < 0)
+ return;
+
+ section += m_firstCandlestickSetSection;
+
+ blockModelSignals();
+ m_model->setData(candlestickModelIndex(section, m_timestamp), set->timestamp());
+ m_model->setData(candlestickModelIndex(section, m_open), set->open());
+ m_model->setData(candlestickModelIndex(section, m_high), set->high());
+ m_model->setData(candlestickModelIndex(section, m_low), set->low());
+ m_model->setData(candlestickModelIndex(section, m_close), set->close());
+ blockModelSignals(false);
+}
+
+void QCandlestickModelMapperPrivate::seriesDestroyed()
+{
+ m_series = 0;
+}
+
+QCandlestickSet *QCandlestickModelMapperPrivate::candlestickSet(QModelIndex index)
+{
+ Q_Q(QCandlestickModelMapper);
+
+ if (!index.isValid())
+ return 0;
+
+ int section = (q->orientation() == Qt::Vertical) ? index.column() : index.row();
+ int pos = (q->orientation() == Qt::Vertical) ? index.row() : index.column();
+
+ if (section < m_firstCandlestickSetSection || section > m_lastCandlestickSetSection)
+ return 0; // This part of model has not been mapped to any candlestick set.
+
+ if (pos != m_timestamp && pos != m_open && pos != m_high && pos != m_low && pos != m_close)
+ return 0; // This part of model has not been mapped to any candlestick set.
+
+ return m_series->candlestickSets().at(section - m_firstCandlestickSetSection);
+}
+
+QModelIndex QCandlestickModelMapperPrivate::candlestickModelIndex(int section, int pos)
+{
+ Q_Q(QCandlestickModelMapper);
+
+ if (section < m_firstCandlestickSetSection || section > m_lastCandlestickSetSection)
+ return QModelIndex(); // invalid
+
+ if (pos != m_timestamp && pos != m_open && pos != m_high && pos != m_low && pos != m_close)
+ return QModelIndex(); // invalid
+
+ if (q->orientation() == Qt::Vertical)
+ return m_model->index(pos, section);
+ else
+ return m_model->index(section, pos);
+}
+
+void QCandlestickModelMapperPrivate::insertData(int start, int end)
+{
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+
+ // Currently candlestickchart needs to be fully recalculated when change is made.
+ initializeCandlestickFromModel();
+}
+
+void QCandlestickModelMapperPrivate::removeData(int start, int end)
+{
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+
+ // Currently candlestickchart needs to be fully recalculated when change is made.
+ initializeCandlestickFromModel();
+}
+
+void QCandlestickModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QCandlestickModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+#include "moc_qcandlestickmodelmapper.cpp"
+#include "moc_qcandlestickmodelmapper_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/qcandlestickmodelmapper.h b/src/charts/candlestickchart/qcandlestickmodelmapper.h
new file mode 100644
index 00000000..217468c9
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickmodelmapper.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QCANDLESTICKMODELMAPPER_H
+#define QCANDLESTICKMODELMAPPER_H
+
+#include <QtCharts/QChartGlobal>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QAbstractItemModel;
+QT_END_NAMESPACE
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickModelMapperPrivate;
+class QCandlestickSeries;
+
+class QT_CHARTS_EXPORT QCandlestickModelMapper : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(QCandlestickSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+
+public:
+ explicit QCandlestickModelMapper(QObject *parent = nullptr);
+
+ void setModel(QAbstractItemModel *model);
+ QAbstractItemModel *model() const;
+
+ void setSeries(QCandlestickSeries *series);
+ QCandlestickSeries *series() const;
+
+ virtual Qt::Orientation orientation() const = 0;
+
+Q_SIGNALS:
+ void modelReplaced();
+ void seriesReplaced();
+
+protected:
+ void setTimestamp(int timestamp);
+ int timestamp() const;
+
+ void setOpen(int open);
+ int open() const;
+
+ void setHigh(int high);
+ int high() const;
+
+ void setLow(int low);
+ int low() const;
+
+ void setClose(int close);
+ int close() const;
+
+ void setFirstCandlestickSetSection(int firstCandlestickSetSection);
+ int firstCandlestickSetSection() const;
+
+ void setLastCandlestickSetSection(int lastCandlestickSetSection);
+ int lastCandlestickSetSection() const;
+
+protected:
+ QCandlestickModelMapperPrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QCandlestickModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKMODELMAPPER_H
diff --git a/src/charts/candlestickchart/qcandlestickmodelmapper_p.h b/src/charts/candlestickchart/qcandlestickmodelmapper_p.h
new file mode 100644
index 00000000..df84e3f2
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickmodelmapper_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QCANDLESTICKMODELMAPPER_P_H
+#define QCANDLESTICKMODELMAPPER_P_H
+
+#include <QtCharts/QCandlestickModelMapper>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QModelIndex;
+QT_END_NAMESPACE
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickSet;
+
+class QCandlestickModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QCandlestickModelMapperPrivate(QCandlestickModelMapper *q);
+
+Q_SIGNALS:
+ void timestampChanged();
+ void openChanged();
+ void highChanged();
+ void lowChanged();
+ void closeChanged();
+ void firstCandlestickSetSectionChanged();
+ void lastCandlestickSetSectionChanged();
+
+private Q_SLOTS:
+ void initializeCandlestickFromModel();
+
+ // for the model
+ void modelDataUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last);
+ void modelRowsInserted(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsInserted(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void modelDestroyed();
+
+ // for the series
+ void candlestickSetsAdded(const QList<QCandlestickSet *> &sets);
+ void candlestickSetsRemoved(const QList<QCandlestickSet *> &sets);
+ void candlestickSetChanged();
+ void seriesDestroyed();
+
+private:
+ QCandlestickSet *candlestickSet(QModelIndex index);
+ QModelIndex candlestickModelIndex(int section, int pos);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+
+private:
+ QAbstractItemModel *m_model;
+ QCandlestickSeries *m_series;
+ int m_timestamp;
+ int m_open;
+ int m_high;
+ int m_low;
+ int m_close;
+ int m_firstCandlestickSetSection;
+ int m_lastCandlestickSetSection;
+ QList<QCandlestickSet *> m_candlestickSets;
+ bool m_modelSignalsBlock;
+ bool m_seriesSignalsBlock;
+
+private:
+ QCandlestickModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QCandlestickModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKMODELMAPPER_P_H
diff --git a/src/charts/candlestickchart/qcandlestickseries.cpp b/src/charts/candlestickchart/qcandlestickseries.cpp
new file mode 100644
index 00000000..2e04d6cf
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickseries.cpp
@@ -0,0 +1,1138 @@
+/****************************************************************************
+**
+** 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 Qt Charts
+ \brief Series for creating a candlestick chart.
+
+ QCandlestickSeries represents a series of data shown as candlesticks. The purpose of this class
+ is to act 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 2.2
+ \instantiates QCandlestickSeries
+ \inqmlmodule QtCharts
+ \inherits AbstractSeries
+ \brief Series for creating a candlestick chart.
+
+ CandlestickSeries represents a series of data shown as candlesticks. The purpose of this class
+ is to act 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
+*/
+
+/*!
+ \property QCandlestickSeries::count
+ \brief The count of sets in series.
+*/
+
+/*!
+ \qmlproperty int CandlestickSeries::count
+ The count of sets in 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 qreal CandlestickSeries::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.
+*/
+
+/*!
+ \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 qreal CandlestickSeries::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.
+*/
+
+/*!
+ \property QCandlestickSeries::bodyWidth
+ \brief The width of the candlestick items.
+
+ The value signifies the relative width of the candlestick item inside its own slot, in the range
+ 0.0 to 1.0. Values outside this range are clamped to 0.0 or 1.0.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSeries::bodyWidth
+ \brief The width of the candlestick items.
+
+ The value signifies the relative width of the candlestick item inside its own slot, in the range
+ 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 outlines.
+*/
+
+/*!
+ \qmlproperty bool CandlestickSeries::bodyOutlineVisible
+ \brief The visibility of the candlestick body outlines.
+*/
+
+/*!
+ \property QCandlestickSeries::capsWidth
+ \brief The width of the caps.
+
+ The value signifies the relative width of the caps inside its own candlestick, in the range 0.0
+ to 1.0. Values outside this range are clamped to 0.0 or 1.0.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSeries::capsWidth
+ \brief The width of the caps.
+
+ The value signifies the relative width of the caps inside its own candlestick, in the range 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
+ \brief The visibility of the caps.
+*/
+
+/*!
+ \property QCandlestickSeries::increasingColor
+ \brief The color of the increasing candlestick item body. Candlestick is \e increasing when its
+ close value is higher than the open value. By default this property is set to brush color.
+ Default color is used also when the property is set to an invalid color value.
+*/
+
+/*!
+ \qmlproperty QColor CandlestickSeries::increasingColor
+ \brief The color of the increasing candlestick item body. Candlestick is \e increasing when its
+ close value is higher than the open value. By default this property is set to brush color.
+ 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. Candlestick is \e decreasing when its
+ open value is higher than the close value. By default this property is set to brush color with
+ alpha channel set to 128. Default color is used also when the property is set to an invalid
+ color value.
+*/
+
+/*!
+ \qmlproperty QColor CandlestickSeries::decreasingColor
+ \brief The color of the decreasing candlestick item body. Candlestick is \e decreasing when its
+ open value is higher than the close value. By default this property is set to brush color with
+ alpha channel set to 128. Default color is used also when the property is set to an invalid
+ color value.
+*/
+
+/*!
+ \property QCandlestickSeries::brush
+ \brief The brush of the candlestick items.
+*/
+
+/*!
+ \property QCandlestickSeries::pen
+ \brief The pen of the candlestick items.
+*/
+
+/*!
+ \qmlproperty QString CandlestickSeries::brushFilename
+ \brief The name of the file used as a brush for the series.
+*/
+
+/*!
+ \fn void QCandlestickSeries::clicked(QCandlestickSet *set)
+ \brief Emitted when a \a set is clicked (pressed and released) on the chart.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::clicked(CandlestickSet set)
+ \brief Emitted when a \a set is clicked (pressed and released) on the chart.
+
+ The corresponding signal handler is \c {onClicked}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::hovered(bool status, QCandlestickSet *set)
+ \brief Emitted when there is change in hover \a status over the \a set.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::hovered(bool status, CandlestickSet set)
+ \brief Emitted when there is change in hover \a status over the \a set.
+
+ The corresponding signal handler is \c {onHovered}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::pressed(QCandlestickSet *set)
+ \brief Emitted when a \a set is pressed on the chart.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::pressed(CandlestickSet set)
+ \brief Emitted when a \a set is pressed on the chart.
+
+ The corresponding signal handler is \c {onPressed}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::released(QCandlestickSet *set)
+ \brief Emitted when a \a set is released on the chart.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::released(CandlestickSet set)
+ \brief Emitted when a \a set is released on the chart.
+
+ The corresponding signal handler is \c {onReleased}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::doubleClicked(QCandlestickSet *set)
+ \brief Emitted when a \a set is double-clicked on the chart.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::doubleClicked(CandlestickSet set)
+ \brief Emitted when a \a set is double-clicked on the chart.
+
+ The corresponding signal handler is \c {onDoubleClicked}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::candlestickSetsAdded(const QList<QCandlestickSet *> &sets)
+ \brief Emitted when new \a sets are added to the series.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::candlestickSetsAdded(list<CandlestickSet> sets)
+ \brief Emitted when new \a sets are added to the series.
+
+ The corresponding signal handler is \c {onCandlestickSetsAdded}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::candlestickSetsRemoved(const QList<QCandlestickSet *> &sets)
+ \brief Emitted when \a sets are removed from the series.
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::candlestickSetsRemoved(list<CandlestickSet> sets)
+ \brief Emitted when \a sets are removed from the series.
+
+ The corresponding signal handler is \c {onCandlestickSetsRemoved}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::countChanged()
+ \brief Emitted when there is a change in the count of candlestick items in the series.
+ \sa count
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::countChanged()
+ \brief Emitted when there is a change in the count of candlestick items in the series.
+ \sa count
+
+ The corresponding signal handler is \c {onCountChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::maximumColumnWidthChanged()
+ \brief Emitted when there is a change in the maximum column width of candlestick items.
+ \sa maximumColumnWidth
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::maximumColumnWidthChanged()
+ \brief Emitted when there is a change in the maximum column width of candlestick items.
+ \sa maximumColumnWidth
+
+ The corresponding signal handler is \c {onMaximumColumnWidthChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::minimumColumnWidthChanged()
+ \brief Emitted when there is a change in the minimum column width of candlestick items.
+ \sa minimumColumnWidth
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::minimumColumnWidthChanged()
+ \brief Emitted when there is a change in the minimum column width of candlestick items.
+ \sa minimumColumnWidth
+
+ The corresponding signal handler is \c {onMinimumColumnWidthChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::bodyWidthChanged()
+ \brief Emitted when the candlestick item width is changed.
+ \sa bodyWidth
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::bodyWidthChanged()
+ \brief Emitted when the candlestick item width is changed.
+ \sa bodyWidth
+
+ The corresponding signal handler is \c {onBodyWidthChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::bodyOutlineVisibilityChanged()
+ \brief Emitted when the visibility of the candlestick item body outline is changed.
+ \sa bodyOutlineVisible
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::bodyOutlineVisibilityChanged()
+ \brief Emitted when the visibility of the candlestick item body outline is changed.
+ \sa bodyOutlineVisible
+
+ The corresponding signal handler is \c {onBodyOutlineVisibilityChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::capsWidthChanged()
+ \brief Emitted when the candlestick item caps width is changed.
+ \sa capsWidth
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::capsWidthChanged()
+ \brief Emitted when the candlestick item caps width is changed.
+ \sa capsWidth
+
+ The corresponding signal handler is \c {onCapsWidthChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::capsVisibilityChanged()
+ \brief Emitted when the visibility of the candlestick item caps is changed.
+ \sa capsVisible
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::capsVisibilityChanged()
+ \brief Emitted when the visibility of the candlestick item caps is changed.
+ \sa capsVisible
+
+ The corresponding signal handler is \c {onCapsVisibilityChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::increasingColorChanged()
+ \brief Emitted when the candlestick item increasing color is changed.
+ \sa increasingColor
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::increasingColorChanged()
+ \brief Emitted when the candlestick item increasing color is changed.
+ \sa increasingColor
+
+ The corresponding signal handler is \c {onIncreasingColorChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::decreasingColorChanged()
+ \brief Emitted when the candlestick item decreasing color is changed.
+ \sa decreasingColor
+*/
+
+/*!
+ \qmlsignal CandlestickSeries::decreasingColorChanged()
+ \brief Emitted when the candlestick item decreasing color is changed.
+ \sa decreasingColor
+
+ The corresponding signal handler is \c {onDecreasingColorChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSeries::brushChanged()
+ \brief Emitted when the candlestick item brush is changed.
+ \sa brush
+*/
+
+/*!
+ \fn void QCandlestickSeries::penChanged()
+ \brief Emitted when the candlestick item pen is changed.
+ \sa pen
+*/
+
+/*!
+ 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);
+}
+
+/*!
+ Adds a single set to the series. Takes ownership of the \a set. If the set is \e null or is
+ already in the series, it won't be appended.
+ Returns \c true if appending succeeded, \c false otherwise.
+*/
+bool QCandlestickSeries::append(QCandlestickSet *set)
+{
+ QList<QCandlestickSet *> sets;
+ sets.append(set);
+
+ return append(sets);
+}
+
+/*!
+ Removes a single set from the series.
+ Returns \c true if the \a set is successfully deleted, \c false otherwise.
+*/
+bool QCandlestickSeries::remove(QCandlestickSet *set)
+{
+ QList<QCandlestickSet *> sets;
+ sets.append(set);
+
+ return remove(sets);
+}
+
+/*!
+ Adds a list of sets to the series. Takes ownership of the \a sets. If any of the sets are
+ \e null, already appended to the series, or the list contains duplicated sets, nothing is
+ appended.
+ Returns \c true if all sets 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 sets from the series. If any of the \a sets are \e null, already removed from
+ the series, or the list contains duplicated sets, nothing is removed.
+ Returns \c true if all sets 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)
+ set->deleteLater();
+ }
+
+ return success;
+}
+
+/*!
+ Inserts a set to the series at \a index position. Takes ownership of the \a set. If the set is
+ \e null or already in the series, it won't be appended.
+ 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 \a set from the series. Does not delete the set object.
+ Returns \c true if take was successful, \c false otherwise.
+ \note The series remains as the set'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;
+}
+
+/*!
+ Removes all sets from the series, and deletes them.
+*/
+void QCandlestickSeries::clear()
+{
+ Q_D(QCandlestickSeries);
+
+ QList<QCandlestickSet *> sets = candlestickSets();
+
+ bool success = d->remove(sets);
+ if (success) {
+ emit candlestickSetsRemoved(sets);
+ emit countChanged();
+ foreach (QCandlestickSet *set, sets)
+ set->deleteLater();
+ }
+}
+
+/*!
+ Returns the list of sets in the series. Ownership of the sets is unchanged.
+ */
+QList<QCandlestickSet *> QCandlestickSeries::candlestickSets() const
+{
+ Q_D(const QCandlestickSeries);
+
+ return d->m_candlestickSets;
+}
+
+/*!
+ Returns the number of the sets in the series.
+*/
+int QCandlestickSeries::count() const
+{
+ return candlestickSets().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);
+}
+
+void QCandlestickSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal maxX(domain()->maxX());
+ qreal minY(domain()->minY());
+ qreal maxY(domain()->maxY());
+
+ if (m_candlestickSets.count()) {
+ QCandlestickSet *set = m_candlestickSets.first();
+ minX = set->timestamp();
+ maxX = set->timestamp();
+ minY = set->low();
+ maxY = set->high();
+ for (int i = 1; i < m_candlestickSets.count(); ++i) {
+ set = m_candlestickSets.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_candlestickSets.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_candlestickSets.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_candlestickSets.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_candlestickSets.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_candlestickSets.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_candlestickSets.contains(set)) || (set == 0) || set->d_ptr->m_series)
+ return false; // Fail if set is already in list or set is null.
+
+ m_candlestickSets.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_candlestickSets.count(); ++i) {
+ const qint64 timestamp = qRound64(m_candlestickSets.at(i)->timestamp());
+ const QString timestampFormat = m_chart->locale().dateTimeFormat(QLocale::ShortFormat);
+ categories << QDateTime::fromMSecsSinceEpoch(timestamp).toString(timestampFormat);
+ }
+ axis->append(categories);
+ }
+}
+
+#include "moc_qcandlestickseries.cpp"
+#include "moc_qcandlestickseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/qcandlestickseries.h b/src/charts/candlestickchart/qcandlestickseries.h
new file mode 100644
index 00000000..3dea6433
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickseries.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QCANDLESTICKSERIES_H
+#define QCANDLESTICKSERIES_H
+
+#include <QtCharts/QAbstractSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickSeriesPrivate;
+class QCandlestickSet;
+
+class QT_CHARTS_EXPORT QCandlestickSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(qreal maximumColumnWidth READ maximumColumnWidth WRITE setMaximumColumnWidth NOTIFY maximumColumnWidthChanged)
+ Q_PROPERTY(qreal minimumColumnWidth READ minimumColumnWidth WRITE setMinimumColumnWidth NOTIFY minimumColumnWidthChanged)
+ Q_PROPERTY(qreal bodyWidth READ bodyWidth WRITE setBodyWidth NOTIFY bodyWidthChanged)
+ Q_PROPERTY(bool bodyOutlineVisible READ bodyOutlineVisible WRITE setBodyOutlineVisible NOTIFY bodyOutlineVisibilityChanged)
+ Q_PROPERTY(qreal capsWidth READ capsWidth WRITE setCapsWidth NOTIFY capsWidthChanged)
+ Q_PROPERTY(bool capsVisible READ capsVisible WRITE setCapsVisible NOTIFY capsVisibilityChanged)
+ Q_PROPERTY(QColor increasingColor READ increasingColor WRITE setIncreasingColor NOTIFY increasingColorChanged)
+ Q_PROPERTY(QColor decreasingColor READ decreasingColor WRITE setDecreasingColor NOTIFY decreasingColorChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+
+public:
+ explicit QCandlestickSeries(QObject *parent = nullptr);
+ ~QCandlestickSeries();
+
+ bool append(QCandlestickSet *set);
+ bool remove(QCandlestickSet *set);
+ bool append(const QList<QCandlestickSet *> &sets);
+ bool remove(const QList<QCandlestickSet *> &sets);
+ bool insert(int index, QCandlestickSet *set);
+ bool take(QCandlestickSet *set);
+ void clear();
+
+ QList<QCandlestickSet *> candlestickSets() const;
+ int count() const;
+
+ QAbstractSeries::SeriesType type() const;
+
+ void setMaximumColumnWidth(qreal maximumColumnWidth);
+ qreal maximumColumnWidth() const;
+
+ void setMinimumColumnWidth(qreal minimumColumnWidth);
+ qreal minimumColumnWidth() const;
+
+ void setBodyWidth(qreal bodyWidth);
+ qreal bodyWidth() const;
+
+ void setBodyOutlineVisible(bool bodyOutlineVisible);
+ bool bodyOutlineVisible() const;
+
+ void setCapsWidth(qreal capsWidth);
+ qreal capsWidth() const;
+
+ void setCapsVisible(bool capsVisible);
+ bool capsVisible() const;
+
+ void setIncreasingColor(const QColor &increasingColor);
+ QColor increasingColor() const;
+
+ void setDecreasingColor(const QColor &decreasingColor);
+ QColor decreasingColor() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+Q_SIGNALS:
+ void clicked(QCandlestickSet *set);
+ void hovered(bool status, QCandlestickSet *set);
+ void pressed(QCandlestickSet *set);
+ void released(QCandlestickSet *set);
+ void doubleClicked(QCandlestickSet *set);
+ void candlestickSetsAdded(const QList<QCandlestickSet *> &sets);
+ void candlestickSetsRemoved(const QList<QCandlestickSet *> &sets);
+ void countChanged();
+ void maximumColumnWidthChanged();
+ void minimumColumnWidthChanged();
+ void bodyWidthChanged();
+ void bodyOutlineVisibilityChanged();
+ void capsWidthChanged();
+ void capsVisibilityChanged();
+ void increasingColorChanged();
+ void decreasingColorChanged();
+ void brushChanged();
+ void penChanged();
+
+private:
+ Q_DISABLE_COPY(QCandlestickSeries)
+ Q_DECLARE_PRIVATE(QCandlestickSeries)
+ friend class CandlestickChartItem;
+ friend class QCandlestickLegendMarkerPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKSERIES_H
diff --git a/src/charts/candlestickchart/qcandlestickseries_p.h b/src/charts/candlestickchart/qcandlestickseries_p.h
new file mode 100644
index 00000000..7ee50103
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickseries_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QCANDLESTICKSERIES_P_H
+#define QCANDLESTICKSERIES_P_H
+
+#include <private/qabstractseries_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class CandlestickAnimation;
+class QBarCategoryAxis;
+class QCandlestickSeries;
+class QCandlestickSet;
+class QDateTimeAxis;
+
+class QCandlestickSeriesPrivate : public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QCandlestickSeriesPrivate(QCandlestickSeries *q);
+ ~QCandlestickSeriesPrivate();
+
+ void initializeDomain();
+ void initializeAxes();
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeAnimations(QChart::AnimationOptions options, int duration, QEasingCurve &curve);
+
+ QList<QLegendMarker *> createLegendMarkers(QLegend *legend);
+
+ virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis *createDefaultAxis(Qt::Orientation orientation) const;
+
+ bool append(const QList<QCandlestickSet *> &sets);
+ bool remove(const QList<QCandlestickSet *> &sets);
+ bool insert(int index, QCandlestickSet *set);
+
+Q_SIGNALS:
+ void clicked(int index, QCandlestickSet *set);
+ void pressed(int index, QCandlestickSet *set);
+ void released(int index, QCandlestickSet *set);
+ void doubleClicked(int index, QCandlestickSet *set);
+ void updated();
+ void updatedLayout();
+ void updatedCandlesticks();
+
+private Q_SLOTS:
+ void handleSeriesChange(QAbstractSeries *series);
+ void handleSeriesRemove(QAbstractSeries *series);
+
+private:
+ void populateBarCategories(QBarCategoryAxis *axis);
+
+protected:
+ QList<QCandlestickSet *> m_candlestickSets;
+ qreal m_maximumColumnWidth;
+ qreal m_minimumColumnWidth;
+ qreal m_bodyWidth;
+ bool m_bodyOutlineVisible;
+ qreal m_capsWidth;
+ bool m_capsVisible;
+ QColor m_increasingColor;
+ QColor m_decreasingColor;
+ bool m_customIncreasingColor;
+ bool m_customDecreasingColor;
+ QBrush m_brush;
+ QPen m_pen;
+ CandlestickAnimation *m_animation;
+
+private:
+ Q_DECLARE_PUBLIC(QCandlestickSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKSERIES_P_H
diff --git a/src/charts/candlestickchart/qcandlestickset.cpp b/src/charts/candlestickchart/qcandlestickset.cpp
new file mode 100644
index 00000000..99779ef7
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickset.cpp
@@ -0,0 +1,487 @@
+/****************************************************************************
+**
+** 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/QCandlestickSet>
+#include <private/qcandlestickset_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QCandlestickSet
+ \since 5.8
+ \inmodule Qt Charts
+ \brief Building block for a candlestick chart.
+
+ QCandlestickSet represents a single candlestick item in a QCandlestickSeries. It takes five
+ values to create a graphical representation of a candlestick item: \e open, \e high, \e low,
+ \e close, and \e timestamp. These values can be either passed to a QCandlestickSet constructor,
+ or set by using setOpen(), setHigh(), setLow(), setClose(), and setTimestamp().
+
+ \sa QCandlestickSeries
+*/
+
+/*!
+ \qmltype CandlestickSet
+ \since 2.2
+ \instantiates QCandlestickSet
+ \inqmlmodule QtCharts
+ \brief Building block for a candlestick chart.
+
+ CandlestickSet represents a single candlestick item in a CandlestickSeries. It takes five
+ values to create a graphical representation of a candlestick item: \l open, \l high, \l low,
+ \l close, and \l timestamp.
+
+ \sa CandlestickSeries
+*/
+
+/*!
+ \property QCandlestickSet::timestamp
+ \brief The timestamp value of the set.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSet::timestamp
+ \brief The timestamp value of the set.
+*/
+
+/*!
+ \property QCandlestickSet::open
+ \brief The open value of the set.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSet::open
+ \brief The open value of the set.
+*/
+
+/*!
+ \property QCandlestickSet::high
+ \brief The high value of the set.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSet::high
+ \brief The high value of the set.
+*/
+
+/*!
+ \property QCandlestickSet::low
+ \brief The low value of the set.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSet::low
+ \brief The low value of the set.
+*/
+
+/*!
+ \property QCandlestickSet::close
+ \brief The close value of the set.
+*/
+
+/*!
+ \qmlproperty qreal CandlestickSet::close
+ \brief The close value of the set.
+*/
+
+/*!
+ \property QCandlestickSet::brush
+ \brief The brush used for drawing the candlestick.
+*/
+
+/*!
+ \property QCandlestickSet::pen
+ \brief The pen used for drawing the candlestick.
+*/
+
+/*!
+ \qmlproperty QString CandlestickSet::brushFilename
+ \brief The name of the file used as a brush for the set.
+*/
+
+/*!
+ \fn void QCandlestickSet::clicked()
+ \brief Emitted when the candlestick item is clicked (pressed and released).
+*/
+
+/*!
+ \qmlsignal CandlestickSet::clicked()
+ \brief Emitted when the candlestick item is clicked (pressed and released).
+
+ The corresponding signal handler is \c {onClicked}.
+*/
+
+/*!
+ \fn void QCandlestickSet::hovered(bool status)
+ \brief Emitted when there is change in hover \a status over a candlestick item.
+
+ Parameter \a status indicates whether the mouse has entered (\c true) or left (\c false) the
+ area of the candlestick item.
+*/
+
+/*!
+ \qmlsignal CandlestickSet::hovered(bool status)
+ \brief Emitted when there is change in hover \a status over a candlestick item.
+
+ Parameter \a status indicates whether the mouse has entered (\c true) or left (\c false) the
+ area of the candlestick item.
+
+ The corresponding signal handler is \c {onHovered}.
+*/
+
+/*!
+ \fn void QCandlestickSet::pressed()
+ \brief Emitted when there is a press on a candlestick item.
+*/
+
+/*!
+ \qmlsignal CandlestickSet::pressed()
+ \brief Emitted when there is a press on a candlestick item.
+
+ The corresponding signal handler is \c {onPressed}.
+*/
+
+/*!
+ \fn void QCandlestickSet::released()
+ \brief Emitted when there is a release on a candlestick item.
+*/
+
+/*!
+ \qmlsignal CandlestickSet::released()
+ \brief Emitted when there is a release on a candlestick item.
+
+ The corresponding signal handler is \c {onReleased}.
+*/
+
+/*!
+ \fn void QCandlestickSet::doubleClicked()
+ \brief Emitted when there is a double-click on a candlestick item.
+*/
+
+/*!
+ \qmlsignal CandlestickSet::doubleClicked()
+ \brief Emitted when there is a double-click on a candlestick item.
+
+ The corresponding signal handler is \c {onDoubleClicked}.
+*/
+
+/*!
+ \fn void QCandlestickSet::timestampChanged()
+ \brief Emitted when the candlestick item timestamp is changed.
+ \sa timestamp
+*/
+
+/*!
+ \qmlsignal CandlestickSet::timestampChanged()
+ \brief Emitted when the candlestick item timestamp is changed.
+ \sa timestamp
+
+ The corresponding signal handler is \c {onTimestampChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSet::openChanged()
+ \brief Emitted when the candlestick item open value is changed.
+ \sa open
+*/
+
+/*!
+ \qmlsignal CandlestickSet::openChanged()
+ \brief Emitted when the candlestick item open value is changed.
+ \sa open
+
+ The corresponding signal handler is \c {onOpenChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSet::highChanged()
+ \brief Emitted when the candlestick item high value is changed.
+ \sa high
+*/
+
+/*!
+ \qmlsignal CandlestickSet::highChanged()
+ \brief Emitted when the candlestick item high value is changed.
+ \sa high
+
+ The corresponding signal handler is \c {onHighChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSet::lowChanged()
+ \brief Emitted when the candlestick item low value is changed.
+ \sa low
+*/
+
+/*!
+ \qmlsignal CandlestickSet::lowChanged()
+ \brief Emitted when the candlestick item low value is changed.
+ \sa low
+
+ The corresponding signal handler is \c {onLowChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSet::closeChanged()
+ \brief Emitted when the candlestick item close value is changed.
+ \sa close
+*/
+
+/*!
+ \qmlsignal CandlestickSet::closeChanged()
+ \brief Emitted when the candlestick item close value is changed.
+ \sa close
+
+ The corresponding signal handler is \c {onCloseChanged}.
+*/
+
+/*!
+ \fn void QCandlestickSet::brushChanged()
+ \brief Emitted when the candlestick item brush is changed.
+ \sa brush
+*/
+
+/*!
+ \fn void QCandlestickSet::penChanged()
+ \brief Emitted when the candlestick item pen is changed.
+ \sa pen
+*/
+
+/*!
+ Constructs a QCandlestickSet with an optional \a timestamp and a \a parent.
+*/
+QCandlestickSet::QCandlestickSet(qreal timestamp, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QCandlestickSetPrivate(timestamp, this))
+{
+}
+
+/*!
+ Constructs a QCandlestickSet with given ordered values. The values \a open, \a high, \a low
+ and \a close are mandatory. The values \a timestamp and \a parent are optional.
+*/
+QCandlestickSet::QCandlestickSet(qreal open, qreal high, qreal low, qreal close, qreal timestamp,
+ QObject *parent)
+ : QObject(parent),
+ d_ptr(new QCandlestickSetPrivate(timestamp, this))
+{
+ Q_D(QCandlestickSet);
+
+ d->m_open = open;
+ d->m_high = high;
+ d->m_low = low;
+ d->m_close = close;
+
+ emit d->updatedLayout();
+}
+
+/*!
+ Destroys the set.
+*/
+QCandlestickSet::~QCandlestickSet()
+{
+}
+
+void QCandlestickSet::setTimestamp(qreal timestamp)
+{
+ Q_D(QCandlestickSet);
+
+ bool changed = d->setTimestamp(timestamp);
+ if (!changed)
+ return;
+
+ emit d->updatedLayout();
+ emit timestampChanged();
+}
+
+qreal QCandlestickSet::timestamp() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_timestamp;
+}
+
+void QCandlestickSet::setOpen(qreal open)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_open == open)
+ return;
+
+ d->m_open = open;
+
+ emit d->updatedLayout();
+ emit openChanged();
+}
+
+qreal QCandlestickSet::open() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_open;
+}
+
+void QCandlestickSet::setHigh(qreal high)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_high == high)
+ return;
+
+ d->m_high = high;
+
+ emit d->updatedLayout();
+ emit highChanged();
+}
+
+qreal QCandlestickSet::high() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_high;
+}
+
+void QCandlestickSet::setLow(qreal low)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_low == low)
+ return;
+
+ d->m_low = low;
+
+ emit d->updatedLayout();
+ emit lowChanged();
+}
+
+qreal QCandlestickSet::low() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_low;
+}
+
+void QCandlestickSet::setClose(qreal close)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_close == close)
+ return;
+
+ d->m_close = close;
+
+ emit d->updatedLayout();
+ emit closeChanged();
+}
+
+qreal QCandlestickSet::close() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_close;
+}
+
+void QCandlestickSet::setBrush(const QBrush &brush)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_brush == brush)
+ return;
+
+ d->m_brush = brush;
+
+ emit d->updatedCandlestick();
+ emit brushChanged();
+}
+
+QBrush QCandlestickSet::brush() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_brush;
+}
+
+void QCandlestickSet::setPen(const QPen &pen)
+{
+ Q_D(QCandlestickSet);
+
+ if (d->m_pen == pen)
+ return;
+
+ d->m_pen = pen;
+
+ emit d->updatedCandlestick();
+ emit penChanged();
+}
+
+QPen QCandlestickSet::pen() const
+{
+ Q_D(const QCandlestickSet);
+
+ return d->m_pen;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QCandlestickSetPrivate::QCandlestickSetPrivate(qreal timestamp, QCandlestickSet *parent)
+ : QObject(parent),
+ q_ptr(parent),
+ m_timestamp(0.0),
+ m_open(0.0),
+ m_high(0.0),
+ m_low(0.0),
+ m_close(0.0),
+ m_brush(QBrush(Qt::NoBrush)),
+ m_pen(QPen(Qt::NoPen)),
+ m_series(nullptr)
+{
+ setTimestamp(timestamp);
+}
+
+QCandlestickSetPrivate::~QCandlestickSetPrivate()
+{
+}
+
+bool QCandlestickSetPrivate::setTimestamp(qreal timestamp)
+{
+ timestamp = qMax(timestamp, 0.0);
+ timestamp = qRound64(timestamp);
+
+ if (m_timestamp == timestamp)
+ return false;
+
+ m_timestamp = timestamp;
+
+ return true;
+}
+
+#include "moc_qcandlestickset.cpp"
+#include "moc_qcandlestickset_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/qcandlestickset.h b/src/charts/candlestickchart/qcandlestickset.h
new file mode 100644
index 00000000..ddbb6c16
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickset.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QCANDLESTICKSET_H
+#define QCANDLESTICKSET_H
+
+#include <QtCharts/QChartGlobal>
+#include <QtGui/QBrush>
+#include <QtGui/QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickSetPrivate;
+
+class QT_CHARTS_EXPORT QCandlestickSet : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal timestamp READ timestamp WRITE setTimestamp NOTIFY timestampChanged)
+ Q_PROPERTY(qreal open READ open WRITE setOpen NOTIFY openChanged)
+ Q_PROPERTY(qreal high READ high WRITE setHigh NOTIFY highChanged)
+ Q_PROPERTY(qreal low READ low WRITE setLow NOTIFY lowChanged)
+ Q_PROPERTY(qreal close READ close WRITE setClose NOTIFY closeChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+
+public:
+ explicit QCandlestickSet(qreal timestamp = 0.0, QObject *parent = nullptr);
+ explicit QCandlestickSet(qreal open, qreal high, qreal low, qreal close, qreal timestamp = 0.0,
+ QObject *parent = nullptr);
+ virtual ~QCandlestickSet();
+
+ void setTimestamp(qreal timestamp);
+ qreal timestamp() const;
+
+ void setOpen(qreal open);
+ qreal open() const;
+
+ void setHigh(qreal high);
+ qreal high() const;
+
+ void setLow(qreal low);
+ qreal low() const;
+
+ void setClose(qreal close);
+ qreal close() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+Q_SIGNALS:
+ void clicked();
+ void hovered(bool status);
+ void pressed();
+ void released();
+ void doubleClicked();
+ void timestampChanged();
+ void openChanged();
+ void highChanged();
+ void lowChanged();
+ void closeChanged();
+ void brushChanged();
+ void penChanged();
+
+private:
+ QScopedPointer<QCandlestickSetPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QCandlestickSet)
+ Q_DISABLE_COPY(QCandlestickSet)
+ friend class QCandlestickSeriesPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKSET_H
diff --git a/src/charts/candlestickchart/qcandlestickset_p.h b/src/charts/candlestickchart/qcandlestickset_p.h
new file mode 100644
index 00000000..327e4ee8
--- /dev/null
+++ b/src/charts/candlestickchart/qcandlestickset_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QCANDLESTICKSET_P_H
+#define QCANDLESTICKSET_P_H
+
+#include <QtCharts/QChartGlobal>
+#include <QtGui/QBrush>
+#include <QtGui/QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickSeriesPrivate;
+class QCandlestickSet;
+
+class QCandlestickSetPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QCandlestickSetPrivate(qreal timestamp, QCandlestickSet *parent);
+ ~QCandlestickSetPrivate();
+
+ bool setTimestamp(qreal timestamp);
+
+Q_SIGNALS:
+ void updatedLayout();
+ void updatedCandlestick();
+
+private:
+ QCandlestickSet *q_ptr;
+ qreal m_timestamp;
+ qreal m_open;
+ qreal m_high;
+ qreal m_low;
+ qreal m_close;
+ QBrush m_brush;
+ QPen m_pen;
+ QCandlestickSeriesPrivate *m_series;
+
+private:
+ Q_DECLARE_PUBLIC(QCandlestickSet)
+ friend class QCandlestickSeriesPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKSET_P_H
diff --git a/src/charts/candlestickchart/qhcandlestickmodelmapper.cpp b/src/charts/candlestickchart/qhcandlestickmodelmapper.cpp
new file mode 100644
index 00000000..b27d37d6
--- /dev/null
+++ b/src/charts/candlestickchart/qhcandlestickmodelmapper.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** 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/QHCandlestickModelMapper>
+#include <private/qcandlestickmodelmapper_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHCandlestickModelMapper
+ \since 5.8
+ \inmodule Qt Charts
+ \brief Horizontal model mapper for a candlestick series.
+
+ Model mappers allow the use of a QAbstractItemModel-derived model as a data source for a chart
+ series, creating a connection between a QCandlestickSeries and the model object. A horizontal
+ model mapper maintains an equal size across all \l {QCandlestickSet} {QCandlestickSets}, and
+ reads the values of the set from the model's rows.
+
+ \note The model used must support adding and removing rows/columns and modifying the data of the
+ cells.
+*/
+
+/*!
+ \qmltype HCandlestickModelMapper
+ \since 2.2
+ \instantiates QHCandlestickModelMapper
+ \inqmlmodule QtCharts
+ \brief Horizontal model mapper for a candlestick series.
+
+ HCandlestickModelMapper allows the use of a QAbstractItemModel-derived model with data in rows
+ as a data source for a candlestick series. It's possible to manipulate the data either through
+ QAbstractItemModel or QCandlestickSeries.
+
+ The following QML example creates a candlestick series with three candlestick sets (assuming the
+ model has at least four rows). Each candlestick set would contain data defined by timestamp,
+ open, high, low and close columns. The name of a set would be defined by the vertical header of
+ the row.
+ \qml
+ CandlestickSeries {
+ HCandlestickModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ timestampColumn: 1
+ openColumn: 2
+ highColumn: 3
+ lowColumn: 4
+ closeColumn: 5
+ firstCandlestickSetRow: 1
+ lastCandlestickSetRow: 3
+ }
+ }
+ \endqml
+
+ \note HCandlestickModelMapper keeps the series and the model in sync.
+*/
+
+/*!
+ \qmlproperty QAbstractItemModel HCandlestickModelMapper::model
+ \brief The QAbstractItemModel-based model that is used by the mapper. The model must be
+ implemented and exposed to QML.
+
+ \note The model used must support adding and removing rows/columns and modifying the data of the
+ cells.
+*/
+
+/*!
+ \qmlproperty CandlestickSeries HCandlestickModelMapper::series
+ \brief Defines the CandlestickSeries based object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper. When a new series is
+ specified, the old series is disconnected (preserving its data).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::timestampColumn
+ \brief Defines the column of the model that contains the timestamp values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::timestampColumn
+ \brief Defines the column of the model that contains the timestamp values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::openColumn
+ \brief Defines the column of the model that contains the open values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::openColumn
+ \brief Defines the column of the model that contains the open values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::highColumn
+ \brief Defines the column of the model that contains the high values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::highColumn
+ \brief Defines the column of the model that contains the high values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::lowColumn
+ \brief Defines the column of the model that contains the low values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::lowColumn
+ \brief Defines the column of the model that contains the low values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::closeColumn
+ \brief Defines the column of the model that contains the close values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::closeColumn
+ \brief Defines the column of the model that contains the close values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::firstCandlestickSetRow
+ \brief Defines the row of the model that is used as the data source for the first set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::firstCandlestickSetRow
+ \brief Defines the row of the model that is used as the data source for the first set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QHCandlestickModelMapper::lastCandlestickSetRow
+ \brief Defines the row of the model that is used as the data source for the last set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int HCandlestickModelMapper::lastCandlestickSetRow
+ \brief Defines the row of the model that is used as the data source for the last set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::timestampColumnChanged()
+ \brief Emitted when the column of the model that contains timestamp values is changed
+ \sa timestampColumn
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::openColumnChanged()
+ \brief Emitted when the column of the model that contains open values is changed.
+ \sa openColumn
+*/
+/*!
+ \fn void QHCandlestickModelMapper::highColumnChanged()
+ \brief Emitted when the column of the model that contains high values is changed.
+ \sa highColumn
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::lowColumnChanged()
+ \brief Emitted when the column of the model that contains low values is changed.
+ \sa lowColumn
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::closeColumnChanged()
+ \brief Emitted when the column of the model that contains close values is changed.
+ \sa closeColumn
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::firstCandlestickSetRowChanged()
+ \brief Emitted when the row of the model that contains the data of the first set is changed.
+ \sa firstCandlestickSetRow
+*/
+
+/*!
+ \fn void QHCandlestickModelMapper::lastCandlestickSetRowChanged()
+ \brief Emitted when the row of the model that contains the data of the last set is changed.
+ \sa lastCandlestickSetRow
+*/
+
+/*!
+ Constructs a horizontal model mapper object which is a child of \a parent.
+*/
+QHCandlestickModelMapper::QHCandlestickModelMapper(QObject *parent)
+ : QCandlestickModelMapper(parent)
+{
+ connect(d_ptr, SIGNAL(timestampChanged()), this, SIGNAL(timestampColumnChanged()));
+ connect(d_ptr, SIGNAL(openChanged()), this, SIGNAL(openColumnChanged()));
+ connect(d_ptr, SIGNAL(highChanged()), this, SIGNAL(highColumnChanged()));
+ connect(d_ptr, SIGNAL(lowChanged()), this, SIGNAL(lowColumnChanged()));
+ connect(d_ptr, SIGNAL(closeChanged()), this, SIGNAL(closeColumnChanged()));
+ connect(d_ptr, SIGNAL(firstCandlestickSetSectionChanged()),
+ this, SIGNAL(firstCandlestickSetRowChanged()));
+ connect(d_ptr, SIGNAL(lastCandlestickSetSectionChanged()),
+ this, SIGNAL(lastCandlestickSetRowChanged()));
+}
+
+/*!
+ Returns Qt::Horizontal. This means that values of the set are read from rows.
+*/
+Qt::Orientation QHCandlestickModelMapper::orientation() const
+{
+ return Qt::Horizontal;
+}
+
+void QHCandlestickModelMapper::setTimestampColumn(int timestampColumn)
+{
+ QCandlestickModelMapper::setTimestamp(timestampColumn);
+}
+
+int QHCandlestickModelMapper::timestampColumn() const
+{
+ return QCandlestickModelMapper::timestamp();
+}
+
+void QHCandlestickModelMapper::setOpenColumn(int openColumn)
+{
+ QCandlestickModelMapper::setOpen(openColumn);
+}
+
+int QHCandlestickModelMapper::openColumn() const
+{
+ return QCandlestickModelMapper::open();
+}
+
+void QHCandlestickModelMapper::setHighColumn(int highColumn)
+{
+ QCandlestickModelMapper::setHigh(highColumn);
+}
+
+int QHCandlestickModelMapper::highColumn() const
+{
+ return QCandlestickModelMapper::high();
+}
+
+void QHCandlestickModelMapper::setLowColumn(int lowColumn)
+{
+ QCandlestickModelMapper::setLow(lowColumn);
+}
+
+int QHCandlestickModelMapper::lowColumn() const
+{
+ return QCandlestickModelMapper::low();
+}
+
+void QHCandlestickModelMapper::setCloseColumn(int closeColumn)
+{
+ QCandlestickModelMapper::setClose(closeColumn);
+}
+
+int QHCandlestickModelMapper::closeColumn() const
+{
+ return QCandlestickModelMapper::close();
+}
+
+void QHCandlestickModelMapper::setFirstCandlestickSetRow(int firstCandlestickSetRow)
+{
+ QCandlestickModelMapper::setFirstCandlestickSetSection(firstCandlestickSetRow);
+}
+
+int QHCandlestickModelMapper::firstCandlestickSetRow() const
+{
+ return QCandlestickModelMapper::firstCandlestickSetSection();
+}
+
+void QHCandlestickModelMapper::setLastCandlestickSetRow(int lastCandlestickSetRow)
+{
+ QCandlestickModelMapper::setLastCandlestickSetSection(lastCandlestickSetRow);
+}
+
+int QHCandlestickModelMapper::lastCandlestickSetRow() const
+{
+ return QCandlestickModelMapper::lastCandlestickSetSection();
+}
+
+#include "moc_qhcandlestickmodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/qhcandlestickmodelmapper.h b/src/charts/candlestickchart/qhcandlestickmodelmapper.h
new file mode 100644
index 00000000..5bae93c2
--- /dev/null
+++ b/src/charts/candlestickchart/qhcandlestickmodelmapper.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QHCANDLESTICKMODELMAPPER_H
+#define QHCANDLESTICKMODELMAPPER_H
+
+#include <QtCharts/QCandlestickModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QHCandlestickModelMapper : public QCandlestickModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(int timestampColumn READ timestampColumn WRITE setTimestampColumn NOTIFY timestampColumnChanged)
+ Q_PROPERTY(int openColumn READ openColumn WRITE setOpenColumn NOTIFY openColumnChanged)
+ Q_PROPERTY(int highColumn READ highColumn WRITE setHighColumn NOTIFY highColumnChanged)
+ Q_PROPERTY(int lowColumn READ lowColumn WRITE setLowColumn NOTIFY lowColumnChanged)
+ Q_PROPERTY(int closeColumn READ closeColumn WRITE setCloseColumn NOTIFY closeColumnChanged)
+ Q_PROPERTY(int firstCandlestickSetRow READ firstCandlestickSetRow WRITE setFirstCandlestickSetRow NOTIFY firstCandlestickSetRowChanged)
+ Q_PROPERTY(int lastCandlestickSetRow READ lastCandlestickSetRow WRITE setLastCandlestickSetRow NOTIFY lastCandlestickSetRowChanged)
+
+public:
+ explicit QHCandlestickModelMapper(QObject *parent = nullptr);
+
+ Qt::Orientation orientation() const;
+
+ void setTimestampColumn(int timestampColumn);
+ int timestampColumn() const;
+
+ void setOpenColumn(int openColumn);
+ int openColumn() const;
+
+ void setHighColumn(int highColumn);
+ int highColumn() const;
+
+ void setLowColumn(int lowColumn);
+ int lowColumn() const;
+
+ void setCloseColumn(int closeColumn);
+ int closeColumn() const;
+
+ void setFirstCandlestickSetRow(int firstCandlestickSetRow);
+ int firstCandlestickSetRow() const;
+
+ void setLastCandlestickSetRow(int lastCandlestickSetRow);
+ int lastCandlestickSetRow() const;
+
+Q_SIGNALS:
+ void timestampColumnChanged();
+ void openColumnChanged();
+ void highColumnChanged();
+ void lowColumnChanged();
+ void closeColumnChanged();
+ void firstCandlestickSetRowChanged();
+ void lastCandlestickSetRowChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHCANDLESTICKMODELMAPPER_H
diff --git a/src/charts/candlestickchart/qvcandlestickmodelmapper.cpp b/src/charts/candlestickchart/qvcandlestickmodelmapper.cpp
new file mode 100644
index 00000000..990c438c
--- /dev/null
+++ b/src/charts/candlestickchart/qvcandlestickmodelmapper.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** 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/QVCandlestickModelMapper>
+#include <private/qcandlestickmodelmapper_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QVCandlestickModelMapper
+ \since 5.8
+ \inmodule Qt Charts
+ \brief Vertical model mapper for a candlestick series.
+
+ Model mappers allow the use of a QAbstractItemModel-derived model as a data source for a chart
+ series, creating a connection between a QCandlestickSeries and the model object. A vertical
+ model mapper maintains an equal size across all \l {QCandlestickSet} {QCandlestickSets}, and
+ reads the values of the set from the model's columns.
+
+ \note The model used must support adding and removing rows/columns and modifying the data of the
+ cells.
+*/
+
+/*!
+ \qmltype VCandlestickModelMapper
+ \since 2.2
+ \instantiates QVCandlestickModelMapper
+ \inqmlmodule QtCharts
+ \brief Vertical model mapper for a candlestick series.
+
+ VCandlestickModelMapper allows the use of a QAbstractItemModel-derived model with data in
+ columns as a data source for a candlestick series. It's possible to manipulate the data either
+ through QAbstractItemModel or QCandlestickSeries.
+
+ The following QML example creates a candlestick series with three candlestick sets (assuming the
+ model has at least four columns). Each candlestick set would contain data defined by timestamp,
+ open, high, low and close rows. The name of a set would be defined by the horizontal header of
+ the column.
+ \qml
+ CandlestickSeries {
+ VCandlestickModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ timestampRow: 1
+ openRow: 2
+ highRow: 3
+ lowRow: 4
+ closeRow: 5
+ firstCandlestickSetColumn: 1
+ lastCandlestickSetColumn: 3
+ }
+ }
+ \endqml
+
+ \note VCandlestickModelMapper keeps the series and the model in sync.
+*/
+
+/*!
+ \qmlproperty QAbstractItemModel VCandlestickModelMapper::model
+ \brief The QAbstractItemModel-based model that is used by the mapper. The model must be
+ implemented and exposed to QML.
+
+ \note The model used must support adding and removing rows/columns and modifying the data of the
+ cells.
+*/
+
+/*!
+ \qmlproperty CandlestickSeries VCandlestickModelMapper::series
+ \brief Defines the CandlestickSeries based object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper. When a new series is
+ specified, the old series is disconnected (preserving its data).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::timestampRow
+ \brief Defines the row of the model that contains the timestamp values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::timestampRow
+ \brief Defines the row of the model that contains the timestamp values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::openRow
+ \brief Defines the row of the model that contains the open values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::openRow
+ \brief Defines the row of the model that contains the open values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::highRow
+ \brief Defines the row of the model that contains the high values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::highRow
+ \brief Defines the row of the model that contains the high values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::lowRow
+ \brief Defines the row of the model that contains the low values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::lowRow
+ \brief Defines the row of the model that contains the low values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::closeRow
+ \brief Defines the row of the model that contains the close values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::closeRow
+ \brief Defines the row of the model that contains the close values of the
+ \l {QCandlestickSet} {QCandlestickSets} in the series. Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::firstCandlestickSetColumn
+ \brief Defines the column of the model that is used as the data source for the first set.
+ Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::firstCandlestickSetColumn
+ \brief Defines the column of the model that is used as the data source for the first set.
+ Default value is -1 (invalid mapping).
+*/
+
+/*!
+ \property QVCandlestickModelMapper::lastCandlestickSetColumn
+ \brief Defines the column of the model that is used as the data source for the last set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \qmlproperty int VCandlestickModelMapper::lastCandlestickSetColumn
+ \brief Defines the column of the model that is used as the data source for the last set. Default
+ value is -1 (invalid mapping).
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::timestampRowChanged()
+ \brief Emitted when the row of the model that contains timestamp values is changed.
+ \sa timestampRow
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::openRowChanged()
+ \brief Emitted when the row of the model that contains open values is changed.
+ \sa openRow
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::highRowChanged()
+ \brief Emitted when the row of the model that contains high values is changed.
+ \sa highRow
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::lowRowChanged()
+ \brief Emitted when the row of the model that contains low values is changed.
+ \sa lowRow
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::closeRowChanged()
+ \brief Emitted when the row of the model that contains close values is changed.
+ \sa closeRow
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::firstCandlestickSetColumnChanged()
+ \brief Emitted when the column of the model that contains the data of the first set is changed.
+ \sa firstCandlestickSetColumn
+*/
+
+/*!
+ \fn void QVCandlestickModelMapper::lastCandlestickSetColumnChanged()
+ \brief Emitted when the column of the model that contains the data of the last set is changed.
+ \sa lastCandlestickSetColumn
+*/
+
+/*!
+ Constructs a vertical model mapper object which is a child of \a parent.
+*/
+QVCandlestickModelMapper::QVCandlestickModelMapper(QObject *parent)
+ : QCandlestickModelMapper(parent)
+{
+ connect(d_ptr, SIGNAL(timestampChanged()), this, SIGNAL(timestampRowChanged()));
+ connect(d_ptr, SIGNAL(openChanged()), this, SIGNAL(openRowChanged()));
+ connect(d_ptr, SIGNAL(highChanged()), this, SIGNAL(highRowChanged()));
+ connect(d_ptr, SIGNAL(lowChanged()), this, SIGNAL(lowRowChanged()));
+ connect(d_ptr, SIGNAL(closeChanged()), this, SIGNAL(closeRowChanged()));
+ connect(d_ptr, SIGNAL(firstCandlestickSetSectionChanged()),
+ this, SIGNAL(firstCandlestickSetColumnChanged()));
+ connect(d_ptr, SIGNAL(lastCandlestickSetSectionChanged()),
+ this, SIGNAL(lastCandlestickSetColumnChanged()));
+}
+
+/*!
+ Returns Qt::Vertical. This means that values of the set are read from columns.
+*/
+Qt::Orientation QVCandlestickModelMapper::orientation() const
+{
+ return Qt::Vertical;
+}
+
+void QVCandlestickModelMapper::setTimestampRow(int timestampRow)
+{
+ QCandlestickModelMapper::setTimestamp(timestampRow);
+}
+
+int QVCandlestickModelMapper::timestampRow() const
+{
+ return QCandlestickModelMapper::timestamp();
+}
+
+void QVCandlestickModelMapper::setOpenRow(int openRow)
+{
+ QCandlestickModelMapper::setOpen(openRow);
+}
+
+int QVCandlestickModelMapper::openRow() const
+{
+ return QCandlestickModelMapper::open();
+}
+
+void QVCandlestickModelMapper::setHighRow(int highRow)
+{
+ QCandlestickModelMapper::setHigh(highRow);
+}
+
+int QVCandlestickModelMapper::highRow() const
+{
+ return QCandlestickModelMapper::high();
+}
+
+void QVCandlestickModelMapper::setLowRow(int lowRow)
+{
+ QCandlestickModelMapper::setLow(lowRow);
+}
+
+int QVCandlestickModelMapper::lowRow() const
+{
+ return QCandlestickModelMapper::low();
+}
+
+void QVCandlestickModelMapper::setCloseRow(int closeRow)
+{
+ QCandlestickModelMapper::setClose(closeRow);
+}
+
+int QVCandlestickModelMapper::closeRow() const
+{
+ return QCandlestickModelMapper::close();
+}
+
+void QVCandlestickModelMapper::setFirstCandlestickSetColumn(int firstCandlestickSetColumn)
+{
+ QCandlestickModelMapper::setFirstCandlestickSetSection(firstCandlestickSetColumn);
+}
+
+int QVCandlestickModelMapper::firstCandlestickSetColumn() const
+{
+ return QCandlestickModelMapper::firstCandlestickSetSection();
+}
+
+void QVCandlestickModelMapper::setLastCandlestickSetColumn(int lastCandlestickSetColumn)
+{
+ QCandlestickModelMapper::setLastCandlestickSetSection(lastCandlestickSetColumn);
+}
+
+int QVCandlestickModelMapper::lastCandlestickSetColumn() const
+{
+ return QCandlestickModelMapper::lastCandlestickSetSection();
+}
+
+#include "moc_qvcandlestickmodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/candlestickchart/qvcandlestickmodelmapper.h b/src/charts/candlestickchart/qvcandlestickmodelmapper.h
new file mode 100644
index 00000000..5cd20f9d
--- /dev/null
+++ b/src/charts/candlestickchart/qvcandlestickmodelmapper.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QVCANDLESTICKMODELMAPPER_H
+#define QVCANDLESTICKMODELMAPPER_H
+
+#include <QtCharts/QCandlestickModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QVCandlestickModelMapper : public QCandlestickModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(int timestampRow READ timestampRow WRITE setTimestampRow NOTIFY timestampRowChanged)
+ Q_PROPERTY(int openRow READ openRow WRITE setOpenRow NOTIFY openRowChanged)
+ Q_PROPERTY(int highRow READ highRow WRITE setHighRow NOTIFY highRowChanged)
+ Q_PROPERTY(int lowRow READ lowRow WRITE setLowRow NOTIFY lowRowChanged)
+ Q_PROPERTY(int closeRow READ closeRow WRITE setCloseRow NOTIFY closeRowChanged)
+ Q_PROPERTY(int firstCandlestickSetColumn READ firstCandlestickSetColumn WRITE setFirstCandlestickSetColumn NOTIFY firstCandlestickSetColumnChanged)
+ Q_PROPERTY(int lastCandlestickSetColumn READ lastCandlestickSetColumn WRITE setLastCandlestickSetColumn NOTIFY lastCandlestickSetColumnChanged)
+
+public:
+ explicit QVCandlestickModelMapper(QObject *parent = nullptr);
+
+ Qt::Orientation orientation() const;
+
+ void setTimestampRow(int timestampRow);
+ int timestampRow() const;
+
+ void setOpenRow(int openRow);
+ int openRow() const;
+
+ void setHighRow(int highRow);
+ int highRow() const;
+
+ void setLowRow(int lowRow);
+ int lowRow() const;
+
+ void setCloseRow(int closeRow);
+ int closeRow() const;
+
+ void setFirstCandlestickSetColumn(int firstCandlestickSetColumn);
+ int firstCandlestickSetColumn() const;
+
+ void setLastCandlestickSetColumn(int lastCandlestickSetColumn);
+ int lastCandlestickSetColumn() const;
+
+Q_SIGNALS:
+ void timestampRowChanged();
+ void openRowChanged();
+ void highRowChanged();
+ void lowRowChanged();
+ void closeRowChanged();
+ void firstCandlestickSetColumnChanged();
+ void lastCandlestickSetColumnChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVCANDLESTICKMODELMAPPER_H
diff --git a/src/charts/chartdataset.cpp b/src/charts/chartdataset.cpp
index cbc4dfbd..97602b57 100644
--- a/src/charts/chartdataset.cpp
+++ b/src/charts/chartdataset.cpp
@@ -153,20 +153,19 @@ void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
*/
void ChartDataSet::removeSeries(QAbstractSeries *series)
{
-
if (! m_seriesList.contains(series)) {
qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
return;
}
- QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
+ QList<QAbstractAxis *> axes = series->d_ptr->m_axes;
- foreach(QAbstractAxis* axis, axes) {
- detachAxis(series,axis);
+ foreach (QAbstractAxis *axis, axes) {
+ detachAxis(series, axis);
}
- emit seriesRemoved(series);
m_seriesList.removeAll(series);
+ emit seriesRemoved(series);
// Reset domain to default
series->d_ptr->setDomain(new XYDomain());
diff --git a/src/charts/chartpresenter_p.h b/src/charts/chartpresenter_p.h
index 5b713799..e3db5ff8 100644
--- a/src/charts/chartpresenter_p.h
+++ b/src/charts/chartpresenter_p.h
@@ -79,6 +79,7 @@ public:
ScatterSeriesZValue = SeriesZValue,
PieSeriesZValue = SeriesZValue,
BoxPlotSeriesZValue = SeriesZValue,
+ CandlestickSeriesZValue = SeriesZValue,
LegendZValue,
TopMostZValue
};
diff --git a/src/charts/charts.pro b/src/charts/charts.pro
index 30546fd0..20f9d005 100644
--- a/src/charts/charts.pro
+++ b/src/charts/charts.pro
@@ -77,6 +77,7 @@ include($$PWD/themes/themes.pri)
include($$PWD/xychart/xychart.pri)
include($$PWD/layout/layout.pri)
include($$PWD/boxplotchart/boxplotchart.pri)
+include($$PWD/candlestickchart/candlestickchart.pri)
HEADERS += $$PUBLIC_HEADERS
HEADERS += $$PRIVATE_HEADERS
diff --git a/src/charts/common.pri b/src/charts/common.pri
index 1d5b6494..18dee553 100644
--- a/src/charts/common.pri
+++ b/src/charts/common.pri
@@ -4,6 +4,7 @@ INCLUDEPATH += $$PWD/ \
$$PWD/axis \
$$PWD/barchart \
$$PWD/boxplotchart \
+ $$PWD/candlestickchart \
$$PWD/domain \
$$PWD/layout \
$$PWD/legend \
diff --git a/src/charts/doc/images/examples_candlestickchart.png b/src/charts/doc/images/examples_candlestickchart.png
new file mode 100644
index 00000000..ac8cebeb
--- /dev/null
+++ b/src/charts/doc/images/examples_candlestickchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcandlestick.png b/src/charts/doc/images/examples_qmlcandlestick.png
new file mode 100755
index 00000000..c380445f
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcandlestick.png
Binary files differ
diff --git a/src/charts/doc/snippets/doc_src_qmlcharts.cpp b/src/charts/doc/snippets/doc_src_qmlcharts.cpp
index c90c02ee..b087fa95 100644
--- a/src/charts/doc/snippets/doc_src_qmlcharts.cpp
+++ b/src/charts/doc/snippets/doc_src_qmlcharts.cpp
@@ -28,5 +28,5 @@
****************************************************************************/
//! [0]
-import QtCharts 2.0
+import QtCharts 2.2
//! [0]
diff --git a/src/charts/doc/src/examples-candlestickchart.qdoc b/src/charts/doc/src/examples-candlestickchart.qdoc
new file mode 100644
index 00000000..2d4d63bc
--- /dev/null
+++ b/src/charts/doc/src/examples-candlestickchart.qdoc
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \example candlestickchart
+ \title Candlestick Chart Example
+ \ingroup qtcharts_examples
+
+ \brief Shows how to create a candlestick chart.
+
+ \image examples_candlestickchart.png
+
+ To display a candlestick chart, we start by creating QCandlestickSeries to handle daily data. We
+ are also specifying custom increasing and decreasing body colors.
+
+ \snippet candlestickchart/main.cpp 1
+
+ QFile is used for accessing a text file where the non-continuous data is kept. The
+ \c CandlestickDataReader is an auxiliary class for reading the text file and finding the open,
+ high, low, close, and timestamp values from the data. The \c CandlestickDataReader is explained
+ in more detail later. The method \c readCandlestickSet() reads the values and sets them to the
+ QCandlestickSet item which the method returns for the caller. The returned QCandlestickSet item
+ is added to the series. We are also saving custom categories list for later use.
+
+ \snippet candlestickchart/main.cpp 2
+
+ Below, a new QChart instance is created and the previously created series object is added to it.
+ We also define a title, and set an animation as
+ \l {QChart::AnimationOption} {QChart::SeriesAnimation}.
+
+ \snippet candlestickchart/main.cpp 3
+
+ Here, we ask the chart to create default axes for our presentation. Then, we set custom
+ categories for the horizontal axis by querying the pointer for the axis from the chart, and then
+ setting the categories from previously saved custom categories list. We also set the range for
+ the vertical axis by querying the pointer for the axis from the chart, and then setting the min
+ and max values for that axis.
+
+ \snippet candlestickchart/main.cpp 4
+
+ Below, we set the legend to be visible and place it at the bottom of the chart.
+
+ \snippet candlestickchart/main.cpp 5
+
+ Finally, we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet candlestickchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window. We also
+ set the size for the chart window and show it.
+
+ \snippet candlestickchart/main.cpp 7
+
+ Here, the method \c readCandlestickSet() is explained in detail. First, a line is read from
+ the file, rejecting any lines starting with # as they are considered comment lines.
+
+ \snippet candlestickchart/candlestickdatareader.cpp 1
+
+ In the file, the data is arranged as a space-delimited sequence of numbers. On this snippet the
+ line is split into single number strings which are stored in a QStringList.
+
+ \snippet candlestickchart/candlestickdatareader.cpp 2
+
+ To select values from the continuous data, following code is used. The values in a \c strList
+ are stored in the following order: timestamp, open, high, low, close.
+
+ \snippet candlestickchart/candlestickdatareader.cpp 3
+
+ Finally, the following snippet shows how to create a new QCandlestickSet and provide it with all
+ the necessary values.
+
+ \snippet candlestickchart/candlestickdatareader.cpp 4
+*/
diff --git a/src/charts/doc/src/qtcharts.qdoc b/src/charts/doc/src/qtcharts.qdoc
index e83e2631..fff47320 100644
--- a/src/charts/doc/src/qtcharts.qdoc
+++ b/src/charts/doc/src/qtcharts.qdoc
@@ -50,7 +50,7 @@
*/
/*!
- \qmlmodule QtCharts 2.1
+ \qmlmodule QtCharts 2.2
\title Qt Charts QML Types
\ingroup qmlmodules
diff --git a/src/charts/legend/legend.pri b/src/charts/legend/legend.pri
index c14cf6b0..5fcb53c7 100644
--- a/src/charts/legend/legend.pri
+++ b/src/charts/legend/legend.pri
@@ -11,8 +11,9 @@ SOURCES += \
$$PWD/qxylegendmarker.cpp \
$$PWD/qarealegendmarker.cpp \
$$PWD/legendscroller.cpp \
- $$PWD/qboxplotlegendmarker.cpp
-
+ $$PWD/qboxplotlegendmarker.cpp \
+ $$PWD/qcandlesticklegendmarker.cpp
+
PRIVATE_HEADERS += \
$$PWD/legendscroller_p.h \
$$PWD/qlegend_p.h \
@@ -23,9 +24,9 @@ PRIVATE_HEADERS += \
$$PWD/qbarlegendmarker_p.h \
$$PWD/qxylegendmarker_p.h \
$$PWD/qarealegendmarker_p.h \
- $$PWD/qboxplotlegendmarker_p.h
-
-
+ $$PWD/qboxplotlegendmarker_p.h \
+ $$PWD/qcandlesticklegendmarker_p.h
+
PUBLIC_HEADERS += \
$$PWD/qlegend.h \
$$PWD/qlegendmarker.h \
@@ -33,4 +34,5 @@ PUBLIC_HEADERS += \
$$PWD/qbarlegendmarker.h \
$$PWD/qxylegendmarker.h \
$$PWD/qarealegendmarker.h \
- $$PWD/qboxplotlegendmarker.h
+ $$PWD/qboxplotlegendmarker.h \
+ $$PWD/qcandlesticklegendmarker.h
diff --git a/src/charts/legend/legendmarkeritem.cpp b/src/charts/legend/legendmarkeritem.cpp
index 125199ea..1c0b5901 100644
--- a/src/charts/legend/legendmarkeritem.cpp
+++ b/src/charts/legend/legendmarkeritem.cpp
@@ -88,8 +88,14 @@ QBrush LegendMarkerItem::brush() const
void LegendMarkerItem::setFont(const QFont &font)
{
m_textItem->setFont(font);
+
QFontMetrics fn(font);
- m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2);
+ QRectF markerRect = QRectF(0, 0, fn.height() / 2, fn.height() / 2);
+ if (m_markerRect != markerRect) {
+ m_markerRect = markerRect;
+ emit markerRectChanged();
+ }
+
updateGeometry();
}
@@ -152,6 +158,11 @@ QRectF LegendMarkerItem::boundingRect() const
return m_boundingRect;
}
+QRectF LegendMarkerItem::markerRect() const
+{
+ return m_markerRect;
+}
+
void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
diff --git a/src/charts/legend/legendmarkeritem_p.h b/src/charts/legend/legendmarkeritem_p.h
index 870cfb2e..c3371742 100644
--- a/src/charts/legend/legendmarkeritem_p.h
+++ b/src/charts/legend/legendmarkeritem_p.h
@@ -56,7 +56,7 @@ class LegendMarkerItem : public QGraphicsObject, public QGraphicsLayoutItem
Q_OBJECT
Q_INTERFACES(QGraphicsLayoutItem)
public:
- explicit LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent = 0);
+ explicit LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent = nullptr);
~LegendMarkerItem();
void setPen(const QPen &pen);
@@ -76,8 +76,9 @@ public:
void setGeometry(const QRectF &rect);
QRectF boundingRect() const;
+ QRectF markerRect() const;
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget = nullptr);
QSizeF sizeHint (Qt::SizeHint which, const QSizeF &constraint) const;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
@@ -85,6 +86,10 @@ public:
QString displayedLabel() const;
void setToolTip(const QString &tooltip);
+
+Q_SIGNALS:
+ void markerRectChanged();
+
protected:
QLegendMarkerPrivate *m_marker; // Knows
QRectF m_markerRect;
diff --git a/src/charts/legend/qcandlesticklegendmarker.cpp b/src/charts/legend/qcandlesticklegendmarker.cpp
new file mode 100644
index 00000000..97208e3c
--- /dev/null
+++ b/src/charts/legend/qcandlesticklegendmarker.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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/QCandlestickLegendMarker>
+#include <private/legendmarkeritem_p.h>
+#include <private/qcandlesticklegendmarker_p.h>
+#include <private/qcandlestickseries_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+QCandlestickLegendMarker::QCandlestickLegendMarker(QCandlestickSeries *series, QLegend *legend,
+ QObject *parent)
+ : QLegendMarker(*new QCandlestickLegendMarkerPrivate(this, series, legend), parent)
+{
+ Q_D(QCandlestickLegendMarker);
+
+ d->updated();
+}
+
+QCandlestickLegendMarker::~QCandlestickLegendMarker()
+{
+}
+
+QLegendMarker::LegendMarkerType QCandlestickLegendMarker::type()
+{
+ return LegendMarkerTypeCandlestick;
+}
+
+QCandlestickSeries* QCandlestickLegendMarker::series()
+{
+ Q_D(QCandlestickLegendMarker);
+
+ return d->m_series;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QCandlestickLegendMarkerPrivate::QCandlestickLegendMarkerPrivate(QCandlestickLegendMarker *q,
+ QCandlestickSeries *series,
+ QLegend *legend)
+ : QLegendMarkerPrivate(q, legend),
+ q_ptr(q),
+ m_series(series)
+{
+ QObject::connect(m_item, SIGNAL(markerRectChanged()), this, SLOT(updated()));
+ QObject::connect(m_series, SIGNAL(nameChanged()), this, SLOT(updated()));
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(updated()));
+}
+
+QCandlestickLegendMarkerPrivate::~QCandlestickLegendMarkerPrivate()
+{
+}
+
+QAbstractSeries* QCandlestickLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QCandlestickLegendMarkerPrivate::relatedObject()
+{
+ return m_series;
+}
+
+void QCandlestickLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+
+ if (!m_customLabel && (m_item->label() != m_series->name())) {
+ m_item->setLabel(m_series->name());
+ labelChanged = true;
+ }
+ if (!m_customBrush) {
+ QLinearGradient gradient;
+ gradient.setStart(0.0, 0.0);
+ gradient.setFinalStop(m_item->markerRect().width(), m_item->markerRect().height());
+ gradient.setColorAt(0.0, m_series->increasingColor());
+ gradient.setColorAt(0.49, m_series->increasingColor());
+ gradient.setColorAt(0.50, m_series->decreasingColor());
+ gradient.setColorAt(1.0, m_series->decreasingColor());
+
+ QBrush brush(gradient);
+ if (m_item->brush() != brush) {
+ m_item->setBrush(brush);
+ brushChanged = true;
+ }
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+}
+
+#include "moc_qcandlesticklegendmarker.cpp"
+#include "moc_qcandlesticklegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/qcandlesticklegendmarker.h b/src/charts/legend/qcandlesticklegendmarker.h
new file mode 100644
index 00000000..dad57c4f
--- /dev/null
+++ b/src/charts/legend/qcandlesticklegendmarker.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QCANDLESTICKLEGENDMARKER_H
+#define QCANDLESTICKLEGENDMARKER_H
+
+#include <QtCharts/QCandlestickSeries>
+#include <QtCharts/QLegendMarker>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QCandlestickLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+
+public:
+ explicit QCandlestickLegendMarker(QCandlestickSeries *series, QLegend *legend,
+ QObject *parent = nullptr);
+ virtual ~QCandlestickLegendMarker();
+
+ virtual LegendMarkerType type();
+
+ // Related series
+ virtual QCandlestickSeries* series();
+
+private:
+ Q_DECLARE_PRIVATE(QCandlestickLegendMarker)
+ Q_DISABLE_COPY(QCandlestickLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKLEGENDMARKER_H
diff --git a/src/charts/legend/qcandlesticklegendmarker_p.h b/src/charts/legend/qcandlesticklegendmarker_p.h
new file mode 100644
index 00000000..1c786b3a
--- /dev/null
+++ b/src/charts/legend/qcandlesticklegendmarker_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Chart API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QCANDLESTICKLEGENDMARKER_P_H
+#define QCANDLESTICKLEGENDMARKER_P_H
+
+#include <private/qlegendmarker_p.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCandlestickLegendMarker;
+class QCandlestickSeries;
+
+class QCandlestickLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QCandlestickLegendMarkerPrivate(QCandlestickLegendMarker *q,
+ QCandlestickSeries *series, QLegend *legend);
+ virtual ~QCandlestickLegendMarkerPrivate();
+
+ virtual QAbstractSeries *series();
+ virtual QObject *relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QCandlestickLegendMarker *q_ptr;
+ QCandlestickSeries *m_series;
+
+ Q_DECLARE_PUBLIC(QCandlestickLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCANDLESTICKLEGENDMARKER_P_H
diff --git a/src/charts/legend/qlegendmarker.cpp b/src/charts/legend/qlegendmarker.cpp
index 8d240876..b9da4852 100644
--- a/src/charts/legend/qlegendmarker.cpp
+++ b/src/charts/legend/qlegendmarker.cpp
@@ -63,6 +63,7 @@ QT_CHARTS_BEGIN_NAMESPACE
\value LegendMarkerTypePie
\value LegendMarkerTypeXY
\value LegendMarkerTypeBoxPlot
+ \value LegendMarkerTypeCandlestick
*/
/*!
diff --git a/src/charts/legend/qlegendmarker.h b/src/charts/legend/qlegendmarker.h
index 142b7e45..86721440 100644
--- a/src/charts/legend/qlegendmarker.h
+++ b/src/charts/legend/qlegendmarker.h
@@ -52,7 +52,8 @@ public:
LegendMarkerTypeBar,
LegendMarkerTypePie,
LegendMarkerTypeXY,
- LegendMarkerTypeBoxPlot
+ LegendMarkerTypeBoxPlot,
+ LegendMarkerTypeCandlestick
};
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
diff --git a/src/charts/qabstractseries.cpp b/src/charts/qabstractseries.cpp
index 31a75044..b5c7d8a7 100644
--- a/src/charts/qabstractseries.cpp
+++ b/src/charts/qabstractseries.cpp
@@ -77,6 +77,7 @@ QT_CHARTS_BEGIN_NAMESPACE
\value SeriesTypeHorizontalStackedBar
\value SeriesTypeHorizontalPercentBar
\value SeriesTypeBoxPlot
+ \value SeriesTypeCandlestick
*/
/*!
diff --git a/src/charts/qabstractseries.h b/src/charts/qabstractseries.h
index 8fedf5c3..2d987ee3 100644
--- a/src/charts/qabstractseries.h
+++ b/src/charts/qabstractseries.h
@@ -63,11 +63,12 @@ public:
SeriesTypeHorizontalBar,
SeriesTypeHorizontalStackedBar,
SeriesTypeHorizontalPercentBar,
- SeriesTypeBoxPlot
+ SeriesTypeBoxPlot,
+ SeriesTypeCandlestick
};
protected:
- QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = Q_NULLPTR);
+ QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = nullptr);
public:
~QAbstractSeries();
diff --git a/src/charts/qchart.h b/src/charts/qchart.h
index 40b53a8f..cf2efb4f 100644
--- a/src/charts/qchart.h
+++ b/src/charts/qchart.h
@@ -191,6 +191,7 @@ protected:
friend class ChartThemeManager;
friend class QAbstractSeries;
friend class QBoxPlotSeriesPrivate;
+ friend class QCandlestickSeriesPrivate;
private:
Q_DISABLE_COPY(QChart)
diff --git a/src/chartsqml2/chartsqml2.pro b/src/chartsqml2/chartsqml2.pro
index fae7dc26..765f25b9 100644
--- a/src/chartsqml2/chartsqml2.pro
+++ b/src/chartsqml2/chartsqml2.pro
@@ -36,7 +36,8 @@ SOURCES += \
declarativepolarchart.cpp \
declarativeboxplotseries.cpp \
declarativechartnode.cpp \
- declarativerendernode.cpp
+ declarativerendernode.cpp \
+ declarativecandlestickseries.cpp
HEADERS += \
declarativechart.h \
@@ -54,7 +55,8 @@ HEADERS += \
declarativepolarchart.h \
declarativeboxplotseries.h \
declarativechartnode.h \
- declarativerendernode.h
+ declarativerendernode.h \
+ declarativecandlestickseries.h
OTHER_FILES = qmldir
diff --git a/src/chartsqml2/chartsqml2_plugin.cpp b/src/chartsqml2/chartsqml2_plugin.cpp
index 5492a45b..af1f15a4 100644
--- a/src/chartsqml2/chartsqml2_plugin.cpp
+++ b/src/chartsqml2/chartsqml2_plugin.cpp
@@ -42,6 +42,7 @@
#include "declarativescatterseries.h"
#include "declarativebarseries.h"
#include "declarativeboxplotseries.h"
+#include "declarativecandlestickseries.h"
#include "declarativepieseries.h"
#include "declarativeaxes.h"
#include <QtCharts/QVXYModelMapper>
@@ -58,6 +59,9 @@
#include <QtCharts/QBoxPlotModelMapper>
#include <QtCharts/QHBoxPlotModelMapper>
#include <QtCharts/QVBoxPlotModelMapper>
+#include <QtCharts/QCandlestickModelMapper>
+#include <QtCharts/QHCandlestickModelMapper>
+#include <QtCharts/QVCandlestickModelMapper>
#ifndef QT_QREAL_IS_FLOAT
#include <QtCharts/QDateTimeAxis>
#endif
@@ -78,6 +82,8 @@ QML_DECLARE_TYPE(DeclarativeBarSeries)
QML_DECLARE_TYPE(DeclarativeBarSet)
QML_DECLARE_TYPE(DeclarativeBoxPlotSeries)
QML_DECLARE_TYPE(DeclarativeBoxSet)
+QML_DECLARE_TYPE(DeclarativeCandlestickSeries)
+QML_DECLARE_TYPE(DeclarativeCandlestickSet)
QML_DECLARE_TYPE(DeclarativeLineSeries)
QML_DECLARE_TYPE(DeclarativePieSeries)
QML_DECLARE_TYPE(DeclarativePieSlice)
@@ -112,6 +118,9 @@ QML_DECLARE_TYPE(QXYModelMapper)
QML_DECLARE_TYPE(QBoxPlotModelMapper)
QML_DECLARE_TYPE(QHBoxPlotModelMapper)
QML_DECLARE_TYPE(QVBoxPlotModelMapper)
+QML_DECLARE_TYPE(QCandlestickModelMapper)
+QML_DECLARE_TYPE(QHCandlestickModelMapper)
+QML_DECLARE_TYPE(QVCandlestickModelMapper)
QML_DECLARE_TYPE(QAbstractSeries)
QML_DECLARE_TYPE(QXYSeries)
@@ -325,6 +334,14 @@ public:
qmlRegisterType<DeclarativeScatterSeries, 5>(uri, 2, 1, "ScatterSeries");
qmlRegisterType<DeclarativeLineSeries, 4>(uri, 2, 1, "LineSeries");
qmlRegisterType<DeclarativeSplineSeries, 4>(uri, 2, 1, "SplineSeries");
+
+ // QtCharts 2.2
+ qmlRegisterType<DeclarativeCandlestickSeries>(uri, 2, 2, "CandlestickSeries");
+ qmlRegisterType<DeclarativeCandlestickSet>(uri, 2, 2, "CandlestickSet");
+ qmlRegisterUncreatableType<QCandlestickModelMapper>(uri, 2, 2, "CandlestickModelMapper",
+ QLatin1String("Trying to create uncreatable: CandlestickModelMapper."));
+ qmlRegisterType<QHCandlestickModelMapper>(uri, 2, 2, "HCandlestickModelMapper");
+ qmlRegisterType<QVCandlestickModelMapper>(uri, 2, 2, "VCandlestickModelMapper");
}
};
diff --git a/src/chartsqml2/declarativecandlestickseries.cpp b/src/chartsqml2/declarativecandlestickseries.cpp
new file mode 100644
index 00000000..6981e85d
--- /dev/null
+++ b/src/chartsqml2/declarativecandlestickseries.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** 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/QHCandlestickModelMapper>
+#include <QtCharts/QVCandlestickModelMapper>
+#include "declarativeaxes.h"
+#include "declarativecandlestickseries.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+DeclarativeCandlestickSet::DeclarativeCandlestickSet(qreal timestamp, QObject *parent)
+ : QCandlestickSet(timestamp, parent)
+{
+ connect(this, SIGNAL(brushChanged()), this, SLOT(handleBrushChanged()));
+}
+
+void DeclarativeCandlestickSet::setBrushFilename(const QString &brushFilename)
+{
+ QImage brushImage(brushFilename);
+ if (QCandlestickSet::brush().textureImage() != brushImage) {
+ QBrush brush = QCandlestickSet::brush();
+ brush.setTextureImage(brushImage);
+
+ QCandlestickSet::setBrush(brush);
+
+ m_brushFilename = brushFilename;
+ m_brushImage = brushImage;
+
+ emit brushFilenameChanged(brushFilename);
+ }
+}
+
+QString DeclarativeCandlestickSet::brushFilename() const
+{
+ return m_brushFilename;
+}
+
+void DeclarativeCandlestickSet::handleBrushChanged()
+{
+ // If the texture image of the brush has changed along the brush
+ // the brush file name needs to be cleared.
+ if (!m_brushFilename.isEmpty() && QCandlestickSet::brush().textureImage() != m_brushImage) {
+ m_brushFilename.clear();
+ emit brushFilenameChanged(QString());
+ }
+}
+
+// Declarative candlestick series ==================================================================
+
+DeclarativeCandlestickSeries::DeclarativeCandlestickSeries(QQuickItem *parent)
+ : QCandlestickSeries(parent),
+ m_axes(new DeclarativeAxes(this))
+{
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)),
+ this, SIGNAL(axisXChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)),
+ this, SIGNAL(axisYChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)),
+ this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)),
+ this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
+
+ connect(this, SIGNAL(hovered(bool, QCandlestickSet *)),
+ this, SLOT(onHovered(bool, QCandlestickSet *)));
+ connect(this, SIGNAL(clicked(QCandlestickSet *)), this, SLOT(onClicked(QCandlestickSet *)));
+ connect(this, SIGNAL(pressed(QCandlestickSet *)), this, SLOT(onPressed(QCandlestickSet *)));
+ connect(this, SIGNAL(released(QCandlestickSet *)), this, SLOT(onReleased(QCandlestickSet *)));
+ connect(this, SIGNAL(doubleClicked(QCandlestickSet *)),
+ this, SLOT(onDoubleClicked(QCandlestickSet *)));
+
+ connect(this, SIGNAL(brushChanged()), this, SLOT(handleBrushChanged()));
+}
+
+QQmlListProperty<QObject> DeclarativeCandlestickSeries::seriesChildren()
+{
+ return QQmlListProperty<QObject>(this, 0, &DeclarativeCandlestickSeries::appendSeriesChildren,
+ 0, 0, 0);
+}
+
+void DeclarativeCandlestickSeries::setBrushFilename(const QString &brushFilename)
+{
+ QImage brushImage(brushFilename);
+ if (QCandlestickSeries::brush().textureImage() != brushImage) {
+ QBrush brush = QCandlestickSeries::brush();
+ brush.setTextureImage(brushImage);
+
+ QCandlestickSeries::setBrush(brush);
+
+ m_brushFilename = brushFilename;
+ m_brushImage = brushImage;
+
+ emit brushFilenameChanged(brushFilename);
+ }
+}
+
+QString DeclarativeCandlestickSeries::brushFilename() const
+{
+ return m_brushFilename;
+}
+
+DeclarativeCandlestickSet *DeclarativeCandlestickSeries::at(int index)
+{
+ QList<QCandlestickSet *> sets = candlestickSets();
+ if (index >= 0 && index < sets.count())
+ return qobject_cast<DeclarativeCandlestickSet *>(sets[index]);
+
+ return 0;
+}
+
+bool DeclarativeCandlestickSeries::append(DeclarativeCandlestickSet *set)
+{
+ return QCandlestickSeries::append(qobject_cast<QCandlestickSet *>(set));
+}
+
+bool DeclarativeCandlestickSeries::remove(DeclarativeCandlestickSet *set)
+{
+ return QCandlestickSeries::remove(qobject_cast<QCandlestickSet *>(set));
+}
+
+bool DeclarativeCandlestickSeries::append(qreal open, qreal high, qreal low, qreal close,
+ qreal timestamp)
+{
+ QCandlestickSet *set = new QCandlestickSet(open, high, low, close, timestamp);
+ if (!QCandlestickSeries::append(set)) {
+ delete set;
+ return false;
+ }
+
+ return true;
+}
+
+bool DeclarativeCandlestickSeries::remove(qreal timestamp)
+{
+ for (int i = 0; i < count(); ++i) {
+ QCandlestickSet *set = candlestickSets().at(i);
+ if (set->timestamp() == timestamp)
+ return QCandlestickSeries::remove(set);
+ }
+
+ return false;
+}
+
+bool DeclarativeCandlestickSeries::insert(int index, DeclarativeCandlestickSet *set)
+{
+ return QCandlestickSeries::insert(index, qobject_cast<QCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::clear()
+{
+ QCandlestickSeries::clear();
+}
+
+void DeclarativeCandlestickSeries::classBegin()
+{
+ // do nothing
+}
+
+void DeclarativeCandlestickSeries::componentComplete()
+{
+ foreach (QObject *child, children()) {
+ if (qobject_cast<DeclarativeCandlestickSet *>(child)) {
+ QCandlestickSeries::append(qobject_cast<DeclarativeCandlestickSet *>(child));
+ } else if (qobject_cast<QHCandlestickModelMapper *>(child)) {
+ QHCandlestickModelMapper *mapper = qobject_cast<QHCandlestickModelMapper *>(child);
+ mapper->setSeries(this);
+ } else if (qobject_cast<QVCandlestickModelMapper *>(child)) {
+ QVCandlestickModelMapper *mapper = qobject_cast<QVCandlestickModelMapper *>(child);
+ mapper->setSeries(this);
+ } // else: do nothing
+ }
+}
+
+void DeclarativeCandlestickSeries::appendSeriesChildren(QQmlListProperty<QObject> *list,
+ QObject *element)
+{
+ // Empty implementation; the children are parsed in componentComplete instead
+ Q_UNUSED(list);
+ Q_UNUSED(element);
+}
+
+void DeclarativeCandlestickSeries::onClicked(QCandlestickSet *set)
+{
+ emit clicked(qobject_cast<DeclarativeCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::onHovered(bool status, QCandlestickSet *set)
+{
+ emit hovered(status, qobject_cast<DeclarativeCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::onPressed(QCandlestickSet *set)
+{
+ emit pressed(qobject_cast<DeclarativeCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::onReleased(QCandlestickSet *set)
+{
+ emit released(qobject_cast<DeclarativeCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::onDoubleClicked(QCandlestickSet *set)
+{
+ emit doubleClicked(qobject_cast<DeclarativeCandlestickSet *>(set));
+}
+
+void DeclarativeCandlestickSeries::handleBrushChanged()
+{
+ // If the texture image of the brush has changed along the brush
+ // the brush file name needs to be cleared.
+ if (!m_brushFilename.isEmpty() && QCandlestickSeries::brush().textureImage() != m_brushImage) {
+ m_brushFilename.clear();
+ emit brushFilenameChanged(QString());
+ }
+}
+
+#include "moc_declarativecandlestickseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/chartsqml2/declarativecandlestickseries.h b/src/chartsqml2/declarativecandlestickseries.h
new file mode 100644
index 00000000..9b7c0e37
--- /dev/null
+++ b/src/chartsqml2/declarativecandlestickseries.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef DECLARATIVECANDLESTICKSERIES_H
+#define DECLARATIVECANDLESTICKSERIES_H
+
+#include <QtCharts/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <QtQml/QQmlParserStatus>
+#include <QtQuick/QQuickItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class DeclarativeAxes;
+class QAbstractAxis;
+
+class DeclarativeCandlestickSet : public QCandlestickSet
+{
+ Q_OBJECT
+ Q_PROPERTY(QString brushFilename READ brushFilename WRITE setBrushFilename NOTIFY brushFilenameChanged)
+
+public:
+ explicit DeclarativeCandlestickSet(qreal timestamp = 0.0, QObject *parent = nullptr);
+ void setBrushFilename(const QString &brushFilename);
+ QString brushFilename() const;
+
+Q_SIGNALS:
+ void brushFilenameChanged(const QString &brushFilename);
+
+private Q_SLOTS:
+ void handleBrushChanged();
+
+private:
+ QString m_brushFilename;
+ QImage m_brushImage;
+};
+
+class DeclarativeCandlestickSeries : public QCandlestickSeries, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(QAbstractAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
+ Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
+ Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged)
+ Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged)
+ Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren)
+ Q_PROPERTY(QString brushFilename READ brushFilename WRITE setBrushFilename NOTIFY brushFilenameChanged)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+
+public:
+ explicit DeclarativeCandlestickSeries(QQuickItem *parent = nullptr);
+ void setAxisX(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ QAbstractAxis *axisX() { return m_axes->axisX(); }
+ void setAxisY(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
+ QAbstractAxis *axisY() { return m_axes->axisY(); }
+ void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
+ QAbstractAxis *axisXTop() { return m_axes->axisXTop(); }
+ void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
+ QQmlListProperty<QObject> seriesChildren();
+ void setBrushFilename(const QString &brushFilename);
+ QString brushFilename() const;
+
+public:
+ Q_INVOKABLE DeclarativeCandlestickSet *at(int index);
+ Q_INVOKABLE bool append(DeclarativeCandlestickSet *set);
+ Q_INVOKABLE bool remove(DeclarativeCandlestickSet *set);
+ Q_INVOKABLE bool append(qreal open, qreal high, qreal low, qreal close, qreal timestamp);
+ Q_INVOKABLE bool remove(qreal timestamp);
+ Q_INVOKABLE bool insert(int index, DeclarativeCandlestickSet *set);
+ Q_INVOKABLE void clear();
+
+public: // from QDeclarativeParserStatus
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void axisXChanged(QAbstractAxis *axis);
+ void axisYChanged(QAbstractAxis *axis);
+ void axisXTopChanged(QAbstractAxis *axis);
+ void axisYRightChanged(QAbstractAxis *axis);
+ void clicked(DeclarativeCandlestickSet *set);
+ void hovered(bool status, DeclarativeCandlestickSet *set);
+ void pressed(DeclarativeCandlestickSet *set);
+ void released(DeclarativeCandlestickSet *set);
+ void doubleClicked(DeclarativeCandlestickSet *set);
+ void brushFilenameChanged(const QString &brushFilename);
+
+public Q_SLOTS:
+ static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
+ void onClicked(QCandlestickSet *set);
+ void onHovered(bool status, QCandlestickSet *set);
+ void onPressed(QCandlestickSet *set);
+ void onReleased(QCandlestickSet *set);
+ void onDoubleClicked(QCandlestickSet *set);
+
+private Q_SLOTS:
+ void handleBrushChanged();
+
+public:
+ DeclarativeAxes *m_axes;
+
+private:
+ QString m_brushFilename;
+ QImage m_brushImage;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // DECLARATIVECANDLESTICKSERIES_H
diff --git a/src/chartsqml2/declarativechart.cpp b/src/chartsqml2/declarativechart.cpp
index ec5e83a0..66b47722 100644
--- a/src/chartsqml2/declarativechart.cpp
+++ b/src/chartsqml2/declarativechart.cpp
@@ -35,6 +35,7 @@
#include "declarativepieseries.h"
#include "declarativesplineseries.h"
#include "declarativeboxplotseries.h"
+#include "declarativecandlestickseries.h"
#include "declarativescatterseries.h"
#include "declarativechartnode.h"
#include "declarativerendernode.h"
@@ -1077,6 +1078,9 @@ QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstrac
case DeclarativeChart::SeriesTypeBoxPlot:
series = new DeclarativeBoxPlotSeries();
break;
+ case DeclarativeChart::SeriesTypeCandlestick:
+ series = new DeclarativeCandlestickSeries();
+ break;
case DeclarativeChart::SeriesTypePie:
series = new DeclarativePieSeries();
break;
@@ -1189,6 +1193,8 @@ void DeclarativeChart::initializeAxes(QAbstractSeries *series)
doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
+ else if (qobject_cast<DeclarativeCandlestickSeries *>(series))
+ doInitializeAxes(series, qobject_cast<DeclarativeCandlestickSeries *>(series)->m_axes);
// else: do nothing
}
diff --git a/src/chartsqml2/declarativechart.h b/src/chartsqml2/declarativechart.h
index 2a37d8ee..dd58b54b 100644
--- a/src/chartsqml2/declarativechart.h
+++ b/src/chartsqml2/declarativechart.h
@@ -97,6 +97,7 @@ public:
SeriesTypeStackedBar,
SeriesTypePercentBar,
SeriesTypeBoxPlot,
+ SeriesTypeCandlestick,
SeriesTypePie,
SeriesTypeScatter,
SeriesTypeSpline,
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index e8cad75c..1b04ac7c 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -23,7 +23,10 @@ SUBDIRS += \
domain \
chartdataset \
qlegend \
- cmake
+ cmake \
+ qcandlestickmodelmapper \
+ qcandlestickseries \
+ qcandlestickset
!contains(QT_COORD_TYPE, float): {
SUBDIRS += \
diff --git a/tests/auto/qcandlestickmodelmapper/qcandlestickmodelmapper.pro b/tests/auto/qcandlestickmodelmapper/qcandlestickmodelmapper.pro
new file mode 100644
index 00000000..81f0b368
--- /dev/null
+++ b/tests/auto/qcandlestickmodelmapper/qcandlestickmodelmapper.pro
@@ -0,0 +1,5 @@
+!include( ../auto.pri ) {
+ error( "Couldn't find the auto.pri file!" )
+}
+
+SOURCES += tst_qcandlestickmodelmapper.cpp
diff --git a/tests/auto/qcandlestickmodelmapper/tst_qcandlestickmodelmapper.cpp b/tests/auto/qcandlestickmodelmapper/tst_qcandlestickmodelmapper.cpp
new file mode 100644
index 00000000..b6110c7f
--- /dev/null
+++ b/tests/auto/qcandlestickmodelmapper/tst_qcandlestickmodelmapper.cpp
@@ -0,0 +1,632 @@
+/****************************************************************************
+**
+** 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/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <QtCharts/QChartView>
+#include <QtCharts/QHCandlestickModelMapper>
+#include <QtCharts/QVCandlestickModelMapper>
+#include <QtCore/QString>
+#include <QtGui/QStandardItemModel>
+#include <QtTest/QtTest>
+
+QT_CHARTS_USE_NAMESPACE
+
+class tst_qcandlestickmodelmapper : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_qcandlestickmodelmapper();
+
+ void createVerticalMapper();
+ void createHorizontalMapper();
+
+public Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void verticalMapper_data();
+ void verticalMapper();
+ void verticalMapperCustomMapping_data();
+ void verticalMapperCustomMapping();
+ void horizontalMapper_data();
+ void horizontalMapper();
+ void horizontalMapperCustomMapping_data();
+ void horizontalMapperCustomMapping();
+ void seriesUpdated();
+ void verticalModelInsertRows();
+ void verticalModelRemoveRows();
+ void verticalModelInsertColumns();
+ void verticalModelRemoveColumns();
+ void horizontalModelInsertRows();
+ void horizontalModelRemoveRows();
+ void horizontalModelInsertColumns();
+ void horizontalModelRemoveColumns();
+ void modelUpdateCell();
+ void verticalMapperSignals();
+ void horizontalMapperSignals();
+
+private:
+ QStandardItemModel *m_model;
+ int m_modelRowCount;
+ int m_modelColumnCount;
+
+ QCandlestickSeries *m_series;
+ QChart *m_chart;
+ QChartView *m_chartView;
+
+ QHCandlestickModelMapper *m_hMapper;
+ QVCandlestickModelMapper *m_vMapper;
+};
+
+tst_qcandlestickmodelmapper::tst_qcandlestickmodelmapper()
+ : m_model(nullptr),
+ m_modelRowCount(10),
+ m_modelColumnCount(8),
+ m_series(nullptr),
+ m_chart(nullptr),
+ m_chartView(nullptr),
+ m_hMapper(nullptr),
+ m_vMapper(nullptr)
+{
+}
+
+void tst_qcandlestickmodelmapper::createHorizontalMapper()
+{
+ m_hMapper = new QHCandlestickModelMapper;
+ QVERIFY(m_hMapper->model() == nullptr);
+ m_hMapper->setTimestampColumn(0);
+ m_hMapper->setOpenColumn(1);
+ m_hMapper->setHighColumn(3);
+ m_hMapper->setLowColumn(5);
+ m_hMapper->setCloseColumn(6);
+ m_hMapper->setFirstCandlestickSetRow(0);
+ m_hMapper->setLastCandlestickSetRow(4);
+ m_hMapper->setModel(m_model);
+ m_hMapper->setSeries(m_series);
+}
+
+void tst_qcandlestickmodelmapper::createVerticalMapper()
+{
+ m_vMapper = new QVCandlestickModelMapper;
+ QVERIFY(m_vMapper->model() == nullptr);
+ m_vMapper->setTimestampRow(0);
+ m_vMapper->setOpenRow(1);
+ m_vMapper->setHighRow(3);
+ m_vMapper->setLowRow(5);
+ m_vMapper->setCloseRow(6);
+ m_vMapper->setFirstCandlestickSetColumn(0);
+ m_vMapper->setLastCandlestickSetColumn(4);
+ m_vMapper->setModel(m_model);
+ m_vMapper->setSeries(m_series);
+}
+
+void tst_qcandlestickmodelmapper::initTestCase()
+{
+ m_chart = new QChart();
+ m_chartView = new QChartView(m_chart);
+ m_chartView->show();
+}
+
+void tst_qcandlestickmodelmapper::cleanupTestCase()
+{
+ delete m_chartView;
+ QTest::qWait(1); // Allow final deleteLaters to run
+}
+
+void tst_qcandlestickmodelmapper::init()
+{
+ m_series = new QCandlestickSeries();
+ m_chart->addSeries(m_series);
+
+ m_model = new QStandardItemModel(m_modelRowCount, m_modelColumnCount, this);
+ for (int row = 0; row < m_modelRowCount; ++row) {
+ for (int column = 0; column < m_modelColumnCount; ++column)
+ m_model->setData(m_model->index(row, column), row * column);
+ }
+}
+
+void tst_qcandlestickmodelmapper::cleanup()
+{
+ m_chart->removeSeries(m_series);
+ delete m_series;
+ m_series = nullptr;
+
+ m_model->clear();
+ m_model->deleteLater();
+ m_model = nullptr;
+
+ if (m_vMapper) {
+ m_vMapper->deleteLater();
+ m_vMapper = nullptr;
+ }
+
+ if (m_hMapper) {
+ m_hMapper->deleteLater();
+ m_hMapper = nullptr;
+ }
+}
+
+void tst_qcandlestickmodelmapper::verticalMapper_data()
+{
+ QTest::addColumn<int>("firstCandlestickSetColumn");
+ QTest::addColumn<int>("lastCandlestickSetColumn");
+ QTest::addColumn<int>("expectedCandlestickSetCount");
+
+ QTest::newRow("last column greater than first column") << 0 << 1 << 2;
+ QTest::newRow("last column equal to first column") << 1 << 1 << 1;
+ QTest::newRow("last column lesser than first column") << 1 << 0 << 0;
+ QTest::newRow("invalid first column and correct last column") << -3 << 1 << 0;
+ QTest::newRow("first column beyond the size of model and correct last column") << m_modelColumnCount << 1 << 0;
+ QTest::newRow("first column beyond the size of model and invalid last column") << m_modelColumnCount << -1 << 0;
+}
+
+void tst_qcandlestickmodelmapper::verticalMapper()
+{
+ QFETCH(int, firstCandlestickSetColumn);
+ QFETCH(int, lastCandlestickSetColumn);
+ QFETCH(int, expectedCandlestickSetCount);
+
+ QCandlestickSeries *series = new QCandlestickSeries();
+ m_chart->addSeries(series);
+
+ createVerticalMapper();
+ m_vMapper->setFirstCandlestickSetColumn(firstCandlestickSetColumn);
+ m_vMapper->setLastCandlestickSetColumn(lastCandlestickSetColumn);
+ m_vMapper->setSeries(series);
+
+ QCOMPARE(m_vMapper->firstCandlestickSetColumn(), qMax(firstCandlestickSetColumn, -1));
+ QCOMPARE(m_vMapper->lastCandlestickSetColumn(), qMax(lastCandlestickSetColumn, -1));
+ QCOMPARE(series->count(), expectedCandlestickSetCount);
+
+ m_chart->removeSeries(series);
+ delete series;
+}
+
+void tst_qcandlestickmodelmapper::verticalMapperCustomMapping_data()
+{
+ QTest::addColumn<int>("timestampRow");
+ QTest::addColumn<int>("openRow");
+ QTest::addColumn<int>("highRow");
+ QTest::addColumn<int>("lowRow");
+ QTest::addColumn<int>("closeRow");
+
+ QTest::newRow("all rows are correct") << 0 << 1 << 2 << 3 << 4;
+ QTest::newRow("all rows are invalid") << -3 << -3 << -3 << -3 << -3;
+ QTest::newRow("timestamp: -1 (invalid)") << -1 << 1 << 2 << 3 << 4;
+ QTest::newRow("timestamp: -3 (invalid - should default to -1)") << -3 << 1 << 2 << 3 << 4;
+ QTest::newRow("timestamp: +1 greater than the number of rows in the model") << m_modelRowCount + 1 << 1 << 2 << 3 << 4;
+ QTest::newRow("open: -1 (invalid)") << 0 << -1 << 2 << 3 << 4;
+ QTest::newRow("open: -3 (invalid - should default to -1)") << 0 << -3 << 2 << 3 << 4;
+ QTest::newRow("open: +1 greater than the number of rows in the model") << 0 << m_modelRowCount + 1 << 2 << 3 << 4;
+ QTest::newRow("high: -1 (invalid)") << 0 << 1 << -1 << 3 << 4;
+ QTest::newRow("high: -3 (invalid - should default to -1)") << 0 << 1 << -3 << 3 << 4;
+ QTest::newRow("high: +1 greater than the number of rows in the model") << 0 << 1 << m_modelRowCount + 1 << 3 << 4;
+ QTest::newRow("low: -1 (invalid)") << 0 << 1 << 2 << -1 << 4;
+ QTest::newRow("low: -3 (invalid - should default to -1)") << 0 << 1 << 2 << -3 << 4;
+ QTest::newRow("low: +1 greater than the number of rows in the model") << 0 << 1 << 2 << m_modelRowCount + 1 << 4;
+ QTest::newRow("close: -1 (invalid)") << 0 << 1 << 2 << 3 << -1;
+ QTest::newRow("close: -3 (invalid - should default to -1)") << 0 << 1 << 2 << 3 << -3;
+ QTest::newRow("close: +1 greater than the number of rows in the model") << 0 << 1 << 2 << 3 << m_modelRowCount + 1;
+}
+
+void tst_qcandlestickmodelmapper::verticalMapperCustomMapping()
+{
+ QFETCH(int, timestampRow);
+ QFETCH(int, openRow);
+ QFETCH(int, highRow);
+ QFETCH(int, lowRow);
+ QFETCH(int, closeRow);
+
+ QCandlestickSeries *series = new QCandlestickSeries();
+ m_chart->addSeries(series);
+ QCOMPARE(series->count(), 0);
+
+ createVerticalMapper();
+ m_vMapper->setTimestampRow(timestampRow);
+ m_vMapper->setOpenRow(openRow);
+ m_vMapper->setHighRow(highRow);
+ m_vMapper->setLowRow(lowRow);
+ m_vMapper->setCloseRow(closeRow);
+ m_vMapper->setSeries(series);
+
+ QCOMPARE(m_vMapper->timestampRow(), qMax(timestampRow, -1));
+ QCOMPARE(m_vMapper->openRow(), qMax(openRow, -1));
+ QCOMPARE(m_vMapper->highRow(), qMax(highRow, -1));
+ QCOMPARE(m_vMapper->lowRow(), qMax(lowRow, -1));
+ QCOMPARE(m_vMapper->closeRow(), qMax(closeRow, -1));
+
+ int count;
+ if ((m_vMapper->timestampRow() >= 0 && m_vMapper->timestampRow() < m_modelRowCount)
+ && (m_vMapper->openRow() >= 0 && m_vMapper->openRow() < m_modelRowCount)
+ && (m_vMapper->highRow() >= 0 && m_vMapper->highRow() < m_modelRowCount)
+ && (m_vMapper->lowRow() >= 0 && m_vMapper->lowRow() < m_modelRowCount)
+ && (m_vMapper->closeRow() >= 0 && m_vMapper->closeRow() < m_modelRowCount))
+ count = m_vMapper->lastCandlestickSetColumn() - m_vMapper->firstCandlestickSetColumn() + 1;
+ else
+ count = 0;
+ QCOMPARE(series->count(), count);
+
+ // change values column mapping to invalid
+ m_vMapper->setFirstCandlestickSetColumn(-1);
+ m_vMapper->setLastCandlestickSetColumn(1);
+ QCOMPARE(series->count(), 0);
+
+ m_chart->removeSeries(series);
+ delete series;
+}
+
+void tst_qcandlestickmodelmapper::horizontalMapper_data()
+{
+ QTest::addColumn<int>("firstCandlestickSetRow");
+ QTest::addColumn<int>("lastCandlestickSetRow");
+ QTest::addColumn<int>("expectedCandlestickSetCount");
+
+ QTest::newRow("last row greater than first row") << 0 << 1 << 2;
+ QTest::newRow("last row equal to first row") << 1 << 1 << 1;
+ QTest::newRow("last row lesser than first row") << 1 << 0 << 0;
+ QTest::newRow("invalid first row and correct last row") << -3 << 1 << 0;
+ QTest::newRow("first row beyond the size of model and correct last row") << m_modelRowCount << 1 << 0;
+ QTest::newRow("first row beyond the size of model and invalid last row") << m_modelRowCount << -1 << 0;
+}
+
+void tst_qcandlestickmodelmapper::horizontalMapper()
+{
+ QFETCH(int, firstCandlestickSetRow);
+ QFETCH(int, lastCandlestickSetRow);
+ QFETCH(int, expectedCandlestickSetCount);
+
+ QCandlestickSeries *series = new QCandlestickSeries();
+ m_chart->addSeries(series);
+
+ createHorizontalMapper();
+ m_hMapper->setFirstCandlestickSetRow(firstCandlestickSetRow);
+ m_hMapper->setLastCandlestickSetRow(lastCandlestickSetRow);
+ m_hMapper->setSeries(series);
+
+ QCOMPARE(m_hMapper->firstCandlestickSetRow(), qMax(firstCandlestickSetRow, -1));
+ QCOMPARE(m_hMapper->lastCandlestickSetRow(), qMax(lastCandlestickSetRow, -1));
+ QCOMPARE(series->count(), expectedCandlestickSetCount);
+
+ m_chart->removeSeries(series);
+ delete series;
+}
+
+void tst_qcandlestickmodelmapper::horizontalMapperCustomMapping_data()
+{
+ QTest::addColumn<int>("timestampColumn");
+ QTest::addColumn<int>("openColumn");
+ QTest::addColumn<int>("highColumn");
+ QTest::addColumn<int>("lowColumn");
+ QTest::addColumn<int>("closeColumn");
+
+ QTest::newRow("all columns are correct") << 0 << 1 << 2 << 3 << 4;
+ QTest::newRow("all columns are invalid") << -3 << -3 << -3 << -3 << -3;
+ QTest::newRow("timestamp: -1 (invalid)") << -1 << 1 << 2 << 3 << 4;
+ QTest::newRow("timestamp: -3 (invalid - should default to -1)") << -3 << 1 << 2 << 3 << 4;
+ QTest::newRow("timestamp: +1 greater than the number of columns in the model") << m_modelColumnCount + 1 << 1 << 2 << 3 << 4;
+ QTest::newRow("open: -1 (invalid)") << 0 << -1 << 2 << 3 << 4;
+ QTest::newRow("open: -3 (invalid - should default to -1)") << 0 << -3 << 2 << 3 << 4;
+ QTest::newRow("open: +1 greater than the number of columns in the model") << 0 << m_modelColumnCount + 1 << 2 << 3 << 4;
+ QTest::newRow("high: -1 (invalid)") << 0 << 1 << -1 << 3 << 4;
+ QTest::newRow("high: -3 (invalid - should default to -1)") << 0 << 1 << -3 << 3 << 4;
+ QTest::newRow("high: +1 greater than the number of columns in the model") << 0 << 1 << m_modelColumnCount + 1 << 3 << 4;
+ QTest::newRow("low: -1 (invalid)") << 0 << 1 << 2 << -1 << 4;
+ QTest::newRow("low: -3 (invalid - should default to -1)") << 0 << 1 << 2 << -3 << 4;
+ QTest::newRow("low: +1 greater than the number of columns in the model") << 0 << 1 << 2 << m_modelColumnCount + 1 << 4;
+ QTest::newRow("close: -1 (invalid)") << 0 << 1 << 2 << 3 << -1;
+ QTest::newRow("close: -3 (invalid - should default to -1)") << 0 << 1 << 2 << 3 << -3;
+ QTest::newRow("close: +1 greater than the number of columns in the model") << 0 << 1 << 2 << 3 << m_modelColumnCount + 1;
+}
+
+void tst_qcandlestickmodelmapper::horizontalMapperCustomMapping()
+{
+ QFETCH(int, timestampColumn);
+ QFETCH(int, openColumn);
+ QFETCH(int, highColumn);
+ QFETCH(int, lowColumn);
+ QFETCH(int, closeColumn);
+
+ QCandlestickSeries *series = new QCandlestickSeries();
+ m_chart->addSeries(series);
+ QCOMPARE(series->count(), 0);
+
+ createHorizontalMapper();
+ m_hMapper->setTimestampColumn(timestampColumn);
+ m_hMapper->setOpenColumn(openColumn);
+ m_hMapper->setHighColumn(highColumn);
+ m_hMapper->setLowColumn(lowColumn);
+ m_hMapper->setCloseColumn(closeColumn);
+ m_hMapper->setSeries(series);
+
+ QCOMPARE(m_hMapper->timestampColumn(), qMax(timestampColumn, -1));
+ QCOMPARE(m_hMapper->openColumn(), qMax(openColumn, -1));
+ QCOMPARE(m_hMapper->highColumn(), qMax(highColumn, -1));
+ QCOMPARE(m_hMapper->lowColumn(), qMax(lowColumn, -1));
+ QCOMPARE(m_hMapper->closeColumn(), qMax(closeColumn, -1));
+
+ int count;
+ if ((m_hMapper->timestampColumn() >= 0 && m_hMapper->timestampColumn() < m_modelColumnCount)
+ && (m_hMapper->openColumn() >= 0 && m_hMapper->openColumn() < m_modelColumnCount)
+ && (m_hMapper->highColumn() >= 0 && m_hMapper->highColumn() < m_modelColumnCount)
+ && (m_hMapper->lowColumn() >= 0 && m_hMapper->lowColumn() < m_modelColumnCount)
+ && (m_hMapper->closeColumn() >= 0 && m_hMapper->closeColumn() < m_modelColumnCount))
+ count = m_hMapper->lastCandlestickSetRow() - m_hMapper->firstCandlestickSetRow() + 1;
+ else
+ count = 0;
+ QCOMPARE(series->count(), count);
+
+ // change values row mapping to invalid
+ m_hMapper->setFirstCandlestickSetRow(-1);
+ m_hMapper->setLastCandlestickSetRow(1);
+ QCOMPARE(series->count(), 0);
+
+ m_chart->removeSeries(series);
+ delete series;
+}
+
+void tst_qcandlestickmodelmapper::seriesUpdated()
+{
+ createVerticalMapper();
+ QVERIFY(m_vMapper->model() != nullptr);
+
+ QCandlestickSet *set = m_series->candlestickSets().value(0, 0);
+ QVERIFY(set != nullptr);
+
+ // update values
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->timestampRow(), 0)).toReal(),set->timestamp());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->openRow(), 0)).toReal(), set->open());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->highRow(), 0)).toReal(), set->high());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->lowRow(), 0)).toReal(), set->low());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->closeRow(), 0)).toReal(), set->close());
+ set->setTimestamp(set->timestamp() + 5.0);
+ set->setOpen(set->open() + 6.0);
+ set->setHigh(set->high() + 7.0);
+ set->setLow(set->low() + 8.0);
+ set->setClose(set->close() + 9.0);
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->timestampRow(), 0)).toReal(),set->timestamp());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->openRow(), 0)).toReal(), set->open());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->highRow(), 0)).toReal(), set->high());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->lowRow(), 0)).toReal(), set->low());
+ QCOMPARE(m_model->data(m_model->index(m_vMapper->closeRow(), 0)).toReal(), set->close());
+
+ // append new sets
+ QList<QCandlestickSet *> newCandlestickSets;
+ newCandlestickSets << new QCandlestickSet(3.0, 5.0, 2.0, 4.0, 1234);
+ newCandlestickSets << new QCandlestickSet(5.0, 7.0, 4.0, 6.0, 5678);
+ m_series->append(newCandlestickSets);
+ QCOMPARE(m_model->columnCount(), m_modelColumnCount + newCandlestickSets.count());
+
+ // remove sets
+ newCandlestickSets.clear();
+ newCandlestickSets << m_series->candlestickSets().at(m_series->count() - 1);
+ newCandlestickSets << m_series->candlestickSets().at(m_series->count() - 2);
+ m_series->remove(newCandlestickSets);
+ QCOMPARE(m_model->columnCount(), m_modelColumnCount);
+}
+
+void tst_qcandlestickmodelmapper::verticalModelInsertRows()
+{
+ createVerticalMapper();
+ int count = m_vMapper->lastCandlestickSetColumn() - m_vMapper->firstCandlestickSetColumn() + 1;
+ QVERIFY(m_vMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->insertRows(3, 4);
+ QCOMPARE(m_series->count(), count);
+}
+
+void tst_qcandlestickmodelmapper::verticalModelRemoveRows()
+{
+ createVerticalMapper();
+ int count = m_vMapper->lastCandlestickSetColumn() - m_vMapper->firstCandlestickSetColumn() + 1;
+ QVERIFY(m_vMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->removeRows(m_modelRowCount - 1, 1);
+ QCOMPARE(m_series->count(), count);
+
+ int removeCount = m_model->rowCount() - m_vMapper->closeRow();
+ m_model->removeRows(m_vMapper->closeRow(), removeCount);
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_qcandlestickmodelmapper::verticalModelInsertColumns()
+{
+ createVerticalMapper();
+ int count = m_vMapper->lastCandlestickSetColumn() - m_vMapper->firstCandlestickSetColumn() + 1;
+ QVERIFY(m_vMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->insertColumns(3, 4);
+ QCOMPARE(m_series->count(), count);
+}
+
+void tst_qcandlestickmodelmapper::verticalModelRemoveColumns()
+{
+ createVerticalMapper();
+ int count = m_vMapper->lastCandlestickSetColumn() - m_vMapper->firstCandlestickSetColumn() + 1;
+ QVERIFY(m_vMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ int removeCount = m_modelColumnCount - 2;
+ m_model->removeColumns(0, removeCount);
+ QCOMPARE(m_series->count(), qMin(m_model->columnCount(), count));
+
+ // leave all the columns
+ m_model->removeColumns(0, m_modelColumnCount - removeCount);
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_qcandlestickmodelmapper::horizontalModelInsertRows()
+{
+ createHorizontalMapper();
+ int count = m_hMapper->lastCandlestickSetRow() - m_hMapper->firstCandlestickSetRow() + 1;
+ QVERIFY(m_hMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->insertRows(3, 4);
+ QCOMPARE(m_series->count(), count);
+}
+
+void tst_qcandlestickmodelmapper::horizontalModelRemoveRows()
+{
+ createHorizontalMapper();
+ int count = m_hMapper->lastCandlestickSetRow() - m_hMapper->firstCandlestickSetRow() + 1;
+ QVERIFY(m_hMapper->model() != 0);
+ QCOMPARE(m_series->count(), qMin(m_model->rowCount(), count));
+
+ int removeCount = m_modelRowCount - 2;
+ m_model->removeRows(0, removeCount);
+ QCOMPARE(m_series->count(), qMin(m_model->rowCount(), count));
+
+ // leave all the columns
+ m_model->removeRows(0, m_modelRowCount - removeCount);
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_qcandlestickmodelmapper::horizontalModelInsertColumns()
+{
+ createHorizontalMapper();
+ int count = m_hMapper->lastCandlestickSetRow() - m_hMapper->firstCandlestickSetRow() + 1;
+ QVERIFY(m_hMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->insertColumns(3, 4);
+ QCOMPARE(m_series->count(), count);
+}
+
+void tst_qcandlestickmodelmapper::horizontalModelRemoveColumns()
+{
+ createHorizontalMapper();
+ int count = m_hMapper->lastCandlestickSetRow() - m_hMapper->firstCandlestickSetRow() + 1;
+ QVERIFY(m_hMapper->model() != 0);
+ QCOMPARE(m_series->count(), count);
+
+ m_model->removeColumns(m_modelColumnCount - 1, 1);
+ QCOMPARE(m_series->count(), count);
+
+ int removeCount = m_model->columnCount() - m_hMapper->closeColumn();
+ m_model->removeColumns(m_hMapper->closeColumn(), removeCount);
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_qcandlestickmodelmapper::modelUpdateCell()
+{
+ createVerticalMapper();
+ QVERIFY(m_vMapper->model() != 0);
+
+ QModelIndex index = m_model->index(m_vMapper->timestampRow(), 0);
+ qreal newValue = 44.0;
+ QVERIFY(m_model->setData(index, newValue));
+ QCOMPARE(m_model->data(index).toReal(), newValue);
+ QCOMPARE(m_series->candlestickSets().at(index.row())->timestamp(), newValue);
+}
+
+void tst_qcandlestickmodelmapper::verticalMapperSignals()
+{
+ QVCandlestickModelMapper *mapper = new QVCandlestickModelMapper();
+
+ QSignalSpy spy0(mapper, SIGNAL(modelReplaced()));
+ QSignalSpy spy1(mapper, SIGNAL(seriesReplaced()));
+ QSignalSpy spy2(mapper, SIGNAL(timestampRowChanged()));
+ QSignalSpy spy3(mapper, SIGNAL(openRowChanged()));
+ QSignalSpy spy4(mapper, SIGNAL(highRowChanged()));
+ QSignalSpy spy5(mapper, SIGNAL(lowRowChanged()));
+ QSignalSpy spy6(mapper, SIGNAL(closeRowChanged()));
+ QSignalSpy spy7(mapper, SIGNAL(firstCandlestickSetColumnChanged()));
+ QSignalSpy spy8(mapper, SIGNAL(lastCandlestickSetColumnChanged()));
+
+ mapper->setModel(m_model);
+ mapper->setSeries(m_series);
+ mapper->setTimestampRow(1);
+ mapper->setOpenRow(2);
+ mapper->setHighRow(3);
+ mapper->setLowRow(4);
+ mapper->setCloseRow(5);
+ mapper->setFirstCandlestickSetColumn(0);
+ mapper->setLastCandlestickSetColumn(1);
+
+ QCOMPARE(spy0.count(), 1);
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy5.count(), 1);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+
+ delete mapper;
+}
+
+void tst_qcandlestickmodelmapper::horizontalMapperSignals()
+{
+ QHCandlestickModelMapper *mapper = new QHCandlestickModelMapper();
+
+ QSignalSpy spy0(mapper, SIGNAL(modelReplaced()));
+ QSignalSpy spy1(mapper, SIGNAL(seriesReplaced()));
+ QSignalSpy spy2(mapper, SIGNAL(timestampColumnChanged()));
+ QSignalSpy spy3(mapper, SIGNAL(openColumnChanged()));
+ QSignalSpy spy4(mapper, SIGNAL(highColumnChanged()));
+ QSignalSpy spy5(mapper, SIGNAL(lowColumnChanged()));
+ QSignalSpy spy6(mapper, SIGNAL(closeColumnChanged()));
+ QSignalSpy spy7(mapper, SIGNAL(firstCandlestickSetRowChanged()));
+ QSignalSpy spy8(mapper, SIGNAL(lastCandlestickSetRowChanged()));
+
+ mapper->setModel(m_model);
+ mapper->setSeries(m_series);
+ mapper->setTimestampColumn(1);
+ mapper->setOpenColumn(2);
+ mapper->setHighColumn(3);
+ mapper->setLowColumn(4);
+ mapper->setCloseColumn(5);
+ mapper->setFirstCandlestickSetRow(0);
+ mapper->setLastCandlestickSetRow(1);
+
+ QCOMPARE(spy0.count(), 1);
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy5.count(), 1);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+
+ delete mapper;
+}
+
+QTEST_MAIN(tst_qcandlestickmodelmapper)
+
+#include "tst_qcandlestickmodelmapper.moc"
diff --git a/tests/auto/qcandlestickseries/qcandlestickseries.pro b/tests/auto/qcandlestickseries/qcandlestickseries.pro
new file mode 100644
index 00000000..ccaa2e25
--- /dev/null
+++ b/tests/auto/qcandlestickseries/qcandlestickseries.pro
@@ -0,0 +1,5 @@
+!include( ../auto.pri ) {
+ error( "Couldn't find the auto.pri file!" )
+}
+
+SOURCES += tst_qcandlestickseries.cpp
diff --git a/tests/auto/qcandlestickseries/tst_qcandlestickseries.cpp b/tests/auto/qcandlestickseries/tst_qcandlestickseries.cpp
new file mode 100644
index 00000000..61201bf3
--- /dev/null
+++ b/tests/auto/qcandlestickseries/tst_qcandlestickseries.cpp
@@ -0,0 +1,936 @@
+/****************************************************************************
+**
+** 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/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <QtCharts/QChartView>
+#include <QtTest/QtTest>
+#include "tst_definitions.h"
+
+QT_CHARTS_USE_NAMESPACE
+
+Q_DECLARE_METATYPE(QCandlestickSet *)
+Q_DECLARE_METATYPE(QList<QCandlestickSet *>)
+
+class tst_QCandlestickSeries : public QObject
+{
+ Q_OBJECT
+
+public Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void qCandlestickSeries();
+ void append();
+ void remove();
+ void appendList();
+ void removeList();
+ void insert();
+ void take();
+ void clear();
+ void candlestickSets();
+ void count();
+ void type();
+ void maximumColumnWidth_data();
+ void maximumColumnWidth();
+ void minimumColumnWidth_data();
+ void minimumColumnWidth();
+ void bodyWidth_data();
+ void bodyWidth();
+ void bodyOutlineVisible();
+ void capsWidth_data();
+ void capsWidth();
+ void capsVisible();
+ void increasingColor();
+ void decreasingColor();
+ void brush();
+ void pen();
+ void mouseClicked();
+ void mouseHovered();
+ void mousePressed();
+ void mouseReleased();
+ void mouseDoubleClicked();
+
+private:
+ QCandlestickSeries *m_series;
+ QList<QCandlestickSet *> m_sets;
+};
+
+void tst_QCandlestickSeries::initTestCase()
+{
+ qRegisterMetaType<QCandlestickSet *>("QCandlestickSet *");
+ qRegisterMetaType<QList<QCandlestickSet *>>("QList<QCandlestickSet *>");
+}
+
+void tst_QCandlestickSeries::cleanupTestCase()
+{
+ QTest::qWait(1); // Allow final deleteLaters to run
+}
+
+void tst_QCandlestickSeries::init()
+{
+ m_series = new QCandlestickSeries();
+ m_series->setMaximumColumnWidth(5432.1);
+ m_series->setMinimumColumnWidth(2.0);
+ m_series->setBodyWidth(0.99);
+ m_series->setCapsWidth(0.99);
+
+ for (int i = 0; i < 5; ++i) {
+ qreal timestamp = QDateTime::currentMSecsSinceEpoch() + i * 1000000;
+
+ QCandlestickSet *set = new QCandlestickSet(timestamp);
+ set->setOpen(4);
+ set->setHigh(4);
+ set->setLow(1);
+ set->setClose(1);
+
+ m_sets.append(set);
+ }
+}
+
+void tst_QCandlestickSeries::cleanup()
+{
+ foreach (QCandlestickSet *set, m_sets) {
+ m_series->remove(set);
+ m_sets.removeAll(set);
+ delete set;
+ }
+
+ delete m_series;
+ m_series = nullptr;
+}
+
+void tst_QCandlestickSeries::qCandlestickSeries()
+{
+ QCandlestickSeries *series = new QCandlestickSeries();
+
+ QVERIFY(series != nullptr);
+
+ delete series;
+ series = nullptr;
+}
+
+void tst_QCandlestickSeries::append()
+{
+ QCOMPARE(m_series->count(), 0);
+
+ // Try adding set
+ QCandlestickSet *set1 = new QCandlestickSet(1234.0);
+ QVERIFY(m_series->append(set1));
+ QCOMPARE(m_series->count(), 1);
+
+ // Try adding another set
+ QCandlestickSet *set2 = new QCandlestickSet(2345.0);
+ QVERIFY(m_series->append(set2));
+ QCOMPARE(m_series->count(), 2);
+
+ // Try adding same set again
+ QVERIFY(!m_series->append(set2));
+ QCOMPARE(m_series->count(), 2);
+
+ // Try adding null set
+ QVERIFY(!m_series->append(nullptr));
+ QCOMPARE(m_series->count(), 2);
+}
+
+void tst_QCandlestickSeries::remove()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Try to remove null pointer (should not remove, should not crash)
+ QVERIFY(!m_series->remove(nullptr));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Try to remove invalid pointer (should not remove, should not crash)
+ QVERIFY(!m_series->remove((QCandlestickSet *)(m_sets.at(0) + 1)));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Remove some sets
+ const int removeCount = 3;
+ for (int i = 0; i < removeCount; ++i)
+ QVERIFY(m_series->remove(m_sets.at(i)));
+ QCOMPARE(m_series->count(), m_sets.count() - removeCount);
+
+ for (int i = removeCount; i < m_sets.count(); ++i)
+ QCOMPARE(m_series->candlestickSets().at(i - removeCount), m_sets.at(i));
+
+ // Try removing all sets again (should be ok, even if some sets have already been removed)
+ for (int i = 0; i < m_sets.count(); ++i)
+ m_series->remove(m_sets.at(i));
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_QCandlestickSeries::appendList()
+{
+ QCOMPARE(m_series->count(), 0);
+
+ // Append new sets (should succeed, count should match the count of sets)
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_series->count());
+
+ // Append same sets again (should fail, count should remain same)
+ QVERIFY(!m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_series->count());
+
+ // Try append empty list (should succeed, but count should remain same)
+ QList<QCandlestickSet *> invalidList;
+ QVERIFY(m_series->append(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Try append list with one new and one existing set (should fail, count remains same)
+ invalidList.append(new QCandlestickSet());
+ invalidList.append(m_sets.at(0));
+ QVERIFY(!m_series->append(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+ delete invalidList.at(0);
+ invalidList.clear();
+
+ // Try append list with null pointers (should fail, count remains same)
+ QVERIFY(invalidList.isEmpty());
+ invalidList.append(nullptr);
+ invalidList.append(nullptr);
+ invalidList.append(nullptr);
+ QVERIFY(!m_series->append(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+}
+
+void tst_QCandlestickSeries::removeList()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Try remove empty list (should fail, but count should remain same)
+ QList<QCandlestickSet *> invalidList;
+ QVERIFY(!m_series->remove(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Try remove list with one new and one existing set (should fail, count remains same)
+ invalidList.append(new QCandlestickSet());
+ invalidList.append(m_sets.at(0));
+ QVERIFY(!m_series->remove(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+ delete invalidList.at(0);
+ invalidList.clear();
+
+ // Try remove list with null pointers (should fail, count remains same)
+ QVERIFY(invalidList.isEmpty());
+ invalidList.append(nullptr);
+ invalidList.append(nullptr);
+ invalidList.append(nullptr);
+ QVERIFY(!m_series->remove(invalidList));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ // Remove all sets (should succeed, count should be zero)
+ QVERIFY(m_series->remove(m_sets));
+ QCOMPARE(m_series->count(), 0);
+
+ // Remove same sets again (should fail, count should remain zero)
+ QVERIFY(!m_series->remove(m_sets));
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_QCandlestickSeries::insert()
+{
+ QCOMPARE(m_series->count(), 0);
+
+ QSignalSpy countSpy(m_series, SIGNAL(countChanged()));
+ QSignalSpy addedSpy(m_series, SIGNAL(candlestickSetsAdded(QList<QCandlestickSet *>)));
+
+ for (int i = 0; i < m_sets.count(); ++i) {
+ QCandlestickSet *set = m_sets.at(i);
+ QVERIFY(m_series->insert(0, set));
+ QCOMPARE(m_series->count(), i + 1);
+ QTRY_COMPARE(countSpy.count(), i + 1);
+ QTRY_COMPARE(addedSpy.count(), i + 1);
+
+ QList<QVariant> args = addedSpy.value(i);
+ QCOMPARE(args.count(), 1);
+ QList<QCandlestickSet *> sets = qvariant_cast<QList<QCandlestickSet *>>(args.at(0));
+ QCOMPARE(sets.count(), 1);
+ QCOMPARE(sets.first(), set);
+ }
+}
+
+void tst_QCandlestickSeries::take()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QSignalSpy countSpy(m_series, SIGNAL(countChanged()));
+ QSignalSpy removedSpy(m_series, SIGNAL(candlestickSetsRemoved(QList<QCandlestickSet *>)));
+
+ for (int i = 0; i < m_sets.count(); ++i) {
+ QCandlestickSet *set = m_sets.at(i);
+ QVERIFY(m_series->take(set));
+ QCOMPARE(m_series->count(), m_sets.count() - i - 1);
+ QTRY_COMPARE(countSpy.count(), i + 1);
+ QTRY_COMPARE(removedSpy.count(), i + 1);
+
+ QList<QVariant> args = removedSpy.value(i);
+ QCOMPARE(args.count(), 1);
+ QList<QCandlestickSet *> sets = qvariant_cast<QList<QCandlestickSet *>>(args.at(0));
+ QCOMPARE(sets.count(), 1);
+ QCOMPARE(sets.first(), set);
+ }
+}
+
+void tst_QCandlestickSeries::clear()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ m_series->clear();
+ QCOMPARE(m_series->count(), 0);
+}
+
+void tst_QCandlestickSeries::candlestickSets()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->candlestickSets(), m_sets);
+
+ for (int i = 0; i < m_sets.count(); ++i)
+ QCOMPARE(m_series->candlestickSets().at(i), m_sets.at(i));
+
+ m_series->clear();
+ QCOMPARE(m_series->candlestickSets(), QList<QCandlestickSet *>());
+}
+
+void tst_QCandlestickSeries::count()
+{
+ m_series->append(m_sets);
+ QCOMPARE(m_series->count(), m_sets.count());
+ QCOMPARE(m_series->count(), m_series->candlestickSets().count());
+}
+
+void tst_QCandlestickSeries::type()
+{
+ QCOMPARE(m_series->type(), QAbstractSeries::SeriesTypeCandlestick);
+}
+
+void tst_QCandlestickSeries::maximumColumnWidth_data()
+{
+ QTest::addColumn<qreal>("maximumColumnWidth");
+ QTest::addColumn<qreal>("expectedMaximumColumnWidth");
+
+ QTest::newRow("maximum column width less than -1.0") << -3.0 << -1.0;
+ QTest::newRow("maximum column equals to -1.0") << -1.0 << -1.0;
+ QTest::newRow("maximum column width greater than -1.0, but less than zero") << -0.5 << -1.0;
+ QTest::newRow("maximum column width equals zero") << 0.0 << 0.0;
+ QTest::newRow("maximum column width greater than zero") << 1.0 << 1.0;
+ QTest::newRow("maximum column width contains a fractional part") << 3.4 << 3.4;
+}
+
+void tst_QCandlestickSeries::maximumColumnWidth()
+{
+ QFETCH(qreal, maximumColumnWidth);
+ QFETCH(qreal, expectedMaximumColumnWidth);
+
+ QSignalSpy spy(m_series, SIGNAL(maximumColumnWidthChanged()));
+
+ m_series->setMaximumColumnWidth(maximumColumnWidth);
+ QCOMPARE(m_series->maximumColumnWidth(), expectedMaximumColumnWidth);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same maximum column width
+ m_series->setMaximumColumnWidth(expectedMaximumColumnWidth);
+ QCOMPARE(m_series->maximumColumnWidth(), expectedMaximumColumnWidth);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::minimumColumnWidth_data()
+{
+ QTest::addColumn<qreal>("minimumColumnWidth");
+ QTest::addColumn<qreal>("expectedMinimumColumnWidth");
+
+ QTest::newRow("minimum column width less than -1.0") << -3.0 << -1.0;
+ QTest::newRow("minimum column equals to -1.0") << -1.0 << -1.0;
+ QTest::newRow("minimum column width greater than -1.0, but less than zero") << -0.5 << -1.0;
+ QTest::newRow("minimum column width equals zero") << 0.0 << 0.0;
+ QTest::newRow("minimum column width greater than zero") << 1.0 << 1.0;
+ QTest::newRow("minimum column width contains a fractional part") << 3.4 << 3.4;
+}
+
+void tst_QCandlestickSeries::minimumColumnWidth()
+{
+ QFETCH(qreal, minimumColumnWidth);
+ QFETCH(qreal, expectedMinimumColumnWidth);
+
+ QSignalSpy spy(m_series, SIGNAL(minimumColumnWidthChanged()));
+
+ m_series->setMinimumColumnWidth(minimumColumnWidth);
+ QCOMPARE(m_series->minimumColumnWidth(), expectedMinimumColumnWidth);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same minimum column width
+ m_series->setMinimumColumnWidth(expectedMinimumColumnWidth);
+ QCOMPARE(m_series->minimumColumnWidth(), expectedMinimumColumnWidth);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::bodyWidth_data()
+{
+ QTest::addColumn<qreal>("bodyWidth");
+ QTest::addColumn<qreal>("expectedBodyWidth");
+
+ QTest::newRow("body width less than zero") << -1.0 << 0.0;
+ QTest::newRow("body width equals zero") << 0.0 << 0.0;
+ QTest::newRow("body width greater than zero and less than one") << 0.5 << 0.5;
+ QTest::newRow("body width equals one") << 1.0 << 1.0;
+ QTest::newRow("body width greater than one") << 2.0 << 1.0;
+}
+
+void tst_QCandlestickSeries::bodyWidth()
+{
+ QFETCH(qreal, bodyWidth);
+ QFETCH(qreal, expectedBodyWidth);
+
+ QSignalSpy spy(m_series, SIGNAL(bodyWidthChanged()));
+
+ m_series->setBodyWidth(bodyWidth);
+ QCOMPARE(m_series->bodyWidth(), expectedBodyWidth);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same body width
+ m_series->setBodyWidth(bodyWidth);
+ QCOMPARE(m_series->bodyWidth(), expectedBodyWidth);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::bodyOutlineVisible()
+{
+ QSignalSpy spy(m_series, SIGNAL(bodyOutlineVisibilityChanged()));
+
+ bool visible = !m_series->bodyOutlineVisible();
+ m_series->setBodyOutlineVisible(visible);
+ QCOMPARE(m_series->bodyOutlineVisible(), visible);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same body outline visibility
+ m_series->setBodyOutlineVisible(visible);
+ QCOMPARE(m_series->bodyOutlineVisible(), visible);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::capsWidth_data()
+{
+ QTest::addColumn<qreal>("capsWidth");
+ QTest::addColumn<qreal>("expectedCapsWidth");
+
+ QTest::newRow("caps width less than zero") << -1.0 << 0.0;
+ QTest::newRow("caps width equals zero") << 0.0 << 0.0;
+ QTest::newRow("caps width greater than zero and less than one") << 0.5 << 0.5;
+ QTest::newRow("caps width equals one") << 1.0 << 1.0;
+ QTest::newRow("caps width greater than one") << 2.0 << 1.0;
+}
+
+void tst_QCandlestickSeries::capsWidth()
+{
+ QFETCH(qreal, capsWidth);
+ QFETCH(qreal, expectedCapsWidth);
+
+ QSignalSpy spy(m_series, SIGNAL(capsWidthChanged()));
+
+ m_series->setCapsWidth(capsWidth);
+ QCOMPARE(m_series->capsWidth(), expectedCapsWidth);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same caps width
+ m_series->setCapsWidth(capsWidth);
+ QCOMPARE(m_series->capsWidth(), expectedCapsWidth);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::capsVisible()
+{
+ QSignalSpy spy(m_series, SIGNAL(capsVisibilityChanged()));
+
+ bool visible = !m_series->capsVisible();
+ m_series->setCapsVisible(visible);
+ QCOMPARE(m_series->capsVisible(), visible);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same caps visibility
+ m_series->setCapsVisible(visible);
+ QCOMPARE(m_series->capsVisible(), visible);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::increasingColor()
+{
+ QSignalSpy spy(m_series, SIGNAL(increasingColorChanged()));
+
+ // Try set new increasing color
+ QColor newColor(200, 200, 200, 200);
+ m_series->setIncreasingColor(newColor);
+ QCOMPARE(m_series->increasingColor(), newColor);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same increasing color again
+ m_series->setIncreasingColor(newColor);
+ QCOMPARE(m_series->increasingColor(), newColor);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set invalid increasing color (should change to default color)
+ QColor defaultColor = m_series->brush().color();
+ defaultColor.setAlpha(128);
+ m_series->setIncreasingColor(QColor());
+ QCOMPARE(m_series->increasingColor(), defaultColor);
+ QCOMPARE(spy.count(), 2);
+
+ // Set new brush, increasing color should change accordingly
+ QBrush brush(newColor);
+ defaultColor = brush.color();
+ defaultColor.setAlpha(128);
+ m_series->setBrush(brush);
+ QCOMPARE(m_series->increasingColor(), defaultColor);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QCandlestickSeries::decreasingColor()
+{
+ QSignalSpy spy(m_series, SIGNAL(decreasingColorChanged()));
+
+ // Try set new decreasing color
+ QColor newColor(200, 200, 200, 200);
+ m_series->setDecreasingColor(newColor);
+ QCOMPARE(m_series->decreasingColor(), newColor);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same decreasing color again
+ m_series->setDecreasingColor(newColor);
+ QCOMPARE(m_series->decreasingColor(), newColor);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set invalid decreasing color (should change to default color)
+ m_series->setDecreasingColor(QColor());
+ QCOMPARE(m_series->decreasingColor(), m_series->brush().color());
+ QCOMPARE(spy.count(), 2);
+
+ // Set new brush, decreasing color should change accordingly
+ m_series->setBrush(QBrush(newColor));
+ QCOMPARE(m_series->decreasingColor(), m_series->brush().color());
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QCandlestickSeries::brush()
+{
+ QSignalSpy spy(m_series, SIGNAL(brushChanged()));
+
+ QBrush brush(QColor(128, 128, 128, 128));
+ QColor increasingColor(brush.color());
+ increasingColor.setAlpha(128);
+ QColor decreasingColor(brush.color());
+ m_series->setBrush(brush);
+ QCOMPARE(m_series->brush(), brush);
+ QCOMPARE(m_series->increasingColor(), increasingColor);
+ QCOMPARE(m_series->decreasingColor(), decreasingColor);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same brush
+ m_series->setBrush(brush);
+ QCOMPARE(m_series->brush(), brush);
+ QCOMPARE(m_series->increasingColor(), increasingColor);
+ QCOMPARE(m_series->decreasingColor(), decreasingColor);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::pen()
+{
+ QSignalSpy spy(m_series, SIGNAL(penChanged()));
+
+ QPen pen(QColor(128, 128, 128, 128));
+ m_series->setPen(pen);
+ QCOMPARE(m_series->pen(), pen);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same pen
+ m_series->setPen(pen);
+ QCOMPARE(m_series->pen(), pen);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSeries::mouseClicked()
+{
+ SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
+
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QCandlestickSet *set1 = m_series->candlestickSets().at(1);
+ QCandlestickSet *set2 = m_series->candlestickSets().at(2);
+
+ QSignalSpy seriesSpy(m_series, SIGNAL(clicked(QCandlestickSet *)));
+ QSignalSpy setSpy1(set1, SIGNAL(clicked()));
+ QSignalSpy setSpy2(set2, SIGNAL(clicked()));
+
+ QChartView view(new QChart());
+ view.resize(400, 300);
+ view.chart()->addSeries(m_series);
+ view.chart()->createDefaultAxes();
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Calculate expected layout for candlesticks
+ QRectF plotArea = view.chart()->plotArea();
+ qreal candlestickWidth = plotArea.width() / m_series->count();
+ qreal candlestickHeight = plotArea.height();
+
+ QMap<QCandlestickSet *, QRectF> layout;
+ layout.insert(set1, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set1),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+ layout.insert(set2, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set2),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+
+ // Click set 1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set1).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 0);
+
+ QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy1.takeFirst().isEmpty());
+
+ // Click set 2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set2).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 0);
+ QCOMPARE(setSpy2.count(), 1);
+
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy2.takeFirst().isEmpty());
+}
+
+void tst_QCandlestickSeries::mouseHovered()
+{
+ SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
+
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QCandlestickSet *set1 = m_series->candlestickSets().at(1);
+ QCandlestickSet *set2 = m_series->candlestickSets().at(2);
+
+ QSignalSpy seriesSpy(m_series, SIGNAL(hovered(bool, QCandlestickSet *)));
+ QSignalSpy setSpy1(set1, SIGNAL(hovered(bool)));
+ QSignalSpy setSpy2(set2, SIGNAL(hovered(bool)));
+
+ QChartView view(new QChart());
+ view.resize(400, 300);
+ view.chart()->addSeries(m_series);
+ view.chart()->createDefaultAxes();
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // This is hack since view does not get events otherwise
+ view.setMouseTracking(true);
+
+ // Calculate expected layout for candlesticks
+ QRectF plotArea = view.chart()->plotArea();
+ qreal candlestickWidth = plotArea.width() / m_series->count();
+ qreal candlestickHeight = plotArea.height();
+
+ QMap<QCandlestickSet *, QRectF> layout;
+ layout.insert(set1, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set1),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+ layout.insert(set2, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set2),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+
+ // Move mouse to left border
+ QTest::mouseMove(view.viewport(), QPoint(0, layout.value(set1).center().y()));
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 0);
+ QCOMPARE(setSpy1.count(), 0);
+ QCOMPARE(setSpy2.count(), 0);
+
+ // Move mouse on top of set 1
+ QTest::mouseMove(view.viewport(), layout.value(set1).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 0);
+
+ QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set1);
+ QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(seriesSpyArgs.at(0).toBool(), true);
+ seriesSpyArgs.clear();
+
+ QList<QVariant> setSpyArgs = setSpy1.takeFirst();
+ QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(setSpyArgs.at(0).toBool(), true);
+ setSpyArgs.clear();
+
+ // Move mouse from top of set 1 to top of set 2
+ QTest::mouseMove(view.viewport(), layout.value(set2).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 2);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 1);
+
+ // Should leave set 1
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set1);
+ QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(seriesSpyArgs.at(0).toBool(), false);
+ // Don't call seriesSpyArgs.clear() here
+
+ setSpyArgs = setSpy1.takeFirst();
+ QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(setSpyArgs.at(0).toBool(), false);
+ // Don't call setSpyArgs.clear() here
+
+ // Should enter set 2
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set2);
+ QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(seriesSpyArgs.at(0).toBool(), true);
+ seriesSpyArgs.clear();
+
+ setSpyArgs = setSpy2.takeFirst();
+ QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(setSpyArgs.at(0).toBool(), true);
+ setSpyArgs.clear();
+
+ // Move mouse from top of set 2 to background
+ QTest::mouseMove(view.viewport(), QPoint(layout.value(set2).center().x(), 0));
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 0);
+ QCOMPARE(setSpy2.count(), 1);
+
+ // Should leave set 2
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set2);
+ QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(seriesSpyArgs.at(0).toBool(), false);
+ seriesSpyArgs.clear();
+
+ setSpyArgs = setSpy2.takeFirst();
+ QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool);
+ QCOMPARE(setSpyArgs.at(0).toBool(), false);
+ setSpyArgs.clear();
+}
+
+void tst_QCandlestickSeries::mousePressed()
+{
+ SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
+
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QCandlestickSet *set1 = m_series->candlestickSets().at(1);
+ QCandlestickSet *set2 = m_series->candlestickSets().at(2);
+
+ QSignalSpy seriesSpy(m_series, SIGNAL(pressed(QCandlestickSet *)));
+ QSignalSpy setSpy1(set1, SIGNAL(pressed()));
+ QSignalSpy setSpy2(set2, SIGNAL(pressed()));
+
+ QChartView view(new QChart());
+ view.resize(400, 300);
+ view.chart()->addSeries(m_series);
+ view.chart()->createDefaultAxes();
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Calculate expected layout for candlesticks
+ QRectF plotArea = view.chart()->plotArea();
+ qreal candlestickWidth = plotArea.width() / m_series->count();
+ qreal candlestickHeight = plotArea.height();
+
+ QMap<QCandlestickSet *, QRectF> layout;
+ layout.insert(set1, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set1),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+ layout.insert(set2, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set2),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+
+ // Press set 1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set1).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 0);
+
+ QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy1.takeFirst().isEmpty());
+
+ // Press set 2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set2).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 0);
+ QCOMPARE(setSpy2.count(), 1);
+
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy2.takeFirst().isEmpty());
+}
+
+void tst_QCandlestickSeries::mouseReleased()
+{
+ SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
+
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QCandlestickSet *set1 = m_series->candlestickSets().at(1);
+ QCandlestickSet *set2 = m_series->candlestickSets().at(2);
+
+ QSignalSpy seriesSpy(m_series, SIGNAL(released(QCandlestickSet *)));
+ QSignalSpy setSpy1(set1, SIGNAL(released()));
+ QSignalSpy setSpy2(set2, SIGNAL(released()));
+
+ QChartView view(new QChart());
+ view.resize(400, 300);
+ view.chart()->addSeries(m_series);
+ view.chart()->createDefaultAxes();
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Calculate expected layout for candlesticks
+ QRectF plotArea = view.chart()->plotArea();
+ qreal candlestickWidth = plotArea.width() / m_series->count();
+ qreal candlestickHeight = plotArea.height();
+
+ QMap<QCandlestickSet *, QRectF> layout;
+ layout.insert(set1, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set1),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+ layout.insert(set2, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set2),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+
+ // Release mouse over set 1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set1).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 0);
+
+ QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy1.takeFirst().isEmpty());
+
+ // Release mouse over set 2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, layout.value(set2).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 0);
+ QCOMPARE(setSpy2.count(), 1);
+
+ seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy2.takeFirst().isEmpty());
+}
+
+void tst_QCandlestickSeries::mouseDoubleClicked()
+{
+ SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
+
+ QVERIFY(m_series->append(m_sets));
+ QCOMPARE(m_series->count(), m_sets.count());
+
+ QCandlestickSet *set1 = m_series->candlestickSets().at(1);
+ QCandlestickSet *set2 = m_series->candlestickSets().at(2);
+
+ QSignalSpy seriesSpy(m_series, SIGNAL(doubleClicked(QCandlestickSet *)));
+ QSignalSpy setSpy1(set1, SIGNAL(doubleClicked()));
+ QSignalSpy setSpy2(set2, SIGNAL(doubleClicked()));
+
+ QChartView view(new QChart());
+ view.resize(400, 300);
+ view.chart()->addSeries(m_series);
+ view.chart()->createDefaultAxes();
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Calculate expected layout for candlesticks
+ QRectF plotArea = view.chart()->plotArea();
+ qreal candlestickWidth = plotArea.width() / m_series->count();
+ qreal candlestickHeight = plotArea.height();
+
+ QMap<QCandlestickSet *, QRectF> layout;
+ layout.insert(set1, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set1),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+ layout.insert(set2, QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(set2),
+ plotArea.top(), candlestickWidth, candlestickHeight));
+
+ // Double-click set 1
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, layout.value(set1).center().toPoint());
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+
+ QCOMPARE(seriesSpy.count(), 1);
+ QCOMPARE(setSpy1.count(), 1);
+ QCOMPARE(setSpy2.count(), 0);
+
+ QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst();
+ QCOMPARE(seriesSpyArgs.count(), 1);
+ QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1);
+ seriesSpyArgs.clear();
+
+ QVERIFY(setSpy1.takeFirst().isEmpty());
+}
+
+QTEST_MAIN(tst_QCandlestickSeries)
+
+#include "tst_qcandlestickseries.moc"
diff --git a/tests/auto/qcandlestickset/qcandlestickset.pro b/tests/auto/qcandlestickset/qcandlestickset.pro
new file mode 100644
index 00000000..e67d1df8
--- /dev/null
+++ b/tests/auto/qcandlestickset/qcandlestickset.pro
@@ -0,0 +1,5 @@
+!include( ../auto.pri ) {
+ error( "Couldn't find the auto.pri file!" )
+}
+
+SOURCES += tst_qcandlestickset.cpp
diff --git a/tests/auto/qcandlestickset/tst_qcandlestickset.cpp b/tests/auto/qcandlestickset/tst_qcandlestickset.cpp
new file mode 100644
index 00000000..5e94d4c9
--- /dev/null
+++ b/tests/auto/qcandlestickset/tst_qcandlestickset.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** 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/QCandlestickSet>
+#include <QtCore/QDateTime>
+#include <QtTest/QtTest>
+
+QT_CHARTS_USE_NAMESPACE
+
+class tst_QCandlestickSet : public QObject
+{
+ Q_OBJECT
+
+public Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void qCandlestickSet_data();
+ void qCandlestickSet();
+ void timestamp_data();
+ void timestamp();
+ void open_data();
+ void open();
+ void high_data();
+ void high();
+ void low_data();
+ void low();
+ void close_data();
+ void close();
+ void brush();
+ void pen();
+
+private:
+ QCandlestickSet* m_candlestickSet;
+};
+
+void tst_QCandlestickSet::initTestCase()
+{
+}
+
+void tst_QCandlestickSet::cleanupTestCase()
+{
+ QTest::qWait(1); // Allow final deleteLaters to run
+}
+
+void tst_QCandlestickSet::init()
+{
+ m_candlestickSet = new QCandlestickSet(QDateTime::currentMSecsSinceEpoch());
+ m_candlestickSet->setOpen(2345.67);
+ m_candlestickSet->setHigh(4567.89);
+ m_candlestickSet->setLow(1234.56);
+ m_candlestickSet->setClose(3456.78);
+}
+
+void tst_QCandlestickSet::cleanup()
+{
+ delete m_candlestickSet;
+ m_candlestickSet = nullptr;
+}
+
+void tst_QCandlestickSet::qCandlestickSet_data()
+{
+ QTest::addColumn<qreal>("timestamp");
+ QTest::addColumn<qreal>("expectedTimestamp");
+
+ QTest::newRow("timestamp less than zero") << -1.0 << 0.0;
+ QTest::newRow("timestamp equals zero") << 0.0 << 0.0;
+ QTest::newRow("timestamp greater than zero") << 1.0 << 1.0;
+ QTest::newRow("timestamp rounded down") << 4.321 << 4.0;
+ QTest::newRow("timestamp rounded up") << 5.678 << 6.0;
+}
+
+void tst_QCandlestickSet::qCandlestickSet()
+{
+ QFETCH(qreal, timestamp);
+ QFETCH(qreal, expectedTimestamp);
+
+ QCandlestickSet candlestickSet(timestamp);
+ QCOMPARE(candlestickSet.timestamp(), expectedTimestamp);
+}
+
+void tst_QCandlestickSet::timestamp_data()
+{
+ QTest::addColumn<qreal>("timestamp");
+ QTest::addColumn<qreal>("expectedTimestamp");
+
+ QTest::newRow("timestamp less than zero") << -1.0 << 0.0;
+ QTest::newRow("timestamp equals zero") << 0.0 << 0.0;
+ QTest::newRow("timestamp greater than zero") << 1.0 << 1.0;
+ QTest::newRow("timestamp rounded down") << 4.321 << 4.0;
+ QTest::newRow("timestamp rounded up") << 5.678 << 6.0;
+}
+
+void tst_QCandlestickSet::timestamp()
+{
+ QFETCH(qreal, timestamp);
+ QFETCH(qreal, expectedTimestamp);
+
+ QSignalSpy spy(m_candlestickSet, SIGNAL(timestampChanged()));
+
+ m_candlestickSet->setTimestamp(timestamp);
+ QCOMPARE(m_candlestickSet->timestamp(), expectedTimestamp);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same timestamp value
+ m_candlestickSet->setTimestamp(expectedTimestamp);
+ QCOMPARE(m_candlestickSet->timestamp(), expectedTimestamp);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::open_data()
+{
+ QTest::addColumn<qreal>("open");
+
+ QTest::newRow("open less than zero") << -1.234;
+ QTest::newRow("open equals zero") << 0.0;
+ QTest::newRow("open greater than zero") << 1.234;
+}
+
+void tst_QCandlestickSet::open()
+{
+ QFETCH(qreal, open);
+
+ QSignalSpy spy(m_candlestickSet, SIGNAL(openChanged()));
+
+ m_candlestickSet->setOpen(open);
+ QCOMPARE(m_candlestickSet->open(), open);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same open value
+ m_candlestickSet->setOpen(open);
+ QCOMPARE(m_candlestickSet->open(), open);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::high_data()
+{
+ QTest::addColumn<qreal>("high");
+
+ QTest::newRow("high less than zero") << -1.234;
+ QTest::newRow("high equals zero") << 0.0;
+ QTest::newRow("high greater than zero") << 1.234;
+}
+
+void tst_QCandlestickSet::high()
+{
+ QFETCH(qreal, high);
+
+ QSignalSpy spy(m_candlestickSet, SIGNAL(highChanged()));
+
+ m_candlestickSet->setHigh(high);
+ QCOMPARE(m_candlestickSet->high(), high);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same high value
+ m_candlestickSet->setHigh(high);
+ QCOMPARE(m_candlestickSet->high(), high);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::low_data()
+{
+ QTest::addColumn<qreal>("low");
+
+ QTest::newRow("low less than zero") << -1.234;
+ QTest::newRow("low equals zero") << 0.0;
+ QTest::newRow("low greater than zero") << 1.234;
+}
+
+void tst_QCandlestickSet::low()
+{
+ QFETCH(qreal, low);
+
+ QSignalSpy spy(m_candlestickSet, SIGNAL(lowChanged()));
+
+ m_candlestickSet->setLow(low);
+ QCOMPARE(m_candlestickSet->low(), low);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same low value
+ m_candlestickSet->setLow(low);
+ QCOMPARE(m_candlestickSet->low(), low);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::close_data()
+{
+ QTest::addColumn<qreal>("close");
+
+ QTest::newRow("close less than zero") << -1.234;
+ QTest::newRow("close equals zero") << 0.0;
+ QTest::newRow("close greater than zero") << 1.234;
+}
+
+void tst_QCandlestickSet::close()
+{
+ QFETCH(qreal, close);
+
+ QSignalSpy spy(m_candlestickSet, SIGNAL(closeChanged()));
+
+ m_candlestickSet->setClose(close);
+ QCOMPARE(m_candlestickSet->close(), close);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same close value
+ m_candlestickSet->setClose(close);
+ QCOMPARE(m_candlestickSet->close(), close);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::brush()
+{
+ QSignalSpy spy(m_candlestickSet, SIGNAL(brushChanged()));
+
+ QCOMPARE(m_candlestickSet->brush(), QBrush(Qt::NoBrush));
+
+ m_candlestickSet->setBrush(QBrush(Qt::NoBrush));
+ QCOMPARE(m_candlestickSet->brush(), QBrush(Qt::NoBrush));
+ QCOMPARE(spy.count(), 0);
+
+ QBrush brush(QColor(128, 128, 128, 128));
+ m_candlestickSet->setBrush(brush);
+ QCOMPARE(m_candlestickSet->brush(), brush);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same brush
+ m_candlestickSet->setBrush(brush);
+ QCOMPARE(m_candlestickSet->brush(), brush);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QCandlestickSet::pen()
+{
+ QSignalSpy spy(m_candlestickSet, SIGNAL(penChanged()));
+
+ QCOMPARE(m_candlestickSet->pen(), QPen(Qt::NoPen));
+
+ m_candlestickSet->setPen(QPen(Qt::NoPen));
+ QCOMPARE(m_candlestickSet->pen(), QPen(Qt::NoPen));
+ QCOMPARE(spy.count(), 0);
+
+ QPen pen(QColor(128, 128, 128, 128));
+ m_candlestickSet->setPen(pen);
+ QCOMPARE(m_candlestickSet->pen(), pen);
+ QCOMPARE(spy.count(), 1);
+
+ // Try set same pen
+ m_candlestickSet->setPen(pen);
+ QCOMPARE(m_candlestickSet->pen(), pen);
+ QCOMPARE(spy.count(), 1);
+}
+
+QTEST_GUILESS_MAIN(tst_QCandlestickSet)
+
+#include "tst_qcandlestickset.moc"
diff --git a/tests/manual/candlesticktester/candlesticktester.pro b/tests/manual/candlesticktester/candlesticktester.pro
new file mode 100644
index 00000000..fd927b6e
--- /dev/null
+++ b/tests/manual/candlesticktester/candlesticktester.pro
@@ -0,0 +1,13 @@
+!include( ../../tests.pri ) {
+ error( "Couldn't find the test.pri file!" )
+}
+
+QT += widgets
+
+SOURCES += main.cpp \
+ mainwidget.cpp \
+ customtablemodel.cpp
+
+HEADERS += \
+ mainwidget.h \
+ customtablemodel.h
diff --git a/tests/manual/candlesticktester/customtablemodel.cpp b/tests/manual/candlesticktester/customtablemodel.cpp
new file mode 100644
index 00000000..e0122429
--- /dev/null
+++ b/tests/manual/candlesticktester/customtablemodel.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** 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/QCandlestickSet>
+#include <QtCore/QRect>
+#include <QtCore/QVector>
+#include <QtGui/QColor>
+#include "customtablemodel.h"
+
+CustomTableModel::CustomTableModel(QObject *parent)
+ : QAbstractTableModel(parent)
+{
+ m_categories.append(QStringLiteral("Timestamp"));
+ m_categories.append(QStringLiteral("Open"));
+ m_categories.append(QStringLiteral("High"));
+ m_categories.append(QStringLiteral("Low"));
+ m_categories.append(QStringLiteral("Close"));
+}
+
+CustomTableModel::~CustomTableModel()
+{
+ qDeleteAll(m_data);
+}
+
+int CustomTableModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return m_data.count();
+}
+
+int CustomTableModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return m_categories.count();
+}
+
+QVariant CustomTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal)
+ return m_categories[section];
+ else
+ return QStringLiteral("%1").arg(section);
+}
+
+bool CustomTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid() && role == Qt::EditRole) {
+ m_data[index.row()]->replace(index.column(), value.toDouble());
+ emit dataChanged(index, index);
+
+ return true;
+ }
+
+ return false;
+}
+
+QVariant CustomTableModel::data(const QModelIndex &index, int role) const
+{
+ switch (role) {
+ case Qt::DisplayRole:
+ // fall through
+ case Qt::EditRole:
+ return m_data[index.row()]->at(index.column());
+ case Qt::BackgroundRole:
+ foreach (QRect rect, m_mapping) {
+ if (rect.contains(index.column(), index.row()))
+ return QColor(m_mapping.key(rect));
+ }
+ // cell is not mapped, return white color
+ return QColor(Qt::white);
+ default:
+ return QVariant();
+ }
+}
+
+Qt::ItemFlags CustomTableModel::flags(const QModelIndex &index) const
+{
+ return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+}
+
+bool CustomTableModel::insertRows(int row, int count, const QModelIndex &parent)
+{
+ beginInsertRows(parent, row, row + count - 1);
+ m_data.append(new QVector<qreal>(columnCount()));
+ endInsertRows();
+
+ return true;
+}
+
+bool CustomTableModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ beginRemoveRows(parent, row, row + count - 1);
+ for (int i = row + count; i >= row; --i)
+ m_data.removeAt(i);
+ endRemoveRows();
+
+ return true;
+}
+
+void CustomTableModel::addRow(QCandlestickSet *set)
+{
+ bool changed = insertRows(m_data.count(), 1);
+
+ if (changed) {
+ QVector<qreal> *row = m_data.last();
+ row->insert(0, set->timestamp());
+ row->insert(1, set->open());
+ row->insert(2, set->high());
+ row->insert(3, set->low());
+ row->insert(4, set->close());
+ }
+}
+
+void CustomTableModel::clearRows()
+{
+ bool changed = removeRows(0, m_data.count());
+ if (changed)
+ m_data.clear();
+}
+
+void CustomTableModel::addMapping(QString color, QRect area)
+{
+ m_mapping.insertMulti(color, area);
+}
+
+void CustomTableModel::clearMapping()
+{
+ m_mapping.clear();
+}
diff --git a/tests/manual/candlesticktester/customtablemodel.h b/tests/manual/candlesticktester/customtablemodel.h
new file mode 100644
index 00000000..4a8965c3
--- /dev/null
+++ b/tests/manual/candlesticktester/customtablemodel.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef CUSTOMTABLEMODEL_H
+#define CUSTOMTABLEMODEL_H
+
+#include <QtCharts/QChartGlobal>
+#include <QtCore/QAbstractTableModel>
+#include <QtCore/QHash>
+#include <QtCore/QRect>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QCandlestickSet;
+QT_CHARTS_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+
+class CustomTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ explicit CustomTableModel(QObject *parent = nullptr);
+ virtual ~CustomTableModel();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+ void addRow(QCandlestickSet *set);
+ void clearRows();
+
+ void addMapping(QString color, QRect area);
+ void clearMapping();
+
+private:
+ QStringList m_categories;
+ QList<QVector<qreal> *> m_data;
+ QHash<QString, QRect> m_mapping;
+};
+
+#endif // CUSTOMTABLEMODEL_H
diff --git a/tests/manual/candlesticktester/main.cpp b/tests/manual/candlesticktester/main.cpp
new file mode 100644
index 00000000..3c893315
--- /dev/null
+++ b/tests/manual/candlesticktester/main.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** 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 <QtWidgets/QApplication>
+#include "mainwidget.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ MainWidget w;
+ w.setWindowTitle(QStringLiteral("Candlestick Chart Tester"));
+ w.resize(1280, 720);
+ w.show();
+
+ return a.exec();
+}
diff --git a/tests/manual/candlesticktester/mainwidget.cpp b/tests/manual/candlesticktester/mainwidget.cpp
new file mode 100644
index 00000000..7364f023
--- /dev/null
+++ b/tests/manual/candlesticktester/mainwidget.cpp
@@ -0,0 +1,691 @@
+/****************************************************************************
+**
+** 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/QCandlestickSeries>
+#include <QtCharts/QCandlestickSet>
+#include <QtCharts/QDateTimeAxis>
+#include <QtCharts/QHCandlestickModelMapper>
+#include <QtCharts/QValueAxis>
+#include <QtCore/QDateTime>
+#include <QtCore/QDebug>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QHeaderView>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QTableView>
+#include "customtablemodel.h"
+#include "mainwidget.h"
+
+QT_CHARTS_USE_NAMESPACE
+
+MainWidget::MainWidget(QWidget *parent)
+ : QWidget(parent),
+ m_chart(new QChart()),
+ m_chartView(new QChartView(m_chart, this)),
+ m_axisX(nullptr),
+ m_axisY(nullptr),
+ m_maximumColumnWidth(-1.0),
+ m_minimumColumnWidth(5.0),
+ m_bodyOutlineVisible(true),
+ m_capsVisible(false),
+ m_bodyWidth(0.5),
+ m_capsWidth(0.5),
+ m_customIncreasingColor(false),
+ m_customDecreasingColor(false),
+ m_hModelMapper(new QHCandlestickModelMapper(this))
+{
+ qsrand(QDateTime::currentDateTime().toTime_t());
+
+ m_chartView->setRenderHint(QPainter::Antialiasing, false);
+
+ m_hModelMapper->setModel(new CustomTableModel(this));
+ m_hModelMapper->setTimestampColumn(0);
+ m_hModelMapper->setOpenColumn(1);
+ m_hModelMapper->setHighColumn(2);
+ m_hModelMapper->setLowColumn(3);
+ m_hModelMapper->setCloseColumn(4);
+
+ QGridLayout *mainLayout = new QGridLayout();
+ mainLayout->addLayout(createSeriesControlsLayout(), 0, 0);
+ mainLayout->addLayout(createSetsControlsLayout(), 1, 0);
+ mainLayout->addLayout(createCandlestickControlsLayout(), 2, 0);
+ mainLayout->addLayout(createMiscellaneousControlsLayout(), 3, 0);
+ mainLayout->addWidget(m_chartView, 0, 1, mainLayout->rowCount() + 1, 1);
+ mainLayout->addLayout(createModelMapperControlsLayout(), 0, 2, mainLayout->rowCount(), 1);
+ setLayout(mainLayout);
+
+ addSeries();
+}
+
+MainWidget::~MainWidget()
+{
+}
+
+QGridLayout *MainWidget::createSeriesControlsLayout()
+{
+ QGridLayout *layout = new QGridLayout();
+ int row = 0;
+
+ layout->addWidget(new QLabel(QStringLiteral("Series controls:")), row, 0, Qt::AlignLeft);
+
+ QPushButton *addSeriesButton = new QPushButton(QStringLiteral("Add a series"));
+ connect(addSeriesButton, SIGNAL(clicked(bool)), this, SLOT(addSeries()));
+ layout->addWidget(addSeriesButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *removeSeriesButton = new QPushButton(QStringLiteral("Remove a series"));
+ connect(removeSeriesButton, SIGNAL(clicked(bool)), this, SLOT(removeSeries()));
+ layout->addWidget(removeSeriesButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *removeAllSeriesButton = new QPushButton(QStringLiteral("Remove all series"));
+ connect(removeAllSeriesButton, SIGNAL(clicked(bool)), this, SLOT(removeAllSeries()));
+ layout->addWidget(removeAllSeriesButton, row++, 1, Qt::AlignLeft);
+
+ return layout;
+}
+
+QGridLayout *MainWidget::createSetsControlsLayout()
+{
+ QGridLayout *layout = new QGridLayout();
+ int row = 0;
+
+ layout->addWidget(new QLabel(QStringLiteral("Sets controls:")), row, 0, Qt::AlignLeft);
+
+ QPushButton *addSetButton = new QPushButton(QStringLiteral("Add a set"));
+ connect(addSetButton, SIGNAL(clicked(bool)), this, SLOT(addSet()));
+ layout->addWidget(addSetButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *insertSetButton = new QPushButton(QStringLiteral("Insert a set"));
+ connect(insertSetButton, SIGNAL(clicked(bool)), this, SLOT(insertSet()));
+ layout->addWidget(insertSetButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *removeSetButton = new QPushButton(QStringLiteral("Remove a set"));
+ connect(removeSetButton, SIGNAL(clicked(bool)), this, SLOT(removeSet()));
+ layout->addWidget(removeSetButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *removeAllSetsButton = new QPushButton(QStringLiteral("Remove all sets"));
+ connect(removeAllSetsButton, SIGNAL(clicked(bool)), this, SLOT(removeAllSets()));
+ layout->addWidget(removeAllSetsButton, row++, 1, Qt::AlignLeft);
+
+ return layout;
+}
+
+QGridLayout *MainWidget::createCandlestickControlsLayout()
+{
+ QGridLayout *layout = new QGridLayout();
+ int row = 0;
+
+ layout->addWidget(new QLabel(QStringLiteral("Maximum column width:")), row, 0, Qt::AlignLeft);
+ QDoubleSpinBox *maximumColumnWidthSpinBox = new QDoubleSpinBox();
+ maximumColumnWidthSpinBox->setRange(-1.0, 1024.0);
+ maximumColumnWidthSpinBox->setDecimals(0);
+ maximumColumnWidthSpinBox->setValue(m_maximumColumnWidth);
+ maximumColumnWidthSpinBox->setSingleStep(1.0);
+ connect(maximumColumnWidthSpinBox, SIGNAL(valueChanged(double)),
+ this, SLOT(changeMaximumColumnWidth(double)));
+ layout->addWidget(maximumColumnWidthSpinBox, row++, 1, Qt::AlignLeft);
+
+ layout->addWidget(new QLabel(QStringLiteral("Minimum column width:")), row, 0, Qt::AlignLeft);
+ QDoubleSpinBox *minimumColumnWidthSpinBox = new QDoubleSpinBox();
+ minimumColumnWidthSpinBox->setRange(-1.0, 1024.0);
+ minimumColumnWidthSpinBox->setDecimals(0);
+ minimumColumnWidthSpinBox->setValue(m_minimumColumnWidth);
+ minimumColumnWidthSpinBox->setSingleStep(1.0);
+ connect(minimumColumnWidthSpinBox, SIGNAL(valueChanged(double)),
+ this, SLOT(changeMinimumColumnWidth(double)));
+ layout->addWidget(minimumColumnWidthSpinBox, row++, 1, Qt::AlignLeft);
+
+ QCheckBox *bodyOutlineVisible = new QCheckBox(QStringLiteral("Body outline visible"));
+ connect(bodyOutlineVisible, SIGNAL(toggled(bool)), this, SLOT(bodyOutlineVisibleToggled(bool)));
+ bodyOutlineVisible->setChecked(m_bodyOutlineVisible);
+ layout->addWidget(bodyOutlineVisible, row++, 0, Qt::AlignLeft);
+
+ QCheckBox *capsVisible = new QCheckBox(QStringLiteral("Caps visible"));
+ connect(capsVisible, SIGNAL(toggled(bool)), this, SLOT(capsVisibleToggled(bool)));
+ capsVisible->setChecked(m_capsVisible);
+ layout->addWidget(capsVisible, row++, 0, Qt::AlignLeft);
+
+ layout->addWidget(new QLabel(QStringLiteral("Candlestick body width:")), row, 0, Qt::AlignLeft);
+ QDoubleSpinBox *bodyWidthSpinBox = new QDoubleSpinBox();
+ bodyWidthSpinBox->setRange(-1.0, 2.0);
+ bodyWidthSpinBox->setValue(m_bodyWidth);
+ bodyWidthSpinBox->setSingleStep(0.1);
+ connect(bodyWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeBodyWidth(double)));
+ layout->addWidget(bodyWidthSpinBox, row++, 1, Qt::AlignLeft);
+
+ layout->addWidget(new QLabel(QStringLiteral("Candlestick caps width:")), row, 0, Qt::AlignLeft);
+ QDoubleSpinBox *capsWidthSpinBox = new QDoubleSpinBox();
+ capsWidthSpinBox->setRange(-1.0, 2.0);
+ capsWidthSpinBox->setValue(m_capsWidth);
+ capsWidthSpinBox->setSingleStep(0.1);
+ connect(capsWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeCapsWidth(double)));
+ layout->addWidget(capsWidthSpinBox, row++, 1, Qt::AlignLeft);
+
+ QCheckBox *increasingColor = new QCheckBox(QStringLiteral("Custom increasing color (only S1)"));
+ connect(increasingColor, SIGNAL(toggled(bool)), this, SLOT(customIncreasingColorToggled(bool)));
+ increasingColor->setChecked(m_customIncreasingColor);
+ layout->addWidget(increasingColor, row++, 0, 1, 2, Qt::AlignLeft);
+
+ QCheckBox *decreasingColor = new QCheckBox(QStringLiteral("Custom decreasing color (only S1)"));
+ connect(decreasingColor, SIGNAL(toggled(bool)), this, SLOT(customDecreasingColorToggled(bool)));
+ decreasingColor->setChecked(m_customDecreasingColor);
+ layout->addWidget(decreasingColor, row++, 0, 1, 2, Qt::AlignLeft);
+
+ return layout;
+}
+
+QGridLayout *MainWidget::createMiscellaneousControlsLayout()
+{
+ QGridLayout *layout = new QGridLayout();
+ int row = 0;
+
+ layout->addWidget(new QLabel(QStringLiteral("Miscellaneous:")), row, 0, Qt::AlignLeft);
+
+ QCheckBox *antialiasingCheckBox = new QCheckBox(QStringLiteral("Antialiasing"));
+ connect(antialiasingCheckBox, SIGNAL(toggled(bool)), this, SLOT(antialiasingToggled(bool)));
+ antialiasingCheckBox->setChecked(false);
+ layout->addWidget(antialiasingCheckBox, row++, 1, Qt::AlignLeft);
+
+ QCheckBox *animationCheckBox = new QCheckBox(QStringLiteral("Animation"));
+ connect(animationCheckBox, SIGNAL(toggled(bool)), this, SLOT(animationToggled(bool)));
+ animationCheckBox->setChecked(false);
+ layout->addWidget(animationCheckBox, row++, 1, Qt::AlignLeft);
+
+ QCheckBox *legendCheckBox = new QCheckBox(QStringLiteral("Legend"));
+ connect(legendCheckBox, SIGNAL(toggled(bool)), this, SLOT(legendToggled(bool)));
+ legendCheckBox->setChecked(true);
+ layout->addWidget(legendCheckBox, row++, 1, Qt::AlignLeft);
+
+ QCheckBox *titleCheckBox = new QCheckBox(QStringLiteral("Title"));
+ connect(titleCheckBox, SIGNAL(toggled(bool)), this, SLOT(titleToggled(bool)));
+ titleCheckBox->setChecked(true);
+ layout->addWidget(titleCheckBox, row++, 1, Qt::AlignLeft);
+
+ layout->addWidget(new QLabel(QStringLiteral("Chart theme:")), row, 0, Qt::AlignLeft);
+ QComboBox *chartThemeComboBox = new QComboBox();
+ chartThemeComboBox->addItem(QStringLiteral("Light"));
+ chartThemeComboBox->addItem(QStringLiteral("Blue Cerulean"));
+ chartThemeComboBox->addItem(QStringLiteral("Dark"));
+ chartThemeComboBox->addItem(QStringLiteral("Brown Sand"));
+ chartThemeComboBox->addItem(QStringLiteral("Blue Ncs"));
+ chartThemeComboBox->addItem(QStringLiteral("High Contrast"));
+ chartThemeComboBox->addItem(QStringLiteral("Blue Icy"));
+ chartThemeComboBox->addItem(QStringLiteral("Qt"));
+ connect(chartThemeComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(changeChartTheme(int)));
+ layout->addWidget(chartThemeComboBox, row++, 1, Qt::AlignLeft);
+
+ layout->addWidget(new QLabel(QStringLiteral("Axis X:")), row, 0, Qt::AlignLeft);
+ QComboBox *axisXComboBox = new QComboBox();
+ axisXComboBox->addItem(QStringLiteral("BarCategory"));
+ axisXComboBox->addItem(QStringLiteral("DateTime"));
+ axisXComboBox->addItem(QStringLiteral("Value"));
+ connect(axisXComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAxisX(int)));
+ layout->addWidget(axisXComboBox, row++, 1, Qt::AlignLeft);
+
+ return layout;
+}
+
+QGridLayout *MainWidget::createModelMapperControlsLayout()
+{
+ QGridLayout *layout = new QGridLayout();
+ int row = 0;
+
+ layout->addWidget(new QLabel(QStringLiteral("First series:")), row, 0, Qt::AlignLeft);
+
+ QPushButton *attachModelMapperButton = new QPushButton(QStringLiteral("Attach model mapper"));
+ connect(attachModelMapperButton, SIGNAL(clicked(bool)), this, SLOT(attachModelMapper()));
+ layout->addWidget(attachModelMapperButton, row++, 1, Qt::AlignLeft);
+
+ QPushButton *detachModelMappeButton = new QPushButton(QStringLiteral("Detach model mapper"));
+ connect(detachModelMappeButton, SIGNAL(clicked(bool)), this, SLOT(detachModelMapper()));
+ layout->addWidget(detachModelMappeButton, row++, 1, Qt::AlignLeft);
+
+ QTableView *tableView = new QTableView();
+ tableView->setMinimumSize(320, 480);
+ tableView->setMaximumSize(320, 480);
+ tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+ tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+ Q_ASSERT_X(m_hModelMapper->model(), Q_FUNC_INFO, "Model is not initialized");
+ tableView->setModel(m_hModelMapper->model());
+ layout->addWidget(tableView, row++, 0, 1, 2, Qt::AlignLeft);
+
+ layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding), row++, 0);
+
+ return layout;
+}
+
+qreal MainWidget::randomValue(int min, int max) const
+{
+ return (qrand() / (qreal(RAND_MAX) + 1)) * ((qMax(min, max) - qMin(min, max)) + qMin(min, max));
+}
+
+QCandlestickSet *MainWidget::randomSet(qreal timestamp)
+{
+ QCandlestickSet *set = new QCandlestickSet(timestamp);
+ set->setOpen(randomValue(4, 11));
+ set->setHigh(randomValue(12, 15));
+ set->setLow(randomValue(0, 3));
+ set->setClose(randomValue(4, 11));
+
+ return set;
+}
+
+void MainWidget::updateAxes()
+{
+ if (m_chart->axes().isEmpty())
+ m_chart->createDefaultAxes();
+
+ QCandlestickSeries *series;
+ if (!m_chart->series().isEmpty())
+ series = qobject_cast<QCandlestickSeries *>(m_chart->series().at(0));
+ else
+ series = nullptr;
+
+ m_axisX = m_chart->axes(Qt::Horizontal).first();
+ if (series && !series->candlestickSets().isEmpty()) {
+ if (m_axisX->type() == QAbstractAxis::AxisTypeBarCategory) {
+ QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis *>(m_axisX);
+ QStringList categories;
+ for (int i = 0; i < series->candlestickSets().count(); ++i)
+ categories.append(QString::number(i));
+ axisX->setCategories(categories);
+ } else { // QAbstractAxis::AxisTypeDateTime || QAbstractAxis::AxisTypeValue
+ qreal msInMonth = 31.0 * 24.0 * 60.0 * 60.0 * 1000.0;
+ qreal min = series->candlestickSets().first()->timestamp() - msInMonth;
+ qreal max = series->candlestickSets().last()->timestamp() + msInMonth;
+ QDateTime minDateTime = QDateTime::fromMSecsSinceEpoch(min);
+ QDateTime maxDateTime = QDateTime::fromMSecsSinceEpoch(max);
+
+ if (m_axisX->type() == QAbstractAxis::AxisTypeDateTime)
+ m_axisX->setRange(minDateTime, maxDateTime);
+ else
+ m_axisX->setRange(min, max);
+ }
+ }
+
+ m_axisY = m_chart->axes(Qt::Vertical).first();
+ m_axisY->setMax(15);
+ m_axisY->setMin(0);
+}
+
+void MainWidget::addSeries()
+{
+ if (m_chart->series().count() > 9) {
+ qDebug() << "Maximum series count is 10";
+ return;
+ }
+
+ QCandlestickSeries *series = new QCandlestickSeries();
+ series->setName(QStringLiteral("S%1").arg(m_chart->series().count() + 1));
+ series->setMaximumColumnWidth(m_maximumColumnWidth);
+ series->setMinimumColumnWidth(m_minimumColumnWidth);
+ series->setBodyOutlineVisible(m_bodyOutlineVisible);
+ series->setBodyWidth(m_bodyWidth);
+ series->setCapsVisible(m_capsVisible);
+ series->setCapsWidth(m_capsWidth);
+
+ if (m_chart->series().isEmpty()) {
+ if (m_customIncreasingColor)
+ series->setIncreasingColor(QColor(Qt::green));
+ if (m_customDecreasingColor)
+ series->setDecreasingColor(QColor(Qt::red));
+
+ for (int month = 1; month <= 12; ++month) {
+ QDateTime dateTime;
+ dateTime.setDate(QDate(QDateTime::currentDateTime().date().year(), month, 1));
+ dateTime.setTime(QTime(12, 34, 56, 789));
+
+ QCandlestickSet *set = randomSet(dateTime.toMSecsSinceEpoch());
+ series->append(set);
+ }
+ } else {
+ QCandlestickSeries *s = qobject_cast<QCandlestickSeries *>(m_chart->series().at(0));
+ for (int i = 0; i < s->candlestickSets().count(); ++i) {
+ QCandlestickSet *set = randomSet(s->candlestickSets().at(i)->timestamp());
+ series->append(set);
+ }
+ }
+
+ m_chart->addSeries(series);
+
+ updateAxes();
+ if (!series->attachedAxes().contains(m_axisX))
+ series->attachAxis(m_axisX);
+ if (!series->attachedAxes().contains(m_axisY))
+ series->attachAxis(m_axisY);
+}
+
+void MainWidget::removeSeries()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ if (m_chart->series().count() == 1)
+ detachModelMapper();
+
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(m_chart->series().last());
+ m_chart->removeSeries(series);
+ delete series;
+ series = nullptr;
+}
+
+void MainWidget::removeAllSeries()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ detachModelMapper();
+
+ m_chart->removeAllSeries();
+}
+
+void MainWidget::addSet()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+
+ QDateTime dateTime;
+ if (series->count()) {
+ dateTime.setMSecsSinceEpoch(series->candlestickSets().last()->timestamp());
+ dateTime = dateTime.addMonths(1);
+ } else {
+ dateTime.setDate(QDate(QDateTime::currentDateTime().date().year(), 1, 1));
+ dateTime.setTime(QTime(12, 34, 56, 789));
+ }
+
+ QCandlestickSet *set = randomSet(dateTime.toMSecsSinceEpoch());
+ series->append(set);
+ }
+
+ updateAxes();
+}
+
+void MainWidget::insertSet()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+
+ QDateTime dateTime;
+ if (series->count()) {
+ dateTime.setMSecsSinceEpoch(series->candlestickSets().first()->timestamp());
+ dateTime = dateTime.addMonths(-1);
+ } else {
+ dateTime.setDate(QDate(QDateTime::currentDateTime().date().year(), 1, 1));
+ dateTime.setTime(QTime(12, 34, 56, 789));
+ }
+
+ QCandlestickSet *set = randomSet(dateTime.toMSecsSinceEpoch());
+ series->insert(0, set);
+ }
+
+ updateAxes();
+}
+
+void MainWidget::removeSet()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ if (series->candlestickSets().isEmpty())
+ qDebug() << "Create a set first";
+ else
+ series->remove(series->candlestickSets().last());
+ }
+
+ updateAxes();
+}
+
+void MainWidget::removeAllSets()
+{
+ if (m_chart->series().isEmpty()) {
+ qDebug() << "Create a series first";
+ return;
+ }
+
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ if (series->candlestickSets().isEmpty())
+ qDebug() << "Create a set first";
+ else
+ series->clear();
+ }
+
+ updateAxes();
+}
+
+void MainWidget::changeMaximumColumnWidth(double width)
+{
+ m_maximumColumnWidth = width;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setMaximumColumnWidth(m_maximumColumnWidth);
+ }
+}
+
+void MainWidget::changeMinimumColumnWidth(double width)
+{
+ m_minimumColumnWidth = width;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setMinimumColumnWidth(m_minimumColumnWidth);
+ }
+}
+
+void MainWidget::bodyOutlineVisibleToggled(bool visible)
+{
+ m_bodyOutlineVisible = visible;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setBodyOutlineVisible(m_bodyOutlineVisible);
+ }
+}
+
+void MainWidget::capsVisibleToggled(bool visible)
+{
+ m_capsVisible = visible;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setCapsVisible(m_capsVisible);
+ }
+}
+
+void MainWidget::changeBodyWidth(double width)
+{
+ m_bodyWidth = width;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setBodyWidth(m_bodyWidth);
+ }
+}
+
+void MainWidget::changeCapsWidth(double width)
+{
+ m_capsWidth = width;
+ foreach (QAbstractSeries *s, m_chart->series()) {
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(s);
+ series->setCapsWidth(m_capsWidth);
+ }
+}
+
+void MainWidget::customIncreasingColorToggled(bool custom)
+{
+ m_customIncreasingColor = custom;
+
+ if (m_chart->series().isEmpty())
+ return;
+
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(m_chart->series().at(0));
+ if (series) {
+ QColor color = m_customIncreasingColor ? QColor(Qt::green) : QColor();
+ series->setIncreasingColor(color);
+ }
+}
+
+void MainWidget::customDecreasingColorToggled(bool custom)
+{
+ m_customDecreasingColor = custom;
+
+ if (m_chart->series().isEmpty())
+ return;
+
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(m_chart->series().at(0));
+ if (series) {
+ QColor color = m_customDecreasingColor ? QColor(Qt::red) : QColor();
+ series->setDecreasingColor(color);
+ }
+}
+
+void MainWidget::antialiasingToggled(bool enabled)
+{
+ m_chartView->setRenderHint(QPainter::Antialiasing, enabled);
+}
+
+void MainWidget::animationToggled(bool enabled)
+{
+ if (enabled)
+ m_chart->setAnimationOptions(QChart::SeriesAnimations);
+ else
+ m_chart->setAnimationOptions(QChart::NoAnimation);
+}
+
+void MainWidget::legendToggled(bool visible)
+{
+ m_chart->legend()->setVisible(visible);
+ if (visible)
+ m_chart->legend()->setAlignment(Qt::AlignBottom);
+}
+
+void MainWidget::titleToggled(bool visible)
+{
+ if (visible)
+ m_chart->setTitle(QStringLiteral("Candlestick Chart"));
+ else
+ m_chart->setTitle(QString());
+}
+
+void MainWidget::changeChartTheme(int themeIndex)
+{
+ if (themeIndex < QChart::ChartThemeLight || themeIndex > QChart::ChartThemeQt) {
+ qDebug() << "Invalid chart theme index:" << themeIndex;
+ return;
+ }
+
+ m_chart->setTheme((QChart::ChartTheme)(themeIndex));
+}
+
+void MainWidget::changeAxisX(int axisXIndex)
+{
+ if (m_axisX) {
+ m_chart->removeAxis(m_axisX);
+ delete m_axisX;
+ }
+
+ switch (axisXIndex) {
+ case 0:
+ m_axisX = new QBarCategoryAxis();
+ break;
+ case 1:
+ m_axisX = new QDateTimeAxis();
+ break;
+ case 2:
+ m_axisX = new QValueAxis();
+ break;
+ default:
+ qDebug() << "Invalid axis x index:" << axisXIndex;
+ return;
+ }
+
+ m_chart->addAxis(m_axisX, Qt::AlignBottom);
+
+ updateAxes();
+
+ foreach (QAbstractSeries *series, m_chart->series())
+ series->attachAxis(m_axisX);
+}
+
+void MainWidget::attachModelMapper()
+{
+ if (m_hModelMapper->series()) {
+ qDebug() << "Model mapper is already attached";
+ return;
+ }
+
+ if (m_chart->series().isEmpty())
+ addSeries();
+
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(m_chart->series().at(0));
+ Q_ASSERT(series);
+ series->setName(QStringLiteral("SWMM")); // Series With Model Mapper
+
+ CustomTableModel *model = qobject_cast<CustomTableModel *>(m_hModelMapper->model());
+ foreach (QCandlestickSet *set, series->candlestickSets())
+ model->addRow(set);
+
+ m_hModelMapper->setFirstCandlestickSetRow(0);
+ m_hModelMapper->setLastCandlestickSetRow(model->rowCount() - 1);
+ m_hModelMapper->setSeries(series);
+}
+
+void MainWidget::detachModelMapper()
+{
+ if (!m_hModelMapper->series())
+ return;
+
+ QCandlestickSeries *series = qobject_cast<QCandlestickSeries *>(m_hModelMapper->series());
+ Q_ASSERT(series);
+ series->setName(QStringLiteral("S1"));
+
+ m_hModelMapper->setSeries(nullptr);
+ m_hModelMapper->setFirstCandlestickSetRow(-1);
+ m_hModelMapper->setLastCandlestickSetRow(-1);
+
+ CustomTableModel *model = qobject_cast<CustomTableModel *>(m_hModelMapper->model());
+ model->clearRows();
+}
diff --git a/tests/manual/candlesticktester/mainwidget.h b/tests/manual/candlesticktester/mainwidget.h
new file mode 100644
index 00000000..4044515a
--- /dev/null
+++ b/tests/manual/candlesticktester/mainwidget.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef MAINWIDGET_H
+#define MAINWIDGET_H
+
+#include <QtCharts/QChartView>
+#include <QtWidgets/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QGridLayout;
+QT_END_NAMESPACE
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QCandlestickSet;
+class QHCandlestickModelMapper;
+QT_CHARTS_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+
+class MainWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWidget(QWidget *parent = nullptr);
+ ~MainWidget();
+
+private:
+ QGridLayout *createSeriesControlsLayout();
+ QGridLayout *createSetsControlsLayout();
+ QGridLayout *createCandlestickControlsLayout();
+ QGridLayout *createMiscellaneousControlsLayout();
+ QGridLayout *createModelMapperControlsLayout();
+
+ qreal randomValue(int min, int max) const;
+ QCandlestickSet *randomSet(qreal timestamp);
+
+ void updateAxes();
+
+private slots:
+ void addSeries();
+ void removeSeries();
+ void removeAllSeries();
+ void addSet();
+ void insertSet();
+ void removeSet();
+ void removeAllSets();
+ void changeMaximumColumnWidth(double width);
+ void changeMinimumColumnWidth(double width);
+ void bodyOutlineVisibleToggled(bool visible);
+ void capsVisibleToggled(bool visible);
+ void changeBodyWidth(double width);
+ void changeCapsWidth(double width);
+ void customIncreasingColorToggled(bool custom);
+ void customDecreasingColorToggled(bool custom);
+ void antialiasingToggled(bool enabled);
+ void animationToggled(bool enabled);
+ void legendToggled(bool visible);
+ void titleToggled(bool visible);
+ void changeChartTheme(int themeIndex);
+ void changeAxisX(int axisXIndex);
+ void attachModelMapper();
+ void detachModelMapper();
+
+private:
+ QChart *m_chart;
+ QChartView *m_chartView;
+ QAbstractAxis *m_axisX;
+ QAbstractAxis *m_axisY;
+ qreal m_maximumColumnWidth;
+ qreal m_minimumColumnWidth;
+ bool m_bodyOutlineVisible;
+ bool m_capsVisible;
+ qreal m_bodyWidth;
+ qreal m_capsWidth;
+ bool m_customIncreasingColor;
+ bool m_customDecreasingColor;
+ QHCandlestickModelMapper *m_hModelMapper;
+};
+
+#endif // MAINWIDGET_H
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 25545aeb..0e02e8c2 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -2,7 +2,8 @@ TEMPLATE = subdirs
SUBDIRS += \
presenterchart \
polarcharttest \
- boxplottester
+ boxplottester \
+ candlesticktester
contains(QT_CONFIG, opengl) {
SUBDIRS += chartwidgettest \