diff options
| author | Brian Potchik <brian@vector35.com> | 2025-09-30 15:09:48 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2025-09-30 15:09:48 -0400 |
| commit | 796932b62e7d007a46d8ad31cdb618e8125073ab (patch) | |
| tree | 35937ae27a646cc6a1d7e79cafd4b46b0991a0b1 /ui | |
| parent | 36a06931b3eac492eb1e609949e2cc5a3a03bf57 (diff) | |
Initial support for opening container formats.
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/containerbrowser.h | 106 | ||||
| -rw-r--r-- | ui/options.h | 2 | ||||
| -rw-r--r-- | ui/uitypes.h | 2 |
3 files changed, 109 insertions, 1 deletions
diff --git a/ui/containerbrowser.h b/ui/containerbrowser.h new file mode 100644 index 00000000..8dddad0a --- /dev/null +++ b/ui/containerbrowser.h @@ -0,0 +1,106 @@ +#pragma once + +#include <QDialog> +#include <QStringList> +#include <QLineEdit> +#include <QTreeView> +#include <QPlainTextEdit> +#include <QLabel> +#include <QDialogButtonBox> +#include <QModelIndex> + +#include "binaryninjaapi.h" +#include "uitypes.h" + +#include <vector> + + +class ContainerTreeModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + enum Columns { ColName, ColType, ColSize, ColPath, ColCount }; + + explicit ContainerTreeModel(TransformSessionRef session, QObject* parent = nullptr); + + // QAbstractItemModel interface + int columnCount(const QModelIndex& parent = {}) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; + QModelIndex parent(const QModelIndex& child) const override; + int rowCount(const QModelIndex& parent = {}) const override; + QVariant data(const QModelIndex& index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + + // Public helpers for the dialog + bool isLeaf(const QModelIndex& index) const; + QStringList pathFor(const QModelIndex& index) const; + void selectNode(const QModelIndex& index); + void rebuild(); + +private: + struct Node + { + QString displayName; // GetFileName() (or synthesized for root) + QString type; // GetTransformName() or "Leaf"/"Root" + QString breadcrumb; // human-readable path "a ▸ b ▸ c" + QStringList pathSegments; // list of filenames from root to this node + quint64 size = 0; // not exposed (kept for future metadata) + bool isLeaf = false; + bool selectable = true; // we allow selection only on leaves + TransformContextRef ctx; + Node* parent = nullptr; + std::vector<std::unique_ptr<Node>> children; + }; + + const Node* nodeFromIndex(const QModelIndex& index) const; + static QString joinBreadcrumb(const QStringList& segments); + void buildChildren(Node* parentNode, const TransformContextRef& ctx, const QStringList& parentSegments); + + TransformSessionRef m_session; + std::unique_ptr<Node> m_root; +}; + + +class AllColumnsFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + explicit AllColumnsFilterProxyModel(QObject* parent = nullptr); + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; +}; + + +class BINARYNINJAUIAPI ContainerBrowser : public QDialog +{ + Q_OBJECT + + TransformSessionRef m_session; + + ContainerTreeModel* m_model; + + QLineEdit* m_filter = nullptr; + QTreeView* m_tree = nullptr; + QPlainTextEdit* m_preview = nullptr; + QLabel* m_status = nullptr; + QDialogButtonBox* m_buttons = nullptr; + AllColumnsFilterProxyModel* m_proxy = nullptr; + + QStringList m_selectedPaths; + + void connectSignals(); + void loadRoot(); + void updatePreviewForIndex(const QModelIndex& proxyIndex); + static QString toHexDump(const QByteArray& data, int bytesPerLine = 16); + +public: + ContainerBrowser(TransformSessionRef session, QWidget* parent = nullptr); + + QStringList selectedPaths() const { return m_selectedPaths; } + + static BinaryViewRef openContainerFile(const QString& path); +}; diff --git a/ui/options.h b/ui/options.h index 3206fc7e..764cb85c 100644 --- a/ui/options.h +++ b/ui/options.h @@ -53,7 +53,7 @@ class BINARYNINJAUIAPI OptionsDialog : public QDialog public: OptionsDialog(QWidget* parent, const QString& name); virtual ~OptionsDialog(); - bool loadViews(); + bool loadViews(BinaryViewRef existingView = nullptr); Q_SIGNALS: void openFile(FileContext* file); diff --git a/ui/uitypes.h b/ui/uitypes.h index 476c0d79..89fa43e6 100644 --- a/ui/uitypes.h +++ b/ui/uitypes.h @@ -108,6 +108,8 @@ typedef BinaryNinja::Ref<BinaryNinja::Tag> TagRef; typedef BinaryNinja::Ref<BinaryNinja::TagType> TagTypeRef; typedef BinaryNinja::Ref<BinaryNinja::TemporaryFile> TemporaryFileRef; typedef BinaryNinja::Ref<BinaryNinja::Transform> TransformRef; +typedef BinaryNinja::Ref<BinaryNinja::TransformContext> TransformContextRef; +typedef BinaryNinja::Ref<BinaryNinja::TransformSession> TransformSessionRef; typedef BinaryNinja::Ref<BinaryNinja::Type> TypeRef; typedef BinaryNinja::Ref<BinaryNinja::TypeArchive> TypeArchiveRef; typedef BinaryNinja::Ref<BinaryNinja::TypeLibrary> TypeLibraryRef; |
