kcms/tabbox: Manage shortcuts via ShortcutSettings

Leverage the standardized ShortcutSettings config object to handle
the shortcuts config for the tabox (setting default values, reading
and saving to KGlobalAccel, etc).

This way, we can remove the extra methods in TabBoxConfigForm and
improve separation between UI and logic.

It also fixes the actions getting stored untranslated when saving
from the KCM (until next restart of KWin)
This commit is contained in:
Ismael Asensio 2023-02-07 07:59:25 +00:00 committed by Vlad Zahorodnii
parent d6315bebd0
commit e504c58286
5 changed files with 68 additions and 121 deletions

View file

@ -11,19 +11,18 @@
#include "kwintabboxconfigform.h"
#include "kwintabboxsettings.h"
#include "shortcutsettings.h"
#include "ui_main.h"
#include <KActionCollection>
#include <KGlobalAccel>
namespace KWin
{
using namespace TabBox;
KWinTabBoxConfigForm::KWinTabBoxConfigForm(TabboxType type, TabBoxSettings *config, QWidget *parent)
KWinTabBoxConfigForm::KWinTabBoxConfigForm(TabboxType type, TabBoxSettings *config, ShortcutSettings *shortcutsConfig, QWidget *parent)
: QWidget(parent)
, m_config(config)
, m_shortcuts(shortcutsConfig)
, ui(new Ui::KWinTabBoxConfigForm)
{
ui->setupUi(this);
@ -64,34 +63,22 @@ KWinTabBoxConfigForm::KWinTabBoxConfigForm(TabboxType type, TabBoxSettings *conf
connect(ui->switchingModeCombo, qOverload<int>(&QComboBox::currentIndexChanged), this, &KWinTabBoxConfigForm::onSwitchingMode);
connect(ui->effectCombo, qOverload<int>(&QComboBox::currentIndexChanged), this, &KWinTabBoxConfigForm::onEffectCombo);
auto addShortcut = [this](const char *name, KKeySequenceWidget *widget, const QKeySequence &sequence = QKeySequence()) {
QAction *action = m_actionCollection->addAction(name);
action->setProperty("isConfigurationAction", true);
action->setText(i18n(name));
m_actionCollection->setDefaultShortcut(action, sequence);
widget->setCheckActionCollections({m_actionCollection});
auto initShortcutWidget = [this](KKeySequenceWidget *widget, const char *name) {
widget->setCheckActionCollections({m_shortcuts->actionCollection()});
widget->setProperty("shortcutAction", name);
connect(widget, &KKeySequenceWidget::keySequenceChanged, this, &KWinTabBoxConfigForm::onShortcutChanged);
};
// Shortcut config. The shortcut belongs to the component "kwin"!
m_actionCollection = new KActionCollection(this, QStringLiteral("kwin"));
m_actionCollection->setComponentDisplayName(i18n("KWin"));
m_actionCollection->setConfigGroup("Navigation");
m_actionCollection->setConfigGlobal(true);
if (TabboxType::Main == type) {
addShortcut("Walk Through Windows", ui->scAll, Qt::ALT | Qt::Key_Tab);
addShortcut("Walk Through Windows (Reverse)", ui->scAllReverse, Qt::ALT | Qt::SHIFT | Qt::Key_Backtab);
addShortcut("Walk Through Windows of Current Application", ui->scCurrent, Qt::ALT | Qt::Key_QuoteLeft);
addShortcut("Walk Through Windows of Current Application (Reverse)", ui->scCurrentReverse, Qt::ALT | Qt::Key_AsciiTilde);
initShortcutWidget(ui->scAll, "Walk Through Windows");
initShortcutWidget(ui->scAllReverse, "Walk Through Windows (Reverse)");
initShortcutWidget(ui->scCurrent, "Walk Through Windows of Current Application");
initShortcutWidget(ui->scCurrentReverse, "Walk Through Windows of Current Application (Reverse)");
} else if (TabboxType::Alternative == type) {
addShortcut("Walk Through Windows Alternative", ui->scAll);
addShortcut("Walk Through Windows Alternative (Reverse)", ui->scAllReverse);
addShortcut("Walk Through Windows of Current Application Alternative", ui->scCurrent);
addShortcut("Walk Through Windows of Current Application Alternative (Reverse)", ui->scCurrentReverse);
initShortcutWidget(ui->scAll, "Walk Through Windows Alternative");
initShortcutWidget(ui->scAllReverse, "Walk Through Windows Alternative (Reverse)");
initShortcutWidget(ui->scCurrent, "Walk Through Windows of Current Application Alternative");
initShortcutWidget(ui->scCurrentReverse, "Walk Through Windows of Current Application Alternative (Reverse)");
}
updateUiFromConfig();
@ -247,62 +234,6 @@ QVariant KWinTabBoxConfigForm::effectComboCurrentData(int role) const
return ui->effectCombo->currentData(role);
}
void KWinTabBoxConfigForm::loadShortcuts()
{
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
const auto shortcuts = KGlobalAccel::self()->globalShortcut(QStringLiteral("kwin"), actionName);
if (!shortcuts.isEmpty()) {
widget->setKeySequence(shortcuts.first());
}
}
}
void KWinTabBoxConfigForm::resetShortcuts()
{
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
QAction *action = m_actionCollection->action(actionName);
widget->setKeySequence(m_actionCollection->defaultShortcut(action));
}
}
void KWinTabBoxConfigForm::saveShortcuts()
{
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
QAction *action = m_actionCollection->action(actionName);
KGlobalAccel::self()->setShortcut(action, {action->shortcut()}, KGlobalAccel::NoAutoloading);
}
}
bool KWinTabBoxConfigForm::isShortcutsChanged() const
{
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
QAction *action = m_actionCollection->action(actionName);
const auto shortcuts = KGlobalAccel::self()->globalShortcut(QStringLiteral("kwin"), actionName);
const QKeySequence savedShortcut = shortcuts.isEmpty() ? QKeySequence() : shortcuts.first();
if (action->shortcut() != savedShortcut) {
return true;
}
}
return false;
}
bool KWinTabBoxConfigForm::isShortcutsDefault() const
{
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
QAction *action = m_actionCollection->action(actionName);
if (action->shortcut() != m_actionCollection->defaultShortcut(action)) {
return false;
}
}
return true;
}
void KWinTabBoxConfigForm::tabBoxToggled(bool on)
{
// Highlight Windows options is availabled if no TabBox effect is selected
@ -374,15 +305,8 @@ void KWinTabBoxConfigForm::onEffectCombo()
void KWinTabBoxConfigForm::onShortcutChanged(const QKeySequence &seq)
{
QString actionName;
if (sender()) {
actionName = sender()->property("shortcutAction").toString();
}
if (actionName.isEmpty()) {
return;
}
QAction *action = m_actionCollection->action(actionName);
action->setShortcut(seq);
const QString actionName = sender()->property("shortcutAction").toString();
m_shortcuts->setShortcut(actionName, seq);
Q_EMIT configChanged();
}
@ -399,6 +323,11 @@ void KWinTabBoxConfigForm::updateUiFromConfig()
setSwitchingModeChanged(static_cast<TabBoxConfig::ClientSwitchingMode>(m_config->switchingMode()));
setLayoutName(m_config->layoutName());
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
widget->setKeySequence(m_shortcuts->shortcut(actionName));
}
updateDefaultIndicators();
}
@ -454,9 +383,7 @@ void KWinTabBoxConfigForm::updateDefaultIndicators()
for (const auto &widget : {ui->scAll, ui->scAllReverse, ui->scCurrent, ui->scCurrentReverse}) {
const QString actionName = widget->property("shortcutAction").toString();
QAction *action = m_actionCollection->action(actionName);
const bool isDefault = (action->shortcut() == m_actionCollection->defaultShortcut(action));
applyDefaultIndicator({widget}, isDefault);
applyDefaultIndicator({widget}, m_shortcuts->isDefault(actionName));
}
}

View file

@ -16,8 +16,6 @@
#include "tabboxconfig.h"
class KActionCollection;
namespace Ui
{
class KWinTabBoxConfigForm;
@ -29,6 +27,7 @@ namespace KWin
namespace TabBox
{
class TabBoxSettings;
class ShortcutSettings;
}
class KWinTabBoxConfigForm : public QWidget
@ -46,7 +45,7 @@ public:
AddonEffect, // i.e not builtin effects
};
explicit KWinTabBoxConfigForm(TabboxType type, TabBox::TabBoxSettings *config, QWidget *parent = nullptr);
explicit KWinTabBoxConfigForm(TabboxType type, TabBox::TabBoxSettings *config, TabBox::ShortcutSettings *shortcutsConfig, QWidget *parent = nullptr);
~KWinTabBoxConfigForm() override;
TabBox::TabBoxSettings *config() const;
@ -59,12 +58,6 @@ public:
void setEffectComboModel(QStandardItemModel *model);
QVariant effectComboCurrentData(int role = Qt::UserRole) const;
void loadShortcuts();
void resetShortcuts();
void saveShortcuts();
bool isShortcutsChanged() const;
bool isShortcutsDefault() const;
Q_SIGNALS:
void configChanged();
void effectConfigButtonClicked();
@ -111,8 +104,8 @@ private:
void setLayoutName(const QString &layoutName);
private:
KActionCollection *m_actionCollection = nullptr;
TabBox::TabBoxSettings *m_config = nullptr;
TabBox::ShortcutSettings *m_shortcuts = nullptr;
bool m_showDefaultIndicator = false;
bool m_isHighlightWindowsEnabled = true;

View file

@ -40,6 +40,7 @@
#include "kwintabboxdata.h"
#include "kwintabboxsettings.h"
#include "layoutpreview.h"
#include "shortcutsettings.h"
K_PLUGIN_FACTORY_WITH_JSON(KWinTabBoxConfigFactory, "kcm_kwintabbox.json", registerPlugin<KWin::KWinTabBoxConfig>(); registerPlugin<KWin::TabBox::KWinTabboxData>();)
@ -54,8 +55,14 @@ KWinTabBoxConfig::KWinTabBoxConfig(QWidget *parent, const QVariantList &args)
, m_data(new KWinTabboxData(this))
{
QTabWidget *tabWidget = new QTabWidget(this);
m_primaryTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Main, m_data->tabBoxConfig(), tabWidget);
m_alternativeTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Alternative, m_data->tabBoxAlternativeConfig(), tabWidget);
m_primaryTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Main,
m_data->tabBoxConfig(),
m_data->shortcutConfig(),
tabWidget);
m_alternativeTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Alternative,
m_data->tabBoxAlternativeConfig(),
m_data->shortcutConfig(),
tabWidget);
tabWidget->addTab(m_primaryTabBoxUi, i18n("Main"));
tabWidget->addTab(m_alternativeTabBoxUi, i18n("Alternative"));
@ -194,15 +201,15 @@ void KWinTabBoxConfig::createConnections(KWinTabBoxConfigForm *form)
void KWinTabBoxConfig::updateUnmanagedState()
{
bool isNeedSave = false;
isNeedSave |= m_data->tabBoxConfig()->isSaveNeeded() || m_primaryTabBoxUi->isShortcutsChanged();
isNeedSave |= m_data->tabBoxAlternativeConfig()->isSaveNeeded() || m_alternativeTabBoxUi->isShortcutsChanged();
const bool isNeedSave = m_data->tabBoxConfig()->isSaveNeeded()
|| m_data->tabBoxAlternativeConfig()->isSaveNeeded()
|| m_data->shortcutConfig()->isSaveNeeded();
unmanagedWidgetChangeState(isNeedSave);
bool isDefault = true;
isDefault &= m_data->tabBoxConfig()->isDefaults() && m_primaryTabBoxUi->isShortcutsDefault();
isDefault &= m_data->tabBoxAlternativeConfig()->isDefaults() && m_alternativeTabBoxUi->isShortcutsDefault();
const bool isDefault = m_data->tabBoxConfig()->isDefaults()
&& m_data->tabBoxAlternativeConfig()->isDefaults()
&& m_data->shortcutConfig()->isDefaults();
unmanagedWidgetDefaultState(isDefault);
}
@ -213,15 +220,13 @@ void KWinTabBoxConfig::load()
m_data->tabBoxConfig()->load();
m_data->tabBoxAlternativeConfig()->load();
m_data->shortcutConfig()->load();
m_data->pluginsConfig()->load();
m_primaryTabBoxUi->updateUiFromConfig();
m_alternativeTabBoxUi->updateUiFromConfig();
m_primaryTabBoxUi->loadShortcuts();
m_alternativeTabBoxUi->loadShortcuts();
updateUnmanagedState();
}
@ -234,11 +239,9 @@ void KWinTabBoxConfig::save()
m_data->pluginsConfig()->setHighlightwindowEnabled(highlightWindows);
m_data->pluginsConfig()->save();
m_primaryTabBoxUi->saveShortcuts();
m_alternativeTabBoxUi->saveShortcuts();
m_data->tabBoxConfig()->save();
m_data->tabBoxAlternativeConfig()->save();
m_data->shortcutConfig()->save();
KCModule::save();
updateUnmanagedState();
@ -252,13 +255,11 @@ void KWinTabBoxConfig::defaults()
{
m_data->tabBoxConfig()->setDefaults();
m_data->tabBoxAlternativeConfig()->setDefaults();
m_data->shortcutConfig()->setDefaults();
m_primaryTabBoxUi->updateUiFromConfig();
m_alternativeTabBoxUi->updateUiFromConfig();
m_primaryTabBoxUi->resetShortcuts();
m_alternativeTabBoxUi->resetShortcuts();
KCModule::defaults();
updateUnmanagedState();
}

View file

@ -145,5 +145,26 @@ KActionCollection *ShortcutSettings::actionCollection() const
return m_actionCollection;
}
QKeySequence ShortcutSettings::shortcut(const QString &name) const
{
QAction *action = m_actionCollection->action(name);
Q_ASSERT(action);
return action->shortcut();
}
void ShortcutSettings::setShortcut(const QString &name, const QKeySequence &seq)
{
QAction *action = m_actionCollection->action(name);
Q_ASSERT(action);
action->setShortcut(seq);
}
bool ShortcutSettings::isDefault(const QString &name) const
{
QAction *action = m_actionCollection->action(name);
Q_ASSERT(action);
return action->shortcut() == m_actionCollection->defaultShortcut(action);
}
} // namespace TabBox
} // namespace KWin

View file

@ -27,6 +27,11 @@ public:
KActionCollection *actionCollection() const;
QKeySequence shortcut(const QString &name) const;
void setShortcut(const QString &name, const QKeySequence &seq);
bool isDefault(const QString &name) const;
private:
KActionCollection *m_actionCollection = nullptr;
};