Files
RedBear-OS/local/recipes/qt/qtdeclarative/source/src/qmlmodels/qqmlobjectmodel.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

497 lines
14 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
#include "qqmlobjectmodel_p.h"
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlinfo.h>
#include <private/qqmlchangeset_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qobject_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
class QQmlObjectModelPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQmlObjectModel)
public:
class Item {
public:
Item(QObject *i = nullptr) : m_item(i) {}
void addRef() { ++m_ref; }
bool deref() { return --m_ref == 0; }
int refCount() const { return m_ref; }
QObject *item() const { return m_item.data(); }
private:
QPointer<QObject> m_item;
int m_ref = 0;
};
QQmlObjectModelPrivate() : QObjectPrivate(), moveId(0) {}
static QQmlObjectModelPrivate *get(QQmlObjectModel *q) { return q->d_func(); }
static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
qsizetype index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.size();
static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
}
static qsizetype children_count(QQmlListProperty<QObject> *prop) {
return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.size();
}
static QObject *children_at(QQmlListProperty<QObject> *prop, qsizetype index) {
return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.at(index).item();
}
static void children_clear(QQmlListProperty<QObject> *prop) {
static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
}
static void children_replace(QQmlListProperty<QObject> *prop, qsizetype index, QObject *item) {
static_cast<QQmlObjectModelPrivate *>(prop->data)->replace(index, item);
}
static void children_removeLast(QQmlListProperty<QObject> *prop) {
auto data = static_cast<QQmlObjectModelPrivate *>(prop->data);
data->remove(data->children.size() - 1, 1);
}
void markNewChild(QQmlObjectModel *q, QObject *item)
{
if (QJSEngine *engine = qjsEngine(q)) {
QV4::WriteBarrier::markCustom(engine->handle(), [&](QV4::MarkStack *markStack) {
QV4::QObjectWrapper::markWrapper(item, markStack);
});
}
}
void insert(int index, QObject *item) {
Q_Q(QQmlObjectModel);
children.insert(index, Item(item));
markNewChild(q, item);
for (int i = index, end = children.size(); i < end; ++i)
setIndex(i);
QQmlChangeSet changeSet;
changeSet.insert(index, 1);
emit q->modelUpdated(changeSet, false);
emit q->countChanged();
emit q->childrenChanged();
}
void replace(int index, QObject *item) {
Q_Q(QQmlObjectModel);
clearIndex(index);
children.replace(index, Item(item));
markNewChild(q, item);
setIndex(index);
QQmlChangeSet changeSet;
changeSet.change(index, 1);
emit q->modelUpdated(changeSet, false);
emit q->childrenChanged();
}
void move(int from, int to, int n) {
Q_Q(QQmlObjectModel);
if (from > to) {
// Only move forwards - flip if backwards moving
int tfrom = from;
int tto = to;
from = tto;
to = tto+n;
n = tfrom-tto;
}
QVarLengthArray<QQmlObjectModelPrivate::Item, 4> store;
for (int i = 0; i < to - from; ++i)
store.append(std::move(children[from + n + i]));
for (int i = 0; i < n; ++i)
store.append(std::move(children[from + i]));
for (int i = 0, end = store.count(); i < end; ++i) {
children[from + i] = std::move(store[i]);
setIndex(from + i);
}
QQmlChangeSet changeSet;
changeSet.move(from, to, n, ++moveId);
emit q->modelUpdated(changeSet, false);
emit q->childrenChanged();
}
void remove(int index, int n) {
Q_Q(QQmlObjectModel);
for (int i = index; i < index + n; ++i)
clearIndex(i);
children.erase(children.begin() + index, children.begin() + index + n);
for (int i = index, end = children.size(); i < end; ++i)
setIndex(i);
QQmlChangeSet changeSet;
changeSet.remove(index, n);
emit q->modelUpdated(changeSet, false);
emit q->countChanged();
emit q->childrenChanged();
}
void clear() {
Q_Q(QQmlObjectModel);
const auto copy = children;
for (const Item &child : copy)
emit q->destroyingItem(child.item());
remove(0, children.size());
}
int indexOf(QObject *item) const {
for (int i = 0; i < children.size(); ++i)
if (children.at(i).item() == item)
return i;
return -1;
}
void markChildren(QV4::MarkStack *markStack) const
{
for (const Item &child : children)
QV4::QObjectWrapper::markWrapper(child.item(), markStack);
}
quint64 _q_createJSWrapper(QQmlV4ExecutionEnginePtr engine);
private:
void setIndex(int child, int index)
{
if (auto *attached = static_cast<QQmlObjectModelAttached *>(
qmlAttachedPropertiesObject<QQmlObjectModel>(children.at(child).item()))) {
attached->setIndex(index);
}
}
void setIndex(int child) { setIndex(child, child); }
void clearIndex(int child) { setIndex(child, -1); }
uint moveId;
QList<Item> children;
};
namespace QV4 {
namespace Heap {
struct QQmlObjectModelWrapper : public QObjectWrapper {
static void markObjects(Base *that, MarkStack *markStack)
{
Q_ASSERT(QV4::Value::fromHeapObject(that).as<QV4::QObjectWrapper>());
QObject *object = static_cast<QObjectWrapper *>(that)->object();
if (!object)
return;
Q_ASSERT(qobject_cast<QQmlObjectModel *>(object));
QQmlObjectModelPrivate::get(static_cast<QQmlObjectModel *>(object))
->markChildren(markStack);
QObjectWrapper::markObjects(that, markStack);
}
};
} // namespace Heap
struct QQmlObjectModelWrapper : public QObjectWrapper {
V4_OBJECT2(QQmlObjectModelWrapper, QObjectWrapper)
};
} // namspace QV4
DEFINE_OBJECT_VTABLE(QV4::QQmlObjectModelWrapper);
quint64 QQmlObjectModelPrivate::_q_createJSWrapper(QQmlV4ExecutionEnginePtr engine)
{
return (engine->memoryManager->allocate<QV4::QQmlObjectModelWrapper>(
q_func()))->asReturnedValue();
}
/*!
\qmltype ObjectModel
\nativetype QQmlObjectModel
\inqmlmodule QtQml.Models
\ingroup qtquick-models
\brief Defines a set of items to be used as a model.
An ObjectModel contains the visual items to be used in a view.
When an ObjectModel is used in a view, the view does not require
a delegate since the ObjectModel already contains the visual
delegate (items).
An item can determine its index within the
model via the \l{ObjectModel::index}{index} attached property.
The example below places three colored rectangles in a ListView.
\code
import QtQuick 2.0
import QtQml.Models 2.1
Rectangle {
ObjectModel {
id: itemModel
Rectangle { height: 30; width: 80; color: "red" }
Rectangle { height: 30; width: 80; color: "green" }
Rectangle { height: 30; width: 80; color: "blue" }
}
ListView {
anchors.fill: parent
model: itemModel
}
}
\endcode
\image objectmodel.png
\sa {Qt Quick Examples - Views}
*/
QQmlObjectModel::QQmlObjectModel(QObject *parent)
: QQmlInstanceModel(*(new QQmlObjectModelPrivate), parent)
{
}
QQmlObjectModel::~QQmlObjectModel() = default;
/*!
\qmlattachedproperty int QtQml.Models::ObjectModel::index
This attached property holds the index of this delegate's item within the model.
It is attached to each instance of the delegate.
*/
QQmlListProperty<QObject> QQmlObjectModel::children()
{
Q_D(QQmlObjectModel);
return QQmlListProperty<QObject>(this, d,
QQmlObjectModelPrivate::children_append,
QQmlObjectModelPrivate::children_count,
QQmlObjectModelPrivate::children_at,
QQmlObjectModelPrivate::children_clear,
QQmlObjectModelPrivate::children_replace,
QQmlObjectModelPrivate::children_removeLast);
}
/*!
\qmlproperty int QtQml.Models::ObjectModel::count
The number of items in the model. This property is readonly.
*/
int QQmlObjectModel::count() const
{
Q_D(const QQmlObjectModel);
return d->children.size();
}
bool QQmlObjectModel::isValid() const
{
return true;
}
QObject *QQmlObjectModel::object(int index, QQmlIncubator::IncubationMode)
{
Q_D(QQmlObjectModel);
QQmlObjectModelPrivate::Item &item = d->children[index];
item.addRef();
QObject *obj = item.item();
if (item.refCount() == 1) {
emit initItem(index, obj);
emit createdItem(index, obj);
}
return obj;
}
QQmlInstanceModel::ReleaseFlags QQmlObjectModel::release(QObject *item, ReusableFlag)
{
Q_D(QQmlObjectModel);
int idx = d->indexOf(item);
if (idx >= 0) {
if (!d->children[idx].deref())
return QQmlInstanceModel::Referenced;
}
return {};
}
QVariant QQmlObjectModel::variantValue(int index, const QString &role)
{
Q_D(QQmlObjectModel);
if (index < 0 || index >= d->children.size())
return QString();
if (QObject *item = d->children.at(index).item())
return item->property(role.toUtf8().constData());
return QString();
}
QQmlIncubator::Status QQmlObjectModel::incubationStatus(int)
{
return QQmlIncubator::Ready;
}
int QQmlObjectModel::indexOf(QObject *item, QObject *) const
{
Q_D(const QQmlObjectModel);
return d->indexOf(item);
}
QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
{
return new QQmlObjectModelAttached(obj);
}
/*!
\qmlmethod object QtQml.Models::ObjectModel::get(int index)
\since 5.6
Returns the item at \a index in the model. This allows the item
to be accessed or modified from JavaScript:
\code
Component.onCompleted: {
objectModel.append(objectComponent.createObject())
console.log(objectModel.get(0).objectName);
objectModel.get(0).objectName = "first";
}
\endcode
The \a index must be an element in the list.
\sa append()
*/
QObject *QQmlObjectModel::get(int index) const
{
Q_D(const QQmlObjectModel);
if (index < 0 || index >= d->children.size())
return nullptr;
return d->children.at(index).item();
}
/*!
\qmlmethod void QtQml.Models::ObjectModel::append(object item)
\since 5.6
Appends a new \a item to the end of the model.
\code
objectModel.append(objectComponent.createObject())
\endcode
\sa insert(), remove()
*/
void QQmlObjectModel::append(QObject *object)
{
Q_D(QQmlObjectModel);
d->insert(count(), object);
}
/*!
\qmlmethod void QtQml.Models::ObjectModel::insert(int index, object item)
\since 5.6
Inserts a new \a item to the model at position \a index.
\code
objectModel.insert(2, objectComponent.createObject())
\endcode
The \a index must be to an existing item in the list, or one past
the end of the list (equivalent to append).
\sa append(), remove()
*/
void QQmlObjectModel::insert(int index, QObject *object)
{
Q_D(QQmlObjectModel);
if (index < 0 || index > count()) {
qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
return;
}
d->insert(index, object);
}
/*!
\qmlmethod void QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
\since 5.6
Moves \a n items \a from one position \a to another.
The from and to ranges must exist; for example, to move the first 3 items
to the end of the model:
\code
objectModel.move(0, objectModel.count - 3, 3)
\endcode
\sa append()
*/
void QQmlObjectModel::move(int from, int to, int n)
{
Q_D(QQmlObjectModel);
if (n <= 0 || from == to)
return;
if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
qmlWarning(this) << tr("move: out of range");
return;
}
d->move(from, to, n);
}
/*!
\qmlmethod void QtQml.Models::ObjectModel::remove(int index, int n = 1)
\since 5.6
Removes \a n items at \a index from the model.
\sa clear()
*/
void QQmlObjectModel::remove(int index, int n)
{
Q_D(QQmlObjectModel);
if (index < 0 || n <= 0 || index + n > count()) {
qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
return;
}
d->remove(index, n);
}
/*!
\qmlmethod void QtQml.Models::ObjectModel::clear()
\since 5.6
Clears all items from the model.
\sa append(), remove()
*/
void QQmlObjectModel::clear()
{
Q_D(QQmlObjectModel);
d->clear();
}
bool QQmlInstanceModel::setRequiredProperty(int index, const QString &name, const QVariant &value)
{
Q_UNUSED(index);
Q_UNUSED(name);
Q_UNUSED(value);
// The view should not call this function, unless
// it's actually handled in a subclass.
Q_UNREACHABLE_RETURN(false);
}
QT_END_NAMESPACE
#include "moc_qqmlobjectmodel_p.cpp"