From 3d6f502bcc4bae477eb3f8d51aa7b90a6c9e9f46 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 25 Oct 2019 13:20:05 +0200 Subject: [PATCH] Incubate delegates asynchronously --- resources/qml/TimelineView.qml | 2 +- src/timeline2/DelegateChooser.cpp | 35 ++++++++++++++++++++++++------- src/timeline2/DelegateChooser.h | 15 ++++++++++++- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 4e379567..046f7800 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -29,7 +29,7 @@ Rectangle { ListView { id: chat - cacheBuffer: parent.height + cacheBuffer: 2000 visible: timelineManager.timeline != null anchors.fill: parent diff --git a/src/timeline2/DelegateChooser.cpp b/src/timeline2/DelegateChooser.cpp index b86fc6cc..e558da61 100644 --- a/src/timeline2/DelegateChooser.cpp +++ b/src/timeline2/DelegateChooser.cpp @@ -95,17 +95,11 @@ DelegateChooser::recalcChild() auto choiceValue = choice->roleValue(); if (!roleValue_.isValid() || !choiceValue.isValid() || choiceValue == roleValue_) { if (child) { - // delete child; + child->setParentItem(nullptr); child = nullptr; } - child = dynamic_cast( - choice->delegate()->create(QQmlEngine::contextForObject(this))); - child->setParentItem(this); - connect(this->child, &QQuickItem::heightChanged, this, [this]() { - this->setHeight(this->child->height()); - }); - this->setHeight(this->child->height()); + choice->delegate()->create(incubator, QQmlEngine::contextForObject(this)); return; } } @@ -118,3 +112,28 @@ DelegateChooser::componentComplete() recalcChild(); } +void +DelegateChooser::DelegateIncubator::statusChanged(QQmlIncubator::Status status) +{ + if (status == QQmlIncubator::Ready) { + chooser.child = dynamic_cast(object()); + if (chooser.child == nullptr) { + nhlog::ui()->error("Delegate has to be derived of Item!"); + delete chooser.child; + return; + } + + chooser.child->setParentItem(&chooser); + connect(chooser.child, &QQuickItem::heightChanged, &chooser, [this]() { + chooser.setHeight(chooser.child->height()); + }); + chooser.setHeight(chooser.child->height()); + QQmlEngine::setObjectOwnership(chooser.child, + QQmlEngine::ObjectOwnership::JavaScriptOwnership); + + } else if (status == QQmlIncubator::Error) { + for (const auto &e : errors()) + nhlog::ui()->error("Error instantiating delegate: {}", + e.toString().toStdString()); + } +} diff --git a/src/timeline2/DelegateChooser.h b/src/timeline2/DelegateChooser.h index 7350e0d3..a20a1489 100644 --- a/src/timeline2/DelegateChooser.h +++ b/src/timeline2/DelegateChooser.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -59,9 +60,21 @@ signals: void roleValueChanged(); private: + struct DelegateIncubator : public QQmlIncubator + { + DelegateIncubator(DelegateChooser &parent) + : QQmlIncubator(QQmlIncubator::AsynchronousIfNested) + , chooser(parent) + {} + void statusChanged(QQmlIncubator::Status status) override; + + DelegateChooser &chooser; + }; + QVariant roleValue_; QList choices_; - QQuickItem *child; + QQuickItem *child = nullptr; + DelegateIncubator incubator{*this}; static void appendChoice(QQmlListProperty *, DelegateChoice *); static int choiceCount(QQmlListProperty *);