summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2021-10-07 12:57:07 -0600
committerRusty Wagner <rusty.wagner@gmail.com>2021-10-26 16:16:50 -0600
commit644f9709668eca8c206d662bf40361180ed1cb8c (patch)
treebc75058cfc894de891aa8419def6b9063bff2943
parentcb46d56c6c95a945bd2835d042ec1c79d16a16ef (diff)
Replace log/scripting console dock widgets with global area concept
-rw-r--r--python/examples/helloglobalarea.py83
-rw-r--r--ui/globalarea.h121
-rw-r--r--ui/logview.h17
-rw-r--r--ui/scriptingconsole.h9
-rw-r--r--ui/tabwidget.h163
-rw-r--r--ui/uicontext.h2
6 files changed, 369 insertions, 26 deletions
diff --git a/python/examples/helloglobalarea.py b/python/examples/helloglobalarea.py
new file mode 100644
index 00000000..565cedb4
--- /dev/null
+++ b/python/examples/helloglobalarea.py
@@ -0,0 +1,83 @@
+# Copyright (c) 2015-2021 Vector 35 Inc
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+# This is an example UI plugin which demonstrates how to add global area widgets to Binary Ninja.
+# See .../api/ui/globalarea.h for interface details.
+
+from binaryninjaui import GlobalAreaWidget, GlobalArea, UIActionHandler
+from PySide6 import QtCore
+from PySide6.QtCore import Qt, QRectF
+from PySide6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QLabel, QWidget
+from PySide6.QtGui import QImage, QPixmap, QPainter, QFont, QColor
+
+instance_id = 0
+
+# Global area widgets must derive from GlobalAreaWidget, not QWidget. GlobalAreaWidget is a QWidget but
+# provides callbacks for global area events, and must be created with a title.
+class HelloGlobalAreaWidget(GlobalAreaWidget):
+ def __init__(self, name):
+ global instance_id
+ GlobalAreaWidget.__init__(self, name)
+ self.actionHandler = UIActionHandler()
+ self.actionHandler.setupActionHandler(self)
+ offset_layout = QHBoxLayout()
+ offset_layout.addWidget(QLabel("Offset: "))
+ self.offset = QLabel(hex(0))
+ offset_layout.addWidget(self.offset)
+ offset_layout.setAlignment(QtCore.Qt.AlignCenter)
+ datatype_layout = QHBoxLayout()
+ datatype_layout.addWidget(QLabel("Data Type: "))
+ self.datatype = QLabel("")
+ datatype_layout.addWidget(self.datatype)
+ datatype_layout.setAlignment(QtCore.Qt.AlignCenter)
+ layout = QVBoxLayout()
+ title = QLabel(name, self)
+ title.setAlignment(QtCore.Qt.AlignCenter)
+ instance = QLabel("Instance: " + str(instance_id), self)
+ instance.setAlignment(QtCore.Qt.AlignCenter)
+ layout.addStretch()
+ layout.addWidget(title)
+ layout.addWidget(instance)
+ layout.addLayout(datatype_layout)
+ layout.addLayout(offset_layout)
+ layout.addStretch()
+ self.setLayout(layout)
+ instance_id += 1
+ self.data = None
+
+ def notifyOffsetChanged(self, offset):
+ self.offset.setText(hex(offset))
+
+ def notifyViewChanged(self, view_frame):
+ if view_frame is None:
+ self.datatype.setText("None")
+ self.data = None
+ else:
+ self.datatype.setText(view_frame.getCurrentView())
+ view = view_frame.getCurrentViewInterface()
+ self.data = view.getData()
+
+ def contextMenuEvent(self, event):
+ self.m_contextMenuManager.show(self.m_menu, self.actionHandler)
+
+# Register the global area widget constructor with Binary Ninja. This will create a new
+# global area widget for each window. The callback function receives a `UIContext` object
+# for identifying the window.
+GlobalArea.addWidget(lambda context: HelloGlobalAreaWidget("Hello"))
diff --git a/ui/globalarea.h b/ui/globalarea.h
new file mode 100644
index 00000000..c49679a1
--- /dev/null
+++ b/ui/globalarea.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include <QtWidgets/QWidget>
+#include "theme.h"
+#include "viewframe.h"
+#include "tabwidget.h"
+
+class BINARYNINJAUIAPI GlobalAreaWidget: public QWidget
+{
+ Q_OBJECT
+
+protected:
+ QString m_title;
+ UIActionHandler m_actionHandler;
+ ContextMenuManager* m_contextMenuManager = nullptr;
+ Menu* m_menu = nullptr;
+
+public:
+ GlobalAreaWidget(const QString& title);
+
+ const QString& title() const { return m_title; }
+
+ virtual void notifyFontChanged() { }
+ virtual void notifyOffsetChanged(uint64_t /*offset*/) { }
+ virtual void notifyThemeChanged() { }
+ virtual void notifyViewChanged(ViewFrame* /*frame*/) { }
+ virtual void notifyViewLocationChanged(View* /*view*/, const ViewLocation& /*viewLocation*/) { }
+ virtual void focus();
+};
+
+class BINARYNINJAUIAPI GlobalAreaTabStyle: public DockableTabStyle
+{
+ int closeButtonSize(const QWidget* widget) const;
+
+public:
+ virtual QSize sizeForTab(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual QRect closeButtonRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual QRect closeIconRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual void paintTab(const QWidget* widget, QStylePainter& p, const DockableTabInfo& info, int idx,
+ int count, int active, DockableTabInteractionState state, const QRect& rect) const override;
+ virtual DockableTabStyle* duplicate() override;
+};
+
+class BINARYNINJAUIAPI GlobalAreaHideButton: public QWidget
+{
+ Q_OBJECT
+
+ bool m_mouseInside = false;
+ bool m_buttonDown = false;
+ QTimer* m_timer;
+
+public:
+ GlobalAreaHideButton();
+ virtual QSize sizeHint() const override;
+
+protected:
+ 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;
+
+private Q_SLOTS:
+ void underMouseTimerEvent();
+
+Q_SIGNALS:
+ void clicked();
+};
+
+class BINARYNINJAUIAPI GlobalArea: public QWidget
+{
+ Q_OBJECT
+
+ SplitTabWidget* m_tabs;
+ DockableTabCollection* m_collection;
+ QSplitter* m_parentSplitter = nullptr;
+ std::optional<QList<int>> m_pendingParentSplitterSizes, m_savedParentSplitterSizes;
+
+ static std::vector<std::function<GlobalAreaWidget*(UIContext*)>> m_widgetFactories;
+
+ QString actionNameForWidget(const QString &title);
+ static QVariant sizesToVariant(const QList<int>& sizes);
+ static std::optional<QList<int>> variantToSizes(const QVariant& variant);
+
+public:
+ GlobalArea();
+ void setSplitter(QSplitter* splitter);
+
+ void addWidget(GlobalAreaWidget* widget, bool canClose = false);
+ static void addWidget(const std::function<GlobalAreaWidget*(UIContext*)>& createWidget);
+
+ void initRegisteredWidgets(UIContext* context);
+
+ void updateFonts();
+ void updateTheme();
+ void updateViewLocation(View* view, const ViewLocation& viewLocation);
+ void viewChanged(ViewFrame* frame);
+
+ bool isWidgetVisible(const QString& title);
+
+ bool toggleVisible();
+ bool toggleWidgetVisible(const QString& title);
+ void focusWidget(const QString& title);
+
+ void saveSizes(const QSettings& settings, const QString& windowStateName);
+ void saveState(const QSettings& settings, const QString& windowStateName);
+ void restoreSizes(const QSettings& settings, const QString& windowStateName);
+ void restoreState(const QSettings& settings, const QString& windowStateName);
+
+Q_SIGNALS:
+ void widgetClosed(GlobalAreaWidget* widget);
+
+private Q_SLOTS:
+ void currentChanged(QWidget* widget);
+ void tabClosed(QWidget* widget);
+ void hideButtonClicked();
+};
diff --git a/ui/logview.h b/ui/logview.h
index c0ff7768..bf9d4627 100644
--- a/ui/logview.h
+++ b/ui/logview.h
@@ -14,7 +14,7 @@
#include "binaryninjaapi.h"
#include "action.h"
-#include "dockhandler.h"
+#include "globalarea.h"
#define LOG_UPDATE_INTERVAL 100
@@ -102,13 +102,13 @@ public Q_SLOTS:
};
-class BINARYNINJAUIAPI LogView: public QListView, public DockContextHandler
+class BINARYNINJAUIAPI LogView: public GlobalAreaWidget
{
Q_OBJECT
- Q_INTERFACES(DockContextHandler)
QPointer<LogStatus> m_logStatus;
std::vector<std::pair<QAction*, bool>> m_actionEnableList;
+ QListView* m_list;
LogListModel* m_listModel;
LogItemDelegate* m_itemDelegate;
QTimer* m_updateTimer;
@@ -118,7 +118,7 @@ class BINARYNINJAUIAPI LogView: public QListView, public DockContextHandler
bool m_hasSelection = false;
public:
- LogView(QWidget* parent, LogStatus* logStatus);
+ LogView(LogStatus* logStatus);
virtual void copy();
virtual bool canCopy();
@@ -128,12 +128,15 @@ public:
static bool IsHexString(const QString& str, std::pair<int, int> offsetLen);
static bool StartsWith0x(const QString& str, std::pair<int, int> offsetLen);
-protected:
- void contextMenuEvent(QContextMenuEvent* event) override;
void notifyFontChanged() override;
void notifyThemeChanged() override;
void notifyViewChanged(ViewFrame* frame) override;
- void notifyVisibilityChanged(bool visible) override;
+ void focus() override;
+
+ LogListModel* model() { return m_listModel; }
+
+protected:
+ void contextMenuEvent(QContextMenuEvent* event) override;
Q_SIGNALS:
void notifyUiStatus();
diff --git a/ui/scriptingconsole.h b/ui/scriptingconsole.h
index b2b3d09e..b0e20253 100644
--- a/ui/scriptingconsole.h
+++ b/ui/scriptingconsole.h
@@ -17,7 +17,7 @@
#include <functional>
#include "binaryninjaapi.h"
#include "action.h"
-#include "dockhandler.h"
+#include "globalarea.h"
#include "uitypes.h"
#define SCRIPT_OUTPUT_UPDATE_INTERVAL 100
@@ -123,10 +123,9 @@ public Q_SLOTS:
class ScriptingConsoleWidget;
-class BINARYNINJAUIAPI ScriptingConsole: public QWidget, public DockContextHandler, BinaryNinja::ScriptingOutputListener
+class BINARYNINJAUIAPI ScriptingConsole: public GlobalAreaWidget, BinaryNinja::ScriptingOutputListener
{
Q_OBJECT
- Q_INTERFACES(DockContextHandler)
struct ScriptOutput
{
@@ -166,8 +165,6 @@ Q_SIGNALS:
protected:
void customEvent(QEvent* event) override;
- void notifyFontChanged() override;
- void notifyVisibilityChanged(bool visible) override;
public:
ScriptingConsole(QWidget* parent, const QString& providerName, const QString& instanceName, ScriptingInstanceRef instance);
@@ -186,6 +183,8 @@ public:
virtual void NotifyError(const std::string& text) override;
virtual void NotifyInputReadyStateChanged(BNScriptingProviderInputReadyState state) override;
virtual void notifyViewChanged(ViewFrame* frame) override;
+ virtual void notifyFontChanged() override;
+ virtual void focus() override;
void moveUpInHistory();
void moveDownInHistory();
diff --git a/ui/tabwidget.h b/ui/tabwidget.h
index fd982b9d..08b84182 100644
--- a/ui/tabwidget.h
+++ b/ui/tabwidget.h
@@ -7,8 +7,10 @@
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QStylePainter>
#include <QtWidgets/QRubberBand>
+#include <QtWidgets/QSplitter>
#include <QtGui/QMouseEvent>
#include "uitypes.h"
+#include "json/json.h"
class DockableTabWidget;
@@ -48,23 +50,74 @@ protected:
virtual void paintEvent(QPaintEvent* event) override;
};
+enum DockableTabInteractionState
+{
+ NoTabInteraction,
+ MouseOverTab,
+ MouseOverCloseButton,
+ CloseButtonPressActive,
+ CloseButtonPressInactive
+};
+
+struct BINARYNINJAUIAPI DockableTabInfo
+{
+ QString title;
+ QString toolTip;
+ QRect tabRect, closeButtonRect, closeIconRect;
+ bool modifiedIndicator;
+ bool canClose;
+};
+
+class BINARYNINJAUIAPI DockableTabStyle
+{
+public:
+ virtual ~DockableTabStyle() {}
+ virtual QSize sizeForTab(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const;
+ virtual QRect closeButtonRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const;
+ virtual QRect closeIconRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const;
+ virtual void paintTab(const QWidget* widget, QStylePainter& p, const DockableTabInfo& info, int idx,
+ int count, int active, DockableTabInteractionState state, const QRect& rect) const;
+ virtual void paintBase(const QWidget* widget, QStylePainter& p, const QRect& rect,
+ const QRect& activeRect) const;
+ virtual DockableTabStyle* duplicate();
+};
+
+class BINARYNINJAUIAPI DefaultDockableTabStyle: public DockableTabStyle
+{
+ QStyleOptionTab styleForTab(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const;
+ int closeButtonSize(const QWidget* widget) const;
+
+public:
+ virtual QSize sizeForTab(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual QRect closeButtonRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual QRect closeIconRect(const QWidget* widget, const DockableTabInfo& info, int idx,
+ int count, int active) const override;
+ virtual void paintTab(const QWidget* widget, QStylePainter& p, const DockableTabInfo& info, int idx,
+ int count, int active, DockableTabInteractionState state, const QRect& rect) const override;
+ virtual void paintBase(const QWidget* widget, QStylePainter& p, const QRect& rect,
+ const QRect& activeRect) const override;
+ virtual DockableTabStyle* duplicate() override;
+};
+
class BINARYNINJAUIAPI DockableTabBar: public QAbstractScrollArea
{
Q_OBJECT
- struct TabInfo
- {
- QString title;
- QString toolTip;
- QRect tabRect, closeButtonRect, closeIconRect;
- bool modifiedIndicator;
- };
-
DockableTabCollection* m_collection;
- std::vector<TabInfo> m_tabs;
+ DockableTabStyle* m_style;
+ std::vector<DockableTabInfo> m_tabs;
int m_active = -1;
+ bool m_canCreateNewWindow = false;
+ bool m_canSplit = false;
bool m_mouseInside = false;
+ int m_tabHover = -1;
int m_closeButtonHover = -1;
int m_closeButtonDown = -1;
@@ -73,6 +126,7 @@ class BINARYNINJAUIAPI DockableTabBar: public QAbstractScrollArea
DockableTabBar* m_tabDragTarget = nullptr;
int m_tabDragWidth;
int m_tabDragTargetIndex = -1;
+ std::optional<Qt::Edge> m_tabDragSplitEdge;
bool m_tabDragNewWindow = false;
QRubberBand* m_tabDropIndicator = nullptr;
@@ -82,11 +136,7 @@ class BINARYNINJAUIAPI DockableTabBar: public QAbstractScrollArea
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);
@@ -99,6 +149,9 @@ public:
void setTabText(int idx, const QString& title);
void setTabToolTip(int idx, const QString& toolTip);
void setTabModifiedIndicator(int idx, bool indicator);
+ void setCanCloseTab(int idx, bool canClose);
+ void setCanCreateNewWindow(bool canCreate);
+ void setCanSplit(bool canSplit);
int count() const;
int currentIndex() const;
@@ -107,15 +160,22 @@ public:
QString tabText(int idx);
QString tabToolTip(int idx);
bool tabModifiedIndicator(int idx);
+ bool canCloseTab(int idx);
+ bool canCreateNewWindow();
+ bool canSplit();
void ensureCurrentTabVisible();
+ DockableTabStyle* tabStyle() const { return m_style; }
+ void setTabStyle(DockableTabStyle* style);
+
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);
+ void splitTab(int idx, Qt::Edge edge);
private Q_SLOTS:
void underMouseTimerEvent();
@@ -137,6 +197,9 @@ class BINARYNINJAUIAPI DockableTabBarWithCornerWidget: public QWidget
{
DockableTabBar* m_bar;
QHBoxLayout* m_barLayout;
+ Qt::Corner m_corner = Qt::TopRightCorner;
+ QWidget* m_cornerWidget = nullptr;
+ QWidget* m_cornerWidgetContainer = nullptr;
protected:
virtual void paintEvent(QPaintEvent* event) override;
@@ -145,6 +208,8 @@ public:
DockableTabBarWithCornerWidget(DockableTabBar* bar);
DockableTabBar* tabBar() const { return m_bar; }
void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner);
+ Qt::Corner corner() const { return m_corner; }
+ QWidget* cornerWidget() const { return m_cornerWidget; }
};
class BINARYNINJAUIAPI DockableTabWidget: public QWidget
@@ -157,7 +222,7 @@ class BINARYNINJAUIAPI DockableTabWidget: public QWidget
QStackedWidget* m_widgets;
void addReparentedTab(DockableTabWidget* source, int idx, QWidget* widget,
- const QString& title, const QString& toolTip);
+ const QString& title, const QString& toolTip, bool canClose);
public:
DockableTabWidget(DockableTabCollection* collection, DockableTabBar* bar = nullptr);
@@ -171,15 +236,28 @@ public:
QWidget* currentWidget();
QWidget* widget(int idx);
DockableTabBar* tabBar() const { return m_bar; }
+ QStackedWidget* container() const { return m_widgets; }
+ DockableTabCollection* collection() const { return m_collection; }
QString tabText(int idx);
bool tabModifiedIndicator(int idx);
+ bool canCloseTab(int idx);
+ bool canCreateNewWindow();
+ bool canSplit();
int indexOf(QWidget* widget);
void setCurrentIndex(int idx);
void setTabText(int idx, const QString& title);
void setTabModifiedIndicator(int idx, bool indicator);
+ void setCanCloseTab(int idx, bool canClose);
+ void setCanCreateNewWindow(bool canCreate);
+ void setCanSplit(bool canSplit);
void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner);
+ Qt::Corner corner() const;
+ QWidget* cornerWidget() const;
+
+ DockableTabStyle* tabStyle() const { return m_bar->tabStyle(); }
+ void setTabStyle(DockableTabStyle* style);
virtual QSize sizeHint() const override;
@@ -190,11 +268,68 @@ Q_SIGNALS:
void newWindowForTab(int idx, QRect rectHint);
void tabRemovedForReparent(int oldIdx, QWidget* widget, DockableTabWidget* target, int newIdx);
void tabAddedForReparent(int idx, DockableTabWidget* source);
+ void splitTab(int idx, Qt::Edge edge);
private Q_SLOTS:
void tabBarCurrentChanged(int idx);
void tabBarCloseRequested(int idx);
void tabBarTabMoved(int oldIdx, int newIdx);
void tabBarNewWindowForTab(int idx, QRect rectHint);
+ void tabBarSplitTab(int idx, Qt::Edge edge);
void reparentTab(int oldIdx, DockableTabWidget* target, int newIdx);
};
+
+class BINARYNINJAUIAPI SplitTabWidget: public QWidget
+{
+ Q_OBJECT
+
+ DockableTabWidget* m_tabs = nullptr;
+ QSplitter* m_splitter = nullptr;
+ SplitTabWidget* m_first = nullptr;
+ SplitTabWidget* m_second = nullptr;
+ QVBoxLayout* m_layout;
+
+ SplitTabWidget(DockableTabWidget* tabs);
+ SplitTabWidget(SplitTabWidget* first, SplitTabWidget* second, Qt::Orientation orientation);
+
+ void splitTabInternal(QWidget* widget, QString title, bool canClose, Qt::Edge edge);
+ void promoteChild(SplitTabWidget* child, SplitTabWidget* other);
+
+ void enumerateTabTree(const std::function<void(SplitTabWidget*, QWidget*, QString)>& func);
+ Json::Value savedLayoutObject() const;
+ void restoreLayoutObject(const Json::Value& layout);
+ void restoreLayoutObjectWithTabs(const Json::Value& layout,
+ std::map<QString, std::pair<DockableTabWidget*, QWidget*>>& tabWidgets);
+ DockableTabWidget* findFirstTabWidget();
+ void collapseEmptyTabs();
+
+public:
+ SplitTabWidget(DockableTabCollection* collection);
+
+ void addTab(QWidget* widget, const QString& title);
+ void setCanCloseTab(QWidget* widget, bool canClose);
+ void enumerateTabs(const std::function<void(QWidget*)>& func);
+ void selectWidget(QWidget* widget);
+ bool isWidgetVisible(QWidget* widget);
+
+ void setTabStyle(DockableTabStyle* style);
+
+ void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner);
+
+ QString savedLayoutString() const;
+ void restoreLayoutString(const QString& layout);
+
+Q_SIGNALS:
+ void tabClosed(QWidget* widget);
+ void currentChanged(QWidget* widget);
+ void layoutChanged();
+
+private Q_SLOTS:
+ void tabCloseRequested(int idx);
+ void currentTabChanged(int idx);
+ void splitTab(int idx, Qt::Edge edge);
+ void tabRemovedForReparent(int oldIdx, QWidget* widget, DockableTabWidget* target, int newIdx);
+ void childTabClosed(QWidget* widget);
+ void childCurrentChanged(QWidget* widget);
+ void childLayoutChanged();
+};
diff --git a/ui/uicontext.h b/ui/uicontext.h
index b0e2adde..de58a74b 100644
--- a/ui/uicontext.h
+++ b/ui/uicontext.h
@@ -20,6 +20,7 @@ class FileContext;
class ViewLocation;
class Sidebar;
class SidebarWidgetContainer;
+class GlobalArea;
struct SelectionInfoForXref;
/*!
@@ -271,6 +272,7 @@ public:
virtual UIActionHandler* contentActionHandler() = 0;
virtual Sidebar* sidebar() = 0;
+ virtual GlobalArea* globalArea() = 0;
void updateCrossReferences(ViewFrame* frame, View* view, const SelectionInfoForXref& selection);