diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index 7cf58d3e0..46151481c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -5,11 +5,13 @@ #include "../client/network/update/client/release_channel.h" #include "../interface/window_main.h" +#include #include #include #include #include #include +#include #include #include #include @@ -240,8 +242,23 @@ void DlgUpdate::downloadSuccessful(const QUrl &filepath) // Try to open the installer. If it opens, quit Cockatrice if (process.startDetached()) { - QMetaObject::invokeMethod(static_cast(parent()), "close", Qt::QueuedConnection); qCInfo(DlgUpdateLog) << "Opened downloaded update file successfully - closing Cockatrice"; + // Close the main window synchronously so file locks are released before the NSIS installer + // (already launched) starts replacing files. This also flushes settings and shuts down the + // tabs, but only when the close is actually accepted: MainWindow may veto it for a running + // card DB update, an open game, or an unsaved deck. In that case keep running so the user + // can resolve the blocker, and tell them the installer is already waiting. + if (auto *window = qobject_cast(parent())) { + if (window->close()) { + QTimer::singleShot(0, qApp, &QCoreApplication::quit); + } else { + QMessageBox::warning(this, tr("Update"), + tr("The update installer is already running and will finish the update once " + "Cockatrice closes. Cockatrice is still busy, so it stays open for now.")); + } + } else { + QTimer::singleShot(0, qApp, &QCoreApplication::quit); + } close(); } else { setLabel(tr("Error"));