7

So i'm trying to add a custom toolbar to IDA 6.4 using their PySide download and the IDAAPI. I've tried adding a toolbar by just creating one but since it doesn't have an exec_() method I can't get it on the screen and it looks like I need to be loading it into a window with something like

self.toolbar = self.addToolBar('var')

though in this case the "self" is a window which makes me think I need a reference to IDA's main window. Anyone know how i can get that reference?

2
  • not a solution, but just for completeness: in IDA 6.7 + they have significant improvements on this described here: hexblog.com/?p=886
    – w s
    Oct 28, 2015 at 12:12
  • yes I've seen that, but doesn't help me for 6.4, thank you though. I've gotten most of the functionality I need by just building a view that i can dock, not as nice as a toolbar but functional.
    – James
    Oct 28, 2015 at 12:14

1 Answer 1

5

New IDA 6.95 API

Perhaps because they saw this question, maybe because of user requests, version 6.95 was released with two IDAPython API functions for creating a menu and a toolbar: create_menu and create_toolbar so now these can be done trivially.

Old trick - Before 6.95

A hack I've been using is finding the application's main window manually and then adding a toolbar directly using QT. IDA only has one main window.

Adding a toolbar that way makes in completely recognizable by IDA as far as I can tell. You can tick it on and off, you can dock and un-dock it, changing to advanced mode automatically shows it as well. However, IDA won't let you add actions to it in IDA 6.7 and above (as described at hexblog.com/?p=886)

A sample code can look something like that:

 for widget in QtGui.qApp.topLevelWidgets():
     if type(widget) == QtGui.QMainWindow:
         mainWindow = widget
         toolbar = mainWindow.addToolBar("My toolbar")

         # and now for adding stuff to our toolbar
         toolbar.addSeparator()
         toolbar.addWidget(...)

Disclaimer: Keep in mind finding the main window this way if risky, undocumented and might not always work. IDA might not like that you're changing stuff underneath it. I do use it and it is working, but YMMV and UAYOR.

Two additional tips for making this hack functional:

  1. Since IDA's main window is not always visible when plugins are loaded, you might want to set a QTimer on finding the main window.
  2. Because its undocumented, i use more ways to find the main window. Using qApp.activeWindow() and/or qApp.focusWidget() and iterating over their .parent()s are good additional choices.

EDIT:

Here's a more complete example of how to hack a toolbar and a menu in from an IDA plugin, handling different loading modes and retying in case the IDA application is not fully set-up yet:

  def init(self):
    self.setup()

    return idaapi.PLUGIN_KEEP

  def setup(self):
    if not self.get_mainwindow():
      self.delay_setup()
      return

    # Add a toolbar like OP requested
    self.toolbar = self.get_mainwindow().addToolBar("My toolbar")
    self.toolbar.setIconSize(QtCore.QSize(16, 16))

    # Bonus: add a menue
    self.menu = QtGui.QMenu("My menu")
    self.get_mainwindow().menuWidget().addMenu(self.menu)

  def delay_setup(self):
    QtCore.QTimer.singleShot(1000, self.setup)

  def get_mainwindow(self):
    if self.mainwindow:
      return self.mainwindow

    app = QtGui.qApp
    widgets = [app.focusWidget(), app.activeWindow()] + app.topLevelWidgets()
    mainwidgets = filter(None, map(self.search_mainwindow, widgets))

    if mainwidgets:
      self.mainwindow = mainwidgets[0]

    return self.mainwindow

  def search_mainwindow(self, widget):
    while widget != None:
      if isinstance(widget, QtGui.QMainWindow):
        return widget
      widget = widget.parent()
    return None

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.