diff --git a/kcms/ksmserver/CMakeLists.txt b/kcms/ksmserver/CMakeLists.txt --- a/kcms/ksmserver/CMakeLists.txt +++ b/kcms/ksmserver/CMakeLists.txt @@ -3,6 +3,7 @@ set(kcm_smserver_PART_SRCS kcmsmserver.cpp smserverconfigimpl.cpp ) +qt5_add_dbus_interface(kcm_smserver_PART_SRCS org.freedesktop.login1.Manager.xml login1_manager) ki18n_wrap_ui(kcm_smserver_PART_SRCS smserverconfigdlg.ui ) 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,11 @@ #include +class QAction; + class SMServerConfigImpl; +class OrgFreedesktopLogin1ManagerInterface; class SMServerConfig : public KCModule { @@ -38,7 +41,13 @@ void defaults() override; private: + void initFirmwareSetup(); + void checkFirmwareSetupRequested(); SMServerConfigImpl* dialog; + + OrgFreedesktopLogin1ManagerInterface *m_login1Manager = nullptr; + 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,10 +46,18 @@ #include #include +#include "kworkspace.h" + +#include "login1_manager.h" + K_PLUGIN_FACTORY(SMSFactory, registerPlugin();) SMServerConfig::SMServerConfig(QWidget *parent, const QVariantList &args) : KCModule(parent, args) + , m_login1Manager(new OrgFreedesktopLogin1ManagerInterface(QStringLiteral("org.freedesktop.login1"), + QStringLiteral("/org/freedesktop/login1"), + QDBusConnection::systemBus(), + this)) { setQuickHelp( i18n("

Session Manager

" " You can configure the session manager here." @@ -59,9 +71,85 @@ 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(m_login1Manager->service(), + m_login1Manager->path(), + m_login1Manager->interface(), + QStringLiteral("SetRebootToFirmwareSetup")); + + message.setArguments({enable}); + // This cannot be set through a generated DBus interface, so we have to create the message ourself. + message.setInteractiveAuthorizationAllowed(true); + + QDBusPendingReply call = m_login1Manager->connection().asyncCall(message); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(call, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this, enable](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + watcher->deleteLater(); + + checkFirmwareSetupRequested(); + + KMessageWidget *message = dialog->firmwareSetupMessageWidget; + + if (reply.isError()) { + // User likely canceled the PolKit prompt, don't show an error in this case + if (reply.error().type() != QDBusError::AccessDenied) { + message->setMessageType(KMessageWidget::Error); + message->setText(i18n("Failed to request restart to firmware setup: %1", reply.error().message())); + message->animatedShow(); + } + return; + } + + if (!enable) { + return; + } + + message->setMessageType(KMessageWidget::Information); + if (m_isUefi) { + message->setText(i18n("Next time the computer is restarted, it will enter the UEFI setup screen.")); + } else { + message->setText(i18n("Next time the computer is restarted, it will enter the firmware setup screen.")); + } + message->addAction(m_rebootNowAction); + message->animatedShow(); + }); + }); + + const QString canFirmareSetup = m_login1Manager->CanRebootToFirmwareSetup().value(); + if (canFirmareSetup == QLatin1String("yes") || canFirmareSetup == QLatin1String("challenge")) { + // 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(true); + } +} + +void SMServerConfig::checkFirmwareSetupRequested() +{ + dialog->firmwareSetupCheck->setChecked(m_login1Manager->property("RebootToFirmwareSetup").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/org.freedesktop.login1.Manager.xml b/kcms/ksmserver/org.freedesktop.login1.Manager.xml new file mode 100644 --- /dev/null +++ b/kcms/ksmserver/org.freedesktop.login1.Manager.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + 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,32 @@ + + + + Firmware Setup + + + + + + true + + + + + + + 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 +170,10 @@ - QLineEdit -
qlineedit.h
+ KMessageWidget + QFrame +
kmessagewidget.h
+ 1
diff --git a/kcms/ksmserver/smserverconfigimpl.cpp b/kcms/ksmserver/smserverconfigimpl.cpp --- a/kcms/ksmserver/smserverconfigimpl.cpp +++ b/kcms/ksmserver/smserverconfigimpl.cpp @@ -27,6 +27,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(){ }