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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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