summaryrefslogtreecommitdiff
path: root/src/settings.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-02 15:07:24 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-02 15:07:24 -0500
commit47e0ff88edd4660513f1d4f3d731008461532a13 (patch)
tree5b73ad0920101190e6e7cb558833e24f31ccdc4d /src/settings.cpp
parent99c6c809b961f2eb3c8538bfa50de7f2f98587ea (diff)
Get and save user keybinds.
Diffstat (limited to 'src/settings.cpp')
-rw-r--r--src/settings.cpp167
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);
+}
+
+}