diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-10-02 15:07:24 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-10-02 15:07:24 -0500 |
commit | 47e0ff88edd4660513f1d4f3d731008461532a13 (patch) | |
tree | 5b73ad0920101190e6e7cb558833e24f31ccdc4d /src/settings.cpp | |
parent | 99c6c809b961f2eb3c8538bfa50de7f2f98587ea (diff) |
Get and save user keybinds.
Diffstat (limited to 'src/settings.cpp')
-rw-r--r-- | src/settings.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/settings.cpp b/src/settings.cpp new file mode 100644 index 0000000..abd53c1 --- /dev/null +++ b/src/settings.cpp @@ -0,0 +1,167 @@ +#include "settings.hpp" + +namespace getsuyomi { + +using fud::FudStatus; + +Settings::Settings(QWidget* parent, Shortcuts&& shortcuts) : QDialog{parent}, m_shortcuts{std::move(shortcuts)} +{ + auto* layout = new QVBoxLayout(); + setWindowTitle("getsuyomi settings"); + + if (!m_shortcuts.valid()) { + return; + } + + auto containerLayout = new QHBoxLayout(); + auto* columnLayout = new QVBoxLayout(); + size_t counter{0}; + constexpr size_t maxEntriesPerColumn{4}; + + for (const auto& action : m_shortcuts.actions()) { + auto* collector = new ShortcutCollector(this, action, m_shortcuts); + columnLayout->addWidget(collector); + counter++; + if (counter % (maxEntriesPerColumn + 1) == 0) { + containerLayout->addLayout(columnLayout); + columnLayout = new QVBoxLayout(); + } + } + + if (columnLayout->count() > 0) { + containerLayout->addLayout(columnLayout); + } + + layout->addLayout(containerLayout); + + auto* dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(dialogButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + layout->addWidget(dialogButtonBox); + + setLayout(layout); +} + +bool Settings::valid() const +{ + return m_shortcuts.valid(); +} + +const Shortcuts& Settings::shortcuts() const +{ + return m_shortcuts; +} + +ShortcutCollector::ShortcutCollector(QWidget* parent, ActionType action, Shortcuts& shortcuts) : + QWidget(parent), m_action{action}, m_shortcuts{shortcuts}, m_bindings{} +{ + m_layout = new QVBoxLayout(); + auto headerLayout = new QHBoxLayout(); + auto* name = new QLabel(actionTypeToString(m_action)); + headerLayout->addWidget(name); + m_shortcutEditor = new QKeySequenceEdit(this); + m_shortcutEditor->setMaximumSequenceLength(1); + connect(m_shortcutEditor, &QKeySequenceEdit::editingFinished, this, &ShortcutCollector::checkBinding); + headerLayout->addWidget(m_shortcutEditor); + + m_acceptButton = new QPushButton("Accept", this); + m_acceptButton->setEnabled(false); + connect(m_acceptButton, &QPushButton::clicked, this, &ShortcutCollector::addBinding); + headerLayout->addWidget(m_acceptButton); + headerLayout->addStretch(); + + m_layout->addLayout(headerLayout); + + auto shortcutOptions = m_shortcuts.shortcuts(m_action); + if (shortcutOptions != std::nullopt) { + for (const auto& binding : *shortcutOptions) { + createBinding(binding); + } + } else { + qWarning("No shortcuts found for %s", actionTypeToString(action)); + } + + setLayout(m_layout); +} + +void ShortcutCollector::createBinding(QKeySequence binding) +{ + auto displayItem = new ShortcutDisplay(this, binding); + m_bindings[binding] = displayItem; + m_layout->addWidget(displayItem); + connect(displayItem, &ShortcutDisplay::removeClicked, this, &ShortcutCollector::removeBinding); +} + +void ShortcutCollector::checkBinding() +{ + auto keySequence = m_shortcutEditor->keySequence(); + if (keySequence == QKeySequence::UnknownKey) { + m_acceptButton->setEnabled(false); + return; + } + + m_acceptButton->setEnabled(not m_shortcuts.contains(keySequence)); +} + +void ShortcutCollector::addBinding() +{ + auto keySequence = m_shortcutEditor->keySequence(); + if (keySequence == QKeySequence::UnknownKey) { + qWarning("Invalid state - can't accept unknown key"); + return; + } else if (m_shortcuts.contains(keySequence)) { + qWarning("Shortcut %s already bound", qPrintable(keySequence.toString())); + return; + } + auto result = m_shortcuts.bind(m_action, keySequence); + if (result != FudStatus::Success) { + qCritical("Error binding %s to action %s", qPrintable(keySequence.toString()), actionTypeToString(m_action)); + return; + } + if (m_bindings.contains(keySequence)) { + qWarning( + "binding %s to action %s already exists", + qPrintable(keySequence.toString()), + actionTypeToString(m_action)); + m_layout->removeWidget(m_bindings[keySequence]); + delete m_bindings[keySequence]; + } + + createBinding(keySequence); + m_shortcutEditor->clear(); +} + +void ShortcutCollector::removeBinding(QKeySequence binding) +{ + auto result = m_shortcuts.remove(binding); + if (result == FudStatus::NotFound) { + qWarning("binding %s not found", qPrintable(binding.toString())); + } else if (result != FudStatus::Success) { + qWarning("error removing binding %s: %s", qPrintable(binding.toString()), FudStatusToString(result)); + } + auto bindingHandle = m_bindings.extract(binding); + if (bindingHandle) { + m_layout->removeWidget(bindingHandle.mapped()); + delete bindingHandle.mapped(); + } else { + qWarning("Could not remove widget!"); + } + checkBinding(); +} + +ShortcutDisplay::ShortcutDisplay(QWidget* parent, QKeySequence shortcut) : QWidget{parent}, m_binding{shortcut} +{ + auto layout = new QHBoxLayout(); + layout->addWidget(new QLabel(shortcut.toString())); + auto* deleteButton = new QPushButton("Delete", this); + connect(deleteButton, &QPushButton::clicked, this, &ShortcutDisplay::removeOnClicked); + layout->addWidget(deleteButton); + setLayout(layout); +} + +void ShortcutDisplay::removeOnClicked() +{ + emit removeClicked(m_binding); +} + +} |