Comment changes

This commit is contained in:
Tim Bentley 2009-07-10 16:41:24 +01:00
commit 7e6ad29306
9 changed files with 547 additions and 137 deletions

View File

@ -31,42 +31,58 @@ class Plugin(object):
Base class for openlp plugins to inherit from.
Basic attributes are:
* name
``name``
The name that should appear in the plugins list.
* version
``version``
The version number of this iteration of the plugin.
* icon
``icon``
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
openlp.org's configuration. This is pre-instantiated.
* log
``log``
A log object used to log debugging messages. This is pre-instantiated.
Hook functions:
* check_pre_conditions()
``check_pre_conditions()``
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.
* add_import_menu_item(import_menu)
``add_import_menu_item(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.
* get_settings_tab()
``get_settings_tab()``
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.
* handle_event(event)
``handle_event(event)``
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.
* save(data)
``save(data)``
A method to convert the plugin's data to a string to be stored in the
Service file.
* load(string)
``load(string)``
A method to convert the string from a Service file into the plugin's
own data format.
* render(theme, screen_number)
``render(theme, screen_number)``
A method used to render something to the screen, given the current theme
and screen number.
"""
@ -78,11 +94,20 @@ class Plugin(object):
"""
This is the constructor for the plugin object. This provides an easy
way for descendent plugins to populate common data. This method *must*
be overridden, like so:
class MyPlugin(Plugin):
def __init__(self):
Plugin.__init(self, 'MyPlugin', '0.1')
...
be overridden, like so::
class MyPlugin(Plugin):
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:
self.name = name
@ -107,50 +132,59 @@ class Plugin(object):
def check_pre_conditions(self):
"""
Provides the Plugin with a handle to check if it can be loaded.
Returns True or False.
"""
return True
def get_media_manager_item(self):
"""
Construct a MediaManagerItem object with all the buttons and things you
need, and return it for integration into openlp.org.
Construct a MediaManagerItem object with all the buttons and things
you need, and return it for integration into openlp.org.
"""
pass
def add_import_menu_item(self, import_menu):
"""
Create a menu item and add it to the "Import" menu.
``import_menu``
The Import menu.
"""
pass
def add_export_menu_item(self, export_menu):
"""
Create a menu item and add it to the "Export" menu.
``export_menu``
The Export menu
"""
pass
def get_settings_tab(self):
"""
Create a menu item and add it to the "Import" menu.
Create a tab for the settings window.
"""
pass
def add_to_menu(self, menubar):
"""
Add menu items to the menu, given the menubar.
``menubar``
The application's menu bar.
"""
pass
def handle_event(self, event):
"""
Handle the event contained in the event object.
"""
def handle_event(self, event):
"""
Handle the event contained in the event object. If you want
to use this default behaviour, you must set self.dnd_id equal
to that sent by the dnd source - eg the MediaItem
``event``
An object describing the event.
"""
# default behaviour - can be overridden if desired
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
string which can be written to the service file.
``data``
The data to be saved.
"""
pass
@ -182,12 +219,21 @@ class Plugin(object):
"""
A string from the service file is passed in. This function parses and
sets up the internals of the plugin.
``string``
The data to be loaded into the plugin.
"""
pass
def render(self, theme, screen=None):
"""
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

View File

@ -29,28 +29,50 @@ class PluginConfig(object):
"""
Initialise the plugin config object, setting the section name to the
plugin name.
``plugin_name``
The name of the plugin to use as a section name.
"""
self.section = plugin_name.lower()
def get_config(self, key, default=None):
"""
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)
def delete_config(self, key):
"""
Delete a configuration value from the configuration registry.
``key``
The name of the configuration to remove.
"""
return ConfigHelper.delete_config(self.section, key)
def set_config(self, key, value):
"""
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)
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()
safe_name = self.section.replace(u' ',u'-')
@ -61,9 +83,21 @@ class PluginConfig(object):
return 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))
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:
files = os.listdir(self.get_data_path())
except:
@ -86,7 +120,10 @@ class PluginConfig(object):
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)
if list_count is not None:
@ -102,7 +139,13 @@ class PluginConfig(object):
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)))
new_count = len(list)
@ -116,7 +159,10 @@ class PluginConfig(object):
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:
name = u'last directory %d' % num
@ -129,7 +175,10 @@ class PluginConfig(object):
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:
name = u'last directory %d' % num

View File

@ -34,8 +34,11 @@ class PluginManager(object):
def __init__(self, dir):
"""
The constructor for the plugin manager.
Passes the controllers on to the plugins for them to interact with via their ServiceItems
The constructor for the plugin manager. Passes the controllers on to
the plugins for them to interact with via their ServiceItems.
``dir``
The directory to search for plugins.
"""
log.info(u'Plugin manager initing')
if not dir in sys.path:
@ -49,7 +52,16 @@ class PluginManager(object):
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
startdepth = len(os.path.abspath(dir).split(os.sep))
@ -104,8 +116,8 @@ class PluginManager(object):
def hook_media_manager(self, mediatoolbox):
"""
Loop through all the plugins. If a plugin has a valid media manager item,
add it to the media manager.
Loop through all the plugins. If a plugin has a valid media manager
item, add it to the media manager.
``mediatoolbox``
The Media Manager itself.
@ -118,8 +130,11 @@ class PluginManager(object):
def hook_settings_tabs(self, settingsform=None):
"""
Loop through all the plugins. If a plugin has a valid settings tab item,
add it to the settings tab.
Loop through all the plugins. If a plugin has a valid 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:
settings_tab = plugin.get_settings_tab()
@ -131,24 +146,30 @@ class PluginManager(object):
def hook_import_menu(self, import_menu):
"""
Loop through all the plugins and give them an opportunity to add an item
to the import menu.
Loop through all the plugins and give them an opportunity to add an
item to the import menu.
``import_menu``
The Import menu.
"""
for plugin in self.plugins:
plugin.add_import_menu_item(import_menu)
def hook_export_menu(self, export_menu):
"""
Loop through all the plugins and give them an opportunity to add an item
to the export menu.
Loop through all the plugins and give them an opportunity to add an
item to the export menu.
``export_menu``
The Export menu.
"""
for plugin in self.plugins:
plugin.add_export_menu_item(export_menu)
def initialise_plugins(self):
"""
Loop through all the plugins and give them an opportunity to add an item
to the export menu.
Loop through all the plugins and give them an opportunity to
initialise themselves.
"""
for plugin in self.plugins:
plugin.initialise()

View File

@ -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
"""
import logging
import os, os.path
import os
import sys
from PyQt4 import QtGui, QtCore
class Renderer:
class Renderer(object):
"""
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.
@ -33,6 +33,9 @@ class Renderer:
log.info(u'Renderer Loaded')
def __init__(self):
"""
Initialise the renderer.
"""
self._rect = None
self._debug = 0
self._right_margin = 64 # the amount of right indent
@ -47,11 +50,20 @@ class Renderer:
self._bg_frame_small = None
def set_debug(self, debug):
"""
Set the debug mode of the renderer.
``debug``
The debug mode.
"""
self._debug=debug
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')
self._theme = theme
@ -64,12 +76,21 @@ class Renderer:
self.set_bg_image(theme.background_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)
self._bg_image_filename = unicode(filename)
if self._frame is not None:
self.scale_bg_image()
def scale_bg_image(self):
"""
Scale the background image to fit the screen.
"""
assert self._frame
preview = QtGui.QImage(self._bg_image_filename)
width = self._frame.width()
@ -89,7 +110,16 @@ class Renderer:
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:
self._bg_frame = None
@ -103,7 +133,14 @@ class Renderer:
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')
verses = []
@ -120,15 +157,28 @@ class Renderer:
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_footer = rect_footer
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')
#print "Render Lines ", lines
bbox = self._render_lines_unaligned(lines, False)
@ -139,14 +189,15 @@ class Renderer:
x, y = self._correctAlignment(self._rect, bbox)
bbox = self._render_lines_unaligned(lines, False, (x, y), True)
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')
return self._frame
def _generate_background_frame(self):
"""
Generate a background frame to the same size as the frame to be used
Results cached for performance reasons.
Generate a background frame to the same size as the frame to be used.
Results are cached for performance reasons.
"""
assert(self._theme)
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):
"""
Given a list of lines, decide how to split them best if they don't all fit on the screen
- this is done by splitting at 1/2, 1/3 or 1/4 of the set
If it doesn't fit, even at this size, just split at each opportunity.
We'll do this by getting the bounding box of each line, and then summing them appropriately
Returns a list of [lists of lines], one set for each screenful
Given a list of lines, decide how to split them best if they don't all
fit on the screen. This is done by splitting at 1/2, 1/3 or 1/4 of the
set. If it doesn't fit, even at this size, just split at each
opportunity. We'll do this by getting the bounding box of each line,
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 = []
for line in lines:
@ -254,6 +313,15 @@ class Renderer:
return retval
def _correctAlignment(self, rect, bbox):
"""
Corrects the vertical alignment of text.
``rect``
The block dimentions.
``bbox``
Footer dimensions?
"""
x = rect.left()
if int(self._theme.display_verticalAlign) == 0:
# top align
@ -268,13 +336,26 @@ class Renderer:
log.error(u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
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
(using the _render_single_line fn - which may result in going
off the bottom) They are expected to be pre-arranged to less
than a screenful (eg. by using split_set_of_lines)
Returns the bounding box of the text as QRect
Given a list of lines to render, render each one in turn (using the
``_render_single_line`` fn - which may result in going off the bottom).
They are expected to be pre-arranged to less than a screenful (eg. by
using split_set_of_lines).
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
brx = x
@ -282,25 +363,37 @@ class Renderer:
for line in lines:
# render after current bottom, but at original left edge
# 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):
brx = thisx
retval = QtCore.QRect(x, y,brx-x, bry-y)
retval = QtCore.QRect(x, y, brx - x, bry - y)
if self._debug:
painter = QtGui.QPainter()
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.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
specified.
If the line is too wide for the context, it wraps, but
right-aligns the surplus words in the manner of song lyrics
Render a single line of words onto the DC, top left corner specified.
If the line is too wide for the context, it wraps, but 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).
``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
# 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
def _set_theme_font(self):
"""
Set the fonts from the current theme settings.
"""
self.footerFont = QtGui.QFont(self._theme.font_footer_name,
int(self._theme.font_footer_proportion), # size
QtGui.QFont.Normal, # weight
@ -408,11 +504,26 @@ class Renderer:
0)# italic
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.
If draw is set, actually draw the text to the current DC as well
return width and height of text as a tuple (w,h)
Find bounding box of text - as render_single_line. If draw is set,
actually draw the text to the current DC as well return width and
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
painter = QtGui.QPainter()
@ -424,7 +535,7 @@ class Renderer:
else:
font = self.mainFont
painter.setFont(font)
if color == None:
if color is None:
if footer:
painter.setPen(QtGui.QColor(self._theme.font_footer_color))
else:
@ -443,7 +554,13 @@ class Renderer:
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.save(u'renderer.png', u'png')

View File

@ -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
"""
import logging
import os, os.path
import sys
from PyQt4 import QtGui, QtCore
from renderer import Renderer
import os
import sys
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.
The plugins will call helper methods to do the rendering but
this class will provide display defense code.
Class to pull all Renderer interactions into one place. The plugins will
call helper methods to do the rendering but this class will provide
display defense code.
"""
global log
log=logging.getLogger(u'RenderManager')
log.info(u'RenderManager Loaded')
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')
self.screen_list = screen_list
self.theme_manager = theme_manager
@ -52,21 +63,46 @@ class RenderManager:
def update_display(self, screen_number):
"""
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')
if self.current_display != screen_number:
self.current_display = screen_number
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_style = global_style
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
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':
self.theme = self.global_theme
elif self.global_style == u'Service':
@ -84,7 +120,7 @@ class RenderManager:
self.theme = self.service_theme
else:
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)
self.themedata = self.theme_manager.getThemeData(self.theme)
self.calculate_default(self.screen_list[self.current_display][u'size'])
@ -92,7 +128,13 @@ class RenderManager:
self.build_text_rectangle(self.themedata)
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
footer_rect = None
if theme.font_main_override == False:
@ -108,31 +150,52 @@ class RenderManager:
self.renderer.set_text_rectangle(main_rect,footer_rect)
def generate_preview(self, themedata):
"""
Generate a preview of a theme.
``themedata``
The theme to generated a preview for.
"""
log.debug(u'generate preview')
self.calculate_default(QtCore.QSize(1024, 768))
self.renderer.set_theme(themedata)
self.build_text_rectangle(themedata)
self.renderer.set_frame_dest(self.width, self.height, True)
lines = []
lines.append(u'Amazing Grace!')
lines.append(u'How sweet the sound')
lines.append(u'To save a wretch like me;')
lines.append(u'I once was lost but now am found,')
lines.append(u'Was blind, but now I see.')
lines1 = []
lines1.append(u'Amazing Grace (John Newton)' )
lines1.append(u'Public Domain')
lines1.append(u'CCLI xxx')
return self.renderer.generate_frame_from_lines(lines, lines1)
verse = []
verse.append(u'Amazing Grace!')
verse.append(u'How sweet the sound')
verse.append(u'To save a wretch like me;')
verse.append(u'I once was lost but now am found,')
verse.append(u'Was blind, but now I see.')
footer = []
footer.append(u'Amazing Grace (John Newton)' )
footer.append(u'Public Domain')
footer.append(u'CCLI xxx')
return self.renderer.generate_frame_from_lines(verse, footer)
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')
self.calculate_default(self.screen_list[self.current_display][u'size'])
self.build_text_rectangle(self.themedata)
self.renderer.set_frame_dest(self.width, self.height)
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')
self.calculate_default(self.screen_list[self.current_display][u'size'])
self.build_text_rectangle(self.themedata)
@ -140,6 +203,12 @@ class RenderManager:
return self.renderer.generate_frame_from_lines(main_text, footer_text)
def resize_image(self, image):
"""
Resize an image to fit on the current screen.
``image``
The image to resize.
"""
preview = QtGui.QImage(image)
w = self.width
h = self.height
@ -154,13 +223,19 @@ class RenderManager:
return newImage
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:
self.width = 1024
self.height = 768
else:
self.width = screen.width()
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
self.footer_start = int(self.height * 0.90)

View File

@ -20,10 +20,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
import logging
import os
import time
from openlp.core.lib import buildIcon
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 manager, the slide controller, and the projection screen
@ -35,7 +37,10 @@ class ServiceItem():
def __init__(self, hostplugin=None):
"""
Init Method
Set up the service item.
``hostplugin``
The plugin that this service item belongs to.
"""
self.plugin = hostplugin
if hostplugin is not None:
@ -56,6 +61,14 @@ class ServiceItem():
self.service_frames = []
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.iconic_representation = buildIcon(icon)
@ -89,27 +102,63 @@ class ServiceItem():
else:
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_path = path
self.service_frames.append({u'title': frame_title, u'image': image})
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'
frame_title = frame_title.split(u'\n')[0]
self.service_frames.append({u'title': frame_title, u'raw_slide': raw_slide})
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_frames.append({u'title': frame_title, u'command': command})
def get_oos_repr(self):
"""
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,
u'icon':self.icon, u'footer':self.raw_footer, u'type':self.service_item_type}
oos_header = {
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 = []
if self.service_item_type == u'text':
for slide in self.service_frames:
@ -124,8 +173,14 @@ class ServiceItem():
def set_from_oos(self, serviceitem, path=None):
"""
This method takes some oos list (passed from the ServiceManager)
and extracts the data actually required
This method takes a service item from a saved service file (passed
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
header = serviceitem[u'serviceitem'][u'header']

View File

@ -23,11 +23,20 @@ from openlp.core.lib import PluginConfig
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):
"""
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)
self.tabTitle = title
@ -43,6 +52,9 @@ class SettingsTab(QtGui.QWidget):
def setTitle(self, title):
"""
Set the title of the tab.
``title``
The title of the tab, which is usually displayed on the tab.
"""
self.tabTitle = title

View File

@ -30,21 +30,34 @@ from xml.etree.ElementTree import ElementTree, XML, dump
"""
import logging
from xml.dom.minidom import Document
from xml.dom.minidom import Document
from xml.etree.ElementTree import ElementTree, XML, dump
class SongXMLBuilder():
"""
This class builds the XML used to describe songs.
"""
def __init__(self):
"""
Set up the song builder.
"""
# Create the minidom document
self.song_xml = Document()
def new_document(self):
"""
Create a new song XML document.
"""
# Create the <song> base element
self.song = self.song_xml.createElement(u'song')
self.song_xml.appendChild(self.song)
self.song.setAttribute(u'version', u'1.0')
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
self.lyrics = self.song_xml.createElement(u'lyrics')
self.lyrics.setAttribute(u'language', u'en')
@ -52,50 +65,72 @@ class SongXMLBuilder():
def add_verse_to_lyrics(self, type, number, content):
"""
type - type of verse (Chorus, Verse , Bridge, Custom etc
number - number of item eg verse 1
content - the text to be stored
Add a verse to the ``<lyrics>`` tag.
``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.setAttribute(u'type', type)
verse.setAttribute(u'label', number)
self.lyrics.appendChild(verse)
# add data as a CDATA section
# add data as a CDATA section to protect the XML from special chars
cds = self.song_xml.createCDATASection(content)
verse.appendChild(cds)
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' ')
def extract_xml(self):
# Print our newly created XML
"""
Extract our newly created XML song.
"""
return self.song_xml.toxml(u'utf-8')
class SongXMLParser():
"""
A class to read in and parse a song's XML.
"""
global log
log = logging.getLogger(u'SongXMLParser')
log.info(u'SongXMLParser Loaded')
def __init__(self, xml):
#print xml
"""
Set up our song XML parser.
``xml``
The XML of the song to be parsed.
"""
try:
self.song_xml = ElementTree(element=XML(xml))
except:
#print "invalid xml ", xml
log.debug(u'invalid xml %s', xml)
log.debug(u'Invalid xml %s', xml)
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 = []
for element in iter:
#print element.tag, element.attrib, element.text
if element.tag == u'verse':
verse_list.append([element.attrib, element.text])
return verse_list
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)

View File

@ -345,5 +345,5 @@ class ThemeXML(object):
s = u''
for k in dir(self):
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