diff --git a/kcms/ksmserver/kcmsmserver.h b/kcms/ksmserver/kcmsmserver.h --- a/kcms/ksmserver/kcmsmserver.h +++ b/kcms/ksmserver/kcmsmserver.h @@ -23,8 +23,9 @@ #include -class SMServerConfigImpl; +class QAction; +class SMServerConfigImpl; class SMServerConfig : public KCModule { @@ -38,7 +39,12 @@ void defaults() override; private: + void initFirmwareSetup(); + void checkFirmwareSetupRequested(); SMServerConfigImpl* dialog; + + QAction *m_rebootNowAction = nullptr; + bool m_isUefi = false; }; #endif diff --git a/kcms/ksmserver/kcmsmserver.cpp b/kcms/ksmserver/kcmsmserver.cpp --- a/kcms/ksmserver/kcmsmserver.cpp +++ b/kcms/ksmserver/kcmsmserver.cpp @@ -19,11 +19,15 @@ * along with this program; if not, write to the Free Software */ +#include +#include +#include +#include #include +#include //Added by qt3to4: #include - #include #include #include @@ -42,8 +46,18 @@ #include #include +#include "kworkspace.h" + K_PLUGIN_FACTORY(SMSFactory, registerPlugin();) +static const QString s_login1Service = QStringLiteral("org.freedesktop.login1"); +static const QString s_login1Path = QStringLiteral("/org/freedesktop/login1"); +static const QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties"); +static const QString s_login1ManagerInterface = QStringLiteral("org.freedesktop.login1.Manager"); +static const QString s_login1RebootToFirmwareSetup = QStringLiteral("RebootToFirmwareSetup"); +static const QString s_login1CanRebootToFirmwareSetup = QStringLiteral("CanRebootToFirmwareSetup"); +static const QString s_login1SetRebootToFirmwareSetup = QStringLiteral("SetRebootToFirmwareSetup"); + SMServerConfig::SMServerConfig(QWidget *parent, const QVariantList &args) : KCModule(parent, args) { @@ -59,9 +73,109 @@ dialog = new SMServerConfigImpl(this); connect(dialog, SIGNAL(changed()), SLOT(changed())); + initFirmwareSetup(); + checkFirmwareSetupRequested(); + topLayout->addWidget(dialog); } +void SMServerConfig::initFirmwareSetup() +{ + m_rebootNowAction = new QAction(QIcon::fromTheme(QStringLiteral("system-reboot")), i18n("Restart Now")); + connect(m_rebootNowAction, &QAction::triggered, this, [] { + KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmNo, KWorkSpace::ShutdownTypeReboot); + }); + + connect(dialog->firmwareSetupCheck, &QCheckBox::clicked, this, [this](bool enable) { + dialog->firmwareSetupMessageWidget->removeAction(m_rebootNowAction); + dialog->firmwareSetupMessageWidget->animatedHide(); + + QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + s_login1Path, + s_login1ManagerInterface, + s_login1SetRebootToFirmwareSetup); + message.setArguments({enable}); + message.setInteractiveAuthorizationAllowed(true); + + QDBusPendingReply call = QDBusConnection::systemBus().asyncCall(message); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(call, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this, enable](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + watcher->deleteLater(); + + checkFirmwareSetupRequested(); + + if (reply.isError()) { + // User likely canceled the PolKit prompt, don't show an error in this case + if (reply.error().type() != QDBusError::AccessDenied) { + dialog->firmwareSetupMessageWidget->setMessageType(KMessageWidget::Error); + dialog->firmwareSetupMessageWidget->setText(i18n("Failed to request restart to firmware setup: %1", reply.error().message())); + dialog->firmwareSetupMessageWidget->animatedShow(); + } + return; + } + + if (enable) { + dialog->firmwareSetupMessageWidget->setMessageType(KMessageWidget::Information); + if (m_isUefi) { + dialog->firmwareSetupMessageWidget->setText(i18n("Next time the computer is restarted, it will enter the UEFI setup screen.")); + } else { + dialog->firmwareSetupMessageWidget->setText(i18n("Next time the computer is restarted, it will enter the firmware setup screen.")); + } + dialog->firmwareSetupMessageWidget->addAction(m_rebootNowAction); + dialog->firmwareSetupMessageWidget->animatedShow(); + } + }); + }); + + QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + s_login1Path, + s_login1ManagerInterface, + s_login1CanRebootToFirmwareSetup); + QDBusPendingReply call = QDBusConnection::systemBus().asyncCall(message); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(call, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + watcher->deleteLater(); + + const bool canFirmwareSetup = (reply.value() == QLatin1String("yes") + || reply.value() == QLatin1String("challenge")); + + if (!canFirmwareSetup) { + return; + } + + // now check whether we're UEFI to provide a more descriptive button label + if (QFileInfo(QStringLiteral("/sys/firmware/efi")).isDir()) { + m_isUefi = true; + dialog->firmwareSetupBox->setTitle(i18n("UEFI Setup")); + dialog->firmwareSetupCheck->setText(i18n("Enter UEFI setup on next restart")); + } + + dialog->firmwareSetupBox->setVisible(canFirmwareSetup); + }); +} + +void SMServerConfig::checkFirmwareSetupRequested() +{ + QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + s_login1Path, + s_dbusPropertiesInterface, + QStringLiteral("Get")); + message.setArguments({s_login1ManagerInterface, s_login1RebootToFirmwareSetup}); + + QDBusPendingReply call = QDBusConnection::systemBus().asyncCall(message); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(call, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + watcher->deleteLater(); + + if (reply.value().isValid()) { + dialog->firmwareSetupCheck->setChecked(reply.value().toBool()); + } + }); +} + void SMServerConfig::load() { KConfigGroup c(KSharedConfig::openConfig(QStringLiteral("ksmserverrc"), KConfig::NoGlobals), diff --git a/kcms/ksmserver/kcmsmserver.desktop b/kcms/ksmserver/kcmsmserver.desktop --- a/kcms/ksmserver/kcmsmserver.desktop +++ b/kcms/ksmserver/kcmsmserver.desktop @@ -102,7 +102,7 @@ Comment[zh_CN]=桌面会话登录和注销 Comment[zh_TW]=桌面作業階段登入與登出 -X-KDE-Keywords=ksmserver,session,logout,confirmation,save,restore +X-KDE-Keywords=ksmserver,session,logout,confirmation,save,restore,efi,uefi,bios X-KDE-Keywords[bs]=ksmserver,sesija,odjava,potvrda,snimanje,vrati X-KDE-Keywords[ca]=ksmserver,sessió,sortida,confirmació,desa,restaura X-KDE-Keywords[ca@valencia]=ksmserver,sessió,eixida,confirmació,guarda,restaura diff --git a/kcms/ksmserver/smserverconfigdlg.ui b/kcms/ksmserver/smserverconfigdlg.ui --- a/kcms/ksmserver/smserverconfigdlg.ui +++ b/kcms/ksmserver/smserverconfigdlg.ui @@ -127,6 +127,28 @@ + + + + Firmware Setup + + + + + + + + + When the computer is restarted the next time, enter firmware setup screen (e.g. UEFI or BIOS setup) + + + Enter firmware setup on next restart + + + + + + @@ -144,8 +166,10 @@ - QLineEdit -
qlineedit.h
+ KMessageWidget + QFrame +
kmessagewidget.h
+ 1
diff --git a/kcms/ksmserver/smserverconfigimpl.h b/kcms/ksmserver/smserverconfigimpl.h --- a/kcms/ksmserver/smserverconfigimpl.h +++ b/kcms/ksmserver/smserverconfigimpl.h @@ -39,6 +39,7 @@ public: SMServerConfigImpl(QWidget *parent=nullptr); ~SMServerConfigImpl() override; + public Q_SLOTS: // Public slots /** No descriptions */ void configChanged(); diff --git a/kcms/ksmserver/smserverconfigimpl.cpp b/kcms/ksmserver/smserverconfigimpl.cpp --- a/kcms/ksmserver/smserverconfigimpl.cpp +++ b/kcms/ksmserver/smserverconfigimpl.cpp @@ -17,6 +17,8 @@ #include "smserverconfigimpl.h" +#include + SMServerConfigImpl::SMServerConfigImpl(QWidget *parent ) : SMServerConfigDlg(parent) { connect(confirmLogoutCheck,&QAbstractButton::toggled, this, &SMServerConfigImpl::configChanged); connect(previousSessionRadio,&QAbstractButton::toggled, this, &SMServerConfigImpl::configChanged); @@ -27,6 +29,10 @@ connect(rebootRadio,&QAbstractButton::toggled, this, &SMServerConfigImpl::configChanged); connect(excludeLineedit,&QLineEdit::textChanged,this, &SMServerConfigImpl::configChanged); connect(offerShutdownCheck,&QAbstractButton::toggled,this, &SMServerConfigImpl::configChanged); + + firmwareSetupBox->hide(); + + firmwareSetupMessageWidget->hide(); } SMServerConfigImpl::~SMServerConfigImpl(){ }