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 Data Visualization 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 "customformatter.h"
31#include <QtDataVisualization/QValue3DAxis>
32#include <QtQml/QQmlExtensionPlugin>
33#include <QtCore/QDebug>
34
35using namespace QtDataVisualization;
36
37Q_DECLARE_METATYPE(QValue3DAxisFormatter *)
38
39static const qreal oneDayMs = 60.0 * 60.0 * 24.0 * 1000.0;
40
41CustomFormatter::CustomFormatter(QObject *parent) :
42 QValue3DAxisFormatter(parent)
43{
44 qRegisterMetaType<QValue3DAxisFormatter *>();
45}
46
47CustomFormatter::~CustomFormatter()
48{
49}
50
51//! [1]
52QValue3DAxisFormatter *CustomFormatter::createNewInstance() const
53{
54 return new CustomFormatter();
55}
56
57void CustomFormatter::populateCopy(QValue3DAxisFormatter &copy) const
58{
59 QValue3DAxisFormatter::populateCopy(copy);
60
61 CustomFormatter *customFormatter = static_cast<CustomFormatter *>(&copy);
62 customFormatter->m_originDate = m_originDate;
63 customFormatter->m_selectionFormat = m_selectionFormat;
64}
65//! [1]
66
67//! [2]
68void CustomFormatter::recalculate()
69{
70 // We want our axis to always have gridlines at date breaks
71
72 // Convert range into QDateTimes
73 QDateTime minTime = valueToDateTime(value: qreal(axis()->min()));
74 QDateTime maxTime = valueToDateTime(value: qreal(axis()->max()));
75
76 // Find out the grid counts
77 QTime midnight(0, 0);
78 QDateTime minFullDate(minTime.date(), midnight);
79 int gridCount = 0;
80 if (minFullDate != minTime)
81 minFullDate = minFullDate.addDays(days: 1);
82 QDateTime maxFullDate(maxTime.date(), midnight);
83
84 gridCount += minFullDate.daysTo(maxFullDate) + 1;
85 int subGridCount = axis()->subSegmentCount() - 1;
86
87 // Reserve space for position arrays and label strings
88 gridPositions().resize(asize: gridCount);
89 subGridPositions().resize(asize: (gridCount + 1) * subGridCount);
90 labelPositions().resize(asize: gridCount);
91 labelStrings().reserve(alloc: gridCount);
92
93 // Calculate positions and format labels
94 qint64 startMs = minTime.toMSecsSinceEpoch();
95 qint64 endMs = maxTime.toMSecsSinceEpoch();
96 qreal dateNormalizer = endMs - startMs;
97 qreal firstLineOffset = (minFullDate.toMSecsSinceEpoch() - startMs) / dateNormalizer;
98 qreal segmentStep = oneDayMs / dateNormalizer;
99 qreal subSegmentStep = 0;
100 if (subGridCount > 0)
101 subSegmentStep = segmentStep / qreal(subGridCount + 1);
102
103 for (int i = 0; i < gridCount; i++) {
104 qreal gridValue = firstLineOffset + (segmentStep * qreal(i));
105 gridPositions()[i] = float(gridValue);
106 labelPositions()[i] = float(gridValue);
107 labelStrings() << minFullDate.addDays(days: i).toString(format: axis()->labelFormat());
108 }
109
110 for (int i = 0; i <= gridCount; i++) {
111 if (subGridPositions().size()) {
112 for (int j = 0; j < subGridCount; j++) {
113 float position;
114 if (i)
115 position = gridPositions().at(i: i - 1) + subSegmentStep * (j + 1);
116 else
117 position = gridPositions().at(i: 0) - segmentStep + subSegmentStep * (j + 1);
118 if (position > 1.0f || position < 0.0f)
119 position = gridPositions().at(i: 0);
120 subGridPositions()[i * subGridCount + j] = position;
121 }
122 }
123 }
124}
125//! [2]
126
127//! [3]
128QString CustomFormatter::stringForValue(qreal value, const QString &format) const
129{
130 Q_UNUSED(format)
131
132 return valueToDateTime(value).toString(format: m_selectionFormat);
133}
134//! [3]
135
136QDate CustomFormatter::originDate() const
137{
138 return m_originDate;
139}
140
141QString CustomFormatter::selectionFormat() const
142{
143 return m_selectionFormat;
144}
145
146void CustomFormatter::setOriginDate(const QDate &date)
147{
148 if (m_originDate != date) {
149 m_originDate = date;
150 markDirty(labelsChange: true);
151 emit originDateChanged(date);
152 }
153}
154
155void CustomFormatter::setSelectionFormat(const QString &format)
156{
157 if (m_selectionFormat != format) {
158 m_selectionFormat = format;
159 markDirty(labelsChange: true); // Necessary to regenerate already visible selection label
160 emit selectionFormatChanged(format);
161 }
162}
163
164//! [0]
165QDateTime CustomFormatter::valueToDateTime(qreal value) const
166{
167 return m_originDate.startOfDay().addMSecs(msecs: qint64(oneDayMs * value));
168}
169//! [0]
170

source code of qtdatavis3d/examples/datavisualization/qmlaxisformatter/customformatter.cpp