-
Notifications
You must be signed in to change notification settings - Fork 0
Notes on Building a Plugin
This document provides a few notes on building a plugin for ViTables. My goal was to add a widget to the workspace that would allow one to visualize an array as an image. The plugin was to take a (M,N) array and display an (M,N) image.
I started working off the development branch because that is where the current work is happening. This means the version is 2.2a1. The development branch uses setuptools
instead of distutils
which means the develop
target is an option. The catch is, the executable no longer dynamically recognizes plugins. The work around is to pass the entry points to the script using a setup script in the plugin directory.
...
setup(
...
install_requires = ["ViTables >2.1",],
dependency_links = [
"https://github.com/uvemas/ViTables@f6cb68227e10bf0658fd11b8daa56b76452b0341#egg=project-version"
],
entry_points = {
"vitables.plugins" :
"myplugin = myplugin:TargetClass"
}
...
)
Note that this also indicates that the development branch of ViTables needs to be installed. You might have to hand install that.
vitables.plugins
assumes that the class has the fields UID
which appears to be a unique id (eg. 'vitables.plugins.import_csv'
), NAME
which is often the plugin_name
, and a COMMENT
. I'm not quite sure why these don't go to the default.
The quickest hack to get the information page on the preferences dialog is to just import vitables.plugins.aboutpage.AboutPage
and mimic the about information from the helpAbout
method in the ImportCSV
class. In the docstring, there is a little more information about what is going on.
The direct way to write to the logging display is to call
vitables.utils.getGui().logger.write('the message')
However, this does not provide the information about where the message came from.
When the script is launched, the root
logger is setup with a file stream and the standard error is removed as a stream handler. In vitables.vtgui.VTGui.setup_logger_window
, the vitables
logger is grabbed and the logging window is set as the stream handler. The root logger is not handled. A work around is to add the GUI's logging window as a stream to handle my logging calls. Getting the logging to the file should Just Work™ because the file handler is added to the root logger. Getting the logging to the console might be trickier; however, I don't really care enough right now to figure it out. Add to that the fact that most users will simply double click which means no console any way.
So, to add a QMdiSubWindow
we get to have a fun run around. We can simply use to following snippet
workspace = vitables.utils.getGui().workspace
widget = AddWidget()
window = workspace.addSubWindow(widget)
where AddWidget()
creates whatever widget you want. The problem with this approach is that vitables
expects the QMdiSubWindow
object to have the attribute dbt_leaf
and getting that attached to the window and persist is a pain.
An alternative is to extend the QMdiSubWindow
and add it to the workspace
class MyWindow(QMdiSubWindow):
def __init__(self, parent, leaf):
super(MyWindow, self).__init__(parent)
widget = AddWidget()
self.setWidget(widget)
# These fields are required by ``vitables``
self.pindex = None
self.dbt_leaf = leaf
# Cleanly close the window.
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
class MyPlugin:
def __init__(self, parent=None):
super(MyPlugin, self).__init__(parent)
# Get the GUI and create an action
gui = vitables.utils.getGui()
action = QtGui.QAction("Do Stuff", gui)
action.triggered.connect(self.doit)
# Add it to the context menu in the tree
vitables.utils.addToLeafContextMenu(action)
# This properly cleans up when the window is closed.
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
def doit(self):
gui = vitables.utils.getGui()
dbt = gui.dbs_tree_model # Grab a reference to the tree
workspace = gui.workspace
for index in vitables.utils.getSelectedIndexes():
leaf = dbt.nodeFromIndex(index) # Convert to the tree leaf
window = MyPlugin(parent=workspace, leaf=leaf)
This get's the basics working. Setting pindex
to None
is modeled after vitables.vtwidgets.zoom_cell
.
The leaf must be a leaf in the tree on the left. To get this, we need to grab the index and query the tree to get the correct leaf. This leaf has an attribute node
that is the desired HDF5 array. This needs to be stored with the window.