diff --git a/keyboard_layout.h b/keyboard_layout.h --- a/keyboard_layout.h +++ b/keyboard_layout.h @@ -22,11 +22,13 @@ #include "input_event_spy.h" #include +#include #include typedef uint32_t xkb_layout_index_t; class KStatusNotifierItem; +class QAction; namespace KWin { @@ -58,12 +60,15 @@ void initNotifierItem(); void switchToNextLayout(); void switchToPreviousLayout(); + void switchToLayout(xkb_layout_index_t index); void updateNotifier(); void reinitNotifierMenu(); + void loadShortcuts(); Xkb *m_xkb; xkb_layout_index_t m_layout = 0; KStatusNotifierItem *m_notifierItem; KSharedConfigPtr m_config; + QVector m_layoutShortcuts; }; } diff --git a/keyboard_layout.cpp b/keyboard_layout.cpp --- a/keyboard_layout.cpp +++ b/keyboard_layout.cpp @@ -46,6 +46,11 @@ KeyboardLayout::~KeyboardLayout() = default; +static QString translatedLayout(const QString &layout) +{ + return i18nd("xkeyboard-config", layout.toUtf8().constData()); +} + void KeyboardLayout::init() { QAction *switchKeyboardAction = new QAction(this); @@ -127,6 +132,12 @@ checkLayoutChange(); } +void KeyboardLayout::switchToLayout(xkb_layout_index_t index) +{ + m_xkb->switchToLayout(index); + checkLayoutChange(); +} + void KeyboardLayout::reconfigure() { m_xkb->reconfigure(); @@ -142,6 +153,30 @@ initNotifierItem(); updateNotifier(); reinitNotifierMenu(); + loadShortcuts(); +} + +void KeyboardLayout::loadShortcuts() +{ + qDeleteAll(m_layoutShortcuts); + m_layoutShortcuts.clear(); + const auto layouts = m_xkb->layoutNames(); + const QString componentName = QStringLiteral("KDE Keyboard Layout Switcher"); + for (auto it = layouts.begin(); it != layouts.end(); it++) { + // layout name is translated in the action name in keyboard kcm! + const QString action = QStringLiteral("Switch keyboard layout to %1").arg(translatedLayout(it.value())); + const auto shortcuts = KGlobalAccel::self()->globalShortcut(componentName, action); + if (shortcuts.isEmpty()) { + continue; + } + QAction *a = new QAction(this); + a->setObjectName(action); + a->setProperty("componentName", componentName); + connect(a, &QAction::triggered, this, + std::bind(&KeyboardLayout::switchToLayout, this, it.key())); + KGlobalAccel::self()->setShortcut(a, shortcuts, KGlobalAccel::Autoloading); + m_layoutShortcuts << a; + } } void KeyboardLayout::keyEvent(KeyEvent *event) @@ -171,7 +206,7 @@ QStringLiteral("org.kde.osdService"), QStringLiteral("kbdLayoutChanged")); - msg << i18nd("xkeyboard-config", m_xkb->layoutName().toUtf8().constData()); + msg << translatedLayout(m_xkb->layoutName()); QDBusConnection::sessionBus().asyncCall(msg); } @@ -181,7 +216,7 @@ if (!m_notifierItem) { return; } - m_notifierItem->setToolTipSubTitle(i18nd("xkeyboard-config", m_xkb->layoutName().toUtf8().constData())); + m_notifierItem->setToolTipSubTitle(translatedLayout(m_xkb->layoutName())); // TODO: update icon } @@ -193,12 +228,8 @@ const auto layouts = m_xkb->layoutNames(); QMenu *menu = new QMenu; - auto switchLayout = [this] (xkb_layout_index_t index) { - m_xkb->switchToLayout(index); - checkLayoutChange(); - }; for (auto it = layouts.begin(); it != layouts.end(); it++) { - menu->addAction(i18nd("xkeyboard-config", it.value().toUtf8().constData()), std::bind(switchLayout, it.key())); + menu->addAction(translatedLayout(it.value()), std::bind(&KeyboardLayout::switchToLayout, this, it.key())); } menu->addSeparator();