/**************************************************************************** ** ** 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 #include #include #include #include "tst_definitions.h" QT_CHARTS_USE_NAMESPACE Q_DECLARE_METATYPE(QCandlestickSet *) Q_DECLARE_METATYPE(QList) 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 sets(); 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: QPointer m_series; struct SetList : QList> { operator QList () const { QList list; for (int i = 0; i < count(); ++i) list.append(at(i)); return list; } }; SetList m_sets; }; void tst_QCandlestickSeries::initTestCase() { qRegisterMetaType("QCandlestickSet *"); qRegisterMetaType>("QList"); } 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() { delete m_series; qDeleteAll(m_sets); m_sets.clear(); } 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))); QVERIFY(!m_sets.at(i)); } QCOMPARE(m_series->count(), m_sets.count() - removeCount); for (int i = removeCount; i < m_sets.count(); ++i) QCOMPARE(m_series->sets().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)); QVERIFY(!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 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 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))); 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 args = addedSpy.value(i); QCOMPARE(args.count(), 1); QList sets = qvariant_cast>(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))); 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 args = removedSpy.value(i); QCOMPARE(args.count(), 1); QList sets = qvariant_cast>(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::sets() { m_series->append(m_sets); QCOMPARE(m_series->sets(), m_sets); for (int i = 0; i < m_sets.count(); ++i) QCOMPARE(m_series->sets().at(i), m_sets.at(i)); m_series->clear(); QCOMPARE(m_series->sets(), QList()); } void tst_QCandlestickSeries::count() { m_series->append(m_sets); QCOMPARE(m_series->count(), m_sets.count()); QCOMPARE(m_series->count(), m_series->sets().count()); } void tst_QCandlestickSeries::type() { QCOMPARE(m_series->type(), QAbstractSeries::SeriesTypeCandlestick); } void tst_QCandlestickSeries::maximumColumnWidth_data() { QTest::addColumn("maximumColumnWidth"); QTest::addColumn("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("minimumColumnWidth"); QTest::addColumn("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("bodyWidth"); QTest::addColumn("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("capsWidth"); QTest::addColumn("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->sets().at(1); QCandlestickSet *set2 = m_series->sets().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(); QVERIFY(QTest::qWaitForWindowExposed(&view)); // Calculate expected layout for candlesticks QRectF plotArea = view.chart()->plotArea(); qreal candlestickWidth = plotArea.width() / m_series->count(); qreal candlestickHeight = plotArea.height(); QMap 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, {}, layout.value(set1).center().toPoint()); QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); QCOMPARE(seriesSpy.count(), 1); QCOMPARE(setSpy1.count(), 1); QCOMPARE(setSpy2.count(), 0); QList seriesSpyArgs = seriesSpy.takeFirst(); QCOMPARE(seriesSpyArgs.count(), 1); QCOMPARE(qvariant_cast(seriesSpyArgs.at(0)), set1); seriesSpyArgs.clear(); QVERIFY(setSpy1.takeFirst().isEmpty()); // Click set 2 QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, 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(seriesSpyArgs.at(0)), set2); seriesSpyArgs.clear(); QVERIFY(setSpy2.takeFirst().isEmpty()); } void tst_QCandlestickSeries::mouseHovered() { SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); SKIP_IF_FLAKY_MOUSE_MOVE(); QVERIFY(m_series->append(m_sets)); QCOMPARE(m_series->count(), m_sets.count()); QCandlestickSet *set1 = m_series->sets().at(1); QCandlestickSet *set2 = m_series->sets().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(); QVERIFY(QTest::qWaitForWindowExposed(&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 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 seriesSpyArgs = seriesSpy.takeFirst(); QCOMPARE(qvariant_cast(seriesSpyArgs.at(1)), set1); QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool); QCOMPARE(seriesSpyArgs.at(0).toBool(), true); seriesSpyArgs.clear(); QList 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(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(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(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->sets().at(1); QCandlestickSet *set2 = m_series->sets().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(); QVERIFY(QTest::qWaitForWindowExposed(&view)); // Calculate expected layout for candlesticks QRectF plotArea = view.chart()->plotArea(); qreal candlestickWidth = plotArea.width() / m_series->count(); qreal candlestickHeight = plotArea.height(); QMap 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, {}, layout.value(set1).center().toPoint()); QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); QCOMPARE(seriesSpy.count(), 1); QCOMPARE(setSpy1.count(), 1); QCOMPARE(setSpy2.count(), 0); QList seriesSpyArgs = seriesSpy.takeFirst(); QCOMPARE(seriesSpyArgs.count(), 1); QCOMPARE(qvariant_cast(seriesSpyArgs.at(0)), set1); seriesSpyArgs.clear(); QVERIFY(setSpy1.takeFirst().isEmpty()); // Press set 2 QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, 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(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->sets().at(1); QCandlestickSet *set2 = m_series->sets().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(); QVERIFY(QTest::qWaitForWindowExposed(&view)); // Calculate expected layout for candlesticks QRectF plotArea = view.chart()->plotArea(); qreal candlestickWidth = plotArea.width() / m_series->count(); qreal candlestickHeight = plotArea.height(); QMap 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, {}, layout.value(set1).center().toPoint()); QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); QCOMPARE(seriesSpy.count(), 1); QCOMPARE(setSpy1.count(), 1); QCOMPARE(setSpy2.count(), 0); QList seriesSpyArgs = seriesSpy.takeFirst(); QCOMPARE(seriesSpyArgs.count(), 1); QCOMPARE(qvariant_cast(seriesSpyArgs.at(0)), set1); seriesSpyArgs.clear(); QVERIFY(setSpy1.takeFirst().isEmpty()); // Release mouse over set 2 QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, 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(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->sets().at(1); QCandlestickSet *set2 = m_series->sets().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(); QVERIFY(QTest::qWaitForWindowExposed(&view)); // Calculate expected layout for candlesticks QRectF plotArea = view.chart()->plotArea(); qreal candlestickWidth = plotArea.width() / m_series->count(); qreal candlestickHeight = plotArea.height(); QMap 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, {}, layout.value(set1).center().toPoint()); QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); QCOMPARE(seriesSpy.count(), 1); QCOMPARE(setSpy1.count(), 1); QCOMPARE(setSpy2.count(), 0); QList seriesSpyArgs = seriesSpy.takeFirst(); QCOMPARE(seriesSpyArgs.count(), 1); QCOMPARE(qvariant_cast(seriesSpyArgs.at(0)), set1); seriesSpyArgs.clear(); QVERIFY(setSpy1.takeFirst().isEmpty()); } QTEST_MAIN(tst_QCandlestickSeries) #include "tst_qcandlestickseries.moc"