Files
RedBear-OS/local/recipes/qt/qtdeclarative/source/src/quicktemplates/qquickspinbox.cpp
T
vasilito f31522130f fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed
Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
2026-05-05 20:20:37 +01:00

533 lines
15 KiB
C++

// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qquickspinbox_p.h"
#include <private/qquickcontrol_p_p.h>
#include <private/qquickindicatorbutton_p.h>
#include <private/qquicktextinput_p.h>
#include <private/qqmlengine_p.h>
#include <QtQml/qqmlinfo.h>
QT_BEGIN_NAMESPACE
/*!
\qmltype SpinBox
\inherits Control
//! \nativetype QQuickSpinBox
\inqmlmodule QtQuick.Controls
\since 5.7
\ingroup qtquickcontrols-input
\ingroup qtquickcontrols-focusscopes
\brief Allows the user to select from a set of preset values.
\image qtquickcontrols-spinbox.png
{Spin box with numeric value and buttons}
SpinBox allows the user to choose an integer value by clicking the up
or down indicator buttons, or by pressing up or down on the keyboard.
Optionally, SpinBox can be also made \l editable, so the user can enter
a text value in the input field.
By default, SpinBox provides discrete values in the range of \c [0-99]
with a \l stepSize of \c 1.
\snippet qtquickcontrols-spinbox.qml 1
\section2 Custom Values
\image qtquickcontrols-spinbox-textual.png
{Spin box displaying textual values}
Even though SpinBox works on integer values, it can be customized to
accept arbitrary input values. The following snippet demonstrates how
\l validator, \l textFromValue and \l valueFromText can be used to
customize the default behavior.
\snippet qtquickcontrols-spinbox-textual.qml 1
A prefix and suffix can be added using regular expressions:
\snippet qtquickcontrols-spinbox-prefix.qml 1
\sa Tumbler, {Customizing SpinBox}, {Focus Management in Qt Quick Controls}
*/
/*!
\since QtQuick.Controls 2.2 (Qt 5.9)
\include qquickspinbox.qdocinc {valueModified} {SpinBox}
*/
class QQuickSpinBoxPrivate
: public QQuickAbstractSpinBox<QQuickSpinBox, int>::QQuickAbstractSpinBoxPrivate
{
Q_DECLARE_PUBLIC(QQuickSpinBox)
public:
QQuickSpinBoxPrivate();
bool setValue(int newValue, bool wrap, ValueStatus modified) override;
void updateValue() override;
void updateDisplayText() override;
void contentItemTextChanged();
QString evaluateTextFromValue(int val) const;
int evaluateValueFromText(const QString &text) const;
bool live = false;
private:
friend class QQuickAbstractSpinBox<QQuickSpinBox, int>::QQuickAbstractSpinBoxPrivate;
};
QQuickSpinBoxPrivate::QQuickSpinBoxPrivate()
: QQuickAbstractSpinBox<QQuickSpinBox, int>::QQuickAbstractSpinBoxPrivate()
{
from = 0;
to = 99;
}
// modified indicates if the value was modified by the user and not programatically
// this is then passed on to updateDisplayText to indicate that the user has modified
// the value so it may need to trigger an update of the contentItem's text too
bool QQuickSpinBoxPrivate::setValue(int newValue, bool allowWrap, ValueStatus modified)
{
Q_Q(QQuickSpinBox);
int correctedValue = newValue;
if (q->isComponentComplete())
correctedValue = boundValue(newValue, allowWrap);
if (modified == ValueStatus::Unmodified && newValue == correctedValue && newValue == value)
return false;
const bool emitSignals = (value != correctedValue);
value = correctedValue;
updateDisplayText();
updateUpEnabled();
updateDownEnabled();
// Only emit the signals if the corrected value is not the same as the
// original value to avoid unnecessary updates
if (emitSignals) {
emit q->valueChanged();
if (modified == ValueStatus::Modified)
emit q->valueModified();
}
return true;
}
void QQuickSpinBoxPrivate::updateValue()
{
if (!contentItem)
return;
const QVariant text = contentItem->property("text");
if (text.isValid())
setValue(evaluateValueFromText(text.toString()), false /* wrap */, ValueStatus::Modified);
}
void QQuickSpinBoxPrivate::updateDisplayText()
{
setDisplayText(evaluateTextFromValue(value));
}
void QQuickSpinBoxPrivate::contentItemTextChanged()
{
Q_Q(QQuickSpinBox);
QQuickTextInput *inputTextItem = qobject_cast<QQuickTextInput *>(q->contentItem());
if (!inputTextItem)
return;
QString text = inputTextItem->text();
#if QT_CONFIG(validator)
if (validator && live)
validator->fixup(text);
#endif
if (live) {
const int enteredVal = evaluateValueFromText(text);
const int correctedValue = boundValue(enteredVal, false);
if (correctedValue == enteredVal && correctedValue != value) {
// If live is true and the text is valid change the value
// setValue will set the displayText for us.
q->setValue(correctedValue);
return;
}
}
// If live is false or the value is not valid, just set the displayText
setDisplayText(text);
}
QString QQuickSpinBoxPrivate::evaluateTextFromValue(int val) const
{
Q_Q(const QQuickSpinBox);
QString text;
QQmlEngine *engine = qmlEngine(q);
if (engine && textFromValue.isCallable()) {
QJSValue loc;
#if QT_CONFIG(qml_locale)
loc = QJSValuePrivate::fromReturnedValue(
engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale));
#endif
text = textFromValue.call(QJSValueList() << val << loc).toString();
} else {
text = locale.toString(val);
}
return text;
}
int QQuickSpinBoxPrivate::evaluateValueFromText(const QString &text) const
{
Q_Q(const QQuickSpinBox);
int value;
QQmlEngine *engine = qmlEngine(q);
if (engine && valueFromText.isCallable()) {
QJSValue loc;
#if QT_CONFIG(qml_locale)
loc = QJSValuePrivate::fromReturnedValue(
engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale));
#endif
value = valueFromText.call(QJSValueList() << text << loc).toInt();
} else {
value = locale.toInt(text);
}
return value;
}
QQuickSpinBox::QQuickSpinBox(QQuickItem *parent)
: QQuickControl(*(new QQuickSpinBoxPrivate), parent),
QQuickAbstractSpinBox<QQuickSpinBox, int>()
{
}
QQuickSpinBox::~QQuickSpinBox()
{
}
/*!
\include qquickspinbox.qdocinc {from} {SpinBox} {0}
*/
void QQuickSpinBox::setFrom(int from)
{
Q_D(QQuickSpinBox);
if (d->from == from)
return;
d->from = from;
emit fromChanged();
if (isComponentComplete()) {
if (!d->setValue(d->value,
/* allowWrap = */ false, QQuickSpinBoxPrivate::ValueStatus::Unmodified)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
}
}
/*!
\include qquickspinbox.qdocinc {to} {SpinBox} {99}
*/
void QQuickSpinBox::setTo(int to)
{
Q_D(QQuickSpinBox);
if (d->to == to)
return;
d->to = to;
emit toChanged();
if (isComponentComplete()) {
if (!d->setValue(d->value,
/* allowWrap = */ false, QQuickSpinBoxPrivate::ValueStatus::Unmodified)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
}
}
/*!
\include qquickspinbox.qdocinc {value-prop} {int} {SpinBox} {0}
*/
void QQuickSpinBox::setValue(int value)
{
Q_D(QQuickSpinBox);
d->setValue(value, false /* wrap */, QQuickSpinBoxPrivate::ValueStatus::Unmodified);
}
/*!
\include qquickspinbox.qdocinc {stepSize} {SpinBox} {1}
*/
void QQuickSpinBox::setStepSize(int step)
{
Q_D(QQuickSpinBox);
if (d->stepSize == step)
return;
d->stepSize = step;
emit stepSizeChanged();
}
/*!
\include qquickspinbox.qdocinc {editable} {SpinBox}
*/
/*!
\qmlproperty bool QtQuick.Controls::SpinBox::live
\since 6.6
This property holds whether the \l value is updated when the user edits the
\l displayText. The default value is \c false. If this property is \c true and
the value entered by the user is valid and within the bounds of the spinbox
[\l from, \l to], the value of the SpinBox will be set. If this property is
\c false or the value entered by the user is outside the boundaries, the
value will not be updated until the enter or return keys are pressed, or the
input field loses focus.
\sa editable, displayText
*/
bool QQuickSpinBox::isLive() const
{
Q_D(const QQuickSpinBox);
return d->live;
}
void QQuickSpinBox::setLive(bool live)
{
Q_D(QQuickSpinBox);
if (d->live == live)
return;
d->live = live;
//make sure to update the value when changing to live
if (live)
d->contentItemTextChanged();
emit liveChanged();
}
#if QT_CONFIG(validator)
/*!
\qmlproperty Validator QtQuick.Controls::SpinBox::validator
This property holds the input text validator for editable spinboxes. By
default, SpinBox uses \l IntValidator to accept input of integer numbers.
\code
SpinBox {
id: control
validator: IntValidator {
locale: control.locale.name
bottom: Math.min(control.from, control.to)
top: Math.max(control.from, control.to)
}
}
\endcode
\sa editable, textFromValue, valueFromText, {Control::locale}{locale},
{Validating Input Text}
*/
#endif
/*!
\qmlproperty function QtQuick.Controls::SpinBox::textFromValue
This property holds a callback function that is called whenever
an integer value needs to be converted to display text.
The default function can be overridden to display custom text for a given
value. This applies to both editable and non-editable spinboxes;
for example, when using the up and down buttons or a mouse wheel to
increment and decrement the value, the new value is converted to display
text using this function.
The callback function signature is \c {string function(value, locale)}.
The function can have one or two arguments, where the first argument
is the value to be converted, and the optional second argument is the
locale that should be used for the conversion, if applicable.
The default implementation does the conversion using
\l {string Number::toLocaleString(locale, format, precision)}{Number.toLocaleString}():
\code
textFromValue: function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }
\endcode
\note When applying a custom \c textFromValue implementation for editable
spinboxes, a matching \l valueFromText implementation must be provided
to be able to convert the custom text back to an integer value.
\sa valueFromText, validator, {Control::locale}{locale}
*/
QJSValue QQuickSpinBox::textFromValue() const
{
Q_D(const QQuickSpinBox);
if (!d->textFromValue.isCallable()) {
QQmlEngine *engine = qmlEngine(this);
if (engine)
d->textFromValue = engine->evaluate(QStringLiteral("(function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); })"));
}
return d->textFromValue;
}
/*!
\qmlproperty function QtQuick.Controls::SpinBox::valueFromText
This property holds a callback function that is called whenever
input text needs to be converted to an integer value.
This function only needs to be overridden when \l textFromValue
is overridden for an editable spinbox.
The callback function signature is \c {int function(text, locale)}.
The function can have one or two arguments, where the first argument
is the text to be converted, and the optional second argument is the
locale that should be used for the conversion, if applicable.
The default implementation does the conversion using \l {QtQml::Locale}{Number.fromLocaleString()}:
\code
valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text); }
\endcode
\note When applying a custom \l textFromValue implementation for editable
spinboxes, a matching \c valueFromText implementation must be provided
to be able to convert the custom text back to an integer value.
\sa textFromValue, validator, {Control::locale}{locale}
*/
QJSValue QQuickSpinBox::valueFromText() const
{
Q_D(const QQuickSpinBox);
if (!d->valueFromText.isCallable()) {
QQmlEngine *engine = qmlEngine(this);
if (engine)
d->valueFromText = engine->evaluate(QStringLiteral("(function(text, locale) { return Number.fromLocaleString(locale, text); })"));
}
return d->valueFromText;
}
/*!
\include qquickindicatorbutton.qdocinc {properties} {SpinBox} {up}
The \c up.hovered property was introduced in \l{QtQuick.Controls} 2.1,
and the \c up.implicitIndicatorWidth and \c up.implicitIndicatorHeight
properties were introduced in \l{QtQuick.Controls} 2.5.
\sa increase()
*/
/*!
\include qquickindicatorbutton.qdocinc {properties} {SpinBox} {down}
The \c down.hovered property was introduced in \l{QtQuick.Controls} 2.1,
and the \c down.implicitIndicatorWidth and \c down.implicitIndicatorHeight
properties were introduced in \l{QtQuick.Controls} 2.5.
\sa decrease()
*/
/*!
\since QtQuick.Controls 2.2 (Qt 5.9)
\include qquickspinbox.qdocinc {inputMethodHints} {SpinBox}
*/
/*!
\since QtQuick.Controls 2.2 (Qt 5.9)
\include qquickspinbox.qdocinc {inputMethodComposing} {SpinBox}
*/
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\include qquickspinbox.qdocinc {wrap} {SpinBox}
*/
void QQuickSpinBox::setWrap(bool wrap)
{
Q_D(QQuickSpinBox);
if (d->wrap == wrap)
return;
d->wrap = wrap;
if (d->value == d->from || d->value == d->to) {
d->updateUpEnabled();
d->updateDownEnabled();
}
emit wrapChanged();
}
/*!
\since QtQuick.Controls 2.4 (Qt 5.11)
\qmlproperty string QtQuick.Controls::SpinBox::displayText
\readonly
This property holds the textual value of the spinbox.
The value of the property is based on \l textFromValue and \l {Control::}
{locale}, and equal to:
\badcode
var text = spinBox.textFromValue(spinBox.value, spinBox.locale)
\endcode
\sa textFromValue
*/
/*!
\include qquickspinbox.qdocinc {increase} {SpinBox}
*/
/*!
\include qquickspinbox.qdocinc {decrease} {SpinBox}
*/
void QQuickSpinBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
Q_D(QQuickSpinBox);
if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem)) {
disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickSpinBoxPrivate::contentItemTextChanged);
}
if (newItem) {
newItem->setActiveFocusOnTab(true);
if (d->activeFocus)
newItem->forceActiveFocus(static_cast<Qt::FocusReason>(d->focusReason));
#if QT_CONFIG(cursor)
if (d->editable)
newItem->setCursor(Qt::IBeamCursor);
#endif
if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) {
connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickSpinBoxPrivate::contentItemTextChanged);
}
}
}
QQuickControlPrivate *QQuickSpinBox::d_base_func()
{
Q_D(QQuickSpinBox);
return d;
}
const QQuickControlPrivate *QQuickSpinBox::d_base_func() const
{
Q_D(const QQuickSpinBox);
return d;
}
QT_END_NAMESPACE
#include "moc_qquickspinbox_p.cpp"