Files
RedBear-OS/local/recipes/qt/qtdeclarative/source/src/quick/util/qquickstate.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

671 lines
20 KiB
C++

// Copyright (C) 2016 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 "qquickstate_p_p.h"
#include "qquickstate_p.h"
#include "qquickstategroup_p.h"
#include "qquickstatechangescript_p.h"
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcStates, "qt.qml.states")
QQuickStateAction::QQuickStateAction()
: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(nullptr), event(nullptr),
specifiedObject(nullptr)
{
}
QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyName,
const QVariant &value)
: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
property(target, propertyName, qmlEngine(target)), toValue(value),
fromBinding(nullptr), event(nullptr),
specifiedObject(target), specifiedProperty(propertyName)
{
if (property.isValid())
fromValue = property.read();
}
QQuickStateAction::QQuickStateAction(QObject *target, const QQmlProperty &property, const QString &propertyName, const QVariant &value)
: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
property(property), toValue(value),
fromBinding(nullptr), event(nullptr),
specifiedObject(target), specifiedProperty(propertyName)
{
if (property.isValid())
fromValue = property.read();
}
QQuickStateActionEvent::~QQuickStateActionEvent()
{
}
void QQuickStateActionEvent::execute()
{
}
bool QQuickStateActionEvent::isReversable()
{
return false;
}
void QQuickStateActionEvent::reverse()
{
}
bool QQuickStateActionEvent::changesBindings()
{
return false;
}
void QQuickStateActionEvent::clearBindings()
{
}
bool QQuickStateActionEvent::mayOverride(QQuickStateActionEvent *other)
{
Q_UNUSED(other);
return false;
}
QQuickStateOperation::QQuickStateOperation(QObjectPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
}
/*!
\qmltype State
\nativetype QQuickState
\inqmlmodule QtQuick
\ingroup qtquick-states
\brief Defines configurations of objects and properties.
A \e state is a set of batched changes from the default configuration.
All items have a default state that defines the default configuration of objects
and property values. New states can be defined by adding State items to the \l {Item::states}{states} property to
allow items to switch between different configurations. These configurations
can, for example, be used to apply different sets of property values or execute
different scripts.
The following example displays a single \l Rectangle. In the default state, the rectangle
is colored black. In the "clicked" state, a PropertyChanges object changes the
rectangle's color to red. Clicking within the MouseArea toggles the rectangle's state
between the default state and the "clicked" state, thus toggling the color of the
rectangle between black and red.
\snippet qml/state.qml 0
Notice the default state is referred to using an empty string ("").
States are commonly used together with \l{Animation and Transitions in Qt Quick}{Transitions} to provide
animations when state changes occur.
\note Setting the state of an object from within another state of the same object is
not allowed.
\sa {Qt Quick Examples - Animation#States}{States example}, {Qt Quick States},
{Animation and Transitions in Qt Quick}{Transitions}, {Qt Qml}
*/
QQuickState::QQuickState(QObject *parent)
: QObject(*(new QQuickStatePrivate), parent)
{
Q_D(QQuickState);
d->transitionManager.setState(this);
}
QQuickState::~QQuickState()
{
Q_D(QQuickState);
if (d->group)
d->group->removeState(this);
}
/*!
\qmlproperty string QtQuick::State::name
This property holds the name of the state.
Each state should have a unique name within its item.
*/
QString QQuickState::name() const
{
Q_D(const QQuickState);
return d->name;
}
void QQuickState::setName(const QString &n)
{
Q_D(QQuickState);
d->name = n;
d->named = true;
}
bool QQuickState::isNamed() const
{
Q_D(const QQuickState);
return d->named;
}
bool QQuickState::isWhenKnown() const
{
Q_D(const QQuickState);
return d->whenKnown;
}
/*!
\qmlproperty bool QtQuick::State::when
This property holds when the state should be applied.
This should be set to an expression that evaluates to \c true when you want the state to
be applied. For example, the following \l Rectangle changes in and out of the "hidden"
state when the \l MouseArea is pressed:
\snippet qml/state-when.qml 0
If multiple states in a group have \c when clauses that evaluate to \c true
at the same time, the first matching state will be applied. For example, in
the following snippet \c state1 will always be selected rather than
\c state2 when sharedCondition becomes \c true.
\qml
Item {
states: [
State { name: "state1"; when: sharedCondition },
State { name: "state2"; when: sharedCondition }
]
// ...
}
\endqml
*/
bool QQuickState::when() const
{
Q_D(const QQuickState);
return d->when;
}
void QQuickState::setWhen(bool when)
{
Q_D(QQuickState);
d->whenKnown = true;
d->when = when;
if (d->group)
d->group->updateAutoState();
}
/*!
\qmlproperty string QtQuick::State::extend
This property holds the state that this state extends.
When a state extends another state, it inherits all the changes of that state.
The state being extended is treated as the base state in regards to
the changes specified by the extending state.
*/
QString QQuickState::extends() const
{
Q_D(const QQuickState);
return d->extends;
}
void QQuickState::setExtends(const QString &extends)
{
Q_D(QQuickState);
d->extends = extends;
}
/*!
\qmlproperty list<Change> QtQuick::State::changes
This property holds the changes to apply for this state
\qmldefault
By default these changes are applied against the default state. If the state
extends another state, then the changes are applied against the state being
extended.
*/
QQmlListProperty<QQuickStateOperation> QQuickState::changes()
{
Q_D(QQuickState);
return QQmlListProperty<QQuickStateOperation>(this, &d->operations,
QQuickStatePrivate::operations_append,
QQuickStatePrivate::operations_count,
QQuickStatePrivate::operations_at,
QQuickStatePrivate::operations_clear,
QQuickStatePrivate::operations_replace,
QQuickStatePrivate::operations_removeLast);
}
int QQuickState::operationCount() const
{
Q_D(const QQuickState);
return d->operations.size();
}
QQuickStateOperation *QQuickState::operationAt(int index) const
{
Q_D(const QQuickState);
return d->operations.at(index);
}
QQuickState &QQuickState::operator<<(QQuickStateOperation *op)
{
Q_D(QQuickState);
d->operations.append(QQuickStatePrivate::OperationGuard(op, &d->operations));
return *this;
}
void QQuickStatePrivate::complete()
{
Q_Q(QQuickState);
for (int ii = 0; ii < reverting.size(); ++ii) {
for (int jj = 0; jj < revertList.size(); ++jj) {
const QQuickRevertAction &revert = reverting.at(ii);
const QQuickSimpleAction &simple = revertList.at(jj);
if ((revert.event && simple.event() == revert.event) ||
simple.property() == revert.property) {
revertList.removeAt(jj);
break;
}
}
}
reverting.clear();
if (group)
group->stateAboutToComplete();
emit q->completed();
}
// Generate a list of actions for this state. This includes coelescing state
// actions that this state "extends"
QQuickStateOperation::ActionList
QQuickStatePrivate::generateActionList() const
{
QQuickStateOperation::ActionList applyList;
if (inState)
return applyList;
// Prevent "extends" recursion
inState = true;
if (!extends.isEmpty()) {
QList<QQuickState *> states = group ? group->states() : QList<QQuickState *>();
for (int ii = 0; ii < states.size(); ++ii)
if (states.at(ii)->name() == extends) {
qmlExecuteDeferred(states.at(ii));
applyList = static_cast<QQuickStatePrivate*>(states.at(ii)->d_func())->generateActionList();
}
}
for (QQuickStateOperation *op : operations)
applyList << op->actions();
inState = false;
return applyList;
}
QQuickStateGroup *QQuickState::stateGroup() const
{
Q_D(const QQuickState);
return d->group;
}
void QQuickState::setStateGroup(QQuickStateGroup *group)
{
Q_D(QQuickState);
d->group = group;
}
void QQuickState::cancel()
{
Q_D(QQuickState);
d->transitionManager.cancel();
}
void QQuickStateAction::deleteFromBinding()
{
if (fromBinding) {
if (fromBinding.isAbstractPropertyBinding()) {
QQmlPropertyPrivate::removeBinding(property);
fromBinding = nullptr;
}
}
}
bool QQuickState::containsPropertyInRevertList(QObject *target, const QString &name) const
{
Q_D(const QQuickState);
if (isStateActive()) {
for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return true;
}
}
return false;
}
bool QQuickState::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue)
{
Q_D(QQuickState);
if (isStateActive()) {
for (QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
simpleAction.setValue(revertValue);
return true;
}
}
}
return false;
}
bool QQuickState::changeBindingInRevertList(QObject *target, const QString &name, QQmlAnyBinding binding)
{
Q_D(QQuickState);
if (isStateActive()) {
for (QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
simpleAction.setBinding(binding);
return true;
}
}
}
return false;
}
bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name)
{
Q_D(QQuickState);
if (isStateActive()) {
for (auto it = d->revertList.begin(), end = d->revertList.end(); it != end; ++it) {
QQuickSimpleAction &simpleAction = *it;
if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (auto binding = simpleAction.binding(); binding) {
QQmlProperty prop = simpleAction.property();
binding.installOn(prop);
}
d->revertList.erase(it);
return true;
}
}
}
return false;
}
void QQuickState::addEntryToRevertList(const QQuickStateAction &action)
{
Q_D(QQuickState);
QQuickSimpleAction simpleAction(action);
d->revertList.append(simpleAction);
}
void QQuickState::removeAllEntriesFromRevertList(QObject *target)
{
Q_D(QQuickState);
if (isStateActive()) {
const auto actionMatchesTarget = [target](const QQuickSimpleAction &simpleAction) {
if (simpleAction.property().object() == target) {
QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (auto binding = simpleAction.binding()) {
QQmlProperty prop = simpleAction.property();
binding.installOn(prop);
}
return true;
}
return false;
};
d->revertList.removeIf(actionMatchesTarget);
}
}
void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionList)
{
Q_D(QQuickState);
if (isStateActive()) {
QList<QQuickSimpleAction> simpleActionList;
simpleActionList.reserve(actionList.size());
for (const QQuickStateAction &action : actionList) {
QQuickSimpleAction simpleAction(action);
action.property.write(action.toValue);
if (auto binding = action.toBinding; binding)
binding.installOn(action.property);
simpleActionList.append(simpleAction);
}
d->revertList.append(simpleActionList);
}
}
QVariant QQuickState::valueInRevertList(QObject *target, const QString &name) const
{
Q_D(const QQuickState);
if (isStateActive()) {
for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return simpleAction.value();
}
}
return QVariant();
}
QQmlAnyBinding QQuickState::bindingInRevertList(QObject *target, const QString &name) const
{
Q_D(const QQuickState);
if (isStateActive()) {
for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return simpleAction.binding();
}
}
return nullptr;
}
bool QQuickState::isStateActive() const
{
return stateGroup() && stateGroup()->state() == name();
}
void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
{
Q_D(QQuickState);
qmlExecuteDeferred(this);
cancel();
if (revert)
revert->cancel();
d->revertList.clear();
d->reverting.clear();
if (revert) {
QQuickStatePrivate *revertPrivate =
static_cast<QQuickStatePrivate*>(revert->d_func());
d->revertList = revertPrivate->revertList;
revertPrivate->revertList.clear();
}
// List of actions caused by this state
QQuickStateOperation::ActionList applyList = d->generateActionList();
// List of actions that need to be reverted to roll back (just) this state
QQuickStatePrivate::SimpleActionList additionalReverts;
// First add the reverse of all the applyList actions
for (int ii = 0; ii < applyList.size(); ++ii) {
QQuickStateAction &action = applyList[ii];
if (action.event) {
if (!action.event->isReversable())
continue;
bool found = false;
for (int jj = 0; jj < d->revertList.size(); ++jj) {
QQuickStateActionEvent *event = d->revertList.at(jj).event();
if (event && event->type() == action.event->type()) {
if (action.event->mayOverride(event)) {
found = true;
if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
action.event->copyOriginals(d->revertList.at(jj).event());
QQuickSimpleAction r(action);
additionalReverts << r;
d->revertList.removeAt(jj);
--jj;
} else if (action.event->isRewindable()) //###why needed?
action.event->saveCurrentValues();
break;
}
}
}
if (!found) {
action.event->saveOriginals();
// Only need to revert the applyList action if the previous
// state doesn't have a higher priority revert already
QQuickSimpleAction r(action);
additionalReverts << r;
}
} else {
bool found = false;
action.fromBinding = QQmlAnyBinding::ofProperty(action.property);
for (int jj = 0; jj < d->revertList.size(); ++jj) {
if (d->revertList.at(jj).property() == action.property) {
found = true;
if (d->revertList.at(jj).binding() != action.fromBinding) {
action.deleteFromBinding();
}
break;
}
}
if (!found) {
if (!action.restore) {
action.deleteFromBinding();;
} else {
// Only need to revert the applyList action if the previous
// state doesn't have a higher priority revert already
QQuickSimpleAction r(action);
additionalReverts << r;
}
}
}
}
// Any reverts from a previous state that aren't carried forth
// into this state need to be translated into apply actions
for (int ii = 0; ii < d->revertList.size(); ++ii) {
bool found = false;
if (d->revertList.at(ii).event()) {
QQuickStateActionEvent *event = d->revertList.at(ii).event();
if (!event->isReversable())
continue;
for (int jj = 0; !found && jj < applyList.size(); ++jj) {
const QQuickStateAction &action = applyList.at(jj);
if (action.event && action.event->type() == event->type()) {
if (action.event->mayOverride(event))
found = true;
}
}
} else {
for (int jj = 0; !found && jj < applyList.size(); ++jj) {
const QQuickStateAction &action = applyList.at(jj);
if (action.property == d->revertList.at(ii).property())
found = true;
}
}
if (!found) {
// If revert list contains bindings assigned to deleted objects, we need to
// prevent reverting properties of those objects.
if (d->revertList.at(ii).binding() && !d->revertList.at(ii).property().object()) {
continue;
}
QVariant cur = d->revertList.at(ii).property().read();
QQmlProperty prop = d->revertList.at(ii).property();
QQmlAnyBinding::removeBindingFrom(prop);
QQuickStateAction a;
a.property = d->revertList.at(ii).property();
a.fromValue = cur;
a.toValue = d->revertList.at(ii).value();
a.toBinding = d->revertList.at(ii).binding();
a.specifiedObject = d->revertList.at(ii).specifiedObject();
a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
a.event = d->revertList.at(ii).event();
a.reverseEvent = d->revertList.at(ii).reverseEvent();
if (a.event && a.event->isRewindable())
a.event->saveCurrentValues();
applyList << a;
// Store these special reverts in the reverting list
if (a.event)
d->reverting << a.event;
else
d->reverting << a.property;
}
}
// All the local reverts now become part of the ongoing revertList
d->revertList << additionalReverts;
if (lcStates().isDebugEnabled()) {
for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.event)
qCDebug(lcStates) << "QQuickStateAction event:" << action.event->type();
else
qCDebug(lcStates) << "QQuickStateAction on" << action.property.object()
<< action.property.name() << "from:" << action.fromValue
<< "to:" << action.toValue;
}
}
d->transitionManager.transition(applyList, trans);
}
QQuickStateOperation::ActionList QQuickStateOperation::actions()
{
return ActionList();
}
QQuickState *QQuickStateOperation::state() const
{
Q_D(const QQuickStateOperation);
return d->m_state;
}
void QQuickStateOperation::setState(QQuickState *state)
{
Q_D(QQuickStateOperation);
d->m_state = state;
}
QT_END_NAMESPACE
#include "moc_qquickstate_p.cpp"