From b92b733828595284fc61529ff9d076d10381e50e Mon Sep 17 00:00:00 2001 From: Josh Miller Date: Tue, 24 May 2011 18:32:30 -0400 Subject: [PATCH] corrections and enable slide loop updates --- openlp.pyw | 1 - openlp/core/ui/generaltab.py | 780 +++++----- openlp/core/ui/slidecontroller.py | 2314 +++++++++++++++-------------- 3 files changed, 1548 insertions(+), 1547 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index f3b380c7a..76d334bae 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -257,4 +257,3 @@ if __name__ == u'__main__': Instantiate and run the application. """ main() - diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 8c9336656..95e8dda4e 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -1,390 +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) - 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 - +# -*- 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(True)).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 + diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 722905c0b..4a0a3bf39 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1,1156 +1,1158 @@ -# -*- 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 +# -*- 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. + """ + 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 QtCore.QSettings().value(self.parent.generalSettingsSection + + u'generalSettingsSection/enable slide loop', QtCore.QVariant(True).toBool): + row = 0 + else: + return + self.__checkUpdateSelectedSlide(row) + self.slideSelected() + + def onSlideSelectedPrevious(self): + """ + Go to the previous slide. + """ + 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 QtCore.QSettings().value(self.parent.generalSettingsSection + + u'generalSettingsSection/enable slide loop', QtCore.QVariant(True).toBool): + 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