← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~milleja46/openlp/milleja46 into lp:openlp

 

Joshua Miller has proposed merging lp:~milleja46/openlp/milleja46 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~milleja46/openlp/milleja46/+merge/62141

Enables the looping or disabling the loop of slides based on a checkbox in the general settings section
-- 
https://code.launchpad.net/~milleja46/openlp/milleja46/+merge/62141
Your team OpenLP Core is requested to review the proposed merge of lp:~milleja46/openlp/milleja46 into lp:openlp.
=== modified file 'openlp.pyw'
--- openlp.pyw	2011-05-21 22:21:34 +0000
+++ openlp.pyw	2011-05-24 14:41:27 +0000
@@ -260,3 +260,4 @@
     Instantiate and run the application.
     """
     main()
+

=== modified file 'openlp/core/ui/generaltab.py'
--- openlp/core/ui/generaltab.py	2011-05-15 10:38:11 +0000
+++ openlp/core/ui/generaltab.py	2011-05-24 14:41:27 +0000
@@ -1,380 +1,390 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2011 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
-# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        #
-# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             #
-# --------------------------------------------------------------------------- #
-# 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                          #
-###############################################################################
-import logging
-
-from PyQt4 import QtCore, QtGui
-
-from openlp.core.lib import SettingsTab, Receiver, translate
-from openlp.core.lib.ui import UiStrings
-from openlp.core.ui import ScreenList
-
-log = logging.getLogger(__name__)
-
-class GeneralTab(SettingsTab):
-    """
-    GeneralTab is the general settings tab in the settings dialog.
-    """
-    def __init__(self, parent):
-        """
-        Initialise the general settings tab
-        """
-        self.screens = ScreenList.get_instance()
-        self.icon_path = u':/icon/openlp-logo-16x16.png'
-        generalTranslated = translate('GeneralTab', 'General')
-        SettingsTab.__init__(self, parent, u'General', generalTranslated)
-
-    def setupUi(self):
-        """
-        Create the user interface for the general settings tab
-        """
-        self.setObjectName(u'GeneralTab')
-        SettingsTab.setupUi(self)
-        self.monitorGroupBox = QtGui.QGroupBox(self.leftColumn)
-        self.monitorGroupBox.setObjectName(u'monitorGroupBox')
-        self.monitorLayout = QtGui.QFormLayout(self.monitorGroupBox)
-        self.monitorLayout.setObjectName(u'monitorLayout')
-        self.monitorLabel = QtGui.QLabel(self.monitorGroupBox)
-        self.monitorLabel.setObjectName(u'monitorLabel')
-        self.monitorLayout.addRow(self.monitorLabel)
-        self.monitorComboBox = QtGui.QComboBox(self.monitorGroupBox)
-        self.monitorComboBox.setObjectName(u'monitorComboBox')
-        self.monitorLayout.addRow(self.monitorComboBox)
-        self.displayOnMonitorCheck = QtGui.QCheckBox(self.monitorGroupBox)
-        self.displayOnMonitorCheck.setObjectName(u'monitorComboBox')
-        self.monitorLayout.addRow(self.displayOnMonitorCheck)
-        self.leftLayout.addWidget(self.monitorGroupBox)
-        self.startupGroupBox = QtGui.QGroupBox(self.leftColumn)
-        self.startupGroupBox.setObjectName(u'startupGroupBox')
-        self.startupLayout = QtGui.QVBoxLayout(self.startupGroupBox)
-        self.startupLayout.setObjectName(u'startupLayout')
-        self.warningCheckBox = QtGui.QCheckBox(self.startupGroupBox)
-        self.warningCheckBox.setObjectName(u'warningCheckBox')
-        self.startupLayout.addWidget(self.warningCheckBox)
-        self.autoOpenCheckBox = QtGui.QCheckBox(self.startupGroupBox)
-        self.autoOpenCheckBox.setObjectName(u'autoOpenCheckBox')
-        self.startupLayout.addWidget(self.autoOpenCheckBox)
-        self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox)
-        self.showSplashCheckBox.setObjectName(u'showSplashCheckBox')
-        self.startupLayout.addWidget(self.showSplashCheckBox)
-        self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox)
-        self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox')
-        self.startupLayout.addWidget(self.checkForUpdatesCheckBox)
-        self.leftLayout.addWidget(self.startupGroupBox)
-        self.settingsGroupBox = QtGui.QGroupBox(self.leftColumn)
-        self.settingsGroupBox.setObjectName(u'settingsGroupBox')
-        self.settingsLayout = QtGui.QFormLayout(self.settingsGroupBox)
-        self.settingsLayout.setObjectName(u'settingsLayout')
-        self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
-        self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox')
-        self.settingsLayout.addRow(self.saveCheckServiceCheckBox)
-        self.autoUnblankCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
-        self.autoUnblankCheckBox.setObjectName(u'autoUnblankCheckBox')
-        self.settingsLayout.addRow(self.autoUnblankCheckBox)
-        self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
-        self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox')
-        self.settingsLayout.addRow(self.autoPreviewCheckBox)
-        # Moved here from image tab
-        self.timeoutLabel = QtGui.QLabel(self.settingsGroupBox)
-        self.timeoutLabel.setObjectName(u'timeoutLabel')
-        self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox)
-        self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
-        self.timeoutSpinBox.setRange(1, 180)
-        self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
-        self.leftLayout.addWidget(self.settingsGroupBox)
-        self.leftLayout.addStretch()
-        self.ccliGroupBox = QtGui.QGroupBox(self.rightColumn)
-        self.ccliGroupBox.setObjectName(u'ccliGroupBox')
-        self.ccliLayout = QtGui.QFormLayout(self.ccliGroupBox)
-        self.ccliLayout.setObjectName(u'ccliLayout')
-        self.numberLabel = QtGui.QLabel(self.ccliGroupBox)
-        self.numberLabel.setObjectName(u'numberLabel')
-        self.numberEdit = QtGui.QLineEdit(self.ccliGroupBox)
-        self.numberEdit.setValidator(QtGui.QIntValidator())
-        self.numberEdit.setObjectName(u'numberEdit')
-        self.ccliLayout.addRow(self.numberLabel, self.numberEdit)
-        self.usernameLabel = QtGui.QLabel(self.ccliGroupBox)
-        self.usernameLabel.setObjectName(u'usernameLabel')
-        self.usernameEdit = QtGui.QLineEdit(self.ccliGroupBox)
-        self.usernameEdit.setObjectName(u'usernameEdit')
-        self.ccliLayout.addRow(self.usernameLabel, self.usernameEdit)
-        self.passwordLabel = QtGui.QLabel(self.ccliGroupBox)
-        self.passwordLabel.setObjectName(u'passwordLabel')
-        self.passwordEdit = QtGui.QLineEdit(self.ccliGroupBox)
-        self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password)
-        self.passwordEdit.setObjectName(u'passwordEdit')
-        self.ccliLayout.addRow(self.passwordLabel, self.passwordEdit)
-        self.rightLayout.addWidget(self.ccliGroupBox)
-        # Moved here from display tab
-        self.displayGroupBox = QtGui.QGroupBox(self.rightColumn)
-        self.displayGroupBox.setObjectName(u'displayGroupBox')
-        self.displayLayout = QtGui.QGridLayout(self.displayGroupBox)
-        self.displayLayout.setObjectName(u'displayLayout')
-        self.overrideCheckBox = QtGui.QCheckBox(self.displayGroupBox)
-        self.overrideCheckBox.setObjectName(u'overrideCheckBox')
-        self.displayLayout.addWidget(self.overrideCheckBox, 2, 0, 1, 4)
-        self.rightLayout.addWidget(self.displayGroupBox)
-        # Custom position
-        self.customXLabel = QtGui.QLabel(self.displayGroupBox)
-        self.customXLabel.setObjectName(u'customXLabel')
-        self.displayLayout.addWidget(self.customXLabel, 3, 0)
-        self.customXValueEdit = QtGui.QSpinBox(self.displayGroupBox)
-        self.customXValueEdit.setObjectName(u'customXValueEdit')
-        self.customXValueEdit.setRange(-9999, 9999)
-        self.displayLayout.addWidget(self.customXValueEdit, 4, 0)
-        self.customYLabel = QtGui.QLabel(self.displayGroupBox)
-        self.customYLabel.setObjectName(u'customYLabel')
-        self.displayLayout.addWidget(self.customYLabel, 3, 1)
-        self.customYValueEdit = QtGui.QSpinBox(self.displayGroupBox)
-        self.customYValueEdit.setObjectName(u'customYValueEdit')
-        self.customYValueEdit.setRange(-9999, 9999)
-        self.displayLayout.addWidget(self.customYValueEdit, 4, 1)
-        self.customWidthLabel = QtGui.QLabel(self.displayGroupBox)
-        self.customWidthLabel.setObjectName(u'customWidthLabel')
-        self.displayLayout.addWidget(self.customWidthLabel, 3, 2)
-        self.customWidthValueEdit = QtGui.QSpinBox(self.displayGroupBox)
-        self.customWidthValueEdit.setObjectName(u'customWidthValueEdit')
-        self.customWidthValueEdit.setMaximum(9999)
-        self.displayLayout.addWidget(self.customWidthValueEdit, 4, 2)
-        self.customHeightLabel = QtGui.QLabel(self.displayGroupBox)
-        self.customHeightLabel.setObjectName(u'customHeightLabel')
-        self.displayLayout.addWidget(self.customHeightLabel, 3, 3)
-        self.customHeightValueEdit = QtGui.QSpinBox(self.displayGroupBox)
-        self.customHeightValueEdit.setObjectName(u'customHeightValueEdit')
-        self.customHeightValueEdit.setMaximum(9999)
-        self.displayLayout.addWidget(self.customHeightValueEdit, 4, 3)
-        self.rightLayout.addWidget(self.displayGroupBox)
-        self.rightLayout.addStretch()
-        # Signals and slots
-        QtCore.QObject.connect(self.overrideCheckBox,
-            QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideCheckBoxToggled)
-        QtCore.QObject.connect(self.customHeightValueEdit,
-            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
-        QtCore.QObject.connect(self.customWidthValueEdit,
-            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
-        QtCore.QObject.connect(self.customYValueEdit,
-            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
-        QtCore.QObject.connect(self.customXValueEdit,
-            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
-        QtCore.QObject.connect(self.monitorComboBox,
-            QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onDisplayChanged)
-        # Reload the tab, as the screen resolution/count may have changed.
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'config_screen_changed'), self.load)
-        # Remove for now
-        self.usernameLabel.setVisible(False)
-        self.usernameEdit.setVisible(False)
-        self.passwordLabel.setVisible(False)
-        self.passwordEdit.setVisible(False)
-
-    def retranslateUi(self):
-        """
-        Translate the general settings tab to the currently selected language
-        """
-        self.tabTitleVisible = translate('OpenLP.GeneralTab', 'General')
-        self.monitorGroupBox.setTitle(translate('OpenLP.GeneralTab',
-            'Monitors'))
-        self.monitorLabel.setText(translate('OpenLP.GeneralTab',
-            'Select monitor for output display:'))
-        self.displayOnMonitorCheck.setText(
-            translate('OpenLP.GeneralTab', 'Display if a single screen'))
-        self.startupGroupBox.setTitle(
-            translate('OpenLP.GeneralTab', 'Application Startup'))
-        self.warningCheckBox.setText(
-            translate('OpenLP.GeneralTab', 'Show blank screen warning'))
-        self.autoOpenCheckBox.setText(translate('OpenLP.GeneralTab',
-            'Automatically open the last service'))
-        self.showSplashCheckBox.setText(
-            translate('OpenLP.GeneralTab', 'Show the splash screen'))
-        self.checkForUpdatesCheckBox.setText(
-            translate('OpenLP.GeneralTab', 'Check for updates to OpenLP'))
-        self.settingsGroupBox.setTitle(
-            translate('OpenLP.GeneralTab', 'Application Settings'))
-        self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab',
-            'Prompt to save before starting a new service'))
-        self.autoUnblankCheckBox.setText(translate('OpenLP.GeneralTab',
-            'Unblank display when adding new live item'))
-        self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab',
-            'Automatically preview next item in service'))
-        self.timeoutLabel.setText(translate('OpenLP.GeneralTab',
-            'Slide loop delay:'))
-        self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec'))
-        self.ccliGroupBox.setTitle(
-            translate('OpenLP.GeneralTab', 'CCLI Details'))
-        self.numberLabel.setText(UiStrings().CCLINumberLabel)
-        self.usernameLabel.setText(
-            translate('OpenLP.GeneralTab', 'SongSelect username:'))
-        self.passwordLabel.setText(
-            translate('OpenLP.GeneralTab', 'SongSelect password:'))
-        # Moved from display tab
-        self.displayGroupBox.setTitle(
-            translate('OpenLP.GeneralTab', 'Display Position'))
-        self.overrideCheckBox.setText(translate('OpenLP.GeneralTab',
-            'Override display position'))
-        self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X'))
-        self.customYLabel.setText(translate('OpenLP.GeneralTab', 'Y'))
-        self.customHeightLabel.setText(translate('OpenLP.GeneralTab', 'Height'))
-        self.customWidthLabel.setText(translate('OpenLP.GeneralTab', 'Width'))
-
-    def load(self):
-        """
-        Load the settings to populate the form
-        """
-        settings = QtCore.QSettings()
-        settings.beginGroup(self.settingsSection)
-        self.monitorComboBox.clear()
-        self.monitorComboBox.addItems(self.screens.get_screen_list())
-        monitorNumber = settings.value(u'monitor',
-            QtCore.QVariant(self.screens.display_count - 1)).toInt()[0]
-        self.monitorComboBox.setCurrentIndex(monitorNumber)
-        self.numberEdit.setText(unicode(settings.value(
-            u'ccli number', QtCore.QVariant(u'')).toString()))
-        self.usernameEdit.setText(unicode(settings.value(
-            u'songselect username', QtCore.QVariant(u'')).toString()))
-        self.passwordEdit.setText(unicode(settings.value(
-            u'songselect password', QtCore.QVariant(u'')).toString()))
-        self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt',
-            QtCore.QVariant(False)).toBool())
-        self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank',
-            QtCore.QVariant(False)).toBool())
-        self.displayOnMonitorCheck.setChecked(self.screens.display)
-        self.warningCheckBox.setChecked(settings.value(u'blank warning',
-            QtCore.QVariant(False)).toBool())
-        self.autoOpenCheckBox.setChecked(settings.value(u'auto open',
-            QtCore.QVariant(False)).toBool())
-        self.showSplashCheckBox.setChecked(settings.value(u'show splash',
-            QtCore.QVariant(True)).toBool())
-        self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check',
-            QtCore.QVariant(True)).toBool())
-        self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview',
-            QtCore.QVariant(False)).toBool())
-        self.timeoutSpinBox.setValue(settings.value(u'loop delay',
-           QtCore.QVariant(5)).toInt()[0])
-        self.overrideCheckBox.setChecked(settings.value(u'override position',
-            QtCore.QVariant(False)).toBool())
-        self.customXValueEdit.setValue(settings.value(u'x position',
-            QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0])
-        self.customYValueEdit.setValue(settings.value(u'y position',
-            QtCore.QVariant(self.screens.current[u'size'].y())).toInt()[0])
-        self.customHeightValueEdit.setValue(settings.value(u'height',
-            QtCore.QVariant(self.screens.current[u'size'].height())).toInt()[0])
-        self.customWidthValueEdit.setValue(settings.value(u'width',
-            QtCore.QVariant(self.screens.current[u'size'].width())).toInt()[0])
-        settings.endGroup()
-        self.customXValueEdit.setEnabled(self.overrideCheckBox.isChecked())
-        self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked())
-        self.customHeightValueEdit.setEnabled(self.overrideCheckBox.isChecked())
-        self.customWidthValueEdit.setEnabled(self.overrideCheckBox.isChecked())
-        self.display_changed = False
-
-    def save(self):
-        """
-        Save the settings from the form
-        """
-        settings = QtCore.QSettings()
-        settings.beginGroup(self.settingsSection)
-        settings.setValue(u'monitor',
-            QtCore.QVariant(self.monitorComboBox.currentIndex()))
-        settings.setValue(u'display on monitor',
-            QtCore.QVariant(self.displayOnMonitorCheck.isChecked()))
-        settings.setValue(u'blank warning',
-            QtCore.QVariant(self.warningCheckBox.isChecked()))
-        settings.setValue(u'auto open',
-            QtCore.QVariant(self.autoOpenCheckBox.isChecked()))
-        settings.setValue(u'show splash',
-            QtCore.QVariant(self.showSplashCheckBox.isChecked()))
-        settings.setValue(u'update check',
-            QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked()))
-        settings.setValue(u'save prompt',
-            QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked()))
-        settings.setValue(u'auto unblank',
-            QtCore.QVariant(self.autoUnblankCheckBox.isChecked()))
-        settings.setValue(u'auto preview',
-            QtCore.QVariant(self.autoPreviewCheckBox.isChecked()))
-        settings.setValue(u'loop delay',
-            QtCore.QVariant(self.timeoutSpinBox.value()))
-        settings.setValue(u'ccli number',
-            QtCore.QVariant(self.numberEdit.displayText()))
-        settings.setValue(u'songselect username',
-            QtCore.QVariant(self.usernameEdit.displayText()))
-        settings.setValue(u'songselect password',
-            QtCore.QVariant(self.passwordEdit.displayText()))
-        settings.setValue(u'x position',
-            QtCore.QVariant(self.customXValueEdit.value()))
-        settings.setValue(u'y position',
-            QtCore.QVariant(self.customYValueEdit.value()))
-        settings.setValue(u'height',
-            QtCore.QVariant(self.customHeightValueEdit.value()))
-        settings.setValue(u'width',
-            QtCore.QVariant(self.customWidthValueEdit.value()))
-        settings.setValue(u'override position',
-            QtCore.QVariant(self.overrideCheckBox.isChecked()))
-        settings.endGroup()
-        # On save update the screens as well
-        self.postSetUp(True)
-
-    def postSetUp(self, postUpdate=False):
-        """
-        Apply settings after settings tab has loaded and most of the
-        system so must be delayed
-        """
-        Receiver.send_message(u'slidecontroller_live_spin_delay',
-            self.timeoutSpinBox.value())
-        # Do not continue on start up.
-        if not postUpdate:
-            return
-        self.screens.set_current_display(self.monitorComboBox.currentIndex())
-        self.screens.display = self.displayOnMonitorCheck.isChecked()
-        self.screens.override[u'size'] = QtCore.QRect(
-            self.customXValueEdit.value(),
-            self.customYValueEdit.value(),
-            self.customWidthValueEdit.value(),
-            self.customHeightValueEdit.value())
-        if self.overrideCheckBox.isChecked():
-            self.screens.set_override_display()
-        else:
-            self.screens.reset_current_display()
-        if self.display_changed:
-            Receiver.send_message(u'config_screen_changed')
-        self.display_changed = False
-
-    def onOverrideCheckBoxToggled(self, checked):
-        """
-        Toggle screen state depending on check box state.
-
-        ``checked``
-            The state of the check box (boolean).
-        """
-        self.customXValueEdit.setEnabled(checked)
-        self.customYValueEdit.setEnabled(checked)
-        self.customHeightValueEdit.setEnabled(checked)
-        self.customWidthValueEdit.setEnabled(checked)
-        self.display_changed = True
-
-    def onDisplayChanged(self):
-        """
-        Called when the width, height, x position or y position has changed.
-        """
-        self.display_changed = True
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        #
+# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             #
+# --------------------------------------------------------------------------- #
+# 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                          #
+###############################################################################
+import logging
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import SettingsTab, Receiver, translate
+from openlp.core.lib.ui import UiStrings
+from openlp.core.ui import ScreenList
+
+log = logging.getLogger(__name__)
+
+class GeneralTab(SettingsTab):
+    """
+    GeneralTab is the general settings tab in the settings dialog.
+    """
+    def __init__(self, parent):
+        """
+        Initialise the general settings tab
+        """
+        self.screens = ScreenList.get_instance()
+        self.icon_path = u':/icon/openlp-logo-16x16.png'
+        generalTranslated = translate('GeneralTab', 'General')
+        SettingsTab.__init__(self, parent, u'General', generalTranslated)
+
+    def setupUi(self):
+        """
+        Create the user interface for the general settings tab
+        """
+        self.setObjectName(u'GeneralTab')
+        SettingsTab.setupUi(self)
+        self.monitorGroupBox = QtGui.QGroupBox(self.leftColumn)
+        self.monitorGroupBox.setObjectName(u'monitorGroupBox')
+        self.monitorLayout = QtGui.QFormLayout(self.monitorGroupBox)
+        self.monitorLayout.setObjectName(u'monitorLayout')
+        self.monitorLabel = QtGui.QLabel(self.monitorGroupBox)
+        self.monitorLabel.setObjectName(u'monitorLabel')
+        self.monitorLayout.addRow(self.monitorLabel)
+        self.monitorComboBox = QtGui.QComboBox(self.monitorGroupBox)
+        self.monitorComboBox.setObjectName(u'monitorComboBox')
+        self.monitorLayout.addRow(self.monitorComboBox)
+        self.displayOnMonitorCheck = QtGui.QCheckBox(self.monitorGroupBox)
+        self.displayOnMonitorCheck.setObjectName(u'monitorComboBox')
+        self.monitorLayout.addRow(self.displayOnMonitorCheck)
+        self.leftLayout.addWidget(self.monitorGroupBox)
+        self.startupGroupBox = QtGui.QGroupBox(self.leftColumn)
+        self.startupGroupBox.setObjectName(u'startupGroupBox')
+        self.startupLayout = QtGui.QVBoxLayout(self.startupGroupBox)
+        self.startupLayout.setObjectName(u'startupLayout')
+        self.warningCheckBox = QtGui.QCheckBox(self.startupGroupBox)
+        self.warningCheckBox.setObjectName(u'warningCheckBox')
+        self.startupLayout.addWidget(self.warningCheckBox)
+        self.autoOpenCheckBox = QtGui.QCheckBox(self.startupGroupBox)
+        self.autoOpenCheckBox.setObjectName(u'autoOpenCheckBox')
+        self.startupLayout.addWidget(self.autoOpenCheckBox)
+        self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox)
+        self.showSplashCheckBox.setObjectName(u'showSplashCheckBox')
+        self.startupLayout.addWidget(self.showSplashCheckBox)
+        self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox)
+        self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox')
+        self.startupLayout.addWidget(self.checkForUpdatesCheckBox)
+        self.leftLayout.addWidget(self.startupGroupBox)
+        self.settingsGroupBox = QtGui.QGroupBox(self.leftColumn)
+        self.settingsGroupBox.setObjectName(u'settingsGroupBox')
+        self.settingsLayout = QtGui.QFormLayout(self.settingsGroupBox)
+        self.settingsLayout.setObjectName(u'settingsLayout')
+        self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
+        self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox')
+        self.settingsLayout.addRow(self.saveCheckServiceCheckBox)
+        self.autoUnblankCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
+        self.autoUnblankCheckBox.setObjectName(u'autoUnblankCheckBox')
+        self.settingsLayout.addRow(self.autoUnblankCheckBox)
+        self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
+        self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox')
+        self.settingsLayout.addRow(self.autoPreviewCheckBox)
+        self.enableLoopCheckbox = QtGui.QCheckBox(self.settingsGroupBox)
+        self.enableLoopCheckbox.setObjectName(u'enableLoopCheckbox')
+        self.settingsLayout.addRow(self.enableLoopCheckbox)
+        # Moved here from image tab
+        self.timeoutLabel = QtGui.QLabel(self.settingsGroupBox)
+        self.timeoutLabel.setObjectName(u'timeoutLabel')
+        self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox)
+        self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
+        self.timeoutSpinBox.setRange(1, 180)
+        self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
+        self.leftLayout.addWidget(self.settingsGroupBox)
+        self.leftLayout.addStretch()
+        self.ccliGroupBox = QtGui.QGroupBox(self.rightColumn)
+        self.ccliGroupBox.setObjectName(u'ccliGroupBox')
+        self.ccliLayout = QtGui.QFormLayout(self.ccliGroupBox)
+        self.ccliLayout.setObjectName(u'ccliLayout')
+        self.numberLabel = QtGui.QLabel(self.ccliGroupBox)
+        self.numberLabel.setObjectName(u'numberLabel')
+        self.numberEdit = QtGui.QLineEdit(self.ccliGroupBox)
+        self.numberEdit.setValidator(QtGui.QIntValidator())
+        self.numberEdit.setObjectName(u'numberEdit')
+        self.ccliLayout.addRow(self.numberLabel, self.numberEdit)
+        self.usernameLabel = QtGui.QLabel(self.ccliGroupBox)
+        self.usernameLabel.setObjectName(u'usernameLabel')
+        self.usernameEdit = QtGui.QLineEdit(self.ccliGroupBox)
+        self.usernameEdit.setObjectName(u'usernameEdit')
+        self.ccliLayout.addRow(self.usernameLabel, self.usernameEdit)
+        self.passwordLabel = QtGui.QLabel(self.ccliGroupBox)
+        self.passwordLabel.setObjectName(u'passwordLabel')
+        self.passwordEdit = QtGui.QLineEdit(self.ccliGroupBox)
+        self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password)
+        self.passwordEdit.setObjectName(u'passwordEdit')
+        self.ccliLayout.addRow(self.passwordLabel, self.passwordEdit)
+        self.rightLayout.addWidget(self.ccliGroupBox)
+        # Moved here from display tab
+        self.displayGroupBox = QtGui.QGroupBox(self.rightColumn)
+        self.displayGroupBox.setObjectName(u'displayGroupBox')
+        self.displayLayout = QtGui.QGridLayout(self.displayGroupBox)
+        self.displayLayout.setObjectName(u'displayLayout')
+        self.overrideCheckBox = QtGui.QCheckBox(self.displayGroupBox)
+        self.overrideCheckBox.setObjectName(u'overrideCheckBox')
+        self.displayLayout.addWidget(self.overrideCheckBox, 2, 0, 1, 4)
+        self.rightLayout.addWidget(self.displayGroupBox)
+        # Custom position
+        self.customXLabel = QtGui.QLabel(self.displayGroupBox)
+        self.customXLabel.setObjectName(u'customXLabel')
+        self.displayLayout.addWidget(self.customXLabel, 3, 0)
+        self.customXValueEdit = QtGui.QSpinBox(self.displayGroupBox)
+        self.customXValueEdit.setObjectName(u'customXValueEdit')
+        self.customXValueEdit.setRange(-9999, 9999)
+        self.displayLayout.addWidget(self.customXValueEdit, 4, 0)
+        self.customYLabel = QtGui.QLabel(self.displayGroupBox)
+        self.customYLabel.setObjectName(u'customYLabel')
+        self.displayLayout.addWidget(self.customYLabel, 3, 1)
+        self.customYValueEdit = QtGui.QSpinBox(self.displayGroupBox)
+        self.customYValueEdit.setObjectName(u'customYValueEdit')
+        self.customYValueEdit.setRange(-9999, 9999)
+        self.displayLayout.addWidget(self.customYValueEdit, 4, 1)
+        self.customWidthLabel = QtGui.QLabel(self.displayGroupBox)
+        self.customWidthLabel.setObjectName(u'customWidthLabel')
+        self.displayLayout.addWidget(self.customWidthLabel, 3, 2)
+        self.customWidthValueEdit = QtGui.QSpinBox(self.displayGroupBox)
+        self.customWidthValueEdit.setObjectName(u'customWidthValueEdit')
+        self.customWidthValueEdit.setMaximum(9999)
+        self.displayLayout.addWidget(self.customWidthValueEdit, 4, 2)
+        self.customHeightLabel = QtGui.QLabel(self.displayGroupBox)
+        self.customHeightLabel.setObjectName(u'customHeightLabel')
+        self.displayLayout.addWidget(self.customHeightLabel, 3, 3)
+        self.customHeightValueEdit = QtGui.QSpinBox(self.displayGroupBox)
+        self.customHeightValueEdit.setObjectName(u'customHeightValueEdit')
+        self.customHeightValueEdit.setMaximum(9999)
+        self.displayLayout.addWidget(self.customHeightValueEdit, 4, 3)
+        self.rightLayout.addWidget(self.displayGroupBox)
+        self.rightLayout.addStretch()
+        # Signals and slots
+        QtCore.QObject.connect(self.overrideCheckBox,
+            QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideCheckBoxToggled)
+        QtCore.QObject.connect(self.customHeightValueEdit,
+            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
+        QtCore.QObject.connect(self.customWidthValueEdit,
+            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
+        QtCore.QObject.connect(self.customYValueEdit,
+            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
+        QtCore.QObject.connect(self.customXValueEdit,
+            QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
+        QtCore.QObject.connect(self.monitorComboBox,
+            QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onDisplayChanged)
+        # Reload the tab, as the screen resolution/count may have changed.
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'config_screen_changed'), self.load)
+        # Remove for now
+        self.usernameLabel.setVisible(False)
+        self.usernameEdit.setVisible(False)
+        self.passwordLabel.setVisible(False)
+        self.passwordEdit.setVisible(False)
+
+    def retranslateUi(self):
+        """
+        Translate the general settings tab to the currently selected language
+        """
+        self.tabTitleVisible = translate('OpenLP.GeneralTab', 'General')
+        self.monitorGroupBox.setTitle(translate('OpenLP.GeneralTab',
+            'Monitors'))
+        self.monitorLabel.setText(translate('OpenLP.GeneralTab',
+            'Select monitor for output display:'))
+        self.displayOnMonitorCheck.setText(
+            translate('OpenLP.GeneralTab', 'Display if a single screen'))
+        self.startupGroupBox.setTitle(
+            translate('OpenLP.GeneralTab', 'Application Startup'))
+        self.warningCheckBox.setText(
+            translate('OpenLP.GeneralTab', 'Show blank screen warning'))
+        self.autoOpenCheckBox.setText(translate('OpenLP.GeneralTab',
+            'Automatically open the last service'))
+        self.showSplashCheckBox.setText(
+            translate('OpenLP.GeneralTab', 'Show the splash screen'))
+        self.checkForUpdatesCheckBox.setText(
+            translate('OpenLP.GeneralTab', 'Check for updates to OpenLP'))
+        self.settingsGroupBox.setTitle(
+            translate('OpenLP.GeneralTab', 'Application Settings'))
+        self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab',
+            'Prompt to save before starting a new service'))
+        self.autoUnblankCheckBox.setText(translate('OpenLP.GeneralTab',
+            'Unblank display when adding new live item'))
+        self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab',
+            'Automatically preview next item in service'))
+        self.enableLoopCheckbox.setText(translate('OpenLP.GeneralTab',
+            'enable slide loop'))
+        self.timeoutLabel.setText(translate('OpenLP.GeneralTab',
+            'Slide loop delay:'))
+        self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec'))
+        self.ccliGroupBox.setTitle(
+            translate('OpenLP.GeneralTab', 'CCLI Details'))
+        self.numberLabel.setText(UiStrings().CCLINumberLabel)
+        self.usernameLabel.setText(
+            translate('OpenLP.GeneralTab', 'SongSelect username:'))
+        self.passwordLabel.setText(
+            translate('OpenLP.GeneralTab', 'SongSelect password:'))
+        # Moved from display tab
+        self.displayGroupBox.setTitle(
+            translate('OpenLP.GeneralTab', 'Display Position'))
+        self.overrideCheckBox.setText(translate('OpenLP.GeneralTab',
+            'Override display position'))
+        self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X'))
+        self.customYLabel.setText(translate('OpenLP.GeneralTab', 'Y'))
+        self.customHeightLabel.setText(translate('OpenLP.GeneralTab', 'Height'))
+        self.customWidthLabel.setText(translate('OpenLP.GeneralTab', 'Width'))
+
+    def load(self):
+        """
+        Load the settings to populate the form
+        """
+        settings = QtCore.QSettings()
+        settings.beginGroup(self.settingsSection)
+        self.monitorComboBox.clear()
+        self.monitorComboBox.addItems(self.screens.get_screen_list())
+        monitorNumber = settings.value(u'monitor',
+            QtCore.QVariant(self.screens.display_count - 1)).toInt()[0]
+        self.monitorComboBox.setCurrentIndex(monitorNumber)
+        self.numberEdit.setText(unicode(settings.value(
+            u'ccli number', QtCore.QVariant(u'')).toString()))
+        self.usernameEdit.setText(unicode(settings.value(
+            u'songselect username', QtCore.QVariant(u'')).toString()))
+        self.passwordEdit.setText(unicode(settings.value(
+            u'songselect password', QtCore.QVariant(u'')).toString()))
+        self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt',
+            QtCore.QVariant(False)).toBool())
+        self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank',
+            QtCore.QVariant(False)).toBool())
+        self.displayOnMonitorCheck.setChecked(self.screens.display)
+        self.warningCheckBox.setChecked(settings.value(u'blank warning',
+            QtCore.QVariant(False)).toBool())
+        self.autoOpenCheckBox.setChecked(settings.value(u'auto open',
+            QtCore.QVariant(False)).toBool())
+        self.showSplashCheckBox.setChecked(settings.value(u'show splash',
+            QtCore.QVariant(True)).toBool())
+        self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check',
+            QtCore.QVariant(False)).toBool())
+        self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview',
+            QtCore.QVariant(False)).toBool())
+        self.enableLoopCheckbox.setChecked(settings.value(u'enable slide loop',
+            QtCore.QVariant(True)).toBool())
+        self.timeoutSpinBox.setValue(settings.value(u'loop delay',
+           QtCore.QVariant(5)).toInt()[0])
+        self.overrideCheckBox.setChecked(settings.value(u'override position',
+            QtCore.QVariant(False)).toBool())
+        self.customXValueEdit.setValue(settings.value(u'x position',
+            QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0])
+        self.customYValueEdit.setValue(settings.value(u'y position',
+            QtCore.QVariant(self.screens.current[u'size'].y())).toInt()[0])
+        self.customHeightValueEdit.setValue(settings.value(u'height',
+            QtCore.QVariant(self.screens.current[u'size'].height())).toInt()[0])
+        self.customWidthValueEdit.setValue(settings.value(u'width',
+            QtCore.QVariant(self.screens.current[u'size'].width())).toInt()[0])
+        settings.endGroup()
+        self.customXValueEdit.setEnabled(self.overrideCheckBox.isChecked())
+        self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked())
+        self.customHeightValueEdit.setEnabled(self.overrideCheckBox.isChecked())
+        self.customWidthValueEdit.setEnabled(self.overrideCheckBox.isChecked())
+        self.display_changed = False
+
+    def save(self):
+        """
+        Save the settings from the form
+        """
+        settings = QtCore.QSettings()
+        settings.beginGroup(self.settingsSection)
+        settings.setValue(u'monitor',
+            QtCore.QVariant(self.monitorComboBox.currentIndex()))
+        settings.setValue(u'display on monitor',
+            QtCore.QVariant(self.displayOnMonitorCheck.isChecked()))
+        settings.setValue(u'blank warning',
+            QtCore.QVariant(self.warningCheckBox.isChecked()))
+        settings.setValue(u'auto open',
+            QtCore.QVariant(self.autoOpenCheckBox.isChecked()))
+        settings.setValue(u'show splash',
+            QtCore.QVariant(self.showSplashCheckBox.isChecked()))
+        settings.setValue(u'update check',
+            QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked()))
+        settings.setValue(u'save prompt',
+            QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked()))
+        settings.setValue(u'auto unblank',
+            QtCore.QVariant(self.autoUnblankCheckBox.isChecked()))
+        settings.setValue(u'auto preview',
+            QtCore.QVariant(self.autoPreviewCheckBox.isChecked()))
+        settings.setValue(u'enable slide loop',
+            QtCore.QVariant(self.enableLoopCheckbox.isChecked()))
+        settings.setValue(u'loop delay',
+            QtCore.QVariant(self.timeoutSpinBox.value()))
+        settings.setValue(u'ccli number',
+            QtCore.QVariant(self.numberEdit.displayText()))
+        settings.setValue(u'songselect username',
+            QtCore.QVariant(self.usernameEdit.displayText()))
+        settings.setValue(u'songselect password',
+            QtCore.QVariant(self.passwordEdit.displayText()))
+        settings.setValue(u'x position',
+            QtCore.QVariant(self.customXValueEdit.value()))
+        settings.setValue(u'y position',
+            QtCore.QVariant(self.customYValueEdit.value()))
+        settings.setValue(u'height',
+            QtCore.QVariant(self.customHeightValueEdit.value()))
+        settings.setValue(u'width',
+            QtCore.QVariant(self.customWidthValueEdit.value()))
+        settings.setValue(u'override position',
+            QtCore.QVariant(self.overrideCheckBox.isChecked()))
+        settings.endGroup()
+        # On save update the screens as well
+        self.postSetUp(True)
+
+    def postSetUp(self, postUpdate=False):
+        """
+        Apply settings after settings tab has loaded and most of the
+        system so must be delayed
+        """
+        Receiver.send_message(u'slidecontroller_live_spin_delay',
+            self.timeoutSpinBox.value())
+        # Do not continue on start up.
+        if not postUpdate:
+            return
+        self.screens.set_current_display(self.monitorComboBox.currentIndex())
+        self.screens.display = self.displayOnMonitorCheck.isChecked()
+        self.screens.override[u'size'] = QtCore.QRect(
+            self.customXValueEdit.value(),
+            self.customYValueEdit.value(),
+            self.customWidthValueEdit.value(),
+            self.customHeightValueEdit.value())
+        if self.overrideCheckBox.isChecked():
+            self.screens.set_override_display()
+        else:
+            self.screens.reset_current_display()
+        if self.display_changed:
+            Receiver.send_message(u'config_screen_changed')
+        self.display_changed = False
+
+    def onOverrideCheckBoxToggled(self, checked):
+        """
+        Toggle screen state depending on check box state.
+
+        ``checked``
+            The state of the check box (boolean).
+        """
+        self.customXValueEdit.setEnabled(checked)
+        self.customYValueEdit.setEnabled(checked)
+        self.customHeightValueEdit.setEnabled(checked)
+        self.customWidthValueEdit.setEnabled(checked)
+        self.display_changed = True
+
+    def onDisplayChanged(self):
+        """
+        Called when the width, height, x position or y position has changed.
+        """
+        self.display_changed = True
+

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2011-05-21 20:21:05 +0000
+++ openlp/core/ui/slidecontroller.py	2011-05-24 14:41:27 +0000
@@ -1,3 +1,4 @@
+<<<<<<< TREE
 # -*- coding: utf-8 -*-
 # vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
 
@@ -1187,3 +1188,1161 @@
             return HideMode.Screen
         else:
             return None
+=======
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        #
+# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             #
+# --------------------------------------------------------------------------- #
+# 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                          #
+###############################################################################
+
+import logging
+import os
+
+from PyQt4 import QtCore, QtGui
+from PyQt4.phonon import Phonon
+
+from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
+    ItemCapabilities, translate
+from openlp.core.lib.ui import UiStrings, shortcut_action
+from openlp.core.ui import HideMode, MainDisplay, ScreenList
+from openlp.core.utils.actions import ActionList, CategoryOrder
+
+log = logging.getLogger(__name__)
+
+class SlideList(QtGui.QTableWidget):
+    """
+    Customised version of QTableWidget which can respond to keyboard
+    events.
+    """
+    def __init__(self, parent=None, name=None):
+        QtGui.QTableWidget.__init__(self, parent.controller)
+        self.parent = parent
+
+
+class SlideController(QtGui.QWidget):
+    """
+    SlideController is the slide controller widget. This widget is what the
+    user uses to control the displaying of verses/slides/etc on the screen.
+    """
+    def __init__(self, parent, isLive=False):
+        """
+        Set up the Slide Controller.
+        """
+        QtGui.QWidget.__init__(self, parent)
+        self.isLive = isLive
+        self.parent = parent
+        self.screens = ScreenList.get_instance()
+        self.ratio = float(self.screens.current[u'size'].width()) / \
+            float(self.screens.current[u'size'].height())
+        self.image_manager = self.parent.image_manager
+        self.loopList = [
+            u'Start Loop',
+            u'Loop Separator',
+            u'Image SpinBox'
+        ]
+        self.songEditList = [
+            u'Edit Song',
+        ]
+        self.volume = 10
+        self.timer_id = 0
+        self.songEdit = False
+        self.selectedRow = 0
+        self.serviceItem = None
+        self.alertTab = None
+        self.panel = QtGui.QWidget(parent.controlSplitter)
+        self.slideList = {}
+        # Layout for holding panel
+        self.panelLayout = QtGui.QVBoxLayout(self.panel)
+        self.panelLayout.setSpacing(0)
+        self.panelLayout.setMargin(0)
+        # Type label for the top of the slide controller
+        self.typeLabel = QtGui.QLabel(self.panel)
+        if self.isLive:
+            self.typeLabel.setText(UiStrings().Live)
+            self.split = 1
+            self.typePrefix = u'live'
+        else:
+            self.typeLabel.setText(UiStrings().Preview)
+            self.split = 0
+            self.typePrefix = u'preview'
+        self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;')
+        self.typeLabel.setAlignment(QtCore.Qt.AlignCenter)
+        self.panelLayout.addWidget(self.typeLabel)
+        # Splitter
+        self.splitter = QtGui.QSplitter(self.panel)
+        self.splitter.setOrientation(QtCore.Qt.Vertical)
+        self.panelLayout.addWidget(self.splitter)
+        # Actual controller section
+        self.controller = QtGui.QWidget(self.splitter)
+        self.controller.setGeometry(QtCore.QRect(0, 0, 100, 536))
+        self.controller.setSizePolicy(
+            QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
+            QtGui.QSizePolicy.Maximum))
+        self.controllerLayout = QtGui.QVBoxLayout(self.controller)
+        self.controllerLayout.setSpacing(0)
+        self.controllerLayout.setMargin(0)
+        # Controller list view
+        self.previewListWidget = SlideList(self)
+        self.previewListWidget.setColumnCount(1)
+        self.previewListWidget.horizontalHeader().setVisible(False)
+        self.previewListWidget.setColumnWidth(0, self.controller.width())
+        self.previewListWidget.isLive = self.isLive
+        self.previewListWidget.setObjectName(u'PreviewListWidget')
+        self.previewListWidget.setSelectionBehavior(
+            QtGui.QAbstractItemView.SelectRows)
+        self.previewListWidget.setSelectionMode(
+            QtGui.QAbstractItemView.SingleSelection)
+        self.previewListWidget.setEditTriggers(
+            QtGui.QAbstractItemView.NoEditTriggers)
+        self.previewListWidget.setHorizontalScrollBarPolicy(
+            QtCore.Qt.ScrollBarAlwaysOff)
+        self.previewListWidget.setAlternatingRowColors(True)
+        self.controllerLayout.addWidget(self.previewListWidget)
+        # Build the full toolbar
+        self.toolbar = OpenLPToolbar(self)
+        sizeToolbarPolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Fixed)
+        sizeToolbarPolicy.setHorizontalStretch(0)
+        sizeToolbarPolicy.setVerticalStretch(0)
+        sizeToolbarPolicy.setHeightForWidth(
+            self.toolbar.sizePolicy().hasHeightForWidth())
+        self.toolbar.setSizePolicy(sizeToolbarPolicy)
+        self.previousItem = self.toolbar.addToolbarButton(
+            translate('OpenLP.SlideController', 'Previous Slide'),
+            u':/slides/slide_previous.png',
+            translate('OpenLP.SlideController', 'Move to previous'),
+            self.onSlideSelectedPrevious,
+            shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp],
+            context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.nextItem = self.toolbar.addToolbarButton(
+            translate('OpenLP.SlideController', 'Next Slide'),
+            u':/slides/slide_next.png',
+            translate('OpenLP.SlideController', 'Move to next'),
+            self.onSlideSelectedNext,
+            shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown],
+            context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.toolbar.addToolbarSeparator(u'Close Separator')
+        if self.isLive:
+            self.hideMenu = QtGui.QToolButton(self.toolbar)
+            self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide'))
+            self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
+            self.toolbar.addToolbarWidget(u'Hide Menu', self.hideMenu)
+            self.hideMenu.setMenu(QtGui.QMenu(
+                translate('OpenLP.SlideController', 'Hide'), self.toolbar))
+            self.blankScreen = shortcut_action(self.hideMenu, u'blankScreen',
+                [QtCore.Qt.Key_Period], self.onBlankDisplay,
+                u':/slides/slide_blank.png', False, UiStrings().LiveToolbar)
+            self.blankScreen.setText(
+                translate('OpenLP.SlideController', 'Blank Screen'))
+            self.themeScreen = shortcut_action(self.hideMenu, u'themeScreen',
+                [QtGui.QKeySequence(u'T')], self.onThemeDisplay,
+                u':/slides/slide_theme.png', False, UiStrings().LiveToolbar)
+            self.themeScreen.setText(
+                translate('OpenLP.SlideController', 'Blank to Theme'))
+            self.desktopScreen = shortcut_action(self.hideMenu,
+                u'desktopScreen', [QtGui.QKeySequence(u'D')],
+                self.onHideDisplay, u':/slides/slide_desktop.png', False,
+                UiStrings().LiveToolbar)
+            self.desktopScreen.setText(
+                translate('OpenLP.SlideController', 'Show Desktop'))
+            self.hideMenu.setDefaultAction(self.blankScreen)
+            self.hideMenu.menu().addAction(self.blankScreen)
+            self.hideMenu.menu().addAction(self.themeScreen)
+            self.hideMenu.menu().addAction(self.desktopScreen)
+            self.toolbar.addToolbarSeparator(u'Loop Separator')
+            startLoop = self.toolbar.addToolbarButton(
+                # Does not need translating - control string.
+                u'Start Loop', u':/media/media_time.png',
+                translate('OpenLP.SlideController', 'Start continuous loop'),
+                self.onStartLoop)
+            action_list = ActionList.get_instance()
+            action_list.add_action(startLoop, UiStrings().LiveToolbar)
+            stopLoop = self.toolbar.addToolbarButton(
+                # Does not need translating - control string.
+                u'Stop Loop', u':/media/media_stop.png',
+                translate('OpenLP.SlideController', 'Stop continuous loop'),
+                self.onStopLoop)
+            action_list.add_action(stopLoop, UiStrings().LiveToolbar)
+            self.toogleLoop = shortcut_action(self, u'toogleLoop',
+                [QtGui.QKeySequence(u'L')], self.onToggleLoop,
+                category=UiStrings().LiveToolbar)
+            self.toogleLoop.setText(translate('OpenLP.SlideController',
+                'Start/Stop continuous loop'))
+            self.addAction(self.toogleLoop)
+            self.delaySpinBox = QtGui.QSpinBox()
+            self.delaySpinBox.setRange(1, 180)
+            self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
+            self.delaySpinBox.setSuffix(UiStrings().Seconds)
+            self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',
+                'Delay between slides in seconds'))
+        else:
+            self.toolbar.addToolbarButton(
+                # Does not need translating - control string.
+                u'Go Live', u':/general/general_live.png',
+                translate('OpenLP.SlideController', 'Move to live'),
+                self.onGoLive)
+            self.toolbar.addToolbarSeparator(u'Close Separator')
+            self.toolbar.addToolbarButton(
+                # Does not need translating - control string.
+                u'Edit Song', u':/general/general_edit.png',
+                translate('OpenLP.SlideController',
+                'Edit and reload song preview'),
+                self.onEditSong)
+        self.controllerLayout.addWidget(self.toolbar)
+        # Build a Media ToolBar
+        self.mediabar = OpenLPToolbar(self)
+        self.mediabar.addToolbarButton(
+            u'Media Start', u':/slides/media_playback_start.png',
+            translate('OpenLP.SlideController', 'Start playing media'),
+            self.onMediaPlay)
+        self.mediabar.addToolbarButton(
+            u'Media Pause', u':/slides/media_playback_pause.png',
+            translate('OpenLP.SlideController', 'Start playing media'),
+            self.onMediaPause)
+        self.mediabar.addToolbarButton(
+            u'Media Stop', u':/slides/media_playback_stop.png',
+            translate('OpenLP.SlideController', 'Start playing media'),
+            self.onMediaStop)
+        if self.isLive:
+            # Build the Song Toolbar
+            self.songMenu = QtGui.QToolButton(self.toolbar)
+            self.songMenu.setText(translate('OpenLP.SlideController', 'Go To'))
+            self.songMenu.setPopupMode(QtGui.QToolButton.InstantPopup)
+            self.toolbar.addToolbarWidget(u'Song Menu', self.songMenu)
+            self.songMenu.setMenu(QtGui.QMenu(
+                translate('OpenLP.SlideController', 'Go To'), self.toolbar))
+            self.toolbar.makeWidgetsInvisible([u'Song Menu'])
+            # Build the volumeSlider.
+            self.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
+            self.volumeSlider.setTickInterval(1)
+            self.volumeSlider.setTickPosition(QtGui.QSlider.TicksAbove)
+            self.volumeSlider.setMinimum(0)
+            self.volumeSlider.setMaximum(10)
+        else:
+            # Build the seekSlider.
+            self.seekSlider = Phonon.SeekSlider()
+            self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
+            self.seekSlider.setObjectName(u'seekSlider')
+            self.mediabar.addToolbarWidget(u'Seek Slider', self.seekSlider)
+            self.volumeSlider = Phonon.VolumeSlider()
+        self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
+        self.volumeSlider.setObjectName(u'volumeSlider')
+        self.mediabar.addToolbarWidget(u'Audio Volume', self.volumeSlider)
+        self.controllerLayout.addWidget(self.mediabar)
+        # Screen preview area
+        self.previewFrame = QtGui.QFrame(self.splitter)
+        self.previewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio))
+        self.previewFrame.setMinimumHeight(100)
+        self.previewFrame.setSizePolicy(QtGui.QSizePolicy(
+            QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Ignored,
+            QtGui.QSizePolicy.Label))
+        self.previewFrame.setFrameShape(QtGui.QFrame.StyledPanel)
+        self.previewFrame.setFrameShadow(QtGui.QFrame.Sunken)
+        self.previewFrame.setObjectName(u'PreviewFrame')
+        self.grid = QtGui.QGridLayout(self.previewFrame)
+        self.grid.setMargin(8)
+        self.grid.setObjectName(u'grid')
+        self.slideLayout = QtGui.QVBoxLayout()
+        self.slideLayout.setSpacing(0)
+        self.slideLayout.setMargin(0)
+        self.slideLayout.setObjectName(u'SlideLayout')
+        if not self.isLive:
+            self.mediaObject = Phonon.MediaObject(self)
+            self.video = Phonon.VideoWidget()
+            self.video.setVisible(False)
+            self.audio = Phonon.AudioOutput(Phonon.VideoCategory,
+                self.mediaObject)
+            Phonon.createPath(self.mediaObject, self.video)
+            Phonon.createPath(self.mediaObject, self.audio)
+            self.video.setGeometry(QtCore.QRect(0, 0, 300, 225))
+            self.slideLayout.insertWidget(0, self.video)
+        # Actual preview screen
+        self.slidePreview = QtGui.QLabel(self)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(
+            self.slidePreview.sizePolicy().hasHeightForWidth())
+        self.slidePreview.setSizePolicy(sizePolicy)
+        self.slidePreview.setFrameShape(QtGui.QFrame.Box)
+        self.slidePreview.setFrameShadow(QtGui.QFrame.Plain)
+        self.slidePreview.setLineWidth(1)
+        self.slidePreview.setScaledContents(True)
+        self.slidePreview.setObjectName(u'SlidePreview')
+        self.slideLayout.insertWidget(0, self.slidePreview)
+        self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
+        # Signals
+        QtCore.QObject.connect(self.previewListWidget,
+            QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
+        if self.isLive:
+            QtCore.QObject.connect(self.volumeSlider,
+                QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume)
+            QtCore.QObject.connect(Receiver.get_receiver(),
+                QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview)
+            QtCore.QObject.connect(Receiver.get_receiver(),
+                QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
+                self.receiveSpinDelay)
+            self.toolbar.makeWidgetsInvisible(self.loopList)
+            self.toolbar.actions[u'Stop Loop'].setVisible(False)
+        else:
+            QtCore.QObject.connect(self.previewListWidget,
+                QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
+                self.onGoLiveClick)
+            self.toolbar.makeWidgetsInvisible(self.songEditList)
+        self.mediabar.setVisible(False)
+        if self.isLive:
+            self.setLiveHotkeys(self)
+            self.__addActionsToWidget(self.previewListWidget)
+        else:
+            self.setPreviewHotkeys()
+            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(),
+            QtCore.SIGNAL(u'slidecontroller_%s_first' % self.typePrefix),
+            self.onSlideSelectedFirst)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_next' % self.typePrefix),
+            self.onSlideSelectedNext)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_previous' % self.typePrefix),
+            self.onSlideSelectedPrevious)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_last' % self.typePrefix),
+            self.onSlideSelectedLast)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_change' % self.typePrefix),
+            self.onSlideChange)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_set' % self.typePrefix),
+            self.onSlideSelectedIndex)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_blank' % self.typePrefix),
+            self.onSlideBlank)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
+            self.onSlideUnblank)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix),
+            self.onTextRequest)
+
+    def setPreviewHotkeys(self, parent=None):
+        self.previousItem.setObjectName(u'previousItemPreview')
+        self.nextItem.setObjectName(u'nextItemPreview')
+        action_list = ActionList.get_instance()
+        action_list.add_action(self.previousItem)
+        action_list.add_action(self.nextItem)
+
+    def setLiveHotkeys(self, parent=None):
+        self.previousItem.setObjectName(u'previousItemLive')
+        self.nextItem.setObjectName(u'nextItemLive')
+        action_list = ActionList.get_instance()
+        action_list.add_category(
+            UiStrings().LiveToolbar, CategoryOrder.standardToolbar)
+        action_list.add_action(self.previousItem)
+        action_list.add_action(self.nextItem)
+        self.previousService = shortcut_action(parent, u'previousService',
+            [QtCore.Qt.Key_Left], self.servicePrevious,
+            category=UiStrings().LiveToolbar,
+            context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.previousService.setText(
+            translate('OpenLP.SlideController', 'Previous Service'))
+        self.nextService = shortcut_action(parent, 'nextService',
+            [QtCore.Qt.Key_Right], self.serviceNext,
+            category=UiStrings().LiveToolbar,
+            context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.nextService.setText(
+            translate('OpenLP.SlideController', 'Next Service'))
+        self.escapeItem = shortcut_action(parent, 'escapeItem',
+            [QtCore.Qt.Key_Escape], self.liveEscape,
+            category=UiStrings().LiveToolbar,
+            context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.escapeItem.setText(
+            translate('OpenLP.SlideController', 'Escape Item'))
+
+    def liveEscape(self):
+        self.display.setVisible(False)
+        self.display.videoStop()
+
+    def servicePrevious(self):
+        Receiver.send_message('servicemanager_previous_item')
+
+    def serviceNext(self):
+        Receiver.send_message('servicemanager_next_item')
+
+    def screenSizeChanged(self):
+        """
+        Settings dialog has changed the screen size of adjust output and
+        screen previews.
+        """
+        # rebuild display as screen size changed
+        self.display = MainDisplay(self, self.image_manager, self.isLive)
+        self.display.alertTab = self.alertTab
+        self.display.setup()
+        if self.isLive:
+            self.__addActionsToWidget(self.display)
+        # The SlidePreview's ratio.
+        self.ratio = float(self.screens.current[u'size'].width()) / \
+            float(self.screens.current[u'size'].height())
+        self.previewSizeChanged()
+        if self.serviceItem:
+            self.refreshServiceItem()
+
+    def __addActionsToWidget(self, widget):
+        widget.addActions([
+            self.previousItem, self.nextItem,
+            self.previousService, self.nextService,
+            self.escapeItem])
+
+    def previewSizeChanged(self):
+        """
+        Takes care of the SlidePreview's size. Is called when one of the the
+        splitters is moved or when the screen size is changed. Note, that this
+        method is (also) called frequently from the mainwindow *paintEvent*.
+        """
+        if self.ratio < float(self.previewFrame.width()) / float(
+            self.previewFrame.height()):
+            # We have to take the height as limit.
+            max_height = self.previewFrame.height() - self.grid.margin() * 2
+            self.slidePreview.setFixedSize(QtCore.QSize(max_height * self.ratio,
+                max_height))
+        else:
+            # We have to take the width as limit.
+            max_width = self.previewFrame.width() - self.grid.margin() * 2
+            self.slidePreview.setFixedSize(QtCore.QSize(max_width,
+                max_width / self.ratio))
+        # Make sure that the frames have the correct size.
+        self.previewListWidget.setColumnWidth(0,
+            self.previewListWidget.viewport().size().width())
+        if self.serviceItem:
+            # Sort out songs, bibles, etc.
+            if self.serviceItem.is_text():
+                self.previewListWidget.resizeRowsToContents()
+            else:
+                # Sort out image heights.
+                width = self.parent.controlSplitter.sizes()[self.split]
+                for framenumber in range(len(self.serviceItem.get_frames())):
+                    self.previewListWidget.setRowHeight(
+                        framenumber, width / self.ratio)
+
+    def onSongBarHandler(self):
+        request = unicode(self.sender().text())
+        slideno = self.slideList[request]
+        self.__updatePreviewSelection(slideno)
+        self.slideSelected()
+
+    def receiveSpinDelay(self, value):
+        """
+        Adjusts the value of the ``delaySpinBox`` to the given one.
+        """
+        self.delaySpinBox.setValue(int(value))
+
+    def enableToolBar(self, item):
+        """
+        Allows the toolbars to be reconfigured based on Controller Type
+        and ServiceItem Type
+        """
+        if self.isLive:
+            self.enableLiveToolBar(item)
+        else:
+            self.enablePreviewToolBar(item)
+
+    def enableLiveToolBar(self, item):
+        """
+        Allows the live toolbar to be customised
+        """
+        self.toolbar.setVisible(True)
+        self.mediabar.setVisible(False)
+        self.toolbar.makeWidgetsInvisible([u'Song Menu'])
+        self.toolbar.makeWidgetsInvisible(self.loopList)
+        self.toogleLoop.setEnabled(False)
+        self.toolbar.actions[u'Start Loop'].setEnabled(False)
+        self.toolbar.actions[u'Stop Loop'].setEnabled(False)
+        self.toolbar.actions[u'Stop Loop'].setVisible(False)
+        if item.is_text():
+            if QtCore.QSettings().value(
+                self.parent.songsSettingsSection + u'/display songbar',
+                QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
+                self.toolbar.makeWidgetsVisible([u'Song Menu'])
+        if item.is_capable(ItemCapabilities.AllowsLoop) and \
+            len(item.get_frames()) > 1:
+            self.toolbar.makeWidgetsVisible(self.loopList)
+            self.toogleLoop.setEnabled(True)
+            self.toolbar.actions[u'Start Loop'].setEnabled(True)
+            self.toolbar.actions[u'Stop Loop'].setEnabled(True)
+        if item.is_media():
+            self.toolbar.setVisible(False)
+            self.mediabar.setVisible(True)
+
+    def enablePreviewToolBar(self, item):
+        """
+        Allows the Preview toolbar to be customised
+        """
+        self.toolbar.setVisible(True)
+        self.mediabar.setVisible(False)
+        self.toolbar.makeWidgetsInvisible(self.songEditList)
+        if item.is_capable(ItemCapabilities.AllowsEdit) and item.from_plugin:
+            self.toolbar.makeWidgetsVisible(self.songEditList)
+        elif item.is_media():
+            self.toolbar.setVisible(False)
+            self.mediabar.setVisible(True)
+            self.volumeSlider.setAudioOutput(self.audio)
+
+    def refreshServiceItem(self):
+        """
+        Method to update the service item if the screen has changed
+        """
+        log.debug(u'refreshServiceItem live = %s' % self.isLive)
+        if self.serviceItem.is_text() or self.serviceItem.is_image():
+            item = self.serviceItem
+            item.render()
+            self._processItem(item, self.selectedRow)
+
+    def addServiceItem(self, item):
+        """
+        Method to install the service item into the controller
+        Called by plugins
+        """
+        log.debug(u'addServiceItem live = %s' % self.isLive)
+        item.render()
+        slideno = 0
+        if self.songEdit:
+            slideno = self.selectedRow
+        self.songEdit = False
+        self._processItem(item, slideno)
+
+    def replaceServiceManagerItem(self, item):
+        """
+        Replacement item following a remote edit
+        """
+        if item.__eq__(self.serviceItem):
+            self._processItem(item, self.previewListWidget.currentRow())
+
+    def addServiceManagerItem(self, item, slideno):
+        """
+        Method to install the service item into the controller and
+        request the correct toolbar for the plugin.
+        Called by ServiceManager
+        """
+        log.debug(u'addServiceManagerItem live = %s' % self.isLive)
+        # If no valid slide number is specified we take the first one.
+        if slideno == -1:
+            slideno = 0
+        # If service item is the same as the current on only change slide
+        if item.__eq__(self.serviceItem):
+            self.__checkUpdateSelectedSlide(slideno)
+            self.slideSelected()
+            return
+        self._processItem(item, slideno)
+
+    def _processItem(self, serviceItem, slideno):
+        """
+        Loads a ServiceItem into the system from ServiceManager
+        Display the slide number passed
+        """
+        log.debug(u'processManagerItem live = %s' % self.isLive)
+        self.onStopLoop()
+        old_item = self.serviceItem
+        self.serviceItem = serviceItem
+        if old_item and self.isLive and old_item.is_capable(
+            ItemCapabilities.ProvidesOwnDisplay):
+            self._resetBlank()
+        Receiver.send_message(u'%s_start' % serviceItem.name.lower(),
+            [serviceItem, self.isLive, self.hideMode(), slideno])
+        self.slideList = {}
+        width = self.parent.controlSplitter.sizes()[self.split]
+        self.previewListWidget.clear()
+        self.previewListWidget.setRowCount(0)
+        self.previewListWidget.setColumnWidth(0, width)
+        if self.isLive:
+            self.songMenu.menu().clear()
+        row = 0
+        text = []
+        for framenumber, frame in enumerate(self.serviceItem.get_frames()):
+            self.previewListWidget.setRowCount(
+                self.previewListWidget.rowCount() + 1)
+            item = QtGui.QTableWidgetItem()
+            slideHeight = 0
+            if self.serviceItem.is_text():
+                if frame[u'verseTag']:
+                    # These tags are already translated.
+                    verse_def = frame[u'verseTag']
+                    verse_def = u'%s%s' % (verse_def[0], verse_def[1:])
+                    two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:])
+                    row = two_line_def
+                    if self.isLive:
+                        if verse_def not in self.slideList:
+                            self.slideList[verse_def] = framenumber
+                            self.songMenu.menu().addAction(verse_def,
+                                self.onSongBarHandler)
+                else:
+                    row += 1
+                item.setText(frame[u'text'])
+            else:
+                label = QtGui.QLabel()
+                label.setMargin(4)
+                label.setScaledContents(True)
+                if self.serviceItem.is_command():
+                    image = resize_image(frame[u'image'],
+                        self.parent.renderer.width,
+                        self.parent.renderer.height)
+                else:
+                    # If current slide set background to image
+                    if framenumber == slideno:
+                        self.serviceItem.bg_image_bytes = \
+                            self.image_manager.get_image_bytes(frame[u'title'])
+                    image = self.image_manager.get_image(frame[u'title'])
+                label.setPixmap(QtGui.QPixmap.fromImage(image))
+                self.previewListWidget.setCellWidget(framenumber, 0, label)
+                slideHeight = width * self.parent.renderer.screen_ratio
+                row += 1
+            text.append(unicode(row))
+            self.previewListWidget.setItem(framenumber, 0, item)
+            if slideHeight != 0:
+                self.previewListWidget.setRowHeight(framenumber, slideHeight)
+        self.previewListWidget.setVerticalHeaderLabels(text)
+        if self.serviceItem.is_text():
+            self.previewListWidget.resizeRowsToContents()
+        self.previewListWidget.setColumnWidth(0,
+            self.previewListWidget.viewport().size().width())
+        self.__updatePreviewSelection(slideno)
+        self.enableToolBar(serviceItem)
+        # Pass to display for viewing.
+        # Postpone image build, we need to do this later to avoid the theme
+        # flashing on the screen
+        if not self.serviceItem.is_image():
+            self.display.buildHtml(self.serviceItem)
+        if serviceItem.is_media():
+            self.onMediaStart(serviceItem)
+        self.slideSelected(True)
+        self.previewListWidget.setFocus()
+        if old_item:
+            # Close the old item after the new one is opened
+            # This avoids the service theme/desktop flashing on screen
+            # However opening a new item of the same type will automatically
+            # close the previous, so make sure we don't close the new one.
+            if old_item.is_command() and not serviceItem.is_command():
+                Receiver.send_message(u'%s_stop' %
+                    old_item.name.lower(), [old_item, self.isLive])
+            if old_item.is_media() and not serviceItem.is_media():
+                self.onMediaClose()
+        Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix,
+            [serviceItem])
+
+    def __updatePreviewSelection(self, slideno):
+        """
+        Utility method to update the selected slide in the list.
+        """
+        if slideno > self.previewListWidget.rowCount():
+            self.previewListWidget.selectRow(
+                self.previewListWidget.rowCount() - 1)
+        else:
+            self.__checkUpdateSelectedSlide(slideno)
+
+    def onTextRequest(self):
+        """
+        Return the text for the current item in controller
+        """
+        data = []
+        if self.serviceItem:
+            for framenumber, frame in enumerate(self.serviceItem.get_frames()):
+                dataItem = {}
+                if self.serviceItem.is_text():
+                    dataItem[u'tag'] = unicode(frame[u'verseTag'])
+                    dataItem[u'text'] = unicode(frame[u'html'])
+                else:
+                    dataItem[u'tag'] = unicode(framenumber)
+                    dataItem[u'text'] = u''
+                dataItem[u'selected'] = \
+                    (self.previewListWidget.currentRow() == framenumber)
+                data.append(dataItem)
+        Receiver.send_message(u'slidecontroller_%s_text_response'
+            % self.typePrefix, data)
+
+    # Screen event methods
+    def onSlideSelectedFirst(self):
+        """
+        Go to the first slide.
+        """
+        if not self.serviceItem:
+            return
+        if self.serviceItem.is_command():
+            Receiver.send_message(u'%s_first' % self.serviceItem.name.lower(),
+                [self.serviceItem, self.isLive])
+            self.updatePreview()
+        else:
+            self.previewListWidget.selectRow(0)
+            self.slideSelected()
+
+    def onSlideSelectedIndex(self, message):
+        """
+        Go to the requested slide
+        """
+        index = int(message[0])
+        if not self.serviceItem:
+            return
+        if self.serviceItem.is_command():
+            Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
+                [self.serviceItem, self.isLive, index])
+            self.updatePreview()
+        else:
+            self.__checkUpdateSelectedSlide(index)
+            self.slideSelected()
+
+    def mainDisplaySetBackground(self):
+        """
+        Allow the main display to blank the main display at startup time
+        """
+        log.debug(u'mainDisplaySetBackground live = %s' % self.isLive)
+        display_type = QtCore.QSettings().value(
+            self.parent.generalSettingsSection + u'/screen blank',
+            QtCore.QVariant(u'')).toString()
+        if not self.display.primary:
+            # Order done to handle initial conversion
+            if display_type == u'themed':
+                self.onThemeDisplay(True)
+            elif display_type == u'hidden':
+                self.onHideDisplay(True)
+            else:
+                self.onBlankDisplay(True)
+
+    def onSlideBlank(self):
+        """
+        Handle the slidecontroller blank event
+        """
+        self.onBlankDisplay(True)
+
+    def onSlideUnblank(self):
+        """
+        Handle the slidecontroller unblank event
+        """
+        self.onBlankDisplay(False)
+
+    def onBlankDisplay(self, checked=None):
+        """
+        Handle the blank screen button actions
+        """
+        if checked is None:
+            checked = self.blankScreen.isChecked()
+        log.debug(u'onBlankDisplay %s' % checked)
+        self.hideMenu.setDefaultAction(self.blankScreen)
+        self.blankScreen.setChecked(checked)
+        self.themeScreen.setChecked(False)
+        self.desktopScreen.setChecked(False)
+        if checked:
+            QtCore.QSettings().setValue(
+                self.parent.generalSettingsSection + u'/screen blank',
+                QtCore.QVariant(u'blanked'))
+        else:
+            QtCore.QSettings().remove(
+                self.parent.generalSettingsSection + u'/screen blank')
+        self.blankPlugin()
+        self.updatePreview()
+
+    def onThemeDisplay(self, checked=None):
+        """
+        Handle the Theme screen button
+        """
+        if checked is None:
+            checked = self.themeScreen.isChecked()
+        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:
+            QtCore.QSettings().setValue(
+                self.parent.generalSettingsSection + u'/screen blank',
+                QtCore.QVariant(u'themed'))
+        else:
+            QtCore.QSettings().remove(
+                self.parent.generalSettingsSection + u'/screen blank')
+        self.blankPlugin()
+        self.updatePreview()
+
+    def onHideDisplay(self, checked=None):
+        """
+        Handle the Hide screen button
+        """
+        if checked is None:
+            checked = self.desktopScreen.isChecked()
+        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:
+            QtCore.QSettings().setValue(
+                self.parent.generalSettingsSection + u'/screen blank',
+                QtCore.QVariant(u'hidden'))
+        else:
+            QtCore.QSettings().remove(
+                self.parent.generalSettingsSection + u'/screen blank')
+        self.hidePlugin(checked)
+        self.updatePreview()
+
+    def blankPlugin(self):
+        """
+        Blank/Hide the display screen within a plugin if required.
+        """
+        hide_mode = self.hideMode()
+        log.debug(u'blankPlugin %s ', hide_mode)
+        if self.serviceItem is not None:
+            if hide_mode:
+                if not self.serviceItem.is_command():
+                    Receiver.send_message(u'maindisplay_hide', hide_mode)
+                Receiver.send_message(u'%s_blank'
+                    % self.serviceItem.name.lower(),
+                    [self.serviceItem, self.isLive, hide_mode])
+            else:
+                if not self.serviceItem.is_command():
+                    Receiver.send_message(u'maindisplay_show')
+                Receiver.send_message(u'%s_unblank'
+                    % self.serviceItem.name.lower(),
+                    [self.serviceItem, self.isLive])
+
+    def hidePlugin(self, hide):
+        """
+        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'maindisplay_hide', HideMode.Screen)
+                Receiver.send_message(u'%s_hide'
+                    % self.serviceItem.name.lower(),
+                    [self.serviceItem, self.isLive])
+            else:
+                if not self.serviceItem.is_command():
+                    Receiver.send_message(u'maindisplay_show')
+                Receiver.send_message(u'%s_unblank'
+                    % self.serviceItem.name.lower(),
+                    [self.serviceItem, self.isLive])
+
+    def onSlideSelected(self, start=False):
+        """
+        Slide selected in controller
+        """
+        self.slideSelected()
+
+    def slideSelected(self, start=False):
+        """
+        Generate the preview when you click on a slide.
+        if this is the Live Controller also display on the screen
+        """
+        row = self.previewListWidget.currentRow()
+        self.selectedRow = 0
+        if row > -1 and row < self.previewListWidget.rowCount():
+            if self.serviceItem.is_command():
+                if self.isLive and not start:
+                    Receiver.send_message(
+                        u'%s_slide' % self.serviceItem.name.lower(),
+                        [self.serviceItem, self.isLive, row])
+                self.updatePreview()
+            else:
+                toDisplay = self.serviceItem.get_rendered_frame(row)
+                if self.serviceItem.is_text():
+                    frame = self.display.text(toDisplay)
+                else:
+                    if start:
+                        self.display.buildHtml(self.serviceItem, toDisplay)
+                        frame = self.display.preview()
+                    else:
+                        frame = self.display.image(toDisplay)
+                    # reset the store used to display first image
+                    self.serviceItem.bg_image_bytes = None
+                self.slidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
+            self.selectedRow = row
+            self.__checkUpdateSelectedSlide(row)
+        Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
+            row)
+
+    def onSlideChange(self, row):
+        """
+        The slide has been changed. Update the slidecontroller accordingly
+        """
+        self.__checkUpdateSelectedSlide(row)
+        self.updatePreview()
+        Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
+            row)
+
+    def updatePreview(self):
+        """
+        This updates the preview frame, for example after changing a slide or
+        using *Blank to Theme*.
+        """
+        log.debug(u'updatePreview %s ' % self.screens.current[u'primary'])
+        if not self.screens.current[u'primary'] and self.serviceItem and \
+            self.serviceItem.is_capable(ItemCapabilities.ProvidesOwnDisplay):
+            # Grab now, but try again in a couple of seconds if slide change
+            # is slow
+            QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
+            QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
+        else:
+            self.slidePreview.setPixmap(
+                QtGui.QPixmap.fromImage(self.display.preview()))
+
+    def grabMainDisplay(self):
+        """
+        Creates an image of the current screen and updates the preview frame.
+        """
+        winid = QtGui.QApplication.desktop().winId()
+        rect = self.screens.current[u'size']
+        winimg = QtGui.QPixmap.grabWindow(winid, rect.x(),
+            rect.y(), rect.width(), rect.height())
+        self.slidePreview.setPixmap(winimg)
+    def onSlideSelectedNext(self):
+        """
+        Go to the next slide.
+        """
+        loopcheck = QtCore.QSettings().value( self.parent.generalSettingsSection + u'generalSettingsSection/enable slide loop', QtCore.QVariant(True).toBool)
+        if not self.serviceItem:
+            return
+        Receiver.send_message(u'%s_next' % self.serviceItem.name.lower(),
+            [self.serviceItem, self.isLive])
+        if self.serviceItem.is_command() and self.isLive:
+            self.updatePreview()
+        else:
+            row = self.previewListWidget.currentRow() + 1
+            if row == self.previewListWidget.rowCount():
+                if loopcheck == True:
+                    row = 0
+                else:
+                    return
+            self.__checkUpdateSelectedSlide(row)
+            self.slideSelected()
+    def onSlideSelectedPrevious(self):
+        """
+        Go to the previous slide.
+        """
+        loopcheck =QtCore.QSettings().value( self.parent.generalSettingsSection + u'enable slide loop', QtCore.QVariant(True).toBool)
+        if not self.serviceItem:
+            return
+        Receiver.send_message(u'%s_previous' % self.serviceItem.name.lower(),
+            [self.serviceItem, self.isLive])
+        if self.serviceItem.is_command() and self.isLive:
+            self.updatePreview()
+        else:
+            row = self.previewListWidget.currentRow() - 1
+            if row == -1:
+                if loopcheck == True:
+                    row = self.previewListWidget.rowCount() - 1
+                else:
+                    return
+            self.__checkUpdateSelectedSlide(row)
+            self.slideSelected()
+
+    def __checkUpdateSelectedSlide(self, row):
+        if row + 1 < self.previewListWidget.rowCount():
+            self.previewListWidget.scrollToItem(
+                self.previewListWidget.item(row + 1, 0))
+        self.previewListWidget.selectRow(row)
+
+    def onSlideSelectedLast(self):
+        """
+        Go to the last slide.
+        """
+        if not self.serviceItem:
+            return
+        Receiver.send_message(u'%s_last' % self.serviceItem.name.lower(),
+            [self.serviceItem, self.isLive])
+        if self.serviceItem.is_command():
+            self.updatePreview()
+        else:
+            self.previewListWidget.selectRow(
+                        self.previewListWidget.rowCount() - 1)
+            self.slideSelected()
+
+    def onToggleLoop(self, toggled):
+        """
+        Toggles the loop state.
+        """
+        if self.toolbar.actions[u'Start Loop'].isVisible():
+            self.onStartLoop()
+        else:
+            self.onStopLoop()
+
+    def onStartLoop(self):
+        """
+        Start the timer loop running and store the timer id
+        """
+        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):
+        """
+        Stop the timer loop running
+        """
+        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):
+        """
+        If the timer event is for this window select next slide
+        """
+        if event.timerId() == self.timer_id:
+            self.onSlideSelectedNext()
+
+    def onEditSong(self):
+        """
+        From the preview display requires the service Item to be editied
+        """
+        self.songEdit = True
+        Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(),
+            u'P:%s' % self.serviceItem.edit_id)
+
+    def onGoLiveClick(self):
+        """
+        triggered by clicking the Preview slide items
+        """
+        if QtCore.QSettings().value(u'advanced/double click live',
+            QtCore.QVariant(False)).toBool():
+            self.onGoLive()
+
+    def onGoLive(self):
+        """
+        If preview copy slide item to live
+        """
+        row = self.previewListWidget.currentRow()
+        if row > -1 and row < self.previewListWidget.rowCount():
+            if self.serviceItem.from_service:
+                Receiver.send_message('servicemanager_preview_live',
+                    u'%s:%s' % (self.serviceItem._uuid, row))
+            else:
+                self.parent.liveController.addServiceManagerItem(
+                    self.serviceItem, row)
+
+    def onMediaStart(self, item):
+        """
+        Respond to the arrival of a media service item
+        """
+        log.debug(u'SlideController onMediaStart')
+        file = os.path.join(item.get_frame_path(), item.get_frame_title())
+        if self.isLive:
+            self.display.video(file, self.volume)
+            self.volumeSlider.setValue(self.volume)
+        else:
+            self.mediaObject.stop()
+            self.mediaObject.clearQueue()
+            self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
+            self.seekSlider.setMediaObject(self.mediaObject)
+            self.seekSlider.show()
+            self.onMediaPlay()
+
+    def mediaVolume(self):
+        """
+        Respond to the release of Volume Slider
+        """
+        log.debug(u'SlideController mediaVolume')
+        self.volume = self.volumeSlider.value()
+        self.display.videoVolume(self.volume)
+
+    def onMediaPause(self):
+        """
+        Respond to the Pause from the media Toolbar
+        """
+        log.debug(u'SlideController onMediaPause')
+        if self.isLive:
+            self.display.videoPause()
+        else:
+            self.mediaObject.pause()
+
+    def onMediaPlay(self):
+        """
+        Respond to the Play from the media Toolbar
+        """
+        log.debug(u'SlideController onMediaPlay')
+        if self.isLive:
+            self.display.videoPlay()
+        else:
+            self.slidePreview.hide()
+            self.video.show()
+            self.mediaObject.play()
+
+    def onMediaStop(self):
+        """
+        Respond to the Stop from the media Toolbar
+        """
+        log.debug(u'SlideController onMediaStop')
+        if self.isLive:
+            self.display.videoStop()
+        else:
+            self.mediaObject.stop()
+            self.video.hide()
+        self.slidePreview.clear()
+        self.slidePreview.show()
+
+    def onMediaClose(self):
+        """
+        Respond to a request to close the Video
+        """
+        log.debug(u'SlideController onMediaStop')
+        if self.isLive:
+            self.display.resetVideo()
+        else:
+            self.mediaObject.stop()
+            self.mediaObject.clearQueue()
+            self.video.hide()
+        self.slidePreview.clear()
+        self.slidePreview.show()
+
+    def _resetBlank(self):
+        """
+        Used by command items which provide their own displays to reset the
+        screen hide attributes
+        """
+        hide_mode = self.hideMode()
+        if hide_mode == HideMode.Blank:
+            self.onBlankDisplay(True)
+        elif hide_mode == HideMode.Theme:
+            self.onThemeDisplay(True)
+        elif hide_mode == HideMode.Screen:
+            self.onHideDisplay(True)
+        else:
+            self.hidePlugin(False)
+
+    def hideMode(self):
+        """
+        Determine what the hide mode should be according to the blank button
+        """
+        if not self.isLive:
+            return None
+        elif self.blankScreen.isChecked():
+            return HideMode.Blank
+        elif self.themeScreen.isChecked():
+            return HideMode.Theme
+        elif self.desktopScreen.isChecked():
+            return HideMode.Screen
+        else:
+            return None
+>>>>>>> MERGE-SOURCE


Follow ups