mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 01:23:24 -08:00
Merge 1a1d58d3db into 7ca697348b
This commit is contained in:
commit
f05bdb65f9
1 changed files with 29 additions and 36 deletions
|
|
@ -10,7 +10,7 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFutureWatcher>
|
||||
#include <QFuture>
|
||||
#include <QMetaObject>
|
||||
#include <QMetaType>
|
||||
#include <QSet>
|
||||
|
|
@ -244,15 +244,15 @@ void VisualDeckStorageModel::startScan()
|
|||
|
||||
// The scan (directory walk + one stat per file) runs on a worker thread so that
|
||||
// constructing the widget never stalls the UI thread on a large deck folder.
|
||||
auto *watcher = new QFutureWatcher<DeckScanResult>(this);
|
||||
connect(watcher, &QFutureWatcher<DeckScanResult>::finished, this, [this, watcher, generation] {
|
||||
watcher->deleteLater();
|
||||
|
||||
// The continuation is bound to this model as its context object: it runs on the UI thread,
|
||||
// and Qt drops it if the model is destroyed first, so no result is delivered to a dead model.
|
||||
QFuture<DeckScanResult> scan =
|
||||
QtConcurrent::run([currentDeckPath]() -> DeckScanResult { return scanDeckDirectory(currentDeckPath); });
|
||||
scan.then(this, [this, generation](const DeckScanResult &result) {
|
||||
if (generation != scanGeneration) {
|
||||
return; // A newer scan started while this one was running; drop the stale result.
|
||||
}
|
||||
|
||||
const DeckScanResult result = watcher->result();
|
||||
folderPaths = result.folderPaths;
|
||||
|
||||
if (result.decks.isEmpty()) {
|
||||
|
|
@ -268,9 +268,6 @@ void VisualDeckStorageModel::startScan()
|
|||
beginLoad(row);
|
||||
}
|
||||
});
|
||||
|
||||
watcher->setFuture(
|
||||
QtConcurrent::run([currentDeckPath]() -> DeckScanResult { return scanDeckDirectory(currentDeckPath); }));
|
||||
}
|
||||
|
||||
void VisualDeckStorageModel::beginLoad(int row)
|
||||
|
|
@ -286,32 +283,7 @@ void VisualDeckStorageModel::beginLoad(int row)
|
|||
const DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(filePath);
|
||||
const int generation = scanGeneration;
|
||||
|
||||
auto *watcher = new QFutureWatcher<std::optional<DeckLoadResult>>(this);
|
||||
connect(watcher, &QFutureWatcher<std::optional<DeckLoadResult>>::finished, this,
|
||||
[this, watcher, filePath, generation] {
|
||||
watcher->deleteLater();
|
||||
|
||||
if (generation != scanGeneration) {
|
||||
return; // The deck list was re-scanned while this load was running; drop the stale result.
|
||||
}
|
||||
|
||||
// Queue the result and apply a bounded number per event loop turn so that
|
||||
// finishing hundreds of loads at once cannot stall the UI thread.
|
||||
const std::optional<DeckLoadResult> result = watcher->result();
|
||||
PendingDeckLoad pending;
|
||||
pending.filePath = filePath;
|
||||
pending.generation = generation;
|
||||
if (result) {
|
||||
pending.ok = true;
|
||||
pending.deck = std::move(result->deck);
|
||||
pending.lastModified = result->lastModified;
|
||||
pending.colorIdentity = std::move(result->colorIdentity);
|
||||
}
|
||||
pendingLoads.append(std::move(pending));
|
||||
schedulePendingLoadDrain();
|
||||
});
|
||||
|
||||
watcher->setFuture(QtConcurrent::run([filePath, fmt]() -> std::optional<DeckLoadResult> {
|
||||
auto load = QtConcurrent::run([filePath, fmt]() -> std::optional<DeckLoadResult> {
|
||||
std::optional<LoadedDeck> deck = DeckLoader::loadFromFile(filePath, fmt, false);
|
||||
if (!deck) {
|
||||
return std::nullopt;
|
||||
|
|
@ -320,7 +292,28 @@ void VisualDeckStorageModel::beginLoad(int row)
|
|||
// keep the completion handler on the UI thread cheap.
|
||||
const QString colorIdentity = getDeckColorIdentity(deck->deckList, CardDatabaseManager::query());
|
||||
return DeckLoadResult{std::move(*deck), QFileInfo(filePath).lastModified(), colorIdentity};
|
||||
}));
|
||||
});
|
||||
|
||||
// Bound to this model as context: runs on the UI thread and is dropped if the model is destroyed first.
|
||||
load.then(this, [this, filePath, generation](std::optional<DeckLoadResult> result) {
|
||||
if (generation != scanGeneration) {
|
||||
return; // The deck list was re-scanned while this load was running; drop the stale result.
|
||||
}
|
||||
|
||||
// Queue the result and apply a bounded number per event loop turn so that
|
||||
// finishing hundreds of loads at once cannot stall the UI thread.
|
||||
PendingDeckLoad pending;
|
||||
pending.filePath = filePath;
|
||||
pending.generation = generation;
|
||||
if (result) {
|
||||
pending.ok = true;
|
||||
pending.deck = std::move(result->deck);
|
||||
pending.lastModified = result->lastModified;
|
||||
pending.colorIdentity = std::move(result->colorIdentity);
|
||||
}
|
||||
pendingLoads.append(std::move(pending));
|
||||
schedulePendingLoadDrain();
|
||||
});
|
||||
}
|
||||
|
||||
void VisualDeckStorageModel::schedulePendingLoadDrain()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue