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/QBarCategoryAxis>
31#include <QtCharts/QCandlestickLegendMarker>
32#include <QtCharts/QCandlestickSeries>
33#include <QtCharts/QCandlestickSet>
34#include <QtCharts/QValueAxis>
35#include <QtCore/QDateTime>
36#include <private/candlestickanimation_p.h>
37#include <private/candlestickchartitem_p.h>
38#include <private/chartdataset_p.h>
39#include <private/charttheme_p.h>
40#include <private/qcandlestickseries_p.h>
41#include <private/qcandlestickset_p.h>
42#include <private/qchart_p.h>
43
44QT_CHARTS_BEGIN_NAMESPACE
45
46/*!
47 \class QCandlestickSeries
48 \since 5.8
49 \inmodule QtCharts
50 \brief The QCandlestickSeries class presents data as candlesticks.
51
52 This class acts as a container for single candlestick items. Each item is drawn to its own category
53 when using QBarCategoryAxis. QDateTimeAxis and QValueAxis can be used as alternatives to
54 QBarCategoryAxis. In this case, each candlestick item is drawn according to its timestamp value.
55
56 \note The timestamps must be unique within a QCandlestickSeries. When using QBarCategoryAxis,
57 only the first one of the candlestick items sharing a timestamp is drawn. If the chart includes
58 multiple instances of QCandlestickSeries, items from different series sharing a timestamp are
59 drawn to the same category. When using QValueAxis or QDateTimeAxis, candlestick items sharing a
60 timestamp will overlap each other.
61
62 See the \l {Candlestick Chart Example} {candlestick chart example} to learn how to create
63 a candlestick chart.
64 \image examples_candlestickchart.png
65
66 \sa QCandlestickSet, QBarCategoryAxis, QDateTimeAxis, QValueAxis
67*/
68
69/*!
70 \qmltype CandlestickSeries
71 \since QtCharts 2.2
72 \instantiates QCandlestickSeries
73 \inqmlmodule QtCharts
74 \inherits AbstractSeries
75 \brief Represents a series of data as candlesticks.
76
77 The CandlestickSeries type acts as a container for single candlestick items.
78 Each item is drawn to its own category
79 when using BarCategoryAxis. DateTimeAxis and ValueAxis can be used as an alternative to
80 BarCategoryAxis. In this case, each candlestick item is drawn according to its timestamp value.
81
82 \note The timestamps must be unique within a CandlestickSeries. When using BarCategoryAxis, only
83 the first one of the candlestick items sharing a timestamp is drawn. If the chart includes
84 multiple instances of CandlestickSeries, items from different series sharing a timestamp are
85 drawn to the same category. When using ValueAxis or DateTimeAxis, candlestick items sharing a
86 timestamp will overlap each other.
87
88 The following QML shows how to create a simple candlestick chart:
89 \code
90 import QtQuick 2.5
91 import QtCharts 2.2
92
93 ChartView {
94 title: "Candlestick Series"
95 width: 400
96 height: 300
97
98 CandlestickSeries {
99 name: "Acme Ltd."
100 increasingColor: "green"
101 decreasingColor: "red"
102
103 CandlestickSet { timestamp: 1435708800000; open: 690; high: 694; low: 599; close: 660 }
104 CandlestickSet { timestamp: 1435795200000; open: 669; high: 669; low: 669; close: 669 }
105 CandlestickSet { timestamp: 1436140800000; open: 485; high: 623; low: 485; close: 600 }
106 CandlestickSet { timestamp: 1436227200000; open: 589; high: 615; low: 377; close: 569 }
107 CandlestickSet { timestamp: 1436313600000; open: 464; high: 464; low: 254; close: 254 }
108 }
109 }
110 \endcode
111
112 \beginfloatleft
113 \image examples_qmlcandlestick.png
114 \endfloat
115 \clearfloat
116
117 \sa CandlestickSet, BarCategoryAxis, DateTimeAxis, ValueAxis
118*/
119
120/*!
121 \qmlproperty AbstractAxis CandlestickSeries::axisX
122 The x-axis used for the series. If you leave both axisX and axisXTop
123 undefined, a value axis is created for the series.
124 \sa axisXTop, ValueAxis
125*/
126
127/*!
128 \qmlproperty AbstractAxis CandlestickSeries::axisY
129 The y-axis used for the series. If you leave both axisY and axisYRight
130 undefined, a value axis is created for the series.
131 \sa axisYRight, ValueAxis
132*/
133
134/*!
135 \qmlproperty AbstractAxis CandlestickSeries::axisXTop
136 The x-axis used for the series, drawn on top of the chart view.
137
138 \note You can only provide either axisX or axisXTop, not both.
139 \sa axisX
140*/
141
142/*!
143 \qmlproperty AbstractAxis CandlestickSeries::axisYRight
144 The y-axis used for the series, drawn to the right on the chart view.
145
146 \note You can only provide either axisY or axisYRight, not both.
147 \sa axisY
148*/
149
150/*!
151 \property QCandlestickSeries::count
152 \brief The number of candlestick items in a series.
153*/
154
155/*!
156 \qmlproperty int CandlestickSeries::count
157 The number of candlestick items in a series.
158*/
159
160/*!
161 \property QCandlestickSeries::maximumColumnWidth
162 \brief The maximum width of the candlestick items in pixels. Setting a negative value means
163 there is no maximum width. All negative values are converted to -1.0.
164*/
165
166/*!
167 \qmlproperty real CandlestickSeries::maximumColumnWidth
168 The maximum width of the candlestick items in pixels. Setting a negative value means
169 there is no maximum width. All negative values are converted to -1.0.
170*/
171
172/*!
173 \property QCandlestickSeries::minimumColumnWidth
174 \brief The minimum width of the candlestick items in pixels. Setting a negative value means
175 there is no minimum width. All negative values are converted to -1.0.
176*/
177
178/*!
179 \qmlproperty real CandlestickSeries::minimumColumnWidth
180 The minimum width of the candlestick items in pixels. Setting a negative value means
181 there is no minimum width. All negative values are converted to -1.0.
182*/
183
184/*!
185 \property QCandlestickSeries::bodyWidth
186 \brief The relative width of the candlestick item within its own slot, in the range
187 from 0.0 to 1.0.
188
189 Values outside this range are clamped to 0.0 or 1.0.
190*/
191
192/*!
193 \qmlproperty real CandlestickSeries::bodyWidth
194 The relative width of the candlestick item within its own slot, in the range
195 from 0.0 to 1.0. Values outside this range are clamped to 0.0 or 1.0.
196*/
197
198/*!
199 \property QCandlestickSeries::bodyOutlineVisible
200 \brief The visibility of the candlestick body outline.
201*/
202
203/*!
204 \qmlproperty bool CandlestickSeries::bodyOutlineVisible
205 The visibility of the candlestick body outlines.
206*/
207
208/*!
209 \property QCandlestickSeries::capsWidth
210 \brief The relative width of the caps within a candlestick, in the range from 0.0
211 to 1.0.
212
213 Values outside this range are clamped to 0.0 or 1.0.
214*/
215
216/*!
217 \qmlproperty real CandlestickSeries::capsWidth
218 The relative width of the caps within a candlestick, in the range from 0.0
219 to 1.0. Values outside this range are clamped to 0.0 or 1.0.
220*/
221
222/*!
223 \property QCandlestickSeries::capsVisible
224 \brief The visibility of the caps.
225*/
226
227/*!
228 \qmlproperty bool CandlestickSeries::capsVisible
229 The visibility of the caps.
230*/
231
232/*!
233 \property QCandlestickSeries::increasingColor
234 \brief The color of the increasing candlestick item body.
235
236 A candlestick is \e increasing when its close value is higher than the open
237 value. By default, this property is set to the brush color. The default
238 color is used also when the property is set to an invalid color value.
239*/
240
241/*!
242 \qmlproperty color CandlestickSeries::increasingColor
243 The color of the increasing candlestick item body.
244 A candlestick is \e increasing when its close value is higher than the open
245 value. By default, this property is set to the brush color. The default
246 color is used also when the property is set to an invalid color value.
247*/
248
249/*!
250 \property QCandlestickSeries::decreasingColor
251 \brief The color of the decreasing candlestick item body.
252
253 A candlestick is \e decreasing when its open value is higher than the close
254 value. By default, this property is set to the brush color with the alpha
255 channel set to 128. The default color is used also when the property is set
256 to an invalid color value.
257*/
258
259/*!
260 \qmlproperty color CandlestickSeries::decreasingColor
261 The color of the decreasing candlestick item body.
262 A candlestick is \e decreasing when its open value is higher than the close
263 value. By default, this property is set to the brush color with the alpha
264 channel set to 128. The default color is used also when the property is set
265 to an invalid color value.
266*/
267
268/*!
269 \property QCandlestickSeries::brush
270 \brief The brush used to fill the candlestick items.
271*/
272
273/*!
274 \property QCandlestickSeries::pen
275 \brief The pen used to draw the lines of the candlestick items.
276*/
277
278/*!
279 \qmlproperty string CandlestickSeries::brushFilename
280 The name of the file used as a brush image for the series.
281*/
282
283/*!
284 \fn void QCandlestickSeries::clicked(QCandlestickSet *set)
285 This signal is emitted when the candlestick item specified by \a set
286 is clicked on the chart.
287*/
288
289/*!
290 \qmlsignal CandlestickSeries::clicked(CandlestickSet set)
291 This signal is emitted when the candlestick item specified by \a set
292 is clicked on the chart.
293
294 The corresponding signal handler is \c {onClicked}.
295*/
296
297/*!
298 \fn void QCandlestickSeries::hovered(bool status, QCandlestickSet *set)
299 This signal is emitted when a mouse is hovered over the candlestick
300 item specified by \a set in a chart.
301
302 When the mouse moves over the item, \a status turns \c true, and when the
303 mouse moves away again, it turns \c false.
304*/
305
306/*!
307 \qmlsignal CandlestickSeries::hovered(bool status, CandlestickSet set)
308 This signal is emitted when a mouse is hovered over the candlestick
309 item specified by \a set in a chart.
310
311 When the mouse moves over the item, \a status turns \c true, and when the
312 mouse moves away again, it turns \c false.
313
314 The corresponding signal handler is \c {onHovered}.
315*/
316
317/*!
318 \fn void QCandlestickSeries::pressed(QCandlestickSet *set)
319 This signal is emitted when the user clicks the candlestick item
320 specified by \a set and holds down the mouse button.
321*/
322
323/*!
324 \qmlsignal CandlestickSeries::pressed(CandlestickSet set)
325 This signal is emitted when the user clicks the candlestick item
326 specified by \a set and holds down the mouse button.
327
328 The corresponding signal handler is \c {onPressed}.
329*/
330
331/*!
332 \fn void QCandlestickSeries::released(QCandlestickSet *set)
333 This signal is emitted when the user releases the mouse press on the
334 candlestick item specified by \a set.
335*/
336
337/*!
338 \qmlsignal CandlestickSeries::released(CandlestickSet set)
339 This signal is emitted when the user releases the mouse press on the
340 candlestick item specified by \a set.
341
342 The corresponding signal handler is \c {onReleased}.
343*/
344
345/*!
346 \fn void QCandlestickSeries::doubleClicked(QCandlestickSet *set)
347 This signal is emitted when the candlestick item specified by \a set
348 is double-clicked on the chart.
349*/
350
351/*!
352 \qmlsignal CandlestickSeries::doubleClicked(CandlestickSet set)
353 This signal is emitted when the candlestick item specified by \a set
354 is double-clicked on the chart.
355
356 The corresponding signal handler is \c {onDoubleClicked}.
357*/
358
359/*!
360 \fn void QCandlestickSeries::candlestickSetsAdded(const QList<QCandlestickSet *> &sets)
361 This signal is emitted when the candlestick items specified by \a
362 sets are added to the series.
363*/
364
365/*!
366 \qmlsignal CandlestickSeries::candlestickSetsAdded(list<CandlestickSet> sets)
367 This signal is emitted when the candlestick items specified by
368 \a sets are added to the series.
369
370 The corresponding signal handler is \c {onCandlestickSetsAdded}.
371*/
372
373/*!
374 \fn void QCandlestickSeries::candlestickSetsRemoved(const QList<QCandlestickSet *> &sets)
375 This signal is emitted when the candlestick items specified by
376 \a sets are removed from the series.
377*/
378
379/*!
380 \qmlsignal CandlestickSeries::candlestickSetsRemoved(list<CandlestickSet> sets)
381 This signal is emitted when the candlestick items specified by
382 \a sets are removed from the series.
383
384 The corresponding signal handler is \c {onCandlestickSetsRemoved}.
385*/
386
387/*!
388 \fn void QCandlestickSeries::countChanged()
389 This signal is emitted when the number of candlestick items in the
390 series changes.
391 \sa count
392*/
393
394/*!
395 \fn void QCandlestickSeries::maximumColumnWidthChanged()
396 This signal is emitted when there is a change in the maximum column width of candlestick items.
397 \sa maximumColumnWidth
398*/
399
400/*!
401 \fn void QCandlestickSeries::minimumColumnWidthChanged()
402 This signal is emitted when there is a change in the minimum column width of candlestick items.
403 \sa minimumColumnWidth
404*/
405
406/*!
407 \fn void QCandlestickSeries::bodyWidthChanged()
408 This signal is emitted when the candlestick item width changes.
409 \sa bodyWidth
410*/
411
412/*!
413 \fn void QCandlestickSeries::bodyOutlineVisibilityChanged()
414 This signal is emitted when the visibility of the candlestick item body outline changes.
415 \sa bodyOutlineVisible
416*/
417
418/*!
419 \fn void QCandlestickSeries::capsWidthChanged()
420 This signal is emitted when the candlestick item caps width changes.
421 \sa capsWidth
422*/
423
424/*!
425 \fn void QCandlestickSeries::capsVisibilityChanged()
426 This signal is emitted when the visibility of the candlestick item caps changes.
427 \sa capsVisible
428*/
429
430/*!
431 \fn void QCandlestickSeries::increasingColorChanged()
432 This signal is emitted when the candlestick item increasing color changes.
433 \sa increasingColor
434*/
435
436/*!
437 \fn void QCandlestickSeries::decreasingColorChanged()
438 This signal is emitted when the candlestick item decreasing color changes.
439 \sa decreasingColor
440*/
441
442/*!
443 \fn void QCandlestickSeries::brushChanged()
444 This signal is emitted when the candlestick item brush changes.
445
446 \sa brush
447*/
448
449/*!
450 \fn void QCandlestickSeries::penChanged()
451 This signal is emitted when the candlestick item pen changes.
452
453 \sa pen
454*/
455
456/*!
457 \qmlmethod CandlestickSeries::at(int index)
458 Returns the candlestick item at the position specified by \a index. Returns
459 null if the index is not valid.
460*/
461
462/*!
463 Constructs an empty QCandlestickSeries. The \a parent is optional.
464*/
465QCandlestickSeries::QCandlestickSeries(QObject *parent)
466 : QAbstractSeries(*new QCandlestickSeriesPrivate(this), parent)
467{
468}
469
470/*!
471 Destroys the series. Removes the series from the chart.
472*/
473QCandlestickSeries::~QCandlestickSeries()
474{
475 Q_D(QCandlestickSeries);
476 if (d->m_chart)
477 d->m_chart->removeSeries(series: this);
478}
479
480/*!
481 \qmlmethod CandlestickSeries::append(CandlestickSet set)
482 Adds a single candlestick item specified by \a set to the series and takes
483 ownership of it. If the item is null or it is already in the series, it
484 is not appended.
485
486 Returns \c true if appending succeeded, \c false otherwise.
487*/
488
489/*!
490 Adds a single candlestick item specified by \a set to the series and takes
491 ownership of it. If the item is null or it is already in the series, it
492 is not appended.
493 Returns \c true if appending succeeded, \c false otherwise.
494*/
495bool QCandlestickSeries::append(QCandlestickSet *set)
496{
497 QList<QCandlestickSet *> sets;
498 sets.append(t: set);
499
500 return append(sets);
501}
502
503/*!
504 \qmlmethod CandlestickSeries::remove(CandlestickSet set)
505 Removes a single candlestick item, specified by \a set, from the series.
506
507 Returns \c true if the item is successfully deleted, \c false otherwise.
508*/
509
510/*!
511 Removes a single candlestick item, specified by \a set, from the series.
512 Returns \c true if the item is successfully deleted, \c false otherwise.
513*/
514bool QCandlestickSeries::remove(QCandlestickSet *set)
515{
516 QList<QCandlestickSet *> sets;
517 sets.append(t: set);
518
519 return remove(sets);
520}
521
522/*!
523 Adds a list of candlestick items specified by \a sets to the series and
524 takes ownership of it. If any of the items are null, already belong to
525 the series, or appear in the list more than once, nothing is appended.
526 Returns \c true if all items were appended successfully, \c false otherwise.
527*/
528bool QCandlestickSeries::append(const QList<QCandlestickSet *> &sets)
529{
530 Q_D(QCandlestickSeries);
531
532 bool success = d->append(sets);
533 if (success) {
534 emit candlestickSetsAdded(sets);
535 emit countChanged();
536 }
537
538 return success;
539}
540
541/*!
542 Removes a list of candlestick items specified by \a sets from the series. If
543 any of the items are null, were already removed from the series, or appear
544 in the list more than once, nothing is removed. Returns \c true if all items
545 were removed successfully, \c false otherwise.
546*/
547bool QCandlestickSeries::remove(const QList<QCandlestickSet *> &sets)
548{
549 Q_D(QCandlestickSeries);
550
551 bool success = d->remove(sets);
552 if (success) {
553 emit candlestickSetsRemoved(sets);
554 emit countChanged();
555 foreach (QCandlestickSet *set, sets)
556 delete set;
557 }
558
559 return success;
560}
561
562/*!
563 \qmlmethod CandlestickSeries::insert(int index, CandlestickSet set)
564 Inserts the candlestick item specified by \a set to the series at the
565 position specified by \a index. Takes ownership of the item. If the
566 item is null or already belongs to the series, it is not inserted.
567
568 Returns \c true if inserting succeeded, \c false otherwise.
569*/
570
571/*!
572 Inserts the candlestick item specified by \a set to the series at the
573 position specified by \a index. Takes ownership of the item. If the
574 item is null or already belongs to the series, it is not inserted.
575 Returns \c true if inserting succeeded, \c false otherwise.
576*/
577bool QCandlestickSeries::insert(int index, QCandlestickSet *set)
578{
579 Q_D(QCandlestickSeries);
580
581 bool success = d->insert(index, set);
582 if (success) {
583 QList<QCandlestickSet *> sets;
584 sets.append(t: set);
585 emit candlestickSetsAdded(sets);
586 emit countChanged();
587 }
588
589 return success;
590}
591
592/*!
593 Takes a single candlestick item, specified by \a set, from the series. Does
594 not delete the item. Returns \c true if the take operation was successful, \c false otherwise.
595 \note The series remains the item's parent object. You must set the parent
596 object to take full ownership.
597*/
598bool QCandlestickSeries::take(QCandlestickSet *set)
599{
600 Q_D(QCandlestickSeries);
601
602 QList<QCandlestickSet *> sets;
603 sets.append(t: set);
604
605 bool success = d->remove(sets);
606 if (success) {
607 emit candlestickSetsRemoved(sets);
608 emit countChanged();
609 }
610
611 return success;
612}
613
614/*!
615 \qmlmethod CandlestickSeries::clear()
616 Removes all candlestick items from the series and permanently deletes them.
617*/
618
619/*!
620 Removes all candlestick items from the series and permanently deletes them.
621*/
622void QCandlestickSeries::clear()
623{
624 Q_D(QCandlestickSeries);
625
626 QList<QCandlestickSet *> sets = this->sets();
627
628 bool success = d->remove(sets);
629 if (success) {
630 emit candlestickSetsRemoved(sets);
631 emit countChanged();
632 foreach (QCandlestickSet *set, sets)
633 delete set;
634 }
635}
636
637/*!
638 Returns the list of candlestick items in the series. Ownership of the
639 items does not change.
640 */
641QList<QCandlestickSet *> QCandlestickSeries::sets() const
642{
643 Q_D(const QCandlestickSeries);
644
645 return d->m_sets;
646}
647
648/*!
649 Returns the number of the candlestick items in the series.
650*/
651int QCandlestickSeries::count() const
652{
653 return sets().count();
654}
655
656/*!
657 Returns the type of the series (QAbstractSeries::SeriesTypeCandlestick).
658*/
659QAbstractSeries::SeriesType QCandlestickSeries::type() const
660{
661 return QAbstractSeries::SeriesTypeCandlestick;
662}
663
664void QCandlestickSeries::setMaximumColumnWidth(qreal maximumColumnWidth)
665{
666 Q_D(QCandlestickSeries);
667
668 if (maximumColumnWidth < 0.0 && maximumColumnWidth != -1.0)
669 maximumColumnWidth = -1.0;
670
671 if (d->m_maximumColumnWidth == maximumColumnWidth)
672 return;
673
674 d->m_maximumColumnWidth = maximumColumnWidth;
675
676 emit d->updatedLayout();
677 emit maximumColumnWidthChanged();
678}
679
680qreal QCandlestickSeries::maximumColumnWidth() const
681{
682 Q_D(const QCandlestickSeries);
683
684 return d->m_maximumColumnWidth;
685}
686
687void QCandlestickSeries::setMinimumColumnWidth(qreal minimumColumnWidth)
688{
689 Q_D(QCandlestickSeries);
690
691 if (minimumColumnWidth < 0.0 && minimumColumnWidth != -1.0)
692 minimumColumnWidth = -1.0;
693
694 if (d->m_minimumColumnWidth == minimumColumnWidth)
695 return;
696
697 d->m_minimumColumnWidth = minimumColumnWidth;
698
699 d->updatedLayout();
700 emit minimumColumnWidthChanged();
701}
702
703qreal QCandlestickSeries::minimumColumnWidth() const
704{
705 Q_D(const QCandlestickSeries);
706
707 return d->m_minimumColumnWidth;
708}
709
710void QCandlestickSeries::setBodyWidth(qreal bodyWidth)
711{
712 Q_D(QCandlestickSeries);
713
714 if (bodyWidth < 0.0)
715 bodyWidth = 0.0;
716 else if (bodyWidth > 1.0)
717 bodyWidth = 1.0;
718
719 if (d->m_bodyWidth == bodyWidth)
720 return;
721
722 d->m_bodyWidth = bodyWidth;
723
724 emit d->updatedLayout();
725 emit bodyWidthChanged();
726}
727
728qreal QCandlestickSeries::bodyWidth() const
729{
730 Q_D(const QCandlestickSeries);
731
732 return d->m_bodyWidth;
733}
734
735void QCandlestickSeries::setBodyOutlineVisible(bool bodyOutlineVisible)
736{
737 Q_D(QCandlestickSeries);
738
739 if (d->m_bodyOutlineVisible == bodyOutlineVisible)
740 return;
741
742 d->m_bodyOutlineVisible = bodyOutlineVisible;
743
744 emit d->updated();
745 emit bodyOutlineVisibilityChanged();
746}
747
748bool QCandlestickSeries::bodyOutlineVisible() const
749{
750 Q_D(const QCandlestickSeries);
751
752 return d->m_bodyOutlineVisible;
753}
754
755void QCandlestickSeries::setCapsWidth(qreal capsWidth)
756{
757 Q_D(QCandlestickSeries);
758
759 if (capsWidth < 0.0)
760 capsWidth = 0.0;
761 else if (capsWidth > 1.0)
762 capsWidth = 1.0;
763
764 if (d->m_capsWidth == capsWidth)
765 return;
766
767 d->m_capsWidth = capsWidth;
768
769 emit d->updatedLayout();
770 emit capsWidthChanged();
771}
772
773qreal QCandlestickSeries::capsWidth() const
774{
775 Q_D(const QCandlestickSeries);
776
777 return d->m_capsWidth;
778}
779
780void QCandlestickSeries::setCapsVisible(bool capsVisible)
781{
782 Q_D(QCandlestickSeries);
783
784 if (d->m_capsVisible == capsVisible)
785 return;
786
787 d->m_capsVisible = capsVisible;
788
789 emit d->updated();
790 emit capsVisibilityChanged();
791}
792
793bool QCandlestickSeries::capsVisible() const
794{
795 Q_D(const QCandlestickSeries);
796
797 return d->m_capsVisible;
798}
799
800void QCandlestickSeries::setIncreasingColor(const QColor &increasingColor)
801{
802 Q_D(QCandlestickSeries);
803
804 QColor color;
805 if (increasingColor.isValid()) {
806 color = increasingColor;
807 d->m_customIncreasingColor = true;
808 } else {
809 color = d->m_brush.color();
810 color.setAlpha(128);
811 d->m_customIncreasingColor = false;
812 }
813
814 if (d->m_increasingColor == color)
815 return;
816
817 d->m_increasingColor = color;
818
819 emit d->updated();
820 emit increasingColorChanged();
821}
822
823QColor QCandlestickSeries::increasingColor() const
824{
825 Q_D(const QCandlestickSeries);
826
827 return d->m_increasingColor;
828}
829
830void QCandlestickSeries::setDecreasingColor(const QColor &decreasingColor)
831{
832 Q_D(QCandlestickSeries);
833
834 QColor color;
835 if (decreasingColor.isValid()) {
836 color = decreasingColor;
837 d->m_customDecreasingColor = true;
838 } else {
839 color = d->m_brush.color();
840 d->m_customDecreasingColor = false;
841 }
842
843 if (d->m_decreasingColor == color)
844 return;
845
846 d->m_decreasingColor = color;
847
848 emit d->updated();
849 emit decreasingColorChanged();
850}
851
852QColor QCandlestickSeries::decreasingColor() const
853{
854 Q_D(const QCandlestickSeries);
855
856 return d->m_decreasingColor;
857}
858
859void QCandlestickSeries::setBrush(const QBrush &brush)
860{
861 Q_D(QCandlestickSeries);
862
863 if (d->m_brush == brush)
864 return;
865
866 d->m_brush = brush;
867 if (!d->m_customIncreasingColor) {
868 QColor color = d->m_brush.color();
869 color.setAlpha(128);
870 if (d->m_increasingColor != color) {
871 d->m_increasingColor = color;
872 emit increasingColorChanged();
873 }
874 }
875 if (!d->m_customDecreasingColor && d->m_decreasingColor != d->m_brush.color()) {
876 d->m_decreasingColor = d->m_brush.color();
877 emit decreasingColorChanged();
878 }
879
880 emit d->updated();
881 emit brushChanged();
882}
883
884QBrush QCandlestickSeries::brush() const
885{
886 Q_D(const QCandlestickSeries);
887
888 return d->m_brush;
889}
890
891void QCandlestickSeries::setPen(const QPen &pen)
892{
893 Q_D(QCandlestickSeries);
894
895 if (d->m_pen == pen)
896 return;
897
898 d->m_pen = pen;
899
900 emit d->updated();
901 emit penChanged();
902}
903
904QPen QCandlestickSeries::pen() const
905{
906 Q_D(const QCandlestickSeries);
907
908 return d->m_pen;
909}
910
911////////////////////////////////////////////////////////////////////////////////////////////////////
912
913QCandlestickSeriesPrivate::QCandlestickSeriesPrivate(QCandlestickSeries *q)
914 : QAbstractSeriesPrivate(q),
915 m_maximumColumnWidth(-1.0),
916 m_minimumColumnWidth(5.0),
917 m_bodyWidth(0.5),
918 m_bodyOutlineVisible(true),
919 m_capsWidth(0.5),
920 m_capsVisible(false),
921 m_increasingColor(QColor(Qt::transparent)),
922 m_decreasingColor(QChartPrivate::defaultBrush().color()),
923 m_customIncreasingColor(false),
924 m_customDecreasingColor(false),
925 m_brush(QChartPrivate::defaultBrush()),
926 m_pen(QChartPrivate::defaultPen()),
927 m_animation(nullptr)
928{
929}
930
931QCandlestickSeriesPrivate::~QCandlestickSeriesPrivate()
932{
933 disconnect(sender: this, signal: 0, receiver: 0, member: 0);
934 qDeleteAll(c: m_sets);
935}
936
937void QCandlestickSeriesPrivate::initializeDomain()
938{
939 qreal minX(domain()->minX());
940 qreal maxX(domain()->maxX());
941 qreal minY(domain()->minY());
942 qreal maxY(domain()->maxY());
943
944 if (m_sets.count()) {
945 QCandlestickSet *set = m_sets.first();
946 minX = set->timestamp();
947 maxX = set->timestamp();
948 minY = set->low();
949 maxY = set->high();
950 for (int i = 1; i < m_sets.count(); ++i) {
951 set = m_sets.at(i);
952 minX = qMin(a: minX, b: qreal(set->timestamp()));
953 maxX = qMax(a: maxX, b: qreal(set->timestamp()));
954 minY = qMin(a: minY, b: set->low());
955 maxY = qMax(a: maxY, b: set->high());
956 }
957 qreal extra = (maxX - minX) / m_sets.count() / 2;
958 minX = minX - extra;
959 maxX = maxX + extra;
960 }
961
962 domain()->setRange(minX, maxX, minY, maxY);
963}
964
965void QCandlestickSeriesPrivate::initializeAxes()
966{
967 foreach (QAbstractAxis* axis, m_axes) {
968 if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
969 if (axis->orientation() == Qt::Horizontal)
970 populateBarCategories(axis: qobject_cast<QBarCategoryAxis *>(object: axis));
971 }
972 }
973}
974
975void QCandlestickSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
976{
977 Q_Q(QCandlestickSeries);
978
979 if (forced || QChartPrivate::defaultBrush() == m_brush) {
980 const QList<QGradient> gradients = theme->seriesGradients();
981 const QGradient gradient = gradients.at(i: index % gradients.size());
982 const QBrush brush(ChartThemeManager::colorAt(gradient, pos: 0.5));
983 q->setBrush(brush);
984 }
985
986 if (forced || QChartPrivate::defaultPen() == m_pen) {
987 QPen pen = theme->outlinePen();
988 pen.setCosmetic(true);
989 q->setPen(pen);
990 }
991}
992
993void QCandlestickSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
994{
995 Q_Q(QCandlestickSeries);
996
997 CandlestickChartItem *item = new CandlestickChartItem(q, parent);
998 m_item.reset(other: item);
999 QAbstractSeriesPrivate::initializeGraphics(parent);
1000
1001 if (m_chart) {
1002 connect(sender: m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries *)),
1003 receiver: this, SLOT(handleSeriesChange(QAbstractSeries *)));
1004 connect(sender: m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries *)),
1005 receiver: this, SLOT(handleSeriesRemove(QAbstractSeries *)));
1006
1007 item->handleCandlestickSeriesChange();
1008 }
1009}
1010
1011void QCandlestickSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
1012 QEasingCurve &curve)
1013{
1014 CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.data());
1015 Q_ASSERT(item);
1016
1017 if (item->animation())
1018 item->animation()->stopAndDestroyLater();
1019
1020 if (options.testFlag(flag: QChart::SeriesAnimations))
1021 m_animation = new CandlestickAnimation(item, duration, curve);
1022 else
1023 m_animation = nullptr;
1024 item->setAnimation(m_animation);
1025
1026 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
1027}
1028
1029QList<QLegendMarker *> QCandlestickSeriesPrivate::createLegendMarkers(QLegend *legend)
1030{
1031 Q_Q(QCandlestickSeries);
1032
1033 QList<QLegendMarker *> list;
1034
1035 return list << new QCandlestickLegendMarker(q, legend);
1036}
1037
1038QAbstractAxis::AxisType QCandlestickSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
1039{
1040 if (orientation == Qt::Horizontal)
1041 return QAbstractAxis::AxisTypeBarCategory;
1042
1043 if (orientation == Qt::Vertical)
1044 return QAbstractAxis::AxisTypeValue;
1045
1046 return QAbstractAxis::AxisTypeNoAxis;
1047}
1048
1049QAbstractAxis* QCandlestickSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
1050{
1051 const QAbstractAxis::AxisType axisType = defaultAxisType(orientation);
1052
1053 if (axisType == QAbstractAxis::AxisTypeBarCategory)
1054 return new QBarCategoryAxis;
1055
1056 if (axisType == QAbstractAxis::AxisTypeValue)
1057 return new QValueAxis;
1058
1059 return 0; // axisType == QAbstractAxis::AxisTypeNoAxis
1060}
1061
1062bool QCandlestickSeriesPrivate::append(const QList<QCandlestickSet *> &sets)
1063{
1064 foreach (QCandlestickSet *set, sets) {
1065 if ((set == 0) || m_sets.contains(t: set) || set->d_ptr->m_series)
1066 return false; // Fail if any of the sets is null or is already appended.
1067 if (sets.count(t: set) != 1)
1068 return false; // Also fail if the same set occurs more than once in the given list.
1069 }
1070
1071 foreach (QCandlestickSet *set, sets) {
1072 m_sets.append(t: set);
1073 connect(sender: set->d_func(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout()));
1074 connect(sender: set->d_func(), SIGNAL(updatedCandlestick()), receiver: this, SIGNAL(updatedCandlesticks()));
1075 set->d_ptr->m_series = this;
1076 }
1077
1078 return true;
1079}
1080
1081bool QCandlestickSeriesPrivate::remove(const QList<QCandlestickSet *> &sets)
1082{
1083 if (sets.count() == 0)
1084 return false;
1085
1086 foreach (QCandlestickSet *set, sets) {
1087 if ((set == 0) || (!m_sets.contains(t: set)))
1088 return false; // Fail if any of the sets is null or is not in series.
1089 if (sets.count(t: set) != 1)
1090 return false; // Also fail if the same set occurs more than once in the given list.
1091 }
1092
1093 foreach (QCandlestickSet *set, sets) {
1094 set->d_ptr->m_series = nullptr;
1095 m_sets.removeOne(t: set);
1096 disconnect(sender: set->d_func(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout()));
1097 disconnect(sender: set->d_func(), SIGNAL(updatedCandlestick()),receiver: this, SIGNAL(updatedCandlesticks()));
1098 }
1099
1100 return true;
1101}
1102
1103bool QCandlestickSeriesPrivate::insert(int index, QCandlestickSet *set)
1104{
1105 if ((m_sets.contains(t: set)) || (set == 0) || set->d_ptr->m_series)
1106 return false; // Fail if set is already in list or set is null.
1107
1108 m_sets.insert(i: index, t: set);
1109 connect(sender: set->d_func(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout()));
1110 connect(sender: set->d_func(), SIGNAL(updatedCandlestick()), receiver: this, SIGNAL(updatedCandlesticks()));
1111 set->d_ptr->m_series = this;
1112
1113 return true;
1114}
1115
1116void QCandlestickSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
1117{
1118 Q_UNUSED(series);
1119
1120 if (m_chart) {
1121 CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.data());
1122 if (item)
1123 item->handleCandlestickSeriesChange();
1124 }
1125}
1126
1127void QCandlestickSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
1128{
1129 Q_Q(const QCandlestickSeries);
1130
1131 QCandlestickSeries *removedSeries = static_cast<QCandlestickSeries *>(series);
1132
1133 if (q == removedSeries && m_animation) {
1134 m_animation->stopAll();
1135 disconnect(sender: m_chart->d_ptr->m_dataset, signal: 0, receiver: removedSeries->d_func(), member: 0);
1136 }
1137
1138 if (q != removedSeries) {
1139 CandlestickChartItem *item = static_cast<CandlestickChartItem *>(m_item.data());
1140 if (item)
1141 item->handleCandlestickSeriesChange();
1142 }
1143}
1144
1145void QCandlestickSeriesPrivate::populateBarCategories(QBarCategoryAxis *axis)
1146{
1147 if (axis->categories().isEmpty()) {
1148 QStringList categories;
1149 for (int i = 0; i < m_sets.count(); ++i) {
1150 const qint64 timestamp = qRound64(d: m_sets.at(i)->timestamp());
1151 const QString timestampFormat = m_chart->locale().dateTimeFormat(format: QLocale::ShortFormat);
1152 categories << QDateTime::fromMSecsSinceEpoch(msecs: timestamp).toString(format: timestampFormat);
1153 }
1154 axis->append(categories);
1155 }
1156}
1157
1158QT_CHARTS_END_NAMESPACE
1159
1160#include "moc_qcandlestickseries.cpp"
1161#include "moc_qcandlestickseries_p.cpp"
1162

source code of qtcharts/src/charts/candlestickchart/qcandlestickseries.cpp