Skip to content

Commit fa6f240

Browse files
committed
ProjectLoader: Add API for stopping loading
1 parent 08c8ca1 commit fa6f240

File tree

3 files changed

+59
-25
lines changed

3 files changed

+59
-25
lines changed

src/projectloader.cpp

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ ProjectLoader::ProjectLoader(QObject *parent) :
4545

4646
ProjectLoader::~ProjectLoader()
4747
{
48-
m_stopLoading = true;
49-
50-
if (m_loadThread.isRunning())
51-
m_loadThread.waitForFinished();
48+
stopLoading();
5249

5350
for (SpriteModel *sprite : m_sprites)
5451
sprite->deleteLater();
@@ -61,8 +58,11 @@ const QString &ProjectLoader::fileName() const
6158

6259
void ProjectLoader::setFileName(const QString &newFileName)
6360
{
64-
if (m_loadThread.isRunning())
61+
if (m_loadThread.isRunning()) {
62+
stopLoading();
6563
m_loadThread.waitForFinished();
64+
QCoreApplication::processEvents();
65+
}
6666

6767
if (newFileName.isEmpty())
6868
return;
@@ -72,7 +72,7 @@ void ProjectLoader::setFileName(const QString &newFileName)
7272
clear();
7373

7474
m_project.setFileName(m_fileName.toStdString());
75-
m_loadStatus = false;
75+
m_loadStatus = LoadStatus::Loading;
7676

7777
// TODO: Do not set these to 0 after libscratchcpp starts doing it itself
7878
m_downloadedAssets = 0;
@@ -87,14 +87,23 @@ void ProjectLoader::setFileName(const QString &newFileName)
8787
m_loadThread = QtConcurrent::run(&callLoad, this);
8888
}
8989

90-
bool ProjectLoader::loadStatus() const
90+
ProjectLoader::LoadStatus ProjectLoader::loadStatus() const
9191
{
9292
if (m_loadThread.isRunning())
93-
return false;
93+
return LoadStatus::Loading;
9494

9595
return m_loadStatus;
9696
}
9797

98+
void ProjectLoader::stopLoading()
99+
{
100+
if (m_loadThread.isRunning()) {
101+
m_project.stopLoading();
102+
m_stopLoading = true;
103+
m_loadThread.waitForFinished();
104+
}
105+
}
106+
98107
bool ProjectLoader::running() const
99108
{
100109
return m_running;
@@ -122,15 +131,17 @@ void ProjectLoader::setEngine(libscratchcpp::IEngine *engine)
122131
StageModel *ProjectLoader::stage()
123132
{
124133
if (m_loadThread.isRunning())
125-
m_loadThread.waitForFinished();
134+
return nullptr;
126135

127136
return &m_stage;
128137
}
129138

130139
QQmlListProperty<SpriteModel> ProjectLoader::sprites()
131140
{
132-
if (m_loadThread.isRunning())
133-
m_loadThread.waitForFinished();
141+
if (m_loadThread.isRunning()) {
142+
m_emptySpriteList.clear();
143+
return QQmlListProperty<SpriteModel>(this, &m_emptySpriteList);
144+
}
134145

135146
return QQmlListProperty<SpriteModel>(this, &m_sprites);
136147
}
@@ -168,9 +179,9 @@ const QStringList &ProjectLoader::unsupportedBlocks() const
168179
void ProjectLoader::start()
169180
{
170181
if (m_loadThread.isRunning())
171-
m_loadThread.waitForFinished();
182+
return;
172183

173-
if (m_loadStatus) {
184+
if (m_loadStatus == LoadStatus::Loaded) {
174185
Q_ASSERT(m_engine);
175186
m_engine->start();
176187
}
@@ -179,9 +190,9 @@ void ProjectLoader::start()
179190
void ProjectLoader::stop()
180191
{
181192
if (m_loadThread.isRunning())
182-
m_loadThread.waitForFinished();
193+
return;
183194

184-
if (m_loadStatus) {
195+
if (m_loadStatus == LoadStatus::Loaded) {
185196
Q_ASSERT(m_engine);
186197
m_engine->stop();
187198
}
@@ -276,12 +287,16 @@ void ProjectLoader::clear()
276287
void ProjectLoader::load()
277288
{
278289
m_unpositionedMonitors.clear();
279-
m_loadStatus = m_project.load();
290+
m_loadStatus = m_project.load() ? LoadStatus::Loaded : LoadStatus::Failed;
280291
m_engineMutex.lock();
281292
m_engine = m_project.engine().get();
282293

283294
if (!m_engine || m_stopLoading) {
284295
m_engineMutex.unlock();
296+
297+
if (m_stopLoading)
298+
m_loadStatus = LoadStatus::Aborted;
299+
285300
emit fileNameChanged();
286301
emit loadStatusChanged();
287302
emit loadingFinished();
@@ -330,6 +345,7 @@ void ProjectLoader::load()
330345

331346
if (m_stopLoading) {
332347
m_engineMutex.unlock();
348+
m_loadStatus = LoadStatus::Aborted;
333349
emit fileNameChanged();
334350
emit loadStatusChanged();
335351
emit loadingFinished();
@@ -364,7 +380,7 @@ void ProjectLoader::initTimer()
364380
void ProjectLoader::redraw()
365381
{
366382
if (m_loadThread.isRunning())
367-
m_loadThread.waitForFinished();
383+
return;
368384

369385
auto stage = m_stage.renderedTarget();
370386

src/projectloader.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ProjectLoader : public QObject
2323
Q_OBJECT
2424
QML_ELEMENT
2525
Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged)
26-
Q_PROPERTY(bool loadStatus READ loadStatus NOTIFY loadStatusChanged)
26+
Q_PROPERTY(LoadStatus loadStatus READ loadStatus NOTIFY loadStatusChanged)
2727
Q_PROPERTY(bool running READ running NOTIFY runningChanged)
2828
Q_PROPERTY(int renderFps READ renderFps NOTIFY renderFpsChanged FINAL)
2929
Q_PROPERTY(libscratchcpp::IEngine *engine READ engine NOTIFY engineChanged)
@@ -43,13 +43,25 @@ class ProjectLoader : public QObject
4343
Q_PROPERTY(unsigned int assetCount READ assetCount NOTIFY assetCountChanged)
4444

4545
public:
46+
enum class LoadStatus
47+
{
48+
Idle,
49+
Loading,
50+
Loaded,
51+
Failed,
52+
Aborted
53+
};
54+
55+
Q_ENUM(LoadStatus)
56+
4657
explicit ProjectLoader(QObject *parent = nullptr);
4758
~ProjectLoader();
4859

4960
const QString &fileName() const;
5061
void setFileName(const QString &newFileName);
5162

52-
bool loadStatus() const;
63+
LoadStatus loadStatus() const;
64+
Q_INVOKABLE void stopLoading();
5365

5466
bool running() const;
5567

@@ -155,10 +167,11 @@ class ProjectLoader : public QObject
155167
libscratchcpp::IEngine *m_engine = nullptr;
156168
libscratchcpp::IEngine *m_oldEngine = nullptr;
157169
QMutex m_engineMutex;
158-
bool m_loadStatus = false;
170+
LoadStatus m_loadStatus = LoadStatus::Idle;
159171
StageModel m_stage;
160172
QList<SpriteModel *> m_sprites;
161173
QList<SpriteModel *> m_clones;
174+
QList<SpriteModel *> m_emptySpriteList;
162175
QList<MonitorModel *> m_monitors;
163176
std::vector<libscratchcpp::Monitor *> m_unpositionedMonitors;
164177
QStringList m_unsupportedBlocks;

test/projectloader/projectloader_test.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ class ProjectLoaderTest : public testing::Test
4646
ASSERT_EQ(monitorsSpy.count(), 1);
4747
ASSERT_TRUE(monitorAddedSpy.empty());
4848
ASSERT_EQ(loader->fileName(), fileName);
49-
ASSERT_FALSE(loader->loadStatus());
49+
ASSERT_EQ(loader->loadStatus(), ProjectLoader::LoadStatus::Loading);
5050

51-
while (!loader->loadStatus())
51+
while (loader->loadStatus() != ProjectLoader::LoadStatus::Loaded)
5252
ASSERT_LE(std::chrono::steady_clock::now(), startTime + timeout);
5353

5454
ASSERT_EQ(loader->fileName(), fileName);
@@ -84,7 +84,7 @@ TEST_F(ProjectLoaderTest, Load)
8484
{
8585
ProjectLoader loader;
8686
ASSERT_TRUE(loader.fileName().isEmpty());
87-
ASSERT_FALSE(loader.loadStatus());
87+
ASSERT_EQ(loader.loadStatus(), ProjectLoader::LoadStatus::Idle);
8888
ASSERT_TRUE(loader.stage());
8989

9090
load(&loader, "load_test.sb3");
@@ -111,13 +111,18 @@ TEST_F(ProjectLoaderTest, Load)
111111

112112
TEST_F(ProjectLoaderTest, UnsupportedBlocks)
113113
{
114+
static const std::chrono::milliseconds timeout(5000);
115+
auto startTime = std::chrono::steady_clock::now();
116+
114117
ProjectLoader loader;
115118
ASSERT_TRUE(loader.fileName().isEmpty());
116-
ASSERT_FALSE(loader.loadStatus());
119+
ASSERT_EQ(loader.loadStatus(), ProjectLoader::LoadStatus::Idle);
117120
ASSERT_TRUE(loader.stage());
118121

119122
loader.setFileName("unsupported_blocks.sb3");
120-
loader.start(); // wait until it loads
123+
124+
while (loader.loadStatus() != ProjectLoader::LoadStatus::Loaded)
125+
ASSERT_LE(std::chrono::steady_clock::now(), startTime + timeout);
121126

122127
auto engine = loader.engine();
123128
const auto &blocks = loader.unsupportedBlocks();

0 commit comments

Comments
 (0)