summaryrefslogtreecommitdiff
path: root/python/examples/hellopane.py
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2021-11-18 13:52:25 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2022-01-10 15:25:18 -0700
commit7f6e54fdc8ff4a06fdcd3c510a37add337f04bac (patch)
tree60cce5955fcc05fc84f35f9662d49c7e0790dde1 /python/examples/hellopane.py
parentd9661f34eec6855d495a10eaafc2a8e2679756a7 (diff)
Refactor main area to use pane system
Diffstat (limited to 'python/examples/hellopane.py')
-rw-r--r--python/examples/hellopane.py125
1 files changed, 125 insertions, 0 deletions
diff --git a/python/examples/hellopane.py b/python/examples/hellopane.py
new file mode 100644
index 00000000..2b9fbe29
--- /dev/null
+++ b/python/examples/hellopane.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2015-2022 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 panes to Binary Ninja.
+# See .../api/ui/pane.h for interface details.
+
+from binaryninjaui import Pane, WidgetPane, UIActionHandler, UIActionHandler, UIAction, Menu, UIContext, UIContextNotification
+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
+
+# Class to handle UI context notifications. This will be used to listen for view and address
+# changes and update the pane accordingly.
+class HelloNotifications(UIContextNotification):
+ def __init__(self, widget):
+ UIContextNotification.__init__(self)
+ self.widget = widget
+
+ # __del__ will not be called because the widget owns a reference to this object. Use
+ # QWidget.destroyed event to know when to stop listening for notifications.
+ self.widget.destroyed.connect(self.destroyed)
+
+ UIContext.registerNotification(self)
+
+ def destroyed(self):
+ UIContext.unregisterNotification(self)
+
+ def OnViewChange(self, context, frame, type):
+ self.widget.updateState()
+
+ def OnAddressChange(self, context, frame, view, location):
+ self.widget.updateState()
+
+# Pane widget itself. This can be any QWidget.
+class HelloPaneWidget(QWidget, UIContextNotification):
+ def __init__(self, data):
+ global instance_id
+ QWidget.__init__(self)
+ 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("Hello Pane", 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 = data
+
+ # Populate initial state
+ self.updateState()
+
+ # Set up view and address change notifications
+ self.notifications = HelloNotifications(self)
+
+ def updateState(self):
+ # Get the currently active view frame for this group of panes. There can be
+ # multiple view frames in a single window, or the pane could be popped out
+ # into its own window. UIContext.currentViewFrameForWidget will determine
+ # the best view frame to use for context.
+ frame = UIContext.currentViewFrameForWidget(self)
+
+ # Update UI according to the active frame
+ if frame:
+ self.datatype.setText(frame.getCurrentView())
+ view = frame.getCurrentViewInterface()
+ self.data = view.getData()
+ self.offset.setText(hex(view.getCurrentOffset()))
+ else:
+ self.datatype.setText("None")
+ self.data = None
+
+ def contextMenuEvent(self, event):
+ self.m_contextMenuManager.show(self.m_menu, self.actionHandler)
+
+ @staticmethod
+ def createPane(context):
+ if context.context and context.binaryView:
+ widget = HelloPaneWidget(context.binaryView)
+ pane = WidgetPane(widget, "Hello")
+ context.context.openPane(pane)
+
+ @staticmethod
+ def canCreatePane(context):
+ return context.context and context.binaryView
+
+UIAction.registerAction("Hello Pane")
+UIActionHandler.globalActions().bindAction("Hello Pane", UIAction(HelloPaneWidget.createPane, HelloPaneWidget.canCreatePane))
+Menu.mainMenu("Tools").addAction("Hello Pane", "Hello")