diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 59237a661..04badb454 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -43,15 +43,14 @@ from traceback import format_exception from PyQt4 import QtCore, QtGui -from openlp.core.lib import Receiver, Settings, check_directory_exists, ScreenList, UiStrings +from openlp.core.lib import Receiver, Settings, check_directory_exists, ScreenList, UiStrings, Registry from openlp.core.resources import qInitResources from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui import SplashScreen -from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \ - get_application_version +from openlp.core.utils import AppLocation, LanguageManager, VersionThread, get_application_version __all__ = [u'OpenLP', u'main'] @@ -284,6 +283,7 @@ def main(args=None): else: app.setApplicationName(u'OpenLP') set_up_logging(AppLocation.get_directory(AppLocation.CacheDir)) + registry = Registry.create() app.setApplicationVersion(get_application_version()[u'version']) # Instance check if not options.testing: diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 6648e3e80..5cbfec11f 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -386,6 +386,7 @@ def create_separated_list(stringlist): u'Locale list separator: start') % (stringlist[0], merged) +from registry import Registry from uistrings import UiStrings from eventreceiver import Receiver from screen import ScreenList diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index dec83e991..72389066b 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -39,7 +39,7 @@ import Queue from PyQt4 import QtCore -from openlp.core.lib import resize_image, image_to_byte, Receiver, ScreenList +from openlp.core.lib import resize_image, image_to_byte, Receiver, Registry, ScreenList log = logging.getLogger(__name__) @@ -182,6 +182,7 @@ class ImageManager(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) + Registry().register(u'image_manager', self) currentScreen = ScreenList().current self.width = currentScreen[u'size'].width() self.height = currentScreen[u'size'].height() diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 30d5c09e1..100f248c0 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -35,8 +35,8 @@ import re from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, translate, \ - Receiver, ListWidgetWithDnD, ServiceItemContext, Settings, UiStrings +from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, build_icon, translate, Receiver, \ + ListWidgetWithDnD, ServiceItemContext, Settings, Registry, UiStrings from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import create_widget_action, critical_error_message_box @@ -99,6 +99,7 @@ class MediaManagerItem(QtGui.QWidget): self.plugin = plugin visible_title = self.plugin.getString(StringContent.VisibleName) self.title = unicode(visible_title[u'title']) + Registry().register(self.title, self) self.settingsSection = self.plugin.name self.icon = None if icon: @@ -469,7 +470,7 @@ class MediaManagerItem(QtGui.QWidget): serviceItem = self.buildServiceItem() if serviceItem: serviceItem.from_plugin = True - self.plugin.previewController.addServiceItem(serviceItem) + self.preview_controller.addServiceItem(serviceItem) if keepFocus: self.listView.setFocus() @@ -495,7 +496,7 @@ class MediaManagerItem(QtGui.QWidget): serviceItem.from_plugin = True if remote: serviceItem.will_auto_start = True - self.plugin.liveController.addServiceItem(serviceItem) + self.live_controller.addServiceItem(serviceItem) def createItemFromId(self, item_id): item = QtGui.QListWidgetItem() @@ -510,7 +511,7 @@ class MediaManagerItem(QtGui.QWidget): QtGui.QMessageBox.information(self, UiStrings().NISp, translate('OpenLP.MediaManagerItem', 'You must select one or more items to add.')) else: - # Is it posssible to process multiple list items to generate + # Is it possible to process multiple list items to generate # multiple service items? if self.singleServiceItem or self.remoteTriggered: log.debug(u'%s Add requested', self.plugin.name) @@ -524,7 +525,7 @@ class MediaManagerItem(QtGui.QWidget): serviceItem = self.buildServiceItem(item, True, remote=remote, context=ServiceItemContext.Service) if serviceItem: serviceItem.from_plugin = False - self.plugin.serviceManager.addServiceItem(serviceItem, replace=replace) + self.service_manager.addServiceItem(serviceItem, replace=replace) def onAddEditClick(self): """ @@ -541,7 +542,7 @@ class MediaManagerItem(QtGui.QWidget): translate('OpenLP.MediaManagerItem', 'You must select an existing service item to add to.')) elif self.plugin.name == serviceItem.name: self.generateSlideData(serviceItem) - self.plugin.serviceManager.addServiceItem(serviceItem, replace=True) + self.service_manager.addServiceItem(serviceItem, replace=True) else: # Turn off the remote edit update message indicator QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'Invalid Service Item'), @@ -617,3 +618,73 @@ class MediaManagerItem(QtGui.QWidget): Performs a plugin specific search for items containing ``string`` """ raise NotImplementedError(u'Plugin.search needs to be defined by the plugin') + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) + + def _get_renderer(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_renderer'): + self._renderer = Registry().get(u'renderer') + return self._renderer + + renderer = property(_get_renderer) + + def _get_live_controller(self): + """ + Adds the live controller to the class dynamically + """ + if not hasattr(self, u'_live_controller'): + self._live_controller = Registry().get(u'live_controller') + return self._live_controller + + live_controller = property(_get_live_controller) + + def _get_preview_controller(self): + """ + Adds the preview controller to the class dynamically + """ + if not hasattr(self, u'_preview_controller'): + self._preview_controller = Registry().get(u'preview_controller') + return self._preview_controller + + preview_controller = property(_get_preview_controller) + + def _get_plugin_manager(self): + """ + Adds the plugin manager to the class dynamically + """ + if not hasattr(self, u'_plugin_manager'): + self._plugin_manager = Registry().get(u'plugin_manager') + return self._plugin_manager + + plugin_manager = property(_get_plugin_manager) + + def _get_media_controller(self): + """ + Adds the media controller to the class dynamically + """ + if not hasattr(self, u'_media_controller'): + self._media_controller = Registry().get(u'media_controller') + return self._media_controller + + media_controller = property(_get_media_controller) + + def _get_service_manager(self): + """ + Adds the plugin manager to the class dynamically + """ + if not hasattr(self, u'_service_manager'): + self._service_manager = Registry().get(u'service_manager') + return self._service_manager + + service_manager = property(_get_service_manager) \ No newline at end of file diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index ba6b7673e..49a08e32a 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -33,7 +33,7 @@ import logging from PyQt4 import QtCore -from openlp.core.lib import Receiver, Settings, UiStrings +from openlp.core.lib import Receiver, Settings, Registry, UiStrings from openlp.core.utils import get_application_version log = logging.getLogger(__name__) @@ -118,8 +118,7 @@ class Plugin(QtCore.QObject): """ log.info(u'loaded') - def __init__(self, name, default_settings, plugin_helpers=None, media_item_class=None, - settings_tab_class=None, version=None): + def __init__(self, name, default_settings, media_item_class=None, settings_tab_class=None, version=None): """ This is the constructor for the plugin object. This provides an easy way for descendent plugins to populate common data. This method *must* @@ -135,9 +134,6 @@ class Plugin(QtCore.QObject): ``default_settings`` A dict containing the plugin's settings. The value to each key is the default value to be used. - ``plugin_helpers`` - Defaults to *None*. A list of helper objects. - ``media_item_class`` The class name of the plugin's media item. @@ -165,15 +161,6 @@ class Plugin(QtCore.QObject): self.mediaItem = None self.weight = 0 self.status = PluginStatus.Inactive - self.previewController = plugin_helpers[u'preview'] - self.liveController = plugin_helpers[u'live'] - self.renderer = plugin_helpers[u'renderer'] - self.serviceManager = plugin_helpers[u'service'] - self.settingsForm = plugin_helpers[u'settings form'] - self.mediaDock = plugin_helpers[u'toolbox'] - self.pluginManager = plugin_helpers[u'pluginmanager'] - self.formParent = plugin_helpers[u'formparent'] - self.mediaController = plugin_helpers[u'mediacontroller'] # Add the default status to the default settings. default_settings[name + u'/status'] = PluginStatus.Inactive default_settings[name + u'/last directory'] = u'' @@ -228,7 +215,7 @@ class Plugin(QtCore.QObject): you need, and return it for integration into OpenLP. """ if self.mediaItemClass: - self.mediaItem = self.mediaItemClass(self.mediaDock.media_dock, self, self.icon) + self.mediaItem = self.mediaItemClass(self.main_window.mediaDockManager.media_dock, self, self.icon) def addImportMenuItem(self, importMenu): """ @@ -298,14 +285,14 @@ class Plugin(QtCore.QObject): """ if self.mediaItem: self.mediaItem.initialise() - self.mediaDock.insert_dock(self.mediaItem, self.icon, self.weight) + self.main_window.mediaDockManager.insert_dock(self.mediaItem, self.icon, self.weight) def finalise(self): """ Called by the plugin Manager to cleanup things. """ if self.mediaItem: - self.mediaDock.remove_dock(self.mediaItem) + self.main_window.mediaDockManager.remove_dock(self.mediaItem) def appStartup(self): """ @@ -421,3 +408,14 @@ class Plugin(QtCore.QObject): The plugin's config has changed """ pass + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) + diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 7fbe7ba9e..ae1d9f984 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -33,7 +33,7 @@ import os import sys import logging -from openlp.core.lib import Plugin, PluginStatus +from openlp.core.lib import Plugin, PluginStatus, Registry log = logging.getLogger(__name__) @@ -43,13 +43,6 @@ class PluginManager(object): and executes all the hooks, as and when necessary. """ log.info(u'Plugin manager loaded') - __instance__ = None - @staticmethod - def get_instance(): - """ - Obtain a single instance of class. - """ - return PluginManager.__instance__ def __init__(self, plugin_dir): """ @@ -60,7 +53,7 @@ class PluginManager(object): The directory to search for plugins. """ log.info(u'Plugin manager Initialising') - PluginManager.__instance__ = self + Registry().register(u'plugin_manager', self) if not plugin_dir in sys.path: log.debug(u'Inserting %s into sys.path', plugin_dir) sys.path.insert(0, plugin_dir) @@ -69,7 +62,7 @@ class PluginManager(object): self.plugins = [] log.info(u'Plugin manager Initialised') - def find_plugins(self, plugin_dir, plugin_helpers): + def find_plugins(self, plugin_dir): """ Scan the directory ``plugin_dir`` for objects inheriting from the ``Plugin`` class. @@ -77,9 +70,6 @@ class PluginManager(object): ``plugin_dir`` The directory to scan. - ``plugin_helpers`` - A list of helper objects to pass to the plugins. - """ log.info(u'Finding plugins') startdepth = len(os.path.abspath(plugin_dir).split(os.sep)) @@ -117,7 +107,7 @@ class PluginManager(object): plugin_objects = [] for p in plugin_classes: try: - plugin = p(plugin_helpers) + plugin = p() log.debug(u'Loaded plugin %s', unicode(p)) plugin_objects.append(plugin) except TypeError: diff --git a/openlp/core/lib/registry.py b/openlp/core/lib/registry.py new file mode 100644 index 000000000..a30ed4ba3 --- /dev/null +++ b/openlp/core/lib/registry.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2013 Raoul Snyman # +# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Provide Registry Services +""" +import logging + +log = logging.getLogger(__name__) + +class Registry(object): + """ + This is the Component Registry. It is a singleton object and is used to provide a + look up service for common objects. + """ + log.info(u'Registry loaded') + __instance__ = None + + def __new__(cls): + if not cls.__instance__: + cls.__instance__ = object.__new__(cls) + return cls.__instance__ + + @classmethod + def create(cls): + """ + The constructor for the component registry providing a single registry of objects. + """ + log.info(u'Registry Initialising') + registry = cls() + registry.service_list = {} + return registry + + def get(self, key): + """ + Extracts the registry value from the list based on the key passed in + """ + if key in self.service_list: + return self.service_list[key] + else: + log.error(u'Service %s not found in list' % key) + raise KeyError(u'Service %s not found in list' % key) + + def register(self, key, reference): + """ + Registers a component against a key. + """ + if key in self.service_list: + log.error(u'Duplicate service exception %s' % key) + raise KeyError(u'Duplicate service exception %s' % key) + else: + self.service_list[key] = reference diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 2eb19c1e7..8e6d9d8ad 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -32,7 +32,7 @@ import logging from PyQt4 import QtGui, QtCore, QtWebKit from openlp.core.lib import ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css, Receiver, \ - ItemCapabilities, FormattingTags, ImageSource, ScreenList + ItemCapabilities, FormattingTags, ImageSource, Registry, ScreenList from openlp.core.lib.theme import ThemeLevel from openlp.core.ui import MainDisplay @@ -57,7 +57,7 @@ class Renderer(object): """ log.info(u'Renderer Loaded') - def __init__(self, image_manager, theme_manager): + def __init__(self): """ Initialise the renderer. @@ -69,15 +69,14 @@ class Renderer(object): The theme_manager instance, used to get the current theme details. """ log.debug(u'Initialisation started') - self.theme_manager = theme_manager - self.image_manager = image_manager self.screens = ScreenList() + Registry().register(u'renderer', self) self.theme_level = ThemeLevel.Global self.global_theme_name = u'' self.service_theme_name = u'' self.item_theme_name = u'' self.force_page = False - self.display = MainDisplay(None, self.image_manager, False, self) + self.display = MainDisplay(None, False, self) self.display.setup() self._theme_dimensions = {} self._calculate_default() @@ -94,7 +93,7 @@ class Renderer(object): self._calculate_default() if self.display: self.display.close() - self.display = MainDisplay(None, self.image_manager, False, self) + self.display = MainDisplay(None, False, self) self.display.setup() self._theme_dimensions = {} @@ -236,7 +235,6 @@ class Renderer(object): serviceItem.add_from_text(VERSE_FOR_LINE_COUNT) else: serviceItem.add_from_text(VERSE) - serviceItem.renderer = self serviceItem.raw_footer = FOOTER # if No file do not update cache if theme_data.background_filename: @@ -644,3 +642,23 @@ class Renderer(object): # this parse we are to be wordy line = line.replace(u'\n', u' ') return line.split(u' ') + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) + + def _get_theme_manager(self): + """ + Adds the theme manager to the class dynamically + """ + if not hasattr(self, u'_theme_manager'): + self._theme_manager = Registry().get(u'theme_manager') + return self._theme_manager + + theme_manager = property(_get_theme_manager) \ No newline at end of file diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 002068109..b6f225cd9 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -39,7 +39,7 @@ import uuid from PyQt4 import QtGui -from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource, Settings +from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource, Settings, Registry log = logging.getLogger(__name__) @@ -148,7 +148,6 @@ class ServiceItem(object): The plugin that this service item belongs to. """ if plugin: - self.renderer = plugin.renderer self.name = plugin.name self.title = u'' self.shortname = u'' @@ -161,7 +160,7 @@ class ServiceItem(object): self.service_item_type = None self._raw_frames = [] self._display_frames = [] - self._uuid = 0 + self.unique_identifier = 0 self.notes = u'' self.from_plugin = False self.capabilities = [] @@ -195,7 +194,7 @@ class ServiceItem(object): Method to set the internal id of the item. This is used to compare service items to see if they are the same. """ - self._uuid = unicode(uuid.uuid1()) + self.unique_identifier = unicode(uuid.uuid1()) self.validate_item() def add_capability(self, capability): @@ -293,7 +292,7 @@ class ServiceItem(object): self.image_border = background self.service_item_type = ServiceItemType.Image self._raw_frames.append({u'title': title, u'path': path}) - self.renderer.image_manager.addImage(path, ImageSource.ImagePlugin, self.image_border) + self.image_manager.addImage(path, ImageSource.ImagePlugin, self.image_border) self._new_item() def add_from_text(self, raw_slide, verse_tag=None): @@ -454,14 +453,14 @@ class ServiceItem(object): def merge(self, other): """ - Updates the _uuid with the value from the original one - The _uuid is unique for a given service item but this allows one to + Updates the unique_identifier with the value from the original one + The unique_identifier is unique for a given service item but this allows one to replace an original version. ``other`` The service item to be merged with """ - self._uuid = other._uuid + self.unique_identifier = other.unique_identifier self.notes = other.notes self.temporary_edit = other.temporary_edit # Copy theme over if present. @@ -478,13 +477,13 @@ class ServiceItem(object): """ if not other: return False - return self._uuid == other._uuid + return self.unique_identifier == other.unique_identifier def __ne__(self, other): """ Confirms the service items are not for the same instance """ - return self._uuid != other._uuid + return self.unique_identifier != other.unique_identifier def is_media(self): """ @@ -637,10 +636,30 @@ class ServiceItem(object): if self.is_image() and not os.path.exists((frame[u'path'])): self.is_valid = False elif self.is_command(): - file = os.path.join(frame[u'path'],frame[u'title']) - if not os.path.exists(file): + file_name = os.path.join(frame[u'path'], frame[u'title']) + if not os.path.exists(file_name): self.is_valid = False if suffix_list and not self.is_text(): - type = frame[u'title'].split(u'.')[-1] - if type.lower() not in suffix_list: + file_suffix = frame[u'title'].split(u'.')[-1] + if file_suffix.lower() not in suffix_list: self.is_valid = False + + def _get_renderer(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_renderer'): + self._renderer = Registry().get(u'renderer') + return self._renderer + + renderer = property(_get_renderer) + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) \ No newline at end of file diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index e14309257..3fed96ec4 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -38,8 +38,8 @@ import sys from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL from PyQt4.phonon import Phonon -from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, translate, PluginManager, expand_tags,\ - Settings, ImageSource +from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, translate, expand_tags,\ + Settings, ImageSource, Registry from openlp.core.lib.theme import BackgroundType from openlp.core.lib import ScreenList @@ -66,7 +66,6 @@ class Display(QtGui.QGraphicsView): self.isLive = live self.controller = controller self.screen = {} - self.plugins = PluginManager.get_instance().plugins # FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with # OpenGL. Only white blank screen is shown on the 2nd monitor all the # time. We need to investigate more how to use OpenGL properly on Mac OS @@ -116,9 +115,8 @@ class MainDisplay(Display): """ This is the display screen as a specialized class from the Display class """ - def __init__(self, parent, imageManager, live, controller): + def __init__(self, parent, live, controller): Display.__init__(self, parent, live, controller) - self.imageManager = imageManager self.screens = ScreenList() self.rebuildCSS = False self.hideMode = None @@ -173,8 +171,8 @@ class MainDisplay(Display): Call the plugins to rebuild the Live display CSS as the screen has not been rebuild on exit of config. """ - if self.rebuildCSS and self.plugins: - for plugin in self.plugins: + if self.rebuildCSS and self.plugin_manager.plugins: + for plugin in self.plugin_manager.plugins: plugin.refreshCss(self.frame) self.rebuildCSS = False @@ -213,8 +211,8 @@ class MainDisplay(Display): splash_image) serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(self.initialFrame) - self.webView.setHtml(build_html(serviceItem, self.screen, - self.isLive, None, plugins=self.plugins)) + self.webView.setHtml(build_html(serviceItem, self.screen, self.isLive, None, + plugins=self.plugin_manager.plugins)) self.__hideMouse() log.debug(u'Finished MainDisplay setup') @@ -280,7 +278,7 @@ class MainDisplay(Display): """ API for replacement backgrounds so Images are added directly to cache. """ - self.imageManager.addImage(path, ImageSource.ImagePlugin, background) + self.image_manager.addImage(path, ImageSource.ImagePlugin, background) if not hasattr(self, u'serviceItem'): return False self.override[u'image'] = path @@ -302,8 +300,8 @@ class MainDisplay(Display): re-added to the image manager. """ log.debug(u'image to display') - image = self.imageManager.getImageBytes(path, ImageSource.ImagePlugin) - self.controller.mediaController.media_reset(self.controller) + image = self.image_manager.getImageBytes(path, ImageSource.ImagePlugin) + self.controller.media_controller.media_reset(self.controller) self.displayImage(image) def displayImage(self, image): @@ -383,17 +381,18 @@ class MainDisplay(Display): self.override = {} else: # replace the background - background = self.imageManager.getImageBytes(self.override[u'image'], ImageSource.ImagePlugin) + background = self.image_manager.getImageBytes(self.override[u'image'], ImageSource.ImagePlugin) self.setTransparency(self.serviceItem.themedata.background_type == BackgroundType.to_string(BackgroundType.Transparent)) if self.serviceItem.themedata.background_filename: - self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes( + self.serviceItem.bg_image_bytes = self.image_manager.getImageBytes( self.serviceItem.themedata.background_filename,ImageSource.Theme) if image_path: - image_bytes = self.imageManager.getImageBytes(image_path, ImageSource.ImagePlugin) + image_bytes = self.image_manager.getImageBytes(image_path, ImageSource.ImagePlugin) else: image_bytes = None - html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes, self.plugins) + html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes, + plugins=self.plugin_manager.plugins) log.debug(u'buildHtml - pre setHtml') self.webView.setHtml(html) log.debug(u'buildHtml - post setHtml') @@ -468,6 +467,26 @@ class MainDisplay(Display): self.setCursor(QtCore.Qt.ArrowCursor) self.frame.evaluateJavaScript('document.body.style.cursor = "auto"') + def _get_plugin_manager(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_plugin_manager'): + self._plugin_manager = Registry().get(u'plugin_manager') + return self._plugin_manager + + plugin_manager = property(_get_plugin_manager) + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) + class AudioPlayer(QtCore.QObject): """ @@ -591,3 +610,4 @@ class AudioPlayer(QtCore.QObject): #@todo is this used? def connectSlot(self, signal, slot): QtCore.QObject.connect(self.mediaObject, signal, slot) + diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 75a81d548..b5f069854 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -40,9 +40,8 @@ from datetime import datetime from PyQt4 import QtCore, QtGui from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, PluginManager, Receiver, translate, ImageManager, \ - PluginStatus, ScreenList, UiStrings -from openlp.core.lib.ui import create_action -from openlp.core.lib import Settings + PluginStatus, Registry, Settings, ScreenList +from openlp.core.lib.ui import UiStrings, create_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \ MediaDockManager, ShortcutListForm, FormattingTagForm from openlp.core.ui.media import MediaController @@ -159,12 +158,12 @@ class Ui_MainWindow(object): # Create the service manager self.serviceManagerDock = OpenLPDockWidget(mainWindow, u'serviceManagerDock', u':/system/system_servicemanager.png') - self.serviceManagerContents = ServiceManager(mainWindow, self.serviceManagerDock) + self.serviceManagerContents = ServiceManager(self.serviceManagerDock) self.serviceManagerDock.setWidget(self.serviceManagerContents) mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.serviceManagerDock) # Create the theme manager self.themeManagerDock = OpenLPDockWidget(mainWindow, u'themeManagerDock', u':/system/system_thememanager.png') - self.themeManagerContents = ThemeManager(mainWindow, self.themeManagerDock) + self.themeManagerContents = ThemeManager(self.themeManagerDock) self.themeManagerContents.setObjectName(u'themeManagerContents') self.themeManagerDock.setWidget(self.themeManagerContents) mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.themeManagerDock) @@ -456,6 +455,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): plugins. """ QtGui.QMainWindow.__init__(self) + Registry().register(u'main_window', self) self.application = application self.clipboard = self.application.clipboard() self.arguments = self.application.args @@ -475,14 +475,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.serviceNotSaved = False self.aboutForm = AboutForm(self) self.mediaController = MediaController(self) - self.settingsForm = SettingsForm(self, self) + self.settingsForm = SettingsForm(self) self.formattingTagForm = FormattingTagForm(self) self.shortcutForm = ShortcutListForm(self) self.recentFiles = [] # Set up the path with plugins plugin_path = AppLocation.get_directory(AppLocation.PluginsDir) self.pluginManager = PluginManager(plugin_path) - self.pluginHelpers = {} self.imageManager = ImageManager() # Set up the interface self.setupUi(self) @@ -543,21 +542,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # warning cyclic dependency # renderer needs to call ThemeManager and # ThemeManager needs to call Renderer - self.renderer = Renderer(self.imageManager, self.themeManagerContents) + self.renderer = Renderer() # Define the media Dock Manager self.mediaDockManager = MediaDockManager(self.mediaToolBox) log.info(u'Load Plugins') - # make the controllers available to the plugins - self.pluginHelpers[u'preview'] = self.previewController - self.pluginHelpers[u'live'] = self.liveController - self.pluginHelpers[u'renderer'] = self.renderer - self.pluginHelpers[u'service'] = self.serviceManagerContents - self.pluginHelpers[u'settings form'] = self.settingsForm - self.pluginHelpers[u'toolbox'] = self.mediaDockManager - self.pluginHelpers[u'pluginmanager'] = self.pluginManager - self.pluginHelpers[u'formparent'] = self - self.pluginHelpers[u'mediacontroller'] = self.mediaController - self.pluginManager.find_plugins(plugin_path, self.pluginHelpers) + self.pluginManager.find_plugins(plugin_path) # hook methods have to happen after find_plugins. Find plugins needs # the controllers hence the hooks have moved from setupUI() to here # Find and insert settings tabs @@ -1341,3 +1330,4 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Check if the new data path is our default. if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir): settings.remove(u'advanced/data path') + diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 4ba327b21..73f311186 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -32,7 +32,7 @@ import os import datetime from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings, UiStrings +from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings, Registry, UiStrings from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players from openlp.core.ui.media.mediaplayer import MediaPlayer @@ -88,6 +88,7 @@ class MediaController(object): """ def __init__(self, parent): self.mainWindow = parent + Registry().register(u'media_controller', self) self.mediaPlayers = {} self.displayControllers = {} self.currentMediaPlayer = {} @@ -130,14 +131,14 @@ class MediaController(object): for item in player.audio_extensions_list: if not item in self.audio_extensions_list: self.audio_extensions_list.append(item) - self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:]) + self.service_manager.supportedSuffixes(item[2:]) self.video_extensions_list = [] for player in self.mediaPlayers.values(): if player.isActive: for item in player.video_extensions_list: if item not in self.video_extensions_list: self.video_extensions_list.extend(item) - self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:]) + self.service_manager.supportedSuffixes(item[2:]) def register_players(self, player): """ @@ -729,3 +730,13 @@ class MediaController(object): if controller.isLive: return controller.display return controller.previewDisplay + + def _get_service_manager(self): + """ + Adds the plugin manager to the class dynamically + """ + if not hasattr(self, u'_service_manager'): + self._service_manager = Registry().get(u'service_manager') + return self._service_manager + + service_manager = property(_get_service_manager) \ No newline at end of file diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py index d6d9a8b06..ce72f4583 100644 --- a/openlp/core/ui/media/webkitplayer.py +++ b/openlp/core/ui/media/webkitplayer.py @@ -411,13 +411,13 @@ class WebkitPlayer(MediaPlayer): else: if display.frame.evaluateJavaScript(u'show_video("isEnded");') == 'true': self.stop(display) - (currentTime, ok) = display.frame.evaluateJavaScript(u'show_video("currentTime");') + currentTime = display.frame.evaluateJavaScript(u'show_video("currentTime");') # check if conversion was ok and value is not 'NaN' - if ok and currentTime != float('inf'): + if currentTime and currentTime != float('inf'): currentTime = int(currentTime * 1000) - (length, ok) = display.frame.evaluateJavaScript(u'show_video("length");') + length = display.frame.evaluateJavaScript(u'show_video("length");') # check if conversion was ok and value is not 'NaN' - if ok and length != float('inf'): + if length and length != float('inf'): length = int(length * 1000) if currentTime > 0: controller.media_info.length = length diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index d7512561b..c757f14d0 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -39,8 +39,8 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, \ - translate, str_to_bool, check_directory_exists, Settings, PluginStatus, UiStrings +from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, SettingsManager, \ + translate, str_to_bool, check_directory_exists, Settings, PluginStatus, Registry, UiStrings from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm @@ -98,26 +98,26 @@ class ServiceManager(QtGui.QWidget): the resources used into one OSZ or oszl file for use on any OpenLP v2 installation. Also handles the UI tasks of moving things up and down etc. """ - def __init__(self, mainwindow, parent=None): + def __init__(self, parent=None): """ Sets up the service manager, toolbars, list view, et al. """ QtGui.QWidget.__init__(self, parent) self.active = build_icon(QtGui.QImage(u':/media/auto-start_active.png')) self.inactive = build_icon(QtGui.QImage(u':/media/auto-start_inactive.png')) - self.mainwindow = mainwindow + Registry().register(u'service_manager', self) self.serviceItems = [] self.suffixes = [] self.dropPosition = 0 self.expandTabs = False - self.serviceId = 0 + self.service_id = 0 # is a new service and has not been saved self._modified = False self._fileName = u'' self.service_has_all_original_files = True - self.serviceNoteForm = ServiceNoteForm(self.mainwindow) - self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow) - self.startTimeForm = StartTimeForm(self.mainwindow) + self.serviceNoteForm = ServiceNoteForm(self.main_window) + self.serviceItemEditForm = ServiceItemEditForm(self.main_window) + self.startTimeForm = StartTimeForm(self.main_window) # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -165,8 +165,7 @@ class ServiceManager(QtGui.QWidget): # Add the bottom toolbar self.orderToolbar = OpenLPToolbar(self) action_list = ActionList.get_instance() - action_list.add_category( - UiStrings().Service, CategoryOrder.standardToolbar) + action_list.add_category(UiStrings().Service, CategoryOrder.standardToolbar) self.serviceManagerList.moveTop = self.orderToolbar.addToolbarAction(u'moveTop', text=translate('OpenLP.ServiceManager', 'Move to &top'), icon=u':/services/service_top.png', tooltip=translate('OpenLP.ServiceManager', 'Move item to the top of the service.'), @@ -231,7 +230,7 @@ class ServiceManager(QtGui.QWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.themeChange) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate) # Last little bits of setting up - self.service_theme = Settings().value(self.mainwindow.serviceManagerSettingsSection + u'/service theme') + self.service_theme = Settings().value(self.main_window.serviceManagerSettingsSection + u'/service theme') self.servicePath = AppLocation.get_section_data_path(u'servicemanager') # build the drag and drop context menu self.dndMenu = QtGui.QMenu() @@ -297,10 +296,10 @@ class ServiceManager(QtGui.QWidget): has been modified. """ if modified: - self.serviceId += 1 + self.service_id += 1 self._modified = modified serviceFile = self.shortFileName() or translate('OpenLP.ServiceManager', 'Untitled Service') - self.mainwindow.setServiceModified(modified, serviceFile) + self.main_window.setServiceModified(modified, serviceFile) def isModified(self): """ @@ -313,8 +312,7 @@ class ServiceManager(QtGui.QWidget): Setter for service file. """ self._fileName = unicode(fileName) - self.mainwindow.setServiceModified(self.isModified(), - self.shortFileName()) + self.main_window.setServiceModified(self.isModified(), self.shortFileName()) Settings().setValue(u'servicemanager/last file', fileName) self._saveLite = self._fileName.endswith(u'.oszl') @@ -382,25 +380,32 @@ class ServiceManager(QtGui.QWidget): elif result == QtGui.QMessageBox.Save: self.decideSaveMethod() if not loadFile: - fileName = QtGui.QFileDialog.getOpenFileName(self.mainwindow, + fileName = QtGui.QFileDialog.getOpenFileName(self.main_window, translate('OpenLP.ServiceManager', 'Open File'), - Settings().value(self.mainwindow.serviceManagerSettingsSection + u'/last directory'), - translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)')) + SettingsManager.get_last_dir(self.main_window.serviceManagerSettingsSection), + translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)')) if not fileName: return False else: fileName = loadFile - Settings().setValue(self.mainwindow.serviceManagerSettingsSection + u'/last directory', split_filename(fileName)[0]) + Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory', + split_filename(fileName)[0]) self.loadFile(fileName) def saveModifiedService(self): - return QtGui.QMessageBox.question(self.mainwindow, + """ + Check to see if a service needs to be saved. + """ + return QtGui.QMessageBox.question(self.main_window, translate('OpenLP.ServiceManager', 'Modified Service'), translate('OpenLP.ServiceManager', 'The current service has been modified. Would you like to save this service?'), QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) def onRecentServiceClicked(self): + """ + Load a recent file as the service triggered by mainwindow recent service list. + """ sender = self.sender() self.loadFile(sender.data()) @@ -411,7 +416,7 @@ class ServiceManager(QtGui.QWidget): self.serviceManagerList.clear() self.serviceItems = [] self.setFileName(u'') - self.serviceId += 1 + self.service_id += 1 self.setModified(False) Settings().setValue(u'servicemanager/last file', u'') Receiver.send_message(u'servicemanager_new_service') @@ -436,7 +441,7 @@ class ServiceManager(QtGui.QWidget): basename = os.path.splitext(file_name)[0] service_file_name = '%s.osd' % basename log.debug(u'ServiceManager.saveFile - %s', path_file_name) - Settings().setValue(self.mainwindow.serviceManagerSettingsSection + u'/last directory', path) + Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory', path) service = [] write_list = [] missing_list = [] @@ -444,7 +449,7 @@ class ServiceManager(QtGui.QWidget): total_size = 0 Receiver.send_message(u'cursor_busy') # Number of items + 1 to zip it - self.mainwindow.displayProgressBar(len(self.serviceItems) + 1) + self.main_window.displayProgressBar(len(self.serviceItems) + 1) # Get list of missing files, and list of files to write for item in self.serviceItems: if not item[u'service_item'].uses_file(): @@ -466,50 +471,48 @@ class ServiceManager(QtGui.QWidget): answer = QtGui.QMessageBox.critical(self, title, message, QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)) if answer == QtGui.QMessageBox.Cancel: - self.mainwindow.finishedProgressBar() + self.main_window.finishedProgressBar() return False Receiver.send_message(u'cursor_busy') # Check if item contains a missing file. for item in list(self.serviceItems): - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() item[u'service_item'].remove_invalid_frames(missing_list) if item[u'service_item'].missing_frames(): self.serviceItems.remove(item) else: service_item = item[u'service_item'].get_service_repr(self._saveLite) if service_item[u'header'][u'background_audio']: - for i, filename in enumerate( - service_item[u'header'][u'background_audio']): - new_file = os.path.join(u'audio', - item[u'service_item']._uuid, filename) + for i, filename in enumerate(service_item[u'header'][u'background_audio']): + new_file = os.path.join(u'audio', item[u'service_item'].unique_identifier, filename) audio_files.append((filename, new_file)) service_item[u'header'][u'background_audio'][i] = new_file # Add the service item to the service. service.append({u'serviceitem': service_item}) self.repaintServiceList(-1, -1) - for file in write_list: - file_size = os.path.getsize(file) + for file_item in write_list: + file_size = os.path.getsize(file_item) total_size += file_size - log.debug(u'ServiceManager.saveFile - ZIP contents size is %i bytes' % total_size) + log.debug(u'ServiceManager.savefile - ZIP contents size is %i bytes' % total_size) service_content = cPickle.dumps(service) # Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be # extracted using unzip in UNIX. allow_zip_64 = (total_size > 2147483648 + len(service_content)) log.debug(u'ServiceManager.saveFile - allowZip64 is %s' % allow_zip_64) - zip = None + zip_file = None success = True - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() try: - zip = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, allow_zip_64) + zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, allow_zip_64) # First we add service contents. # We save ALL filenames into ZIP using UTF-8. - zip.writestr(service_file_name.encode(u'utf-8'), service_content) + zip_file.writestr(service_file_name.encode(u'utf-8'), service_content) # Finally add all the listed media files. for write_from in write_list: - zip.write(write_from, write_from.encode(u'utf-8')) + zip_file.write(write_from, write_from.encode(u'utf-8')) for audio_from, audio_to in audio_files: if audio_from.startswith(u'audio'): - # When items are saved, they get new UUID's. Let's copy the + # When items are saved, they get new unique_identifier. Let's copy the # file to the new location. Unused files can be ignored, # OpenLP automatically cleans up the service manager dir on # exit. @@ -519,7 +522,7 @@ class ServiceManager(QtGui.QWidget): check_directory_exists(save_path) if not os.path.exists(save_file): shutil.copy(audio_from, save_file) - zip.write(audio_from, audio_to.encode(u'utf-8')) + zip_file.write(audio_from, audio_to.encode(u'utf-8')) except IOError: log.exception(u'Failed to save service to disk: %s', temp_file_name) Receiver.send_message(u'openlp_error_message', { @@ -528,28 +531,24 @@ class ServiceManager(QtGui.QWidget): }) success = False finally: - if zip: - zip.close() - self.mainwindow.finishedProgressBar() + if zip_file: + zip_file.close() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') if success: try: shutil.copy(temp_file_name, path_file_name) except: return self.saveFileAs() - self.mainwindow.addRecentFile(path_file_name) + self.main_window.addRecentFile(path_file_name) self.setModified(False) delete_file(temp_file_name) return success def saveLocalFile(self): """ - Save the current service file. - - A temporary file is created so that we don't overwrite the existing one - and leave a mangled service file should there be an error when saving. - No files are added to this version of the service as it is deisgned - to only work on the machine it was save on if there are files. + Save the current service file but leave all the file references alone to point to the current machine. + This format is not transportable as it will not contain any files. """ if not self.fileName(): return self.saveFileAs() @@ -559,29 +558,29 @@ class ServiceManager(QtGui.QWidget): log.debug(temp_file_name) path_file_name = unicode(self.fileName()) path, file_name = os.path.split(path_file_name) - basename = os.path.splitext(file_name)[0] - service_file_name = '%s.osd' % basename + base_name = os.path.splitext(file_name)[0] + service_file_name = '%s.osd' % base_name log.debug(u'ServiceManager.saveFile - %s', path_file_name) - Settings().setValue(self.mainwindow.serviceManagerSettingsSection + u'/last directory', path) + Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory', path) service = [] Receiver.send_message(u'cursor_busy') # Number of items + 1 to zip it - self.mainwindow.displayProgressBar(len(self.serviceItems) + 1) + self.main_window.displayProgressBar(len(self.serviceItems) + 1) for item in self.serviceItems: - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() service_item = item[u'service_item'].get_service_repr(self._saveLite) #@todo check for file item on save. service.append({u'serviceitem': service_item}) - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() service_content = cPickle.dumps(service) - zip = None + zip_file = None success = True - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() try: - zip = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, + zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, True) # First we add service contents. - zip.writestr(service_file_name.encode(u'utf-8'), service_content) + zip_file.writestr(service_file_name.encode(u'utf-8'), service_content) except IOError: log.exception(u'Failed to save service to disk: %s', temp_file_name) Receiver.send_message(u'openlp_error_message', { @@ -590,16 +589,16 @@ class ServiceManager(QtGui.QWidget): }) success = False finally: - if zip: - zip.close() - self.mainwindow.finishedProgressBar() + if zip_file: + zip_file.close() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') if success: try: shutil.copy(temp_file_name, path_file_name) except: return self.saveFileAs() - self.mainwindow.addRecentFile(path_file_name) + self.main_window.addRecentFile(path_file_name) self.setModified(False) delete_file(temp_file_name) return success @@ -627,16 +626,16 @@ class ServiceManager(QtGui.QWidget): default_filename = format_time(default_pattern, local_time) else: default_filename = u'' - directory = Settings().value(self.mainwindow.serviceManagerSettingsSection + u'/last directory') + directory = Settings().value(self.main_window.serviceManagerSettingsSection + u'/last directory') path = os.path.join(directory, default_filename) # SaveAs from osz to oszl is not valid as the files will be deleted # on exit which is not sensible or usable in the long term. if self._fileName.endswith(u'oszl') or self.service_has_all_original_files: - fileName = QtGui.QFileDialog.getSaveFileName(self.mainwindow, UiStrings().SaveService, path, + fileName = QtGui.QFileDialog.getSaveFileName(self.main_window, UiStrings().SaveService, path, translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)')) else: - fileName = QtGui.QFileDialog.getSaveFileName(self.mainwindow, UiStrings().SaveService, path, + fileName = QtGui.QFileDialog.getSaveFileName(self.main_window, UiStrings().SaveService, path, translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz);;')) if not fileName: return False @@ -695,26 +694,25 @@ class ServiceManager(QtGui.QWidget): fileTo.close() self.newFile() self.setFileName(fileName) - self.mainwindow.displayProgressBar(len(items)) + self.main_window.displayProgressBar(len(items)) for item in items: - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() serviceItem = ServiceItem() - serviceItem.renderer = self.mainwindow.renderer if self._saveLite: serviceItem.set_from_service(item) else: serviceItem.set_from_service(item, self.servicePath) serviceItem.validate_item(self.suffixes) - self.load_item_uuid = 0 + self.load_item_unique_identifier = 0 if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate): Receiver.send_message(u'%s_service_load' % serviceItem.name.lower(), serviceItem) # if the item has been processed - if serviceItem._uuid == self.load_item_uuid: + if serviceItem.unique_identifier == self.load_item_unique_identifier: serviceItem.edit_id = int(self.load_item_edit_id) serviceItem.temporary_edit = self.load_item_temporary self.addServiceItem(serviceItem, repaint=False) delete_file(p_file) - self.mainwindow.addRecentFile(fileName) + self.main_window.addRecentFile(fileName) self.setModified(False) Settings().setValue('servicemanager/last file', fileName) else: @@ -741,7 +739,7 @@ class ServiceManager(QtGui.QWidget): fileTo.close() if zip: zip.close() - self.mainwindow.finishedProgressBar() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') self.repaintServiceList(-1, -1) @@ -756,6 +754,9 @@ class ServiceManager(QtGui.QWidget): self.loadFile(fileName) def contextMenu(self, point): + """ + The Right click context menu from the Serviceitem list + """ item = self.serviceManagerList.itemAt(point) if item is None: return @@ -777,15 +778,13 @@ class ServiceManager(QtGui.QWidget): if item.parent() is None: self.notesAction.setVisible(True) if serviceItem[u'service_item'].is_capable(ItemCapabilities.CanLoop) and \ - len(serviceItem[u'service_item'].get_frames()) > 1: + len(serviceItem[u'service_item'].get_frames()) > 1: self.autoPlaySlidesGroup.menuAction().setVisible(True) self.autoPlaySlidesOnce.setChecked(serviceItem[u'service_item'].auto_play_slides_once) self.autoPlaySlidesLoop.setChecked(serviceItem[u'service_item'].auto_play_slides_loop) self.timedSlideInterval.setChecked(serviceItem[u'service_item'].timed_slide_interval > 0) if serviceItem[u'service_item'].timed_slide_interval > 0: - delay_suffix = u' ' - delay_suffix += unicode(serviceItem[u'service_item'].timed_slide_interval) - delay_suffix += u' s' + delay_suffix = u' %s s' % unicode(serviceItem[u'service_item'].timed_slide_interval) else: delay_suffix = u' ...' self.timedSlideInterval.setText(translate('OpenLP.ServiceManager', '&Delay between slides') + delay_suffix) @@ -802,13 +801,13 @@ class ServiceManager(QtGui.QWidget): self.autoStartAction.setText(translate('OpenLP.ServiceManager', '&Auto Start - active')) self.autoStartAction.setIcon(self.active) if serviceItem[u'service_item'].is_text(): - for plugin in self.mainwindow.pluginManager.plugins: + for plugin in self.plugin_manager.plugins: if plugin.name == u'custom' and plugin.status == PluginStatus.Active: self.create_custom_action.setVisible(True) break self.themeMenu.menuAction().setVisible(False) # Set up the theme menu. - if serviceItem[u'service_item'].is_text() and self.mainwindow.renderer.theme_level == ThemeLevel.Song: + if serviceItem[u'service_item'].is_text() and self.renderer.theme_level == ThemeLevel.Song: self.themeMenu.menuAction().setVisible(True) # The service item does not have a theme, check the "Default". if serviceItem[u'service_item'].theme is None: @@ -884,8 +883,8 @@ class ServiceManager(QtGui.QWidget): timed_slide_interval, 0, 180, 1) if ok: service_item.timed_slide_interval = timed_slide_interval - if service_item.timed_slide_interval <> 0 and not service_item.auto_play_slides_loop\ - and not service_item.auto_play_slides_once: + if service_item.timed_slide_interval != 0 and not service_item.auto_play_slides_loop \ + and not service_item.auto_play_slides_once: service_item.auto_play_slides_loop = True elif service_item.timed_slide_interval == 0: service_item.auto_play_slides_loop = False @@ -917,9 +916,9 @@ class ServiceManager(QtGui.QWidget): Called by the SlideController to request a preview item be made live and allows the next preview to be updated if relevant. """ - uuid, row = message.split(u':') + unique_identifier, row = message.split(u':') for sitem in self.serviceItems: - if sitem[u'service_item']._uuid == uuid: + if sitem[u'service_item'].unique_identifier == unique_identifier: item = self.serviceManagerList.topLevelItem(sitem[u'order'] - 1) self.serviceManagerList.setCurrentItem(item) self.makeLive(int(row)) @@ -1122,7 +1121,7 @@ class ServiceManager(QtGui.QWidget): self.service_has_all_original_files = False # Repaint the screen self.serviceManagerList.clear() - for itemcount, item in enumerate(self.serviceItems): + for item_count, item in enumerate(self.serviceItems): serviceitem = item[u'service_item'] treewidgetitem = QtGui.QTreeWidgetItem(self.serviceManagerList) if serviceitem.is_valid: @@ -1171,7 +1170,7 @@ class ServiceManager(QtGui.QWidget): text = frame[u'title'].replace(u'\n', u' ') child.setText(0, text[:40]) child.setData(0, QtCore.Qt.UserRole, count) - if serviceItem == itemcount: + if serviceItem == item_count: if item[u'expanded'] and serviceItemChild == count: self.serviceManagerList.setCurrentItem(child) elif serviceItemChild == -1: @@ -1195,8 +1194,8 @@ class ServiceManager(QtGui.QWidget): """ log.debug(u'onThemeComboBoxSelected') self.service_theme = self.themeComboBox.currentText() - self.mainwindow.renderer.set_service_theme(self.service_theme) - Settings().setValue(self.mainwindow.serviceManagerSettingsSection + u'/service theme', self.service_theme) + self.renderer.set_service_theme(self.service_theme) + Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/service theme', self.service_theme) self.regenerateServiceItems(True) def themeChange(self): @@ -1205,7 +1204,7 @@ class ServiceManager(QtGui.QWidget): sure the theme combo box is in the correct state. """ log.debug(u'themeChange') - visible = self.mainwindow.renderer.theme_level == ThemeLevel.Global + visible = self.renderer.theme_level == ThemeLevel.Global self.themeLabel.setVisible(visible) self.themeComboBox.setVisible(visible) @@ -1253,7 +1252,7 @@ class ServiceManager(QtGui.QWidget): Triggered from plugins to update service items. Save the values as they will be used as part of the service load """ - edit_id, self.load_item_uuid, temporary = message.split(u':') + edit_id, self.load_item_unique_identifier, temporary = message.split(u':') self.load_item_edit_id = int(edit_id) self.load_item_temporary = str_to_bool(temporary) @@ -1262,13 +1261,13 @@ class ServiceManager(QtGui.QWidget): Using the service item passed replace the one with the same edit id if found. """ - for itemcount, item in enumerate(self.serviceItems): + for item_count, item in enumerate(self.serviceItems): if item[u'service_item'].edit_id == newItem.edit_id and item[u'service_item'].name == newItem.name: newItem.render() newItem.merge(item[u'service_item']) item[u'service_item'] = newItem - self.repaintServiceList(itemcount + 1, 0) - self.mainwindow.liveController.replaceServiceManagerItem(newItem) + self.repaintServiceList(item_count + 1, 0) + self.live_controller.replaceServiceManagerItem(newItem) self.setModified() def addServiceItem(self, item, rebuild=False, expand=None, replace=False, repaint=True, selected=False): @@ -1290,7 +1289,7 @@ class ServiceManager(QtGui.QWidget): item.merge(self.serviceItems[sitem][u'service_item']) self.serviceItems[sitem][u'service_item'] = item self.repaintServiceList(sitem, child) - self.mainwindow.liveController.replaceServiceManagerItem(item) + self.live_controller.replaceServiceManagerItem(item) else: item.render() # nothing selected for dnd @@ -1313,7 +1312,7 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(self.dropPosition, -1) # if rebuilding list make sure live is fixed. if rebuild: - self.mainwindow.liveController.replaceServiceManagerItem(item) + self.live_controller.replaceServiceManagerItem(item) self.dropPosition = 0 self.setModified() @@ -1324,8 +1323,7 @@ class ServiceManager(QtGui.QWidget): Receiver.send_message(u'cursor_busy') item, child = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.mainwindow.previewController.addServiceManagerItem( - self.serviceItems[item][u'service_item'], child) + self.preview_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], child) else: critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', @@ -1365,16 +1363,15 @@ class ServiceManager(QtGui.QWidget): child = row Receiver.send_message(u'cursor_busy') if self.serviceItems[item][u'service_item'].is_valid: - self.mainwindow.liveController.addServiceManagerItem( - self.serviceItems[item][u'service_item'], child) - if Settings().value(self.mainwindow.generalSettingsSection + u'/auto preview'): + self.live_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], child) + if Settings().value(self.main_window.generalSettingsSection + u'/auto preview'): item += 1 if self.serviceItems and item < len(self.serviceItems) and \ self.serviceItems[item][u'service_item'].is_capable(ItemCapabilities.CanPreview): - self.mainwindow.previewController.addServiceManagerItem(self.serviceItems[item][u'service_item'], 0) + self.preview_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], 0) next_item = self.serviceManagerList.topLevelItem(item) self.serviceManagerList.setCurrentItem(next_item) - self.mainwindow.liveController.previewListWidget.setFocus() + self.live_controller.previewListWidget.setFocus() else: critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', @@ -1410,11 +1407,11 @@ class ServiceManager(QtGui.QWidget): serviceItem = -1 serviceItemChild = -1 for item in items: - parentitem = item.parent() - if parentitem is None: + parent_item = item.parent() + if parent_item is None: serviceItem = item.data(0, QtCore.Qt.UserRole) else: - serviceItem = parentitem.data(0, QtCore.Qt.UserRole) + serviceItem = parent_item.data(0, QtCore.Qt.UserRole) serviceItemChild = item.data(0, QtCore.Qt.UserRole) # Adjust for zero based arrays. serviceItem -= 1 @@ -1463,7 +1460,7 @@ class ServiceManager(QtGui.QWidget): if item is None: endpos = len(self.serviceItems) else: - endpos = self._getParentItemData(item) - 1 + endpos = self._get_parent_item_data(item) - 1 serviceItem = self.serviceItems[startpos] self.serviceItems.remove(serviceItem) self.serviceItems.insert(endpos, serviceItem) @@ -1476,21 +1473,21 @@ class ServiceManager(QtGui.QWidget): self.dropPosition = len(self.serviceItems) else: # we are over something so lets investigate - pos = self._getParentItemData(item) - 1 + pos = self._get_parent_item_data(item) - 1 serviceItem = self.serviceItems[pos] if (plugin == serviceItem[u'service_item'].name and serviceItem[u'service_item'].is_capable(ItemCapabilities.CanAppend)): action = self.dndMenu.exec_(QtGui.QCursor.pos()) # New action required if action == self.newAction: - self.dropPosition = self._getParentItemData(item) + self.dropPosition = self._get_parent_item_data(item) # Append to existing action if action == self.addToAction: - self.dropPosition = self._getParentItemData(item) + self.dropPosition = self._get_parent_item_data(item) item.setSelected(True) replace = True else: - self.dropPosition = self._getParentItemData(item) + self.dropPosition = self._get_parent_item_data(item) Receiver.send_message(u'%s_add_service_item' % plugin, replace) def updateThemeList(self, theme_list): @@ -1518,10 +1515,13 @@ class ServiceManager(QtGui.QWidget): themeGroup.addAction(create_widget_action(self.themeMenu, theme, text=theme, checked=False, triggers=self.onThemeChangeAction)) find_and_set_in_combo_box(self.themeComboBox, self.service_theme) - self.mainwindow.renderer.set_service_theme(self.service_theme) + self.renderer.set_service_theme(self.service_theme) self.regenerateServiceItems() def onThemeChangeAction(self): + """ + Handles theme change events + """ theme = self.sender().objectName() # No object name means that the "Default" theme is supposed to be used. if not theme: @@ -1530,16 +1530,69 @@ class ServiceManager(QtGui.QWidget): self.serviceItems[item][u'service_item'].update_theme(theme) self.regenerateServiceItems(True) - def _getParentItemData(self, item): - parentitem = item.parent() - if parentitem is None: + def _get_parent_item_data(self, item): + """ + Finds and returns the parent item for any item + """ + parent_item = item.parent() + if parent_item is None: return item.data(0, QtCore.Qt.UserRole) else: - return parentitem.data(0, QtCore.Qt.UserRole) + return parent_item.data(0, QtCore.Qt.UserRole) def printServiceOrder(self): """ Print a Service Order Sheet. """ - settingDialog = PrintServiceForm(self.mainwindow, self) + settingDialog = PrintServiceForm(self.main_window, self) settingDialog.exec_() + + def _get_renderer(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_renderer'): + self._renderer = Registry().get(u'renderer') + return self._renderer + + renderer = property(_get_renderer) + + def _get_live_controller(self): + """ + Adds the live controller to the class dynamically + """ + if not hasattr(self, u'_live_controller'): + self._live_controller = Registry().get(u'live_controller') + return self._live_controller + + live_controller = property(_get_live_controller) + + def _get_preview_controller(self): + """ + Adds the preview controller to the class dynamically + """ + if not hasattr(self, u'_preview_controller'): + self._preview_controller = Registry().get(u'preview_controller') + return self._preview_controller + + preview_controller = property(_get_preview_controller) + + def _get_plugin_manager(self): + """ + Adds the plugin manager to the class dynamically + """ + if not hasattr(self, u'_plugin_manager'): + self._plugin_manager = Registry().get(u'plugin_manager') + return self._plugin_manager + + plugin_manager = property(_get_plugin_manager) + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) \ No newline at end of file diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 2807f215a..f54bc8729 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -33,7 +33,7 @@ import logging from PyQt4 import QtGui -from openlp.core.lib import Receiver, build_icon, PluginStatus +from openlp.core.lib import Receiver, build_icon, PluginStatus, Registry from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab from openlp.core.ui.media import PlayerTab from settingsdialog import Ui_SettingsDialog @@ -44,21 +44,21 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Provide the form to manipulate the settings for OpenLP """ - def __init__(self, mainWindow, parent=None): + def __init__(self, parent=None): """ Initialise the settings form """ - self.mainWindow = mainWindow + Registry().register(u'settings_form', self) QtGui.QDialog.__init__(self, parent) self.setupUi(self) # General tab self.generalTab = GeneralTab(self) # Themes tab - self.themesTab = ThemesTab(self, mainWindow) + self.themesTab = ThemesTab(self, self.main_window) # Advanced tab self.advancedTab = AdvancedTab(self) # Advanced tab - self.playerTab = PlayerTab(self, mainWindow) + self.playerTab = PlayerTab(self, self.main_window) def exec_(self): # load all the settings @@ -142,3 +142,13 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): if self.resetSuffixes: self.mainWindow.serviceManagerContents.resetSupportedSuffixes() self.resetSuffixes = False + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) \ No newline at end of file diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 4c20970cd..05151b20e 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -35,10 +35,9 @@ from collections import deque from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, translate, build_icon, build_html, \ - PluginManager, ServiceItem, ImageSource, SlideLimits, ServiceItemAction, Settings, ScreenList, UiStrings -from openlp.core.lib.ui import create_action -from openlp.core.lib import SlideLimits, ServiceItemAction + ServiceItem, ImageSource, SlideLimits, ServiceItemAction, Settings, Registry, UiStrings, ScreenList from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType +from openlp.core.lib.ui import create_action from openlp.core.utils.actions import ActionList, CategoryOrder log = logging.getLogger(__name__) @@ -83,8 +82,6 @@ class SlideController(DisplayController): self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height()) except ZeroDivisionError: self.ratio = 1 - self.imageManager = self.parent().imageManager - self.mediaController = self.parent().mediaController self.loopList = [ u'playSlidesMenu', u'loopSeparator', @@ -110,6 +107,7 @@ class SlideController(DisplayController): # Type label for the top of the slide controller self.typeLabel = QtGui.QLabel(self.panel) if self.isLive: + Registry().register(u'live_controller', self) self.typeLabel.setText(UiStrings().Live) self.split = 1 self.typePrefix = u'live' @@ -118,6 +116,7 @@ class SlideController(DisplayController): self.category = UiStrings().LiveToolbar ActionList.get_instance().add_category(unicode(self.category), CategoryOrder.standardToolbar) else: + Registry().register(u'preview_controller', self) self.typeLabel.setText(UiStrings().Preview) self.split = 0 self.typePrefix = u'preview' @@ -231,7 +230,7 @@ class SlideController(DisplayController): tooltip=translate('OpenLP.SlideController', 'Edit and reload song preview.'), triggers=self.onEditSong) self.controllerLayout.addWidget(self.toolbar) # Build the Media Toolbar - self.mediaController.register_controller(self) + self.media_controller.register_controller(self) if self.isLive: # Build the Song Toolbar self.songMenu = QtGui.QToolButton(self.toolbar) @@ -354,8 +353,7 @@ class SlideController(DisplayController): self.setLiveHotkeys(self) self.__addActionsToWidget(self.previewListWidget) else: - self.previewListWidget.addActions( - [self.nextItem, self.previousItem]) + self.previewListWidget.addActions([self.nextItem, self.previousItem]) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix), self.onStopLoop) QtCore.QObject.connect(Receiver.get_receiver(), @@ -450,7 +448,7 @@ class SlideController(DisplayController): def liveEscape(self): self.display.setVisible(False) - self.mediaController.media_stop(self) + self.media_controller.media_stop(self) def toggleDisplay(self, action): """ @@ -507,7 +505,7 @@ class SlideController(DisplayController): # rebuild display as screen size changed if self.display: self.display.close() - self.display = MainDisplay(self, self.imageManager, self.isLive, self) + self.display = MainDisplay(self, self.isLive, self) self.display.setup() if self.isLive: self.__addActionsToWidget(self.display) @@ -517,13 +515,13 @@ class SlideController(DisplayController): self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height()) except ZeroDivisionError: self.ratio = 1 - self.mediaController.setup_display(self.display, False) + self.media_controller.setup_display(self.display, False) self.previewSizeChanged() self.previewDisplay.setup() serviceItem = ServiceItem() self.previewDisplay.webView.setHtml(build_html(serviceItem, self.previewDisplay.screen, None, self.isLive, - plugins=PluginManager.get_instance().plugins)) - self.mediaController.setup_display(self.previewDisplay,True) + plugins=self.plugin_manager.plugins)) + self.media_controller.setup_display(self.previewDisplay,True) if self.serviceItem: self.refreshServiceItem() @@ -773,9 +771,9 @@ class SlideController(DisplayController): else: # If current slide set background to image if framenumber == slideno: - self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes(frame[u'path'], + self.serviceItem.bg_image_bytes = self.image_manager.getImageBytes(frame[u'path'], ImageSource.ImagePlugin) - image = self.imageManager.getImage(frame[u'path'], ImageSource.ImagePlugin) + image = self.image_manager.getImage(frame[u'path'], ImageSource.ImagePlugin) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * (1 / self.ratio) @@ -1214,7 +1212,8 @@ class SlideController(DisplayController): row = self.previewListWidget.currentRow() if -1 < row < self.previewListWidget.rowCount(): if self.serviceItem.from_service: - Receiver.send_message('servicemanager_preview_live', u'%s:%s' % (self.serviceItem._uuid, row)) + Receiver.send_message('servicemanager_preview_live', u'%s:%s' % + (self.serviceItem.unique_identifier, row)) else: self.parent().liveController.addServiceManagerItem(self.serviceItem, row) @@ -1223,7 +1222,7 @@ class SlideController(DisplayController): Respond to the arrival of a media service item """ log.debug(u'SlideController onMediaStart') - self.mediaController.video(self.controllerType, item, self.hideMode()) + self.media_controller.video(self.controllerType, item, self.hideMode()) if not self.isLive: self.previewDisplay.show() self.slidePreview.hide() @@ -1233,7 +1232,7 @@ class SlideController(DisplayController): Respond to a request to close the Video """ log.debug(u'SlideController onMediaClose') - self.mediaController.media_reset(self) + self.media_controller.media_reset(self) self.previewDisplay.hide() self.slidePreview.show() @@ -1279,3 +1278,34 @@ class SlideController(DisplayController): def onTrackTriggered(self): action = self.sender() self.display.audioPlayer.goTo(action.data()) + + def _get_plugin_manager(self): + """ + Adds the plugin manager to the class dynamically + """ + if not hasattr(self, u'_plugin_manager'): + self._plugin_manager = Registry().get(u'plugin_manager') + return self._plugin_manager + + plugin_manager = property(_get_plugin_manager) + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) + + def _get_media_controller(self): + """ + Adds the media controller to the class dynamically + """ + if not hasattr(self, u'_media_controller'): + self._media_controller = Registry().get(u'media_controller') + return self._media_controller + + media_controller = property(_get_media_controller) + diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 29d4ddfa0..1c7921121 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -37,7 +37,8 @@ from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, Receiver, SettingsManager, translate, \ - check_item_selected, check_directory_exists, create_thumb, validate_thumb, ImageSource, Settings, UiStrings + check_item_selected, check_directory_exists, create_thumb, validate_thumb, ImageSource, Settings, Registry, \ + UiStrings from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType from openlp.core.lib.ui import critical_error_message_box, create_widget_action from openlp.core.theme import Theme @@ -50,9 +51,9 @@ class ThemeManager(QtGui.QWidget): """ Manages the orders of Theme. """ - def __init__(self, mainwindow, parent=None): + def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) - self.mainwindow = mainwindow + Registry().register(u'theme_manager', self) self.settingsSection = u'themes' self.themeForm = ThemeForm(self) self.fileRenameForm = FileRenameForm(self) @@ -261,11 +262,10 @@ class ThemeManager(QtGui.QWidget): old_theme_data = self.getThemeData(old_theme_name) self.cloneThemeData(old_theme_data, new_theme_name) self.deleteTheme(old_theme_name) - for plugin in self.mainwindow.pluginManager.plugins: + for plugin in self.plugin_manager.plugins: if plugin.usesTheme(old_theme_name): plugin.renameTheme(old_theme_name, new_theme_name) - self.mainwindow.renderer.update_theme( - new_theme_name, old_theme_name) + self.renderer.update_theme(new_theme_name, old_theme_name) self.loadThemes() def onCopyTheme(self): @@ -312,7 +312,7 @@ class ThemeManager(QtGui.QWidget): self.themeForm.theme = theme self.themeForm.exec_(True) self.oldBackgroundImage = None - self.mainwindow.renderer.update_theme(theme.theme_name) + self.renderer.update_theme(theme.theme_name) self.loadThemes() def onDeleteTheme(self): @@ -327,7 +327,7 @@ class ThemeManager(QtGui.QWidget): row = self.themeListWidget.row(item) self.themeListWidget.takeItem(row) self.deleteTheme(theme) - self.mainwindow.renderer.update_theme(theme, only_delete=True) + self.renderer.update_theme(theme, only_delete=True) # As we do not reload the themes, push out the change. Reload the # list as the internal lists and events need to be triggered. self._pushThemes() @@ -474,8 +474,7 @@ class ThemeManager(QtGui.QWidget): Name of the theme to load from file """ log.debug(u'getthemedata for theme %s', theme_name) - xml_file = os.path.join(self.path, unicode(theme_name), - unicode(theme_name) + u'.xml') + xml_file = os.path.join(self.path, unicode(theme_name), unicode(theme_name) + u'.xml') xml = get_text_file_string(xml_file) if not xml: log.debug(u'No theme data - using default theme') @@ -631,9 +630,9 @@ class ThemeManager(QtGui.QWidget): """ self._writeTheme(theme, image_from, image_to) if theme.background_type == BackgroundType.to_string(BackgroundType.Image): - self.mainwindow.imageManager.updateImageBorder(theme.background_filename, + self.image_manager.updateImageBorder(theme.background_filename, ImageSource.Theme, QtGui.QColor(theme.background_border_color)) - self.mainwindow.imageManager.processUpdates() + self.image_manager.processUpdates() def _writeTheme(self, theme, image_from, image_to): """ @@ -680,11 +679,11 @@ class ThemeManager(QtGui.QWidget): """ Called to update the themes' preview images. """ - self.mainwindow.displayProgressBar(len(self.themeList)) + self.main_window.displayProgressBar(len(self.themeList)) for theme in self.themeList: - self.mainwindow.incrementProgressBar() + self.main_window.incrementProgressBar() self.generateAndSaveImage(self.path, theme, self.getThemeData(theme)) - self.mainwindow.finishedProgressBar() + self.main_window.finishedProgressBar() self.loadThemes() def generateImage(self, theme_data, forcePage=False): @@ -698,7 +697,7 @@ class ThemeManager(QtGui.QWidget): Flag to tell message lines per page need to be generated. """ log.debug(u'generateImage \n%s ', theme_data) - return self.mainwindow.renderer.generate_preview(theme_data, forcePage) + return self.renderer.generate_preview(theme_data, forcePage) def getPreviewImage(self, theme): """ @@ -747,7 +746,7 @@ class ThemeManager(QtGui.QWidget): return False # check for use in the system else where. if testPlugin: - for plugin in self.mainwindow.pluginManager.plugins: + for plugin in self.plugin_manager.plugins: if plugin.usesTheme(theme): critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'), translate('OpenLP.ThemeManager', 'Theme %s is used in the %s plugin.') % @@ -805,3 +804,42 @@ class ThemeManager(QtGui.QWidget): new_theme.display_vertical_align = vAlignCorrection return new_theme.extract_xml() + def _get_renderer(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_renderer'): + self._renderer = Registry().get(u'renderer') + return self._renderer + + renderer = property(_get_renderer) + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) + + def _get_plugin_manager(self): + """ + Adds the Renderer to the class dynamically + """ + if not hasattr(self, u'_plugin_manager'): + self._plugin_manager = Registry().get(u'plugin_manager') + return self._plugin_manager + + plugin_manager = property(_get_plugin_manager) + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index d4a9627df..ba5e08c7f 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -459,7 +459,7 @@ def get_uno_instance(resolver): def format_time(text, local_time): """ - Workaround for Python built-in time formatting fuction time.strftime(). + Workaround for Python built-in time formatting function time.strftime(). time.strftime() accepts only ascii characters. This function accepts unicode string and passes individual % placeholders to time.strftime(). diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 1a4e8e411..29727b79d 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -128,8 +128,8 @@ __default_settings__ = { class AlertsPlugin(Plugin): log.info(u'Alerts Plugin loaded') - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'alerts', __default_settings__, plugin_helpers, settings_tab_class=AlertsTab) + def __init__(self): + Plugin.__init__(self, u'alerts', __default_settings__, settings_tab_class=AlertsTab) self.weight = -3 self.iconPath = u':/plugins/plugin_alerts.png' self.icon = build_icon(self.iconPath) @@ -151,7 +151,7 @@ class AlertsPlugin(Plugin): text=translate('AlertsPlugin', '&Alert'), icon=u':/plugins/plugin_alerts.png', statustip=translate('AlertsPlugin', 'Show an alert message.'), visible=False, shortcuts=[u'F7'], triggers=self.onAlertsTrigger) - self.serviceManager.mainwindow.toolsMenu.addAction(self.toolsAlertItem) + self.main_window.toolsMenu.addAction(self.toolsAlertItem) def initialise(self): log.info(u'Alerts Initialising') diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 8af7b3e21..cedb7acfc 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -45,7 +45,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.manager = plugin.manager self.plugin = plugin self.item_id = None - QtGui.QDialog.__init__(self, plugin.formParent) + QtGui.QDialog.__init__(self, self.plugin.main_window) self.setupUi(self) QtCore.QObject.connect(self.displayButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked) QtCore.QObject.connect(self.displayCloseButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayCloseClicked) diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 54ad44227..d24858db5 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -68,8 +68,8 @@ __default_settings__ = { class BiblePlugin(Plugin): log.info(u'Bible Plugin loaded') - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'bibles', __default_settings__, plugin_helpers, BibleMediaItem, BiblesTab) + def __init__(self): + Plugin.__init__(self, u'bibles', __default_settings__, BibleMediaItem, BiblesTab) self.weight = -9 self.iconPath = u':/plugins/plugin_bibles.png' self.icon = build_icon(self.iconPath) @@ -108,7 +108,7 @@ class BiblePlugin(Plugin): """ Plugin.appStartup(self) if self.manager.old_bible_databases: - if QtGui.QMessageBox.information(self.formParent, + if QtGui.QMessageBox.information(self.main_window, translate('OpenLP', 'Information'), translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your existing Bibles.\n' 'Should OpenLP upgrade now?'), @@ -149,7 +149,7 @@ class BiblePlugin(Plugin): Upgrade older bible databases. """ if not hasattr(self, u'upgrade_wizard'): - self.upgrade_wizard = BibleUpgradeForm(self.formParent, self.manager, self) + self.upgrade_wizard = BibleUpgradeForm(self.main_window, self.manager, self) # If the import was not cancelled then reload. if self.upgrade_wizard.exec_(): self.mediaItem.reloadBibles() diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 306265f35..fd1109221 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -479,7 +479,7 @@ class BibleMediaItem(MediaManagerItem): elif self.advancedTab.isVisible(): bible = self.advancedVersionComboBox.currentText() if bible: - self.editBibleForm = EditBibleForm(self, self.plugin.formParent, self.plugin.manager) + self.editBibleForm = EditBibleForm(self, self.main_window, self.plugin.manager) self.editBibleForm.loadBible(bible) if self.editBibleForm.exec_(): self.reloadBibles() diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 116c6454a..d80b8929d 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -60,8 +60,8 @@ class CustomPlugin(Plugin): """ log.info(u'Custom Plugin loaded') - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'custom', __default_settings__, plugin_helpers, CustomMediaItem, CustomTab) + def __init__(self): + Plugin.__init__(self, u'custom', __default_settings__, CustomMediaItem, CustomTab) self.weight = -5 self.manager = Manager(u'custom', init_schema) self.iconPath = u':/plugins/plugin_custom.png' diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index f9b5097ef..b4938e929 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -57,7 +57,7 @@ class CustomMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'custom/custom' MediaManagerItem.__init__(self, parent, plugin, icon) - self.edit_custom_form = EditCustomForm(self, self.plugin.formParent, self.plugin.manager) + self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager) self.singleServiceItem = False self.quickPreviewAllowed = True self.hasSearch = True @@ -256,7 +256,7 @@ class CustomMediaItem(MediaManagerItem): and_(CustomSlide.title == item.title, CustomSlide.theme_name == item.theme, CustomSlide.credits == item.raw_footer[0][len(item.title) + 1:])) if custom: - Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item._uuid, False)) + Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item.unique_identifier, False)) else: if self.add_custom_from_service: self.create_from_service_item(item) @@ -286,7 +286,7 @@ class CustomMediaItem(MediaManagerItem): self.plugin.manager.save_object(custom) self.onSearchTextButtonClicked() if item.name.lower() == u'custom': - Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item._uuid, False)) + Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item.unique_identifier, False)) def onClearTextButtonClick(self): """ diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index d46fabb9d..11e542e60 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -45,8 +45,8 @@ __default_settings__ = { class ImagePlugin(Plugin): log.info(u'Image Plugin loaded') - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'images', __default_settings__, plugin_helpers, ImageMediaItem, ImageTab) + def __init__(self): + Plugin.__init__(self, u'images', __default_settings__, ImageMediaItem, ImageTab) self.weight = -7 self.iconPath = u':/plugins/plugin_images.png' self.icon = build_icon(self.iconPath) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 7d864c33b..092103c86 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -100,22 +100,22 @@ class ImageMediaItem(MediaManagerItem): row_list = [item.row() for item in self.listView.selectedIndexes()] row_list.sort(reverse=True) Receiver.send_message(u'cursor_busy') - self.plugin.formParent.displayProgressBar(len(row_list)) + self.main_window.displayProgressBar(len(row_list)) for row in row_list: text = self.listView.item(row) if text: delete_file(os.path.join(self.servicePath, text.text())) self.listView.takeItem(row) - self.plugin.formParent.incrementProgressBar() - Settings().setValue(self.settingsSection + u'/images files', self.getFileList()) - self.plugin.formParent.finishedProgressBar() + self.main_window.incrementProgressBar() + SettingsManager.setValue(self.settingsSection + u'/images files', self.getFileList()) + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') self.listView.blockSignals(False) def loadList(self, images, initialLoad=False): if not initialLoad: Receiver.send_message(u'cursor_busy') - self.plugin.formParent.displayProgressBar(len(images)) + self.main_window.displayProgressBar(len(images)) # Sort the images by its filename considering language specific # characters. images.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1]) @@ -135,9 +135,9 @@ class ImageMediaItem(MediaManagerItem): item_name.setData(QtCore.Qt.UserRole, imageFile) self.listView.addItem(item_name) if not initialLoad: - self.plugin.formParent.incrementProgressBar() + self.main_window.incrementProgressBar() if not initialLoad: - self.plugin.formParent.finishedProgressBar() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') def generateSlideData(self, service_item, item=None, xmlVersion=False, diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index c8bba1022..443087a09 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -64,14 +64,14 @@ class MediaMediaItem(MediaManagerItem): self.mediaObject = None self.displayController = DisplayController(parent) self.displayController.controllerLayout = QtGui.QVBoxLayout() - self.plugin.mediaController.register_controller(self.displayController) - self.plugin.mediaController.set_controls_visible(self.displayController, False) + self.media_controller.register_controller(self.displayController) + self.media_controller.set_controls_visible(self.displayController, False) self.displayController.previewDisplay = Display(self.displayController, False, self.displayController) self.displayController.previewDisplay.hide() self.displayController.previewDisplay.setGeometry(QtCore.QRect(0, 0, 300, 300)) self.displayController.previewDisplay.screen = {u'size':self.displayController.previewDisplay.geometry()} self.displayController.previewDisplay.setup() - self.plugin.mediaController.setup_display(self.displayController.previewDisplay, False) + self.media_controller.setup_display(self.displayController.previewDisplay, False) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'video_background_replaced'), self.videobackgroundReplaced) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.rebuild_players) @@ -131,7 +131,7 @@ class MediaMediaItem(MediaManagerItem): """ Called to reset the Live background with the media selected, """ - self.plugin.liveController.mediaController.media_reset(self.plugin.liveController) + self.live_controller.mediaController.media_reset(self.plugin.liveController) self.resetAction.setVisible(False) def videobackgroundReplaced(self): @@ -154,7 +154,7 @@ class MediaMediaItem(MediaManagerItem): service_item.shortname = service_item.title (path, name) = os.path.split(filename) service_item.add_from_command(path, name,CLAPPERBOARD) - if self.plugin.liveController.mediaController.video(DisplayControllerType.Live, service_item, + if self.live_controller.mediaController.video(DisplayControllerType.Live, service_item, videoBehindText=True): self.resetAction.setVisible(True) else: @@ -186,7 +186,7 @@ class MediaMediaItem(MediaManagerItem): # Only get start and end times if going to a service if context == ServiceItemContext.Service: # Start media and obtain the length - if not self.plugin.mediaController.media_length(service_item): + if not self.media_controller.media_length(service_item): return False service_item.add_capability(ItemCapabilities.CanAutoStartForLive) service_item.add_capability(ItemCapabilities.RequiresMedia) @@ -212,11 +212,11 @@ class MediaMediaItem(MediaManagerItem): """ self.populateDisplayTypes() self.onNewFileMasks = translate('MediaPlugin.MediaItem', 'Videos (%s);;Audio (%s);;%s (*)') % ( - u' '.join(self.plugin.mediaController.video_extensions_list), - u' '.join(self.plugin.mediaController.audio_extensions_list), UiStrings().AllFiles) + u' '.join(self.media_controller.video_extensions_list), + u' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles) def displaySetup(self): - self.plugin.mediaController.setup_display(self.displayController.previewDisplay, False) + self.media_controller.setup_display(self.displayController.previewDisplay, False) def populateDisplayTypes(self): """ @@ -228,7 +228,7 @@ class MediaMediaItem(MediaManagerItem): self.displayTypeComboBox.blockSignals(True) self.displayTypeComboBox.clear() usedPlayers, overridePlayer = get_media_players() - mediaPlayers = self.plugin.mediaController.mediaPlayers + mediaPlayers = self.media_controller.mediaPlayers currentIndex = 0 for player in usedPlayers: # load the drop down selection @@ -270,7 +270,7 @@ class MediaMediaItem(MediaManagerItem): elif track_info.isFile(): filename = os.path.split(unicode(track))[1] item_name = QtGui.QListWidgetItem(filename) - if u'*.%s' % (filename.split(u'.')[-1].lower()) in self.plugin.mediaController.audio_extensions_list: + if u'*.%s' % (filename.split(u'.')[-1].lower()) in self.media_controller.audio_extensions_list: item_name.setIcon(AUDIO) else: item_name.setIcon(VIDEO) @@ -288,9 +288,9 @@ class MediaMediaItem(MediaManagerItem): media.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1]) ext = [] if type == MediaType.Audio: - ext = self.plugin.mediaController.audio_extensions_list + ext = self.media_controller.audio_extensions_list else: - ext = self.plugin.mediaController.video_extensions_list + ext = self.media_controller.video_extensions_list ext = map(lambda x: x[1:], ext) media = filter(lambda x: os.path.splitext(x)[1] in ext, media) return media diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index e1468cccf..d93f120ec 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -31,7 +31,7 @@ import logging from PyQt4 import QtCore -from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings +from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings, Registry from openlp.plugins.media.lib import MediaMediaItem, MediaTab log = logging.getLogger(__name__) @@ -46,8 +46,8 @@ __default_settings__ = { class MediaPlugin(Plugin): log.info(u'%s MediaPlugin loaded', __name__) - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'media', __default_settings__, plugin_helpers, MediaMediaItem) + def __init__(self): + Plugin.__init__(self, u'media', __default_settings__, MediaMediaItem) self.weight = -6 self.iconPath = u':/plugins/plugin_media.png' self.icon = build_icon(self.iconPath) @@ -97,26 +97,26 @@ class MediaPlugin(Plugin): Time to tidy up on exit """ log.info(u'Media Finalising') - self.mediaController.finalise() + self.media_controller.finalise() Plugin.finalise(self) def getDisplayCss(self): """ Add css style sheets to htmlbuilder """ - return self.mediaController.get_media_display_css() + return self.media_controller.get_media_display_css() def getDisplayJavaScript(self): """ Add javascript functions to htmlbuilder """ - return self.mediaController.get_media_display_javascript() + return self.media_controller.get_media_display_javascript() def getDisplayHtml(self): """ Add html code to htmlbuilder """ - return self.mediaController.get_media_display_html() + return self.media_controller.get_media_display_html() def appStartup(self): """ @@ -129,7 +129,7 @@ class MediaPlugin(Plugin): settings.beginGroup(self.settingsSection) if settings.contains(u'use phonon'): log.info(u'Found old Phonon setting') - players = self.mediaController.mediaPlayers.keys() + players = self.media_controller.mediaPlayers.keys() has_phonon = u'phonon' in players if settings.value(u'use phonon') and has_phonon: log.debug(u'Converting old setting to new setting') @@ -137,8 +137,18 @@ class MediaPlugin(Plugin): if players: new_players = [player for player in players if player != u'phonon'] new_players.insert(0, u'phonon') - self.mediaController.mediaPlayers[u'phonon'].isActive = True + self.media_controller.mediaPlayers[u'phonon'].isActive = True settings.setValue(u'players', u','.join(new_players)) self.settingsTab.load() settings.remove(u'use phonon') settings.endGroup() + + def _get_media_controller(self): + """ + Adds the media controller to the class dynamically + """ + if not hasattr(self, u'_media_controller'): + self._media_controller = Registry().get(u'media_controller') + return self._media_controller + + media_controller = property(_get_media_controller) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 94ba4dad3..fe533a791 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -153,13 +153,13 @@ class PresentationMediaItem(MediaManagerItem): Receiver.send_message(u'cursor_busy') if not initialLoad: Receiver.send_message(u'cursor_busy') - self.plugin.formParent.displayProgressBar(len(files)) + self.main_window.displayProgressBar(len(files)) # Sort the presentations by its filename considering language specific characters. files.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1]) for file in files: if not initialLoad: - self.plugin.formParent.incrementProgressBar() + self.main_window.incrementProgressBar() if currlist.count(file) > 0: continue filename = os.path.split(unicode(file))[1] @@ -208,7 +208,7 @@ class PresentationMediaItem(MediaManagerItem): self.listView.addItem(item_name) Receiver.send_message(u'cursor_normal') if not initialLoad: - self.plugin.formParent.finishedProgressBar() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') def onDeleteClick(self): @@ -220,15 +220,15 @@ class PresentationMediaItem(MediaManagerItem): row_list = [item.row() for item in items] row_list.sort(reverse=True) Receiver.send_message(u'cursor_busy') - self.plugin.formParent.displayProgressBar(len(row_list)) + self.main_window.displayProgressBar(len(row_list)) for item in items: filepath = unicode(item.data(QtCore.Qt.UserRole)) for cidx in self.controllers: doc = self.controllers[cidx].add_document(filepath) doc.presentation_deleted() doc.close_presentation() - self.plugin.formParent.incrementProgressBar() - self.plugin.formParent.finishedProgressBar() + self.main_window.incrementProgressBar() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') for row in row_list: self.listView.takeItem(row) diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 515faa18f..883bb4bb8 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -59,13 +59,13 @@ class PresentationPlugin(Plugin): """ log = logging.getLogger(u'PresentationPlugin') - def __init__(self, plugin_helpers): + def __init__(self): """ PluginPresentation constructor. """ log.debug(u'Initialised') self.controllers = {} - Plugin.__init__(self, u'presentations', __default_settings__, plugin_helpers, __default_settings__) + Plugin.__init__(self, u'presentations', __default_settings__, __default_settings__) self.weight = -8 self.iconPath = u':/plugins/plugin_presentations.png' self.icon = build_icon(self.iconPath) @@ -111,7 +111,7 @@ class PresentationPlugin(Plugin): Create the Media Manager List """ self.mediaItem = PresentationMediaItem( - self.mediaDock.media_dock, self, self.icon, self.controllers) + self.main_window.mediaDockManager.media_dock, self, self.icon, self.controllers) def registerControllers(self, controller): """ diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index aa9fb0235..af12cc9c4 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -252,17 +252,17 @@ class HttpConnection(object): service_items = [] service_manager = self.parent.plugin.serviceManager if self.parent.current_item: - cur_uuid = self.parent.current_item._uuid + current_unique_identifier = self.parent.current_item.unique_identifier else: - cur_uuid = None + current_unique_identifier = None for item in service_manager.serviceItems: service_item = item[u'service_item'] service_items.append({ - u'id': unicode(service_item._uuid), + u'id': unicode(service_item.unique_identifier), u'title': unicode(service_item.get_display_title()), u'plugin': unicode(service_item.name), u'notes': unicode(service_item.notes), - u'selected': (service_item._uuid == cur_uuid) + u'selected': (service_item.unique_identifier == current_unique_identifier) }) return service_items @@ -386,9 +386,9 @@ class HttpConnection(object): Poll OpenLP to determine the current slide number and item name. """ result = { - u'service': self.parent.plugin.serviceManager.serviceId, + u'service': self.parent.plugin.serviceManager.service_id, u'slide': self.parent.current_slide or 0, - u'item': self.parent.current_item._uuid if self.parent.current_item else u'', + u'item': self.parent.current_item.unique_identifier if self.parent.current_item else u'', u'twelve':Settings().value(u'remotes/twelve hour'), u'blank': self.parent.plugin.liveController.blankScreen.isChecked(), u'theme': self.parent.plugin.liveController.themeScreen.isChecked(), @@ -459,7 +459,7 @@ class HttpConnection(object): data.append(item) json_data = {u'results': {u'slides': data}} if current_item: - json_data[u'results'][u'item'] = self.parent.current_item._uuid + json_data[u'results'][u'item'] = self.parent.current_item.unique_identifier else: if self.url_params and self.url_params.get(u'data'): try: diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 5e71ba5b4..160b7d542 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -44,11 +44,11 @@ __default_settings__ = { class RemotesPlugin(Plugin): log.info(u'Remote Plugin loaded') - def __init__(self, plugin_helpers): + def __init__(self): """ remotes constructor """ - Plugin.__init__(self, u'remotes', __default_settings__, plugin_helpers, settings_tab_class=RemoteTab) + Plugin.__init__(self, u'remotes', __default_settings__, settings_tab_class=RemoteTab) self.iconPath = u':/plugins/plugin_remote.png' self.icon = build_icon(self.iconPath) self.weight = -1 diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 83adffb92..5cfd01643 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -39,8 +39,8 @@ import shutil from PyQt4 import QtCore, QtGui from openlp.core.lib import PluginStatus, Receiver, MediaType, translate, create_separated_list, \ - check_directory_exists, UiStrings -from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, \ + check_directory_exists, Registry, UiStrings +from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, critical_error_message_box, \ find_and_set_in_combo_box from openlp.core.utils import AppLocation from openlp.plugins.songs.forms import EditVerseForm, MediaFilesForm @@ -88,8 +88,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.onVerseListViewClicked) QtCore.QObject.connect(self.verseOrderEdit, QtCore.SIGNAL(u'textChanged(QString)'), self.onVerseOrderTextChanged) - QtCore.QObject.connect(self.themeAddButton, QtCore.SIGNAL(u'clicked()'), - self.mediaitem.plugin.renderer.theme_manager.onAddTheme) + QtCore.QObject.connect(self.themeAddButton, QtCore.SIGNAL(u'clicked()'), self.theme_manager.onAddTheme) QtCore.QObject.connect(self.maintenanceButton, QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked) QtCore.QObject.connect(self.audioAddFromFileButton, QtCore.SIGNAL(u'clicked()'), self.onAudioAddFromFileButtonClicked) @@ -909,3 +908,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): except: log.exception(u'Problem processing song Lyrics \n%s', sxml.dump_xml()) + def _get_theme_manager(self): + """ + Adds the theme manager to the class dynamically + """ + if not hasattr(self, u'_theme_manager'): + self._theme_manager = Registry().get(u'theme_manager') + return self._theme_manager + + theme_manager = property(_get_theme_manager) \ No newline at end of file diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index eb0980a75..efadd6b61 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -59,7 +59,7 @@ class SongImportForm(OpenLPWizard): ``plugin`` The songs plugin. """ - self.clipboard = plugin.formParent.clipboard + self.clipboard = self.main_window.clipboard OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp') def setupUi(self, image): diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 644869251..cd23ad731 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -71,8 +71,7 @@ class SongMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'songs/song' MediaManagerItem.__init__(self, parent, plugin, icon) - self.editSongForm = EditSongForm(self, self.plugin.formParent, - self.plugin.manager) + self.editSongForm = EditSongForm(self, self.main_window, self.plugin.manager) self.openLyrics = OpenLyrics(self.plugin.manager) self.singleServiceItem = False self.songMaintenanceForm = SongMaintenanceForm(self.plugin.manager, self) @@ -373,7 +372,7 @@ class SongMediaItem(MediaManagerItem): QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No: return Receiver.send_message(u'cursor_busy') - self.plugin.formParent.displayProgressBar(len(items)) + self.main_window.displayProgressBar(len(items)) for item in items: item_id = item.data(QtCore.Qt.UserRole) media_files = self.plugin.manager.get_all_objects(MediaFile, MediaFile.song_id == item_id) @@ -389,8 +388,8 @@ class SongMediaItem(MediaManagerItem): except OSError: log.exception(u'Could not remove directory: %s', save_path) self.plugin.manager.delete_object(Song, item_id) - self.plugin.formParent.incrementProgressBar() - self.plugin.formParent.finishedProgressBar() + self.main_window.incrementProgressBar() + self.main_window.finishedProgressBar() Receiver.send_message(u'cursor_normal') self.onSearchTextButtonClicked() @@ -538,7 +537,7 @@ class SongMediaItem(MediaManagerItem): temporary = True # Update service with correct song id. if editId: - Receiver.send_message(u'service_item_update%s:%s:%s' % (editId, item._uuid, temporary)) + Receiver.send_message(u'service_item_update%s:%s:%s' % (editId, item.unique_identifier, temporary)) def search(self, string, showError): """ diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index df157ade3..4f57d3e21 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -73,11 +73,11 @@ class SongsPlugin(Plugin): """ log.info(u'Song Plugin loaded') - def __init__(self, plugin_helpers): + def __init__(self): """ Create and set up the Songs plugin. """ - Plugin.__init__(self, u'songs', __default_settings__, plugin_helpers, SongMediaItem, SongsTab) + Plugin.__init__(self, u'songs', __default_settings__, SongMediaItem, SongsTab) self.manager = Manager(u'songs', init_schema, upgrade_mod=upgrade) self.weight = -10 self.iconPath = u':/plugins/plugin_songs.png' @@ -157,7 +157,7 @@ class SongsPlugin(Plugin): if maxSongs == 0: return progressDialog = QtGui.QProgressDialog(translate('SongsPlugin', 'Reindexing songs...'), UiStrings().Cancel, - 0, maxSongs, self.formParent) + 0, maxSongs, self.main_window) progressDialog.setWindowTitle(translate('SongsPlugin', 'Reindexing songs')) progressDialog.setWindowModality(QtCore.Qt.WindowModal) songs = self.manager.get_all_objects(Song) @@ -200,8 +200,7 @@ class SongsPlugin(Plugin): ``newTheme`` The new name the plugin should now use. """ - songsUsingTheme = self.manager.get_all_objects(Song, - Song.theme_name == oldTheme) + songsUsingTheme = self.manager.get_all_objects(Song, Song.theme_name == oldTheme) for song in songsUsingTheme: song.theme_name = newTheme self.manager.save_object(song) @@ -261,7 +260,7 @@ class SongsPlugin(Plugin): if not song_dbs: return Receiver.send_message(u'openlp_process_events') - progress = QtGui.QProgressDialog(self.formParent) + progress = QtGui.QProgressDialog(self.main_window) progress.setWindowModality(QtCore.Qt.WindowModal) progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs')) progress.setLabelText(translate('OpenLP.Ui', 'Starting import...')) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index b39d65ed9..398997715 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -60,8 +60,8 @@ __default_settings__ = { class SongUsagePlugin(Plugin): log.info(u'SongUsage Plugin loaded') - def __init__(self, plugin_helpers): - Plugin.__init__(self, u'songusage', __default_settings__, plugin_helpers) + def __init__(self): + Plugin.__init__(self, u'songusage', __default_settings__) self.manager = Manager(u'songusage', init_schema, upgrade_mod=upgrade) self.weight = -4 self.icon = build_icon(u':/plugins/plugin_songusage.png') @@ -107,12 +107,12 @@ class SongUsagePlugin(Plugin): self.songUsageMenu.addSeparator() self.songUsageMenu.addAction(self.songUsageReport) self.songUsageMenu.addAction(self.songUsageDelete) - self.songUsageActiveButton = QtGui.QToolButton(self.formParent.statusBar) + self.songUsageActiveButton = QtGui.QToolButton(self.main_window.statusBar) self.songUsageActiveButton.setCheckable(True) self.songUsageActiveButton.setAutoRaise(True) self.songUsageActiveButton.setStatusTip(translate('SongUsagePlugin', 'Toggle the tracking of song usage.')) self.songUsageActiveButton.setObjectName(u'songUsageActiveButton') - self.formParent.statusBar.insertPermanentWidget(1, self.songUsageActiveButton) + self.main_window.statusBar.insertPermanentWidget(1, self.songUsageActiveButton) self.songUsageActiveButton.hide() # Signals and slots QtCore.QObject.connect(self.songUsageStatus, QtCore.SIGNAL(u'visibilityChanged(bool)'), @@ -134,8 +134,8 @@ class SongUsagePlugin(Plugin): action_list.add_action(self.songUsageStatus, translate('SongUsagePlugin', 'Song Usage')) action_list.add_action(self.songUsageDelete, translate('SongUsagePlugin', 'Song Usage')) action_list.add_action(self.songUsageReport, translate('SongUsagePlugin', 'Song Usage')) - self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.formParent) - self.songUsageDetailForm = SongUsageDetailForm(self, self.formParent) + self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.main_window) + self.songUsageDetailForm = SongUsageDetailForm(self, self.main_window) self.songUsageMenu.menuAction().setVisible(True) self.songUsageActiveButton.show() diff --git a/tests/functional/openlp_core_lib/test_registry.py b/tests/functional/openlp_core_lib/test_registry.py new file mode 100644 index 000000000..16d0de52a --- /dev/null +++ b/tests/functional/openlp_core_lib/test_registry.py @@ -0,0 +1,38 @@ +""" + Package to test the openlp.core.lib package. +""" +import os + +from unittest import TestCase +from mock import MagicMock +from openlp.core.lib import Registry + +TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources')) + +class TestRegistry(TestCase): + + def registry_basic_test(self): + """ + Test the Service Item basic test + """ + # GIVEN: A new registry + registry = Registry.create() + + # WHEN: I add a service it should save it + mock_1 = MagicMock() + Registry().register(u'test1', mock_1) + + # THEN: we should be able retrieve the saved object + assert Registry().get(u'test1') == mock_1, u'The saved service can be retrieved and matches' + + # WHEN: I add a service for the second time I am mad. + # THEN I will get an exception + with self.assertRaises(KeyError) as context: + Registry().register(u'test1', mock_1) + self.assertEqual(context.exception[0], u'Duplicate service exception test1') + + # WHEN I try to get back a non existent service + # THEN I will get an exception + with self.assertRaises(KeyError) as context: + temp = Registry().get(u'test2') + self.assertEqual(context.exception[0], u'Service test2 not found in list') \ No newline at end of file diff --git a/tests/functional/openlp_core_lib/test_serviceitem.py b/tests/functional/openlp_core_lib/test_serviceitem.py index c2b9aacb1..2b7185370 100644 --- a/tests/functional/openlp_core_lib/test_serviceitem.py +++ b/tests/functional/openlp_core_lib/test_serviceitem.py @@ -2,10 +2,13 @@ Package to test the openlp.core.lib package. """ import os +import cPickle from unittest import TestCase + from mock import MagicMock -from openlp.core.lib import ServiceItem +from openlp.core.lib import ServiceItem, Registry + VERSE = u'The Lord said to {r}Noah{/r}: \n'\ 'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\ @@ -18,11 +21,23 @@ FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456'] TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources')) + class TestServiceItem(TestCase): + def setUp(self): + """ + Set up the Registry + """ + registry = Registry.create() + mocked_renderer = MagicMock() + mocked_image_manager = MagicMock() + mocked_renderer.format_slide.return_value = [VERSE] + Registry().register(u'renderer', mocked_renderer) + Registry().register(u'image_manager', mocked_image_manager) + def serviceitem_basic_test(self): """ - Test the Service Item basic test + Test the Service Item - basic test """ # GIVEN: A new service item @@ -35,7 +50,7 @@ class TestServiceItem(TestCase): def serviceitem_add_text_test(self): """ - Test the Service Item add text test + Test the Service Item - add text test """ # GIVEN: A new service item service_item = ServiceItem(None) @@ -48,11 +63,6 @@ class TestServiceItem(TestCase): assert service_item.is_valid is True, u'The new service item should be valid' assert service_item.missing_frames() is False, u'check frames loaded ' - # GIVEN: A service item with text - mocked_renderer = MagicMock() - mocked_renderer.format_slide.return_value = [VERSE] - service_item.renderer = mocked_renderer - # WHEN: Render called assert len(service_item._display_frames) == 0, u'A blank Service Item with no display frames' service_item.render(True) @@ -63,13 +73,11 @@ class TestServiceItem(TestCase): def serviceitem_add_image_test(self): """ - Test the Service Item add image test + Test the Service Item - add image test """ # GIVEN: A new service item and a mocked renderer service_item = ServiceItem(None) service_item.name = u'test' - mocked_renderer = MagicMock() - service_item.renderer = mocked_renderer # WHEN: adding image to a service item test_image = os.path.join(TESTPATH, u'church.jpg') @@ -120,13 +128,11 @@ class TestServiceItem(TestCase): def serviceitem_add_command_test(self): """ - Test the Service Item add command test + Test the Service Item - add command test """ # GIVEN: A new service item and a mocked renderer service_item = ServiceItem(None) service_item.name = u'test' - mocked_renderer = MagicMock() - service_item.renderer = mocked_renderer # WHEN: adding image to a service item test_file = os.path.join(TESTPATH, u'church.jpg') @@ -154,10 +160,55 @@ class TestServiceItem(TestCase): service_item.validate_item([u'jpg']) # THEN the service item should be valid - assert service_item.is_valid is True, u'The service item is valid' + assert service_item.is_valid is True, u'The service item should be valid' # WHEN validating a service item with a different suffix service_item.validate_item([u'png']) # THEN the service item should not be valid assert service_item.is_valid is False, u'The service item is not valid' + + def serviceitem_load_custom_from_service_test(self): + """ + Test the Service Item - adding a custom slide from a saved service + """ + # GIVEN: A new service item and a mocked add icon function + service_item = ServiceItem(None) + mocked_add_icon = MagicMock() + service_item.add_icon = mocked_add_icon + + # WHEN: adding a custom from a saved Service + line = self.convert_file_service_item(u'serviceitem_custom1.osd') + service_item.set_from_service(line) + + # THEN: We should get back a valid service item + assert service_item.is_valid is True, u'The new service item should be valid' + assert len(service_item._display_frames) == 0, u'The service item has no display frames' + assert len(service_item.capabilities) == 5, u'There are 5 default custom item capabilities' + service_item.render(True) + assert (service_item.get_display_title()) == u'Test Custom', u'The custom title should be correct' + + def serviceitem_load_image_from_service_test(self): + """ + Test the Service Item - adding an image from a saved service + """ + # GIVEN: A new service item and a mocked add icon function + service_item = ServiceItem(None) + mocked_add_icon = MagicMock() + service_item.add_icon = mocked_add_icon + + # WHEN: adding a custom from a saved Service + + # THEN: We should get back a valid service item + assert service_item.is_valid is True, u'The new service item should be valid' + + + def convert_file_service_item(self, name): + service_file = os.path.join(TESTPATH, name) + try: + open_file = open(service_file, u'r') + items = cPickle.load(open_file) + first_line = items[0] + except: + first_line = u'' + return first_line \ No newline at end of file diff --git a/tests/functional/openlp_core_ui/test_starttimedialog.py b/tests/functional/openlp_core_ui/test_starttimedialog.py index 0aed81592..c4b175106 100644 --- a/tests/functional/openlp_core_ui/test_starttimedialog.py +++ b/tests/functional/openlp_core_ui/test_starttimedialog.py @@ -1,13 +1,12 @@ """ -Package to test the openlp.core.ui package. + Package to test the openlp.core.ui package. """ import sys from unittest import TestCase -from mock import MagicMock - +from mock import MagicMock, patch from openlp.core.ui import starttimeform -from PyQt4 import QtCore, QtGui, QtTest +from PyQt4 import QtGui, QtTest class TestStartTimeDialog(TestCase): @@ -48,10 +47,19 @@ class TestStartTimeDialog(TestCase): """ Test StartTimeDialog display initialisation """ - #GIVEN: A service item with with time + # GIVEN: A service item with with time mocked_serviceitem = MagicMock() mocked_serviceitem.start_time = 61 mocked_serviceitem.end_time = 3701 + # WHEN displaying the UI and pressing enter self.form.item = mocked_serviceitem - #self.form.exec_() + with patch(u'openlp.core.lib.QtGui.QDialog') as MockedQtGuiQDialog: + MockedQtGuiQDialog.return_value = True + #does not work yet + #self.form.exec_() + + # THEN the following values are returned + self.assertEqual(self.form.hourSpinBox.value(), 0) + self.assertEqual(self.form.minuteSpinBox.value(), 0) + self.assertEqual(self.form.secondSpinBox.value(), 0) \ No newline at end of file diff --git a/tests/resources/serviceitem_custom1.osd b/tests/resources/serviceitem_custom1.osd new file mode 100644 index 000000000..7f75b39f4 --- /dev/null +++ b/tests/resources/serviceitem_custom1.osd @@ -0,0 +1,96 @@ +(lp1 +(dp2 +Vserviceitem +p3 +(dp4 +Vheader +p5 +(dp6 +Vfooter +p7 +(lp8 +VTest Custom Credits +p9 +asVaudit +p10 +V +sVsearch +p11 +V +sVwill_auto_start +p12 +I00 +sVname +p13 +Vcustom +p14 +sVplugin +p15 +g14 +sVdata +p16 +V +sVnotes +p17 +V +sVtitle +p18 +VTest Custom +p19 +sVfrom_plugin +p20 +I00 +sVcapabilities +p21 +(lp22 +I2 +aI1 +aI5 +aI13 +aI8 +asVmedia_length +p23 +I0 +sVtheme_overwritten +p24 +I00 +sVtheme +p25 +NsVxml_version +p26 +NsVend_time +p27 +I0 +sVbackground_audio +p28 +(lp29 +sVtype +p30 +I1 +sVstart_time +p31 +I0 +sVicon +p32 +V:/plugins/plugin_custom.png +p33 +ssg16 +(lp34 +(dp35 +VverseTag +p36 +NsVraw_slide +p37 +VSlide 1 +p38 +sVtitle +p39 +g38 +sa(dp40 +g36 +Nsg37 +VSlide 2 +p41 +sg39 +g41 +sassa. \ No newline at end of file diff --git a/tests/resources/serviceitem_image1.osd b/tests/resources/serviceitem_image1.osd new file mode 100644 index 000000000..7dfeda2d8 --- /dev/null +++ b/tests/resources/serviceitem_image1.osd @@ -0,0 +1,79 @@ +(lp1 +(dp2 +Vserviceitem +p3 +(dp4 +Vheader +p5 +(dp6 +Vfooter +p7 +(lp8 +sVaudit +p9 +V +sVsearch +p10 +V +sVwill_auto_start +p11 +I00 +sVname +p12 +Vimages +p13 +sVplugin +p14 +g13 +sVdata +p15 +V +sVnotes +p16 +V +sVtitle +p17 +VImages +p18 +sVfrom_plugin +p19 +I00 +sVcapabilities +p20 +(lp21 +I3 +aI1 +aI5 +aI6 +asVmedia_length +p22 +I0 +sVtheme_overwritten +p23 +I00 +sVtheme +p24 +I-1 +sVxml_version +p25 +NsVend_time +p26 +I0 +sVbackground_audio +p27 +(lp28 +sVtype +p29 +I2 +sVstart_time +p30 +I0 +sVicon +p31 +V:/plugins/plugin_images.png +p32 +ssg15 +(lp33 +VIMG_7453.JPG +p34 +assa. \ No newline at end of file