1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCore/qregularexpression.h>
5#include <QtGui/qbrush.h>
6
7#include "private/qquickrectangle_p.h"
8#include "utils_p.h"
9
10QT_BEGIN_NAMESPACE
11
12Utils::ParamType Utils::preParseFormat(
13 const QString &format, QString &preStr, QString &postStr, int &precision, char &formatSpec)
14{
15 static QRegularExpression formatMatcher(
16 QStringLiteral("^([^%]*)%([\\-\\+#\\s\\d\\.lhjztL]*)([dicuoxfegXFEG])(.*)$"));
17 static QRegularExpression precisionMatcher(QStringLiteral("\\.(\\d+)"));
18
19 Utils::ParamType retVal;
20
21 QRegularExpressionMatch formatMatch = formatMatcher.match(subject: format, offset: 0);
22
23 if (formatMatch.hasMatch()) {
24 preStr = formatMatch.captured(nth: 1);
25 // Six and 'g' are defaults in Qt API
26 precision = 6;
27 if (!formatMatch.captured(nth: 2).isEmpty()) {
28 QRegularExpressionMatch precisionMatch = precisionMatcher.match(subject: formatMatch.captured(nth: 2),
29 offset: 0);
30 if (precisionMatch.hasMatch())
31 precision = precisionMatch.captured(nth: 1).toInt();
32 }
33 if (formatMatch.captured(nth: 3).isEmpty())
34 formatSpec = 'g';
35 else
36 formatSpec = formatMatch.captured(nth: 3).at(i: 0).toLatin1();
37 postStr = formatMatch.captured(nth: 4);
38 retVal = mapFormatCharToParamType(formatSpec);
39 } else {
40 retVal = ParamType::Unknown;
41 // The out parameters are irrelevant in unknown case
42 }
43
44 return retVal;
45}
46
47Utils::ParamType Utils::mapFormatCharToParamType(char formatSpec)
48{
49 ParamType retVal = ParamType::Unknown;
50 if (formatSpec == 'd' || formatSpec == 'i' || formatSpec == 'c') {
51 retVal = ParamType::Int;
52 } else if (formatSpec == 'u' || formatSpec == 'o' || formatSpec == 'x' || formatSpec == 'X') {
53 retVal = ParamType::UInt;
54 } else if (formatSpec == 'f' || formatSpec == 'F' || formatSpec == 'e' || formatSpec == 'E'
55 || formatSpec == 'g' || formatSpec == 'G') {
56 retVal = ParamType::Real;
57 }
58
59 return retVal;
60}
61
62QString Utils::formatLabelSprintf(const QByteArray &format, Utils::ParamType paramType, qreal value)
63{
64 switch (paramType) {
65 case ParamType::Int:
66 return QString::asprintf(format: format.constData(), qint64(value));
67 case ParamType::UInt:
68 return QString::asprintf(format: format.constData(), quint64(value));
69 case ParamType::Real:
70 return QString::asprintf(format: format.constData(), value);
71 default:
72 // Return format string to detect errors. Bars selection label logic also
73 // depends on this.
74 return QString::fromUtf8(ba: format);
75 }
76}
77
78QString Utils::formatLabelLocalized(Utils::ParamType paramType,
79 qreal value,
80 const QLocale &locale,
81 const QString &preStr,
82 const QString &postStr,
83 int precision,
84 char formatSpec,
85 const QByteArray &format)
86{
87 switch (paramType) {
88 case ParamType::Int:
89 case ParamType::UInt:
90 return preStr + locale.toString(i: qint64(value)) + postStr;
91 case ParamType::Real:
92 return preStr + locale.toString(f: value, format: formatSpec, precision) + postStr;
93 default:
94 // Return format string to detect errors. Bars selection label logic also
95 // depends on this.
96 return QString::fromUtf8(ba: format);
97 }
98}
99
100QString Utils::defaultLabelFormat()
101{
102 static const QString defaultFormat(QStringLiteral("%.2f"));
103 return defaultFormat;
104}
105
106float Utils::wrapValue(float value, float min, float max)
107{
108 if (value > max) {
109 value = min + (value - max);
110
111 // In case single wrap fails, jump to opposite end.
112 if (value > max)
113 value = min;
114 }
115
116 if (value < min) {
117 value = max + (value - min);
118
119 // In case single wrap fails, jump to opposite end.
120 if (value < min)
121 value = max;
122 }
123
124 return value;
125}
126
127QQuaternion Utils::calculateRotation(QVector3D xyzRotations)
128{
129 QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: xyzRotations.x());
130 QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(x: 0.0f, y: 1.0f, z: 0.0f, angle: xyzRotations.y());
131 QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(x: 0.0f, y: 0.0f, z: 1.0f, angle: xyzRotations.z());
132 QQuaternion totalRotation = rotQuatY * rotQuatZ * rotQuatX;
133 return totalRotation;
134}
135
136void Utils::verifyGradientCompleteness(QLinearGradient &gradient)
137{
138 // Fix the start and end stops of the gradient, to make sure it's complete
139 // (0...1)
140 auto stops = gradient.stops();
141 if (stops.first().first != 0.) {
142 const QColor firstColor = stops.first().second;
143 gradient.setColorAt(pos: 0., color: firstColor);
144 }
145 if (stops.last().first != 1.) {
146 const QColor lastColor = stops.last().second;
147 gradient.setColorAt(pos: 1., color: lastColor);
148 }
149}
150
151void Utils::setSeriesGradient(QAbstract3DSeries *series, QJSValue gradient, GradientType type)
152{
153 auto newGradient = qobject_cast<QQuickGradient *>(object: gradient.toQObject());
154 QLinearGradient linearGradient;
155 linearGradient.setStops(newGradient->gradientStops());
156
157 switch (type) {
158 case GradientType::Base:
159 series->setBaseGradient(linearGradient);
160 break;
161 case GradientType::Single:
162 series->setSingleHighlightGradient(linearGradient);
163 break;
164 case GradientType::Multi:
165 series->setMultiHighlightGradient(linearGradient);
166 break;
167 default: // Never goes here
168 break;
169 }
170}
171
172void Utils::setSeriesGradient(QAbstract3DSeries *series, QQuickGradient *gradient, GradientType type)
173{
174 QLinearGradient lg;
175 lg.setStops(gradient->gradientStops());
176 switch (type) {
177 case GradientType::Base:
178 series->setBaseGradient(lg);
179 break;
180 case GradientType::Single:
181 series->setSingleHighlightGradient(lg);
182 break;
183 case GradientType::Multi:
184 series->setMultiHighlightGradient(lg);
185 break;
186 default: // Never goes here
187 break;
188 }
189}
190
191void Utils::connectSeriesGradient(QAbstract3DSeries *series,
192 QJSValue newGradient,
193 GradientType type,
194 QJSValue &memberGradient)
195{
196 // connect new / disconnect old
197 if (newGradient.isQObject() && !newGradient.equals(other: memberGradient)) {
198 auto quickGradient = qobject_cast<QQuickGradient *>(object: memberGradient.toQObject());
199 if (quickGradient)
200 QObject::disconnect(sender: quickGradient, signal: 0, receiver: series, member: 0);
201
202 memberGradient = newGradient;
203 quickGradient = qobject_cast<QQuickGradient *>(object: memberGradient.toQObject());
204
205 const int updatedIndex = QMetaMethod::fromSignal(signal: &QQuickGradient::updated).methodIndex();
206
207 int handleIndex = -1;
208 switch (type) {
209 case GradientType::Base:
210 handleIndex = series->metaObject()->indexOfSlot(slot: "handleBaseGradientUpdate()");
211 break;
212 case GradientType::Single:
213 handleIndex = series->metaObject()->indexOfSlot(
214 slot: "handleSingleHighlightGradientUpdate()");
215 break;
216 case GradientType::Multi:
217 handleIndex = series->metaObject()->indexOfSlot(slot: "handleMultiHighlightGradientUpdate()");
218 break;
219 default: // Never goes here
220 break;
221 }
222
223 if (quickGradient)
224 QMetaObject::connect(sender: quickGradient, signal_index: updatedIndex, receiver: series, method_index: handleIndex);
225 }
226
227 if (!memberGradient.isNull())
228 setSeriesGradient(series, gradient: memberGradient, type);
229}
230
231QT_END_NAMESPACE
232

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtgraphs/src/graphs3d/utils/utils.cpp