From 22e3101c2297700a9d2aabe96db796e9917424f2 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 3 Apr 2024 23:10:18 -0500 Subject: [PATCH] Add KeybindEdit widget --- scwx-qt/scwx-qt.cmake | 2 + scwx-qt/source/scwx/qt/ui/keybind_edit.cpp | 137 +++++++++++++++++++++ scwx-qt/source/scwx/qt/ui/keybind_edit.hpp | 41 ++++++ 3 files changed, 180 insertions(+) create mode 100644 scwx-qt/source/scwx/qt/ui/keybind_edit.cpp create mode 100644 scwx-qt/source/scwx/qt/ui/keybind_edit.hpp diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 179c7bc9..2a515e88 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -227,6 +227,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/flow_layout.hpp source/scwx/qt/ui/imgui_debug_dialog.hpp source/scwx/qt/ui/imgui_debug_widget.hpp + source/scwx/qt/ui/keybind_edit.hpp source/scwx/qt/ui/layer_dialog.hpp source/scwx/qt/ui/left_elided_item_delegate.hpp source/scwx/qt/ui/level2_products_widget.hpp @@ -249,6 +250,7 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/flow_layout.cpp source/scwx/qt/ui/imgui_debug_dialog.cpp source/scwx/qt/ui/imgui_debug_widget.cpp + source/scwx/qt/ui/keybind_edit.cpp source/scwx/qt/ui/layer_dialog.cpp source/scwx/qt/ui/left_elided_item_delegate.cpp source/scwx/qt/ui/level2_products_widget.cpp diff --git a/scwx-qt/source/scwx/qt/ui/keybind_edit.cpp b/scwx-qt/source/scwx/qt/ui/keybind_edit.cpp new file mode 100644 index 00000000..b2cc1ec7 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/keybind_edit.cpp @@ -0,0 +1,137 @@ +#include +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +static const std::string logPrefix_ = "scwx::qt::ui::keybind_edit"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class KeybindEdit::Impl +{ +public: + explicit Impl() {}; + ~Impl() = default; + + QKeySequence sequence_ {}; +}; + +KeybindEdit::KeybindEdit(QWidget* parent) : + QLineEdit(parent), p {std::make_unique()} +{ + setReadOnly(true); + setClearButtonEnabled(true); + + QAction* clearAction = findChild(); + if (clearAction != nullptr) + { + clearAction->setEnabled(true); + + connect(clearAction, + &QAction::triggered, + this, + [this](bool /* checked */) + { + logger_->trace("clearAction"); + + if (!p->sequence_.isEmpty()) + { + // Clear saved sequence + p->sequence_ = QKeySequence {}; + setText(p->sequence_.toString()); + Q_EMIT KeySequenceChanged({}); + } + }); + } +} + +KeybindEdit::~KeybindEdit() {} + +QKeySequence KeybindEdit::key_sequence() const +{ + return p->sequence_; +} + +void KeybindEdit::set_key_sequence(const QKeySequence& sequence) +{ + if (sequence != p->sequence_) + { + p->sequence_ = sequence; + setText(sequence.toString()); + Q_EMIT KeySequenceChanged(sequence); + } +} + +void KeybindEdit::focusInEvent(QFocusEvent* e) +{ + logger_->trace("focusInEvent"); + + // Replace text with placeholder prompting for input + setPlaceholderText("Press any key"); + setText({}); + + QLineEdit::focusInEvent(e); +} + +void KeybindEdit::focusOutEvent(QFocusEvent* e) +{ + logger_->trace("focusOutEvent"); + + // Replace text with saved sequence + setPlaceholderText({}); + setText(p->sequence_.toString()); + + QLineEdit::focusOutEvent(e); +} + +void KeybindEdit::keyPressEvent(QKeyEvent* e) +{ + logger_->trace("keyPressEvent"); + + QKeySequence sequence {}; + + switch (e->key()) + { + case Qt::Key::Key_Shift: + case Qt::Key::Key_Control: + case Qt::Key::Key_Alt: + case Qt::Key::Key_Meta: + case Qt::Key::Key_Mode_switch: + // Record modifiers only in sequence + sequence = e->modifiers().toInt(); + break; + + default: + // Record modifiers and keys in sequence, and save sequence + sequence = e->modifiers().toInt() | e->key(); + + if (sequence != p->sequence_) + { + p->sequence_ = sequence; + Q_EMIT KeySequenceChanged(sequence); + } + + clearFocus(); + break; + } + + setText(sequence.toString()); +} + +void KeybindEdit::keyReleaseEvent(QKeyEvent*) +{ + logger_->trace("keyReleaseEvent"); + + // Modifiers were released prior to pressing a non-modifier key + setText({}); +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/keybind_edit.hpp b/scwx-qt/source/scwx/qt/ui/keybind_edit.hpp new file mode 100644 index 00000000..3d90bcbf --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/keybind_edit.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +class KeybindEdit : public QLineEdit +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(KeybindEdit) + +public: + explicit KeybindEdit(QWidget* parent = nullptr); + ~KeybindEdit(); + + QKeySequence key_sequence() const; + + void set_key_sequence(const QKeySequence& sequence); + +protected: + void focusInEvent(QFocusEvent* e) override; + void focusOutEvent(QFocusEvent* e) override; + void keyPressEvent(QKeyEvent* e) override; + void keyReleaseEvent(QKeyEvent* e) override; + +signals: + void KeySequenceChanged(const QKeySequence& sequence); + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace ui +} // namespace qt +} // namespace scwx