From 52e3f2cd5f782f77d4bdb08380672a24b5c488a2 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 9 Feb 2022 18:49:40 +0100 Subject: [PATCH] QmlDesigner: Cache last image in 3D view and add busy indicator This patch caches the last image from a document/model. The result ist that when reopening a file in the 3D editor the user sees immediately something. Since the view is not interactive, yet, we show a busy indicator until the view is fully initialized. Change-Id: I26c8b0ea69f98ceb41580624c51d48d1e633ab80 Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen Reviewed-by: Qt CI Bot --- .../qmldesigner/misc/BusyIndicator.qml | 86 +++++++++++++++++++ .../components/edit3d/edit3dcanvas.cpp | 54 +++++++++++- .../components/edit3d/edit3dcanvas.h | 8 +- .../components/edit3d/edit3dview.cpp | 14 ++- .../components/edit3d/edit3dview.h | 3 + 5 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 share/qtcreator/qmldesigner/misc/BusyIndicator.qml diff --git a/share/qtcreator/qmldesigner/misc/BusyIndicator.qml b/share/qtcreator/qmldesigner/misc/BusyIndicator.qml new file mode 100644 index 00000000000..93cf639bca7 --- /dev/null +++ b/share/qtcreator/qmldesigner/misc/BusyIndicator.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls + +BusyIndicator { + id: control + + contentItem: Item { + implicitWidth: 64 + implicitHeight: 64 + + Item { + id: item + anchors.centerIn: parent + width: 64 + height: 64 + opacity: control.running ? 1 : 0 + + Behavior on opacity { + OpacityAnimator { + duration: 250 + } + } + + RotationAnimator { + target: item + running: control.visible && control.running + from: 0 + to: 360 + loops: Animation.Infinite + duration: 2000 + } + + Repeater { + id: repeater + model: 6 + + Rectangle { + id: delegate + anchors.centerIn: parent + implicitWidth: 10 + implicitHeight: 10 + radius: 5 + color: "#2aafd3" + + required property int index + + transform: [ + Translate { + y: -Math.min(item.width, item.height) * 0.5 + 5 + }, + Rotation { + angle: delegate.index / repeater.count * 360 + origin.x: 5 + origin.y: 5 + } + ] + } + } + } + } +} diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp index 7ea74f6cbee..65e1b763e59 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp @@ -30,21 +30,43 @@ #include "nodehints.h" #include "qmlvisualnode.h" +#include + +#include + #include #include -#include +#include #include +#include +#include namespace QmlDesigner { +static QQuickWidget *createBusyIndicator(QWidget *p) +{ + auto widget = new QQuickWidget(p); + + const QString source = Core::ICore::resourcePath("qmldesigner/misc/BusyIndicator.qml").toString(); + QTC_ASSERT(QFileInfo::exists(source), return widget); + widget->setSource(QUrl::fromLocalFile(source)); + widget->setFixedSize(64, 64); + widget->setAttribute(Qt::WA_AlwaysStackOnTop); + widget->setClearColor(Qt::transparent); + widget->setResizeMode(QQuickWidget::SizeRootObjectToView); + return widget; +} + Edit3DCanvas::Edit3DCanvas(Edit3DWidget *parent) - : QWidget(parent), - m_parent(parent) + : QWidget(parent) + , m_parent(parent) + , m_busyIndicator(createBusyIndicator(this)) { setMouseTracking(true); setAcceptDrops(true); setFocusPolicy(Qt::ClickFocus); + m_busyIndicator->show(); } void Edit3DCanvas::updateRenderImage(const QImage &img) @@ -58,6 +80,21 @@ void Edit3DCanvas::updateActiveScene(qint32 activeScene) m_activeScene = activeScene; } +QImage QmlDesigner::Edit3DCanvas::renderImage() const +{ + return m_image; +} + +void Edit3DCanvas::setOpacity(qreal opacity) +{ + m_opacity = opacity; +} + +QWidget *Edit3DCanvas::busyIndicator() const +{ + return m_busyIndicator; +} + void Edit3DCanvas::mousePressEvent(QMouseEvent *e) { m_parent->view()->sendInputEvent(e); @@ -108,11 +145,17 @@ void Edit3DCanvas::paintEvent(QPaintEvent *e) QPainter painter(this); + if (m_opacity < 1.0) { + painter.fillRect(rect(), Qt::black); + painter.setOpacity(m_opacity); + } + painter.drawImage(rect(), m_image, QRect(0, 0, m_image.width(), m_image.height())); } void Edit3DCanvas::resizeEvent(QResizeEvent *e) { + positionBusyInidicator(); m_parent->view()->edit3DViewResized(e->size()); } @@ -161,4 +204,9 @@ void Edit3DCanvas::focusInEvent(QFocusEvent *focusEvent) QWidget::focusInEvent(focusEvent); } +void Edit3DCanvas::positionBusyInidicator() +{ + m_busyIndicator->move(width() / 2 - 32, height() / 2 - 32); +} + } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h index b6f07683d7e..faa164bfe9c 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h @@ -45,8 +45,10 @@ public: void updateRenderImage(const QImage &img); void updateActiveScene(qint32 activeScene); - qint32 activeScene() const { return m_activeScene; } + QImage renderImage() const; + void setOpacity(qreal opacity); + QWidget *busyIndicator() const; protected: void mousePressEvent(QMouseEvent *e) override; @@ -64,11 +66,15 @@ protected: void focusInEvent(QFocusEvent *focusEvent) override; private: + void positionBusyInidicator(); + QPointer m_parent; QImage m_image; qint32 m_activeScene = -1; ItemLibraryEntry m_itemLibraryEntry; QElapsedTimer m_usageTimer; + qreal m_opacity = 1.0; + QWidget *m_busyIndicator = nullptr; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 8e6d75efc37..8a8007ec2ea 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -110,6 +110,10 @@ void Edit3DView::renderImage3DChanged(const QImage &img) // Notify puppet to resize if received image wasn't correct size if (img.size() != canvasSize()) edit3DViewResized(canvasSize()); + if (edit3DWidget()->canvas()->busyIndicator()->isVisible()) { + edit3DWidget()->canvas()->setOpacity(1.0); + edit3DWidget()->canvas()->busyIndicator()->hide(); + } } void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) @@ -195,13 +199,19 @@ void Edit3DView::modelAttached(Model *model) AbstractView::modelAttached(model); checkImports(); + auto cachedImage = m_canvasCache.take(model); + if (cachedImage) { + edit3DWidget()->canvas()->updateRenderImage(*cachedImage); + edit3DWidget()->canvas()->setOpacity(0.5); + } + + edit3DWidget()->canvas()->busyIndicator()->show(); } void Edit3DView::modelAboutToBeDetached(Model *model) { - Q_UNUSED(model) - // Hide the canvas when model is detached (i.e. changing documents) + m_canvasCache.insert(model, edit3DWidget()->canvas()->renderImage()); edit3DWidget()->showCanvas(false); AbstractView::modelAboutToBeDetached(model); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 721a69bfa2e..daddb84d6c8 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -27,6 +27,8 @@ #include "view3dactioncommand.h" #include "seekerslider.h" +#include + #include #include #include @@ -107,6 +109,7 @@ private: Edit3DAction *m_visibilityTogglesAction = nullptr; SeekerSlider *m_seeker = nullptr; int particlemode; + ModelCache m_canvasCache; }; } // namespace QmlDesigner