How to create a custom plugin for BKChem

What is a plugin

From version 0.10.0-pre1 BKChem supports custom plugins, that is pieces of code that can be inserted into BKChem without need of modification of the program. These are typically written by users and provide some minor enhancements to the functionality of the program.

How does BKChem handle plugins

A BKChem plugin in general consists of two main parts. The first one is a short XML file that describes the plugin. If you don't know anything about XML, just don't worry. It is so easy that even I understand it :). The second part is a Python script that is the actual code of the plugin.

On startup BKChem searches in predefined directories (plugins directory in the BKChem installation directory and plugins directory in the users .bkchem directory - located either in the installation directory or the users HOME directory) and tries to read all XML files (having extension .xml) and find if they describe some plugin. If yes, it performs an action depending on the type of plugin.

At the time of writing of this document there are two distinct types of plugins that BKchem supports. The default (and probably most interesting one) is the script plugin. For such a plugin an entry into the menu is added and the plugin code is executed when the entry is selected.

The second type of plugin is mode plugin. Modes are used in BKChem to provide different types of actions to perform on the drawn objects. They are represented by the main toolbar of the program. There is an "edit mode", "draw mode", "rotate mode" etc. A plugin of this type adds a new mode to BKChem, enabling a new functionality. It is a little more complicated matter, because it implies a deeper knowledge of BKChem to write such a plugin, and therefore is not described in this material, yet.

Writing a script plugin - brief tutorial

Foreword

As mentioned above a plugin consist of two separate files - a XML document describing the plugin and a Python script containing the actual code. In case of script plugin, the only file that is read on BKChem startup is the XML file. If this file is successfully read, an entry is added to the Plugins menu. The Python script is not executed until requested by the user.

This fact has two major implications:

The XML specification file

The XML file describing the plugin is very short and simple as you can see on this example:

<?xml version="1.0" encoding="utf-8"?>

<plugin>

  <meta>
    <author email="beda@zirael.org">Beda Kosata</author>
    <description>
      Finds all aromatic bonds in the current drawing (paper) and marks them
      by setting their color to red.
    </description>
  </meta>

  <source>
    <file>red_aromates.py</file>
    <menu-text lang="en">Mark aromatic bonds</menu-text>
    <menu-text lang="cs">Označ aromatické vazby</menu-text>
  </source>
</plugin>

The only necessary part is content of the <source> tag, where the <file> tag says which file contains the Python script and the <menu-text> tag says how the entry in the "Plugins" menu for this plugin should be called.

The sample config file contains also a meta tag with information about the author and the function of the plugin. It is considered good habit to provide these information if you are going to distribute your plugins to other people. The description of the function of the plugin will be shown in the program status-bar when the cursor is over the plugin menu entry.

Both the <menu-text> and <description elements may have an optional lang attribute, that says in what language the text is. In this case more than one such elements may be present with different lang attributes. BKChem will choose the one that corresponds to the current language setting or uses the first one, if no matching language is found.

The Python script

The heart (or maybe brain) of the plugin is the Python script. Inside this script you can use any Python functions you want, there is no limit. WARNING: Because of this, the plugins present a possible threat to your computer. A plugin from an unknown source may delete all data from you harddisk, send your private emails to strange people or even drink all your beer and kick you out of your own house - you have been warned.

The way how the script communicates with BKChem is via a global variable App that represents the instance of the BKChem application. You may call its methods, retrieve its attributes etc.

Bellow is a sample script that find all aromatic bonds in all molecules present on the current paper and sets their color to dark red.

# at first we cancel all selections
App.paper.unselect_all()

# App.paper is the current paper
# App.paper.molecules is a list of all molecules on this paper
for mol in App.paper.molecules:

  # the aromaticity of bonds is not checked by default
  # therefore we must at first call the mark_aromatic_bonds() method
  mol.mark_aromatic_bonds()

  # then we can loop over all the bonds
  # and change the color of all the aromatic ones
  for b in mol.bonds:
    if b.aromatic:
      b.line_color = "#aa0000"
      b.redraw()
    

After the script finishes a new undo record is started automatically, therefore any changes by the plugin are undoable in one step.

Last word

There are some sample plugins distributed together with BKChem (in the directory plugins under the main BKChem directory (not the /bkchem/bkchem/plugins, but /bkchem/plugins). Some of them are pretty simple, some a little more complex. Feel free to use them for studying or as starting material for your own scripts.