summaryrefslogtreecommitdiff
path: root/ui/xreflist.h
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2020-02-29 13:40:13 -0500
committerPeter LaFosse <peter@vector35.com>2020-03-18 13:20:40 -0400
commit6fbeb0e96af2a1b61467cf813642329613f573ab (patch)
tree9b78b65ec2f77d3145e6de9f8294ec251344e683 /ui/xreflist.h
parentb67f98d1e982b37ab80c32c019c5c221512e608e (diff)
Cross References Overhaul
- Add ability to toggle between cross reference tree view and table view - Add cross reference search/filtering and pinned cross references - Add count of filtered/total on the 'Filter' button
Diffstat (limited to 'ui/xreflist.h')
-rw-r--r--ui/xreflist.h390
1 files changed, 320 insertions, 70 deletions
diff --git a/ui/xreflist.h b/ui/xreflist.h
index 6d14f908..03498d8c 100644
--- a/ui/xreflist.h
+++ b/ui/xreflist.h
@@ -2,18 +2,32 @@
#include <QtCore/QAbstractItemModel>
#include <QtCore/QItemSelectionModel>
+#include <QtCore/QSortFilterProxyModel>
+#include <QtCore/QModelIndex>
+#include <QtGui/QImage>
+#include <QtCore/QParallelAnimationGroup>
#include <QtWidgets/QListView>
#include <QtWidgets/QStyledItemDelegate>
#include <QtWidgets/QTreeView>
-#include <QtGui/QImage>
+#include <QtWidgets/QTableView>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QScrollArea>
+#include <QtWidgets/QToolButton>
+
#include <vector>
+#include <deque>
#include <memory>
#include "binaryninjaapi.h"
#include "dockhandler.h"
#include "viewframe.h"
+#include "fontsettings.h"
-
+class XrefHeader;
class XrefItem
{
public:
@@ -36,84 +50,123 @@ protected:
uint64_t m_addr;
XrefType m_type;
XrefDirection m_direction;
+ mutable XrefHeader* m_parentItem;
+ mutable int m_size;
- std::vector<std::shared_ptr<XrefItem>> m_childItems;
- std::weak_ptr<XrefItem> m_parentItem;
public:
- XrefItem();
- XrefItem(FunctionRef func);
- XrefItem(FunctionRef func, ArchitectureRef arch, uint64_t addr, XrefType type, XrefDirection direction);
- XrefItem(BinaryNinja::ReferenceSource referenceSource, XrefType type, XrefDirection direction);
+ explicit XrefItem();
+ explicit XrefItem(XrefHeader* parent, XrefType type, FunctionRef func);
+ explicit XrefItem(BinaryNinja::ReferenceSource referenceSource, XrefType type, XrefDirection direction);
+ XrefItem(const XrefItem& ref);
virtual ~XrefItem();
- void appendChild(std::shared_ptr<XrefItem> child, std::shared_ptr<XrefItem> parent);
- std::shared_ptr<XrefItem> child(size_t row) const;
- size_t childCount() const { return m_childItems.size(); }
- size_t columnCount() const { return 1; }
- size_t row() const;
- std::weak_ptr<XrefItem> parentItem() const { return m_parentItem; }
XrefDirection direction() const { return m_direction; }
FunctionRef func() const { return m_func; }
ArchitectureRef arch() const { return m_arch; }
uint64_t addr() const { return m_addr; }
XrefType type() const { return m_type; }
+ int size() const { return m_size; }
+ void setSize(int size) const { m_size = size; }
+ void setParent(XrefHeader* parent) const;
+ virtual XrefItem* parent() const { return (XrefItem*)m_parentItem; }
+ virtual XrefItem* child(int) const { return nullptr; }
+ virtual int childCount() const { return 0; }
- bool operator==(const XrefItem& other)
- {
- if (!((m_direction == other.m_direction) &&
- (m_addr == other.m_addr) &&
- (m_type == other.m_type)))
- return false;
-
- if (!m_func ^ !other.m_func)
- return false;
-
- if (!m_func && !other.m_func)
- return true;
-
- return (m_func->GetStart() == other.m_func->GetStart());
- }
-
- bool operator!=(const XrefItem& other)
- {
- return !(*this == other);
- }
+ int row() const;
+ bool operator==(const XrefItem& other) const;
+ bool operator!=(const XrefItem& other) const;
};
class XrefHeader: public XrefItem
{
+protected:
QString m_name;
public:
- XrefHeader() {}
- XrefHeader(const QString& name);
+ XrefHeader();
+ XrefHeader(const QString& name, XrefItem::XrefType type, XrefHeader* parent, FunctionRef func);
virtual ~XrefHeader() {}
+
virtual QString name() const { return m_name; }
+ XrefItem::XrefType type() const { return m_type; }
+
+ virtual void appendChild(XrefItem* ref) = 0;
+ virtual int row(const XrefItem* item) const = 0;
+ virtual XrefItem* child(int i) const = 0;
+ virtual int childCount() const = 0;
+};
+
+
+class XrefFunctionHeader : public XrefHeader
+{
+ std::deque<XrefItem*> m_refs;
+public:
+ XrefFunctionHeader();
+ XrefFunctionHeader(FunctionRef func, XrefHeader* parent, XrefItem* child);
+ XrefFunctionHeader(const XrefFunctionHeader& header);
+ virtual int childCount() const override { return m_refs.size(); }
+ virtual uint64_t addr() const { return m_func->GetStart(); }
+ virtual void appendChild(XrefItem* ref) override;
+ virtual int row(const XrefItem* item) const override;
+ virtual XrefItem* child(int i) const override;
+};
+
+
+class XrefCodeReferences: public XrefHeader
+{
+ std::map<FunctionRef, XrefFunctionHeader*> m_refs;
+ std::deque<XrefFunctionHeader*> m_refList;
+public:
+ XrefCodeReferences(XrefHeader* parent);
+ virtual ~XrefCodeReferences();
+ virtual int childCount() const override { return m_refs.size(); }
+ virtual void appendChild(XrefItem* ref) override;
+ XrefHeader* parentOf(XrefItem* ref) const;
+ virtual int row(const XrefItem* item) const override;
+ virtual XrefItem* child(int i) const override;
};
-class XrefFunctionHeader: public XrefItem
+class XrefDataReferences: public XrefHeader
{
+ std::deque<XrefItem*> m_refs;
public:
- XrefFunctionHeader() {}
- XrefFunctionHeader(FunctionRef func) : XrefItem(func) {};
- virtual ~XrefFunctionHeader() {}
+ XrefDataReferences(XrefHeader* parent);
+ virtual ~XrefDataReferences();
+ virtual int childCount() const override { return m_refs.size(); };
+ virtual void appendChild(XrefItem* ref) override;
+ virtual int row(const XrefItem* item) const override;
+ virtual XrefItem* child(int i) const override;
};
-class BINARYNINJAUIAPI CrossReferenceListModel : public QAbstractItemModel
+class XrefRoot: public XrefHeader
+{
+ std::map<int, XrefHeader*> m_refs;
+public:
+ XrefRoot();
+ XrefRoot(XrefRoot&& root);
+ ~XrefRoot();
+ virtual int childCount() const override { return m_refs.size(); }
+ void appendChild(XrefItem* ref) override;
+ XrefHeader* parentOf(XrefItem* ref);
+ virtual int row(const XrefItem* item) const override;
+ virtual XrefHeader* child(int i) const override;
+};
+
+class BINARYNINJAUIAPI CrossReferenceTreeModel : public QAbstractItemModel
{
Q_OBJECT
- std::shared_ptr<XrefHeader> m_rootItem;
+ XrefRoot* m_rootItem;
QWidget* m_owner;
BinaryViewRef m_data;
- std::vector<std::shared_ptr<XrefItem>> m_refs;
+ std::vector<XrefItem> m_refs;
public:
- CrossReferenceListModel(QWidget* parent, BinaryViewRef data);
- virtual ~CrossReferenceListModel() {}
+ CrossReferenceTreeModel(QWidget* parent, BinaryViewRef data);
+ virtual ~CrossReferenceTreeModel() {}
virtual QModelIndex index(int row, int col, const QModelIndex& parent = QModelIndex()) const override;
virtual QVariant data(const QModelIndex& i, int role) const override;
@@ -124,9 +177,42 @@ public:
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
QModelIndex nextValidIndex(const QModelIndex& current) const;
QModelIndex prevValidIndex(const QModelIndex& current) const;
- bool selectRef(XrefItem* ref, XrefItem* root, QItemSelectionModel* selectionModel);
+ bool selectRef(XrefItem* ref, QItemSelectionModel* selectionModel);
+ XrefRoot* getRoot() { return m_rootItem; }
+ bool setModelData(std::vector<XrefItem>& refs, QItemSelectionModel* selectionModel, bool& selectionUpdated);
+ int leafCount() const;
+};
- bool setModelData(std::vector<std::shared_ptr<XrefItem>>& refs, QItemSelectionModel* selectionModel, bool& selectionUpdated);
+
+class BINARYNINJAUIAPI CrossReferenceTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+ QWidget* m_owner;
+ BinaryViewRef m_data;
+ std::vector<XrefItem> m_refs;
+public:
+ enum ColumnHeaders
+ {
+ Direction = 0,
+ Address = 1,
+ Function = 2,
+ Preview = 3
+ };
+
+ CrossReferenceTableModel(QWidget* parent, BinaryViewRef data);
+ virtual ~CrossReferenceTableModel() {}
+
+ virtual QModelIndex index(int row, int col, const QModelIndex& parent = QModelIndex()) const override;
+ virtual QVariant data(const QModelIndex& i, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex& index) const override;
+ virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { (void)parent; return m_refs.size(); };
+ virtual QModelIndex parent(const QModelIndex& i) const override { (void)i; return QModelIndex(); }
+ virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override { (void) parent; return 4;};
+ virtual QVariant headerData(int column, Qt::Orientation orientation, int role) const override;
+ virtual bool hasChildren(const QModelIndex&) const override { return false; }
+ bool setModelData(std::vector<XrefItem>& refs, QItemSelectionModel* selectionModel, bool& selectionUpdated);
+ const XrefItem& getRow(int idx);
};
@@ -137,58 +223,222 @@ class BINARYNINJAUIAPI CrossReferenceItemDelegate: public QStyledItemDelegate
QFont m_font;
int m_baseline, m_charWidth, m_charHeight, m_charOffset;
QImage m_xrefTo, m_xrefFrom;
-
- void initFont();
+ bool m_table;
public:
- CrossReferenceItemDelegate(QWidget* parent);
+ CrossReferenceItemDelegate(QWidget* parent, bool table);
void updateFonts();
-
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+ virtual void paintTreeRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const;
+ virtual void paintTableRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const;
+ virtual QImage DrawArrow(bool direction) const;
};
-class BINARYNINJAUIAPI CrossReferenceList: public QTreeView, public DockContextHandler
+
+class BINARYNINJAUIAPI CrossReferenceFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
- Q_INTERFACES(DockContextHandler)
+ bool m_showData = true;
+ bool m_showCode = true;
+ bool m_showIncoming = true;
+ bool m_showOutgoing = true;
+ bool m_table;
+
+public:
+ CrossReferenceFilterProxyModel(QObject* parent, bool table);
+protected:
+ virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
+ virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
+ virtual QVariant data(const QModelIndex& index, int role) const override;
+ virtual bool hasChildren(const QModelIndex& parent) const override;
+public Q_SLOTS:
+ void directionChanged(int index);
+ void typeChanged(int index);
+};
+
+class CrossReferenceWidget;
+class BINARYNINJAUIAPI CrossReferenceContainer
+{
+protected:
ViewFrame* m_view;
- CrossReferenceListModel* m_tree;
+ CrossReferenceWidget* m_parent;
+ BinaryViewRef m_data;
+ UIActionHandler m_actionHandler;
+public:
+ CrossReferenceContainer(CrossReferenceWidget* parent, ViewFrame* view, BinaryViewRef data);
+ virtual ~CrossReferenceContainer() {}
+ virtual QModelIndex translateIndex(const QModelIndex& idx) const = 0;
+ virtual bool getReference(const QModelIndex& idx, FunctionRef& func, uint64_t& addr) const = 0;
+ virtual QModelIndex nextIndex() = 0;
+ virtual QModelIndex prevIndex() = 0;
+ virtual QModelIndexList selectedRows() const = 0;
+ virtual bool hasSelection() const = 0;
+ virtual void setNewSelection(std::vector<XrefItem>& refs, bool newRefTarget) = 0;
+ virtual void updateFonts() = 0;
+ virtual int leafCount() const = 0;
+ virtual int filteredCount() const = 0;
+};
+
+
+class BINARYNINJAUIAPI CrossReferenceTree: public QTreeView, public CrossReferenceContainer
+{
+ Q_OBJECT
+
+ CrossReferenceTreeModel* m_tree;
+ CrossReferenceFilterProxyModel* m_model;
+ CrossReferenceItemDelegate* m_itemDelegate;
+
+protected:
+ void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override;
+ virtual bool getReference(const QModelIndex& idx, FunctionRef& func, uint64_t& addr) const override;
+
+public:
+ CrossReferenceTree(CrossReferenceWidget* parent, ViewFrame* view, BinaryViewRef data);
+ virtual ~CrossReferenceTree();
+
+ void setNewSelection(std::vector<XrefItem>& refs, bool newRefTarget) override;
+ virtual QModelIndex nextIndex() override;
+ virtual QModelIndex prevIndex() override;
+ virtual bool hasSelection() const override { return selectionModel()->selectedRows().size() != 0; }
+ virtual void mouseMoveEvent(QMouseEvent* e) override;
+ virtual void mousePressEvent(QMouseEvent* e) override;
+ virtual void keyPressEvent(QKeyEvent* e) override;
+ virtual bool event(QEvent* event) override;
+ virtual QModelIndexList selectedRows() const override { return selectionModel()->selectedRows(); }
+ virtual QModelIndex translateIndex(const QModelIndex& idx) const override { return m_model->mapToSource(idx); }
+ virtual void updateFonts() override;
+ virtual int leafCount() const override;
+ virtual int filteredCount() const override;
+ void updateTextFilter(const QString& filterText);
+
+Q_SIGNALS:
+ void newSelection();
+};
+
+
+class BINARYNINJAUIAPI CrossReferenceTable: public QTableView, public CrossReferenceContainer
+{
+ Q_OBJECT
+
+ CrossReferenceTableModel* m_table;
CrossReferenceItemDelegate* m_itemDelegate;
+ CrossReferenceFilterProxyModel* m_model;
+
+ int m_charWidth = 0;
+ int m_charHeight = 0;
+ int m_maxWidthAddress = 0;
+ int m_maxWidthFunction = 0;
+ int m_maxWidthPreview = 0;
+public:
+ CrossReferenceTable(CrossReferenceWidget* parent, ViewFrame* view, BinaryViewRef data);
+ virtual ~CrossReferenceTable();
+
+ void setNewSelection(std::vector<XrefItem>& refs, bool newRefTarget) override;
+ virtual QModelIndex nextIndex() override;
+ virtual QModelIndex prevIndex() override;
+ virtual bool hasSelection() const override { return selectionModel()->selectedRows().size() != 0; }
+ virtual QModelIndexList selectedRows() const override { return selectionModel()->selectedRows(); }
+ virtual bool getReference(const QModelIndex& idx, FunctionRef& func, uint64_t& addr) const override;
+ virtual void mouseMoveEvent(QMouseEvent* e) override;
+ virtual void mousePressEvent(QMouseEvent* e) override;
+ virtual void keyPressEvent(QKeyEvent* e) override;
+ virtual bool event(QEvent* event) override;
+ virtual QModelIndex translateIndex(const QModelIndex& idx) const override { return m_model->mapToSource(idx); }
+ virtual void updateFonts() override;
+ virtual int leafCount() const override;
+ virtual int filteredCount() const override;
+public Q_SLOTS:
+ void updateTextFilter(const QString& filterText);
+Q_SIGNALS:
+ void newSelection();
+};
+
+class ExpandableGroup;
+class BINARYNINJAUIAPI CrossReferenceWidget: public QWidget, public DockContextHandler
+{
+ Q_OBJECT
+ Q_INTERFACES(DockContextHandler)
+
+ ViewFrame* m_view;
BinaryViewRef m_data;
+ QAbstractItemView* m_object;
+ QLabel* m_label;
+ QCheckBox* m_pinRefs;
+ QComboBox* m_direction, *m_type;
+ CrossReferenceTable* m_table;
+ CrossReferenceTree* m_tree;
+ CrossReferenceContainer* m_container;
+ bool m_useTableView;
QTimer* m_hoverTimer;
QPoint m_hoverPos;
+ QStringList m_historyEntries;
+ int m_historySize;
+ QLineEdit* m_lineEdit;
+ ExpandableGroup* m_group;
uint64_t m_curRefTarget = 0;
+ uint64_t m_curRefTargetEnd = 0;
+ uint64_t m_newRefTarget = 0;
+ uint64_t m_newRefTargetEnd = 0;
bool m_navigating = false;
bool m_navToNextOrPrevStarted = false;
+ bool m_pinned;
-protected:
virtual void contextMenuEvent(QContextMenuEvent* event) override;
- virtual void keyPressEvent(QKeyEvent* e) override;
- virtual void mouseMoveEvent(QMouseEvent* e) override;
- virtual void mousePressEvent(QMouseEvent* e) override;
- virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
+ virtual void wheelEvent(QWheelEvent* e) override;
+
+public:
+ CrossReferenceWidget(ViewFrame* view, BinaryViewRef data, bool pinned);
virtual void notifyFontChanged() override;
virtual bool shouldBeVisible(ViewFrame* frame) override;
- virtual void wheelEvent(QWheelEvent* e) override;
- virtual void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
- void goToReference(const QModelIndex& idx);
+
+ virtual void setCurrentSelection(uint64_t begin, uint64_t end);
+ virtual void setCurrentPinnedSelection(uint64_t begin, uint64_t end);
+ void updatePinnedSelection();
+ virtual void navigateToNext();
+ virtual void navigateToPrev();
+ virtual bool selectFirstRow();
+ virtual bool hasSelection() const;
+ virtual void goToReference(const QModelIndex& idx);
+
+ virtual void restartHoverTimer(QMouseEvent* e);
+ virtual void startHoverTimer(QMouseEvent* e);
+ virtual void keyPressEvent(QKeyEvent* e) override;
+ virtual bool keyPressHandler(QKeyEvent* e);
+ void useTableView(bool tableView, bool init);
+ bool tableView() const { return m_useTableView; }
private Q_SLOTS:
void hoverTimerEvent();
+
+public Q_SLOTS:
void referenceActivated(const QModelIndex& idx);
+ void pinnedStateChanged(bool state);
+ void selectionChanged();
+ void typeChanged(int change);
+ void directionChanged(int change);
+};
-public:
- CrossReferenceList(ViewFrame* view, BinaryViewRef data);
- virtual ~CrossReferenceList();
- void setCurrentSelection(uint64_t begin, uint64_t end);
- void navigateToNext();
- void navigateToPrev();
+class BINARYNINJAUIAPI ExpandableGroup : public QWidget
+{
+ Q_OBJECT
- bool hasSelection();
-};
+private:
+ QToolButton* m_button;
+ QParallelAnimationGroup* m_animation;
+ QScrollArea* m_content;
+ int m_duration = 100;
+
+public Q_SLOTS:
+ void toggle(bool collapsed);
+
+public:
+ explicit ExpandableGroup(const QString& title = "", QWidget* parent = nullptr);
+ void setContentLayout(QLayout* contentLayout);
+ void setTitle(const QString& title) { m_button->setText(title); }
+}; \ No newline at end of file