1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Charts module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 or (at your option) any later version |
20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by |
21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QtCharts/QCandlestickSeries> |
31 | #include <QtCharts/QCandlestickSet> |
32 | #include <QtCharts/QChartView> |
33 | #include <QtTest/QtTest> |
34 | #include "tst_definitions.h" |
35 | |
36 | QT_CHARTS_USE_NAMESPACE |
37 | |
38 | Q_DECLARE_METATYPE(QCandlestickSet *) |
39 | Q_DECLARE_METATYPE(QList<QCandlestickSet *>) |
40 | |
41 | class tst_QCandlestickSeries : public QObject |
42 | { |
43 | Q_OBJECT |
44 | |
45 | public Q_SLOTS: |
46 | void initTestCase(); |
47 | void cleanupTestCase(); |
48 | void init(); |
49 | void cleanup(); |
50 | |
51 | private Q_SLOTS: |
52 | void qCandlestickSeries(); |
53 | void append(); |
54 | void remove(); |
55 | void appendList(); |
56 | void removeList(); |
57 | void insert(); |
58 | void take(); |
59 | void clear(); |
60 | void sets(); |
61 | void count(); |
62 | void type(); |
63 | void maximumColumnWidth_data(); |
64 | void maximumColumnWidth(); |
65 | void minimumColumnWidth_data(); |
66 | void minimumColumnWidth(); |
67 | void bodyWidth_data(); |
68 | void bodyWidth(); |
69 | void bodyOutlineVisible(); |
70 | void capsWidth_data(); |
71 | void capsWidth(); |
72 | void capsVisible(); |
73 | void increasingColor(); |
74 | void decreasingColor(); |
75 | void brush(); |
76 | void pen(); |
77 | void mouseClicked(); |
78 | void mouseHovered(); |
79 | void mousePressed(); |
80 | void mouseReleased(); |
81 | void mouseDoubleClicked(); |
82 | |
83 | private: |
84 | QPointer<QCandlestickSeries> m_series; |
85 | struct SetList : QList<QPointer<QCandlestickSet>> { |
86 | operator QList<QCandlestickSet *> () const { |
87 | QList<QCandlestickSet *> list; |
88 | for (int i = 0; i < count(); ++i) |
89 | list.append(t: at(i)); |
90 | return list; |
91 | } |
92 | }; SetList m_sets; |
93 | }; |
94 | |
95 | void tst_QCandlestickSeries::initTestCase() |
96 | { |
97 | qRegisterMetaType<QCandlestickSet *>(typeName: "QCandlestickSet *" ); |
98 | qRegisterMetaType<QList<QCandlestickSet *>>(typeName: "QList<QCandlestickSet *>" ); |
99 | } |
100 | |
101 | void tst_QCandlestickSeries::cleanupTestCase() |
102 | { |
103 | QTest::qWait(ms: 1); // Allow final deleteLaters to run |
104 | } |
105 | |
106 | void tst_QCandlestickSeries::init() |
107 | { |
108 | m_series = new QCandlestickSeries(); |
109 | m_series->setMaximumColumnWidth(5432.1); |
110 | m_series->setMinimumColumnWidth(2.0); |
111 | m_series->setBodyWidth(0.99); |
112 | m_series->setCapsWidth(0.99); |
113 | |
114 | for (int i = 0; i < 5; ++i) { |
115 | qreal timestamp = QDateTime::currentMSecsSinceEpoch() + i * 1000000; |
116 | |
117 | QCandlestickSet *set = new QCandlestickSet(timestamp); |
118 | set->setOpen(4); |
119 | set->setHigh(4); |
120 | set->setLow(1); |
121 | set->setClose(1); |
122 | |
123 | m_sets.append(t: set); |
124 | } |
125 | } |
126 | |
127 | void tst_QCandlestickSeries::cleanup() |
128 | { |
129 | delete m_series; |
130 | qDeleteAll(c: m_sets); |
131 | m_sets.clear(); |
132 | } |
133 | |
134 | void tst_QCandlestickSeries::qCandlestickSeries() |
135 | { |
136 | QCandlestickSeries *series = new QCandlestickSeries(); |
137 | |
138 | QVERIFY(series != nullptr); |
139 | |
140 | delete series; |
141 | series = nullptr; |
142 | } |
143 | |
144 | void tst_QCandlestickSeries::append() |
145 | { |
146 | QCOMPARE(m_series->count(), 0); |
147 | |
148 | // Try adding set |
149 | QCandlestickSet *set1 = new QCandlestickSet(1234.0); |
150 | QVERIFY(m_series->append(set1)); |
151 | QCOMPARE(m_series->count(), 1); |
152 | |
153 | // Try adding another set |
154 | QCandlestickSet *set2 = new QCandlestickSet(2345.0); |
155 | QVERIFY(m_series->append(set2)); |
156 | QCOMPARE(m_series->count(), 2); |
157 | |
158 | // Try adding same set again |
159 | QVERIFY(!m_series->append(set2)); |
160 | QCOMPARE(m_series->count(), 2); |
161 | |
162 | // Try adding null set |
163 | QVERIFY(!m_series->append(nullptr)); |
164 | QCOMPARE(m_series->count(), 2); |
165 | } |
166 | |
167 | void tst_QCandlestickSeries::remove() |
168 | { |
169 | m_series->append(sets: m_sets); |
170 | QCOMPARE(m_series->count(), m_sets.count()); |
171 | |
172 | // Try to remove null pointer (should not remove, should not crash) |
173 | QVERIFY(!m_series->remove(nullptr)); |
174 | QCOMPARE(m_series->count(), m_sets.count()); |
175 | |
176 | // Try to remove invalid pointer (should not remove, should not crash) |
177 | QVERIFY(!m_series->remove((QCandlestickSet *)(m_sets.at(0) + 1))); |
178 | QCOMPARE(m_series->count(), m_sets.count()); |
179 | |
180 | // Remove some sets |
181 | const int removeCount = 3; |
182 | for (int i = 0; i < removeCount; ++i) { |
183 | QVERIFY(m_series->remove(m_sets.at(i))); |
184 | QVERIFY(!m_sets.at(i)); |
185 | } |
186 | QCOMPARE(m_series->count(), m_sets.count() - removeCount); |
187 | |
188 | for (int i = removeCount; i < m_sets.count(); ++i) |
189 | QCOMPARE(m_series->sets().at(i - removeCount), m_sets.at(i)); |
190 | |
191 | // Try removing all sets again (should be ok, even if some sets have already been removed) |
192 | for (int i = 0; i < m_sets.count(); ++i) { |
193 | m_series->remove(set: m_sets.at(i)); |
194 | QVERIFY(!m_sets.at(i)); |
195 | } |
196 | QCOMPARE(m_series->count(), 0); |
197 | } |
198 | |
199 | void tst_QCandlestickSeries::appendList() |
200 | { |
201 | QCOMPARE(m_series->count(), 0); |
202 | |
203 | // Append new sets (should succeed, count should match the count of sets) |
204 | QVERIFY(m_series->append(m_sets)); |
205 | QCOMPARE(m_series->count(), m_series->count()); |
206 | |
207 | // Append same sets again (should fail, count should remain same) |
208 | QVERIFY(!m_series->append(m_sets)); |
209 | QCOMPARE(m_series->count(), m_series->count()); |
210 | |
211 | // Try append empty list (should succeed, but count should remain same) |
212 | QList<QCandlestickSet *> invalidList; |
213 | QVERIFY(m_series->append(invalidList)); |
214 | QCOMPARE(m_series->count(), m_sets.count()); |
215 | |
216 | // Try append list with one new and one existing set (should fail, count remains same) |
217 | invalidList.append(t: new QCandlestickSet()); |
218 | invalidList.append(t: m_sets.at(i: 0)); |
219 | QVERIFY(!m_series->append(invalidList)); |
220 | QCOMPARE(m_series->count(), m_sets.count()); |
221 | delete invalidList.at(i: 0); |
222 | invalidList.clear(); |
223 | |
224 | // Try append list with null pointers (should fail, count remains same) |
225 | QVERIFY(invalidList.isEmpty()); |
226 | invalidList.append(t: nullptr); |
227 | invalidList.append(t: nullptr); |
228 | invalidList.append(t: nullptr); |
229 | QVERIFY(!m_series->append(invalidList)); |
230 | QCOMPARE(m_series->count(), m_sets.count()); |
231 | } |
232 | |
233 | void tst_QCandlestickSeries::removeList() |
234 | { |
235 | m_series->append(sets: m_sets); |
236 | QCOMPARE(m_series->count(), m_sets.count()); |
237 | |
238 | // Try remove empty list (should fail, but count should remain same) |
239 | QList<QCandlestickSet *> invalidList; |
240 | QVERIFY(!m_series->remove(invalidList)); |
241 | QCOMPARE(m_series->count(), m_sets.count()); |
242 | |
243 | // Try remove list with one new and one existing set (should fail, count remains same) |
244 | invalidList.append(t: new QCandlestickSet()); |
245 | invalidList.append(t: m_sets.at(i: 0)); |
246 | QVERIFY(!m_series->remove(invalidList)); |
247 | QCOMPARE(m_series->count(), m_sets.count()); |
248 | delete invalidList.at(i: 0); |
249 | invalidList.clear(); |
250 | |
251 | // Try remove list with null pointers (should fail, count remains same) |
252 | QVERIFY(invalidList.isEmpty()); |
253 | invalidList.append(t: nullptr); |
254 | invalidList.append(t: nullptr); |
255 | invalidList.append(t: nullptr); |
256 | QVERIFY(!m_series->remove(invalidList)); |
257 | QCOMPARE(m_series->count(), m_sets.count()); |
258 | |
259 | // Remove all sets (should succeed, count should be zero) |
260 | QVERIFY(m_series->remove(m_sets)); |
261 | QCOMPARE(m_series->count(), 0); |
262 | |
263 | // Remove same sets again (should fail, count should remain zero) |
264 | QVERIFY(!m_series->remove(m_sets)); |
265 | QCOMPARE(m_series->count(), 0); |
266 | } |
267 | |
268 | void tst_QCandlestickSeries::insert() |
269 | { |
270 | QCOMPARE(m_series->count(), 0); |
271 | |
272 | QSignalSpy countSpy(m_series, SIGNAL(countChanged())); |
273 | QSignalSpy addedSpy(m_series, SIGNAL(candlestickSetsAdded(QList<QCandlestickSet *>))); |
274 | |
275 | for (int i = 0; i < m_sets.count(); ++i) { |
276 | QCandlestickSet *set = m_sets.at(i); |
277 | QVERIFY(m_series->insert(0, set)); |
278 | QCOMPARE(m_series->count(), i + 1); |
279 | QTRY_COMPARE(countSpy.count(), i + 1); |
280 | QTRY_COMPARE(addedSpy.count(), i + 1); |
281 | |
282 | QList<QVariant> args = addedSpy.value(i); |
283 | QCOMPARE(args.count(), 1); |
284 | QList<QCandlestickSet *> sets = qvariant_cast<QList<QCandlestickSet *>>(v: args.at(i: 0)); |
285 | QCOMPARE(sets.count(), 1); |
286 | QCOMPARE(sets.first(), set); |
287 | } |
288 | } |
289 | |
290 | void tst_QCandlestickSeries::take() |
291 | { |
292 | m_series->append(sets: m_sets); |
293 | QCOMPARE(m_series->count(), m_sets.count()); |
294 | |
295 | QSignalSpy countSpy(m_series, SIGNAL(countChanged())); |
296 | QSignalSpy removedSpy(m_series, SIGNAL(candlestickSetsRemoved(QList<QCandlestickSet *>))); |
297 | |
298 | for (int i = 0; i < m_sets.count(); ++i) { |
299 | QCandlestickSet *set = m_sets.at(i); |
300 | QVERIFY(m_series->take(set)); |
301 | QCOMPARE(m_series->count(), m_sets.count() - i - 1); |
302 | QTRY_COMPARE(countSpy.count(), i + 1); |
303 | QTRY_COMPARE(removedSpy.count(), i + 1); |
304 | |
305 | QList<QVariant> args = removedSpy.value(i); |
306 | QCOMPARE(args.count(), 1); |
307 | QList<QCandlestickSet *> sets = qvariant_cast<QList<QCandlestickSet *>>(v: args.at(i: 0)); |
308 | QCOMPARE(sets.count(), 1); |
309 | QCOMPARE(sets.first(), set); |
310 | } |
311 | } |
312 | |
313 | void tst_QCandlestickSeries::clear() |
314 | { |
315 | m_series->append(sets: m_sets); |
316 | QCOMPARE(m_series->count(), m_sets.count()); |
317 | |
318 | m_series->clear(); |
319 | QCOMPARE(m_series->count(), 0); |
320 | } |
321 | |
322 | void tst_QCandlestickSeries::sets() |
323 | { |
324 | m_series->append(sets: m_sets); |
325 | QCOMPARE(m_series->sets(), m_sets); |
326 | |
327 | for (int i = 0; i < m_sets.count(); ++i) |
328 | QCOMPARE(m_series->sets().at(i), m_sets.at(i)); |
329 | |
330 | m_series->clear(); |
331 | QCOMPARE(m_series->sets(), QList<QCandlestickSet *>()); |
332 | } |
333 | |
334 | void tst_QCandlestickSeries::count() |
335 | { |
336 | m_series->append(sets: m_sets); |
337 | QCOMPARE(m_series->count(), m_sets.count()); |
338 | QCOMPARE(m_series->count(), m_series->sets().count()); |
339 | } |
340 | |
341 | void tst_QCandlestickSeries::type() |
342 | { |
343 | QCOMPARE(m_series->type(), QAbstractSeries::SeriesTypeCandlestick); |
344 | } |
345 | |
346 | void tst_QCandlestickSeries::maximumColumnWidth_data() |
347 | { |
348 | QTest::addColumn<qreal>(name: "maximumColumnWidth" ); |
349 | QTest::addColumn<qreal>(name: "expectedMaximumColumnWidth" ); |
350 | |
351 | QTest::newRow(dataTag: "maximum column width less than -1.0" ) << -3.0 << -1.0; |
352 | QTest::newRow(dataTag: "maximum column equals to -1.0" ) << -1.0 << -1.0; |
353 | QTest::newRow(dataTag: "maximum column width greater than -1.0, but less than zero" ) << -0.5 << -1.0; |
354 | QTest::newRow(dataTag: "maximum column width equals zero" ) << 0.0 << 0.0; |
355 | QTest::newRow(dataTag: "maximum column width greater than zero" ) << 1.0 << 1.0; |
356 | QTest::newRow(dataTag: "maximum column width contains a fractional part" ) << 3.4 << 3.4; |
357 | } |
358 | |
359 | void tst_QCandlestickSeries::maximumColumnWidth() |
360 | { |
361 | QFETCH(qreal, maximumColumnWidth); |
362 | QFETCH(qreal, expectedMaximumColumnWidth); |
363 | |
364 | QSignalSpy spy(m_series, SIGNAL(maximumColumnWidthChanged())); |
365 | |
366 | m_series->setMaximumColumnWidth(maximumColumnWidth); |
367 | QCOMPARE(m_series->maximumColumnWidth(), expectedMaximumColumnWidth); |
368 | QCOMPARE(spy.count(), 1); |
369 | |
370 | // Try set same maximum column width |
371 | m_series->setMaximumColumnWidth(expectedMaximumColumnWidth); |
372 | QCOMPARE(m_series->maximumColumnWidth(), expectedMaximumColumnWidth); |
373 | QCOMPARE(spy.count(), 1); |
374 | } |
375 | |
376 | void tst_QCandlestickSeries::minimumColumnWidth_data() |
377 | { |
378 | QTest::addColumn<qreal>(name: "minimumColumnWidth" ); |
379 | QTest::addColumn<qreal>(name: "expectedMinimumColumnWidth" ); |
380 | |
381 | QTest::newRow(dataTag: "minimum column width less than -1.0" ) << -3.0 << -1.0; |
382 | QTest::newRow(dataTag: "minimum column equals to -1.0" ) << -1.0 << -1.0; |
383 | QTest::newRow(dataTag: "minimum column width greater than -1.0, but less than zero" ) << -0.5 << -1.0; |
384 | QTest::newRow(dataTag: "minimum column width equals zero" ) << 0.0 << 0.0; |
385 | QTest::newRow(dataTag: "minimum column width greater than zero" ) << 1.0 << 1.0; |
386 | QTest::newRow(dataTag: "minimum column width contains a fractional part" ) << 3.4 << 3.4; |
387 | } |
388 | |
389 | void tst_QCandlestickSeries::minimumColumnWidth() |
390 | { |
391 | QFETCH(qreal, minimumColumnWidth); |
392 | QFETCH(qreal, expectedMinimumColumnWidth); |
393 | |
394 | QSignalSpy spy(m_series, SIGNAL(minimumColumnWidthChanged())); |
395 | |
396 | m_series->setMinimumColumnWidth(minimumColumnWidth); |
397 | QCOMPARE(m_series->minimumColumnWidth(), expectedMinimumColumnWidth); |
398 | QCOMPARE(spy.count(), 1); |
399 | |
400 | // Try set same minimum column width |
401 | m_series->setMinimumColumnWidth(expectedMinimumColumnWidth); |
402 | QCOMPARE(m_series->minimumColumnWidth(), expectedMinimumColumnWidth); |
403 | QCOMPARE(spy.count(), 1); |
404 | } |
405 | |
406 | void tst_QCandlestickSeries::bodyWidth_data() |
407 | { |
408 | QTest::addColumn<qreal>(name: "bodyWidth" ); |
409 | QTest::addColumn<qreal>(name: "expectedBodyWidth" ); |
410 | |
411 | QTest::newRow(dataTag: "body width less than zero" ) << -1.0 << 0.0; |
412 | QTest::newRow(dataTag: "body width equals zero" ) << 0.0 << 0.0; |
413 | QTest::newRow(dataTag: "body width greater than zero and less than one" ) << 0.5 << 0.5; |
414 | QTest::newRow(dataTag: "body width equals one" ) << 1.0 << 1.0; |
415 | QTest::newRow(dataTag: "body width greater than one" ) << 2.0 << 1.0; |
416 | } |
417 | |
418 | void tst_QCandlestickSeries::bodyWidth() |
419 | { |
420 | QFETCH(qreal, bodyWidth); |
421 | QFETCH(qreal, expectedBodyWidth); |
422 | |
423 | QSignalSpy spy(m_series, SIGNAL(bodyWidthChanged())); |
424 | |
425 | m_series->setBodyWidth(bodyWidth); |
426 | QCOMPARE(m_series->bodyWidth(), expectedBodyWidth); |
427 | QCOMPARE(spy.count(), 1); |
428 | |
429 | // Try set same body width |
430 | m_series->setBodyWidth(bodyWidth); |
431 | QCOMPARE(m_series->bodyWidth(), expectedBodyWidth); |
432 | QCOMPARE(spy.count(), 1); |
433 | } |
434 | |
435 | void tst_QCandlestickSeries::bodyOutlineVisible() |
436 | { |
437 | QSignalSpy spy(m_series, SIGNAL(bodyOutlineVisibilityChanged())); |
438 | |
439 | bool visible = !m_series->bodyOutlineVisible(); |
440 | m_series->setBodyOutlineVisible(visible); |
441 | QCOMPARE(m_series->bodyOutlineVisible(), visible); |
442 | QCOMPARE(spy.count(), 1); |
443 | |
444 | // Try set same body outline visibility |
445 | m_series->setBodyOutlineVisible(visible); |
446 | QCOMPARE(m_series->bodyOutlineVisible(), visible); |
447 | QCOMPARE(spy.count(), 1); |
448 | } |
449 | |
450 | void tst_QCandlestickSeries::capsWidth_data() |
451 | { |
452 | QTest::addColumn<qreal>(name: "capsWidth" ); |
453 | QTest::addColumn<qreal>(name: "expectedCapsWidth" ); |
454 | |
455 | QTest::newRow(dataTag: "caps width less than zero" ) << -1.0 << 0.0; |
456 | QTest::newRow(dataTag: "caps width equals zero" ) << 0.0 << 0.0; |
457 | QTest::newRow(dataTag: "caps width greater than zero and less than one" ) << 0.5 << 0.5; |
458 | QTest::newRow(dataTag: "caps width equals one" ) << 1.0 << 1.0; |
459 | QTest::newRow(dataTag: "caps width greater than one" ) << 2.0 << 1.0; |
460 | } |
461 | |
462 | void tst_QCandlestickSeries::capsWidth() |
463 | { |
464 | QFETCH(qreal, capsWidth); |
465 | QFETCH(qreal, expectedCapsWidth); |
466 | |
467 | QSignalSpy spy(m_series, SIGNAL(capsWidthChanged())); |
468 | |
469 | m_series->setCapsWidth(capsWidth); |
470 | QCOMPARE(m_series->capsWidth(), expectedCapsWidth); |
471 | QCOMPARE(spy.count(), 1); |
472 | |
473 | // Try set same caps width |
474 | m_series->setCapsWidth(capsWidth); |
475 | QCOMPARE(m_series->capsWidth(), expectedCapsWidth); |
476 | QCOMPARE(spy.count(), 1); |
477 | } |
478 | |
479 | void tst_QCandlestickSeries::capsVisible() |
480 | { |
481 | QSignalSpy spy(m_series, SIGNAL(capsVisibilityChanged())); |
482 | |
483 | bool visible = !m_series->capsVisible(); |
484 | m_series->setCapsVisible(visible); |
485 | QCOMPARE(m_series->capsVisible(), visible); |
486 | QCOMPARE(spy.count(), 1); |
487 | |
488 | // Try set same caps visibility |
489 | m_series->setCapsVisible(visible); |
490 | QCOMPARE(m_series->capsVisible(), visible); |
491 | QCOMPARE(spy.count(), 1); |
492 | } |
493 | |
494 | void tst_QCandlestickSeries::increasingColor() |
495 | { |
496 | QSignalSpy spy(m_series, SIGNAL(increasingColorChanged())); |
497 | |
498 | // Try set new increasing color |
499 | QColor newColor(200, 200, 200, 200); |
500 | m_series->setIncreasingColor(newColor); |
501 | QCOMPARE(m_series->increasingColor(), newColor); |
502 | QCOMPARE(spy.count(), 1); |
503 | |
504 | // Try set same increasing color again |
505 | m_series->setIncreasingColor(newColor); |
506 | QCOMPARE(m_series->increasingColor(), newColor); |
507 | QCOMPARE(spy.count(), 1); |
508 | |
509 | // Try set invalid increasing color (should change to default color) |
510 | QColor defaultColor = m_series->brush().color(); |
511 | defaultColor.setAlpha(128); |
512 | m_series->setIncreasingColor(QColor()); |
513 | QCOMPARE(m_series->increasingColor(), defaultColor); |
514 | QCOMPARE(spy.count(), 2); |
515 | |
516 | // Set new brush, increasing color should change accordingly |
517 | QBrush brush(newColor); |
518 | defaultColor = brush.color(); |
519 | defaultColor.setAlpha(128); |
520 | m_series->setBrush(brush); |
521 | QCOMPARE(m_series->increasingColor(), defaultColor); |
522 | QCOMPARE(spy.count(), 3); |
523 | } |
524 | |
525 | void tst_QCandlestickSeries::decreasingColor() |
526 | { |
527 | QSignalSpy spy(m_series, SIGNAL(decreasingColorChanged())); |
528 | |
529 | // Try set new decreasing color |
530 | QColor newColor(200, 200, 200, 200); |
531 | m_series->setDecreasingColor(newColor); |
532 | QCOMPARE(m_series->decreasingColor(), newColor); |
533 | QCOMPARE(spy.count(), 1); |
534 | |
535 | // Try set same decreasing color again |
536 | m_series->setDecreasingColor(newColor); |
537 | QCOMPARE(m_series->decreasingColor(), newColor); |
538 | QCOMPARE(spy.count(), 1); |
539 | |
540 | // Try set invalid decreasing color (should change to default color) |
541 | m_series->setDecreasingColor(QColor()); |
542 | QCOMPARE(m_series->decreasingColor(), m_series->brush().color()); |
543 | QCOMPARE(spy.count(), 2); |
544 | |
545 | // Set new brush, decreasing color should change accordingly |
546 | m_series->setBrush(QBrush(newColor)); |
547 | QCOMPARE(m_series->decreasingColor(), m_series->brush().color()); |
548 | QCOMPARE(spy.count(), 3); |
549 | } |
550 | |
551 | void tst_QCandlestickSeries::brush() |
552 | { |
553 | QSignalSpy spy(m_series, SIGNAL(brushChanged())); |
554 | |
555 | QBrush brush(QColor(128, 128, 128, 128)); |
556 | QColor increasingColor(brush.color()); |
557 | increasingColor.setAlpha(128); |
558 | QColor decreasingColor(brush.color()); |
559 | m_series->setBrush(brush); |
560 | QCOMPARE(m_series->brush(), brush); |
561 | QCOMPARE(m_series->increasingColor(), increasingColor); |
562 | QCOMPARE(m_series->decreasingColor(), decreasingColor); |
563 | QCOMPARE(spy.count(), 1); |
564 | |
565 | // Try set same brush |
566 | m_series->setBrush(brush); |
567 | QCOMPARE(m_series->brush(), brush); |
568 | QCOMPARE(m_series->increasingColor(), increasingColor); |
569 | QCOMPARE(m_series->decreasingColor(), decreasingColor); |
570 | QCOMPARE(spy.count(), 1); |
571 | } |
572 | |
573 | void tst_QCandlestickSeries::pen() |
574 | { |
575 | QSignalSpy spy(m_series, SIGNAL(penChanged())); |
576 | |
577 | QPen pen(QColor(128, 128, 128, 128)); |
578 | m_series->setPen(pen); |
579 | QCOMPARE(m_series->pen(), pen); |
580 | QCOMPARE(spy.count(), 1); |
581 | |
582 | // Try set same pen |
583 | m_series->setPen(pen); |
584 | QCOMPARE(m_series->pen(), pen); |
585 | QCOMPARE(spy.count(), 1); |
586 | } |
587 | |
588 | void tst_QCandlestickSeries::mouseClicked() |
589 | { |
590 | SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); |
591 | |
592 | QVERIFY(m_series->append(m_sets)); |
593 | QCOMPARE(m_series->count(), m_sets.count()); |
594 | |
595 | QCandlestickSet *set1 = m_series->sets().at(i: 1); |
596 | QCandlestickSet *set2 = m_series->sets().at(i: 2); |
597 | |
598 | QSignalSpy seriesSpy(m_series, SIGNAL(clicked(QCandlestickSet *))); |
599 | QSignalSpy setSpy1(set1, SIGNAL(clicked())); |
600 | QSignalSpy setSpy2(set2, SIGNAL(clicked())); |
601 | |
602 | QChartView view(new QChart()); |
603 | view.resize(w: 400, h: 300); |
604 | view.chart()->addSeries(series: m_series); |
605 | view.chart()->createDefaultAxes(); |
606 | view.show(); |
607 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
608 | |
609 | // Calculate expected layout for candlesticks |
610 | QRectF plotArea = view.chart()->plotArea(); |
611 | qreal candlestickWidth = plotArea.width() / m_series->count(); |
612 | qreal candlestickHeight = plotArea.height(); |
613 | |
614 | QMap<QCandlestickSet *, QRectF> layout; |
615 | layout.insert(akey: set1, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set1), |
616 | plotArea.top(), candlestickWidth, candlestickHeight)); |
617 | layout.insert(akey: set2, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set2), |
618 | plotArea.top(), candlestickWidth, candlestickHeight)); |
619 | |
620 | // Click set 1 |
621 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set1).center().toPoint()); |
622 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
623 | |
624 | QCOMPARE(seriesSpy.count(), 1); |
625 | QCOMPARE(setSpy1.count(), 1); |
626 | QCOMPARE(setSpy2.count(), 0); |
627 | |
628 | QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst(); |
629 | QCOMPARE(seriesSpyArgs.count(), 1); |
630 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1); |
631 | seriesSpyArgs.clear(); |
632 | |
633 | QVERIFY(setSpy1.takeFirst().isEmpty()); |
634 | |
635 | // Click set 2 |
636 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set2).center().toPoint()); |
637 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
638 | |
639 | QCOMPARE(seriesSpy.count(), 1); |
640 | QCOMPARE(setSpy1.count(), 0); |
641 | QCOMPARE(setSpy2.count(), 1); |
642 | |
643 | seriesSpyArgs = seriesSpy.takeFirst(); |
644 | QCOMPARE(seriesSpyArgs.count(), 1); |
645 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2); |
646 | seriesSpyArgs.clear(); |
647 | |
648 | QVERIFY(setSpy2.takeFirst().isEmpty()); |
649 | } |
650 | |
651 | void tst_QCandlestickSeries::mouseHovered() |
652 | { |
653 | SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); |
654 | SKIP_IF_FLAKY_MOUSE_MOVE(); |
655 | |
656 | QVERIFY(m_series->append(m_sets)); |
657 | QCOMPARE(m_series->count(), m_sets.count()); |
658 | |
659 | QCandlestickSet *set1 = m_series->sets().at(i: 1); |
660 | QCandlestickSet *set2 = m_series->sets().at(i: 2); |
661 | |
662 | QSignalSpy seriesSpy(m_series, SIGNAL(hovered(bool, QCandlestickSet *))); |
663 | QSignalSpy setSpy1(set1, SIGNAL(hovered(bool))); |
664 | QSignalSpy setSpy2(set2, SIGNAL(hovered(bool))); |
665 | |
666 | QChartView view(new QChart()); |
667 | view.resize(w: 400, h: 300); |
668 | view.chart()->addSeries(series: m_series); |
669 | view.chart()->createDefaultAxes(); |
670 | view.show(); |
671 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
672 | |
673 | // This is hack since view does not get events otherwise |
674 | view.setMouseTracking(true); |
675 | |
676 | // Calculate expected layout for candlesticks |
677 | QRectF plotArea = view.chart()->plotArea(); |
678 | qreal candlestickWidth = plotArea.width() / m_series->count(); |
679 | qreal candlestickHeight = plotArea.height(); |
680 | |
681 | QMap<QCandlestickSet *, QRectF> layout; |
682 | layout.insert(akey: set1, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set1), |
683 | plotArea.top(), candlestickWidth, candlestickHeight)); |
684 | layout.insert(akey: set2, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set2), |
685 | plotArea.top(), candlestickWidth, candlestickHeight)); |
686 | |
687 | // Move mouse to left border |
688 | QTest::mouseMove(widget: view.viewport(), pos: QPoint(0, layout.value(akey: set1).center().y())); |
689 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
690 | |
691 | QCOMPARE(seriesSpy.count(), 0); |
692 | QCOMPARE(setSpy1.count(), 0); |
693 | QCOMPARE(setSpy2.count(), 0); |
694 | |
695 | // Move mouse on top of set 1 |
696 | QTest::mouseMove(widget: view.viewport(), pos: layout.value(akey: set1).center().toPoint()); |
697 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
698 | |
699 | QCOMPARE(seriesSpy.count(), 1); |
700 | QCOMPARE(setSpy1.count(), 1); |
701 | QCOMPARE(setSpy2.count(), 0); |
702 | |
703 | QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst(); |
704 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set1); |
705 | QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool); |
706 | QCOMPARE(seriesSpyArgs.at(0).toBool(), true); |
707 | seriesSpyArgs.clear(); |
708 | |
709 | QList<QVariant> setSpyArgs = setSpy1.takeFirst(); |
710 | QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool); |
711 | QCOMPARE(setSpyArgs.at(0).toBool(), true); |
712 | setSpyArgs.clear(); |
713 | |
714 | // Move mouse from top of set 1 to top of set 2 |
715 | QTest::mouseMove(widget: view.viewport(), pos: layout.value(akey: set2).center().toPoint()); |
716 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
717 | |
718 | QCOMPARE(seriesSpy.count(), 2); |
719 | QCOMPARE(setSpy1.count(), 1); |
720 | QCOMPARE(setSpy2.count(), 1); |
721 | |
722 | // Should leave set 1 |
723 | seriesSpyArgs = seriesSpy.takeFirst(); |
724 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set1); |
725 | QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool); |
726 | QCOMPARE(seriesSpyArgs.at(0).toBool(), false); |
727 | // Don't call seriesSpyArgs.clear() here |
728 | |
729 | setSpyArgs = setSpy1.takeFirst(); |
730 | QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool); |
731 | QCOMPARE(setSpyArgs.at(0).toBool(), false); |
732 | // Don't call setSpyArgs.clear() here |
733 | |
734 | // Should enter set 2 |
735 | seriesSpyArgs = seriesSpy.takeFirst(); |
736 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set2); |
737 | QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool); |
738 | QCOMPARE(seriesSpyArgs.at(0).toBool(), true); |
739 | seriesSpyArgs.clear(); |
740 | |
741 | setSpyArgs = setSpy2.takeFirst(); |
742 | QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool); |
743 | QCOMPARE(setSpyArgs.at(0).toBool(), true); |
744 | setSpyArgs.clear(); |
745 | |
746 | // Move mouse from top of set 2 to background |
747 | QTest::mouseMove(widget: view.viewport(), pos: QPoint(layout.value(akey: set2).center().x(), 0)); |
748 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
749 | |
750 | QCOMPARE(seriesSpy.count(), 1); |
751 | QCOMPARE(setSpy1.count(), 0); |
752 | QCOMPARE(setSpy2.count(), 1); |
753 | |
754 | // Should leave set 2 |
755 | seriesSpyArgs = seriesSpy.takeFirst(); |
756 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(1)), set2); |
757 | QCOMPARE(seriesSpyArgs.at(0).type(), QVariant::Bool); |
758 | QCOMPARE(seriesSpyArgs.at(0).toBool(), false); |
759 | seriesSpyArgs.clear(); |
760 | |
761 | setSpyArgs = setSpy2.takeFirst(); |
762 | QCOMPARE(setSpyArgs.at(0).type(), QVariant::Bool); |
763 | QCOMPARE(setSpyArgs.at(0).toBool(), false); |
764 | setSpyArgs.clear(); |
765 | } |
766 | |
767 | void tst_QCandlestickSeries::mousePressed() |
768 | { |
769 | SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); |
770 | |
771 | QVERIFY(m_series->append(m_sets)); |
772 | QCOMPARE(m_series->count(), m_sets.count()); |
773 | |
774 | QCandlestickSet *set1 = m_series->sets().at(i: 1); |
775 | QCandlestickSet *set2 = m_series->sets().at(i: 2); |
776 | |
777 | QSignalSpy seriesSpy(m_series, SIGNAL(pressed(QCandlestickSet *))); |
778 | QSignalSpy setSpy1(set1, SIGNAL(pressed())); |
779 | QSignalSpy setSpy2(set2, SIGNAL(pressed())); |
780 | |
781 | QChartView view(new QChart()); |
782 | view.resize(w: 400, h: 300); |
783 | view.chart()->addSeries(series: m_series); |
784 | view.chart()->createDefaultAxes(); |
785 | view.show(); |
786 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
787 | |
788 | // Calculate expected layout for candlesticks |
789 | QRectF plotArea = view.chart()->plotArea(); |
790 | qreal candlestickWidth = plotArea.width() / m_series->count(); |
791 | qreal candlestickHeight = plotArea.height(); |
792 | |
793 | QMap<QCandlestickSet *, QRectF> layout; |
794 | layout.insert(akey: set1, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set1), |
795 | plotArea.top(), candlestickWidth, candlestickHeight)); |
796 | layout.insert(akey: set2, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set2), |
797 | plotArea.top(), candlestickWidth, candlestickHeight)); |
798 | |
799 | // Press set 1 |
800 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set1).center().toPoint()); |
801 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
802 | |
803 | QCOMPARE(seriesSpy.count(), 1); |
804 | QCOMPARE(setSpy1.count(), 1); |
805 | QCOMPARE(setSpy2.count(), 0); |
806 | |
807 | QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst(); |
808 | QCOMPARE(seriesSpyArgs.count(), 1); |
809 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1); |
810 | seriesSpyArgs.clear(); |
811 | |
812 | QVERIFY(setSpy1.takeFirst().isEmpty()); |
813 | |
814 | // Press set 2 |
815 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set2).center().toPoint()); |
816 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
817 | |
818 | QCOMPARE(seriesSpy.count(), 1); |
819 | QCOMPARE(setSpy1.count(), 0); |
820 | QCOMPARE(setSpy2.count(), 1); |
821 | |
822 | seriesSpyArgs = seriesSpy.takeFirst(); |
823 | QCOMPARE(seriesSpyArgs.count(), 1); |
824 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2); |
825 | seriesSpyArgs.clear(); |
826 | |
827 | QVERIFY(setSpy2.takeFirst().isEmpty()); |
828 | } |
829 | |
830 | void tst_QCandlestickSeries::mouseReleased() |
831 | { |
832 | SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); |
833 | |
834 | QVERIFY(m_series->append(m_sets)); |
835 | QCOMPARE(m_series->count(), m_sets.count()); |
836 | |
837 | QCandlestickSet *set1 = m_series->sets().at(i: 1); |
838 | QCandlestickSet *set2 = m_series->sets().at(i: 2); |
839 | |
840 | QSignalSpy seriesSpy(m_series, SIGNAL(released(QCandlestickSet *))); |
841 | QSignalSpy setSpy1(set1, SIGNAL(released())); |
842 | QSignalSpy setSpy2(set2, SIGNAL(released())); |
843 | |
844 | QChartView view(new QChart()); |
845 | view.resize(w: 400, h: 300); |
846 | view.chart()->addSeries(series: m_series); |
847 | view.chart()->createDefaultAxes(); |
848 | view.show(); |
849 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
850 | |
851 | // Calculate expected layout for candlesticks |
852 | QRectF plotArea = view.chart()->plotArea(); |
853 | qreal candlestickWidth = plotArea.width() / m_series->count(); |
854 | qreal candlestickHeight = plotArea.height(); |
855 | |
856 | QMap<QCandlestickSet *, QRectF> layout; |
857 | layout.insert(akey: set1, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set1), |
858 | plotArea.top(), candlestickWidth, candlestickHeight)); |
859 | layout.insert(akey: set2, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set2), |
860 | plotArea.top(), candlestickWidth, candlestickHeight)); |
861 | |
862 | // Release mouse over set 1 |
863 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set1).center().toPoint()); |
864 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
865 | |
866 | QCOMPARE(seriesSpy.count(), 1); |
867 | QCOMPARE(setSpy1.count(), 1); |
868 | QCOMPARE(setSpy2.count(), 0); |
869 | |
870 | QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst(); |
871 | QCOMPARE(seriesSpyArgs.count(), 1); |
872 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1); |
873 | seriesSpyArgs.clear(); |
874 | |
875 | QVERIFY(setSpy1.takeFirst().isEmpty()); |
876 | |
877 | // Release mouse over set 2 |
878 | QTest::mouseClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set2).center().toPoint()); |
879 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
880 | |
881 | QCOMPARE(seriesSpy.count(), 1); |
882 | QCOMPARE(setSpy1.count(), 0); |
883 | QCOMPARE(setSpy2.count(), 1); |
884 | |
885 | seriesSpyArgs = seriesSpy.takeFirst(); |
886 | QCOMPARE(seriesSpyArgs.count(), 1); |
887 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set2); |
888 | seriesSpyArgs.clear(); |
889 | |
890 | QVERIFY(setSpy2.takeFirst().isEmpty()); |
891 | } |
892 | |
893 | void tst_QCandlestickSeries::mouseDoubleClicked() |
894 | { |
895 | SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); |
896 | |
897 | QVERIFY(m_series->append(m_sets)); |
898 | QCOMPARE(m_series->count(), m_sets.count()); |
899 | |
900 | QCandlestickSet *set1 = m_series->sets().at(i: 1); |
901 | QCandlestickSet *set2 = m_series->sets().at(i: 2); |
902 | |
903 | QSignalSpy seriesSpy(m_series, SIGNAL(doubleClicked(QCandlestickSet *))); |
904 | QSignalSpy setSpy1(set1, SIGNAL(doubleClicked())); |
905 | QSignalSpy setSpy2(set2, SIGNAL(doubleClicked())); |
906 | |
907 | QChartView view(new QChart()); |
908 | view.resize(w: 400, h: 300); |
909 | view.chart()->addSeries(series: m_series); |
910 | view.chart()->createDefaultAxes(); |
911 | view.show(); |
912 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
913 | |
914 | // Calculate expected layout for candlesticks |
915 | QRectF plotArea = view.chart()->plotArea(); |
916 | qreal candlestickWidth = plotArea.width() / m_series->count(); |
917 | qreal candlestickHeight = plotArea.height(); |
918 | |
919 | QMap<QCandlestickSet *, QRectF> layout; |
920 | layout.insert(akey: set1, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set1), |
921 | plotArea.top(), candlestickWidth, candlestickHeight)); |
922 | layout.insert(akey: set2, avalue: QRectF(plotArea.left() + candlestickWidth * m_sets.indexOf(t: set2), |
923 | plotArea.top(), candlestickWidth, candlestickHeight)); |
924 | |
925 | // Double-click set 1 |
926 | QTest::mouseDClick(widget: view.viewport(), button: Qt::LeftButton, stateKey: {}, pos: layout.value(akey: set1).center().toPoint()); |
927 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, maxtime: 1000); |
928 | |
929 | QCOMPARE(seriesSpy.count(), 1); |
930 | QCOMPARE(setSpy1.count(), 1); |
931 | QCOMPARE(setSpy2.count(), 0); |
932 | |
933 | QList<QVariant> seriesSpyArgs = seriesSpy.takeFirst(); |
934 | QCOMPARE(seriesSpyArgs.count(), 1); |
935 | QCOMPARE(qvariant_cast<QCandlestickSet *>(seriesSpyArgs.at(0)), set1); |
936 | seriesSpyArgs.clear(); |
937 | |
938 | QVERIFY(setSpy1.takeFirst().isEmpty()); |
939 | } |
940 | |
941 | QTEST_MAIN(tst_QCandlestickSeries) |
942 | |
943 | #include "tst_qcandlestickseries.moc" |
944 | |