diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index 1b957e5df..2d4134ee3 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -219,6 +219,10 @@ class EventReceiver(QtCore.QObject): ``cursor_normal`` Resets the cursor to default + ``update_display_css`` + CSS has been updated which needs to be changed on the main display. + + """ def __init__(self): """ diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 8e31d8950..863943e40 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -73,13 +73,7 @@ body { #video2 { z-index: 3; } -#alert { - position: absolute; - left: 0px; - top: 0px; - z-index: 10; - %s -} +%s #footer { position: absolute; z-index: 6; @@ -179,7 +173,7 @@ sup { break; } } - + %s function show_image(src){ var img = document.getElementById('image'); img.src = src; @@ -225,34 +219,6 @@ sup { } } - function show_alert(alerttext, position){ - var text = document.getElementById('alert'); - text.innerHTML = alerttext; - if(alerttext == '') { - text.style.visibility = 'hidden'; - return 0; - } - if(position == ''){ - position = getComputedStyle(text, '').verticalAlign; - } - switch(position) - { - case 'top': - text.style.top = '0px'; - break; - case 'middle': - text.style.top = ((window.innerHeight - text.clientHeight) / 2) - + 'px'; - break; - case 'bottom': - text.style.top = (window.innerHeight - text.clientHeight) - + 'px'; - break; - } - text.style.visibility = 'visible'; - return text.clientHeight; - } - function show_footer(footertext){ document.getElementById('footer').innerHTML = footertext; } @@ -316,14 +282,15 @@ sup { %s +%s
- """ -def build_html(item, screen, alert, islive, background, image=None): +def build_html(item, screen, islive, background, image=None, + plugins=None): """ Build the full web paged structure for display @@ -333,9 +300,6 @@ def build_html(item, screen, alert, islive, background, image=None): ``screen`` Current display information - ``alert`` - Alert display display information - ``islive`` Item is going live, rather than preview/theme building @@ -344,6 +308,9 @@ def build_html(item, screen, alert, islive, background, image=None): ``image`` Image media item - bytes + + ``plugins`` + The List of available plugins """ width = screen[u'size'].width() height = screen[u'size'].height() @@ -360,14 +327,24 @@ def build_html(item, screen, alert, islive, background, image=None): image_src = u'src="data:image/png;base64,%s"' % image else: image_src = u'style="display:none;"' + css_additions = u'' + js_additions = u'' + html_additions = u'' + if plugins: + for plugin in plugins: + css_additions += plugin.getDisplayCss() + js_additions += plugin.getDisplayJavaScript() + html_additions += plugin.getDisplayHtml() html = HTMLSRC % (build_background_css(item, width, height), width, height, - build_alert_css(alert, width), + css_additions, build_footer_css(item, height), build_lyrics_css(item, webkitvers), u'true' if theme and theme.display_slide_transition and islive \ else u'false', + js_additions, bgimage_src, image_src, + html_additions, build_lyrics_html(item, webkitvers)) return html diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index db7d4845b..0d925f582 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -369,3 +369,30 @@ class Plugin(QtCore.QObject): """ self.textStrings[name] = {u'title': title, u'tooltip': tooltip} + def getDisplayCss(self): + """ + Add css style sheets to htmlbuilder. + """ + return u'' + + def getDisplayJavaScript(self): + """ + Add javascript functions to htmlbuilder. + """ + return u'' + + def refreshCss(self, frame): + """ + Allow plugins to refresh javascript on displayed screen. + + ``frame`` + The Web frame holding the page. + """ + return u'' + + def getDisplayHtml(self): + """ + Add html code to htmlbuilder. + """ + return u'' + diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 2248d0ddd..277842167 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -42,6 +42,13 @@ class PluginManager(object): """ log.info(u'Plugin manager loaded') + @staticmethod + def get_instance(): + """ + Obtain a single instance of class. + """ + return PluginManager.instance + def __init__(self, plugin_dir): """ The constructor for the plugin manager. Passes the controllers on to @@ -51,6 +58,7 @@ class PluginManager(object): The directory to search for plugins. """ log.info(u'Plugin manager Initialising') + PluginManager.instance = self if not plugin_dir in sys.path: log.debug(u'Inserting %s into sys.path', plugin_dir) sys.path.insert(0, plugin_dir) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 36f911df5..ac2956041 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -35,7 +35,7 @@ from PyQt4 import QtCore, QtGui, QtWebKit from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ - translate + translate, PluginManager from openlp.core.ui import HideMode, ScreenList @@ -56,7 +56,8 @@ class MainDisplay(QtGui.QGraphicsView): self.isLive = live self.imageManager = imageManager self.screens = ScreenList.get_instance() - self.alertTab = None + self.plugins = PluginManager.get_instance().plugins + self.rebuildCSS = False self.hideMode = None self.videoHide = False self.override = {} @@ -80,6 +81,26 @@ class MainDisplay(QtGui.QGraphicsView): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_phonon_creation'), self.createMediaObject) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'update_display_css'), self.cssChanged) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_updated'), self.configChanged) + + def cssChanged(self): + """ + We may need to rebuild the CSS on the live display. + """ + self.rebuildCSS = True + + def configChanged(self): + """ + 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: + plugin.refreshCss(self.frame) + self.rebuildCSS = False def retranslateUi(self): """ @@ -111,6 +132,9 @@ class MainDisplay(QtGui.QGraphicsView): self.screen[u'size'].width(), self.screen[u'size'].height()) self.page = self.webView.page() self.frame = self.page.mainFrame() + if self.isLive and log.getEffectiveLevel() == logging.DEBUG: + self.webView.settings().setAttribute( + QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) QtCore.QObject.connect(self.webView, QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) @@ -153,7 +177,7 @@ class MainDisplay(QtGui.QGraphicsView): serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(self.initialFrame) self.webView.setHtml(build_html(serviceItem, self.screen, - self.alertTab, self.isLive, None)) + self.isLive, None)) self.__hideMouse() # To display or not to display? if not self.screen[u'primary']: @@ -492,8 +516,8 @@ class MainDisplay(QtGui.QGraphicsView): image_bytes = self.imageManager.get_image_bytes(image) else: image_bytes = None - html = build_html(self.serviceItem, self.screen, self.alertTab, - self.isLive, background, image_bytes) + html = build_html(self.serviceItem, self.screen, self.isLive, + background, image_bytes, self.plugins) log.debug(u'buildHtml - pre setHtml') self.webView.setHtml(html) log.debug(u'buildHtml - post setHtml') diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 49d27a466..37da93b5b 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -58,7 +58,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): # load all the settings self.settingListWidget.clear() for tabIndex in range(0, self.stackedLayout.count() + 1): - # take at 0 and the rest shuffell up. + # take at 0 and the rest shuffle up. self.stackedLayout.takeAt(0) self.insertTab(self.generalTab, 0, PluginStatus.Active) self.insertTab(self.themesTab, 1, PluginStatus.Active) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 354cfa168..7e6e0d54e 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -79,7 +79,6 @@ class SlideController(QtGui.QWidget): self.songEdit = False self.selectedRow = 0 self.serviceItem = None - self.alertTab = None self.panel = QtGui.QWidget(parent.controlSplitter) self.slideList = {} # Layout for holding panel @@ -423,7 +422,6 @@ class SlideController(QtGui.QWidget): if self.display: self.display.close() self.display = MainDisplay(self, self.imageManager, self.isLive) - self.display.alertTab = self.alertTab self.display.setup() if self.isLive: self.__addActionsToWidget(self.display) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 21db1972a..213c6814f 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager from openlp.core.lib.ui import icon_action, UiStrings +from openlp.core.lib.theme import VerticalType from openlp.core.utils.actions import ActionList from openlp.plugins.alerts.lib import AlertsManager, AlertsTab from openlp.plugins.alerts.lib.db import init_schema @@ -39,6 +40,63 @@ from openlp.plugins.alerts.forms import AlertForm log = logging.getLogger(__name__) +JAVASCRIPT = """ + function show_alert(alerttext, position){ + var text = document.getElementById('alert'); + text.innerHTML = alerttext; + if(alerttext == '') { + text.style.visibility = 'hidden'; + return 0; + } + if(position == ''){ + position = getComputedStyle(text, '').verticalAlign; + } + switch(position) + { + case 'top': + text.style.top = '0px'; + break; + case 'middle': + text.style.top = ((window.innerHeight - text.clientHeight) / 2) + + 'px'; + break; + case 'bottom': + text.style.top = (window.innerHeight - text.clientHeight) + + 'px'; + break; + } + text.style.visibility = 'visible'; + return text.clientHeight; + } + + function update_css(align, font, size, color, bgcolor){ + var text = document.getElementById('alert'); + text.style.verticalAlign = align; + text.style.fontSize = size + "pt"; + text.style.fontFamily = font; + text.style.color = color; + text.style.backgroundColor = bgcolor; + } +""" +CSS = """ + #alert { + position: absolute; + left: 0px; + top: 0px; + z-index: 10; + width: 100%%; + vertical-align: %s; + font-family: %s; + font-size: %spt; + color: %s; + background-color: %s; + } +""" + +HTML = """ + +""" + class AlertsPlugin(Plugin): log.info(u'Alerts Plugin loaded') @@ -79,7 +137,6 @@ class AlertsPlugin(Plugin): self.toolsAlertItem.setVisible(True) action_list = ActionList.get_instance() action_list.add_action(self.toolsAlertItem, UiStrings().Tools) - self.liveController.alertTab = self.settings_tab def finalise(self): """ @@ -121,3 +178,35 @@ class AlertsPlugin(Plugin): u'title': translate('AlertsPlugin', 'Alerts', 'container title') } + def getDisplayJavaScript(self): + """ + Add Javascript to the main display. + """ + return JAVASCRIPT + + def getDisplayCss(self): + """ + Add CSS to the main display. + """ + align = VerticalType.Names[self.settings_tab.location] + return CSS % (align, self.settings_tab.font_face, + self.settings_tab.font_size, self.settings_tab.font_color, + self.settings_tab.bg_color) + + def getDisplayHtml(self): + """ + Add HTML to the main display. + """ + return HTML + + def refreshCss(self, frame): + """ + Trigger an update of the CSS in the maindisplay. + + ``frame`` + The Web frame holding the page. + """ + align = VerticalType.Names[self.settings_tab.location] + frame.evaluateJavaScript(u'update_css("%s", "%s", "%s", "%s", "%s")' % + (align, self.settings_tab.font_face, self.settings_tab.font_size, + self.settings_tab.font_color, self.settings_tab.bg_color)) diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 15577fd0e..8720c5111 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsTab, translate +from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib.ui import UiStrings, create_valign_combo class AlertsTab(SettingsTab): @@ -140,6 +140,7 @@ class AlertsTab(SettingsTab): def onTimeoutSpinBoxChanged(self): self.timeout = self.timeoutSpinBox.value() + self.changed = True def onFontSizeSpinBoxChanged(self): self.font_size = self.fontSizeSpinBox.value() @@ -171,10 +172,15 @@ class AlertsTab(SettingsTab): font.setFamily(self.font_face) self.fontComboBox.setCurrentFont(font) self.updateDisplay() + self.changed = False def save(self): settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) + # Check value has changed as no event handles this field + if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \ + self.verticalComboBox.currentIndex(): + self.changed = True settings.setValue(u'background color', QtCore.QVariant(self.bg_color)) settings.setValue(u'font color', QtCore.QVariant(self.font_color)) settings.setValue(u'font size', QtCore.QVariant(self.font_size)) @@ -184,6 +190,9 @@ class AlertsTab(SettingsTab): self.location = self.verticalComboBox.currentIndex() settings.setValue(u'location', QtCore.QVariant(self.location)) settings.endGroup() + if self.changed: + Receiver.send_message(u'update_display_css') + self.changed = False def updateDisplay(self): font = QtGui.QFont() @@ -193,4 +202,5 @@ class AlertsTab(SettingsTab): self.fontPreview.setFont(font) self.fontPreview.setStyleSheet(u'background-color: %s; color: %s' % (self.bg_color, self.font_color)) + self.changed = True