App: guard individual import tasks during shutdown

This commit is contained in:
Marco Allegretti 2026-02-13 18:55:33 +01:00
parent 4b7655bc6b
commit cca49615d6

View file

@ -731,31 +731,55 @@ void App::importAllGames()
void App::importFromSteam() void App::importFromSteam()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Steam library...")); setImportStatus(tr("Scanning Steam library..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
SteamImporter importer; SteamImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Steam import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Steam import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -763,31 +787,55 @@ void App::importFromSteam()
void App::importFromLutris() void App::importFromLutris()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Lutris library...")); setImportStatus(tr("Scanning Lutris library..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
LutrisImporter importer; LutrisImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Lutris import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Lutris import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -795,31 +843,55 @@ void App::importFromLutris()
void App::importFromHeroic() void App::importFromHeroic()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Heroic library...")); setImportStatus(tr("Scanning Heroic library..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
HeroicImporter importer; HeroicImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Heroic import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Heroic import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -827,31 +899,55 @@ void App::importFromHeroic()
void App::importFromDesktop() void App::importFromDesktop()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning desktop entries...")); setImportStatus(tr("Scanning desktop entries..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
DesktopImporter importer; DesktopImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Desktop import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Desktop import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -859,31 +955,55 @@ void App::importFromDesktop()
void App::importFromBottles() void App::importFromBottles()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Bottles...")); setImportStatus(tr("Scanning Bottles..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
BottlesImporter importer; BottlesImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Bottles import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Bottles import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -891,31 +1011,55 @@ void App::importFromBottles()
void App::importFromFlatpak() void App::importFromFlatpak()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Flatpak games...")); setImportStatus(tr("Scanning Flatpak games..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
FlatpakImporter importer; FlatpakImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Flatpak import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Flatpak import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -923,31 +1067,55 @@ void App::importFromFlatpak()
void App::importFromItch() void App::importFromItch()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning itch.io library...")); setImportStatus(tr("Scanning itch.io library..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
ItchImporter importer; ItchImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("itch.io import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("itch.io import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -955,31 +1123,55 @@ void App::importFromItch()
void App::importFromLegendary() void App::importFromLegendary()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning Legendary library...")); setImportStatus(tr("Scanning Legendary library..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
LegendaryImporter importer; LegendaryImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("Legendary import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("Legendary import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });
@ -987,31 +1179,55 @@ void App::importFromLegendary()
void App::importFromRetroArch() void App::importFromRetroArch()
{ {
if (m_importing) if (m_importing || m_shuttingDown.load())
return; return;
setImporting(true); setImporting(true);
setImportStatus(tr("Scanning RetroArch playlists...")); setImportStatus(tr("Scanning RetroArch playlists..."));
[[maybe_unused]] auto future = QtConcurrent::run([this]() { [[maybe_unused]] auto future = QtConcurrent::run([self = QPointer<App>(this)]() {
if (!self || self->m_shuttingDown.load()) {
return;
}
RetroArchImporter importer; RetroArchImporter importer;
QList<Game *> games = importer.importGames(); QList<Game *> games = importer.importGames();
if (!self || self->m_shuttingDown.load()) {
for (Game *game : games) {
delete game;
}
return;
}
QThread *appThread = self->thread();
for (Game *game : games) { for (Game *game : games) {
game->moveToThread(this->thread()); if (game) {
game->setParent(nullptr); game->moveToThread(appThread);
game->setParent(nullptr);
}
} }
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
this, self.data(),
[this, games]() { [self, games]() {
for (Game *game : games) { if (!self || self->m_shuttingDown.load()) {
m_gameModel->addGame(game); for (Game *game : games) {
if (game) {
game->deleteLater();
}
}
return;
} }
setImportStatus(tr("RetroArch import complete: %1 games found").arg(games.count())); for (Game *game : games) {
setImporting(false); if (game) {
saveLibrary(); self->m_gameModel->addGame(game);
Q_EMIT importCompleted(games.count()); }
}
self->setImportStatus(self->tr("RetroArch import complete: %1 games found").arg(games.count()));
self->setImporting(false);
self->saveLibrary();
Q_EMIT self->importCompleted(games.count());
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });