1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCharts/qcategoryaxis.h>
5#include <QtCharts/QColorAxis>
6#include <QtCharts/qlogvalueaxis.h>
7#include <QtCore/qmath.h>
8#include <private/chartpresenter_p.h>
9#include <private/verticalaxis_p.h>
10#include <private/qabstractaxis_p.h>
11
12QT_BEGIN_NAMESPACE
13
14VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
15 : CartesianChartAxis(axis, item, intervalAxis)
16{
17}
18
19VerticalAxis::~VerticalAxis()
20{
21}
22
23QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
24{
25 Q_UNUSED(constraint);
26 QSizeF sh(0, 0);
27 // Size hint from here is used as the base for label size hints; if labels are not
28 // visible, we need to increase the size or we end up showing "..." when
29 // the title should be visible
30 qreal labelPaddingFactor = labelsVisible() ? 1 : 2;
31
32 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
33 return sh;
34
35 switch (which) {
36 case Qt::MinimumSize: {
37 QRectF titleRect = ChartPresenter::textBoundingRect(font: axis()->titleFont(),
38 QStringLiteral("..."));
39 sh = QSizeF(labelPaddingFactor * (titleRect.height() + (titlePadding() * 2.0)),
40 titleRect.width());
41 break;
42 }
43 case Qt::MaximumSize:
44 case Qt::PreferredSize: {
45 QRectF titleRect = ChartPresenter::textBoundingRect(font: axis()->titleFont(),
46 text: axis()->titleText());
47 sh = QSizeF(labelPaddingFactor * (titleRect.height() + (titlePadding() * 2.0)),
48 titleRect.width());
49 break;
50 }
51 default:
52 break;
53 }
54 return sh;
55}
56
57void VerticalAxis::updateGeometry()
58{
59 const QList<qreal> &layout = ChartAxisElement::layout();
60 const QList<qreal> &dynamicMinorTicklayout = ChartAxisElement::dynamicMinorTicklayout();
61
62 if (layout.isEmpty() && dynamicMinorTicklayout.isEmpty()
63 && axis()->type() != QAbstractAxis::AxisTypeLogValue) {
64 return;
65 }
66
67 QStringList labelList = labels();
68
69 QList<QGraphicsItem *> labels = labelItems();
70 QList<QGraphicsItem *> arrow = arrowItems();
71 QGraphicsTextItem *title = titleItem();
72
73 Q_ASSERT(labels.size() == labelList.size());
74 Q_ASSERT(layout.size() == labelList.size());
75
76 const QRectF &axisRect = axisGeometry();
77 const QRectF &gridRect = gridGeometry();
78
79 qreal height = axisRect.bottom();
80
81 //arrow
82 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(i: 0));
83
84 //arrow position
85 if (axis()->type() != QAbstractAxis::AxisTypeColor) {
86 if (axis()->alignment() == Qt::AlignLeft)
87 arrowItem->setLine(x1: axisRect.right(), y1: gridRect.top(), x2: axisRect.right(), y2: gridRect.bottom());
88 else if (axis()->alignment() == Qt::AlignRight)
89 arrowItem->setLine(x1: axisRect.left(), y1: gridRect.top(), x2: axisRect.left(), y2: gridRect.bottom());
90 }
91
92 //title
93 QRectF titleBoundingRect;
94 QString titleText = axis()->titleText();
95 qreal labelAvailableSpace = axisRect.width();
96 if (!titleText.isEmpty() && titleItem()->isVisible()) {
97 const qreal titleAvailableSpace =
98 axisRect.width() - labelPadding() - (titlePadding() * 2.0);
99 qreal minimumLabelWidth = ChartPresenter::textBoundingRect(font: axis()->labelsFont(),
100 QStringLiteral("...")).width();
101 qreal titleSpace = titleAvailableSpace - minimumLabelWidth;
102
103 if (axis()->type() == QAbstractAxis::AxisTypeColor) {
104 QColorAxis *colorAxis = static_cast<QColorAxis *>(axis());
105 titleSpace -= colorAxis->size() + colorScalePadding();
106 }
107
108 title->setHtml(ChartPresenter::truncatedText(font: axis()->titleFont(), text: titleText, angle: qreal(90.0),
109 maxWidth: titleSpace, maxHeight: gridRect.height(),
110 boundingRect&: titleBoundingRect));
111
112 title->setTextWidth(titleBoundingRect.height());
113
114 titleBoundingRect = title->boundingRect();
115
116 QPointF center = gridRect.center() - titleBoundingRect.center();
117 if (axis()->alignment() == Qt::AlignLeft) {
118 title->setPos(ax: axisRect.left() - titleBoundingRect.width() / 2.0
119 + titleBoundingRect.height() / 2.0 + titlePadding(), ay: center.y());
120 } else if (axis()->alignment() == Qt::AlignRight) {
121 title->setPos(ax: axisRect.right() - titleBoundingRect.width() / 2.0
122 - titleBoundingRect.height() / 2.0 - titlePadding(), ay: center.y());
123 }
124
125 title->setTransformOriginPoint(titleBoundingRect.center());
126 title->setRotation(270);
127 labelAvailableSpace -= titleBoundingRect.height();
128
129 if (axis()->type() == QAbstractAxis::AxisTypeColor) {
130 QColorAxis *colorAxis = static_cast<QColorAxis *>(axis());
131 labelAvailableSpace -= colorAxis->size() + colorScalePadding();
132 }
133 }
134
135 QList<QGraphicsItem *> lines = gridItems();
136 QList<QGraphicsItem *> shades = shadeItems();
137
138 bool labelsTruncated = false;
139
140 for (int i = 0; i < layout.size(); ++i) {
141 //items
142 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
143 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i: i + 1));
144 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
145
146 //grid line
147 if (axis()->isReverse()) {
148 gridItem->setLine(x1: gridRect.left(), y1: gridRect.top() + gridRect.bottom() - layout[i],
149 x2: gridRect.right(), y2: gridRect.top() + gridRect.bottom() - layout[i]);
150 } else {
151 gridItem->setLine(x1: gridRect.left(), y1: layout[i], x2: gridRect.right(), y2: layout[i]);
152 }
153
154 //label text wrapping
155 QString text;
156 if (axis()->isReverse() && axis()->type() != QAbstractAxis::AxisTypeCategory)
157 text = labelList.at(i: labelList.size() - i - 1);
158 else
159 text = labelList.at(i);
160
161 QRectF boundingRect;
162 // don't truncate empty labels
163 if (text.isEmpty()) {
164 labelItem->setHtml(text);
165 } else {
166 QString displayText = text;
167 if (axis()->truncateLabels()) {
168 qreal labelHeight = (axisRect.height() / layout.size()) - (2 * labelPadding());
169 // Replace digits with ellipsis "..." if number does not fit
170 displayText =
171 ChartPresenter::truncatedText(font: axis()->labelsFont(), text, angle: axis()->labelsAngle(),
172 maxWidth: labelAvailableSpace, maxHeight: labelHeight, boundingRect);
173 } else {
174 boundingRect = ChartPresenter::textBoundingRect(font: axis()->labelsFont(),
175 text: displayText, angle: axis()->labelsAngle());
176 }
177
178 labelItem->setTextWidth(ChartPresenter::textBoundingRect(font: axis()->labelsFont(),
179 text: displayText).width());
180
181 labelItem->setHtml(displayText);
182
183 labelsTruncated |= displayText != text;
184 }
185
186 //label transformation origin point
187 const QRectF &rect = labelItem->boundingRect();
188 QPointF center = rect.center();
189 labelItem->setTransformOriginPoint(ax: center.x(), ay: center.y());
190 qreal widthDiff = rect.width() - boundingRect.width();
191 qreal heightDiff = rect.height() - boundingRect.height();
192
193 //ticks and label position
194 QPointF labelPos;
195 if (axis()->alignment() == Qt::AlignLeft) {
196
197 qreal tickStopX = axisRect.right();
198
199 if (axis()->type() == QAbstractAxis::AxisTypeColor) {
200 QColorAxis *colorAxis = static_cast<QColorAxis *>(axis());
201 QGraphicsPixmapItem *colorScale = colorScaleItem();
202
203 const qreal penWidth = axis()->linePen().widthF();
204 // penWidth / 2 is half of tick width
205 colorScale->setOffset(ax: axisRect.right() - colorAxis->size() - colorScalePadding(),
206 ay: layout[i] - penWidth / 2);
207 prepareColorScale(width: colorAxis->size(), height: gridRect.height() + penWidth);
208
209 tickStopX = axisRect.right() - colorAxis->size() - colorScalePadding();
210 }
211
212 if (axis()->isReverse()) {
213 labelPos = QPointF(tickStopX - rect.width() + (widthDiff / 2.0) - labelPadding(),
214 gridRect.top() + gridRect.bottom()
215 - layout[layout.size() - i - 1] - center.y());
216 tickItem->setLine(x1: tickStopX - labelPadding(),
217 y1: gridRect.top() + gridRect.bottom() - layout[i], x2: tickStopX,
218 y2: gridRect.top() + gridRect.bottom() - layout[i]);
219 } else {
220 labelPos = QPointF(tickStopX - rect.width() + (widthDiff / 2.0) - labelPadding(),
221 layout[i] - center.y());
222 tickItem->setLine(x1: tickStopX - labelPadding(), y1: layout[i], x2: tickStopX, y2: layout[i]);
223 }
224 } else if (axis()->alignment() == Qt::AlignRight) {
225 qreal tickStartX = axisRect.left();
226
227 if (axis()->type() == QAbstractAxis::AxisTypeColor) {
228 QColorAxis *colorAxis = static_cast<QColorAxis *>(axis());
229 QGraphicsPixmapItem *colorScale = colorScaleItem();
230
231 const qreal penWidth = axis()->linePen().widthF();
232 // penWidth / 2 is half of tick width
233 colorScale->setOffset(ax: axisRect.x() + colorScalePadding(), ay: layout[i] - penWidth / 2);
234 prepareColorScale(width: colorAxis->size(), height: gridRect.height() + penWidth);
235
236 tickStartX = axisRect.x() + colorScalePadding() + colorAxis->size();
237 }
238
239
240 if (axis()->isReverse()) {
241 tickItem->setLine(x1: tickStartX, y1: gridRect.top() + gridRect.bottom() - layout[i],
242 x2: tickStartX + labelPadding(),
243 y2: gridRect.top() + gridRect.bottom() - layout[i]);
244 labelPos = QPointF(tickStartX + labelPadding() - (widthDiff / 2.0),
245 gridRect.top() + gridRect.bottom()
246 - layout[layout.size() - i - 1] - center.y());
247 } else {
248
249 labelPos = QPointF(tickStartX + labelPadding() - (widthDiff / 2.0),
250 layout[i] - center.y());
251 tickItem->setLine(x1: tickStartX, y1: layout[i], x2: tickStartX + labelPadding(), y2: layout[i]);
252 }
253 }
254
255 //label in between
256 bool forceHide = false;
257 bool labelOnValue = false;
258 if (intervalAxis() && (i + 1) != layout.size()
259 && axis()->type() != QAbstractAxis::AxisTypeColor) {
260 qreal lowerBound;
261 qreal upperBound;
262 if (axis()->isReverse()) {
263 lowerBound = qMax(a: gridRect.top() + gridRect.bottom() - layout[i + 1],
264 b: gridRect.top());
265 upperBound = qMin(a: gridRect.top() + gridRect.bottom() - layout[i],
266 b: gridRect.bottom());
267 } else {
268 lowerBound = qMin(a: layout[i], b: gridRect.bottom());
269 upperBound = qMax(a: layout[i + 1], b: gridRect.top());
270 }
271 const qreal delta = lowerBound - upperBound;
272 if (axis()->type() != QAbstractAxis::AxisTypeCategory) {
273 // Hide label in case visible part of the category at the grid edge is too narrow
274 if (delta < boundingRect.height()
275 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
276 forceHide = true;
277 } else {
278 labelPos.setY(lowerBound - (delta / 2.0) - center.y());
279 }
280 } else {
281 QCategoryAxis *categoryAxis = static_cast<QCategoryAxis *>(axis());
282 if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionCenter) {
283 if (delta < boundingRect.height()
284 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
285 forceHide = true;
286 } else {
287 labelPos.setY(lowerBound - (delta / 2.0) - center.y());
288 }
289 } else if (categoryAxis->labelsPosition()
290 == QCategoryAxis::AxisLabelsPositionOnValue) {
291 labelOnValue = true;
292 if (axis()->isReverse()) {
293 labelPos.setY(gridRect.top() + gridRect.bottom()
294 - layout[i + 1] - center.y());
295 } else {
296 labelPos.setY(upperBound - center.y());
297 }
298 }
299 }
300 }
301
302 // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases
303 labelItem->setPos(labelPos.toPoint());
304
305 //label overlap detection - compensate one pixel for rounding errors
306 if (axis()->isReverse()) {
307 if (forceHide)
308 labelItem->setVisible(false);
309 } else if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
310 ((labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom()
311 && !labelOnValue) ||
312 (labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0) && !labelOnValue)) {
313 labelItem->setVisible(false);
314 }
315 else {
316 labelItem->setVisible(true);
317 height=labelItem->pos().y();
318 }
319
320 //shades
321 QGraphicsRectItem *shadeItem = 0;
322 if (i == 0)
323 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(i: 0));
324 else if (i % 2)
325 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(i: (i / 2) + 1));
326 if (shadeItem) {
327 qreal lowerBound;
328 qreal upperBound;
329 if (i == 0) {
330 if (axis()->isReverse()) {
331 upperBound = gridRect.top();
332 lowerBound = gridRect.top() + gridRect.bottom() - layout[i];
333 } else {
334 lowerBound = gridRect.bottom();
335 upperBound = layout[0];
336 }
337 } else {
338 if (axis()->isReverse()) {
339 upperBound = gridRect.top() + gridRect.bottom() - layout[i];
340 if (i == layout.size() - 1) {
341 lowerBound = gridRect.bottom();
342 } else {
343 lowerBound = qMax(a: gridRect.top() + gridRect.bottom() - layout[i + 1],
344 b: gridRect.top());
345 }
346 } else {
347 lowerBound = layout[i];
348 if (i == layout.size() - 1)
349 upperBound = gridRect.top();
350 else
351 upperBound = qMax(a: layout[i + 1], b: gridRect.top());
352 }
353
354 }
355 if (lowerBound > gridRect.bottom())
356 lowerBound = gridRect.bottom();
357 if (upperBound < gridRect.top())
358 upperBound = gridRect.top();
359 shadeItem->setRect(ax: gridRect.left(), ay: upperBound, w: gridRect.width(),
360 h: lowerBound - upperBound);
361 if (shadeItem->rect().height() <= 0.0)
362 shadeItem->setVisible(false);
363 else
364 shadeItem->setVisible(true);
365 }
366
367 // check if the grid line and the axis tick should be shown
368 const bool gridLineVisible = (gridItem->line().p1().y() >= gridRect.top()
369 && gridItem->line().p1().y() <= gridRect.bottom());
370 gridItem->setVisible(gridLineVisible);
371 tickItem->setVisible(gridLineVisible);
372 }
373
374 axis()->d_ptr->setLabelsTruncated(labelsTruncated);
375
376 updateMinorTickGeometry();
377
378 // begin/end grid line in case labels between
379 if (intervalAxis()) {
380 QGraphicsLineItem *gridLine;
381 gridLine = static_cast<QGraphicsLineItem *>(lines.at(i: layout.size()));
382 gridLine->setLine(x1: gridRect.left(), y1: gridRect.top(), x2: gridRect.right(), y2: gridRect.top());
383 gridLine->setVisible(true);
384 gridLine = static_cast<QGraphicsLineItem*>(lines.at(i: layout.size() + 1));
385 gridLine->setLine(x1: gridRect.left(), y1: gridRect.bottom(), x2: gridRect.right(), y2: gridRect.bottom());
386 gridLine->setVisible(true);
387 }
388}
389
390void VerticalAxis::updateMinorTickGeometry()
391{
392 if (!axis())
393 return;
394
395 QList<qreal> layout = ChartAxisElement::layout();
396 int minorTickCount = 0;
397 qreal tickSpacing = 0.0;
398 QList<qreal> minorTickSpacings;
399 switch (axis()->type()) {
400 case QAbstractAxis::AxisTypeValue: {
401 const QValueAxis *valueAxis = qobject_cast<QValueAxis *>(object: axis());
402
403 minorTickCount = valueAxis->minorTickCount();
404
405 if (valueAxis->tickType() == QValueAxis::TicksFixed) {
406 if (valueAxis->tickCount() >= 2)
407 tickSpacing = layout.at(i: 0) - layout.at(i: 1);
408
409 for (int i = 0; i < minorTickCount; ++i) {
410 const qreal ratio = (1.0 / qreal(minorTickCount + 1)) * qreal(i + 1);
411 minorTickSpacings.append(t: tickSpacing * ratio);
412 }
413 }
414 break;
415 }
416 case QAbstractAxis::AxisTypeLogValue: {
417 const QLogValueAxis *logValueAxis = qobject_cast<QLogValueAxis *>(object: axis());
418 const qreal base = logValueAxis->base();
419 const qreal logBase = qLn(v: base);
420
421 minorTickCount = logValueAxis->minorTickCount();
422 if (minorTickCount < 0)
423 minorTickCount = qMax(a: qFloor(v: base) - 2, b: 0);
424
425 // Two "virtual" ticks are required to make sure that all minor ticks
426 // are displayed properly (even for the partially visible segments of
427 // the chart).
428 if (layout.size() >= 2) {
429 // Calculate tickSpacing as a difference between visible ticks
430 // whenever it is possible. Virtual ticks will not be correctly
431 // positioned when the layout is animating.
432 tickSpacing = layout.at(i: 0) - layout.at(i: 1);
433 layout.prepend(t: layout.at(i: 0) + tickSpacing);
434 layout.append(t: layout.at(i: layout.size() - 1) - tickSpacing);
435 } else {
436 const qreal logMax = qLn(v: logValueAxis->max()) / logBase;
437 const qreal logMin = qLn(v: logValueAxis->min()) / logBase;
438 const qreal logExtraMaxTick = qFloor(v: logMax) + 1.0;
439 const qreal logExtraMinTick = qCeil(v: logMin) - 1.0;
440 const qreal edge = gridGeometry().bottom();
441 const qreal delta = gridGeometry().height() / qAbs(t: logMax - logMin);
442 const qreal extraMaxTick = edge - (logExtraMaxTick - qMin(a: logMin, b: logMax)) * delta;
443 const qreal extraMinTick = edge - (logExtraMinTick - qMin(a: logMin, b: logMax)) * delta;
444
445 // Calculate tickSpacing using one (if layout.size() == 1) or two
446 // (if layout.size() == 0) "virtual" ticks. In both cases animation
447 // will not work as expected. This should be fixed later.
448 layout.prepend(t: extraMinTick);
449 layout.append(t: extraMaxTick);
450 tickSpacing = layout.at(i: 0) - layout.at(i: 1);
451 }
452
453 const qreal minorTickStepValue = qFabs(v: base - 1.0) / qreal(minorTickCount + 1);
454 for (int i = 0; i < minorTickCount; ++i) {
455 const qreal x = minorTickStepValue * qreal(i + 1) + 1.0;
456 const qreal minorTickSpacing = tickSpacing * (qLn(v: x) / logBase);
457 minorTickSpacings.append(t: minorTickSpacing);
458 }
459 break;
460 }
461 default:
462 // minor ticks are not supported
463 break;
464 }
465
466 const QValueAxis *valueAxis = qobject_cast<QValueAxis *>(object: axis());
467 if (valueAxis && valueAxis->tickType() == QValueAxis::TicksDynamic) {
468 const QList<qreal> dynamicMinorTicklayout = ChartAxisElement::dynamicMinorTicklayout();
469 const QRectF &gridRect = gridGeometry();
470 const qreal deltaY = gridRect.height() / (valueAxis->max() - valueAxis->min());
471 const qreal bottomPos = gridRect.bottom();
472 const qreal topPos = gridRect.top();
473
474 for (int i = 0; i < dynamicMinorTicklayout.size(); i++) {
475 QGraphicsLineItem *minorGridLineItem =
476 static_cast<QGraphicsLineItem *>(minorGridItems().value(i));
477 QGraphicsLineItem *minorArrowLineItem =
478 static_cast<QGraphicsLineItem *>(minorArrowItems().value(i));
479 if (!minorGridLineItem || !minorArrowLineItem)
480 continue;
481
482 qreal minorGridLineItemY = 0.0;
483 if (axis()->isReverse())
484 minorGridLineItemY = topPos + dynamicMinorTicklayout.at(i) * deltaY;
485 else
486 minorGridLineItemY = bottomPos - dynamicMinorTicklayout.at(i) * deltaY;
487
488 qreal minorArrowLineItemX1;
489 qreal minorArrowLineItemX2;
490 switch (axis()->alignment()) {
491 case Qt::AlignLeft:
492 minorArrowLineItemX1 = gridGeometry().left() - labelPadding() / 2.0;
493 minorArrowLineItemX2 = gridGeometry().left();
494 break;
495 case Qt::AlignRight:
496 minorArrowLineItemX1 = gridGeometry().right();
497 minorArrowLineItemX2 = gridGeometry().right() + labelPadding() / 2.0;
498 break;
499 default:
500 minorArrowLineItemX1 = 0.0;
501 minorArrowLineItemX2 = 0.0;
502 break;
503 }
504
505 minorGridLineItem->setLine(x1: gridGeometry().left(), y1: minorGridLineItemY,
506 x2: gridGeometry().right(), y2: minorGridLineItemY);
507 minorArrowLineItem->setLine(x1: minorArrowLineItemX1, y1: minorGridLineItemY,
508 x2: minorArrowLineItemX2, y2: minorGridLineItemY);
509
510 // check if the minor grid line and the minor axis arrow should be shown
511 bool minorGridLineVisible = (minorGridLineItemY >= gridGeometry().top()
512 && minorGridLineItemY <= gridGeometry().bottom());
513 minorGridLineItem->setVisible(minorGridLineVisible);
514 minorArrowLineItem->setVisible(minorGridLineVisible);
515 }
516 } else {
517 if (minorTickCount < 1 || tickSpacing == 0.0 || minorTickSpacings.size() != minorTickCount)
518 return;
519
520 for (int i = 0; i < layout.size() - 1; ++i) {
521 for (int j = 0; j < minorTickCount; ++j) {
522 const int minorItemIndex = i * minorTickCount + j;
523 QGraphicsLineItem *minorGridLineItem =
524 static_cast<QGraphicsLineItem *>(minorGridItems().value(i: minorItemIndex));
525 QGraphicsLineItem *minorArrowLineItem =
526 static_cast<QGraphicsLineItem *>(minorArrowItems().value(i: minorItemIndex));
527 if (!minorGridLineItem || !minorArrowLineItem)
528 continue;
529
530 const qreal minorTickSpacing = minorTickSpacings.value(i: j, defaultValue: 0.0);
531
532 qreal minorGridLineItemY = 0.0;
533 if (axis()->isReverse()) {
534 minorGridLineItemY = std::floor(x: gridGeometry().top() + gridGeometry().bottom()
535 - layout.at(i) + minorTickSpacing);
536 } else {
537 minorGridLineItemY = std::ceil(x: layout.at(i) - minorTickSpacing);
538 }
539
540 qreal minorArrowLineItemX1;
541 qreal minorArrowLineItemX2;
542 switch (axis()->alignment()) {
543 case Qt::AlignLeft:
544 minorArrowLineItemX1 = gridGeometry().left() - labelPadding() / 2.0;
545 minorArrowLineItemX2 = gridGeometry().left();
546 break;
547 case Qt::AlignRight:
548 minorArrowLineItemX1 = gridGeometry().right();
549 minorArrowLineItemX2 = gridGeometry().right() + labelPadding() / 2.0;
550 break;
551 default:
552 minorArrowLineItemX1 = 0.0;
553 minorArrowLineItemX2 = 0.0;
554 break;
555 }
556
557 minorGridLineItem->setLine(x1: gridGeometry().left(), y1: minorGridLineItemY,
558 x2: gridGeometry().right(), y2: minorGridLineItemY);
559 minorArrowLineItem->setLine(x1: minorArrowLineItemX1, y1: minorGridLineItemY,
560 x2: minorArrowLineItemX2, y2: minorGridLineItemY);
561
562 // check if the minor grid line and the minor axis arrow should be shown
563 bool minorGridLineVisible = (minorGridLineItemY >= gridGeometry().top()
564 && minorGridLineItemY <= gridGeometry().bottom());
565 minorGridLineItem->setVisible(minorGridLineVisible);
566 minorArrowLineItem->setVisible(minorGridLineVisible);
567 }
568 }
569 }
570}
571
572QT_END_NAMESPACE
573

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtcharts/src/charts/axis/verticalaxis.cpp