File indexing completed on 2024-05-12 17:07:19

0001 /*
0002     kcmsmserver.cpp
0003     SPDX-FileCopyrightText: 2000, 2002 Oswald Buddenhagen <ossi@kde.org>
0004 
0005     based on kcmtaskbar.cpp
0006     SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
0007 
0008     SPDX-FileCopyrightText: 2019 Kevin Ottens <kevin.ottens@enioka.com>
0009     SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
0010 
0011     SPDX-License-Identifier: GPL-2.0-or-later
0012 */
0013 
0014 #include <QAction>
0015 #include <QDBusConnection>
0016 #include <QDBusPendingCallWatcher>
0017 #include <QDBusPendingReply>
0018 #include <QFileInfo>
0019 
0020 #include <KDesktopFile>
0021 #include <KPluginFactory>
0022 #include <KProcess>
0023 #include <QDBusInterface>
0024 #include <kworkspace.h>
0025 
0026 #include "kcmsmserver.h"
0027 #include "smserverdata.h"
0028 #include "smserversettings.h"
0029 
0030 #include <KLocalizedString>
0031 
0032 #include <sessionmanagement.h>
0033 
0034 #include "login1_manager.h"
0035 
0036 K_PLUGIN_FACTORY_WITH_JSON(SMServerConfigFactory, "kcm_smserver.json", registerPlugin<SMServerConfig>(); registerPlugin<SMServerData>();)
0037 
0038 SMServerConfig::SMServerConfig(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0039     : KQuickAddons::ManagedConfigModule(parent, metaData, args)
0040     , m_login1Manager(new OrgFreedesktopLogin1ManagerInterface(QStringLiteral("org.freedesktop.login1"),
0041                                                                QStringLiteral("/org/freedesktop/login1"),
0042                                                                QDBusConnection::systemBus(),
0043                                                                this))
0044 {
0045     auto settings = new SMServerSettings(this);
0046     qmlRegisterSingletonInstance("org.kde.desktopsession.private", 1, 0, "Settings", settings);
0047 
0048     setQuickHelp(
0049         i18n("<h1>Session Manager</h1>"
0050              " You can configure the session manager here."
0051              " This includes options such as whether or not the session exit (logout)"
0052              " should be confirmed, whether the session should be restored again when logging in"
0053              " and whether the computer should be automatically shut down after session"
0054              " exit by default."));
0055 
0056     checkFirmwareSetupRequested();
0057     m_restartInSetupScreenInitial = m_restartInSetupScreen;
0058 
0059     setButtons(Help | Apply | Default);
0060 
0061     const QString canFirmwareSetup = m_login1Manager->CanRebootToFirmwareSetup().value();
0062     if (canFirmwareSetup == QLatin1String("yes") || canFirmwareSetup == QLatin1String("challenge")) {
0063         m_canFirmwareSetup = true;
0064         // now check whether we're UEFI to provide a more descriptive button label
0065         if (QFileInfo(QStringLiteral("/sys/firmware/efi")).isDir()) {
0066             m_isUefi = true;
0067         }
0068     }
0069 }
0070 
0071 SMServerConfig::~SMServerConfig() = default;
0072 
0073 bool SMServerConfig::isUefi() const
0074 {
0075     return m_isUefi;
0076 }
0077 
0078 bool SMServerConfig::restartInSetupScreen() const
0079 {
0080     return m_restartInSetupScreen;
0081 }
0082 
0083 void SMServerConfig::setRestartInSetupScreen(bool restartInSetupScreen)
0084 {
0085     if (m_restartInSetupScreen == restartInSetupScreen) {
0086         return;
0087     }
0088 
0089     QDBusMessage message = QDBusMessage::createMethodCall(m_login1Manager->service(),
0090                                                           m_login1Manager->path(),
0091                                                           m_login1Manager->interface(),
0092                                                           QStringLiteral("SetRebootToFirmwareSetup"));
0093 
0094     message.setArguments({restartInSetupScreen});
0095     // This cannot be set through a generated DBus interface, so we have to create the message ourself.
0096     message.setInteractiveAuthorizationAllowed(true);
0097 
0098     QDBusPendingReply<void> call = m_login1Manager->connection().asyncCall(message);
0099     QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(call, this);
0100     connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this, restartInSetupScreen](QDBusPendingCallWatcher *watcher) {
0101         QDBusPendingReply<void> reply = *watcher;
0102         watcher->deleteLater();
0103 
0104         checkFirmwareSetupRequested();
0105 
0106         settingsChanged();
0107 
0108         if (reply.isError()) {
0109             // User likely canceled the PolKit prompt, don't show an error in this case
0110             if (reply.error().type() != QDBusError::AccessDenied) {
0111                 m_error = reply.error().message();
0112                 Q_EMIT errorChanged();
0113             }
0114             return;
0115         } else if (m_error.length() > 0) {
0116             m_error = QString();
0117             Q_EMIT errorChanged();
0118         }
0119         m_restartInSetupScreen = restartInSetupScreen;
0120         Q_EMIT restartInSetupScreenChanged();
0121 
0122         if (!restartInSetupScreen) {
0123             return;
0124         }
0125     });
0126 }
0127 
0128 QString SMServerConfig::error() const
0129 {
0130     return m_error;
0131 }
0132 
0133 void SMServerConfig::reboot()
0134 {
0135     auto sm = new SessionManagement(this);
0136     auto doShutdown = [sm]() {
0137         sm->requestReboot();
0138         delete sm;
0139     };
0140     if (sm->state() == SessionManagement::State::Loading) {
0141         connect(sm, &SessionManagement::stateChanged, this, doShutdown);
0142     } else {
0143         doShutdown();
0144     }
0145 }
0146 
0147 void SMServerConfig::checkFirmwareSetupRequested()
0148 {
0149     m_restartInSetupScreen = m_login1Manager->property("RebootToFirmwareSetup").toBool();
0150     Q_EMIT restartInSetupScreenChanged();
0151 }
0152 
0153 bool SMServerConfig::canFirmwareSetup() const
0154 {
0155     return m_canFirmwareSetup;
0156 }
0157 
0158 bool SMServerConfig::isSaveNeeded() const
0159 {
0160     return m_restartInSetupScreen != m_restartInSetupScreenInitial;
0161 }
0162 
0163 bool SMServerConfig::isDefaults() const
0164 {
0165     return !m_restartInSetupScreen;
0166 }
0167 
0168 void SMServerConfig::defaults()
0169 {
0170     ManagedConfigModule::defaults();
0171     setRestartInSetupScreen(false);
0172 }
0173 
0174 void SMServerConfig::save()
0175 {
0176     ManagedConfigModule::save();
0177     Q_EMIT ksmserverSettingsChanged();
0178 }
0179 
0180 #include "kcmsmserver.moc"