diff --git a/cli/application.cpp b/cli/application.cpp index 070faa9..df76ada 100644 --- a/cli/application.cpp +++ b/cli/application.cpp @@ -34,6 +34,7 @@ Application::Application() : // setup argument callbacks m_args.status.setCallback(bind(&Application::printStatus, this, _1)); m_args.log.setCallback(bind(&Application::requestLog, this, _1)); + m_args.stop.setCallback(bind(&Application::requestShutdown, this, _1)); m_args.restart.setCallback(bind(&Application::requestRestart, this, _1)); m_args.rescan.setCallback(bind(&Application::requestRescan, this, _1)); m_args.rescanAll.setCallback(bind(&Application::requestRescanAll, this, _1)); @@ -168,6 +169,14 @@ void Application::requestLog(const ArgumentOccurrence &) cerr.flush(); } +void Application::requestShutdown(const ArgumentOccurrence &) +{ + connect(&m_connection, &SyncthingConnection::shutdownTriggered, &QCoreApplication::quit); + m_connection.shutdown(); + cerr << "Request shutdown " << m_settings.syncthingUrl.toLocal8Bit().data() << " ..."; + cerr.flush(); +} + void Application::requestRestart(const ArgumentOccurrence &) { connect(&m_connection, &SyncthingConnection::restartTriggered, &QCoreApplication::quit); diff --git a/cli/application.h b/cli/application.h index b4c8477..402071b 100644 --- a/cli/application.h +++ b/cli/application.h @@ -27,6 +27,7 @@ private slots: private: void requestLog(const ArgumentOccurrence &); + void requestShutdown(const ArgumentOccurrence &); void requestRestart(const ArgumentOccurrence &); void requestRescan(const ArgumentOccurrence &occurrence); void requestRescanAll(const ArgumentOccurrence &); diff --git a/cli/args.cpp b/cli/args.cpp index 338c4ed..5b906f3 100644 --- a/cli/args.cpp +++ b/cli/args.cpp @@ -6,6 +6,7 @@ Args::Args() : help(parser), status("status", 's', "shows the status"), log("log", 'l', "shows the Syncthing log"), + stop("stop", '\0', "stops Syncthing"), restart("restart", '\0', "restarts Syncthing"), rescan("rescan", 'r', "rescans the specified directories"), rescanAll("rescan-all", '\0', "rescans all directories"), @@ -31,8 +32,7 @@ Args::Args() : resume.setValueNames({"dev ID"}); resume.setRequiredValueCount(-1); - parser.setMainArguments({&status, &log, &restart, &rescan, &rescanAll, &pause, &pauseAll, - &resume, &resumeAll, + parser.setMainArguments({&status, &log, &stop, &restart, &rescan, &rescanAll, &pause, &pauseAll, &resume, &resumeAll, &configFile, &apiKey, &url, &credentials, &certificate, &help}); // allow setting default values via environment diff --git a/cli/args.h b/cli/args.h index a82aa49..094bc5b 100644 --- a/cli/args.h +++ b/cli/args.h @@ -12,7 +12,7 @@ struct Args Args(); ArgumentParser parser; HelpArgument help; - OperationArgument status, log, restart, rescan, rescanAll, pause, pauseAll, resume, resumeAll; + OperationArgument status, log, stop, restart, rescan, rescanAll, pause, pauseAll, resume, resumeAll; ConfigValueArgument dir, dev; ConfigValueArgument configFile, apiKey, url, credentials, certificate; }; diff --git a/connector/syncthingconnection.cpp b/connector/syncthingconnection.cpp index c2024de..c212dfa 100644 --- a/connector/syncthingconnection.cpp +++ b/connector/syncthingconnection.cpp @@ -359,6 +359,16 @@ void SyncthingConnection::restart() QObject::connect(postData(QStringLiteral("system/restart"), QUrlQuery()), &QNetworkReply::finished, this, &SyncthingConnection::readRestart); } +/*! + * \brief Requests Syncthing to exit and not restart. + * + * The signal error() is emitted when the request was not successful. + */ +void SyncthingConnection::shutdown() +{ + QObject::connect(postData(QStringLiteral("system/shutdown"), QUrlQuery()), &QNetworkReply::finished, this, &SyncthingConnection::readShutdown); +} + /*! * \brief Considers all notifications as read; hence might trigger a status update. */ @@ -1396,6 +1406,22 @@ void SyncthingConnection::readRestart() } } +/*! + * \brief Reads results of shutdown(). + */ +void SyncthingConnection::readShutdown() +{ + auto *reply = static_cast(sender()); + reply->deleteLater(); + switch(reply->error()) { + case QNetworkReply::NoError: + emit shutdownTriggered(); + break; + default: + emit error(tr("Unable to request shutdown: ") + reply->errorString()); + } +} + /*! * \brief Sets the connection status. Ensures statusChanged() is emitted. * \param status Specifies the status; should be either SyncthingStatus::Disconnected or SyncthingStatus::Default. There is no use diff --git a/connector/syncthingconnection.h b/connector/syncthingconnection.h index 3ec224c..0e10ad9 100644 --- a/connector/syncthingconnection.h +++ b/connector/syncthingconnection.h @@ -212,6 +212,7 @@ public Q_SLOTS: void rescan(const QString &dirId); void rescanAllDirs(); void restart(); + void shutdown(); void considerAllNotificationsRead(); Q_SIGNALS: @@ -232,6 +233,7 @@ Q_SIGNALS: void pauseTriggered(const QString &devId); void resumeTriggered(const QString &devId); void restartTriggered(); + void shutdownTriggered(); private Q_SLOTS: void requestConfig(); @@ -262,6 +264,7 @@ private Q_SLOTS: void readRescan(); void readPauseResume(); void readRestart(); + void readShutdown(); void continueConnecting(); void continueReconnecting();