← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/alpha3 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/alpha3 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)


Start of Display changes.
- Move output displays to QGraphicScene's
- Sort out Video display so it works with hiding / displaying
- Move Alerts to Html from Images
- Hide the Service Dropdown when Global Theme is set
- Slidecontroller Button cleanups

Some code is still missing but what we have works but there may be issues which need fixing.
Hang in there Alpha 3 will be great!
-- 
https://code.launchpad.net/~trb143/openlp/alpha3/+merge/28661
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/alpha3 into lp:openlp.
=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2010-06-13 19:34:25 +0000
+++ openlp/core/ui/maindisplay.py	2010-06-28 18:09:27 +0000
@@ -45,18 +45,67 @@
         QtGui.QWidget.__init__(self)
         self.screens = screens
         self.videoDisplay = VideoDisplay(self, screens)
+        self.audioPlayer = AudioPlayer(self)
         self.mainDisplay = MainDisplay(self, screens)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'videodisplay_start'), self.onStartVideo)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'videodisplay_stop'), self.onStopVideo)
 
     def setup(self):
         self.videoDisplay.setup()
         self.mainDisplay.setup()
 
+    def hideDisplay(self, message):
+        """
+        Hide the output displays
+        """
+        self.videoDisplay.mediaHide(message)
+        self.mainDisplay.hideDisplay(message)
+
+    def showDisplay(self, message):
+        """
+        Hide the output displays
+        """
+        self.videoDisplay.mediaShow(message)
+        self.mainDisplay.showDisplay(message)
+
+    def addAlert(self, alertMessage, location):
+        """
+        Handles the add Alert Message to the Displays
+        """
+        self.mainDisplay.addAlert(alertMessage, location)
+
+    def onStartVideo(self, item):
+        """
+        Handles the Starting of a Video and Display Management
+        """
+        self.videoDisplay.setVisible(True)
+        self.mainDisplay.setVisible(False)
+        self.videoDisplay.onMediaQueue(item)
+
+    def onStopVideo(self):
+        """
+        Handles the Stopping of a Video and Display Management
+        """
+        self.mainDisplay.setVisible(True)
+        self.videoDisplay.setVisible(False)
+        self.videoDisplay.onMediaStop()
+
     def close(self):
+        """
+        Handles the closure of the displays
+        """
         self.videoDisplay.close()
+        self.audioPlayer.close()
         self.mainDisplay.close()
 
 
-class DisplayWidget(QtGui.QWidget):
+class DisplayWidget(QtGui.QGraphicsView):
     """
     Customised version of QTableWidget which can respond to keyboard
     events.
@@ -117,32 +166,26 @@
         log.debug(u'Initialisation started')
         DisplayWidget.__init__(self, parent)
         self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint)
-        self.setWindowState(QtCore.Qt.WindowFullScreen)
+        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
         self.parent = parent
-        self.setWindowTitle(u'OpenLP Display')
         # WA_TranslucentBackground is not available in QT4.4
         try:
             self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
         except AttributeError:
             pass
         self.screens = screens
-        self.display_image = QtGui.QLabel(self)
-        self.display_image.setScaledContents(True)
-        self.display_text = QtGui.QLabel(self)
-        self.display_text.setScaledContents(True)
-        self.display_alert = QtGui.QLabel(self)
-        self.display_alert.setScaledContents(True)
+        self.setupScene()
+        self.setupImage()
+        self.setupText()
+        self.setupAlert()
+        self.setupBlank()
         self.primary = True
         self.blankFrame = None
         self.frame = None
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'videodisplay_start'), self.hideDisplayForVideo)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'videodisplay_background'), self.hideDisplayForVideo)
+        #Hide desktop for now untill we know where to put it
+        #and what size it should be.
+        self.setVisible(False)
 
     def setup(self):
         """
@@ -153,12 +196,8 @@
         self.setVisible(False)
         self.screen = self.screens.current
         #Sort out screen locations and sizes
-        self.display_alert.setGeometry(self.screen[u'size'])
-        self.display_image.resize(
-            self.screen[u'size'].width(), self.screen[u'size'].height())
-        self.display_text.resize(
-            self.screen[u'size'].width(), self.screen[u'size'].height())
         self.setGeometry(self.screen[u'size'])
+        self.scene.setSceneRect(0,0,self.size().width(), self.size().height())
         #Build a custom splash screen
         self.InitialFrame = QtGui.QImage(
             self.screen[u'size'].width(),
@@ -186,30 +225,58 @@
         self.transparent = QtGui.QPixmap(
             self.screen[u'size'].width(), self.screen[u'size'].height())
         self.transparent.fill(QtCore.Qt.transparent)
-        self.display_alert.setPixmap(self.transparent)
-        self.display_text.setPixmap(self.transparent)
-        self.frameView(self.transparent)
+#        self.display_text.setPixmap(self.transparent)
+        #self.frameView(self.transparent)
         # To display or not to display?
         if not self.screen[u'primary']:
-            self.showFullScreen()
+            self.setVisible(True)
             self.primary = False
         else:
             self.setVisible(False)
             self.primary = True
 
+    def setupScene(self):
+        self.scene = QtGui.QGraphicsScene(self)
+        self.scene.setSceneRect(0,0,self.size().width(), self.size().height())
+        self.setScene(self.scene)
+
+    def setupImage(self):
+        self.display_image = QtGui.QGraphicsPixmapItem()
+        self.display_image.setZValue(2)
+        self.scene.addItem(self.display_image)
+
+    def setupText(self):
+        #self.display_text = QtGui.QGraphicsTextItem()
+        self.display_text = QtGui.QGraphicsPixmapItem()
+        #self.display_text.setPos(0,0)
+        #self.display_text.setTextWidth(self.size().width())
+        self.display_text.setZValue(4)
+        self.scene.addItem(self.display_text)
+
+    def setupAlert(self):
+        self.alertText = QtGui.QGraphicsTextItem()
+        self.alertText.setTextWidth(self.size().width())
+        self.alertText.setZValue(8)
+        self.scene.addItem(self.alertText)
+
+    def setupBlank(self):
+        self.display_blank = QtGui.QGraphicsPixmapItem()
+        self.display_blank.setZValue(10)
+        self.scene.addItem(self.display_blank)
+
     def resetDisplay(self):
         log.debug(u'resetDisplay')
         Receiver.send_message(u'slidecontroller_live_stop_loop')
         if self.primary:
             self.setVisible(False)
         else:
-            self.showFullScreen()
+            self.setVisible(True)
 
-    def hideDisplayForVideo(self):
-        """
-        Hides the main display if for the video to be played
-        """
-        self.hideDisplay(HideMode.Screen)
+#    def hideDisplayForVideo(self):
+#        """
+#        Hides the main display if for the video to be played
+#        """
+#        self.hideDisplay(HideMode.Screen)
 
     def hideDisplay(self, mode=HideMode.Screen):
         """
@@ -217,45 +284,30 @@
         Store the images so they can be replaced when required
         """
         log.debug(u'hideDisplay mode = %d', mode)
-        self.storeImage = QtGui.QPixmap(self.display_image.pixmap())
-        self.storeText = QtGui.QPixmap(self.display_text.pixmap())
-        self.display_alert.setPixmap(self.transparent)
-        self.display_text.setPixmap(self.transparent)
+        #self.display_text.setPixmap(self.transparent)
         if mode == HideMode.Screen:
-            self.display_image.setPixmap(self.transparent)
+            #self.display_image.setPixmap(self.transparent)
+            self.setVisible(False)
         elif mode == HideMode.Blank:
-            self.display_image.setPixmap(
+            self.display_blank.setPixmap(
                 QtGui.QPixmap.fromImage(self.blankFrame))
         else:
             if self.parent.renderManager.renderer.bg_frame:
-                self.display_image.setPixmap(QtGui.QPixmap.fromImage(
+                self.display_blank.setPixmap(QtGui.QPixmap.fromImage(
                     self.parent.renderManager.renderer.bg_frame))
             else:
-                self.display_image.setPixmap(
+                self.display_blank.setPixmap(
                     QtGui.QPixmap.fromImage(self.blankFrame))
-        self.moveToTop()
-
-    def moveToTop(self):
-        log.debug(u'moveToTop')
-        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint |
-            QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog)
-        self.show()
-
-    def showDisplay(self):
+
+    def showDisplay(self, message=u''):
         """
         Show the stored layers so the screen reappears as it was
         originally.
         Make the stored images None to release memory.
         """
         log.debug(u'showDisplay')
-        if self.storeImage:
-            self.display_image.setPixmap(self.storeImage)
-        self.display_alert.setPixmap(self.transparent)
-        if self.storeText:
-            self.display_text.setPixmap(self.storeText)
-        self.storeImage = None
-        self.store = None
-        self.moveToTop()
+        self.display_blank.setPixmap(self.transparent)
+        #Trigger actions when display is active again
         Receiver.send_message(u'maindisplay_active')
 
     def addImageWithText(self, frame):
@@ -263,21 +315,24 @@
         frame = resize_image(
             frame, self.screen[u'size'].width(), self.screen[u'size'].height())
         self.display_image.setPixmap(QtGui.QPixmap.fromImage(frame))
-        self.moveToTop()
-
-    def setAlertSize(self, top, height):
-        log.debug(u'setAlertSize')
-        self.display_alert.setGeometry(
-            QtCore.QRect(0, top,
-                        self.screen[u'size'].width(), height))
-
-    def addAlertImage(self, frame, blank=False):
+
+    def addAlert(self, message, location):
+        """
+        Places the Alert text on the display at the correct location
+        ``messgae``
+            Text to be displayed
+        ``location``
+            Where on the screen the text should be.  From the AlertTab
+            Combo box.
+        """
         log.debug(u'addAlertImage')
-        if blank:
-            self.display_alert.setPixmap(self.transparent)
+        if location == 0:
+            self.alertText.setPos(0, 0)
+        elif location == 1:
+            self.alertText.setPos(0,self.size().height()/2)
         else:
-            self.display_alert.setPixmap(frame)
-        self.moveToTop()
+            self.alertText.setPos(0,self.size().height() - 76)
+        self.alertText.setHtml(message)
 
     def frameView(self, frame, transition=False, display=True):
         """
@@ -285,14 +340,16 @@
         if the alert is in progress the alert is added on top
         ``frame``
             Image frame to be rendered
+        ``transition``
+            Are transitions required.
         """
-        log.debug(u'frameView %d' % (display))
+        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.repaint()
+                    self.update()
                 self.frame = None
                 if frame[u'trans'] is not None:
                     self.display_text.setPixmap(
@@ -311,7 +368,6 @@
                 self.display_frame = frame
             if not self.isVisible() and self.screens.display:
                 self.setVisible(True)
-                self.showFullScreen()
         else:
             self.storeText = QtGui.QPixmap.fromImage(frame[u'main'])
 
@@ -339,37 +395,29 @@
         self.screens = screens
         self.hidden = False
         self.message = None
+        self.mediaActive = False
         self.mediaObject = Phonon.MediaObject()
         self.setAspectRatio(aspect)
         self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory)
         Phonon.createPath(self.mediaObject, self)
         Phonon.createPath(self.mediaObject, self.audioObject)
         flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog
-        # WindowsStaysOnBottomHint is not available in QT4.4
-        try:
-            flags = flags | QtCore.Qt.WindowStaysOnBottomHint
-        except AttributeError:
-            pass
+##        # WindowsStaysOnBottomHint is not available in QT4.4
+#        try:
+#            flags = flags | QtCore.Qt.WindowStaysOnBottomHint
+#        except AttributeError:
+#            pass
         self.setWindowFlags(flags)
-
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'maindisplay_hide'), self.mediaHide)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'maindisplay_show'), self.mediaShow)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'videodisplay_start'), self.onMediaQueue)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'videodisplay_play'), self.onMediaPlay)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'videodisplay_pause'), self.onMediaPause)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'videodisplay_stop'), self.onMediaStop)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground)
+#        QtCore.QObject.connect(Receiver.get_receiver(),
+#            QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'config_updated'), self.setup)
         QtCore.QObject.connect(self.mediaObject,
-            QtCore.SIGNAL(u'finished()'), self.onMediaBackground)
+            QtCore.SIGNAL(u'finished()'), self.onMediaStop)
         self.setVisible(False)
 
     def keyPressEvent(self, event):
@@ -392,38 +440,48 @@
         #Sort out screen locations and sizes
         self.setGeometry(self.screen[u'size'])
         # To display or not to display?
-        if not self.screen[u'primary'] and self.isVisible():
-            self.showFullScreen()
+        if not self.screen[u'primary']: # and self.isVisible():
+            #self.showFullScreen()
+            self.setVisible(False)
             self.primary = False
         else:
             self.setVisible(False)
             self.primary = True
 
-    def onMediaBackground(self, message=None):
-        """
-        Play a video triggered from the video plugin with the
-        file name passed in on the event.
-        Also triggered from the Finish event so the video will loop
-        if it is triggered from the plugin
-        """
-        log.debug(u'VideoDisplay Queue new media message %s' % message)
-        #If not file take the stored one
-        if not message:
-            message = self.message
-        # still no file name then stop as it was a normal video stopping
-        if message:
-            self.mediaObject.setCurrentSource(Phonon.MediaSource(message))
-            self.message = message
-            self._play()
+    def closeEvent(self, event):
+        """
+        Shutting down so clean up connections
+        """
+        self.onMediaStop()
+        for pth in self.outputPaths():
+          disconnected = pth.disconnect()
+
+#    def onMediaBackground(self, message=None):
+#        """
+#        Play a video triggered from the video plugin with the
+#        file name passed in on the event.
+#        Also triggered from the Finish event so the video will loop
+#        if it is triggered from the plugin
+#        """
+#        log.debug(u'VideoDisplay Queue new media message %s' % message)
+#        #If not file take the stored one
+#        if not message:
+#            message = self.message
+#        # still no file name then stop as it was a normal video stopping
+#        if message:
+#            self.mediaObject.setCurrentSource(Phonon.MediaSource(message))
+#            self.message = message
+#            self._play()
 
     def onMediaQueue(self, message):
         """
         Set up a video to play from the serviceitem.
         """
         log.debug(u'VideoDisplay Queue new media message %s' % message)
-        file = os.path.join(message[0].get_frame_path(),
-            message[0].get_frame_title())
+        file = os.path.join(message.get_frame_path(),
+            message.get_frame_title())
         self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
+        self.mediaActive = True
         self._play()
 
     def onMediaPlay(self):
@@ -442,7 +500,6 @@
         log.debug(u'VideoDisplay _play called')
         self.mediaObject.play()
         self.setVisible(True)
-        self.showFullScreen()
 
     def onMediaPause(self):
         """
@@ -458,6 +515,7 @@
         """
         log.debug(u'VideoDisplay Media stopped by user')
         self.message = None
+        self.mediaActive = False
         self.mediaObject.stop()
         self.onMediaFinish()
 
@@ -469,7 +527,7 @@
         self.mediaObject.clearQueue()
         self.setVisible(False)
 
-    def mediaHide(self):
+    def mediaHide(self, message=u''):
         """
         Hide the video display
         """
@@ -477,10 +535,90 @@
         self.hidden = True
         self.setVisible(False)
 
-    def mediaShow(self):
+    def mediaShow(self, message=''):
         """
         Show the video disaply if it was already hidden
         """
         if self.hidden:
             self.hidden = False
-            self._play()
+            if self.mediaActive:
+                self._play()
+
+class AudioPlayer(QtCore.QObject):
+    """
+    This Class will play audio only allowing components to work witn a
+    soundtrack which does not take over the user interface.
+    """
+    log.info(u'AudioPlayer Loaded')
+
+    def __init__(self, parent):
+        """
+        The constructor for the display form.
+
+        ``parent``
+            The parent widget.
+
+        ``screens``
+            The list of screens.
+        """
+        log.debug(u'AudioPlayer Initialisation started')
+        QtCore.QObject.__init__(self)
+        self.parent = parent
+        self.message = None
+        self.mediaObject = Phonon.MediaObject()
+        self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory)
+        Phonon.createPath(self.mediaObject, self.audioObject)
+
+    def setup(self):
+        """
+        Sets up the Audio Player for use
+        """
+        log.debug(u'AudioPlayer Setup')
+
+    def close(self):
+        """
+        Shutting down so clean up connections
+        """
+        self.onMediaStop()
+        for pth in self.mediaObject.outputPaths():
+            disconnected = pth.disconnect()
+
+    def onMediaQueue(self, message):
+        """
+        Set up a video to play from the serviceitem.
+        """
+        log.debug(u'AudioPlayer Queue new media message %s' % message)
+        file = os.path.join(message[0].get_frame_path(),
+            message[0].get_frame_title())
+        self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
+        self.onMediaPlay()
+
+    def onMediaPlay(self):
+        """
+        We want to play the play so start it
+        """
+        log.debug(u'AudioPlayer _play called')
+        self.mediaObject.play()
+
+    def onMediaPause(self):
+        """
+        Pause the Audio
+        """
+        log.debug(u'AudioPlayer Media paused by user')
+        self.mediaObject.pause()
+
+    def onMediaStop(self):
+        """
+        Stop the Audio and clean up
+        """
+        log.debug(u'AudioPlayer Media stopped by user')
+        self.message = None
+        self.mediaObject.stop()
+        self.onMediaFinish()
+
+    def onMediaFinish(self):
+        """
+        Clean up the Object queue
+        """
+        log.debug(u'AudioPlayer Reached end of media playlist')
+        self.mediaObject.clearQueue()

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2010-06-20 12:43:09 +0000
+++ openlp/core/ui/servicemanager.py	2010-06-28 18:09:27 +0000
@@ -33,7 +33,7 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \
-    Receiver, build_icon, ItemCapabilities, SettingsManager, translate
+    Receiver, build_icon, ItemCapabilities, SettingsManager, translate, ThemeLevel
 from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm
 from openlp.core.utils import AppLocation
 
@@ -134,15 +134,13 @@
         self.ThemeLabel = QtGui.QLabel(translate('ServiceManager', 'Theme:'),
             self)
         self.ThemeLabel.setMargin(3)
-        self.Toolbar.addWidget(self.ThemeLabel)
+        self.Toolbar.addToolbarWidget(u'ThemeLabel', self.ThemeLabel)
         self.ThemeComboBox = QtGui.QComboBox(self.Toolbar)
         self.ThemeComboBox.setToolTip(translate('ServiceManager',
             'Select a theme for the service'))
         self.ThemeComboBox.setSizeAdjustPolicy(
             QtGui.QComboBox.AdjustToContents)
-        self.ThemeWidget = QtGui.QWidgetAction(self.Toolbar)
-        self.ThemeWidget.setDefaultWidget(self.ThemeComboBox)
-        self.Toolbar.addAction(self.ThemeWidget)
+        self.Toolbar.addToolbarWidget(u'ThemeWidget', self.ThemeComboBox)
         self.Layout.addWidget(self.Toolbar)
         # Create the service manager list
         self.ServiceManagerList = ServiceManagerList(self)
@@ -214,6 +212,8 @@
             QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'theme_update_global'), self.themeChange)
         # Last little bits of setting up
         self.service_theme = unicode(QtCore.QSettings().value(
             self.parent.serviceSettingsSection + u'/service theme',
@@ -756,6 +756,18 @@
             QtCore.QVariant(self.service_theme))
         self.regenerateServiceItems()
 
+    def themeChange(self):
+        """
+        The theme may have changed in the settings dialog so make
+        sure the theme combo box is in the correct state.
+        """
+        if self.parent.RenderManager.theme_level == ThemeLevel.Global:
+            self.Toolbar.actions[u'ThemeLabel'].setVisible(False)
+            self.Toolbar.actions[u'ThemeWidget'].setVisible(False)
+        else:
+            self.Toolbar.actions[u'ThemeLabel'].setVisible(True)
+            self.Toolbar.actions[u'ThemeWidget'].setVisible(True)
+
     def regenerateServiceItems(self):
         """
         Rebuild the service list as things have changed and a

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2010-06-25 20:20:03 +0000
+++ openlp/core/ui/slidecontroller.py	2010-06-28 18:09:27 +0000
@@ -107,7 +107,6 @@
         self.mainDisplay = self.parent.displayManager.mainDisplay
         self.loopList = [
             u'Start Loop',
-            u'Stop Loop',
             u'Loop Separator',
             u'Image SpinBox'
         ]
@@ -196,18 +195,25 @@
                 self.onSlideSelectedLast)
         if self.isLive:
             self.Toolbar.addToolbarSeparator(u'Close Separator')
-            self.blankButton = self.Toolbar.addToolbarButton(
-                u'Blank Screen', u':/slides/slide_blank.png',
-                translate('SlideController', 'Blank Screen'),
-                self.onBlankDisplay, True)
-            self.themeButton = self.Toolbar.addToolbarButton(
-                u'Display Theme', u':/slides/slide_theme.png',
-                translate('SlideController', 'Theme Screen'),
-                self.onThemeDisplay, True)
-            self.hideButton = self.Toolbar.addToolbarButton(
-                u'Hide screen', u':/slides/slide_desktop.png',
-                translate('SlideController', 'Hide Screen'),
-                self.onHideDisplay, True)
+            self.HideMenu = QtGui.QToolButton(self.Toolbar)
+            self.HideMenu.setText(translate('SlideController', 'Hide'))
+            self.HideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
+            self.Toolbar.addToolbarWidget(u'Hide Menu', self.HideMenu)
+            self.HideMenu.setMenu(QtGui.QMenu(
+                translate('SlideController', 'Hide'), self.Toolbar))
+            self.BlankScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu)
+            self.BlankScreen.setCheckable(True)
+            QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay)
+            self.ThemeScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu)
+            self.ThemeScreen.setCheckable(True)
+            QtCore.QObject.connect(self.ThemeScreen, QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay)
+            self.DesktopScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.HideMenu)
+            self.DesktopScreen.setCheckable(True)
+            QtCore.QObject.connect(self.DesktopScreen, QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay)
+            self.HideMenu.setDefaultAction(self.BlankScreen)
+            self.HideMenu.menu().addAction(self.BlankScreen)
+            self.HideMenu.menu().addAction(self.ThemeScreen)
+            self.HideMenu.menu().addAction(self.DesktopScreen)
         if not self.isLive:
             self.Toolbar.addToolbarSeparator(u'Close Separator')
             self.Toolbar.addToolbarButton(
@@ -252,19 +258,6 @@
             u'Media Stop', u':/slides/media_playback_stop.png',
             translate('SlideController', 'Start playing media'),
             self.onMediaStop)
-        if self.isLive:
-            self.blankButton = self.Mediabar.addToolbarButton(
-                u'Blank Screen', u':/slides/slide_blank.png',
-                translate('SlideController', 'Blank Screen'),
-                self.onBlankDisplay, True)
-            self.themeButton = self.Mediabar.addToolbarButton(
-                u'Display Theme', u':/slides/slide_theme.png',
-                translate('SlideController', 'Theme Screen'),
-                self.onThemeDisplay, True)
-            self.hideButton = self.Mediabar.addToolbarButton(
-                u'Hide screen', u':/slides/slide_desktop.png',
-                translate('SlideController', 'Hide Screen'),
-                self.onHideDisplay, True)
         if not self.isLive:
             self.seekSlider = Phonon.SeekSlider()
             self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
@@ -340,6 +333,7 @@
                     self.receiveSpinDelay)
         if isLive:
             self.Toolbar.makeWidgetsInvisible(self.loopList)
+            self.Toolbar.actions[u'Stop Loop'].setVisible(False)
         else:
             self.Toolbar.makeWidgetsInvisible(self.songEditList)
         self.Mediabar.setVisible(False)
@@ -436,8 +430,8 @@
         self.Mediabar.setVisible(False)
         self.Toolbar.makeWidgetsInvisible([u'Song Menu'])
         self.Toolbar.makeWidgetsInvisible(self.loopList)
+        self.Toolbar.actions[u'Stop Loop'].setVisible(False)
         if item.is_text():
-            self.Toolbar.makeWidgetsInvisible(self.loopList)
             if QtCore.QSettings().value(
                 self.parent.songsSettingsSection + u'/show songbar',
                 QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
@@ -519,21 +513,21 @@
         """
         log.debug(u'processManagerItem')
         self.onStopLoop()
-        #If old item was a command tell it to stop        
+        #If old item was a command tell it to stop
         if self.serviceItem:
             if self.serviceItem.is_command():
-                Receiver.send_message(u'%s_stop' % 
+                Receiver.send_message(u'%s_stop' %
                     self.serviceItem.name.lower(), [serviceItem, self.isLive])
             if self.serviceItem.is_media():
                 self.onMediaStop()
         if serviceItem.is_media():
             self.onMediaStart(serviceItem)
-        if self.isLive:
-            blanked = self.blankButton.isChecked()
-        else:
-            blanked = False
-        Receiver.send_message(u'%s_start' % serviceItem.name.lower(),
-            [serviceItem, self.isLive, blanked, slideno])
+#        if self.isLive:
+#            blanked = self.blankButton.isChecked()
+#        else:
+#            blanked = False
+#        Receiver.send_message(u'%s_start' % serviceItem.name.lower(),
+#            [serviceItem, self.isLive, blanked, slideno])
         self.slideList = {}
         width = self.parent.ControlSplitter.sizes()[self.split]
         #Set pointing cursor when we have somthing to point at
@@ -661,7 +655,7 @@
         """
         log.debug(u'mainDisplaySetBackground')
         if not self.mainDisplay.primary:
-            self.blankButton.setChecked(True)
+            self.onBlankDisplay(True)
 
     def onSlideBlank(self):
         """
@@ -679,55 +673,55 @@
         """
         Handle the blank screen button actions
         """
-        log.debug(u'onBlankDisplay %d' % checked)
-        self.hideButton.setChecked(False)
-        self.themeButton.setChecked(False)
-        self.canDisplay = not checked
+        log.debug(u'onBlankDisplay %s' % checked)
+        self.HideMenu.setDefaultAction(self.BlankScreen)
+        self.BlankScreen.setChecked(checked)
+        self.ThemeScreen.setChecked(False)
+        self.DesktopScreen.setChecked(False)
         QtCore.QSettings().setValue(
             self.parent.generalSettingsSection + u'/screen blank',
             QtCore.QVariant(checked))
         if checked:
             Receiver.send_message(u'maindisplay_hide', HideMode.Blank)
-            self.blankPlugin(True)
         else:
             Receiver.send_message(u'maindisplay_show')
-            self.blankPlugin(False)
+        self.blankPlugin(checked)
 
     def onThemeDisplay(self, checked):
         """
         Handle the Theme screen button
         """
-        log.debug(u'onThemeDisplay %d' % checked)
-        self.blankButton.setChecked(False)
-        self.hideButton.setChecked(False)
-        self.canDisplay = False
+        log.debug(u'onThemeDisplay %s' % checked)
+        self.HideMenu.setDefaultAction(self.ThemeScreen)
+        self.BlankScreen.setChecked(False)
+        self.ThemeScreen.setChecked(checked)
+        self.DesktopScreen.setChecked(False)
         if checked:
             Receiver.send_message(u'maindisplay_hide', HideMode.Theme)
-            self.blankPlugin(True)
         else:
             Receiver.send_message(u'maindisplay_show')
-            self.blankPlugin(False)
+        self.blankPlugin(checked)
 
     def onHideDisplay(self, checked):
         """
         Handle the Hide screen button
         """
-        log.debug(u'onHideDisplay %d' % checked)
-        self.blankButton.setChecked(False)
-        self.themeButton.setChecked(False)
-        self.canDisplay = False
+        log.debug(u'onHideDisplay %s' % checked)
+        self.HideMenu.setDefaultAction(self.DesktopScreen)
+        self.BlankScreen.setChecked(False)
+        self.ThemeScreen.setChecked(False)
+        self.DesktopScreen.setChecked(checked)
         if checked:
             Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
-            self.hidePlugin(True)
         else:
             Receiver.send_message(u'maindisplay_show')
-            self.hidePlugin(False)
+        self.hidePlugin(checked)
 
     def blankPlugin(self, blank):
         """
         Blank the display screen within a plugin if required.
         """
-        log.debug(u'blankPlugin %d ', blank)
+        log.debug(u'blankPlugin %s ', blank)
         if self.serviceItem is not None:
             if blank:
                 Receiver.send_message(u'%s_blank'
@@ -740,8 +734,9 @@
 
     def hidePlugin(self, hide):
         """
-        Blank the display screen.
+        Tell the plugin to hide the display screen.
         """
+        log.debug(u'hidePlugin %s ', hide)
         if self.serviceItem is not None:
             if hide:
                 Receiver.send_message(u'%s_hide'
@@ -786,7 +781,7 @@
                 log.log(
                     15, u'Slide Rendering took %4s' % (time.time() - before))
                 if self.isLive:
-                    self.mainDisplay.frameView(frame, True, self.canDisplay)
+                    self.mainDisplay.frameView(frame, True)#, self.canDisplay)
             self.selectedRow = row
         Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
             row)
@@ -889,6 +884,8 @@
         if self.PreviewListWidget.rowCount() > 1:
             self.timer_id = self.startTimer(
                 int(self.DelaySpinBox.value()) * 1000)
+            self.Toolbar.actions[u'Stop Loop'].setVisible(True)
+            self.Toolbar.actions[u'Start Loop'].setVisible(False)
 
     def onStopLoop(self):
         """
@@ -897,6 +894,8 @@
         if self.timer_id != 0:
             self.killTimer(self.timer_id)
             self.timer_id = 0
+            self.Toolbar.actions[u'Start Loop'].setVisible(True)
+            self.Toolbar.actions[u'Stop Loop'].setVisible(False)
 
     def timerEvent(self, event):
         """
@@ -928,8 +927,7 @@
         """
         log.debug(u'SlideController onMediaStart')
         if self.isLive:
-            Receiver.send_message(u'videodisplay_start',
-                [item, self.blankButton.isChecked()])
+            Receiver.send_message(u'videodisplay_start', item)
         else:
             self.mediaObject.stop()
             self.mediaObject.clearQueue()

=== modified file 'openlp/core/ui/themestab.py'
--- openlp/core/ui/themestab.py	2010-06-18 23:18:08 +0000
+++ openlp/core/ui/themestab.py	2010-06-28 18:09:27 +0000
@@ -150,9 +150,9 @@
         settings.setValue(u'global theme',
             QtCore.QVariant(self.global_theme))
         settings.endGroup()
-        Receiver.send_message(u'theme_update_global', self.global_theme)
         self.parent.RenderManager.set_global_theme(
             self.global_theme, self.theme_level)
+        Receiver.send_message(u'theme_update_global', self.global_theme)
 
     def postSetUp(self):
         Receiver.send_message(u'theme_update_global', self.global_theme)

=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
--- openlp/plugins/alerts/lib/alertsmanager.py	2010-06-21 18:28:36 +0000
+++ openlp/plugins/alerts/lib/alertsmanager.py	2010-06-28 18:09:27 +0000
@@ -31,6 +31,15 @@
 
 log = logging.getLogger(__name__)
 
+HTMLCODE = u"""
+   <p style=\"color:%s;
+   background-color:%s;
+   font-family:%s;
+   font-size: %spt; \">
+    %s
+    </p>
+"""
+
 class AlertsManager(QtCore.QObject):
     """
     AlertsTab is the Alerts settings tab in the settings dialog.
@@ -47,28 +56,6 @@
             QtCore.SIGNAL(u'maindisplay_active'), self.generateAlert)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'alerts_text'), self.onAlertText)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
-
-    def screenChanged(self):
-        log.debug(u'screen changed')
-        self.alertTab = self.parent.alertsTab
-        self.screen = self.parent.maindisplay.screens.current
-        self.font = QtGui.QFont()
-        self.font.setFamily(self.alertTab.font_face)
-        self.font.setBold(True)
-        self.font.setPointSize(self.alertTab.font_size)
-        self.metrics = QtGui.QFontMetrics(self.font)
-        self.alertHeight = self.metrics.height() + 4
-        if self.alertTab.location == 0:
-            self.alertScreenPosition = 0
-        else:
-            self.alertScreenPosition = self.screen[u'size'].height() \
-                - self.alertHeight
-            self.alertHeight = self.screen[u'size'].height() \
-                - self.alertScreenPosition
-        self.parent.maindisplay.setAlertSize(self.alertScreenPosition,
-            self.alertHeight)
 
     def onAlertText(self, message):
         """
@@ -88,8 +75,6 @@
             display text
         """
         log.debug(u'display alert called %s' % text)
-        if not self.screen:
-            self.screenChanged()
         self.alertList.append(text)
         if self.timer_id != 0:
             Receiver.send_message(u'maindisplay_status_text',
@@ -100,37 +85,33 @@
         self.generateAlert()
 
     def generateAlert(self):
+        """
+        Format and request the Alert and start the timer
+        """
         log.debug(u'Generate Alert called')
         if len(self.alertList) == 0:
             return
         text = self.alertList.pop(0)
         alertTab = self.parent.alertsTab
-        alertframe = \
-            QtGui.QPixmap(self.screen[u'size'].width(), self.alertHeight)
-        alertframe.fill(QtCore.Qt.transparent)
-        painter = QtGui.QPainter(alertframe)
-        painter.fillRect(alertframe.rect(), QtCore.Qt.transparent)
-        painter.setRenderHint(QtGui.QPainter.Antialiasing)
-        painter.fillRect(
-            QtCore.QRect(
-                0, 0, alertframe.rect().width(),
-                alertframe.rect().height()),
-            QtGui.QColor(self.alertTab.bg_color))
-        painter.setFont(self.font)
-        painter.setPen(QtGui.QColor(self.alertTab.font_color))
-        x, y = (0, 2)
-        painter.drawText(
-            x, y + self.metrics.height() - self.metrics.descent() - 1, text)
-        painter.end()
-        self.parent.maindisplay.addAlertImage(alertframe)
+        text = HTMLCODE % (alertTab.font_color, alertTab.bg_color,
+                           alertTab.font_face, alertTab.font_size, text)
+        self.parent.preview_controller.parent.displayManager.addAlert(text, alertTab.location)
         # check to see if we have a timer running
         if self.timer_id == 0:
             self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
 
     def timerEvent(self, event):
+        """
+        Time has finished so if our time then request the next Alert
+        if there is one and reset the timer.
+        ``event``
+            the QT event that has been triggered.
+
+        """
         log.debug(u'timer event')
+        alertTab = self.parent.alertsTab
         if event.timerId() == self.timer_id:
-            self.parent.maindisplay.addAlertImage(None, True)
+            self.parent.preview_controller.parent.displayManager.addAlert(u'', alertTab.location)
         self.killTimer(self.timer_id)
         self.timer_id = 0
         self.generateAlert()

=== modified file 'openlp/plugins/alerts/lib/alertstab.py'
--- openlp/plugins/alerts/lib/alertstab.py	2010-06-21 16:47:34 +0000
+++ openlp/plugins/alerts/lib/alertstab.py	2010-06-28 18:09:27 +0000
@@ -128,6 +128,7 @@
         self.LocationComboBox = QtGui.QComboBox(self.LocationWidget)
         self.LocationComboBox.addItem(QtCore.QString())
         self.LocationComboBox.addItem(QtCore.QString())
+        self.LocationComboBox.addItem(QtCore.QString())
         self.LocationComboBox.setObjectName(u'LocationComboBox')
         self.LocationLayout.addWidget(self.LocationComboBox)
         self.LocationSpacer = QtGui.QSpacerItem(147, 20,
@@ -208,9 +209,11 @@
             translate('AlertsPlugin.AlertsTab', 'Preview'))
         self.FontPreview.setText(
             translate('AlertsPlugin.AlertsTab', 'openlp.org'))
-        self.LocationComboBox.setItemText(0, 
+        self.LocationComboBox.setItemText(0,
             translate('AlertsPlugin.AlertsTab', 'Top'))
-        self.LocationComboBox.setItemText(1, 
+        self.LocationComboBox.setItemText(1,
+            translate('AlertsPlugin.AlertsTab', 'Middle'))
+        self.LocationComboBox.setItemText(2,
             translate('AlertsPlugin.AlertsTab', 'Bottom'))
 
     def onBackgroundColorButtonClicked(self):
@@ -295,4 +298,4 @@
         font.setPointSize(self.font_size)
         self.FontPreview.setFont(font)
         self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' %
-            (self.bg_color, self.font_color))
\ No newline at end of file
+            (self.bg_color, self.font_color))


Follow ups