summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--resources/qml/Root.qml84
-rw-r--r--resources/qml/dialogs/ShortcutEditor.qml37
-rw-r--r--src/MainWindow.cpp1
-rw-r--r--src/MainWindow.h3
-rw-r--r--src/UserSettingsPage.cpp25
-rw-r--r--src/ui/KeySequenceRegistry.cpp241
-rw-r--r--src/ui/KeySequenceRegistry.h116
-rw-r--r--src/ui/ShortcutRegistry.cpp158
-rw-r--r--src/ui/ShortcutRegistry.h84
10 files changed, 464 insertions, 289 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd6ac90b..ddf0d3cd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -397,8 +397,8 @@ set(SRC_FILES
src/ui/RoomSettings.h
src/ui/RoomSummary.cpp
src/ui/RoomSummary.h
- src/ui/ShortcutRegistry.cpp
- src/ui/ShortcutRegistry.h
+ src/ui/KeySequenceRegistry.cpp
+ src/ui/KeySequenceRegistry.h
src/ui/Theme.cpp
src/ui/Theme.h
src/ui/UIA.cpp
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 6cdfc99c..b506b93e 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -112,15 +112,14 @@ Pane {
onActivated: Qt.quit()
}
- EditableShortcut {
+ EditableKeySequence {
id: quickSwitcherShortcut
name: qsTr("Room search")
- description: qsTr("Opens a search bar for quick switching between rooms")
- shortcut: "Ctrl+K"
+ defaultKeySequence: "Ctrl+K"
}
Shortcut {
- sequence: quickSwitcherShortcut.shortcut
+ sequence: quickSwitcherShortcut.keySequence
onActivated: {
var component = Qt.createComponent("qrc:/resources/qml/QuickSwitcher.qml");
@@ -134,45 +133,98 @@ Pane {
}
}
- EditableShortcut {
+ EditableKeySequence {
id: nextRoomWithActivityShortcut
name: qsTr("Next room with activity")
- description: qsTr("Switches to the next unread room in the roomlist")
// Add alternative shortcut, because sometimes Alt+A is stolen by the TextEdit
- shortcuts: ["Alt+A", "Ctrl+Shift+A"]
+ defaultKeySequences: ["Alt+A", "Ctrl+Shift+A"]
}
Shortcut {
- sequences: nextRoomWithActivityShortcut.shortcuts
+ sequences: nextRoomWithActivityShortcut.keySequence
onActivated: Rooms.nextRoomWithActivity()
}
- EditableShortcut {
+ EditableKeySequence {
id: nextRoomShortcut
name: qsTr("Next room")
- description: qsTr("Switches to the room below the room that is currently open")
- shortcut: "Ctrl+Down"
+ defaultKeySequence: "Ctrl+Down"
}
Shortcut {
- sequence: nextRoomShortcut.shortcut
+ sequence: nextRoomShortcut.keySequence
onActivated: Rooms.nextRoom()
}
- EditableShortcut {
+ EditableKeySequence {
id: previousRoomShortcut
name: qsTr("Previous room")
- description: qsTr("Switches to the room above the room that is currently open")
- shortcut: "Ctrl+Up"
+ defaultKeySequence: "Ctrl+Up"
}
Shortcut {
- sequence: previousRoomShortcut.shortcut
+ sequence: previousRoomShortcut.keySequence
onActivated: Rooms.previousRoom()
}
+
+ EditableKeySequence {
+ id: nextSpaceShortcut
+
+ name: qsTr("Next space")
+ }
+ Shortcut {
+ sequence: nextSpaceShortcut.keySequence
+
+// onActivated: Communities.setCurrentTagId(model.id)
+ }
+
+ EditableKeySequence {
+ id: previousSpaceShortcut
+
+ name: qsTr("Previous space")
+ }
+ Shortcut {
+ sequence: previousSpaceShortcut.keySequence
+
+// onActivated: Communities.setCurrentTagId(model.id)
+ }
+
+ EditableKeySequence {
+ id: allRoomsSpaceShortcut
+
+ name: qsTr("Show all rooms")
+ }
+ Shortcut {
+ sequence: allRoomsSpaceShortcut.keySequence
+
+ onActivated: Communities.setCurrentTagId("global")
+ }
+
+ EditableKeySequence {
+ id: favoriteRoomsShortcut
+
+ name: qsTr("Show favorite rooms")
+ }
+ Shortcut {
+ sequence: favoriteRoomsShortcut.keySequence
+
+ onActivated: Communities.setCurrentTagId("m.favourite")
+ }
+
+ EditableKeySequence {
+ id: directChatsShortcut
+
+ name: qsTr("Show direct chats")
+ }
+ Shortcut {
+ sequence: directChatsShortcut.keySequence
+
+ onActivated: Communities.setCurrentTagId("dm")
+ }
+
Connections {
function onOpenJoinRoomDialog() {
var component = Qt.createComponent("qrc:/resources/qml/dialogs/JoinRoomDialog.qml");
diff --git a/resources/qml/dialogs/ShortcutEditor.qml b/resources/qml/dialogs/ShortcutEditor.qml
index 0bd8a00b..b2558557 100644
--- a/resources/qml/dialogs/ShortcutEditor.qml
+++ b/resources/qml/dialogs/ShortcutEditor.qml
@@ -28,42 +28,31 @@ ApplicationWindow {
anchors.fill: parent
ListView {
- model: ShortcutRegistry
+ model: KeySequenceRegistry
delegate: RowLayout {
id: del
required property string name
- required property string description
- required property string shortcut
+ required property string keySequence
spacing: Nheko.paddingMedium
width: ListView.view.width
height: implicitHeight + Nheko.paddingSmall * 2
- ColumnLayout {
- spacing: Nheko.paddingSmall
-
- Label {
- text: del.name
- font.bold: true
- font.pointSize: fontMetrics.font.pointSize * 1.1
- }
-
- Label {
- text: del.description
- }
+ Label {
+ text: del.name
}
Item { Layout.fillWidth: true }
Button {
- property bool selectingNewShortcut: false
+ property bool selectingNewKeySequence: false
- text: selectingNewShortcut ? qsTr("Input..") : del.shortcut
- onClicked: selectingNewShortcut = !selectingNewShortcut
+ text: selectingNewKeySequence ? qsTr("Input..") : (del.keySequence === "" ? "None" : del.keySequence)
+ onClicked: selectingNewKeySequence = !selectingNewKeySequence
Keys.onPressed: event => {
- if (!selectingNewShortcut)
+ if (!selectingNewKeySequence)
return;
event.accepted = true;
@@ -77,12 +66,14 @@ ApplicationWindow {
if (event.modifiers & Qt.ShiftModifier)
keySequence += "Shift+";
- if (event.key === 0 || event.key === Qt.Key_unknown || event.key === Qt.Key_Control || event.key === Qt.Key_Alt || event.key === Qt.Key_AltGr || event.key === Qt.Key_Meta || event.key === Qt.Key_Shift)
+ if (event.key === 0 || event.key === Qt.Key_unknown || event.key === Qt.Key_Control || event.key === Qt.Key_Alt ||
+ event.key === Qt.Key_AltGr || event.key === Qt.Key_Meta || event.key === Qt.Key_Super_L || event.key === Qt.Key_Super_R ||
+ event.key === Qt.Key_Shift)
keySequence += "...";
else {
- keySequence += ShortcutRegistry.keycodeToChar(event.key);
- ShortcutRegistry.changeShortcut(del.name, keySequence);
- selectingNewShortcut = false;
+ keySequence += KeySequenceRegistry.keycodeToChar(event.key);
+ KeySequenceRegistry.changeKeySequence(del.name, keySequence);
+ selectingNewKeySequence = false;
}
}
}
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index a003dee3..d06171de 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -57,7 +57,6 @@ MainWindow *MainWindow::instance_ = nullptr;
MainWindow::MainWindow(QWindow *parent)
: QQuickView(parent)
, userSettings_{UserSettings::instance()}
- , shortcuts_{new ShortcutRegistry}
{
instance_ = this;
diff --git a/src/MainWindow.h b/src/MainWindow.h
index e5b395cb..a070266e 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -11,7 +11,7 @@
#include <QSharedPointer>
#include <QSystemTrayIcon>
-#include "ShortcutRegistry.h"
+#include "KeySequenceRegistry.h"
#include "UserSettingsPage.h"
#include "dock/Dock.h"
@@ -141,7 +141,6 @@ private:
//! Tray icon that shows the unread message count.
TrayIcon *trayIcon_;
Dock *dock_;
- ShortcutRegistry *shortcuts_;
MxcImageProvider *imgProvider = nullptr;
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 67ab9bab..5306f577 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -30,8 +30,10 @@ QSharedPointer<UserSettings> UserSettings::instance_;
UserSettings::UserSettings()
{
- connect(
- QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() { instance_.clear(); });
+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() {
+ instance_->save();
+ instance_.clear();
+ });
}
QSharedPointer<UserSettings>
@@ -164,6 +166,16 @@ UserSettings::load(std::optional<QString> profile)
disableCertificateValidation_ =
settings.value(QStringLiteral("disable_certificate_validation"), false).toBool();
+ settings.beginGroup(QStringLiteral("user"));
+ settings.beginGroup(QStringLiteral("shortcuts"));
+ QMap<QString, QStringList> bindings;
+ for (const auto &key : settings.childKeys())
+ bindings[key] = settings.value(key).toStringList();
+ qDebug() << "restoring with size:" << bindings.size();
+ KeySequenceRegistry::instance()->restoreBindings(bindings);
+ settings.endGroup(); // user/shortcuts
+ settings.endGroup(); // user/shortcuts
+
applyTheme();
}
@@ -882,7 +894,7 @@ UserSettings::save()
settings.beginGroup(QStringLiteral("sidebar"));
settings.setValue(QStringLiteral("community_list_width"), communityListWidth_);
settings.setValue(QStringLiteral("room_list_width"), roomListWidth_);
- settings.endGroup(); // window
+ settings.endGroup(); // sidebar
settings.beginGroup(QStringLiteral("timeline"));
settings.setValue(QStringLiteral("buttons"), buttonsInTimeline_);
@@ -939,6 +951,13 @@ UserSettings::save()
settings.setValue(QStringLiteral("space_background_maintenance"), updateSpaceVias_);
settings.setValue(QStringLiteral("expired_events_background_maintenance"), expireEvents_);
+ settings.beginGroup(QStringLiteral("shortcuts"));
+ auto bindings = KeySequenceRegistry::instance()->dumpBindings();
+ for (const auto &[name, sequences] : bindings.asKeyValueRange())
+ settings.setValue(name, sequences);
+ qDebug() << "saved with size:" << bindings.size();
+ settings.endGroup(); // shortcuts
+
settings.endGroup(); // user
QString prefix = (profile_ != QLatin1String("") && profile_ != QLatin1String("default"))
diff --git a/src/ui/KeySequenceRegistry.cpp b/src/ui/KeySequenceRegistry.cpp
new file mode 100644
index 00000000..8184ff48
--- /dev/null
+++ b/src/ui/KeySequenceRegistry.cpp
@@ -0,0 +1,241 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "KeySequenceRegistry.h"
+
+KeySequenceRegistry *KeySequenceRegistry::s_instance = nullptr;
+
+KeySequenceImpl::KeySequenceImpl(const QString &name,
+ const QStringList &keySequences,
+ QObject *parent)
+ : QObject{parent}
+ , m_name{name}
+ , m_keySequences{keySequences}
+{
+}
+
+void
+KeySequenceImpl::setKeySequences(const QStringList &keySequences)
+{
+ if (keySequences == m_keySequences)
+ return;
+ m_keySequences = keySequences;
+ emit keySequencesChanged();
+}
+
+EditableKeySequence::EditableKeySequence(QObject *parent)
+ : QObject{parent}
+{
+ KeySequenceRegistry::instance()->registerKeySequence(this);
+}
+
+EditableKeySequence::EditableKeySequence(const QString &name, QObject *parent)
+ : QObject{parent}
+ , m_name{name}
+{
+ KeySequenceRegistry::instance()->registerKeySequence(this);
+}
+
+const QString
+EditableKeySequence::keySequence() const
+{
+ return (m_impl && m_impl->keySequences().size() > 0) ? m_impl->keySequences().first()
+ : defaultKeySequence();
+}
+
+const QStringList
+EditableKeySequence::keySequences() const
+{
+ return m_impl ? m_impl->keySequences() : defaultKeySequences();
+}
+
+const QString
+EditableKeySequence::defaultKeySequence() const
+{
+ return m_defaultKeySequences.size() > 0 ? m_defaultKeySequences.first().toString() : QString{};
+}
+
+const QStringList
+EditableKeySequence::defaultKeySequences() const
+{
+ QStringList dest;
+ dest.resize(m_defaultKeySequences.size());
+ std::transform(m_defaultKeySequences.begin(),
+ m_defaultKeySequences.end(),
+ dest.begin(),
+ [](const auto &keySequence) { return keySequence.toString(); });
+ return dest;
+}
+
+void
+EditableKeySequence::setName(const QString &name)
+{
+ if (name == m_name)
+ return;
+ m_name = name;
+ emit nameChanged();
+ KeySequenceRegistry::instance()->registerKeySequence(this);
+}
+
+void
+EditableKeySequence::setKeySequence(const QString &keySequence)
+{
+ setKeySequences({keySequence});
+}
+
+void
+EditableKeySequence::setKeySequences(const QStringList &keySequences)
+{
+ m_impl->setKeySequences(keySequences);
+}
+
+void
+EditableKeySequence::setDefaultKeySequence(const QString &keySequence)
+{
+ setDefaultKeySequences({keySequence});
+}
+
+void
+EditableKeySequence::setDefaultKeySequences(const QStringList &keySequences)
+{
+ QList<QKeySequence> temp;
+ temp.resize(keySequences.size());
+ std::transform(keySequences.begin(),
+ keySequences.end(),
+ temp.begin(),
+ [](const auto &keySequence) { return QKeySequence(keySequence); });
+
+ if (temp == m_defaultKeySequences)
+ return;
+ m_defaultKeySequences = temp;
+ emit defaultKeySequencesChanged();
+
+ if (m_impl && m_impl->keySequences().isEmpty())
+ m_impl->setKeySequences(keySequences);
+}
+
+KeySequenceRegistry::KeySequenceRegistry(QObject *parent)
+ : QAbstractListModel{parent}
+{
+ s_instance = this;
+}
+
+KeySequenceRegistry *
+KeySequenceRegistry::instance()
+{
+ if (!s_instance)
+ s_instance = new KeySequenceRegistry;
+ return s_instance;
+}
+
+KeySequenceRegistry *
+KeySequenceRegistry::create(QQmlEngine *qmlEngine, QJSEngine *)
+{
+ // The instance has to exist before it is used. We cannot replace it.
+ Q_ASSERT(s_instance);
+
+ // The engine has to have the same thread affinity as the singleton.
+ Q_ASSERT(qmlEngine->thread() == s_instance->thread());
+
+ // There can only be one engine accessing the singleton.
+ static QJSEngine *s_engine = nullptr;
+ if (s_engine)
+ Q_ASSERT(qmlEngine == s_engine);
+ else
+ s_engine = qmlEngine;
+
+ QJSEngine::setObjectOwnership(s_instance, QJSEngine::CppOwnership);
+ return s_instance;
+}
+
+QHash<int, QByteArray>
+KeySequenceRegistry::roleNames() const
+{
+ return {{Roles::Name, "name"}, {Roles::KeySequence, "keySequence"}};
+}
+
+QVariant
+KeySequenceRegistry::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= m_keySequences.size() || index.row() < 0)
+ return {};
+
+ switch (role) {
+ case Roles::Name:
+ return m_keySequences.at(index.row())->name();
+ case Roles::KeySequence: {
+ const auto &data = m_keySequences.at(index.row())->keySequences();
+ return data.size() > 0 ? data.first() : QString{};
+ }
+ default:
+ return {};
+ }
+}
+
+void
+KeySequenceRegistry::changeKeySequence(const QString &name, const QString &newKeySequence)
+{
+ for (int i = 0; i < m_keySequences.size(); ++i) {
+ if (m_keySequences.at(i)->name() == name) {
+ m_keySequences.at(i)->setKeySequences({newKeySequence});
+ emit dataChanged(index(i), index(i), {Roles::KeySequence});
+ return;
+ }
+ }
+}
+
+QString
+KeySequenceRegistry::keycodeToChar(int keycode) const
+{
+ return QString((char)keycode);
+}
+
+QMap<QString, QStringList>
+KeySequenceRegistry::dumpBindings() const
+{
+ QMap<QString, QStringList> bindings;
+ for (const auto sequence : m_keySequences)
+ bindings[sequence->name()] = sequence->keySequences();
+ return bindings;
+}
+
+void
+KeySequenceRegistry::restoreBindings(const QMap<QString, QStringList> &bindings)
+{
+ for (const auto &[name, keySequences] : bindings.asKeyValueRange()) {
+ if (auto it = std::find_if(m_keySequences.begin(),
+ m_keySequences.end(),
+ [&name](const auto &impl) { return impl->name() == name; });
+ it != m_keySequences.end())
+ (*it)->setKeySequences(keySequences);
+ else
+ m_keySequences.push_back(new KeySequenceImpl{name, keySequences});
+ }
+}
+
+void
+KeySequenceRegistry::registerKeySequence(EditableKeySequence *action)
+{
+ if (action->name().isEmpty())
+ return;
+
+ KeySequenceImpl *impl = nullptr;
+ if (auto it =
+ std::find_if(m_keySequences.begin(),
+ m_keySequences.end(),
+ [action](const auto &impl) { return impl->name() == action->name(); });
+ it != m_keySequences.end())
+ impl = *it;
+ else {
+ impl = new KeySequenceImpl{action->name(), action->keySequences()};
+ m_keySequences.push_back(impl);
+ }
+
+ action->m_impl = impl;
+ connect(impl,
+ &KeySequenceImpl::keySequencesChanged,
+ action,
+ &EditableKeySequence::keySequencesChanged);
+ emit action->keySequencesChanged();
+}
diff --git a/src/ui/KeySequenceRegistry.h b/src/ui/KeySequenceRegistry.h
new file mode 100644
index 00000000..a00f4005
--- /dev/null
+++ b/src/ui/KeySequenceRegistry.h
@@ -0,0 +1,116 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <QAbstractListModel>
+#include <QKeySequence>
+#include <QQmlEngine>
+
+class KeySequenceImpl : public QObject
+{
+ Q_OBJECT
+
+public:
+ KeySequenceImpl(const QString &name,
+ const QStringList &keySequences,
+ QObject *parent = nullptr);
+
+ const QString &name() const { return m_name; }
+ const QStringList &keySequences() const { return m_keySequences; }
+
+ void setKeySequences(const QStringList &keySequences);
+
+signals:
+ void keySequencesChanged();
+
+private:
+ const QString m_name;
+ QStringList m_keySequences;
+};
+
+class EditableKeySequence : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL)
+ Q_PROPERTY(
+ QString keySequence READ keySequence WRITE setKeySequence NOTIFY keySequencesChanged FINAL)
+ Q_PROPERTY(QStringList keySequences READ keySequences WRITE setKeySequences NOTIFY
+ keySequencesChanged FINAL)
+ Q_PROPERTY(QString defaultKeySequence READ defaultKeySequence WRITE setDefaultKeySequence NOTIFY
+ defaultKeySequencesChanged FINAL)
+ Q_PROPERTY(QStringList defaultKeySequences READ defaultKeySequences WRITE setDefaultKeySequences
+ NOTIFY defaultKeySequencesChanged FINAL)
+
+public:
+ EditableKeySequence(QObject *parent = nullptr);
+ EditableKeySequence(const QString &name, QObject *parent = nullptr);
+
+ const QString &name() const { return m_name; }
+ const QString keySequence() const;
+ const QStringList keySequences() const;
+ const QString defaultKeySequence() const;
+ const QStringList defaultKeySequences() const;
+
+ void setName(const QString &name);
+ void setKeySequence(const QString &keySequence);
+ void setKeySequences(const QStringList &keySequences);
+ void setDefaultKeySequence(const QString &keySequence);
+ void setDefaultKeySequences(const QStringList &keySequences);
+
+signals:
+ void nameChanged();
+ void keySequencesChanged();
+ void defaultKeySequencesChanged();
+
+private:
+ QString m_name;
+ QList<QKeySequence> m_defaultKeySequences;
+
+ KeySequenceImpl *m_impl = nullptr;
+
+ friend class KeySequenceRegistry;
+};
+
+class KeySequenceRegistry : public QAbstractListModel
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ enum Roles
+ {
+ Name,
+ KeySequence,
+ };
+
+ static KeySequenceRegistry *instance();
+ static KeySequenceRegistry *create(QQmlEngine *qmlEngine, QJSEngine *);
+
+ QHash<int, QByteArray> roleNames() const override;
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return m_keySequences.size();
+ }
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ Q_INVOKABLE void changeKeySequence(const QString &name, const QString &newKeysequence);
+ Q_INVOKABLE QString keycodeToChar(int keycode) const;
+
+ QMap<QString, QStringList> dumpBindings() const;
+ void restoreBindings(const QMap<QString, QStringList> &bindings);
+
+private:
+ explicit KeySequenceRegistry(QObject *parent = nullptr);
+
+ void registerKeySequence(EditableKeySequence *action);
+
+ static KeySequenceRegistry *s_instance;
+ QList<KeySequenceImpl *> m_keySequences;
+
+ friend EditableKeySequence;
+};
diff --git a/src/ui/ShortcutRegistry.cpp b/src/ui/ShortcutRegistry.cpp
deleted file mode 100644
index 5c32b8cb..00000000
--- a/src/ui/ShortcutRegistry.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-// SPDX-FileCopyrightText: Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "ShortcutRegistry.h"
-
-ShortcutRegistry *ShortcutRegistry::s_instance = nullptr;
-
-EditableShortcut::EditableShortcut(QObject *parent)
- : QObject{parent}
-{
- ShortcutRegistry::instance()->registerShortcut(this);
-}
-
-EditableShortcut::EditableShortcut(const QString &name, const QString &description, QObject *parent)
- : QObject{parent}
- , m_name{name}
- , m_description{description}
-{
- ShortcutRegistry::instance()->registerShortcut(this);
-}
-
-const QStringList
-EditableShortcut::shortcuts() const
-{
- QStringList dest;
- dest.resize(m_shortcuts.size());
- std::transform(m_shortcuts.begin(), m_shortcuts.end(), dest.begin(), [](const auto &shortcut) {
- return shortcut.toString();
- });
- return dest;
-}
-
-void
-EditableShortcut::setName(const QString &name)
-{
- if (name == m_name)
- return;
- m_name = name;
- emit nameChanged();
-}
-
-void
-EditableShortcut::setDescription(const QString &description)
-{
- if (description == m_description)
- return;
- m_description = description;
- emit descriptionChanged();
-}
-
-void
-EditableShortcut::setShortcut(const QString &shortcut)
-{
- setShortcuts({shortcut});
-}
-
-void
-EditableShortcut::setShortcuts(const QStringList &shortcuts)
-{
- QList<QKeySequence> temp;
- temp.resize(shortcuts.size());
- std::transform(shortcuts.begin(), shortcuts.end(), temp.begin(), [](const auto &shortcut) {
- return QKeySequence(shortcut);
- });
-
- if (temp == m_shortcuts)
- return;
- m_shortcuts = temp;
- emit shortcutsChanged();
-}
-
-ShortcutRegistry::ShortcutRegistry(QObject *parent)
- : QAbstractListModel{parent}
-{
- if (s_instance)
- m_shortcuts = s_instance->m_shortcuts;
-
- s_instance = this;
-}
-
-ShortcutRegistry *
-ShortcutRegistry::instance()
-{
- return s_instance;
-}
-
-ShortcutRegistry *
-ShortcutRegistry::create(QQmlEngine *qmlEngine, QJSEngine *)
-{
- // The instance has to exist before it is used. We cannot replace it.
- Q_ASSERT(s_instance);
-
- // The engine has to have the same thread affinity as the singleton.
- Q_ASSERT(qmlEngine->thread() == s_instance->thread());
-
- // There can only be one engine accessing the singleton.
- static QJSEngine *s_engine = nullptr;
- if (s_engine)
- Q_ASSERT(qmlEngine == s_engine);
- else
- s_engine = qmlEngine;
-
- QJSEngine::setObjectOwnership(s_instance, QJSEngine::CppOwnership);
- return s_instance;
-}
-
-QHash<int, QByteArray>
-ShortcutRegistry::roleNames() const
-{
- return {
- {Roles::Name, "name"}, {Roles::Description, "description"}, {Roles::Shortcut, "shortcut"}};
-}
-
-QVariant
-ShortcutRegistry::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid() || index.row() >= m_shortcuts.size() || index.row() < 0)
- return {};
-
- switch (role) {
- case Roles::Name:
- return m_shortcuts[index.row()]->name();
- case Roles::Description:
- return m_shortcuts[index.row()]->description();
- case Roles::Shortcut:
- return m_shortcuts[index.row()]->shortcut();
- default:
- return {};
- }
-}
-
-void
-ShortcutRegistry::changeShortcut(const QString &name, const QString &newShortcut)
-{
- for (int i = 0; i < m_shortcuts.size(); ++i) {
- if (m_shortcuts[i]->name() == name) {
- qDebug() << "new:" << newShortcut;
- m_shortcuts[i]->setShortcut(newShortcut);
- emit dataChanged(index(i), index(i), {Roles::Shortcut});
- return;
- }
- }
-}
-
-QString
-ShortcutRegistry::keycodeToChar(int keycode) const
-{
- return QString((char)keycode);
-}
-
-void
-ShortcutRegistry::registerShortcut(EditableShortcut *action)
-{
- beginInsertRows({}, m_shortcuts.size(), m_shortcuts.size());
- m_shortcuts.push_back(action);
- endInsertRows();
-}
diff --git a/src/ui/ShortcutRegistry.h b/src/ui/ShortcutRegistry.h
deleted file mode 100644
index c2fe6265..00000000
--- a/src/ui/ShortcutRegistry.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-FileCopyrightText: Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QAbstractListModel>
-#include <QKeySequence>
-#include <QQmlEngine>
-
-class EditableShortcut : public QObject
-{
- Q_OBJECT
- QML_ELEMENT
-
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL)
- Q_PROPERTY(
- QString description READ description WRITE setDescription NOTIFY descriptionChanged FINAL)
- Q_PROPERTY(QString shortcut READ shortcut WRITE setShortcut NOTIFY shortcutsChanged FINAL)
- Q_PROPERTY(
- QStringList shortcuts READ shortcuts WRITE setShortcuts NOTIFY shortcutsChanged FINAL)
-
-public:
- EditableShortcut(QObject *parent = nullptr);
- EditableShortcut(const QString &name, const QString &description, QObject *parent = nullptr);
-
- const QString &name() const { return m_name; }
- const QString &description() const { return m_description; }
- const QString shortcut() const
- {
- return m_shortcuts.size() > 0 ? m_shortcuts.first().toString() : QString{};
- }
- const QStringList shortcuts() const;
-
- void setName(const QString &name);
- void setDescription(const QString &description);
- void setShortcut(const QString &shortcut);
- void setShortcuts(const QStringList &shortcuts);
-
-signals:
- void nameChanged();
- void descriptionChanged();
- void shortcutsChanged();
-
-private:
- QString m_name;
- QString m_description;
- QList<QKeySequence> m_shortcuts;
-};
-
-class ShortcutRegistry : public QAbstractListModel
-{
- Q_OBJECT
- QML_ELEMENT
- QML_SINGLETON
-
-public:
- enum Roles
- {
- Name,
- Description,
- Shortcut,
- };
-
- explicit ShortcutRegistry(QObject *parent = nullptr);
-
- static ShortcutRegistry *instance();
- static ShortcutRegistry *create(QQmlEngine *qmlEngine, QJSEngine *);
-
- QHash<int, QByteArray> roleNames() const override;
- int rowCount(const QModelIndex & = QModelIndex()) const override { return m_shortcuts.size(); }
- QVariant data(const QModelIndex &index, int role) const override;
-
- Q_INVOKABLE void changeShortcut(const QString &name, const QString &newShortcut);
- Q_INVOKABLE QString keycodeToChar(int keycode) const;
-
-private:
- void registerShortcut(EditableShortcut *action);
-
- static ShortcutRegistry *s_instance;
- QList<EditableShortcut *> m_shortcuts;
-
- friend EditableShortcut;
-};