diff options
author | David Redondo <kde@david-redondo.de> | 2022-01-13 10:04:13 +0100 |
---|---|---|
committer | David Redondo <kde@david-redondo.de> | 2022-01-24 13:23:55 +0000 |
commit | 820dc0a553e50cc4560733d43fca2674a61d43b3 (patch) | |
tree | 6a89465d257b5b238b6bcd6a7f2f339ac167b9b6 | |
parent | 41d37407e80f5ccd110cf303c20a181f95fa7e73 (diff) | |
download | kconfig-820dc0a553e50cc4560733d43fca2674a61d43b3.tar.gz kconfig-820dc0a553e50cc4560733d43fca2674a61d43b3.tar.bz2 |
Introduce StandardShortcutWatcher to watch for runtime changes
Currently an application needs to be restarted before it can see
any changes made to the standard shortcut configuration. To notify
about changes a new class is introduced that looks for those
changes using KConfigWatcher and also updates the global map.
CCBUG:426656
-rw-r--r-- | autotests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | autotests/kstandardshortcutwatchertest.cpp | 63 | ||||
-rw-r--r-- | src/gui/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/gui/kstandardshortcut.cpp | 10 | ||||
-rw-r--r-- | src/gui/kstandardshortcut_p.h | 20 | ||||
-rw-r--r-- | src/gui/kstandardshortcutwatcher.cpp | 46 | ||||
-rw-r--r-- | src/gui/kstandardshortcutwatcher.h | 54 |
7 files changed, 194 insertions, 3 deletions
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index a7e37e5a..725d789f 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -57,6 +57,7 @@ ecm_add_tests( kconfigloadertest.cpp kconfigskeletontest.cpp kstandardshortcuttest.cpp + kstandardshortcutwatchertest.cpp NAME_PREFIX kconfiggui- LINK_LIBRARIES KF5::ConfigGui Qt${QT_MAJOR_VERSION}::Test ) diff --git a/autotests/kstandardshortcutwatchertest.cpp b/autotests/kstandardshortcutwatchertest.cpp new file mode 100644 index 00000000..f20fc635 --- /dev/null +++ b/autotests/kstandardshortcutwatchertest.cpp @@ -0,0 +1,63 @@ +/* + SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de> + + SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#include "kstandardshortcutwatcher.h" +#include "kconfiggroup.h" +#include "ksharedconfig.h" + +#include <QSignalSpy> +#include <QStandardPaths> +#include <QTest> + +class KStandardShortcutWatcherTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); + void init(); + void testSignal(); + void testDataUpdated(); +}; + +Q_DECLARE_METATYPE(KStandardShortcut::StandardShortcut) + +const QList<QKeySequence> newShortcut = {Qt::CTRL + Qt::Key_Adiaeresis}; + +void KStandardShortcutWatcherTest::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); + qRegisterMetaType<KStandardShortcut::StandardShortcut>(); + QVERIFY(KStandardShortcut::hardcodedDefaultShortcut(KStandardShortcut::Open) != newShortcut); +} + +void KStandardShortcutWatcherTest::init() +{ + KStandardShortcut::saveShortcut(KStandardShortcut::Open, KStandardShortcut::hardcodedDefaultShortcut(KStandardShortcut::Open)); +} + +void KStandardShortcutWatcherTest::testSignal() +{ + QSignalSpy signalSpy(KStandardShortcut::shortcutWatcher(), &KStandardShortcut::StandardShortcutWatcher::shortcutChanged); + KStandardShortcut::saveShortcut(KStandardShortcut::Open, newShortcut); + QTRY_COMPARE(signalSpy.count(), 1); + const QList<QVariant> arguments = signalSpy.takeFirst(); + QCOMPARE(arguments[0].toInt(), KStandardShortcut::Open); + QCOMPARE(arguments[1].value<QList<QKeySequence>>(), newShortcut); +} + +void KStandardShortcutWatcherTest::testDataUpdated() +{ + QSignalSpy signalSpy(KStandardShortcut::shortcutWatcher(), &KStandardShortcut::StandardShortcutWatcher::shortcutChanged); + // Writing manually to forego automatic update in saveShortcut() + KConfigGroup group(KSharedConfig::openConfig(), "Shortcuts"); + group.writeEntry("Open", QKeySequence::listToString(newShortcut), KConfig::Global | KConfig::Notify); + group.config()->sync(); + QTRY_COMPARE(signalSpy.count(), 1); + QCOMPARE(KStandardShortcut::open(), newShortcut); +} + +QTEST_MAIN(KStandardShortcutWatcherTest) +#include "kstandardshortcutwatchertest.moc" diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 2136ec9f..403b0367 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(KF5ConfigGui PRIVATE kconfigloader.cpp kconfigskeleton.cpp kstandardshortcut.cpp + kstandardshortcutwatcher.cpp kwindowconfig.cpp ) @@ -37,6 +38,7 @@ ecm_generate_headers(KConfigGui_HEADERS KConfigLoader KConfigSkeleton KStandardShortcut + KStandardShortcutWatcher KWindowConfig REQUIRED_HEADERS KConfigGui_HEADERS @@ -60,6 +62,7 @@ if (PythonModuleGeneration_FOUND) kconfigloader.h kconfigskeleton.h kstandardshortcut.h + kstandardshortcutwatcher.h kwindowconfig.h ) endif() diff --git a/src/gui/kstandardshortcut.cpp b/src/gui/kstandardshortcut.cpp index 1f67901f..e7639219 100644 --- a/src/gui/kstandardshortcut.cpp +++ b/src/gui/kstandardshortcut.cpp @@ -8,8 +8,10 @@ */ #include "kstandardshortcut.h" +#include "kstandardshortcutwatcher.h" #include "kconfig.h" +#include "kconfigwatcher.h" #include "ksharedconfig.h" #include <kconfiggroup.h> @@ -437,7 +439,7 @@ static void sanitizeShortcutList(QList<QKeySequence> *list) On X11, if QApplication was initialized with GUI disabled, the default will always be used. */ -static void initialize(StandardShortcut id) +void initialize(StandardShortcut id) { KStandardShortcutInfo *info = guardedStandardShortcutInfo(id); @@ -483,7 +485,8 @@ void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut) // If the shortcut is the equal to the hardcoded one we remove it from // kdeglobal if necessary and return. if (cg.hasKey(info->name)) { - cg.deleteEntry(info->name, KConfig::Global | KConfig::Persistent); + cg.deleteEntry(info->name, KConfig::Global | KConfig::Persistent | KConfig::Notify); + cg.sync(); } return; @@ -491,7 +494,8 @@ void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut) // Write the changed shortcut to kdeglobals sanitizeShortcutList(&info->cut); - cg.writeEntry(info->name, QKeySequence::listToString(info->cut), KConfig::Global | KConfig::Persistent); + cg.writeEntry(info->name, QKeySequence::listToString(info->cut), KConfig::Global | KConfig::Persistent | KConfig::Notify); + cg.sync(); } QString name(StandardShortcut id) diff --git a/src/gui/kstandardshortcut_p.h b/src/gui/kstandardshortcut_p.h new file mode 100644 index 00000000..f4b0a0fb --- /dev/null +++ b/src/gui/kstandardshortcut_p.h @@ -0,0 +1,20 @@ +/* + This file is part of the KDE libraries + SPDX-FileCopyrightText: 1997 Stefan Taferner <taferner@alpin.or.at> + SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org> + SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org> + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +#ifndef KSTANDARDSHORTCUT_P_H +#define KSTANDARDSHORTCUT_P_H + +#include "kstandardshortcut.h" + +namespace KStandardShortcut +{ +void initialize(StandardShortcut id); +} + +#endif diff --git a/src/gui/kstandardshortcutwatcher.cpp b/src/gui/kstandardshortcutwatcher.cpp new file mode 100644 index 00000000..1be5e503 --- /dev/null +++ b/src/gui/kstandardshortcutwatcher.cpp @@ -0,0 +1,46 @@ +/* + SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de> + + SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#include "kstandardshortcutwatcher.h" + +#include "kconfigwatcher.h" +#include "kstandardshortcut_p.h" + +namespace KStandardShortcut +{ +class StandardShortcutWatcherPrivate +{ +public: + KConfigWatcher::Ptr watcher = KConfigWatcher::create(KSharedConfig::openConfig()); +}; + +StandardShortcutWatcher::StandardShortcutWatcher(QObject *parent) + : QObject(parent) + , d(std::make_unique<StandardShortcutWatcherPrivate>()) +{ + connect(d->watcher.get(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &keys) { + if (group.name() != QStringLiteral("Shortcuts")) { + return; + } + for (const auto &key : keys) { + const StandardShortcut shortcut = KStandardShortcut::findByName(QString::fromUtf8(key)); + if (shortcut != KStandardShortcut::AccelNone) { + initialize(shortcut); + Q_EMIT shortcutChanged(shortcut, KStandardShortcut::shortcut(shortcut)); + } + } + }); +} + +StandardShortcutWatcher::~StandardShortcutWatcher() = default; + +StandardShortcutWatcher *shortcutWatcher() +{ + static StandardShortcutWatcher watcher; + return &watcher; +} + +} diff --git a/src/gui/kstandardshortcutwatcher.h b/src/gui/kstandardshortcutwatcher.h new file mode 100644 index 00000000..64c6d3d4 --- /dev/null +++ b/src/gui/kstandardshortcutwatcher.h @@ -0,0 +1,54 @@ +/* + SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de> + + SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#ifndef KSTANDARDSHORTCUTWATCHER_H +#define KSTANDARDSHORTCUTWATCHER_H + +#include "kstandardshortcut.h" + +#include <QObject> + +#include <memory> + +#include <kconfiggui_export.h> + +namespace KStandardShortcut +{ +class StandardShortcutWatcherPrivate; + +/** + * Watches for changes made to standard shortcuts and notifies about those changes. + * @see KStandardShortcut::shortcutWatcher + * @since 5.91 + */ +class KCONFIGGUI_EXPORT StandardShortcutWatcher : public QObject +{ + Q_OBJECT +public: + ~StandardShortcutWatcher(); +Q_SIGNALS: + /** + * The standardshortcut @p id was changed to @p shortcut + */ + void shortcutChanged(KStandardShortcut::StandardShortcut id, const QList<QKeySequence> &shortcut); + +private: + explicit StandardShortcutWatcher(QObject *parent = nullptr); + friend StandardShortcutWatcher *shortcutWatcher(); + std::unique_ptr<StandardShortcutWatcherPrivate> d; +}; + +/** + * Returns the global KStandardShortcutWatcher instance of this program. + * In addition to the notifying about changes it also keeps the information returned by the + * functions in @p KStandardShortcut up to date. + * The object is created by the first call to this function. + * @since 5.91 + */ +KCONFIGGUI_EXPORT StandardShortcutWatcher *shortcutWatcher(); +} + +#endif |