summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2021-08-13 16:21:20 -0400
committerRusty Wagner <rusty.wagner@gmail.com>2021-10-04 18:55:01 -0600
commitc80d3d99b9e11c4120cd3a36349d8161f01c7a24 (patch)
treee1a5ed642b638f0a4e4d770b35a86f0c04bda5c4
parent072021568045f1bceb39b3dc217235c5eebc37a9 (diff)
Custom tab widget for tear-away tabs
-rw-r--r--binaryninjaapi.h3
-rw-r--r--ui/addressindicator.h1
-rw-r--r--ui/featuremap.h18
-rw-r--r--ui/minigraph.h16
-rw-r--r--ui/sidebar.h2
-rw-r--r--ui/tabwidget.h184
-rw-r--r--ui/viewframe.h14
7 files changed, 218 insertions, 20 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index f3bea556..917341aa 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -262,6 +262,9 @@ namespace BinaryNinja
m_obj = other.m_obj;
}
other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
}
return *this;
}
diff --git a/ui/addressindicator.h b/ui/addressindicator.h
index 5b724d96..d67e7d79 100644
--- a/ui/addressindicator.h
+++ b/ui/addressindicator.h
@@ -16,6 +16,7 @@ class BINARYNINJAUIAPI AddressIndicator: public MenuHelper
public:
AddressIndicator(QWidget* parent);
+ void clear();
void setOffsets(uint64_t begin, uint64_t end, BinaryViewRef view);
protected:
diff --git a/ui/featuremap.h b/ui/featuremap.h
index f8c38cdf..ec597038 100644
--- a/ui/featuremap.h
+++ b/ui/featuremap.h
@@ -27,10 +27,9 @@ class Menu;
class View;
class ViewFrame;
-class BINARYNINJAUIAPI FeatureMap: public QWidget, public BinaryNinja::BinaryDataNotification, public DockContextHandler
+class BINARYNINJAUIAPI FeatureMap: public QWidget, public BinaryNinja::BinaryDataNotification
{
Q_OBJECT
- Q_INTERFACES(DockContextHandler)
QImage* m_image = nullptr;
QImage* m_staticImage = nullptr;
@@ -45,9 +44,8 @@ class BINARYNINJAUIAPI FeatureMap: public QWidget, public BinaryNinja::BinaryDat
size_t m_bvHeight = 0;
uint64_t m_bvLength = 0;
- int m_defaultWidth = 100;
- bool m_autoRotate = true;
- bool m_naturalOrientation = true;
+ int m_defaultWidth = 64;
+ bool m_naturalOrientation;
int m_curLocX = 0;
int m_curLocY = 0;
@@ -57,7 +55,8 @@ class BINARYNINJAUIAPI FeatureMap: public QWidget, public BinaryNinja::BinaryDat
QVector<QColor> m_colors;
QVector<QRgb> m_colorTable;
- bool m_enableOrientationUpdate = false;
+ Menu m_menu;
+ ContextMenuManager* m_contextMenuManager;
class BackgroundRefresh: public BinaryNinja::RefCountObject
{
@@ -74,18 +73,17 @@ class BINARYNINJAUIAPI FeatureMap: public QWidget, public BinaryNinja::BinaryDat
BinaryNinja::Ref<BackgroundRefresh> m_backgroundRefresh = nullptr;
void updateCoordinates();
- bool updateOrientation();
public:
- FeatureMap(ViewFrame* frame, BinaryViewRef data);
+ FeatureMap(ViewFrame* frame, BinaryViewRef data, bool vertical = true);
virtual ~FeatureMap();
View* getBinaryDataNavigableView(bool preferGraphView = false);
void backgroundRefresh();
std::pair<uint64_t, bool> getLinearOffsetForAddress(uint64_t addr);
- virtual void notifyOffsetChanged(uint64_t offset) override;
- virtual void notifyThemeChanged() override;
+ void notifyOffsetChanged(uint64_t offset);
+ void notifyThemeChanged();
void renderDataVariable(const BinaryNinja::DataVariable& var, bool ignoreString = false);
diff --git a/ui/minigraph.h b/ui/minigraph.h
index 8af61e83..90a0c318 100644
--- a/ui/minigraph.h
+++ b/ui/minigraph.h
@@ -5,18 +5,17 @@
#include <QtWidgets/QWidget>
#include "binaryninjaapi.h"
-#include "dockhandler.h"
#include "uitypes.h"
+#include "sidebar.h"
class ContextMenuManager;
class FlowGraphWidget;
class Menu;
class ViewFrame;
-class BINARYNINJAUIAPI MiniGraph: public QWidget, public DockContextHandler
+class BINARYNINJAUIAPI MiniGraph: public SidebarWidget
{
Q_OBJECT
- Q_INTERFACES(DockContextHandler)
ViewFrame* m_frame;
FlowGraphWidget* m_flowGraphWidget = nullptr;
@@ -26,8 +25,6 @@ public:
~MiniGraph();
virtual void notifyViewChanged(ViewFrame* frame) override;
- virtual void notifyVisibilityChanged(bool visible) override;
- virtual bool shouldBeVisible(ViewFrame* frame) override;
protected:
virtual void contextMenuEvent(QContextMenuEvent* event) override;
@@ -39,3 +36,12 @@ protected:
public Q_SLOTS:
void notifyUpdate();
};
+
+
+class BINARYNINJAUIAPI MiniGraphSidebarWidgetType: public SidebarWidgetType
+{
+public:
+ MiniGraphSidebarWidgetType();
+ virtual SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override;
+ virtual bool isInReferenceArea() const override { return true; }
+};
diff --git a/ui/sidebar.h b/ui/sidebar.h
index b2ae9261..7d8d1b02 100644
--- a/ui/sidebar.h
+++ b/ui/sidebar.h
@@ -178,6 +178,8 @@ public:
void toggleSidebar();
+ void moveContextToContainer(ViewFrame* frame, SidebarWidgetContainer* target);
+
Q_SIGNALS:
void showContents();
void hideContents();
diff --git a/ui/tabwidget.h b/ui/tabwidget.h
new file mode 100644
index 00000000..a02f8cd9
--- /dev/null
+++ b/ui/tabwidget.h
@@ -0,0 +1,184 @@
+#pragma once
+
+#include <QtWidgets/QTabWidget>
+#include <QtWidgets/QTabBar>
+#include <QtWidgets/QStackedWidget>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QAbstractScrollArea>
+#include <QtWidgets/QStylePainter>
+#include <QtWidgets/QRubberBand>
+#include <QtGui/QMouseEvent>
+#include "uitypes.h"
+
+
+class DockableTabWidget;
+
+class BINARYNINJAUIAPI DockableTabCollection
+{
+ std::set<DockableTabWidget*> m_containers;
+
+public:
+ void registerContainer(DockableTabWidget* widget);
+ void unregisterContainer(DockableTabWidget* widget);
+
+ const std::set<DockableTabWidget*>& containers() const { return m_containers; }
+};
+
+class BINARYNINJAUIAPI TabDragIndicator: public QWidget
+{
+ Q_OBJECT
+
+ QPixmap m_pixmap;
+ QImage m_newWindowImage;
+ QSize m_size, m_currentSize;
+ QPoint m_offset;
+ bool m_newWindow;
+
+public:
+ TabDragIndicator(QPixmap pixmap, QSize size, QPoint pt, QPoint offset, bool newWindow);
+ void moveToMouse(QPoint pt);
+
+ QPixmap pixmap() const { return m_pixmap; }
+ QSize size() const { return m_size; }
+ QPoint offset() const { return m_offset; }
+
+protected:
+ virtual QSize sizeHint() const override;
+ virtual QSize minimumSizeHint() const override;
+ virtual void paintEvent(QPaintEvent* event) override;
+};
+
+class BINARYNINJAUIAPI DockableTabBar: public QAbstractScrollArea
+{
+ Q_OBJECT
+
+ struct TabInfo
+ {
+ QString title;
+ QString toolTip;
+ QRect tabRect, closeButtonRect, closeIconRect;
+ };
+
+ DockableTabCollection* m_collection;
+ std::vector<TabInfo> m_tabs;
+ int m_active = -1;
+
+ bool m_mouseInside = false;
+ int m_closeButtonHover = -1;
+ int m_closeButtonDown = -1;
+
+ std::optional<QPoint> m_tabDragStart;
+ TabDragIndicator* m_tabDragIndicator = nullptr;
+ DockableTabBar* m_tabDragTarget = nullptr;
+ int m_tabDragWidth;
+ int m_tabDragTargetIndex = -1;
+ bool m_tabDragNewWindow = false;
+ QRubberBand* m_tabDropIndicator = nullptr;
+
+ int m_placeholderIndex = -1;
+ int m_placeholderWidth;
+ QRect m_placeholderRect;
+
+ QTimer* m_timer;
+
+ QStyleOptionTab styleForTab(int idx, const TabInfo& info) const;
+ QSize sizeForTab(const QStyleOptionTab& tabStyle, const TabInfo& info) const;
+ int closeButtonSize() const;
+ void updateLayout();
+ void paintTab(QStylePainter& p, const TabInfo& info, int i, const QRect& rect);
+
+public:
+ DockableTabBar(DockableTabCollection* collection);
+ virtual ~DockableTabBar();
+
+ int addTab(const QString& title);
+ int insertTab(int idx, const QString& title);
+ void removeTab(int idx);
+ void setCurrentIndex(int idx);
+ void setTabText(int idx, const QString& title);
+ void setTabToolTip(int idx, const QString& toolTip);
+
+ int count() const;
+ int currentIndex() const;
+ int tabAt(const QPoint& pt);
+ QRect tabRect(int idx);
+ QString tabText(int idx);
+ QString tabToolTip(int idx);
+
+ void ensureCurrentTabVisible();
+
+Q_SIGNALS:
+ void currentChanged(int idx);
+ void tabCloseRequested(int idx);
+ void tabMoved(int oldIdx, int newIdx);
+ void newWindowForTab(int idx, QRect rectHint);
+ void reparentTab(int oldIdx, DockableTabWidget* target, int newIdx);
+
+private Q_SLOTS:
+ void underMouseTimerEvent();
+
+protected:
+ virtual QSize sizeHint() const override;
+ virtual QSize minimumSizeHint() const override;
+ virtual void paintEvent(QPaintEvent* event) override;
+ virtual void enterEvent(QEnterEvent* event) override;
+ virtual void leaveEvent(QEvent* event) override;
+ virtual void mouseMoveEvent(QMouseEvent* event) override;
+ virtual void mousePressEvent(QMouseEvent* event) override;
+ virtual void mouseReleaseEvent(QMouseEvent* event) override;
+ virtual void resizeEvent(QResizeEvent* event) override;
+ virtual void wheelEvent(QWheelEvent* event) override;
+};
+
+class BINARYNINJAUIAPI DockableTabWidget: public QWidget
+{
+ Q_OBJECT
+
+ DockableTabCollection* m_collection;
+ DockableTabBar* m_bar;
+ QHBoxLayout* m_barLayout;
+ QStackedWidget* m_widgets;
+
+ void addReparentedTab(DockableTabWidget* source, int idx, QWidget* widget,
+ const QString& title, const QString& toolTip);
+
+public:
+ DockableTabWidget(DockableTabCollection* collection);
+
+ int addTab(QWidget* widget, const QString& title);
+ int insertTab(int idx, QWidget* widget, const QString& title);
+ void removeTab(int idx);
+
+ int count();
+ int currentIndex();
+ QWidget* currentWidget();
+ QWidget* widget(int idx);
+ DockableTabBar* tabBar() const { return m_bar; }
+ QString tabText(int idx);
+ int indexOf(QWidget* widget);
+
+ void setCurrentIndex(int idx);
+ void setTabText(int idx, const QString& title);
+
+ void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner);
+
+ virtual QSize sizeHint() const override;
+
+protected:
+ virtual void paintEvent(QPaintEvent* event) override;
+
+Q_SIGNALS:
+ void tabCloseRequested(int idx);
+ void currentChanged(int idx);
+ void tabMoved(int oldIdx, int newIdx);
+ void newWindowForTab(int idx, QRect rectHint);
+ void tabRemovedForReparent(int oldIdx, QWidget* widget, DockableTabWidget* target, int newIdx);
+ void tabAddedForReparent(int idx, DockableTabWidget* source);
+
+private Q_SLOTS:
+ void tabBarCurrentChanged(int idx);
+ void tabBarCloseRequested(int idx);
+ void tabBarTabMoved(int oldIdx, int newIdx);
+ void tabBarNewWindowForTab(int idx, QRect rectHint);
+ void reparentTab(int oldIdx, DockableTabWidget* target, int newIdx);
+};
diff --git a/ui/viewframe.h b/ui/viewframe.h
index d64dcc0a..1445c780 100644
--- a/ui/viewframe.h
+++ b/ui/viewframe.h
@@ -309,7 +309,6 @@ private:
bool m_fileContentsLock = true; // file contents protection from accidental modification in the UI
ClickableStateLabel* m_fileContentsLockStatus;
BinaryViewRef m_data;
- DockHandler* m_docks;
QWidget* m_view = nullptr;
QWidget* m_viewContainer;
QVBoxLayout* m_viewLayout;
@@ -318,6 +317,10 @@ private:
std::list<BinaryNinja::Ref<HistoryEntry>> m_back, m_forward;
bool m_graphViewPreferred = false;
std::vector<QString> m_viewTypePriority;
+ QStackedWidget* m_featureMapContainer;
+ std::map<BinaryViewRef, FeatureMap*> m_featureMaps;
+ QSplitter* m_featureMapSplitter;
+ bool m_rightSideFeatureMap = true;
UIActionHandler m_actionHandler;
@@ -345,7 +348,7 @@ public:
void setFileContentsLocked(bool enable);
QWidget* getFileContentsLockStatus();
- DockHandler* getDockHandler() const { return m_docks; }
+ DockHandler* getDockHandler();
QString getTabName();
QString getShortFileName();
@@ -367,9 +370,10 @@ public:
bool isGraphViewPreferred() { return m_graphViewPreferred; }
void setGraphViewPreferred(bool graphViewPreferred) { m_graphViewPreferred = graphViewPreferred; }
void focus();
- void closeFeatureMap(bool recreate = false);
- QWidget* createFeatureMap();
+ void createFeatureMap();
+ void recreateFeatureMaps();
void refreshFeatureMap();
+ void updateFeatureMapLocation(const ViewLocation& location);
QWidget* getExtendedView(const QString& name, bool create = false);
@@ -463,7 +467,7 @@ public Q_SLOTS:
virtual void compile();
private Q_SLOTS:
- void deleteFeatureMap(bool recreate);
+ void splitterMoved(int pos, int idx);
Q_SIGNALS:
void notifyCloseFeatureMap(bool recreate);