Development:Plugin Developers Guide

From OpenLP
Jump to: navigation, search

This page is outdated and needs to be updated

Warning!!!!: A lot has changed in OpenLP and this guide is out dated. Whilst it may provide some value, don't expect any code based on the page to work. The examples on this page need updating before they will be functional.

Plugin Architecture

Directory Structure

All plugins need to have the same directory structure. The Songs plugin's directory structure is illustrated below as an example:

Plugin architecture.png

Each plugin has a directory within the openlp.org "plugins" directory. This directory is named the same as the plugin's name. Within the name directory there will be a nameplugin.py file which contains the NamePlugin class. This plugin class extends the builtin openlp.org Plugin class. This provides your plugin with a number of key methods to override.

Naming Conventions

  • All code should follow the Python syntax guidelines, known as PEP 8.
  • The recommended naming convention for plugins is the plural of the object it provides (e.g. Songs).
  • Plugin names should not contain spaces.

Base Plugin Class

The base Plugin class is shown below, with all the hooks that you need to provide if you want to make use of its functionality.

Note: This is a cut down version of the Plugin class.

 1 class Plugin(object):
 2     def __init__(self, name=None, version=None):
 3         if name is not None:
 4             self.name = name
 5         else:
 6             self.name = 'Plugin'
 7         if version is not None:
 8             self.version = version
 9         self.icon = None
10         self.config = PluginConfig(self.name)
11         self.weight = 0
12         # Set up logging
13         self.log = logging.getLogger(self.name)
14 
15     def check_pre_conditions(self):
16         return True
17 
18     def get_media_manager_item(self):
19         pass
20 
21     def add_import_menu_item(self, import_menu):
22         pass
23 
24     def add_export_menu_item(self, export_menu):
25         pass
26 
27     def get_settings_tab(self):
28         pass
29 
30     def add_to_menu(self, menubar):
31         pass
32 
33     def handle_event(self, event):
34         pass
35 
36     def about(self):
37         pass
38 
39     def save(self, data):
40         pass
41 
42     def load(self, string):
43         pass
44 
45     def render(self, theme, screen=None):
46         pass
47 
48     def initalise(self):
49         pass

Developing An Example Plugin

Starting The Plugin

So let's start by building a very basic plugin, one that will add an item to the media manager, which will have a toolbar, and one button on the toolbar that pops up a "Hello World" message (we had to get the "Hello World" in *somewhere* ;-) ).

  • First create a directory in the plugins directory. Let's call it helloworld.
  • Create a __init__.py file in that directory. This converts the directory into a Python module, so that openlp.org can load your plugin.
  • Create a file named helloworldplugin.py.

The Plugin Code

Next we'll need some code in that new plugin file. Copy and paste the following code into the new file. Don't forget to create yourself a little icon, and update the path to the icon to match your icon's path.

 1 import os
 2 
 3 from openlp.core.lib import Plugin, MediaManagerItem
 4 
 5 class HelloWorldPlugin(Plugin):
 6     def __init__(self):
 7         # Call the parent constructor
 8         Plugin.__init__(self, 'HelloWorld', '1.9.0')
 9         # Create the plugin icon
10         self.icon = QtGui.QIcon()
11         self.icon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(
12             os.path.join(os.path.asbpath(os.path.basename(__file__)),
13             'resources', 'images', 'helloworld.png'))), QtGui.QIcon.Normal,
14             QtGui.QIcon.Off)
15 
16     def get_media_manager_item(self):
17         # Create the MediaManagerItem object
18         self.MediaManagerItem = MediaManagerItem(self.icon, 'Hello World')
19         # Add a toolbar
20         self.MediaManagerItem.addToolbar()
21         # Create button for the toolbar
22         self.MediaManagerItem.addToolbarButton('Hello World', 'Says, "Hello World"',
23             os.path.join(os.path.asbpath(os.path.basename(__file__)), 'resources',
24             'images', 'helloworld.png'), self.onHelloWorldClick, 'HelloWorldItem')
25 
26     def onHelloWorldClick(self):
27         QtGui.QMessageBox.information(None, 'Hello World!',
28             'This is just a little message box to say, "Hello World!"',
29             QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok)

An Explanation

So how does the plugin work?

  • Import the os module for use with file paths in our plugin.
  • Import the Plugin classes, so that we can use them in our code.
  • Make our class descend from the Plugin class.
  • Create a constructor:
    • Call the Plugin class's constructor to set up some basic information.
    • Load an icon for our plugin into the plugin's icon property.
  • Implement the get_media_manager_item() hook:
    • Create an instance of the XXXManagerItem class.
  • Implement the get_settings_tab() hook:
    • Create an instance of the XXXTab class.
    • Add a toolbar to the item.
    • Add a button to the toolbar, with the following parameters:
      • Caption
      • Tooltip
      • Icon
      • Slot (a function to react to the triggered() signal/event)
      • Object name
  • Create the Slot with an applicable action (in our case, showing a "Hello World" dialog).

Plugin Hooks

Hooks are special Python methods that are executed at various points throughout openlp.org. The list below shows all of these hooks, when each of them is activated, and what each one of them is supposed to do.

about()

Show a dialog when the user clicks on the 'About' button in the plugin manager.

save(media_item)

A plugin's media item is passed to this function, which should return a ServiceItem object which can be written to the service file.

load(service_item)

A ServiceItem object from the service file is passed in. This function parses and sets up an instance of the plugin's media item for use within the plugin.

render(screen, service_item, theme)

Render the screenth screenful of the service_item (a ServiceItem object), using theme settings in theme.

What is screen? An object, a number, a canvas?

get_media_manager_item()

Construct a MediaManagerItem object with all the buttons and things you need, and return it for integration into openlp.org's Media Manager.

add_import_menu_item(import_menu)

Given the import menu item, add an item to the Import menu.

add_export_menu_item(export_menu)

Given the export menu item, add an item to the Export menu.

add_to_menu(menubar)

Add menu items to the menu, given the menubar.

handle_event(event)

Handle the event contained in the event object.

initialise()

Called by the plugin manager to setup any additional features on creation.

Configuration

Configuration File

Each plugin comes with a built-in self.config object, which reads and writes to a plugin-specific section of the openlp.org configuration file. On Linux, Mac OS X, and other Unix-like operating systems, this configuration file can be found in the following location: ~/.openlp/openlp.conf. On Windows, this file is found in: C:\Documents and Settings\username\Application Data\.openlp\openlp.conf.

For example:

[<pluginName>]

last dir = /home/<name>/somedirectory

This is location where the last file loaded into the plugin came from.

list count = 2

This is a count of how many files are to be loaded into the plugin's list

list item 1 = /home/<name>/somedirectory/somefile.xyz

The location and name of the file to be loaded into the plugin's list.

PluginUtls Class

A PluginUtils class can be added the the Plugin's definition to provide access to a number of utility methods to reduce code duplication. These methods will return empty lists or strings if the configuration tags have not been defined.

add_to_context_menu(self, base, icon, text, slot)

Defines a Context menu item with icon 'icon' and text 'text'. Which is connected to list 'base' and will trigger action 'slot' when selected.

add_to_context_separator(self, base)

Defines a Context separator item for the context menu

_load_display_list()

Reads the configuration data and returns a list of items to the added to the display list.

_save_display_list(self, displaylist)

Takes a display list 'displaylist' and saves the details in the configuration file allowing the list to be reloaded later.

_get_last_dir

Reads the configuration file to provide the last directory used by the plugin

_save_last_directory(self, filename)

Extracts the directory part of the filename and saves that in the configuration file

Plugin Dialogs

Media Items

Settings Tabs

The Settings dialog calls each plugin using the get_settings_tab method. The plugin is able to create a tab on the Settings Dialog by returning a class extending SettingsTab.

 1 class HelloWorldTab(SettingsTab):
 2     def __init__(self):
 3         HelloWorldTab.__init__(self, u'Hello World')
 4 
 5     def setupUi(self):
 6         self.setObjectName(u'HelloWorldTab')
 7 
 8     def retranslateUi(self):
 9         pass   
10 
11 
12     def load(self):
13         pass
14 
15     def save(self):
16         pass