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

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