// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include #include "private/qquickrectangle_p.h" #include "utils_p.h" QT_BEGIN_NAMESPACE Utils::ParamType Utils::preParseFormat( const QString &format, QString &preStr, QString &postStr, int &precision, char &formatSpec) { static QRegularExpression formatMatcher( QStringLiteral("^([^%]*)%([\\-\\+#\\s\\d\\.lhjztL]*)([dicuoxfegXFEG])(.*)$")); static QRegularExpression precisionMatcher(QStringLiteral("\\.(\\d+)")); Utils::ParamType retVal; QRegularExpressionMatch formatMatch = formatMatcher.match(format, 0); if (formatMatch.hasMatch()) { preStr = formatMatch.captured(1); // Six and 'g' are defaults in Qt API precision = 6; if (!formatMatch.captured(2).isEmpty()) { QRegularExpressionMatch precisionMatch = precisionMatcher.match(formatMatch.captured(2), 0); if (precisionMatch.hasMatch()) precision = precisionMatch.captured(1).toInt(); } if (formatMatch.captured(3).isEmpty()) formatSpec = 'g'; else formatSpec = formatMatch.captured(3).at(0).toLatin1(); postStr = formatMatch.captured(4); retVal = mapFormatCharToParamType(formatSpec); } else { retVal = ParamType::Unknown; // The out parameters are irrelevant in unknown case } return retVal; } Utils::ParamType Utils::mapFormatCharToParamType(char formatSpec) { ParamType retVal = ParamType::Unknown; if (formatSpec == 'd' || formatSpec == 'i' || formatSpec == 'c') { retVal = ParamType::Int; } else if (formatSpec == 'u' || formatSpec == 'o' || formatSpec == 'x' || formatSpec == 'X') { retVal = ParamType::UInt; } else if (formatSpec == 'f' || formatSpec == 'F' || formatSpec == 'e' || formatSpec == 'E' || formatSpec == 'g' || formatSpec == 'G') { retVal = ParamType::Real; } return retVal; } QString Utils::formatLabelSprintf(const QByteArray &format, Utils::ParamType paramType, qreal value) { switch (paramType) { case ParamType::Int: return QString::asprintf(format.constData(), qint64(value)); case ParamType::UInt: return QString::asprintf(format.constData(), quint64(value)); case ParamType::Real: return QString::asprintf(format.constData(), value); default: // Return format string to detect errors. Bars selection label logic also // depends on this. return QString::fromUtf8(format); } } QString Utils::formatLabelLocalized(Utils::ParamType paramType, qreal value, const QLocale &locale, const QString &preStr, const QString &postStr, int precision, char formatSpec, const QByteArray &format) { switch (paramType) { case ParamType::Int: case ParamType::UInt: return preStr + locale.toString(qint64(value)) + postStr; case ParamType::Real: return preStr + locale.toString(value, formatSpec, precision) + postStr; default: // Return format string to detect errors. Bars selection label logic also // depends on this. return QString::fromUtf8(format); } } QString Utils::defaultLabelFormat() { static const QString defaultFormat(QStringLiteral("%.2f")); return defaultFormat; } float Utils::wrapValue(float value, float min, float max) { if (value > max) { value = min + (value - max); // In case single wrap fails, jump to opposite end. if (value > max) value = min; } if (value < min) { value = max + (value - min); // In case single wrap fails, jump to opposite end. if (value < min) value = max; } return value; } QQuaternion Utils::calculateRotation(QVector3D xyzRotations) { QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, xyzRotations.x()); QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, xyzRotations.y()); QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, xyzRotations.z()); QQuaternion totalRotation = rotQuatY * rotQuatZ * rotQuatX; return totalRotation; } void Utils::verifyGradientCompleteness(QLinearGradient &gradient) { // Fix the start and end stops of the gradient, to make sure it's complete // (0...1) auto stops = gradient.stops(); if (stops.first().first != 0.) { const QColor firstColor = stops.first().second; gradient.setColorAt(0., firstColor); } if (stops.last().first != 1.) { const QColor lastColor = stops.last().second; gradient.setColorAt(1., lastColor); } } void Utils::setSeriesGradient(QAbstract3DSeries *series, QJSValue gradient, GradientType type) { auto newGradient = qobject_cast(gradient.toQObject()); QLinearGradient linearGradient; linearGradient.setStops(newGradient->gradientStops()); switch (type) { case GradientType::Base: series->setBaseGradient(linearGradient); break; case GradientType::Single: series->setSingleHighlightGradient(linearGradient); break; case GradientType::Multi: series->setMultiHighlightGradient(linearGradient); break; default: // Never goes here break; } } void Utils::setSeriesGradient(QAbstract3DSeries *series, QQuickGradient *gradient, GradientType type) { QLinearGradient lg; lg.setStops(gradient->gradientStops()); switch (type) { case GradientType::Base: series->setBaseGradient(lg); break; case GradientType::Single: series->setSingleHighlightGradient(lg); break; case GradientType::Multi: series->setMultiHighlightGradient(lg); break; default: // Never goes here break; } } void Utils::connectSeriesGradient(QAbstract3DSeries *series, QJSValue newGradient, GradientType type, QJSValue &memberGradient) { // connect new / disconnect old if (newGradient.isQObject() && !newGradient.equals(memberGradient)) { auto quickGradient = qobject_cast(memberGradient.toQObject()); if (quickGradient) QObject::disconnect(quickGradient, 0, series, 0); memberGradient = newGradient; quickGradient = qobject_cast(memberGradient.toQObject()); const int updatedIndex = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex(); int handleIndex = -1; switch (type) { case GradientType::Base: handleIndex = series->metaObject()->indexOfSlot("handleBaseGradientUpdate()"); break; case GradientType::Single: handleIndex = series->metaObject()->indexOfSlot( "handleSingleHighlightGradientUpdate()"); break; case GradientType::Multi: handleIndex = series->metaObject()->indexOfSlot("handleMultiHighlightGradientUpdate()"); break; default: // Never goes here break; } if (quickGradient) QMetaObject::connect(quickGradient, updatedIndex, series, handleIndex); } if (!memberGradient.isNull()) setSeriesGradient(series, memberGradient, type); } QT_END_NAMESPACE