From b3af02308b7032cd991ee251abdee09bd3d877ea Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 10 Jul 2009 15:16:15 +0200 Subject: [PATCH] More docstrings cleanups. --- openlp/core/lib/plugin.py | 102 ++++++++++----- openlp/core/lib/pluginconfig.py | 57 ++++++++- openlp/core/lib/pluginmanager.py | 47 +++++-- openlp/core/lib/renderer.py | 191 +++++++++++++++++++++++------ openlp/core/lib/rendermanager.py | 131 +++++++++++++++----- openlp/core/lib/serviceitem.py | 73 +++++++++-- openlp/core/lib/settingstab.py | 16 ++- openlp/core/lib/songxmlhandler.py | 65 +++++++--- openlp/core/lib/themexmlhandler.py | 2 +- 9 files changed, 547 insertions(+), 137 deletions(-) diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index bff11c4ed..7b306ec76 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -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 diff --git a/openlp/core/lib/pluginconfig.py b/openlp/core/lib/pluginconfig.py index 519e4e255..3c9d2b70d 100644 --- a/openlp/core/lib/pluginconfig.py +++ b/openlp/core/lib/pluginconfig.py @@ -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 diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index b557400b9..e8eb308a5 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -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() diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index e3774ba10..3f389afa7 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -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') diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index 4fa8a88e9..6c3d11001 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -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) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 4f1e5abf4..f9dfa2097 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -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'] diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index 1eddbee0e..421d0744d 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -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 diff --git a/openlp/core/lib/songxmlhandler.py b/openlp/core/lib/songxmlhandler.py index 14ed4ea0b..9cb0bb4e9 100644 --- a/openlp/core/lib/songxmlhandler.py +++ b/openlp/core/lib/songxmlhandler.py @@ -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 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 ```` tag which contains the lyrics of the + song. + """ # Create the main 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 ```` 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) diff --git a/openlp/core/lib/themexmlhandler.py b/openlp/core/lib/themexmlhandler.py index 4c6789193..acb451653 100644 --- a/openlp/core/lib/themexmlhandler.py +++ b/openlp/core/lib/themexmlhandler.py @@ -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