diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2021-08-13 16:21:20 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2021-10-04 18:55:01 -0600 |
| commit | c80d3d99b9e11c4120cd3a36349d8161f01c7a24 (patch) | |
| tree | e1a5ed642b638f0a4e4d770b35a86f0c04bda5c4 | |
| parent | 072021568045f1bceb39b3dc217235c5eebc37a9 (diff) | |
Custom tab widget for tear-away tabs
| -rw-r--r-- | binaryninjaapi.h | 3 | ||||
| -rw-r--r-- | ui/addressindicator.h | 1 | ||||
| -rw-r--r-- | ui/featuremap.h | 18 | ||||
| -rw-r--r-- | ui/minigraph.h | 16 | ||||
| -rw-r--r-- | ui/sidebar.h | 2 | ||||
| -rw-r--r-- | ui/tabwidget.h | 184 | ||||
| -rw-r--r-- | ui/viewframe.h | 14 |
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); |
