fix: remove unnecessary qml context creation
This commit is contained in:
parent
9145f83639
commit
cc54d9bc5b
2 changed files with 37 additions and 68 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
#include "lazylistview.hpp"
|
#include "lazylistview.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <qqmlcontext.h>
|
||||||
#include <qtimer.h>
|
#include <qtimer.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
@ -572,57 +573,43 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
const auto roleNames = m_model->roleNames();
|
const auto roleNames = m_model->roleNames();
|
||||||
const auto role = roleNames.isEmpty() ? Qt::DisplayRole : roleNames.constBegin().key();
|
|
||||||
|
|
||||||
// Use the delegate component's creation context directly for beginCreate
|
// Use the delegate component's creation context for beginCreate
|
||||||
// so bound components (pragma ComponentBehavior: Bound) are accepted.
|
// so bound components (pragma ComponentBehavior: Bound) are accepted.
|
||||||
// A per-delegate child context is kept for data updates.
|
|
||||||
auto* compContext = m_delegate->creationContext();
|
auto* compContext = m_delegate->creationContext();
|
||||||
auto* parentContext = compContext ? compContext : qmlContext(this);
|
if (!compContext)
|
||||||
if (!parentContext)
|
compContext = qmlContext(this);
|
||||||
|
if (!compContext)
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
entry.context = new QQmlContext(parentContext, this);
|
auto* obj = m_delegate->beginCreate(compContext);
|
||||||
|
|
||||||
// Build property map for both context properties and initial properties
|
|
||||||
const auto index = m_model->index(modelIndex, 0);
|
|
||||||
QVariantMap initialProps;
|
|
||||||
|
|
||||||
bool hasModelData = false;
|
|
||||||
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
|
||||||
const auto name = QString::fromUtf8(it.value());
|
|
||||||
const auto value = m_model->data(index, it.key());
|
|
||||||
entry.context->setContextProperty(name, value);
|
|
||||||
initialProps.insert(name, value);
|
|
||||||
if (name == QStringLiteral("modelData"))
|
|
||||||
hasModelData = true;
|
|
||||||
}
|
|
||||||
entry.context->setContextProperty(QStringLiteral("index"), modelIndex);
|
|
||||||
initialProps.insert(QStringLiteral("index"), modelIndex);
|
|
||||||
|
|
||||||
// Provide modelData for single-role models or if not already provided by role names
|
|
||||||
if (!hasModelData) {
|
|
||||||
const auto value = m_model->data(index, role);
|
|
||||||
entry.context->setContextProperty(QStringLiteral("modelData"), value);
|
|
||||||
initialProps.insert(QStringLiteral("modelData"), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the creation context for beginCreate to satisfy bound component checks
|
|
||||||
// (pragma ComponentBehavior: Bound). Data is passed via setInitialProperties.
|
|
||||||
auto* creationCtx = compContext ? compContext : parentContext;
|
|
||||||
auto* obj = m_delegate->beginCreate(creationCtx);
|
|
||||||
entry.item = qobject_cast<QQuickItem*>(obj);
|
entry.item = qobject_cast<QQuickItem*>(obj);
|
||||||
|
|
||||||
if (!entry.item) {
|
if (!entry.item) {
|
||||||
if (obj)
|
if (obj)
|
||||||
m_delegate->completeCreate();
|
m_delegate->completeCreate();
|
||||||
delete obj;
|
delete obj;
|
||||||
delete entry.context;
|
|
||||||
entry.context = nullptr;
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set initial properties to satisfy required property declarations
|
// Build initial properties from model data
|
||||||
|
const auto index = m_model->index(modelIndex, 0);
|
||||||
|
QVariantMap initialProps;
|
||||||
|
bool hasModelData = false;
|
||||||
|
|
||||||
|
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
||||||
|
const auto name = QString::fromUtf8(it.value());
|
||||||
|
initialProps.insert(name, m_model->data(index, it.key()));
|
||||||
|
if (name == QStringLiteral("modelData"))
|
||||||
|
hasModelData = true;
|
||||||
|
}
|
||||||
|
initialProps.insert(QStringLiteral("index"), modelIndex);
|
||||||
|
|
||||||
|
if (!hasModelData) {
|
||||||
|
const auto role = roleNames.isEmpty() ? Qt::DisplayRole : roleNames.constBegin().key();
|
||||||
|
initialProps.insert(QStringLiteral("modelData"), m_model->data(index, role));
|
||||||
|
}
|
||||||
|
|
||||||
m_delegate->setInitialProperties(entry.item, initialProps);
|
m_delegate->setInitialProperties(entry.item, initialProps);
|
||||||
|
|
||||||
entry.item->setParentItem(this);
|
entry.item->setParentItem(this);
|
||||||
|
|
@ -706,14 +693,10 @@ void LazyListView::destroyDelegate(DelegateEntry& entry) {
|
||||||
entry.item->deleteLater();
|
entry.item->deleteLater();
|
||||||
entry.item = nullptr;
|
entry.item = nullptr;
|
||||||
}
|
}
|
||||||
if (entry.context) {
|
|
||||||
entry.context->deleteLater();
|
|
||||||
entry.context = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
||||||
if (!m_model)
|
if (!m_model || !entry.item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto roleNames = m_model->roleNames();
|
const auto roleNames = m_model->roleNames();
|
||||||
|
|
@ -722,27 +705,16 @@ void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
||||||
|
|
||||||
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
||||||
const auto name = QString::fromUtf8(it.value());
|
const auto name = QString::fromUtf8(it.value());
|
||||||
const auto value = m_model->data(index, it.key());
|
entry.item->setProperty(name.toUtf8().constData(), m_model->data(index, it.key()));
|
||||||
if (entry.context)
|
|
||||||
entry.context->setContextProperty(name, value);
|
|
||||||
if (entry.item)
|
|
||||||
entry.item->setProperty(name.toUtf8().constData(), value);
|
|
||||||
if (name == QStringLiteral("modelData"))
|
if (name == QStringLiteral("modelData"))
|
||||||
hasModelData = true;
|
hasModelData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.context)
|
|
||||||
entry.context->setContextProperty(QStringLiteral("index"), entry.modelIndex);
|
|
||||||
if (entry.item)
|
|
||||||
entry.item->setProperty("index", entry.modelIndex);
|
entry.item->setProperty("index", entry.modelIndex);
|
||||||
|
|
||||||
if (!hasModelData) {
|
if (!hasModelData) {
|
||||||
const auto role = roleNames.isEmpty() ? Qt::DisplayRole : roleNames.constBegin().key();
|
const auto role = roleNames.isEmpty() ? Qt::DisplayRole : roleNames.constBegin().key();
|
||||||
const auto value = m_model->data(index, role);
|
entry.item->setProperty("modelData", m_model->data(index, role));
|
||||||
if (entry.context)
|
|
||||||
entry.context->setContextProperty(QStringLiteral("modelData"), value);
|
|
||||||
if (entry.item)
|
|
||||||
entry.item->setProperty("modelData", value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -824,10 +796,10 @@ void LazyListView::onRowsInserted(const QModelIndex& parent, int first, int last
|
||||||
int newIdx = it.key() >= first ? it.key() + insertCount : it.key();
|
int newIdx = it.key() >= first ? it.key() + insertCount : it.key();
|
||||||
auto entry = std::move(it.value());
|
auto entry = std::move(it.value());
|
||||||
entry.modelIndex = newIdx;
|
entry.modelIndex = newIdx;
|
||||||
if (entry.context)
|
if (entry.item) {
|
||||||
entry.context->setContextProperty(QStringLiteral("index"), newIdx);
|
entry.item->setProperty("index", newIdx);
|
||||||
if (entry.item)
|
|
||||||
m_itemToIndex[entry.item] = newIdx;
|
m_itemToIndex[entry.item] = newIdx;
|
||||||
|
}
|
||||||
shifted.insert(newIdx, std::move(entry));
|
shifted.insert(newIdx, std::move(entry));
|
||||||
}
|
}
|
||||||
m_delegates = std::move(shifted);
|
m_delegates = std::move(shifted);
|
||||||
|
|
@ -894,10 +866,10 @@ void LazyListView::onRowsRemoved(const QModelIndex& parent, int first, int last)
|
||||||
int newIdx = it.key() > last ? it.key() - removeCount : it.key();
|
int newIdx = it.key() > last ? it.key() - removeCount : it.key();
|
||||||
auto entry = std::move(it.value());
|
auto entry = std::move(it.value());
|
||||||
entry.modelIndex = newIdx;
|
entry.modelIndex = newIdx;
|
||||||
if (entry.context)
|
if (entry.item) {
|
||||||
entry.context->setContextProperty(QStringLiteral("index"), newIdx);
|
entry.item->setProperty("index", newIdx);
|
||||||
if (entry.item)
|
|
||||||
m_itemToIndex[entry.item] = newIdx;
|
m_itemToIndex[entry.item] = newIdx;
|
||||||
|
}
|
||||||
shifted.insert(newIdx, std::move(entry));
|
shifted.insert(newIdx, std::move(entry));
|
||||||
}
|
}
|
||||||
m_delegates = std::move(shifted);
|
m_delegates = std::move(shifted);
|
||||||
|
|
@ -939,10 +911,10 @@ void LazyListView::onRowsMoved(const QModelIndex& parent, int start, int end, co
|
||||||
|
|
||||||
auto entry = std::move(it.value());
|
auto entry = std::move(it.value());
|
||||||
entry.modelIndex = newIdx;
|
entry.modelIndex = newIdx;
|
||||||
if (entry.context)
|
if (entry.item) {
|
||||||
entry.context->setContextProperty(QStringLiteral("index"), newIdx);
|
entry.item->setProperty("index", newIdx);
|
||||||
if (entry.item)
|
|
||||||
m_itemToIndex[entry.item] = newIdx;
|
m_itemToIndex[entry.item] = newIdx;
|
||||||
|
}
|
||||||
remapped.insert(newIdx, std::move(entry));
|
remapped.insert(newIdx, std::move(entry));
|
||||||
}
|
}
|
||||||
m_delegates = std::move(remapped);
|
m_delegates = std::move(remapped);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include <qhash.h>
|
#include <qhash.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlcomponent.h>
|
#include <qqmlcomponent.h>
|
||||||
#include <qqmlcontext.h>
|
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qquickitem.h>
|
#include <qquickitem.h>
|
||||||
#include <qrect.h>
|
#include <qrect.h>
|
||||||
|
|
@ -164,7 +163,6 @@ private:
|
||||||
struct DelegateEntry {
|
struct DelegateEntry {
|
||||||
int modelIndex = -1;
|
int modelIndex = -1;
|
||||||
QQuickItem* item = nullptr;
|
QQuickItem* item = nullptr;
|
||||||
QQmlContext* context = nullptr;
|
|
||||||
bool pendingRemoval = false;
|
bool pendingRemoval = false;
|
||||||
QMetaObject::Connection attachedConnection;
|
QMetaObject::Connection attachedConnection;
|
||||||
};
|
};
|
||||||
|
|
@ -196,7 +194,6 @@ private:
|
||||||
void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QList<int>& roles);
|
void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QList<int>& roles);
|
||||||
void onModelReset();
|
void onModelReset();
|
||||||
|
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
QAbstractItemModel* m_model = nullptr;
|
QAbstractItemModel* m_model = nullptr;
|
||||||
QQmlComponent* m_delegate = nullptr;
|
QQmlComponent* m_delegate = nullptr;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue