mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 06:01:33 -06:00
Add reboot option when downloads complete
This commit implements a new "Reboot System" option that allows users to automatically reboot the computer when all downloads are complete, similar to the existing shutdown, suspend, and hibernate options. Closes #10774. PR #23525.
This commit is contained in:
@@ -776,8 +776,9 @@ void Application::allTorrentsFinished()
|
|||||||
bool isShutdown = pref->shutdownWhenDownloadsComplete();
|
bool isShutdown = pref->shutdownWhenDownloadsComplete();
|
||||||
bool isSuspend = pref->suspendWhenDownloadsComplete();
|
bool isSuspend = pref->suspendWhenDownloadsComplete();
|
||||||
bool isHibernate = pref->hibernateWhenDownloadsComplete();
|
bool isHibernate = pref->hibernateWhenDownloadsComplete();
|
||||||
|
bool isReboot = pref->rebootWhenDownloadsComplete();
|
||||||
|
|
||||||
bool haveAction = isExit || isShutdown || isSuspend || isHibernate;
|
const bool haveAction = isExit || isShutdown || isSuspend || isHibernate || isReboot;
|
||||||
if (!haveAction) return;
|
if (!haveAction) return;
|
||||||
|
|
||||||
ShutdownDialogAction action = ShutdownDialogAction::Exit;
|
ShutdownDialogAction action = ShutdownDialogAction::Exit;
|
||||||
@@ -787,6 +788,8 @@ void Application::allTorrentsFinished()
|
|||||||
action = ShutdownDialogAction::Hibernate;
|
action = ShutdownDialogAction::Hibernate;
|
||||||
else if (isShutdown)
|
else if (isShutdown)
|
||||||
action = ShutdownDialogAction::Shutdown;
|
action = ShutdownDialogAction::Shutdown;
|
||||||
|
else if (isReboot)
|
||||||
|
action = ShutdownDialogAction::Reboot;
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
// ask confirm
|
// ask confirm
|
||||||
@@ -808,6 +811,7 @@ void Application::allTorrentsFinished()
|
|||||||
pref->setShutdownWhenDownloadsComplete(false);
|
pref->setShutdownWhenDownloadsComplete(false);
|
||||||
pref->setSuspendWhenDownloadsComplete(false);
|
pref->setSuspendWhenDownloadsComplete(false);
|
||||||
pref->setHibernateWhenDownloadsComplete(false);
|
pref->setHibernateWhenDownloadsComplete(false);
|
||||||
|
pref->setRebootWhenDownloadsComplete(false);
|
||||||
// Make sure preferences are synced before exiting
|
// Make sure preferences are synced before exiting
|
||||||
m_shutdownAct = action;
|
m_shutdownAct = action;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1297,6 +1297,19 @@ void Preferences::setShutdownWhenDownloadsComplete(const bool shutdown)
|
|||||||
setValue(u"Preferences/Downloads/AutoShutDownOnCompletion"_s, shutdown);
|
setValue(u"Preferences/Downloads/AutoShutDownOnCompletion"_s, shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::rebootWhenDownloadsComplete() const
|
||||||
|
{
|
||||||
|
return value(u"Preferences/Downloads/AutoRebootOnCompletion"_s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setRebootWhenDownloadsComplete(const bool reboot)
|
||||||
|
{
|
||||||
|
if (reboot == rebootWhenDownloadsComplete())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setValue(u"Preferences/Downloads/AutoRebootOnCompletion"_s, reboot);
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::suspendWhenDownloadsComplete() const
|
bool Preferences::suspendWhenDownloadsComplete() const
|
||||||
{
|
{
|
||||||
return value(u"Preferences/Downloads/AutoSuspendOnCompletion"_s, false);
|
return value(u"Preferences/Downloads/AutoSuspendOnCompletion"_s, false);
|
||||||
|
|||||||
@@ -287,6 +287,8 @@ public:
|
|||||||
|
|
||||||
bool shutdownWhenDownloadsComplete() const;
|
bool shutdownWhenDownloadsComplete() const;
|
||||||
void setShutdownWhenDownloadsComplete(bool shutdown);
|
void setShutdownWhenDownloadsComplete(bool shutdown);
|
||||||
|
bool rebootWhenDownloadsComplete() const;
|
||||||
|
void setRebootWhenDownloadsComplete(bool reboot);
|
||||||
bool suspendWhenDownloadsComplete() const;
|
bool suspendWhenDownloadsComplete() const;
|
||||||
void setSuspendWhenDownloadsComplete(bool suspend);
|
void setSuspendWhenDownloadsComplete(bool suspend);
|
||||||
bool hibernateWhenDownloadsComplete() const;
|
bool hibernateWhenDownloadsComplete() const;
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ enum class ShutdownDialogAction
|
|||||||
Exit,
|
Exit,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
Suspend,
|
Suspend,
|
||||||
Hibernate
|
Hibernate,
|
||||||
|
Reboot
|
||||||
};
|
};
|
||||||
|
|
||||||
using QStringMap = QMap<QString, QString>;
|
using QStringMap = QMap<QString, QString>;
|
||||||
|
|||||||
@@ -87,22 +87,30 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
|||||||
{
|
{
|
||||||
::SetSuspendState(TRUE, FALSE, FALSE);
|
::SetSuspendState(TRUE, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else if (action == ShutdownDialogAction::Shutdown)
|
||||||
{
|
{
|
||||||
std::wstring msg = QCoreApplication::translate("misc"
|
std::wstring msg = QCoreApplication::translate("misc"
|
||||||
, "qBittorrent will shutdown the computer now because all downloads are complete.").toStdWString();
|
, "qBittorrent will shutdown the computer now because all downloads are complete.").toStdWString();
|
||||||
::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, FALSE);
|
::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, FALSE);
|
||||||
}
|
}
|
||||||
|
else if (action == ShutdownDialogAction::Reboot)
|
||||||
|
{
|
||||||
|
std::wstring msg = QCoreApplication::translate("misc"
|
||||||
|
, "qBittorrent will reboot the computer now because all downloads are complete.").toStdWString();
|
||||||
|
::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Disable shutdown privilege.
|
// Disable shutdown privilege.
|
||||||
tkp.Privileges[0].Attributes = 0;
|
tkp.Privileges[0].Attributes = 0;
|
||||||
::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
||||||
|
|
||||||
#elif defined(Q_OS_MACOS)
|
#elif defined(Q_OS_MACOS)
|
||||||
AEEventID EventToSend;
|
AEEventID EventToSend {};
|
||||||
if (action != ShutdownDialogAction::Shutdown)
|
if (action == ShutdownDialogAction::Suspend)
|
||||||
EventToSend = kAESleep;
|
EventToSend = kAESleep;
|
||||||
else
|
else if (action == ShutdownDialogAction::Reboot)
|
||||||
|
EventToSend = kAERestart;
|
||||||
|
else if (action == ShutdownDialogAction::Shutdown)
|
||||||
EventToSend = kAEShutDown;
|
EventToSend = kAEShutDown;
|
||||||
AEAddressDesc targetDesc;
|
AEAddressDesc targetDesc;
|
||||||
const ProcessSerialNumber kPSNOfSystemProcess = {0, kSystemProcess};
|
const ProcessSerialNumber kPSNOfSystemProcess = {0, kSystemProcess};
|
||||||
@@ -133,7 +141,7 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
|||||||
|
|
||||||
#elif defined(QBT_USES_DBUS)
|
#elif defined(QBT_USES_DBUS)
|
||||||
// Use dbus to power off / suspend the system
|
// Use dbus to power off / suspend the system
|
||||||
if (action != ShutdownDialogAction::Shutdown)
|
if ((action == ShutdownDialogAction::Suspend) || (action == ShutdownDialogAction::Hibernate))
|
||||||
{
|
{
|
||||||
// Some recent systems use systemd's logind
|
// Some recent systems use systemd's logind
|
||||||
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||||
@@ -166,7 +174,7 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
|||||||
else
|
else
|
||||||
halIface.call(u"Hibernate"_s);
|
halIface.call(u"Hibernate"_s);
|
||||||
}
|
}
|
||||||
else
|
else if (action == ShutdownDialogAction::Shutdown)
|
||||||
{
|
{
|
||||||
// Some recent systems use systemd's logind
|
// Some recent systems use systemd's logind
|
||||||
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||||
@@ -190,6 +198,30 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
|||||||
QDBusConnection::systemBus());
|
QDBusConnection::systemBus());
|
||||||
halIface.call(u"Shutdown"_s);
|
halIface.call(u"Shutdown"_s);
|
||||||
}
|
}
|
||||||
|
else if (action == ShutdownDialogAction::Reboot)
|
||||||
|
{
|
||||||
|
// Some recent systems use systemd's logind
|
||||||
|
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||||
|
u"org.freedesktop.login1.Manager"_s, QDBusConnection::systemBus());
|
||||||
|
if (login1Iface.isValid())
|
||||||
|
{
|
||||||
|
login1Iface.call(u"Reboot"_s, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Else, other recent systems use ConsoleKit
|
||||||
|
QDBusInterface consolekitIface(u"org.freedesktop.ConsoleKit"_s, u"/org/freedesktop/ConsoleKit/Manager"_s,
|
||||||
|
u"org.freedesktop.ConsoleKit.Manager"_s, QDBusConnection::systemBus());
|
||||||
|
if (consolekitIface.isValid())
|
||||||
|
{
|
||||||
|
consolekitIface.call(u"Restart"_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// HAL (older systems)
|
||||||
|
QDBusInterface halIface(u"org.freedesktop.Hal"_s, u"/org/freedesktop/Hal/devices/computer"_s,
|
||||||
|
u"org.freedesktop.Hal.Device.SystemPowerManagement"_s,
|
||||||
|
QDBusConnection::systemBus());
|
||||||
|
halIface.call(u"Reboot"_s);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,10 +388,16 @@ MainWindow::MainWindow(IGUIApplication *app, const WindowState initialState, con
|
|||||||
autoShutdownGroup->addAction(m_ui->actionAutoShutdown);
|
autoShutdownGroup->addAction(m_ui->actionAutoShutdown);
|
||||||
autoShutdownGroup->addAction(m_ui->actionAutoSuspend);
|
autoShutdownGroup->addAction(m_ui->actionAutoSuspend);
|
||||||
autoShutdownGroup->addAction(m_ui->actionAutoHibernate);
|
autoShutdownGroup->addAction(m_ui->actionAutoHibernate);
|
||||||
|
autoShutdownGroup->addAction(m_ui->actionAutoReboot);
|
||||||
#if (!defined(Q_OS_UNIX) || defined(Q_OS_MACOS)) || defined(QBT_USES_DBUS)
|
#if (!defined(Q_OS_UNIX) || defined(Q_OS_MACOS)) || defined(QBT_USES_DBUS)
|
||||||
m_ui->actionAutoShutdown->setChecked(pref->shutdownWhenDownloadsComplete());
|
m_ui->actionAutoShutdown->setChecked(pref->shutdownWhenDownloadsComplete());
|
||||||
|
m_ui->actionAutoReboot->setChecked(pref->rebootWhenDownloadsComplete());
|
||||||
m_ui->actionAutoSuspend->setChecked(pref->suspendWhenDownloadsComplete());
|
m_ui->actionAutoSuspend->setChecked(pref->suspendWhenDownloadsComplete());
|
||||||
m_ui->actionAutoHibernate->setChecked(pref->hibernateWhenDownloadsComplete());
|
m_ui->actionAutoHibernate->setChecked(pref->hibernateWhenDownloadsComplete());
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
// macOS doesn't support Hibernate via Apple Events API
|
||||||
|
m_ui->actionAutoHibernate->setDisabled(true);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
m_ui->actionAutoShutdown->setDisabled(true);
|
m_ui->actionAutoShutdown->setDisabled(true);
|
||||||
m_ui->actionAutoSuspend->setDisabled(true);
|
m_ui->actionAutoSuspend->setDisabled(true);
|
||||||
@@ -1790,30 +1796,31 @@ void MainWindow::on_actionCriticalMessages_triggered(const bool checked)
|
|||||||
setExecutionLogMsgTypes(flags);
|
setExecutionLogMsgTypes(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAutoExit_toggled(bool enabled)
|
void MainWindow::on_actionAutoExit_toggled(const bool enabled)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << enabled;
|
|
||||||
Preferences::instance()->setShutdownqBTWhenDownloadsComplete(enabled);
|
Preferences::instance()->setShutdownqBTWhenDownloadsComplete(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAutoSuspend_toggled(bool enabled)
|
void MainWindow::on_actionAutoSuspend_toggled(const bool enabled)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << enabled;
|
|
||||||
Preferences::instance()->setSuspendWhenDownloadsComplete(enabled);
|
Preferences::instance()->setSuspendWhenDownloadsComplete(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAutoHibernate_toggled(bool enabled)
|
void MainWindow::on_actionAutoHibernate_toggled(const bool enabled)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << enabled;
|
|
||||||
Preferences::instance()->setHibernateWhenDownloadsComplete(enabled);
|
Preferences::instance()->setHibernateWhenDownloadsComplete(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAutoShutdown_toggled(bool enabled)
|
void MainWindow::on_actionAutoShutdown_toggled(const bool enabled)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << enabled;
|
|
||||||
Preferences::instance()->setShutdownWhenDownloadsComplete(enabled);
|
Preferences::instance()->setShutdownWhenDownloadsComplete(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionAutoReboot_toggled(const bool enabled)
|
||||||
|
{
|
||||||
|
Preferences::instance()->setRebootWhenDownloadsComplete(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updatePowerManagementState() const
|
void MainWindow::updatePowerManagementState() const
|
||||||
{
|
{
|
||||||
const auto *pref = Preferences::instance();
|
const auto *pref = Preferences::instance();
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ private slots:
|
|||||||
void on_actionAutoSuspend_toggled(bool);
|
void on_actionAutoSuspend_toggled(bool);
|
||||||
void on_actionAutoHibernate_toggled(bool);
|
void on_actionAutoHibernate_toggled(bool);
|
||||||
void on_actionAutoShutdown_toggled(bool);
|
void on_actionAutoShutdown_toggled(bool);
|
||||||
|
void on_actionAutoReboot_toggled(bool);
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
void on_actionStatistics_triggered();
|
void on_actionStatistics_triggered();
|
||||||
void on_actionCreateTorrent_triggered();
|
void on_actionCreateTorrent_triggered();
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
<addaction name="actionAutoExit"/>
|
<addaction name="actionAutoExit"/>
|
||||||
<addaction name="actionAutoSuspend"/>
|
<addaction name="actionAutoSuspend"/>
|
||||||
<addaction name="actionAutoHibernate"/>
|
<addaction name="actionAutoHibernate"/>
|
||||||
|
<addaction name="actionAutoReboot"/>
|
||||||
<addaction name="actionAutoShutdown"/>
|
<addaction name="actionAutoShutdown"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="actionCreateTorrent"/>
|
<addaction name="actionCreateTorrent"/>
|
||||||
@@ -397,6 +398,14 @@
|
|||||||
<string>Sh&utdown System</string>
|
<string>Sh&utdown System</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionAutoReboot">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Reboot System</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionAutoShutdownDisabled">
|
<action name="actionAutoShutdownDisabled">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ void ShutdownConfirmDialog::initText()
|
|||||||
okButton->setText(tr("&Hibernate Now"));
|
okButton->setText(tr("&Hibernate Now"));
|
||||||
setWindowTitle(tr("Hibernate confirmation"));
|
setWindowTitle(tr("Hibernate confirmation"));
|
||||||
break;
|
break;
|
||||||
|
case ShutdownDialogAction::Reboot:
|
||||||
|
m_msg = tr("The computer is going to reboot.");
|
||||||
|
okButton->setText(tr("&Reboot Now"));
|
||||||
|
setWindowTitle(tr("Reboot confirmation"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_msg += u'\n';
|
m_msg += u'\n';
|
||||||
|
|||||||
Reference in New Issue
Block a user