diff --git a/src/app/main.cpp b/src/app/main.cpp index 197fed52..95c7c522 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) try { Controller controller(app.parseArgs()); - QObject::connect(&controller, &Controller::quit, &app, &QApplication::quit); + QObject::connect(&controller, &Controller::finished, &app, &Application::requestQuit); // Pass control to Controller::run() when the event loop starts. QTimer::singleShot(0, &controller, &Controller::run); diff --git a/src/controller/application.cpp b/src/controller/application.cpp index 20cd2eda..9f8ee776 100644 --- a/src/controller/application.cpp +++ b/src/controller/application.cpp @@ -88,6 +88,11 @@ Application::Application(int& argc, char** argv, const QString& name) : #endif } +void Application::requestQuit() noexcept +{ + QMetaObject::invokeMethod(this, [] { QCoreApplication::quit(); }, Qt::QueuedConnection); +} + bool Application::isDarkTheme() { #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) diff --git a/src/controller/application.hpp b/src/controller/application.hpp index 3dedbcd9..e988887e 100644 --- a/src/controller/application.hpp +++ b/src/controller/application.hpp @@ -45,6 +45,8 @@ class Application : public QApplication public: Application(int& argc, char** argv, const QString& name); + void requestQuit() noexcept; + static bool isDarkTheme(); void loadTranslations(const QString& lang = {}); static CommandWithArguments parseArgs(); diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp index af5fd1e4..33c0391e 100644 --- a/src/controller/controller.cpp +++ b/src/controller/controller.cpp @@ -85,10 +85,10 @@ try { WebEidUI::showAboutPage(); return; case CommandType::QUIT: - // If quit is requested, respond with empty JSON object and quit immediately. - qInfo() << "Quit requested, exiting"; + // If quit is requested, respond with empty JSON object and finish immediately. + qInfo() << "Quit requested, finishing"; writeResponseToStdOut(true, {}, "quit"); - emit quit(); + finish(); return; default: break; @@ -218,7 +218,7 @@ try { _result = res; writeResponseToStdOut(isInStdinMode, res, commandHandler->commandType()); - exit(); + finish(); } catch (const std::exception& error) { onCriticalFailure(error.what()); } @@ -263,7 +263,7 @@ try { qDebug() << "User cancelled"; _result = makeErrorObject(RESP_USER_CANCEL, QStringLiteral("User cancelled")); writeResponseToStdOut(isInStdinMode, _result, commandType()); - exit(); + finish(); } catch (const std::exception& e) { onCriticalFailure(e.what()); } @@ -285,17 +285,17 @@ try { // user. writeResponseToStdOut(isInStdinMode, _result, commandType()); } - exit(); + finish(); } catch (const std::exception& e) { qCritical() << "Failed to write stdout" << e.what(); - exit(); + finish(); } -void Controller::exit() noexcept +void Controller::finish() noexcept { disposeUI(); waitForChildThreads(); - emit quit(); + emit finished(); } void Controller::waitForChildThreads() noexcept diff --git a/src/controller/controller.hpp b/src/controller/controller.hpp index 33314e9c..d69f891d 100644 --- a/src/controller/controller.hpp +++ b/src/controller/controller.hpp @@ -37,7 +37,7 @@ class Controller : public QObject const QVariantMap& result() const { return _result; } signals: - void quit(); + void finished(); void retry(const RetriableError error); void statusUpdate(RetriableError status); void stopCardEventMonitorThread(); @@ -65,7 +65,7 @@ class Controller : public QObject void onDialogOK(const EidCertificateAndPinInfo& certAndPinInfo) noexcept; void onDialogCancel() noexcept; - // Failure handler, reports the error and quits the application. + // Failure handler, reports the error and finishes the operation. void onCriticalFailure(const QString& error) noexcept; private: @@ -73,7 +73,7 @@ class Controller : public QObject void connectRetry(const ControllerChildThread* childThread) const; void createWindow(); void disposeUI() noexcept; - void exit() noexcept; + void finish() noexcept; void waitForChildThreads() noexcept; CommandType commandType() const noexcept; diff --git a/src/mac/main.mm b/src/mac/main.mm index e45fd466..5f307710 100644 --- a/src/mac/main.mm +++ b/src/mac/main.mm @@ -130,9 +130,9 @@ - (void)notificationEvent:(NSNotification*)notification Controller controller({ CommandType(QString::fromNSString(req[@"command"])), argumentJson.object().toVariantMap()}); - controller.run(); QEventLoop e; - QObject::connect(&controller, &Controller::quit, &e, &QEventLoop::quit); + QObject::connect(&controller, &Controller::finished, &e, &QEventLoop::quit); + QTimer::singleShot(0, &controller, &Controller::run); e.exec(); resp = [NSApplication toNSDictionary:controller.result()]; } catch (const std::exception& error) { @@ -198,7 +198,7 @@ int main(int argc, char* argv[]) Controller controller(std::move(args)); - QObject::connect(&controller, &Controller::quit, &app, &QApplication::quit); + QObject::connect(&controller, &Controller::finished, &app, &Application::requestQuit); // Pass control to Controller::run() when the event loop starts. QTimer::singleShot(0, &controller, &Controller::run); diff --git a/src/ui/webeiddialog.cpp b/src/ui/webeiddialog.cpp index 8798eb03..23922969 100644 --- a/src/ui/webeiddialog.cpp +++ b/src/ui/webeiddialog.cpp @@ -208,7 +208,7 @@ void WebEidDialog::showAboutPage() d->ui->pageStack->setCurrentIndex(int(Page::ABOUT)); d->resizeHeight(); d->open(); - connect(d, &WebEidDialog::finished, qApp, &QApplication::quit); + connect(d, &WebEidDialog::finished, qApp, &Application::requestQuit); } void WebEidDialog::showFatalErrorPage() diff --git a/tests/mock-ui/mock-ui.hpp b/tests/mock-ui/mock-ui.hpp index 300cb057..db577425 100644 --- a/tests/mock-ui/mock-ui.hpp +++ b/tests/mock-ui/mock-ui.hpp @@ -60,13 +60,13 @@ class MockUI : public WebEidUI void onSmartCardStatusUpdate(const RetriableError) override { emit rejected(); - // Schedule invoking Controller::exit(). + // Schedule invoking Controller::finish(). emit destroyed(); } void quit() final { - // Schedule invoking Controller::exit(). + // Schedule invoking Controller::finish(). emit destroyed(); } }; diff --git a/tests/tests/main.cpp b/tests/tests/main.cpp index 82cf496c..7b4c1205 100644 --- a/tests/tests/main.cpp +++ b/tests/tests/main.cpp @@ -70,10 +70,10 @@ private slots: void authenticate_validArgumentsResultInValidToken(); - void quit_exits(); + void quit_finishes(); private: - void runEventLoopVerifySignalsEmitted(QSignalSpy& actionSpy, bool waitForQuit = true); + void runEventLoopVerifySignalsEmitted(QSignalSpy& actionSpy, bool waitForFinish = true); void initGetCert(); void initAuthenticate(); void initCard(bool withSigningScript = true); @@ -197,34 +197,33 @@ void WebEidTests::authenticate_validArgumentsResultInValidToken() QStringLiteral("MIIEAzCCA2WgAwIBAgIQOWkBW")); } -void WebEidTests::quit_exits() +void WebEidTests::quit_finishes() { try { controller = std::make_unique(CommandWithArguments {CommandType::QUIT, {}}); - QSignalSpy quitSpy(controller.get(), &Controller::quit); + QSignalSpy finishedSpy(controller.get(), &Controller::finished); QTimer::singleShot(0, controller.get(), &Controller::run); - QVERIFY(quitSpy.wait()); + QVERIFY(finishedSpy.wait()); } catch (const std::exception& e) { - QFAIL(QStringLiteral("WebEidTests::quit_exits() failed with exception: %s") + QFAIL(QStringLiteral("WebEidTests::quit_finishes() failed with exception: %s") .arg(QLatin1String(e.what())) .toUtf8()); } } -void WebEidTests::runEventLoopVerifySignalsEmitted(QSignalSpy& actionSpy, bool waitForQuit) +void WebEidTests::runEventLoopVerifySignalsEmitted(QSignalSpy& actionSpy, bool waitForFinish) { - // Waits until Controller emits quit. - QSignalSpy quitSpy(controller.get(), &Controller::quit); + QSignalSpy finishedSpy(controller.get(), &Controller::finished); // Pass control to Controller::run() when the event loop starts. QTimer::singleShot(0, controller.get(), &Controller::run); // Run the event loop, verify that signals were emitted. QVERIFY(actionSpy.wait()); - if (waitForQuit && quitSpy.count() < 1) { - QVERIFY(quitSpy.wait()); + if (waitForFinish && finishedSpy.count() < 1) { + QVERIFY(finishedSpy.wait()); } }