|
|
<span style="background:#FFB6C1">**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.**</span>
|
|
|
|
|
|
## 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:
|
|
|
|
|
|
![images/plugin-dir-med.png](images/plugin-dir-med.png
|
|
|
"plugin-dir-med.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](http://www.python.org/dev/peps/pep-0008/).
|
|
|
- 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](Classes_Plugin "wikilink").
|
|
|
|
|
|
``` python numberLines
|
|
|
class Plugin(object):
|
|
|
def __init__(self, name=None, version=None):
|
|
|
if name is not None:
|
|
|
self.name = name
|
|
|
else:
|
|
|
self.name = 'Plugin'
|
|
|
if version is not None:
|
|
|
self.version = version
|
|
|
self.icon = None
|
|
|
self.config = PluginConfig(self.name)
|
|
|
self.weight = 0
|
|
|
# Set up logging
|
|
|
self.log = logging.getLogger(self.name)
|
|
|
|
|
|
def check_pre_conditions(self):
|
|
|
return True
|
|
|
|
|
|
def get_media_manager_item(self):
|
|
|
pass
|
|
|
|
|
|
def add_import_menu_item(self, import_menu):
|
|
|
pass
|
|
|
|
|
|
def add_export_menu_item(self, export_menu):
|
|
|
pass
|
|
|
|
|
|
def get_settings_tab(self):
|
|
|
pass
|
|
|
|
|
|
def add_to_menu(self, menubar):
|
|
|
pass
|
|
|
|
|
|
def handle_event(self, event):
|
|
|
pass
|
|
|
|
|
|
def about(self):
|
|
|
pass
|
|
|
|
|
|
def save(self, data):
|
|
|
pass
|
|
|
|
|
|
def load(self, string):
|
|
|
pass
|
|
|
|
|
|
def render(self, theme, screen=None):
|
|
|
pass
|
|
|
|
|
|
def initalise(self):
|
|
|
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.
|
|
|
|
|
|
``` python numberLines
|
|
|
import os
|
|
|
|
|
|
from openlp.core.lib import Plugin, MediaManagerItem
|
|
|
|
|
|
class HelloWorldPlugin(Plugin):
|
|
|
def __init__(self):
|
|
|
# Call the parent constructor
|
|
|
Plugin.__init__(self, 'HelloWorld', '1.9.0')
|
|
|
# Create the plugin icon
|
|
|
self.icon = QtGui.QIcon()
|
|
|
self.icon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(
|
|
|
os.path.join(os.path.asbpath(os.path.basename(__file__)),
|
|
|
'resources', 'images', 'helloworld.png'))), QtGui.QIcon.Normal,
|
|
|
QtGui.QIcon.Off)
|
|
|
|
|
|
def get_media_manager_item(self):
|
|
|
# Create the MediaManagerItem object
|
|
|
self.MediaManagerItem = MediaManagerItem(self.icon, 'Hello World')
|
|
|
# Add a toolbar
|
|
|
self.MediaManagerItem.addToolbar()
|
|
|
# Create button for the toolbar
|
|
|
self.MediaManagerItem.addToolbarButton('Hello World', 'Says, "Hello World"',
|
|
|
os.path.join(os.path.asbpath(os.path.basename(__file__)), 'resources',
|
|
|
'images', 'helloworld.png'), self.onHelloWorldClick, 'HelloWorldItem')
|
|
|
|
|
|
def onHelloWorldClick(self):
|
|
|
QtGui.QMessageBox.information(None, 'Hello World!',
|
|
|
'This is just a little message box to say, "Hello World!"',
|
|
|
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.
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
- - 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.
|
|
|
|
|
|
``` python numberLines
|
|
|
|
|
|
class HelloWorldTab(SettingsTab):
|
|
|
def __init__(self):
|
|
|
HelloWorldTab.__init__(self, u'Hello World')
|
|
|
|
|
|
def setupUi(self):
|
|
|
self.setObjectName(u'HelloWorldTab')
|
|
|
|
|
|
def retranslateUi(self):
|
|
|
pass
|
|
|
|
|
|
|
|
|
def load(self):
|
|
|
pass
|
|
|
|
|
|
def save(self):
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
[P](Development/Pages "wikilink")
|
|
|
[P](Category:Documentation "wikilink") |