forked from openlp/openlp
Comment changes
This commit is contained in:
commit
7e6ad29306
@ -31,42 +31,58 @@ class Plugin(object):
|
|||||||
Base class for openlp plugins to inherit from.
|
Base class for openlp plugins to inherit from.
|
||||||
|
|
||||||
Basic attributes are:
|
Basic attributes are:
|
||||||
* name
|
|
||||||
|
``name``
|
||||||
The name that should appear in the plugins list.
|
The name that should appear in the plugins list.
|
||||||
* version
|
|
||||||
|
``version``
|
||||||
The version number of this iteration of the plugin.
|
The version number of this iteration of the plugin.
|
||||||
* icon
|
|
||||||
|
``icon``
|
||||||
An instance of QIcon, which holds an icon for this plugin.
|
An instance of QIcon, which holds an icon for this plugin.
|
||||||
* config
|
|
||||||
|
``config``
|
||||||
An instance of PluginConfig, which allows plugins to read and write to
|
An instance of PluginConfig, which allows plugins to read and write to
|
||||||
openlp.org's configuration. This is pre-instantiated.
|
openlp.org's configuration. This is pre-instantiated.
|
||||||
* log
|
|
||||||
|
``log``
|
||||||
A log object used to log debugging messages. This is pre-instantiated.
|
A log object used to log debugging messages. This is pre-instantiated.
|
||||||
|
|
||||||
Hook functions:
|
Hook functions:
|
||||||
* check_pre_conditions()
|
|
||||||
|
``check_pre_conditions()``
|
||||||
Provides the Plugin with a handle to check if it can be loaded.
|
Provides the Plugin with a handle to check if it can be loaded.
|
||||||
* get_media_manager_item()
|
|
||||||
|
``get_media_manager_item()``
|
||||||
Returns an instance of MediaManagerItem to be used in the Media Manager.
|
Returns an instance of MediaManagerItem to be used in the Media Manager.
|
||||||
* add_import_menu_item(import_menu)
|
|
||||||
|
``add_import_menu_item(import_menu)``
|
||||||
Add an item to the Import menu.
|
Add an item to the Import menu.
|
||||||
* add_export_menu_item(export_menu)
|
|
||||||
|
``add_export_menu_item(export_menu)``
|
||||||
Add an item to the Export menu.
|
Add an item to the Export menu.
|
||||||
* get_settings_tab()
|
|
||||||
|
``get_settings_tab()``
|
||||||
Returns an instance of SettingsTabItem to be used in the Settings dialog.
|
Returns an instance of SettingsTabItem to be used in the Settings dialog.
|
||||||
* add_to_menu(menubar)
|
|
||||||
|
``add_to_menu(menubar)``
|
||||||
A method to add a menu item to anywhere in the menu, given the menu bar.
|
A method to add a menu item to anywhere in the menu, given the menu bar.
|
||||||
* handle_event(event)
|
|
||||||
|
``handle_event(event)``
|
||||||
A method use to handle events, given an Event object.
|
A method use to handle events, given an Event object.
|
||||||
* about()
|
|
||||||
|
``about()``
|
||||||
Used in the plugin manager, when a person clicks on the 'About' button.
|
Used in the plugin manager, when a person clicks on the 'About' button.
|
||||||
* save(data)
|
|
||||||
|
``save(data)``
|
||||||
A method to convert the plugin's data to a string to be stored in the
|
A method to convert the plugin's data to a string to be stored in the
|
||||||
Service file.
|
Service file.
|
||||||
* load(string)
|
|
||||||
|
``load(string)``
|
||||||
A method to convert the string from a Service file into the plugin's
|
A method to convert the string from a Service file into the plugin's
|
||||||
own data format.
|
own data format.
|
||||||
* render(theme, screen_number)
|
|
||||||
|
``render(theme, screen_number)``
|
||||||
A method used to render something to the screen, given the current theme
|
A method used to render something to the screen, given the current theme
|
||||||
and screen number.
|
and screen number.
|
||||||
"""
|
"""
|
||||||
@ -78,11 +94,20 @@ class Plugin(object):
|
|||||||
"""
|
"""
|
||||||
This is the constructor for the plugin object. This provides an easy
|
This is the constructor for the plugin object. This provides an easy
|
||||||
way for descendent plugins to populate common data. This method *must*
|
way for descendent plugins to populate common data. This method *must*
|
||||||
be overridden, like so:
|
be overridden, like so::
|
||||||
class MyPlugin(Plugin):
|
|
||||||
def __init__(self):
|
class MyPlugin(Plugin):
|
||||||
Plugin.__init(self, 'MyPlugin', '0.1')
|
def __init__(self):
|
||||||
...
|
Plugin.__init(self, u'MyPlugin', u'0.1')
|
||||||
|
|
||||||
|
``name``
|
||||||
|
Defaults to *None*. The name of the plugin.
|
||||||
|
|
||||||
|
``version``
|
||||||
|
Defaults to *None*. The version of the plugin.
|
||||||
|
|
||||||
|
``plugin_helpers``
|
||||||
|
Defaults to *None*. A list of helper objects.
|
||||||
"""
|
"""
|
||||||
if name is not None:
|
if name is not None:
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -107,50 +132,59 @@ class Plugin(object):
|
|||||||
def check_pre_conditions(self):
|
def check_pre_conditions(self):
|
||||||
"""
|
"""
|
||||||
Provides the Plugin with a handle to check if it can be loaded.
|
Provides the Plugin with a handle to check if it can be loaded.
|
||||||
|
|
||||||
Returns True or False.
|
Returns True or False.
|
||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_media_manager_item(self):
|
def get_media_manager_item(self):
|
||||||
"""
|
"""
|
||||||
Construct a MediaManagerItem object with all the buttons and things you
|
Construct a MediaManagerItem object with all the buttons and things
|
||||||
need, and return it for integration into openlp.org.
|
you need, and return it for integration into openlp.org.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add_import_menu_item(self, import_menu):
|
def add_import_menu_item(self, import_menu):
|
||||||
"""
|
"""
|
||||||
Create a menu item and add it to the "Import" menu.
|
Create a menu item and add it to the "Import" menu.
|
||||||
|
|
||||||
|
``import_menu``
|
||||||
|
The Import menu.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add_export_menu_item(self, export_menu):
|
def add_export_menu_item(self, export_menu):
|
||||||
"""
|
"""
|
||||||
Create a menu item and add it to the "Export" menu.
|
Create a menu item and add it to the "Export" menu.
|
||||||
|
|
||||||
|
``export_menu``
|
||||||
|
The Export menu
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_settings_tab(self):
|
def get_settings_tab(self):
|
||||||
"""
|
"""
|
||||||
Create a menu item and add it to the "Import" menu.
|
Create a tab for the settings window.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add_to_menu(self, menubar):
|
def add_to_menu(self, menubar):
|
||||||
"""
|
"""
|
||||||
Add menu items to the menu, given the menubar.
|
Add menu items to the menu, given the menubar.
|
||||||
|
|
||||||
|
``menubar``
|
||||||
|
The application's menu bar.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handle_event(self, event):
|
|
||||||
"""
|
|
||||||
Handle the event contained in the event object.
|
|
||||||
"""
|
|
||||||
def handle_event(self, event):
|
def handle_event(self, event):
|
||||||
"""
|
"""
|
||||||
Handle the event contained in the event object. If you want
|
Handle the event contained in the event object. If you want
|
||||||
to use this default behaviour, you must set self.dnd_id equal
|
to use this default behaviour, you must set self.dnd_id equal
|
||||||
to that sent by the dnd source - eg the MediaItem
|
to that sent by the dnd source - eg the MediaItem
|
||||||
|
|
||||||
|
``event``
|
||||||
|
An object describing the event.
|
||||||
"""
|
"""
|
||||||
# default behaviour - can be overridden if desired
|
# default behaviour - can be overridden if desired
|
||||||
log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload))
|
log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload))
|
||||||
@ -175,6 +209,9 @@ class Plugin(object):
|
|||||||
"""
|
"""
|
||||||
Service item data is passed to this function, which should return a
|
Service item data is passed to this function, which should return a
|
||||||
string which can be written to the service file.
|
string which can be written to the service file.
|
||||||
|
|
||||||
|
``data``
|
||||||
|
The data to be saved.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -182,12 +219,21 @@ class Plugin(object):
|
|||||||
"""
|
"""
|
||||||
A string from the service file is passed in. This function parses and
|
A string from the service file is passed in. This function parses and
|
||||||
sets up the internals of the plugin.
|
sets up the internals of the plugin.
|
||||||
|
|
||||||
|
``string``
|
||||||
|
The data to be loaded into the plugin.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def render(self, theme, screen=None):
|
def render(self, theme, screen=None):
|
||||||
"""
|
"""
|
||||||
Render the screenth screenful of data using theme settings in theme.
|
Render the screenth screenful of data using theme settings in theme.
|
||||||
|
|
||||||
|
``theme``
|
||||||
|
The theme to use when rendering.
|
||||||
|
|
||||||
|
``screen``
|
||||||
|
Defaults to *None*. The screen to render to.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -29,28 +29,50 @@ class PluginConfig(object):
|
|||||||
"""
|
"""
|
||||||
Initialise the plugin config object, setting the section name to the
|
Initialise the plugin config object, setting the section name to the
|
||||||
plugin name.
|
plugin name.
|
||||||
|
|
||||||
|
``plugin_name``
|
||||||
|
The name of the plugin to use as a section name.
|
||||||
"""
|
"""
|
||||||
self.section = plugin_name.lower()
|
self.section = plugin_name.lower()
|
||||||
|
|
||||||
def get_config(self, key, default=None):
|
def get_config(self, key, default=None):
|
||||||
"""
|
"""
|
||||||
Get a configuration value from the configuration registry.
|
Get a configuration value from the configuration registry.
|
||||||
|
|
||||||
|
``key``
|
||||||
|
The name of configuration to load.
|
||||||
|
|
||||||
|
``default``
|
||||||
|
Defaults to *None*. The default value to return if there is no
|
||||||
|
other value.
|
||||||
"""
|
"""
|
||||||
return ConfigHelper.get_config(self.section, key, default)
|
return ConfigHelper.get_config(self.section, key, default)
|
||||||
|
|
||||||
def delete_config(self, key):
|
def delete_config(self, key):
|
||||||
"""
|
"""
|
||||||
Delete a configuration value from the configuration registry.
|
Delete a configuration value from the configuration registry.
|
||||||
|
|
||||||
|
``key``
|
||||||
|
The name of the configuration to remove.
|
||||||
"""
|
"""
|
||||||
return ConfigHelper.delete_config(self.section, key)
|
return ConfigHelper.delete_config(self.section, key)
|
||||||
|
|
||||||
def set_config(self, key, value):
|
def set_config(self, key, value):
|
||||||
"""
|
"""
|
||||||
Set a configuration value in the configuration registry.
|
Set a configuration value in the configuration registry.
|
||||||
|
|
||||||
|
``key``
|
||||||
|
The name of the configuration to save.
|
||||||
|
|
||||||
|
``value``
|
||||||
|
The value of the configuration to save.
|
||||||
"""
|
"""
|
||||||
return ConfigHelper.set_config(self.section, key, value)
|
return ConfigHelper.set_config(self.section, key, value)
|
||||||
|
|
||||||
def get_data_path(self):
|
def get_data_path(self):
|
||||||
|
"""
|
||||||
|
Dynamically build the data file path for a plugin.
|
||||||
|
"""
|
||||||
#app_data = ConfigHelper.get_data_path()
|
#app_data = ConfigHelper.get_data_path()
|
||||||
app_data = ConfigHelper.get_data_path()
|
app_data = ConfigHelper.get_data_path()
|
||||||
safe_name = self.section.replace(u' ',u'-')
|
safe_name = self.section.replace(u' ',u'-')
|
||||||
@ -61,9 +83,21 @@ class PluginConfig(object):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
def set_data_path(self, path):
|
def set_data_path(self, path):
|
||||||
|
"""
|
||||||
|
Set the data file path.
|
||||||
|
|
||||||
|
``path``
|
||||||
|
The path to save.
|
||||||
|
"""
|
||||||
return self.set_config(u'data path', os.path.basename(path))
|
return self.set_config(u'data path', os.path.basename(path))
|
||||||
|
|
||||||
def get_files(self, suffix=None):
|
def get_files(self, suffix=None):
|
||||||
|
"""
|
||||||
|
Get a list of files from the data files path.
|
||||||
|
|
||||||
|
``suffix``
|
||||||
|
Defaults to *None*. The extension to search for.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
files = os.listdir(self.get_data_path())
|
files = os.listdir(self.get_data_path())
|
||||||
except:
|
except:
|
||||||
@ -86,7 +120,10 @@ class PluginConfig(object):
|
|||||||
|
|
||||||
def load_list(self, name):
|
def load_list(self, name):
|
||||||
"""
|
"""
|
||||||
Load a list from the config file
|
Load a list from the config file.
|
||||||
|
|
||||||
|
``name``
|
||||||
|
The name of the list.
|
||||||
"""
|
"""
|
||||||
list_count = self.get_config(u'%s count' % name)
|
list_count = self.get_config(u'%s count' % name)
|
||||||
if list_count is not None:
|
if list_count is not None:
|
||||||
@ -102,7 +139,13 @@ class PluginConfig(object):
|
|||||||
|
|
||||||
def set_list(self, name, list):
|
def set_list(self, name, list):
|
||||||
"""
|
"""
|
||||||
Save a list to the config file
|
Save a list to the config file.
|
||||||
|
|
||||||
|
``name``
|
||||||
|
The name of the list to save.
|
||||||
|
|
||||||
|
``list``
|
||||||
|
The list of values to save.
|
||||||
"""
|
"""
|
||||||
old_count = int(self.get_config(u'%s count' % name, int(0)))
|
old_count = int(self.get_config(u'%s count' % name, int(0)))
|
||||||
new_count = len(list)
|
new_count = len(list)
|
||||||
@ -116,7 +159,10 @@ class PluginConfig(object):
|
|||||||
|
|
||||||
def get_last_dir(self, num=None):
|
def get_last_dir(self, num=None):
|
||||||
"""
|
"""
|
||||||
Read the last directory used for plugin
|
Read the last directory used for plugin.
|
||||||
|
|
||||||
|
``num``
|
||||||
|
Defaults to *None*. A further qualifier.
|
||||||
"""
|
"""
|
||||||
if num is not None:
|
if num is not None:
|
||||||
name = u'last directory %d' % num
|
name = u'last directory %d' % num
|
||||||
@ -129,7 +175,10 @@ class PluginConfig(object):
|
|||||||
|
|
||||||
def set_last_dir(self, directory, num=None):
|
def set_last_dir(self, directory, num=None):
|
||||||
"""
|
"""
|
||||||
Save the last directory used for plugin
|
Save the last directory used for plugin.
|
||||||
|
|
||||||
|
``num``
|
||||||
|
Defaults to *None*. A further qualifier.
|
||||||
"""
|
"""
|
||||||
if num is not None:
|
if num is not None:
|
||||||
name = u'last directory %d' % num
|
name = u'last directory %d' % num
|
||||||
|
@ -34,8 +34,11 @@ class PluginManager(object):
|
|||||||
|
|
||||||
def __init__(self, dir):
|
def __init__(self, dir):
|
||||||
"""
|
"""
|
||||||
The constructor for the plugin manager.
|
The constructor for the plugin manager. Passes the controllers on to
|
||||||
Passes the controllers on to the plugins for them to interact with via their ServiceItems
|
the plugins for them to interact with via their ServiceItems.
|
||||||
|
|
||||||
|
``dir``
|
||||||
|
The directory to search for plugins.
|
||||||
"""
|
"""
|
||||||
log.info(u'Plugin manager initing')
|
log.info(u'Plugin manager initing')
|
||||||
if not dir in sys.path:
|
if not dir in sys.path:
|
||||||
@ -49,7 +52,16 @@ class PluginManager(object):
|
|||||||
|
|
||||||
def find_plugins(self, dir, plugin_helpers, eventmanager):
|
def find_plugins(self, dir, plugin_helpers, eventmanager):
|
||||||
"""
|
"""
|
||||||
Scan the directory dir for objects inheriting from openlp.plugin
|
Scan the directory dir for objects inheriting from ``openlp.plugin``.
|
||||||
|
|
||||||
|
``dir``
|
||||||
|
The directory to scan.
|
||||||
|
|
||||||
|
``plugin_helpers``
|
||||||
|
A list of helper objects to pass to the plugins.
|
||||||
|
|
||||||
|
``eventmanager``
|
||||||
|
The event manager to pass to the plugins.
|
||||||
"""
|
"""
|
||||||
self.plugin_helpers = plugin_helpers
|
self.plugin_helpers = plugin_helpers
|
||||||
startdepth = len(os.path.abspath(dir).split(os.sep))
|
startdepth = len(os.path.abspath(dir).split(os.sep))
|
||||||
@ -104,8 +116,8 @@ class PluginManager(object):
|
|||||||
|
|
||||||
def hook_media_manager(self, mediatoolbox):
|
def hook_media_manager(self, mediatoolbox):
|
||||||
"""
|
"""
|
||||||
Loop through all the plugins. If a plugin has a valid media manager item,
|
Loop through all the plugins. If a plugin has a valid media manager
|
||||||
add it to the media manager.
|
item, add it to the media manager.
|
||||||
|
|
||||||
``mediatoolbox``
|
``mediatoolbox``
|
||||||
The Media Manager itself.
|
The Media Manager itself.
|
||||||
@ -118,8 +130,11 @@ class PluginManager(object):
|
|||||||
|
|
||||||
def hook_settings_tabs(self, settingsform=None):
|
def hook_settings_tabs(self, settingsform=None):
|
||||||
"""
|
"""
|
||||||
Loop through all the plugins. If a plugin has a valid settings tab item,
|
Loop through all the plugins. If a plugin has a valid settings tab
|
||||||
add it to the settings tab.
|
item, add it to the settings tab.
|
||||||
|
|
||||||
|
``settingsform``
|
||||||
|
Defaults to *None*. The settings form to add tabs to.
|
||||||
"""
|
"""
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
settings_tab = plugin.get_settings_tab()
|
settings_tab = plugin.get_settings_tab()
|
||||||
@ -131,24 +146,30 @@ class PluginManager(object):
|
|||||||
|
|
||||||
def hook_import_menu(self, import_menu):
|
def hook_import_menu(self, import_menu):
|
||||||
"""
|
"""
|
||||||
Loop through all the plugins and give them an opportunity to add an item
|
Loop through all the plugins and give them an opportunity to add an
|
||||||
to the import menu.
|
item to the import menu.
|
||||||
|
|
||||||
|
``import_menu``
|
||||||
|
The Import menu.
|
||||||
"""
|
"""
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
plugin.add_import_menu_item(import_menu)
|
plugin.add_import_menu_item(import_menu)
|
||||||
|
|
||||||
def hook_export_menu(self, export_menu):
|
def hook_export_menu(self, export_menu):
|
||||||
"""
|
"""
|
||||||
Loop through all the plugins and give them an opportunity to add an item
|
Loop through all the plugins and give them an opportunity to add an
|
||||||
to the export menu.
|
item to the export menu.
|
||||||
|
|
||||||
|
``export_menu``
|
||||||
|
The Export menu.
|
||||||
"""
|
"""
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
plugin.add_export_menu_item(export_menu)
|
plugin.add_export_menu_item(export_menu)
|
||||||
|
|
||||||
def initialise_plugins(self):
|
def initialise_plugins(self):
|
||||||
"""
|
"""
|
||||||
Loop through all the plugins and give them an opportunity to add an item
|
Loop through all the plugins and give them an opportunity to
|
||||||
to the export menu.
|
initialise themselves.
|
||||||
"""
|
"""
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
plugin.initialise()
|
plugin.initialise()
|
||||||
|
@ -18,12 +18,12 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os, os.path
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
|
|
||||||
class Renderer:
|
class Renderer(object):
|
||||||
"""
|
"""
|
||||||
Genarates a pixmap image of a array of text. The Text is formatted to
|
Genarates a pixmap image of a array of text. The Text is formatted to
|
||||||
make sure it fits on the screen and if not extra frames a generated.
|
make sure it fits on the screen and if not extra frames a generated.
|
||||||
@ -33,6 +33,9 @@ class Renderer:
|
|||||||
log.info(u'Renderer Loaded')
|
log.info(u'Renderer Loaded')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Initialise the renderer.
|
||||||
|
"""
|
||||||
self._rect = None
|
self._rect = None
|
||||||
self._debug = 0
|
self._debug = 0
|
||||||
self._right_margin = 64 # the amount of right indent
|
self._right_margin = 64 # the amount of right indent
|
||||||
@ -47,11 +50,20 @@ class Renderer:
|
|||||||
self._bg_frame_small = None
|
self._bg_frame_small = None
|
||||||
|
|
||||||
def set_debug(self, debug):
|
def set_debug(self, debug):
|
||||||
|
"""
|
||||||
|
Set the debug mode of the renderer.
|
||||||
|
|
||||||
|
``debug``
|
||||||
|
The debug mode.
|
||||||
|
"""
|
||||||
self._debug=debug
|
self._debug=debug
|
||||||
|
|
||||||
def set_theme(self, theme):
|
def set_theme(self, theme):
|
||||||
"""
|
"""
|
||||||
External API to pass in the theme to be used
|
Set the theme to be used.
|
||||||
|
|
||||||
|
``theme``
|
||||||
|
The theme to be used.
|
||||||
"""
|
"""
|
||||||
log.debug(u'set theme')
|
log.debug(u'set theme')
|
||||||
self._theme = theme
|
self._theme = theme
|
||||||
@ -64,12 +76,21 @@ class Renderer:
|
|||||||
self.set_bg_image(theme.background_filename)
|
self.set_bg_image(theme.background_filename)
|
||||||
|
|
||||||
def set_bg_image(self, filename):
|
def set_bg_image(self, filename):
|
||||||
|
"""
|
||||||
|
Set a background image.
|
||||||
|
|
||||||
|
``filename``
|
||||||
|
The name of the image file.
|
||||||
|
"""
|
||||||
log.debug(u'set bg image %s', filename)
|
log.debug(u'set bg image %s', filename)
|
||||||
self._bg_image_filename = unicode(filename)
|
self._bg_image_filename = unicode(filename)
|
||||||
if self._frame is not None:
|
if self._frame is not None:
|
||||||
self.scale_bg_image()
|
self.scale_bg_image()
|
||||||
|
|
||||||
def scale_bg_image(self):
|
def scale_bg_image(self):
|
||||||
|
"""
|
||||||
|
Scale the background image to fit the screen.
|
||||||
|
"""
|
||||||
assert self._frame
|
assert self._frame
|
||||||
preview = QtGui.QImage(self._bg_image_filename)
|
preview = QtGui.QImage(self._bg_image_filename)
|
||||||
width = self._frame.width()
|
width = self._frame.width()
|
||||||
@ -89,7 +110,16 @@ class Renderer:
|
|||||||
|
|
||||||
def set_frame_dest(self, frame_width, frame_height, preview=False):
|
def set_frame_dest(self, frame_width, frame_height, preview=False):
|
||||||
"""
|
"""
|
||||||
External API to pass the frame size to be painted
|
Set the size of the slide.
|
||||||
|
|
||||||
|
``frame_width``
|
||||||
|
The width of the slide.
|
||||||
|
|
||||||
|
``frame_height``
|
||||||
|
The height of the slide.
|
||||||
|
|
||||||
|
``preview``
|
||||||
|
Defaults to *False*. Whether or not to generate a preview.
|
||||||
"""
|
"""
|
||||||
if preview == True:
|
if preview == True:
|
||||||
self._bg_frame = None
|
self._bg_frame = None
|
||||||
@ -103,7 +133,14 @@ class Renderer:
|
|||||||
|
|
||||||
def format_slide(self, words, footer):
|
def format_slide(self, words, footer):
|
||||||
"""
|
"""
|
||||||
External API to sort out the text to pe placed on the frame
|
Figure out how much text can appear on a slide, using the current
|
||||||
|
theme settings.
|
||||||
|
|
||||||
|
``words``
|
||||||
|
The words to be fitted on the slide.
|
||||||
|
|
||||||
|
``footer``
|
||||||
|
The footer of the slide.
|
||||||
"""
|
"""
|
||||||
log.debug(u'format_slide - Start')
|
log.debug(u'format_slide - Start')
|
||||||
verses = []
|
verses = []
|
||||||
@ -120,15 +157,28 @@ class Renderer:
|
|||||||
|
|
||||||
def set_text_rectangle(self, rect_main, rect_footer):
|
def set_text_rectangle(self, rect_main, rect_footer):
|
||||||
"""
|
"""
|
||||||
Sets the rectangle within which text should be rendered
|
Sets the rectangle within which text should be rendered.
|
||||||
|
|
||||||
|
``rect_main``
|
||||||
|
The main text block.
|
||||||
|
|
||||||
|
``rect_footer``
|
||||||
|
The footer text block.
|
||||||
"""
|
"""
|
||||||
self._rect = rect_main
|
self._rect = rect_main
|
||||||
self._rect_footer = rect_footer
|
self._rect_footer = rect_footer
|
||||||
|
|
||||||
def generate_frame_from_lines(self, lines, footer_lines=None):
|
def generate_frame_from_lines(self, lines, footer_lines=None):
|
||||||
"""
|
"""
|
||||||
Render a set of lines according to the theme, return bounding box
|
Render a set of lines according to the theme, and return the block
|
||||||
"""
|
dimensions.
|
||||||
|
|
||||||
|
``lines``
|
||||||
|
The lines to be rendered.
|
||||||
|
|
||||||
|
``footer_lines``
|
||||||
|
Defaults to *None*. The footer to render.
|
||||||
|
"""
|
||||||
log.debug(u'generate_frame_from_lines - Start')
|
log.debug(u'generate_frame_from_lines - Start')
|
||||||
#print "Render Lines ", lines
|
#print "Render Lines ", lines
|
||||||
bbox = self._render_lines_unaligned(lines, False)
|
bbox = self._render_lines_unaligned(lines, False)
|
||||||
@ -139,14 +189,15 @@ class Renderer:
|
|||||||
x, y = self._correctAlignment(self._rect, bbox)
|
x, y = self._correctAlignment(self._rect, bbox)
|
||||||
bbox = self._render_lines_unaligned(lines, False, (x, y), True)
|
bbox = self._render_lines_unaligned(lines, False, (x, y), True)
|
||||||
if footer_lines is not None:
|
if footer_lines is not None:
|
||||||
bbox = self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()), True )
|
bbox = self._render_lines_unaligned(footer_lines, True,
|
||||||
|
(self._rect_footer.left(), self._rect_footer.top()), True)
|
||||||
log.debug(u'generate_frame_from_lines - Finish')
|
log.debug(u'generate_frame_from_lines - Finish')
|
||||||
return self._frame
|
return self._frame
|
||||||
|
|
||||||
def _generate_background_frame(self):
|
def _generate_background_frame(self):
|
||||||
"""
|
"""
|
||||||
Generate a background frame to the same size as the frame to be used
|
Generate a background frame to the same size as the frame to be used.
|
||||||
Results cached for performance reasons.
|
Results are cached for performance reasons.
|
||||||
"""
|
"""
|
||||||
assert(self._theme)
|
assert(self._theme)
|
||||||
self._bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(),
|
self._bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(),
|
||||||
@ -196,11 +247,19 @@ class Renderer:
|
|||||||
|
|
||||||
def _split_set_of_lines(self, lines, footer):
|
def _split_set_of_lines(self, lines, footer):
|
||||||
"""
|
"""
|
||||||
Given a list of lines, decide how to split them best if they don't all fit on the screen
|
Given a list of lines, decide how to split them best if they don't all
|
||||||
- this is done by splitting at 1/2, 1/3 or 1/4 of the set
|
fit on the screen. This is done by splitting at 1/2, 1/3 or 1/4 of the
|
||||||
If it doesn't fit, even at this size, just split at each opportunity.
|
set. If it doesn't fit, even at this size, just split at each
|
||||||
We'll do this by getting the bounding box of each line, and then summing them appropriately
|
opportunity. We'll do this by getting the bounding box of each line,
|
||||||
Returns a list of [lists of lines], one set for each screenful
|
and then summing them appropriately.
|
||||||
|
|
||||||
|
Returns a list of [lists of lines], one set for each screenful.
|
||||||
|
|
||||||
|
``lines``
|
||||||
|
The lines of text to split.
|
||||||
|
|
||||||
|
``footer``
|
||||||
|
The footer text.
|
||||||
"""
|
"""
|
||||||
bboxes = []
|
bboxes = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@ -254,6 +313,15 @@ class Renderer:
|
|||||||
return retval
|
return retval
|
||||||
|
|
||||||
def _correctAlignment(self, rect, bbox):
|
def _correctAlignment(self, rect, bbox):
|
||||||
|
"""
|
||||||
|
Corrects the vertical alignment of text.
|
||||||
|
|
||||||
|
``rect``
|
||||||
|
The block dimentions.
|
||||||
|
|
||||||
|
``bbox``
|
||||||
|
Footer dimensions?
|
||||||
|
"""
|
||||||
x = rect.left()
|
x = rect.left()
|
||||||
if int(self._theme.display_verticalAlign) == 0:
|
if int(self._theme.display_verticalAlign) == 0:
|
||||||
# top align
|
# top align
|
||||||
@ -268,13 +336,26 @@ class Renderer:
|
|||||||
log.error(u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
|
log.error(u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
|
||||||
return x, y
|
return x, y
|
||||||
|
|
||||||
def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0), live=False):
|
def _render_lines_unaligned(self, lines, footer, tlcorner=(0, 0), live=False):
|
||||||
"""
|
"""
|
||||||
Given a list of lines to render, render each one in turn
|
Given a list of lines to render, render each one in turn (using the
|
||||||
(using the _render_single_line fn - which may result in going
|
``_render_single_line`` fn - which may result in going off the bottom).
|
||||||
off the bottom) They are expected to be pre-arranged to less
|
They are expected to be pre-arranged to less than a screenful (eg. by
|
||||||
than a screenful (eg. by using split_set_of_lines)
|
using split_set_of_lines).
|
||||||
Returns the bounding box of the text as QRect
|
|
||||||
|
Returns the bounding box of the text as QRect.
|
||||||
|
|
||||||
|
``lines``
|
||||||
|
The lines of text to render.
|
||||||
|
|
||||||
|
``footer``
|
||||||
|
The slide footer.
|
||||||
|
|
||||||
|
``tlcorner``
|
||||||
|
Defaults to *``(0, 0)``*. Co-ordinates of the top left corner.
|
||||||
|
|
||||||
|
``live``
|
||||||
|
Defaults to *False*. Whether or not this is a live screen.
|
||||||
"""
|
"""
|
||||||
x, y = tlcorner
|
x, y = tlcorner
|
||||||
brx = x
|
brx = x
|
||||||
@ -282,25 +363,37 @@ class Renderer:
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
# render after current bottom, but at original left edge
|
# render after current bottom, but at original left edge
|
||||||
# keep track of right edge to see which is biggest
|
# keep track of right edge to see which is biggest
|
||||||
(thisx, bry) = self._render_and_wrap_single_line(line, footer, (x , bry), live)
|
(thisx, bry) = self._render_and_wrap_single_line(line, footer, (x, bry), live)
|
||||||
if (thisx > brx):
|
if (thisx > brx):
|
||||||
brx = thisx
|
brx = thisx
|
||||||
retval = QtCore.QRect(x, y,brx-x, bry-y)
|
retval = QtCore.QRect(x, y, brx - x, bry - y)
|
||||||
if self._debug:
|
if self._debug:
|
||||||
painter = QtGui.QPainter()
|
painter = QtGui.QPainter()
|
||||||
painter.begin(self._frame)
|
painter.begin(self._frame)
|
||||||
painter.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
|
painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 255)))
|
||||||
painter.drawRect(retval)
|
painter.drawRect(retval)
|
||||||
painter.end()
|
painter.end()
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def _render_and_wrap_single_line(self, line, footer, tlcorner=(0,0), live=False):
|
def _render_and_wrap_single_line(self, line, footer, tlcorner=(0, 0), live=False):
|
||||||
"""
|
"""
|
||||||
Render a single line of words onto the DC, top left corner
|
Render a single line of words onto the DC, top left corner specified.
|
||||||
specified.
|
If the line is too wide for the context, it wraps, but right-aligns
|
||||||
If the line is too wide for the context, it wraps, but
|
the surplus words in the manner of song lyrics.
|
||||||
right-aligns the surplus words in the manner of song lyrics
|
|
||||||
Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
|
Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
|
||||||
|
|
||||||
|
``line``
|
||||||
|
Line of text to be rendered.
|
||||||
|
|
||||||
|
``footer``
|
||||||
|
The footer of the slide.
|
||||||
|
|
||||||
|
``tlcorner``
|
||||||
|
Defaults to *``(0, 0)``*. The top left corner.
|
||||||
|
|
||||||
|
``live``
|
||||||
|
Defaults to *False*. Whether or not this is a live screen.
|
||||||
"""
|
"""
|
||||||
x, y = tlcorner
|
x, y = tlcorner
|
||||||
# We draw the text to see how big it is and then iterate to make it fit
|
# We draw the text to see how big it is and then iterate to make it fit
|
||||||
@ -397,6 +490,9 @@ class Renderer:
|
|||||||
return brcorner
|
return brcorner
|
||||||
|
|
||||||
def _set_theme_font(self):
|
def _set_theme_font(self):
|
||||||
|
"""
|
||||||
|
Set the fonts from the current theme settings.
|
||||||
|
"""
|
||||||
self.footerFont = QtGui.QFont(self._theme.font_footer_name,
|
self.footerFont = QtGui.QFont(self._theme.font_footer_name,
|
||||||
int(self._theme.font_footer_proportion), # size
|
int(self._theme.font_footer_proportion), # size
|
||||||
QtGui.QFont.Normal, # weight
|
QtGui.QFont.Normal, # weight
|
||||||
@ -408,11 +504,26 @@ class Renderer:
|
|||||||
0)# italic
|
0)# italic
|
||||||
self.mainFont.setPixelSize(int(self._theme.font_main_proportion))
|
self.mainFont.setPixelSize(int(self._theme.font_main_proportion))
|
||||||
|
|
||||||
def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None):
|
def _get_extent_and_render(self, line, footer, tlcorner=(0, 0), draw=False, color=None):
|
||||||
"""
|
"""
|
||||||
Find bounding box of text - as render_single_line.
|
Find bounding box of text - as render_single_line. If draw is set,
|
||||||
If draw is set, actually draw the text to the current DC as well
|
actually draw the text to the current DC as well return width and
|
||||||
return width and height of text as a tuple (w,h)
|
height of text as a tuple (w, h).
|
||||||
|
|
||||||
|
``line``
|
||||||
|
The line of text to render.
|
||||||
|
|
||||||
|
``footer``
|
||||||
|
The footer text.
|
||||||
|
|
||||||
|
``tlcorner``
|
||||||
|
Defaults to *``(0, 0)``*. The top left corner co-ordinates.
|
||||||
|
|
||||||
|
``draw``
|
||||||
|
Defaults to *False*. Draw the text to the current surface.
|
||||||
|
|
||||||
|
``color``
|
||||||
|
Defaults to *None*. The colour to draw with.
|
||||||
"""
|
"""
|
||||||
# setup defaults
|
# setup defaults
|
||||||
painter = QtGui.QPainter()
|
painter = QtGui.QPainter()
|
||||||
@ -424,7 +535,7 @@ class Renderer:
|
|||||||
else:
|
else:
|
||||||
font = self.mainFont
|
font = self.mainFont
|
||||||
painter.setFont(font)
|
painter.setFont(font)
|
||||||
if color == None:
|
if color is None:
|
||||||
if footer:
|
if footer:
|
||||||
painter.setPen(QtGui.QColor(self._theme.font_footer_color))
|
painter.setPen(QtGui.QColor(self._theme.font_footer_color))
|
||||||
else:
|
else:
|
||||||
@ -443,7 +554,13 @@ class Renderer:
|
|||||||
|
|
||||||
def snoop_Image(self, image, image2=None):
|
def snoop_Image(self, image, image2=None):
|
||||||
"""
|
"""
|
||||||
Debugging method to allow images to be viewed
|
Debugging method to allow images to be viewed.
|
||||||
|
|
||||||
|
``image``
|
||||||
|
An image to save to disk.
|
||||||
|
|
||||||
|
``image2``
|
||||||
|
Defaults to *None*. Another image to save to disk.
|
||||||
"""
|
"""
|
||||||
im = image.toImage()
|
im = image.toImage()
|
||||||
im.save(u'renderer.png', u'png')
|
im.save(u'renderer.png', u'png')
|
||||||
|
@ -18,26 +18,37 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os, os.path
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
|
||||||
from renderer import Renderer
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import linecache
|
import linecache
|
||||||
|
|
||||||
class RenderManager:
|
from PyQt4 import QtGui, QtCore
|
||||||
|
|
||||||
|
from renderer import Renderer
|
||||||
|
|
||||||
|
class RenderManager(object):
|
||||||
"""
|
"""
|
||||||
Class to pull all Renderer interactions into one place.
|
Class to pull all Renderer interactions into one place. The plugins will
|
||||||
The plugins will call helper methods to do the rendering but
|
call helper methods to do the rendering but this class will provide
|
||||||
this class will provide display defense code.
|
display defense code.
|
||||||
"""
|
"""
|
||||||
global log
|
global log
|
||||||
log=logging.getLogger(u'RenderManager')
|
log=logging.getLogger(u'RenderManager')
|
||||||
log.info(u'RenderManager Loaded')
|
log.info(u'RenderManager Loaded')
|
||||||
|
|
||||||
def __init__(self, theme_manager, screen_list, screen_number=0):
|
def __init__(self, theme_manager, screen_list, screen_number=0):
|
||||||
|
"""
|
||||||
|
Initialise the render manager.
|
||||||
|
|
||||||
|
``theme_manager``
|
||||||
|
The ThemeManager instance, used to get the current theme details.
|
||||||
|
|
||||||
|
``screen_list``
|
||||||
|
The list of screens available.
|
||||||
|
|
||||||
|
``screen_number``
|
||||||
|
Defaults to *0*. The index of the output/display screen.
|
||||||
|
"""
|
||||||
log.debug(u'Initilisation started')
|
log.debug(u'Initilisation started')
|
||||||
self.screen_list = screen_list
|
self.screen_list = screen_list
|
||||||
self.theme_manager = theme_manager
|
self.theme_manager = theme_manager
|
||||||
@ -52,21 +63,46 @@ class RenderManager:
|
|||||||
def update_display(self, screen_number):
|
def update_display(self, screen_number):
|
||||||
"""
|
"""
|
||||||
Updates the render manager's information about the current screen.
|
Updates the render manager's information about the current screen.
|
||||||
|
|
||||||
|
``screen_number``
|
||||||
|
The updated index of the output/display screen.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Update Display')
|
log.debug(u'Update Display')
|
||||||
if self.current_display != screen_number:
|
if self.current_display != screen_number:
|
||||||
self.current_display = screen_number
|
self.current_display = screen_number
|
||||||
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
||||||
|
|
||||||
def set_global_theme(self, global_theme, global_style = u'Global'):
|
def set_global_theme(self, global_theme, global_style=u'Global'):
|
||||||
|
"""
|
||||||
|
Set the global-level theme and the theme level.
|
||||||
|
|
||||||
|
``global_theme``
|
||||||
|
The global-level theme to be set.
|
||||||
|
|
||||||
|
``global_style``
|
||||||
|
Defaults to *"Global"*. The theme level, can be "Global",
|
||||||
|
"Service" or "Song".
|
||||||
|
"""
|
||||||
self.global_theme = global_theme
|
self.global_theme = global_theme
|
||||||
self.global_style = global_style
|
self.global_style = global_style
|
||||||
|
|
||||||
def set_service_theme(self, service_theme):
|
def set_service_theme(self, service_theme):
|
||||||
|
"""
|
||||||
|
Set the service-level theme.
|
||||||
|
|
||||||
|
``service_theme``
|
||||||
|
The service-level theme to be set.
|
||||||
|
"""
|
||||||
self.service_theme = service_theme
|
self.service_theme = service_theme
|
||||||
|
|
||||||
def set_override_theme(self, theme):
|
def set_override_theme(self, theme):
|
||||||
log.debug(u'set override theme to %s', theme)
|
"""
|
||||||
|
Set the appropriate theme depending on the theme level.
|
||||||
|
|
||||||
|
``theme``
|
||||||
|
The name of the song-level theme.
|
||||||
|
"""
|
||||||
|
log.debug(u'set override theme to %s', theme)
|
||||||
if self.global_style == u'Global':
|
if self.global_style == u'Global':
|
||||||
self.theme = self.global_theme
|
self.theme = self.global_theme
|
||||||
elif self.global_style == u'Service':
|
elif self.global_style == u'Service':
|
||||||
@ -84,7 +120,7 @@ class RenderManager:
|
|||||||
self.theme = self.service_theme
|
self.theme = self.service_theme
|
||||||
else:
|
else:
|
||||||
self.theme = self.global_theme
|
self.theme = self.global_theme
|
||||||
if self.theme is not self.renderer.theme_name:
|
if self.theme != self.renderer.theme_name:
|
||||||
log.debug(u'theme is now %s', self.theme)
|
log.debug(u'theme is now %s', self.theme)
|
||||||
self.themedata = self.theme_manager.getThemeData(self.theme)
|
self.themedata = self.theme_manager.getThemeData(self.theme)
|
||||||
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
||||||
@ -92,7 +128,13 @@ class RenderManager:
|
|||||||
self.build_text_rectangle(self.themedata)
|
self.build_text_rectangle(self.themedata)
|
||||||
|
|
||||||
def build_text_rectangle(self, theme):
|
def build_text_rectangle(self, theme):
|
||||||
log.debug(u'build_text_rectangle ')
|
"""
|
||||||
|
Builds a text block using the settings in ``theme``.
|
||||||
|
|
||||||
|
``theme``
|
||||||
|
The theme to build a text block for.
|
||||||
|
"""
|
||||||
|
log.debug(u'build_text_rectangle')
|
||||||
main_rect = None
|
main_rect = None
|
||||||
footer_rect = None
|
footer_rect = None
|
||||||
if theme.font_main_override == False:
|
if theme.font_main_override == False:
|
||||||
@ -108,31 +150,52 @@ class RenderManager:
|
|||||||
self.renderer.set_text_rectangle(main_rect,footer_rect)
|
self.renderer.set_text_rectangle(main_rect,footer_rect)
|
||||||
|
|
||||||
def generate_preview(self, themedata):
|
def generate_preview(self, themedata):
|
||||||
|
"""
|
||||||
|
Generate a preview of a theme.
|
||||||
|
|
||||||
|
``themedata``
|
||||||
|
The theme to generated a preview for.
|
||||||
|
"""
|
||||||
log.debug(u'generate preview')
|
log.debug(u'generate preview')
|
||||||
self.calculate_default(QtCore.QSize(1024, 768))
|
self.calculate_default(QtCore.QSize(1024, 768))
|
||||||
self.renderer.set_theme(themedata)
|
self.renderer.set_theme(themedata)
|
||||||
self.build_text_rectangle(themedata)
|
self.build_text_rectangle(themedata)
|
||||||
self.renderer.set_frame_dest(self.width, self.height, True)
|
self.renderer.set_frame_dest(self.width, self.height, True)
|
||||||
lines = []
|
verse = []
|
||||||
lines.append(u'Amazing Grace!')
|
verse.append(u'Amazing Grace!')
|
||||||
lines.append(u'How sweet the sound')
|
verse.append(u'How sweet the sound')
|
||||||
lines.append(u'To save a wretch like me;')
|
verse.append(u'To save a wretch like me;')
|
||||||
lines.append(u'I once was lost but now am found,')
|
verse.append(u'I once was lost but now am found,')
|
||||||
lines.append(u'Was blind, but now I see.')
|
verse.append(u'Was blind, but now I see.')
|
||||||
lines1 = []
|
footer = []
|
||||||
lines1.append(u'Amazing Grace (John Newton)' )
|
footer.append(u'Amazing Grace (John Newton)' )
|
||||||
lines1.append(u'Public Domain')
|
footer.append(u'Public Domain')
|
||||||
lines1.append(u'CCLI xxx')
|
footer.append(u'CCLI xxx')
|
||||||
return self.renderer.generate_frame_from_lines(lines, lines1)
|
return self.renderer.generate_frame_from_lines(verse, footer)
|
||||||
|
|
||||||
def format_slide(self, words):
|
def format_slide(self, words):
|
||||||
|
"""
|
||||||
|
Calculate how much text can fid on a slide.
|
||||||
|
|
||||||
|
``words``
|
||||||
|
The words to go on the slides.
|
||||||
|
"""
|
||||||
log.debug(u'format slide')
|
log.debug(u'format slide')
|
||||||
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
||||||
self.build_text_rectangle(self.themedata)
|
self.build_text_rectangle(self.themedata)
|
||||||
self.renderer.set_frame_dest(self.width, self.height)
|
self.renderer.set_frame_dest(self.width, self.height)
|
||||||
return self.renderer.format_slide(words, False)
|
return self.renderer.format_slide(words, False)
|
||||||
|
|
||||||
def generate_slide(self,main_text, footer_text):
|
def generate_slide(self, main_text, footer_text):
|
||||||
|
"""
|
||||||
|
Generate the actual slide image.
|
||||||
|
|
||||||
|
``main_text``
|
||||||
|
The text for the main area of the slide.
|
||||||
|
|
||||||
|
``footer_text``
|
||||||
|
The text for the slide footer.
|
||||||
|
"""
|
||||||
log.debug(u'generate slide')
|
log.debug(u'generate slide')
|
||||||
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
self.calculate_default(self.screen_list[self.current_display][u'size'])
|
||||||
self.build_text_rectangle(self.themedata)
|
self.build_text_rectangle(self.themedata)
|
||||||
@ -140,6 +203,12 @@ class RenderManager:
|
|||||||
return self.renderer.generate_frame_from_lines(main_text, footer_text)
|
return self.renderer.generate_frame_from_lines(main_text, footer_text)
|
||||||
|
|
||||||
def resize_image(self, image):
|
def resize_image(self, image):
|
||||||
|
"""
|
||||||
|
Resize an image to fit on the current screen.
|
||||||
|
|
||||||
|
``image``
|
||||||
|
The image to resize.
|
||||||
|
"""
|
||||||
preview = QtGui.QImage(image)
|
preview = QtGui.QImage(image)
|
||||||
w = self.width
|
w = self.width
|
||||||
h = self.height
|
h = self.height
|
||||||
@ -154,13 +223,19 @@ class RenderManager:
|
|||||||
return newImage
|
return newImage
|
||||||
|
|
||||||
def calculate_default(self, screen):
|
def calculate_default(self, screen):
|
||||||
log.debug(u'calculate default %s' , screen)
|
"""
|
||||||
|
Calculate the default dimentions of the screen.
|
||||||
|
|
||||||
|
``screen``
|
||||||
|
The QWidget instance of the screen.
|
||||||
|
"""
|
||||||
|
log.debug(u'calculate default %s', screen)
|
||||||
if self.current_display == 0:
|
if self.current_display == 0:
|
||||||
self.width = 1024
|
self.width = 1024
|
||||||
self.height = 768
|
self.height = 768
|
||||||
else:
|
else:
|
||||||
self.width = screen.width()
|
self.width = screen.width()
|
||||||
self.height = screen.height()
|
self.height = screen.height()
|
||||||
log.debug(u'calculate default %d,%d' , self.width, self.height)
|
log.debug(u'calculate default %d, %d', self.width, self.height)
|
||||||
# 90% is start of footer
|
# 90% is start of footer
|
||||||
self.footer_start = int(self.height * 0.90)
|
self.footer_start = int(self.height * 0.90)
|
||||||
|
@ -20,10 +20,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from openlp.core.lib import buildIcon
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
class ServiceItem():
|
from openlp.core.lib import buildIcon
|
||||||
|
|
||||||
|
class ServiceItem(object):
|
||||||
"""
|
"""
|
||||||
The service item is a base class for the plugins to use to interact with
|
The service item is a base class for the plugins to use to interact with
|
||||||
the service manager, the slide controller, and the projection screen
|
the service manager, the slide controller, and the projection screen
|
||||||
@ -35,7 +37,10 @@ class ServiceItem():
|
|||||||
|
|
||||||
def __init__(self, hostplugin=None):
|
def __init__(self, hostplugin=None):
|
||||||
"""
|
"""
|
||||||
Init Method
|
Set up the service item.
|
||||||
|
|
||||||
|
``hostplugin``
|
||||||
|
The plugin that this service item belongs to.
|
||||||
"""
|
"""
|
||||||
self.plugin = hostplugin
|
self.plugin = hostplugin
|
||||||
if hostplugin is not None:
|
if hostplugin is not None:
|
||||||
@ -56,6 +61,14 @@ class ServiceItem():
|
|||||||
self.service_frames = []
|
self.service_frames = []
|
||||||
|
|
||||||
def addIcon(self, icon):
|
def addIcon(self, icon):
|
||||||
|
"""
|
||||||
|
Add an icon to the service item. This is used when displaying the
|
||||||
|
service item in the service manager.
|
||||||
|
|
||||||
|
``icon``
|
||||||
|
An instance of QIcon or a string to an icon in the resource or on
|
||||||
|
disk.
|
||||||
|
"""
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.iconic_representation = buildIcon(icon)
|
self.iconic_representation = buildIcon(icon)
|
||||||
|
|
||||||
@ -89,27 +102,63 @@ class ServiceItem():
|
|||||||
else:
|
else:
|
||||||
log.error(u'Invalid value renderer :%s' % self.service_item_type)
|
log.error(u'Invalid value renderer :%s' % self.service_item_type)
|
||||||
|
|
||||||
def add_from_image(self, path, frame_title, image):
|
def add_from_image(self, path, frame_title, image):
|
||||||
|
"""
|
||||||
|
Add an image slide to the service item.
|
||||||
|
|
||||||
|
``path``
|
||||||
|
The directory in which the image file is located.
|
||||||
|
|
||||||
|
``frame_title``
|
||||||
|
A title for the slide in the service item.
|
||||||
|
|
||||||
|
``image``
|
||||||
|
The actual image file name.
|
||||||
|
"""
|
||||||
self.service_item_type = u'image'
|
self.service_item_type = u'image'
|
||||||
self.service_item_path = path
|
self.service_item_path = path
|
||||||
self.service_frames.append({u'title': frame_title, u'image': image})
|
self.service_frames.append({u'title': frame_title, u'image': image})
|
||||||
|
|
||||||
def add_from_text(self, frame_title, raw_slide):
|
def add_from_text(self, frame_title, raw_slide):
|
||||||
|
"""
|
||||||
|
Add a text slide to the service item.
|
||||||
|
|
||||||
|
``frame_title``
|
||||||
|
The title of the slide in the service item.
|
||||||
|
|
||||||
|
``raw_slide``
|
||||||
|
The raw text of the slide.
|
||||||
|
"""
|
||||||
self.service_item_type = u'text'
|
self.service_item_type = u'text'
|
||||||
frame_title = frame_title.split(u'\n')[0]
|
frame_title = frame_title.split(u'\n')[0]
|
||||||
self.service_frames.append({u'title': frame_title, u'raw_slide': raw_slide})
|
self.service_frames.append({u'title': frame_title, u'raw_slide': raw_slide})
|
||||||
|
|
||||||
def add_from_command(self, frame_title, command):
|
def add_from_command(self, frame_title, command):
|
||||||
|
"""
|
||||||
|
Add a slide from a command.
|
||||||
|
|
||||||
|
``frame_title``
|
||||||
|
The title of the slide in the service item.
|
||||||
|
|
||||||
|
``command``
|
||||||
|
The command of/for the slide.
|
||||||
|
"""
|
||||||
self.service_item_type = u'command'
|
self.service_item_type = u'command'
|
||||||
self.service_frames.append({u'title': frame_title, u'command': command})
|
self.service_frames.append({u'title': frame_title, u'command': command})
|
||||||
|
|
||||||
def get_oos_repr(self):
|
def get_oos_repr(self):
|
||||||
"""
|
"""
|
||||||
This method returns some text which can be saved into the OOS
|
This method returns some text which can be saved into the OOS
|
||||||
file to represent this item
|
file to represent this item.
|
||||||
"""
|
"""
|
||||||
oos_header = {u'plugin': self.shortname,u'theme':self.theme, u'title':self.title,
|
oos_header = {
|
||||||
u'icon':self.icon, u'footer':self.raw_footer, u'type':self.service_item_type}
|
u'plugin': self.shortname,
|
||||||
|
u'theme':self.theme,
|
||||||
|
u'title':self.title,
|
||||||
|
u'icon':self.icon,
|
||||||
|
u'footer':self.raw_footer,
|
||||||
|
u'type':self.service_item_type
|
||||||
|
}
|
||||||
oos_data = []
|
oos_data = []
|
||||||
if self.service_item_type == u'text':
|
if self.service_item_type == u'text':
|
||||||
for slide in self.service_frames:
|
for slide in self.service_frames:
|
||||||
@ -124,8 +173,14 @@ class ServiceItem():
|
|||||||
|
|
||||||
def set_from_oos(self, serviceitem, path=None):
|
def set_from_oos(self, serviceitem, path=None):
|
||||||
"""
|
"""
|
||||||
This method takes some oos list (passed from the ServiceManager)
|
This method takes a service item from a saved service file (passed
|
||||||
and extracts the data actually required
|
from the ServiceManager) and extracts the data actually required.
|
||||||
|
|
||||||
|
``serviceitem``
|
||||||
|
The item to extract data from.
|
||||||
|
|
||||||
|
``path``
|
||||||
|
Defaults to *None*. Any path data, usually for images.
|
||||||
"""
|
"""
|
||||||
#print "sfs", serviceitem
|
#print "sfs", serviceitem
|
||||||
header = serviceitem[u'serviceitem'][u'header']
|
header = serviceitem[u'serviceitem'][u'header']
|
||||||
|
@ -23,11 +23,20 @@ from openlp.core.lib import PluginConfig
|
|||||||
|
|
||||||
class SettingsTab(QtGui.QWidget):
|
class SettingsTab(QtGui.QWidget):
|
||||||
"""
|
"""
|
||||||
SettingsTab is a helper widget for plugins to define Tabs for the settings dialog.
|
SettingsTab is a helper widget for plugins to define Tabs for the settings
|
||||||
|
dialog.
|
||||||
"""
|
"""
|
||||||
def __init__(self, title=None, section=None):
|
def __init__(self, title=None, section=None):
|
||||||
"""
|
"""
|
||||||
Constructor to create the Steetings tab item.
|
Constructor to create the Settings tab item.
|
||||||
|
|
||||||
|
``title``
|
||||||
|
Defaults to *None*. The title of the tab, which is usually
|
||||||
|
displayed on the tab.
|
||||||
|
|
||||||
|
``section``
|
||||||
|
Defaults to *None*. This is the section in the configuration file
|
||||||
|
to write to when the ``save`` method is called.
|
||||||
"""
|
"""
|
||||||
QtGui.QWidget.__init__(self)
|
QtGui.QWidget.__init__(self)
|
||||||
self.tabTitle = title
|
self.tabTitle = title
|
||||||
@ -43,6 +52,9 @@ class SettingsTab(QtGui.QWidget):
|
|||||||
def setTitle(self, title):
|
def setTitle(self, title):
|
||||||
"""
|
"""
|
||||||
Set the title of the tab.
|
Set the title of the tab.
|
||||||
|
|
||||||
|
``title``
|
||||||
|
The title of the tab, which is usually displayed on the tab.
|
||||||
"""
|
"""
|
||||||
self.tabTitle = title
|
self.tabTitle = title
|
||||||
|
|
||||||
|
@ -30,21 +30,34 @@ from xml.etree.ElementTree import ElementTree, XML, dump
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from xml.dom.minidom import Document
|
from xml.dom.minidom import Document
|
||||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||||
|
|
||||||
class SongXMLBuilder():
|
class SongXMLBuilder():
|
||||||
|
"""
|
||||||
|
This class builds the XML used to describe songs.
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Set up the song builder.
|
||||||
|
"""
|
||||||
# Create the minidom document
|
# Create the minidom document
|
||||||
self.song_xml = Document()
|
self.song_xml = Document()
|
||||||
|
|
||||||
def new_document(self):
|
def new_document(self):
|
||||||
|
"""
|
||||||
|
Create a new song XML document.
|
||||||
|
"""
|
||||||
# Create the <song> base element
|
# Create the <song> base element
|
||||||
self.song = self.song_xml.createElement(u'song')
|
self.song = self.song_xml.createElement(u'song')
|
||||||
self.song_xml.appendChild(self.song)
|
self.song_xml.appendChild(self.song)
|
||||||
self.song.setAttribute(u'version', u'1.0')
|
self.song.setAttribute(u'version', u'1.0')
|
||||||
|
|
||||||
def add_lyrics_to_song(self):
|
def add_lyrics_to_song(self):
|
||||||
|
"""
|
||||||
|
Set up and add a ``<lyrics>`` tag which contains the lyrics of the
|
||||||
|
song.
|
||||||
|
"""
|
||||||
# Create the main <lyrics> element
|
# Create the main <lyrics> element
|
||||||
self.lyrics = self.song_xml.createElement(u'lyrics')
|
self.lyrics = self.song_xml.createElement(u'lyrics')
|
||||||
self.lyrics.setAttribute(u'language', u'en')
|
self.lyrics.setAttribute(u'language', u'en')
|
||||||
@ -52,50 +65,72 @@ class SongXMLBuilder():
|
|||||||
|
|
||||||
def add_verse_to_lyrics(self, type, number, content):
|
def add_verse_to_lyrics(self, type, number, content):
|
||||||
"""
|
"""
|
||||||
type - type of verse (Chorus, Verse , Bridge, Custom etc
|
Add a verse to the ``<lyrics>`` tag.
|
||||||
number - number of item eg verse 1
|
|
||||||
content - the text to be stored
|
``type``
|
||||||
|
A string denoting the type of verse. Possible values are "Chorus",
|
||||||
|
"Verse", "Bridge", and "Custom".
|
||||||
|
|
||||||
|
``number``
|
||||||
|
An integer denoting the number of the item, for example: verse 1.
|
||||||
|
|
||||||
|
``content``
|
||||||
|
The actual text of the verse to be stored.
|
||||||
"""
|
"""
|
||||||
verse = self.song_xml.createElement(u'verse')
|
verse = self.song_xml.createElement(u'verse')
|
||||||
verse.setAttribute(u'type', type)
|
verse.setAttribute(u'type', type)
|
||||||
verse.setAttribute(u'label', number)
|
verse.setAttribute(u'label', number)
|
||||||
self.lyrics.appendChild(verse)
|
self.lyrics.appendChild(verse)
|
||||||
|
# add data as a CDATA section to protect the XML from special chars
|
||||||
# add data as a CDATA section
|
|
||||||
cds = self.song_xml.createCDATASection(content)
|
cds = self.song_xml.createCDATASection(content)
|
||||||
verse.appendChild(cds)
|
verse.appendChild(cds)
|
||||||
|
|
||||||
def dump_xml(self):
|
def dump_xml(self):
|
||||||
# Debugging aid to see what we have
|
"""
|
||||||
|
Debugging aid to dump XML so that we can see what we have.
|
||||||
|
"""
|
||||||
print self.song_xml.toprettyxml(indent=u' ')
|
print self.song_xml.toprettyxml(indent=u' ')
|
||||||
|
|
||||||
def extract_xml(self):
|
def extract_xml(self):
|
||||||
# Print our newly created XML
|
"""
|
||||||
|
Extract our newly created XML song.
|
||||||
|
"""
|
||||||
return self.song_xml.toxml(u'utf-8')
|
return self.song_xml.toxml(u'utf-8')
|
||||||
|
|
||||||
class SongXMLParser():
|
class SongXMLParser():
|
||||||
|
"""
|
||||||
|
A class to read in and parse a song's XML.
|
||||||
|
"""
|
||||||
global log
|
global log
|
||||||
log = logging.getLogger(u'SongXMLParser')
|
log = logging.getLogger(u'SongXMLParser')
|
||||||
log.info(u'SongXMLParser Loaded')
|
log.info(u'SongXMLParser Loaded')
|
||||||
|
|
||||||
def __init__(self, xml):
|
def __init__(self, xml):
|
||||||
#print xml
|
"""
|
||||||
|
Set up our song XML parser.
|
||||||
|
|
||||||
|
``xml``
|
||||||
|
The XML of the song to be parsed.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.song_xml = ElementTree(element=XML(xml))
|
self.song_xml = ElementTree(element=XML(xml))
|
||||||
except:
|
except:
|
||||||
#print "invalid xml ", xml
|
log.debug(u'Invalid xml %s', xml)
|
||||||
log.debug(u'invalid xml %s', xml)
|
|
||||||
|
|
||||||
def get_verses(self):
|
def get_verses(self):
|
||||||
#return a list of verse's and attributes
|
"""
|
||||||
iter=self.song_xml.getiterator()
|
Iterates through the verses in the XML and returns a list of verses
|
||||||
|
and their attributes.
|
||||||
|
"""
|
||||||
|
iter = self.song_xml.getiterator()
|
||||||
verse_list = []
|
verse_list = []
|
||||||
for element in iter:
|
for element in iter:
|
||||||
#print element.tag, element.attrib, element.text
|
|
||||||
if element.tag == u'verse':
|
if element.tag == u'verse':
|
||||||
verse_list.append([element.attrib, element.text])
|
verse_list.append([element.attrib, element.text])
|
||||||
return verse_list
|
return verse_list
|
||||||
|
|
||||||
def dump_xml(self):
|
def dump_xml(self):
|
||||||
# Debugging aid to see what we have
|
"""
|
||||||
|
Debugging aid to dump XML so that we can see what we have.
|
||||||
|
"""
|
||||||
print dump(self.song_xml)
|
print dump(self.song_xml)
|
||||||
|
@ -345,5 +345,5 @@ class ThemeXML(object):
|
|||||||
s = u''
|
s = u''
|
||||||
for k in dir(self):
|
for k in dir(self):
|
||||||
if k[0:1] != u'_':
|
if k[0:1] != u'_':
|
||||||
s += u'%30s : %s\n' %(k, getattr(self, k))
|
s += u'%30s: %s\n' %(k, getattr(self, k))
|
||||||
return s
|
return s
|
||||||
|
Loading…
Reference in New Issue
Block a user