From 8f2e99d1b6e814fcf7b9142889b7f2dfab5dd94e Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 6 Apr 2026 19:10:03 -0400 Subject: Function signature table in edit function dialog --- ui/completioncombobox.h | 34 ++++++++++++++++++++++ ui/typecompletioncombobox.h | 70 +++++++++++++++++++++++++++++++++++++++++++++ ui/typedialog.h | 35 ++--------------------- 3 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 ui/completioncombobox.h create mode 100644 ui/typecompletioncombobox.h diff --git a/ui/completioncombobox.h b/ui/completioncombobox.h new file mode 100644 index 00000000..1135d4e4 --- /dev/null +++ b/ui/completioncombobox.h @@ -0,0 +1,34 @@ +#pragma once + +#include "uitypes.h" +#include +#include + +//! CompletionComboBox is a subclass of QComboBox intended to have a more +//! familiar user experience when working with auto-completion. +//! +//! Most notably, the keypress is intercepted so that the tab key can be +//! used to cycle through completion options. This is similar the behavior found +//! in most text editors and IDEs. +//! +//! Additionally, the combo box is editable and uses case-sensitive matching, +//! popup-style completion, and a "no insert" policy by default. +class BINARYNINJAUIAPI CompletionComboBox : public QComboBox { + Q_OBJECT + + bool m_forwardReturnEvents = true; + + //! Manually cycle the selected completion suggestion, forward by default. + bool cycleCompletion(bool forward = true); + +protected: + bool event(QEvent* event) override; + +public: + CompletionComboBox(QWidget* parent = nullptr); + + void setForwardReturnEvents(bool forward) { m_forwardReturnEvents = forward; } + +Q_SIGNALS: + void enterPressed(); +}; diff --git a/ui/typecompletioncombobox.h b/ui/typecompletioncombobox.h new file mode 100644 index 00000000..e512836a --- /dev/null +++ b/ui/typecompletioncombobox.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#ifndef BINARYNINJAUI_BINDINGS + #include +#endif +#include +#include "completioncombobox.h" +#include "binaryninjaapi.h" +#include "uitypes.h" + + +#ifdef BINARYNINJAUI_BINDINGS +// QThread has issues working in the bindings on some platforms +class GetTypesListThread; +#else + +/*! + + \ingroup typedialog +*/ +class BINARYNINJAUIAPI GetTypesListThread : public QThread +{ + Q_OBJECT + + QStringList m_allTypes; + std::function m_completeFunc; + std::mutex m_mutex; + bool m_done; + BinaryNinja::TypeContainer m_typeContainer; + +protected: + virtual void run() override; + +public: + GetTypesListThread(BinaryNinja::TypeContainer typeContainer, const std::function& completeFunc); + void cancel(); + + const QStringList& getTypes() const { return m_allTypes; } +}; +#endif + +//! A CompletionComboBox pre-configured for type name autocompletion. +//! +//! Fetches type names from a TypeContainer in a background thread and populates +//! the completer model. Respects the ui.types.substring and +//! ui.types.maxAutoFeaturesCount settings. +//! +//! Optionally manages a persistent input history stored in QSettings. +class BINARYNINJAUIAPI TypeCompletionComboBox : public CompletionComboBox +{ + Q_OBJECT + + QStringListModel* m_model; + GetTypesListThread* m_updateThread = nullptr; + QStringList m_historyEntries; + int m_historySize; + + void customEvent(QEvent* event) override; + +public: + TypeCompletionComboBox(std::optional typeContainer, QWidget* parent = nullptr, + QString existing = QString()); + ~TypeCompletionComboBox(); + + //! Commit the current text to the persistent input history. + void commitHistory(); + + QStringListModel* completionModel() const { return m_model; } +}; diff --git a/ui/typedialog.h b/ui/typedialog.h index 690b1650..77e599e9 100644 --- a/ui/typedialog.h +++ b/ui/typedialog.h @@ -5,16 +5,13 @@ #include #include #include -#ifndef BINARYNINJAUI_BINDINGS - #include -#endif #include "binaryninjaapi.h" #include "uitypes.h" +#include "typecompletioncombobox.h" #ifdef BINARYNINJAUI_BINDINGS // QThread has issues working in the bindings on some platforms -class GetTypesListThread; class ParseTypeThread; #else @@ -24,30 +21,6 @@ class ParseTypeThread; \ingroup uiapi */ -/*! - - \ingroup typedialog -*/ -class BINARYNINJAUIAPI GetTypesListThread : public QThread -{ - Q_OBJECT - - QStringList m_allTypes; - std::function m_completeFunc; - std::mutex m_mutex; - bool m_done; - BinaryNinja::TypeContainer m_typeContainer; - - protected: - virtual void run() override; - - public: - GetTypesListThread(BinaryNinja::TypeContainer typeContainer, const std::function& completeFunc); - void cancel(); - - const QStringList& getTypes() const { return m_allTypes; } -}; - Q_DECLARE_METATYPE(BinaryNinja::QualifiedNameAndType); /*! QThread subclass for handling type string parsing to avoid UI interruptions. @@ -80,16 +53,13 @@ class BINARYNINJAUIAPI TypeDialog : public QDialog { Q_OBJECT - QComboBox* m_combo; + TypeCompletionComboBox* m_combo; QStringListModel* m_model; QLabel* m_prompt; QString m_promptText; std::optional m_typeContainer; bool m_resultValid = true; bool m_resolved = false; - QStringList m_historyEntries; - int m_historySize; - GetTypesListThread* m_updateThread = nullptr; BinaryNinja::QualifiedNameAndType m_type; QPushButton* m_acceptButton; QTimer* m_updateTimer; @@ -99,7 +69,6 @@ class BINARYNINJAUIAPI TypeDialog : public QDialog QString m_parseError; void commitHistory(); - void customEvent(QEvent* event); void saveLocation(); void reject(); void accept(); -- cgit v1.3.1