1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <private/percentbarchartitem_p.h>
5#include <private/bar_p.h>
6#include <private/qabstractbarseries_p.h>
7#include <QtCharts/QBarSet>
8#include <private/qbarset_p.h>
9
10QT_BEGIN_NAMESPACE
11
12PercentBarChartItem::PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
13 AbstractBarChartItem(series, item)
14{
15 m_orientation = Qt::Vertical;
16 connect(sender: series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)),
17 receiver: this, SLOT(handleLabelsPositionChanged()));
18 connect(sender: series, SIGNAL(labelsFormatChanged(QString)), receiver: this, SLOT(positionLabels()));
19}
20
21QString PercentBarChartItem::generateLabelText(int set, int category, qreal value)
22{
23 Q_UNUSED(value);
24
25 static const QString valueTag(QLatin1String("@value"));
26 qreal p = m_series->d_func()->percentageAt(set, category) * 100.0;
27 QString vString(presenter()->numberToString(value: p, f: 'f', prec: 0));
28 QString valueLabel;
29 if (m_series->labelsFormat().isEmpty()) {
30 vString.append(QStringLiteral("%"));
31 valueLabel = vString;
32 } else {
33 valueLabel = m_series->labelsFormat();
34 valueLabel.replace(before: valueTag, after: vString);
35 }
36
37 return valueLabel;
38}
39
40void PercentBarChartItem::initializeLayout(int set, int category,
41 int layoutIndex, bool resetAnimation)
42{
43 Q_UNUSED(set);
44 Q_UNUSED(resetAnimation);
45
46 QRectF rect;
47
48 if (set > 0) {
49 QBarSet *barSet = m_series->barSets().at(i: set - 1);
50 Bar *bar = m_indexForBarMap.value(key: barSet).value(key: category);
51 rect = m_layout.at(i: bar->layoutIndex());
52 rect.setBottom(rect.top());
53 } else {
54 QPointF topLeft;
55 QPointF bottomRight;
56 const qreal barWidth = m_series->d_func()->barWidth() * m_seriesWidth;
57 if (domain()->type() == AbstractDomain::XLogYDomain
58 || domain()->type() == AbstractDomain::LogXLogYDomain) {
59 topLeft = topLeftPoint(category, barWidth, value: domain()->minY());
60 bottomRight = bottomRightPoint(category, barWidth, value: domain()->minY());
61 } else {
62 topLeft = topLeftPoint(category, barWidth, value: 0.0);
63 bottomRight = bottomRightPoint(category, barWidth, value: 0.0);
64 }
65 if (m_validData) {
66 rect.setTopLeft(topLeft);
67 rect.setBottomRight(bottomRight);
68 }
69 }
70
71 m_layout[layoutIndex] = rect.normalized();
72}
73
74void PercentBarChartItem::markLabelsDirty(QBarSet *barset, int index, int count)
75{
76 Q_UNUSED(barset);
77 // Percent series need to dirty all labels of the stack
78 QList<QBarSet *> sets = m_barMap.keys();
79 for (int set = 0; set < sets.size(); set++)
80 AbstractBarChartItem::markLabelsDirty(barset: sets.at(i: set), index, count);
81}
82
83QPointF PercentBarChartItem::topLeftPoint(int category, qreal barWidth, qreal value)
84{
85 return domain()->calculateGeometryPoint(
86 point: QPointF(m_seriesPosAdjustment + category - (barWidth / 2.0), value), ok&: m_validData);
87}
88
89QPointF PercentBarChartItem::bottomRightPoint(int category, qreal barWidth, qreal value)
90{
91 return domain()->calculateGeometryPoint(
92 point: QPointF(m_seriesPosAdjustment + category + (barWidth / 2.0), value), ok&: m_validData);
93}
94
95QList<QRectF> PercentBarChartItem::calculateLayout()
96{
97 QList<QRectF> layout;
98 layout.resize(size: m_layout.size());
99
100 const int setCount = m_series->count();
101 const qreal barWidth = m_series->d_func()->barWidth() * m_seriesWidth;
102
103 QList<qreal> categorySums(m_categoryCount);
104 QList<qreal> tempSums(m_categoryCount, 0.0);
105
106 for (int category = 0; category < m_categoryCount; category++)
107 categorySums[category] = m_series->d_func()->categorySum(category: category + m_firstCategory);
108
109 for (int set = 0; set < setCount; set++) {
110 QBarSet *barSet = m_series->barSets().at(i: set);
111 const QList<Bar *> bars = m_barMap.value(key: barSet);
112 for (int i = 0; i < m_categoryCount; i++) {
113 Bar *bar = bars.at(i);
114 const int category = bar->index();
115 qreal &sum = tempSums[category - m_firstCategory];
116 const qreal &categorySum = categorySums.at(i: category - m_firstCategory);
117 qreal value = barSet->at(index: category);
118 QRectF rect;
119 qreal topY = 0.0;
120 qreal newSum = value + sum;
121 qreal bottomY = 0.0;
122 if (categorySum != 0.0) {
123 if (newSum > 0.0)
124 topY = 100.0 * newSum / categorySum;
125 if (sum > 0.0)
126 bottomY = 100.0 * sum / categorySum;
127 }
128 QPointF topLeft = topLeftPoint(category, barWidth, value: topY);
129 QPointF bottomRight;
130 if (domain()->type() == AbstractDomain::XLogYDomain
131 || domain()->type() == AbstractDomain::LogXLogYDomain) {
132 bottomRight = bottomRightPoint(category, barWidth,
133 value: set ? bottomY : domain()->minY());
134 } else {
135 bottomRight = bottomRightPoint(category, barWidth, value: bottomY);
136 }
137
138 rect.setTopLeft(topLeft);
139 rect.setBottomRight(bottomRight);
140 layout[bar->layoutIndex()] = rect.normalized();
141 sum = newSum;
142 }
143 }
144 return layout;
145}
146
147void PercentBarChartItem::handleLabelsPositionChanged()
148{
149 positionLabels();
150}
151
152void PercentBarChartItem::positionLabels()
153{
154 positionLabelsVertical();
155}
156
157QT_END_NAMESPACE
158
159#include "moc_percentbarchartitem_p.cpp"
160

source code of qtcharts/src/charts/barchart/vertical/percent/percentbarchartitem.cpp