mirror of https://github.com/Nheko-Reborn/nheko
This will eventually allow users to assign arbitrary shortcuts to actions to give them the ability to have shortcuts for everything(tm).pull/1568/head
parent
03be9e479a
commit
66ade755eb
@ -0,0 +1,140 @@ |
||||
#include "ShortcutRegistry.h" |
||||
|
||||
ShortcutRegistry *ShortcutRegistry::s_instance = nullptr; |
||||
|
||||
EditableShortcut::EditableShortcut(QObject *parent) |
||||
: QObject{parent} |
||||
{ |
||||
} |
||||
|
||||
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(); |
||||
} |
||||
|
||||
EditableShortcut::EditableShortcut(const QString &name, const QString &description, QObject *parent) |
||||
: QObject{parent} |
||||
, m_name{name} |
||||
, m_description{description} |
||||
{ |
||||
ShortcutRegistry::instance()->registerShortcut(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 {}; |
||||
} |
||||
} |
||||
|
||||
bool ShortcutRegistry::setData(const QModelIndex &index, const QVariant &value, int role) |
||||
{ |
||||
if (!index.isValid() || index.row() >= m_shortcuts.size() || index.row() < 0) |
||||
return false; |
||||
|
||||
switch (role) |
||||
{ |
||||
case Roles::Shortcut: |
||||
if (auto shortcut = QKeySequence(value.toString()); !shortcut.isEmpty()) { |
||||
m_shortcuts[index.row()]->setShortcut(shortcut.toString()); |
||||
return true; |
||||
} else |
||||
return false; |
||||
default: |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
ShortcutRegistry::ShortcutRegistry(QObject *parent) |
||||
: QAbstractListModel{parent} |
||||
{ |
||||
s_instance = this; |
||||
} |
||||
|
||||
void ShortcutRegistry::registerShortcut(EditableShortcut *action) |
||||
{ |
||||
m_shortcuts.push_back(action); |
||||
} |
@ -0,0 +1,81 @@ |
||||
#pragma once |
||||
|
||||
#include <QAbstractListModel> |
||||
#include <QAction> |
||||
#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); |
||||
EditableShortcut(const QString &name, const QString &description, const QString &text, QObject *parent = nullptr); |
||||
EditableShortcut(const QString &name, const QString &description, const QIcon &icon, const QString &text, 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, |
||||
}; |
||||
|
||||
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; |
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override; |
||||
|
||||
private: |
||||
explicit ShortcutRegistry(QObject *parent = nullptr); |
||||
|
||||
void registerShortcut(EditableShortcut *action); |
||||
|
||||
static ShortcutRegistry *s_instance; |
||||
QList<EditableShortcut *> m_shortcuts; |
||||
|
||||
friend EditableShortcut; |
||||
}; |
Loading…
Reference in new issue