From 9712c996d91241526ae734fd5238b4c03020ad72 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:34:45 +0100 Subject: [PATCH 1/2] ProjectLoader: Add properties for download progress --- ScratchCPPGui/projectloader.cpp | 29 +++++++++++++++++++++++++++++ ScratchCPPGui/projectloader.h | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/ScratchCPPGui/projectloader.cpp b/ScratchCPPGui/projectloader.cpp index 44bfb47..610ab72 100644 --- a/ScratchCPPGui/projectloader.cpp +++ b/ScratchCPPGui/projectloader.cpp @@ -20,6 +20,18 @@ void runEventLoop(IEngine *engine) ProjectLoader::ProjectLoader(QObject *parent) : QObject(parent) { + m_project.setDownloadProgressCallback([this](unsigned int finished, unsigned int all) { + if (finished != m_downloadedAssets) { + m_downloadedAssets = finished; + emit downloadedAssetsChanged(); + } + + if (all != m_assetCount) { + m_assetCount = all; + emit assetCountChanged(); + } + }); + initTimer(); // Update refresh rate when primary screen changes @@ -66,6 +78,13 @@ void ProjectLoader::setFileName(const QString &newFileName) m_project.setScratchVersion(ScratchVersion::Scratch3); m_project.setFileName(m_fileName.toStdString()); m_loadStatus = false; + + // TODO: Do not set these to 0 after libscratchcpp starts doing it itself + m_downloadedAssets = 0; + m_assetCount = 0; + emit downloadedAssetsChanged(); + emit assetCountChanged(); + emit loadStatusChanged(); emit fileNameChanged(); @@ -397,3 +416,13 @@ void ProjectLoader::setEventLoopEnabled(bool newEventLoopEnabled) m_engineMutex.unlock(); emit eventLoopEnabledChanged(); } + +unsigned int ProjectLoader::downloadedAssets() const +{ + return m_downloadedAssets; +} + +unsigned int ProjectLoader::assetCount() const +{ + return m_assetCount; +} diff --git a/ScratchCPPGui/projectloader.h b/ScratchCPPGui/projectloader.h index 5de7c61..c354d06 100644 --- a/ScratchCPPGui/projectloader.h +++ b/ScratchCPPGui/projectloader.h @@ -30,6 +30,8 @@ class ProjectLoader : public QObject Q_PROPERTY(int cloneLimit READ cloneLimit WRITE setCloneLimit NOTIFY cloneLimitChanged) Q_PROPERTY(bool spriteFencing READ spriteFencing WRITE setSpriteFencing NOTIFY spriteFencingChanged) Q_PROPERTY(bool eventLoopEnabled READ eventLoopEnabled WRITE setEventLoopEnabled NOTIFY eventLoopEnabledChanged) + Q_PROPERTY(unsigned int downloadedAssets READ downloadedAssets NOTIFY downloadedAssetsChanged) + Q_PROPERTY(unsigned int assetCount READ assetCount NOTIFY assetCountChanged) public: explicit ProjectLoader(QObject *parent = nullptr); @@ -72,6 +74,10 @@ class ProjectLoader : public QObject bool eventLoopEnabled() const; void setEventLoopEnabled(bool newEventLoopEnabled); + unsigned int downloadedAssets() const; + + unsigned int assetCount() const; + signals: void fileNameChanged(); void loadStatusChanged(); @@ -86,6 +92,8 @@ class ProjectLoader : public QObject void cloneLimitChanged(); void spriteFencingChanged(); void eventLoopEnabledChanged(); + void downloadedAssetsChanged(); + void assetCountChanged(); protected: void timerEvent(QTimerEvent *event) override; @@ -113,6 +121,8 @@ class ProjectLoader : public QObject int m_cloneLimit = 300; bool m_spriteFencing = true; bool m_eventLoopEnabled = true; + std::atomic m_downloadedAssets = 0; + std::atomic m_assetCount = 0; }; } // namespace scratchcppgui From 3bf773fd5441eb93c4816b810c2d076dac08f5b1 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:36:32 +0100 Subject: [PATCH 2/2] ProjectPlayer: Add loading progress indicators --- ScratchCPPGui/ProjectPlayer.qml | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/ScratchCPPGui/ProjectPlayer.qml b/ScratchCPPGui/ProjectPlayer.qml index b632fc3..40d76aa 100644 --- a/ScratchCPPGui/ProjectPlayer.qml +++ b/ScratchCPPGui/ProjectPlayer.qml @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later import QtQuick +import QtQuick.Layouts +import QtQuick.Controls import ScratchCPPGui ProjectScene { @@ -9,11 +11,21 @@ ProjectScene { property alias turboMode: loader.turboMode property alias cloneLimit: loader.cloneLimit property alias spriteFencing: loader.spriteFencing + property bool showLoadingProgress: true + readonly property bool loading: priv.loading + readonly property int downloadedAssets: loader.downloadedAssets + readonly property int assetCount: loader.assetCount signal loaded() signal failedToLoad() id: root clip: true + onFileNameChanged: priv.loading = true; + + QtObject { + id: priv + property bool loading: false + } ProjectLoader { id: loader @@ -21,6 +33,8 @@ ProjectScene { stageWidth: parent.width stageHeight: parent.height onLoadingFinished: { + priv.loading = false; + if(loadStatus) loaded(); else @@ -55,4 +69,44 @@ ProjectScene { Component.onCompleted: modelData.renderedTarget = this } } + + Loader { + anchors.fill: parent + active: showLoadingProgress && loading + + sourceComponent: ColumnLayout { + anchors.fill: parent + + Item { Layout.fillHeight: true } + + BusyIndicator { + Layout.fillWidth: true + Layout.maximumWidth: 100 + Layout.alignment: Qt.AlignHCenter + running: true + } + + Label { + Layout.alignment: Qt.AlignHCenter + font.bold: true + font.pointSize: 12 + text: { + if(loading) + return assetCount == downloadedAssets ? qsTr("Loading project...") : qsTr("Downloading assets... (%1 of %2)").arg(downloadedAssets).arg(assetCount); + else + return ""; + } + } + + ProgressBar { + Layout.fillWidth: true + from: 0 + to: assetCount + value: downloadedAssets + indeterminate: assetCount == downloadedAssets + } + + Item { Layout.fillHeight: true } + } + } }