##// END OF EJS Templates
Added candlestick chart type...
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>

File last commit:

r2896:facc2941efbf
r2896:facc2941efbf
Show More
mainwidget.cpp
691 lines | 24.3 KiB | text/x-c | CppLexer
/****************************************************************************
**
** 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();
}