From 4767ec08a2031e6a4e247218aef48753112b2079 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 05:52:52 +0100 Subject: [PATCH 1/4] Image display refactoring --- openlp/core/lib/serviceitem.py | 10 ++- openlp/core/ui/maindisplay.py | 106 ++++++++++++++++++++---------- openlp/core/ui/slidecontroller.py | 10 ++- 3 files changed, 88 insertions(+), 38 deletions(-) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index dfcad984a..c107a1872 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -35,6 +35,7 @@ import uuid from PyQt4 import QtGui from openlp.core.lib import build_icon, resize_image +from openlp.core.utils import AppLocation log = logging.getLogger(__name__) @@ -92,6 +93,7 @@ class ServiceItem(object): self.is_valid = True self.cache = {} self.icon = None + self.serviceItemPath = AppLocation.get_section_data_path(u'serviceItems') def add_capability(self, capability): """ @@ -153,9 +155,12 @@ class ServiceItem(object): del self.cache[len(self._display_frames)] log.log(15, u'Formatting took %4s' % (time.time() - before)) elif self.service_item_type == ServiceItemType.Image: - for slide in self._raw_frames: + for count, slide in enumerate(self._raw_frames): slide[u'image'] = resize_image(slide[u'image'], self.render_manager.width, self.render_manager.height) + path = os.path.join(self.serviceItemPath, self._uuid + unicode(count) + u'.png') + slide[u'image'].save(path) + slide[u'display'] = path elif self.service_item_type == ServiceItemType.Command: pass else: @@ -371,7 +376,8 @@ class ServiceItem(object): if self.service_item_type == ServiceItemType.Text: return self.render_individual(row) else: - return {u'main':self._raw_frames[row][u'image'], u'trans':None} + return {u'main':self._raw_frames[row][u'image'], + u'trans':None, u'display':self._raw_frames[row][u'display']} def get_frame_title(self, row=0): """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 632178f87..4b571822c 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -26,14 +26,21 @@ import logging import os -from PyQt4 import QtCore, QtGui +from PyQt4 import QtCore, QtGui, QtWebKit from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, resize_image from openlp.core.ui import HideMode +from openlp.core.utils import AppLocation log = logging.getLogger(__name__) +HTMLIMAGE = """ + + + + """ + class DisplayManager(QtGui.QWidget): """ Wrapper class to hold the display widgets. @@ -76,10 +83,16 @@ class DisplayManager(QtGui.QWidget): def addAlert(self, alertMessage, location): """ - Handles the add Alert Message to the Displays + Handles the addition of an Alert Message to the Displays """ self.mainDisplay.addAlert(alertMessage, location) + def displayImage(self, path): + """ + Handles the addition of a background Image to the displays + """ + self.mainDisplay.displayImage(path) + def onStartVideo(self, item): """ Handles the Starting of a Video and Display Management @@ -183,7 +196,7 @@ class MainDisplay(DisplayWidget): self.primary = True self.blankFrame = None self.frame = None - #Hide desktop for now untill we know where to put it + #Hide desktop for now until we know where to put it #and what size it should be. self.setVisible(False) @@ -198,6 +211,7 @@ class MainDisplay(DisplayWidget): #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) + self.imageDisplay.setGeometry(0, 0, self.size().width(), self.size().height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( self.screen[u'size'].width(), @@ -211,7 +225,7 @@ class MainDisplay(DisplayWidget): (self.screen[u'size'].width() - splash_image.width()) / 2, (self.screen[u'size'].height() - splash_image.height()) / 2, splash_image) - self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) + #self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) self.repaint() #Build a Black screen painter = QtGui.QPainter() @@ -241,9 +255,15 @@ class MainDisplay(DisplayWidget): self.setScene(self.scene) def setupImage(self): - self.display_image = QtGui.QGraphicsPixmapItem() - self.display_image.setZValue(2) - self.scene.addItem(self.display_image) +# self.display_image = QtGui.QGraphmaindisplay.pyicsPixmapItem() +# self.display_image.setZValue(2) +# self.scene.addItem(self.display_image) + self.imageDisplay = QtWebKit.QWebView() + self.proxy = QtGui.QGraphicsProxyWidget() + self.proxy.setWidget(self.imageDisplay) + self.proxy.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) + self.proxy.setZValue(2) + self.scene.addItem(self.proxy) def setupText(self): #self.display_text = QtGui.QGraphicsTextItem() @@ -319,7 +339,7 @@ class MainDisplay(DisplayWidget): def addAlert(self, message, location): """ Places the Alert text on the display at the correct location - ``messgae`` + ``message`` Text to be displayed ``location`` Where on the screen the text should be. From the AlertTab @@ -334,7 +354,16 @@ class MainDisplay(DisplayWidget): self.alertText.setPos(0,self.size().height() - 76) self.alertText.setHtml(message) - def frameView(self, frame, transition=False, display=True): + def displayImage(self, path): + """ + Places the Image passed on the display screen + ``path`` + The path to the image to be displayed + """ + log.debug(u'adddisplayImage') + self.imageDisplay.setHtml(HTMLIMAGE % path) + + def frameView(self, frame, transition=False): """ Called from a slide controller to display a frame if the alert is in progress the alert is added on top @@ -343,33 +372,44 @@ class MainDisplay(DisplayWidget): ``transition`` Are transitions required. """ - log.debug(u'frameView %d' % display) - if display: - if transition: - if self.frame is not None: - self.display_text.setPixmap( - QtGui.QPixmap.fromImage(self.frame)) - self.update() - self.frame = None - if frame[u'trans'] is not None: - self.display_text.setPixmap( - QtGui.QPixmap.fromImage(frame[u'trans'])) - self.repaint() - self.frame = frame[u'trans'] + log.debug(u'frameView') + if transition: + if self.frame is not None: self.display_text.setPixmap( - QtGui.QPixmap.fromImage(frame[u'main'])) - self.display_frame = frame[u'main'] + QtGui.QPixmap.fromImage(self.frame)) + self.update() + self.frame = None + if frame[u'trans'] is not None: + self.display_text.setPixmap( + QtGui.QPixmap.fromImage(frame[u'trans'])) self.repaint() - else: - if isinstance(frame, QtGui.QPixmap): - self.display_text.setPixmap(frame) - else: - self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) - self.display_frame = frame - if not self.isVisible() and self.screens.display: - self.setVisible(True) + self.frame = frame[u'trans'] + self.display_text.setPixmap( + QtGui.QPixmap.fromImage(frame[u'main'])) + self.display_frame = frame[u'main'] + self.repaint() else: - self.storeText = QtGui.QPixmap.fromImage(frame[u'main']) + if isinstance(frame, QtGui.QPixmap): + self.display_text.setPixmap(frame) + else: + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) + self.display_frame = frame + if not self.isVisible() and self.screens.display: + self.setVisible(True) + + def closeEvent(self, event): + """ + Shutting down cleans up background files + """ + serviceItemPath = AppLocation.get_section_data_path(u'serviceItems') + for file in os.listdir(serviceItemPath): + file_path = os.path.join(serviceItemPath, file) + try: + if os.path.isfile(file_path): + os.remove(file_path) + except OSError: + log.exception(u'Failed to clean up servicePath') + class VideoDisplay(Phonon.VideoWidget): """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 69019a696..5a34d09f8 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -105,6 +105,7 @@ class SlideController(QtGui.QWidget): self.isLive = isLive self.parent = parent self.mainDisplay = self.parent.displayManager.mainDisplay + self.displayManager = self.parent.displayManager self.loopList = [ u'Start Loop', u'Loop Separator', @@ -526,8 +527,8 @@ class SlideController(QtGui.QWidget): # blanked = self.blankButton.isChecked() # else: # blanked = False -# Receiver.send_message(u'%s_start' % serviceItem.name.lower(), -# [serviceItem, self.isLive, blanked, slideno]) + Receiver.send_message(u'%s_start' % serviceItem.name.lower(), + [serviceItem, self.isLive, True, slideno]) self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] #Set pointing cursor when we have somthing to point at @@ -781,7 +782,10 @@ class SlideController(QtGui.QWidget): log.log( 15, u'Slide Rendering took %4s' % (time.time() - before)) if self.isLive: - self.mainDisplay.frameView(frame, True)#, self.canDisplay) + if self.serviceItem.is_text(): + self.mainDisplay.frameView(frame, True) + else: + self.displayManager.displayImage(frame[u'display']) self.selectedRow = row Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) From 7198148a485dd73d595db65c3752777cc035e230 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 17:10:54 +0100 Subject: [PATCH 2/4] Replaceable Backgound images now work --- openlp/core/ui/maindisplay.py | 13 +++++++------ openlp/plugins/images/lib/mediaitem.py | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 4b571822c..715228e21 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -211,7 +211,7 @@ class MainDisplay(DisplayWidget): #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) - self.imageDisplay.setGeometry(0, 0, self.size().width(), self.size().height()) + self.webView.setGeometry(0, 0, self.size().width(), self.size().height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( self.screen[u'size'].width(), @@ -255,12 +255,13 @@ class MainDisplay(DisplayWidget): self.setScene(self.scene) def setupImage(self): -# self.display_image = QtGui.QGraphmaindisplay.pyicsPixmapItem() -# self.display_image.setZValue(2) -# self.scene.addItem(self.display_image) - self.imageDisplay = QtWebKit.QWebView() + self.webView = QtWebKit.QWebView() + self.page = self.webView.page() + self.imageDisplay = self.page.mainFrame() + self.imageDisplay.setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff) + self.imageDisplay.setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) self.proxy = QtGui.QGraphicsProxyWidget() - self.proxy.setWidget(self.imageDisplay) + self.proxy.setWidget(self.webView) self.proxy.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) self.proxy.setZValue(2) self.scene.addItem(self.proxy) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index bcc3a84c4..a1c2d03fe 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -175,12 +175,12 @@ class ImageMediaItem(MediaManagerItem): translate('ImagePlugin.MediaItem', 'No item selected'), translate('ImagePlugin.MediaItem', 'You must select one item')) - items = self.ListView.selectedIndexes() - for item in items: - bitem = self.ListView.item(item.row()) - filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) - frame = QtGui.QImage(unicode(filename)) - self.parent.maindisplay.addImageWithText(frame) + return + item = self.buildServiceItem() + item.render() + self.parent.live_controller.displayManager. \ + displayImage(item.get_rendered_frame(0)[u'display']) + def onPreviewClick(self): MediaManagerItem.onPreviewClick(self) From 8b5931d50cb059bd28bc30d428208d10c446079e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 17:30:25 +0100 Subject: [PATCH 3/4] Video and Image updates --- openlp/core/ui/maindisplay.py | 33 ++++++++++++++++++++ openlp/plugins/media/lib/mediaitem.py | 44 ++++++++++++++++----------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 715228e21..ae6d400fe 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -41,6 +41,23 @@ HTMLIMAGE = """ """ +#http://www.steveheffernan.com/html5-video-player/demo-video-player.html +HTMLVIDEO = u""" + + \" + + + """ + class DisplayManager(QtGui.QWidget): """ Wrapper class to hold the display widgets. @@ -93,6 +110,12 @@ class DisplayManager(QtGui.QWidget): """ self.mainDisplay.displayImage(path) + def displayVideo(self, path): + """ + Handles the addition of a background Video to the displays + """ + self.mainDisplay.displayVideo(path) + def onStartVideo(self, item): """ Handles the Starting of a Video and Display Management @@ -364,6 +387,16 @@ class MainDisplay(DisplayWidget): log.debug(u'adddisplayImage') self.imageDisplay.setHtml(HTMLIMAGE % path) + def displayVideo(self, path): + """ + Places the Video passed on the display screen + ``path`` + The path to the image to be displayed + """ + log.debug(u'adddisplayVideo') + self.imageDisplay.setHtml(HTMLVIDEO % + (path, self.screen[u'size'].width(), self.screen[u'size'].height())) + def frameView(self, frame, transition=False): """ Called from a slide controller to display a frame diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 6cd7b175b..938dc1297 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -29,7 +29,8 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected + ItemCapabilities, SettingsManager, translate, check_item_selected, \ + context_menu_action log = logging.getLogger(__name__) @@ -73,13 +74,13 @@ class MediaMediaItem(MediaManagerItem): self.hasNewIcon = False self.hasEditIcon = False -# def addListViewToToolBar(self): -# MediaManagerItem.addListViewToToolBar(self) -# self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) -# self.ListView.addAction( -# context_menu_action(self.ListView, u':/slides/slide_blank.png', -# translate('MediaPlugin.MediaItem', 'Replace Live Background'), -# self.onReplaceClick)) + def addListViewToToolBar(self): + MediaManagerItem.addListViewToToolBar(self) + self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.ListView.addAction( + context_menu_action(self.ListView, u':/slides/slide_blank.png', + translate('MediaPlugin.MediaItem', 'Replace Live Background'), + self.onReplaceClick)) def addEndHeaderBar(self): self.ImageWidget = QtGui.QWidget(self) @@ -92,24 +93,31 @@ class MediaMediaItem(MediaManagerItem): self.ImageWidget.setSizePolicy(sizePolicy) self.ImageWidget.setObjectName(u'ImageWidget') #Replace backgrounds do not work at present so remove functionality. -# self.blankButton = self.Toolbar.addToolbarButton( -# u'Replace Background', u':/slides/slide_blank.png', -# translate('MediaPlugin.MediaItem', 'Replace Live Background'), -# self.onReplaceClick, False) + self.blankButton = self.Toolbar.addToolbarButton( + u'Replace Background', u':/slides/slide_blank.png', + translate('MediaPlugin.MediaItem', 'Replace Live Background'), + self.onReplaceClick, False) # Add the song widget to the page layout self.PageLayout.addWidget(self.ImageWidget) -# def onReplaceClick(self): + def onReplaceClick(self): # if self.background: # self.background = False # Receiver.send_message(u'videodisplay_stop') # else: # self.background = True -# if not self.ListView.selectedIndexes(): -# QtGui.QMessageBox.information(self, -# translate('MediaPlugin.MediaItem', 'No item selected'), -# translate('MediaPlugin.MediaItem', -# 'You must select one item')) + if not self.ListView.selectedIndexes(): + QtGui.QMessageBox.information(self, + translate('MediaPlugin.MediaItem', 'No item selected'), + translate('MediaPlugin.MediaItem', + 'You must select one item')) + return + item = self.ListView.currentItem() + if item is None: + return False + filename = unicode(item.data(QtCore.Qt.UserRole).toString()) + print filename + self.parent.live_controller.displayManager.displayVideo(filename) # items = self.ListView.selectedIndexes() # for item in items: # bitem = self.ListView.item(item.row()) From 9ebdc1e2d3fad3184fd086a4e21c9098d24542a2 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 18:05:12 +0100 Subject: [PATCH 4/4] Update missing checks --- openlp/plugins/images/lib/mediaitem.py | 17 +++++++---------- openlp/plugins/media/lib/mediaitem.py | 18 ++++++------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index a1c2d03fe..ee7a22106 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -170,16 +170,13 @@ class ImageMediaItem(MediaManagerItem): return False def onReplaceClick(self): - if not self.ListView.selectedIndexes(): - QtGui.QMessageBox.information(self, - translate('ImagePlugin.MediaItem', 'No item selected'), - translate('ImagePlugin.MediaItem', - 'You must select one item')) - return - item = self.buildServiceItem() - item.render() - self.parent.live_controller.displayManager. \ - displayImage(item.get_rendered_frame(0)[u'display']) + if check_item_selected(self.ListView, + translate('ImagePlugin.MediaItem', + 'You must select an item to process.')): + item = self.buildServiceItem() + item.render() + self.parent.live_controller.displayManager. \ + displayImage(item.get_rendered_frame(0)[u'display']) def onPreviewClick(self): diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 938dc1297..10c398912 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -106,18 +106,12 @@ class MediaMediaItem(MediaManagerItem): # Receiver.send_message(u'videodisplay_stop') # else: # self.background = True - if not self.ListView.selectedIndexes(): - QtGui.QMessageBox.information(self, - translate('MediaPlugin.MediaItem', 'No item selected'), - translate('MediaPlugin.MediaItem', - 'You must select one item')) - return - item = self.ListView.currentItem() - if item is None: - return False - filename = unicode(item.data(QtCore.Qt.UserRole).toString()) - print filename - self.parent.live_controller.displayManager.displayVideo(filename) + if check_item_selected(self.ListView, + translate('ImagePlugin.MediaItem', + 'You must select an item to process.')): + item = self.ListView.currentItem() + filename = unicode(item.data(QtCore.Qt.UserRole).toString()) + self.parent.live_controller.displayManager.displayVideo(filename) # items = self.ListView.selectedIndexes() # for item in items: # bitem = self.ListView.item(item.row())