From 4c8217008593f34fdd70ce8b579d1979a6b994a4 Mon Sep 17 00:00:00 2001 From: Ezike Ebuka Date: Tue, 19 Oct 2021 11:32:11 -0600 Subject: [PATCH] Add "Configure Displays" action to desktop context menu With a multi-screen setup, it's possible to get into a situation where all of your means to launch apps have gone missing because a screen forgot its containmewt or moved the only panel onto a disabled output, or any number of other issues that unfortunately have not yet been resolved. In such a situation, it is common for people to try to fix it by visiting the KScreen KCM to switch around their primary screens, enable disabled outputs, turn it off and on again, etc. However if your only visible means to launch apps has gone missing, you may have a hard time accessing the KScreen KCM. In such a circumstance, it can be helpful to have the action in the desktop context menu so that people can right-click on the wallpaper of any screen that *is* working and make System Settings launch with the KScreen KCM on that screen. Co-authored-by: Nate Graham BUG: 355679 FIXED-IN: 5.24 --- containmentactions/contextmenu/CMakeLists.txt | 1 + containmentactions/contextmenu/menu.cpp | 35 +++++++++++++++++++ containmentactions/contextmenu/menu.h | 2 ++ 3 files changed, 38 insertions(+) diff --git a/containmentactions/contextmenu/CMakeLists.txt b/containmentactions/contextmenu/CMakeLists.txt index 5bb3c37bf..eec7aaf21 100644 --- a/containmentactions/contextmenu/CMakeLists.txt +++ b/containmentactions/contextmenu/CMakeLists.txt @@ -20,4 +20,5 @@ target_link_libraries(plasma_containmentactions_contextmenu KF5::Plasma KF5::XmlGui KF5::KIOCore + KF5::KIOGui PW::KWorkspace) diff --git a/containmentactions/contextmenu/menu.cpp b/containmentactions/contextmenu/menu.cpp index cea852bb8..7c87dc4b2 100644 --- a/containmentactions/contextmenu/menu.cpp +++ b/containmentactions/contextmenu/menu.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ ContextMenu::ContextMenu(QObject *parent, const QVariantList &args) , m_runCommandAction(nullptr) , m_lockScreenAction(nullptr) , m_logoutAction(nullptr) + , m_configureDisplaysAction(nullptr) , m_separator1(nullptr) , m_separator2(nullptr) , m_separator3(nullptr) @@ -52,6 +54,8 @@ void ContextMenu::restore(const KConfigGroup &config) QHash actions; QSet disabled; + // clang-format off + // because it really wants to mangle this nice aligned list if (c->containmentType() == Plasma::Types::PanelContainment || c->containmentType() == Plasma::Types::CustomPanelContainment) { m_actionOrder << QStringLiteral("add widgets") << QStringLiteral("_add panel") @@ -61,6 +65,7 @@ void ContextMenu::restore(const KConfigGroup &config) } else { actions.insert(QStringLiteral("configure shortcuts"), false); m_actionOrder << QStringLiteral("configure") + << QStringLiteral("_display_settings") << QStringLiteral("run associated application") << QStringLiteral("configure shortcuts") << QStringLiteral("_sep1") @@ -79,6 +84,7 @@ void ContextMenu::restore(const KConfigGroup &config) disabled.insert(QStringLiteral("configure shortcuts")); disabled.insert(QStringLiteral("_run_command")); } + // clang-format on for (const QString &name : qAsConst(m_actionOrder)) { actions.insert(name, !disabled.contains(name)); @@ -115,6 +121,10 @@ void ContextMenu::restore(const KConfigGroup &config) }); connect(m_logoutAction, &QAction::triggered, this, &ContextMenu::startLogout); + m_configureDisplaysAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Configure Display Settings…"), this); + m_configureDisplaysAction->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-display"))); + connect(m_configureDisplaysAction, &QAction::triggered, this, &ContextMenu::configureDisplays); + m_separator1 = new QAction(this); m_separator1->setSeparator(true); m_separator2 = new QAction(this); @@ -183,6 +193,10 @@ QAction *ContextMenu::action(const QString &name) if (KAuthorized::authorize(QStringLiteral("logout"))) { return m_logoutAction; } + } else if (name == QLatin1String("_display_settings")) { + if (KAuthorized::authorizeControlModule(QStringLiteral("kcm_kscreen.desktop")) && KService::serviceByStorageId(QStringLiteral("kcm_kscreen"))) { + return m_configureDisplaysAction; + } } else if (name == QLatin1String("edit mode")) { if (c->corona()) { return c->corona()->actions()->action(QStringLiteral("edit mode")); @@ -226,6 +240,27 @@ void ContextMenu::startLogout() } } +// FIXME: this function contains some code copied from KCMShell::openSystemSettings() +// which is not publicly available to C++ code right now. Eventually we should +// move that code into KIO so it's accessible to everyone, and then call that +// function instead of this one +void ContextMenu::configureDisplays() +{ + const QString systemSettings = QStringLiteral("systemsettings"); + const QString kscreenKCM = QStringLiteral("kcm_kscreen"); + + KIO::CommandLauncherJob *job = nullptr; + + // Open in System Settings if it's available + if (KService::serviceByDesktopName(systemSettings)) { + job = new KIO::CommandLauncherJob(QStringLiteral("systemsettings5"), {kscreenKCM}); + job->setDesktopName(systemSettings); + } else { + job = new KIO::CommandLauncherJob(QStringLiteral("kcmshell5"), {kscreenKCM}); + } + job->start(); +} + QWidget *ContextMenu::createConfigurationInterface(QWidget *parent) { QWidget *widget = new QWidget(parent); diff --git a/containmentactions/contextmenu/menu.h b/containmentactions/contextmenu/menu.h index 57f2fb0b8..7296b458f 100644 --- a/containmentactions/contextmenu/menu.h +++ b/containmentactions/contextmenu/menu.h @@ -30,11 +30,13 @@ public: public Q_SLOTS: void runCommand(); void startLogout(); + void configureDisplays(); private: QAction *m_runCommandAction; QAction *m_lockScreenAction; QAction *m_logoutAction; + QAction *m_configureDisplaysAction; QAction *m_separator1; QAction *m_separator2; QAction *m_separator3;