aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Redondo <kde@david-redondo.de>2022-01-13 10:04:13 +0100
committerDavid Redondo <kde@david-redondo.de>2022-01-24 13:23:55 +0000
commit820dc0a553e50cc4560733d43fca2674a61d43b3 (patch)
tree6a89465d257b5b238b6bcd6a7f2f339ac167b9b6
parent41d37407e80f5ccd110cf303c20a181f95fa7e73 (diff)
downloadkconfig-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.txt1
-rw-r--r--autotests/kstandardshortcutwatchertest.cpp63
-rw-r--r--src/gui/CMakeLists.txt3
-rw-r--r--src/gui/kstandardshortcut.cpp10
-rw-r--r--src/gui/kstandardshortcut_p.h20
-rw-r--r--src/gui/kstandardshortcutwatcher.cpp46
-rw-r--r--src/gui/kstandardshortcutwatcher.h54
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