diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 18e71f837..b5bbea842 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -303,7 +303,8 @@ class Settings(QtCore.QSettings): 'projector/last directory import': '', 'projector/last directory export': '', 'projector/poll time': 20, # PJLink timeout is 30 seconds - 'projector/socket timeout': 5 # 5 second socket timeout + 'projector/socket timeout': 5, # 5 second socket timeout + 'projector/source dialog type': 0 # Source select dialog box type } __file_path__ = '' __obsolete_settings__ = [ diff --git a/openlp/core/lib/projector/__init__.py b/openlp/core/lib/projector/__init__.py new file mode 100644 index 000000000..23fdf82f8 --- /dev/null +++ b/openlp/core/lib/projector/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Ken Roberts, Simon Scudder, # +# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Dave Warnock, Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# 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 # +############################################################################### +""" + :mod:`openlp.core.ui.projector` + + Initialization for the openlp.core.ui.projector modules. +""" + +class DialogSourceStyle(object): + """ + An enumeration for projector dialog box type. + """ + Tabbed = 0 + Single = 1 diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py index 32226f6b3..2dc8ca2dc 100644 --- a/openlp/core/ui/projector/manager.py +++ b/openlp/core/ui/projector/manager.py @@ -44,11 +44,12 @@ from openlp.core.common import RegistryProperties, Settings, OpenLPMixin, \ RegistryMixin, translate from openlp.core.lib import OpenLPToolbar from openlp.core.lib.ui import create_widget_action +from openlp.core.lib.projector import DialogSourceStyle from openlp.core.lib.projector.constants import * from openlp.core.lib.projector.db import ProjectorDB from openlp.core.lib.projector.pjlink1 import PJLink1 from openlp.core.ui.projector.editform import ProjectorEditForm -from openlp.core.ui.projector.sourceselectform import SourceSelectDialog +from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle # Dict for matching projector status to display icon STATUS_ICONS = {S_NOT_CONNECTED: ':/projector/projector_item_disconnect.png', @@ -300,13 +301,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, self.projectordb = ProjectorDB() else: log.debug('Using existing ProjectorDB() instance') - settings = Settings() - settings.beginGroup(self.settings_section) - self.autostart = settings.value('connect on start') - self.poll_time = settings.value('poll time') - self.socket_timeout = settings.value('socket timeout') - settings.endGroup() - del(settings) + self.get_settings() def bootstrap_post_set_up(self): """ @@ -318,6 +313,16 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, self.projector_form.editProjector.connect(self.edit_projector_from_wizard) self.projector_list_widget.itemSelectionChanged.connect(self.update_icons) + def get_settings(self): + settings = Settings() + settings.beginGroup(self.settings_section) + self.autostart = settings.value('connect on start') + self.poll_time = settings.value('poll time') + self.socket_timeout = settings.value('socket timeout') + self.source_select_dialog_type = settings.value('source dialog type') + settings.endGroup() + del(settings) + def context_menu(self, point): """ Build the Right Click Context menu and set state. @@ -354,37 +359,6 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, self.menu.projector = real_projector self.menu.exec_(self.projector_list_widget.mapToGlobal(point)) - def _select_input_widget(self, parent, selected, code, text): - """ - Build the radio button widget for selecting source input menu - - :param parent: parent widget - :param selected: Selected widget text - :param code: PJLink code for this widget - :param text: Text to display - :returns: radio button widget - """ - widget = QtGui.QRadioButton(text, parent=parent) - widget.setChecked(True if code == selected else False) - widget.button_role = code - widget.clicked.connect(self._select_input_radio) - self.radio_buttons.append(widget) - return widget - - def _select_input_radio(self, opt1=None, opt2=None): - """ - Returns the currently selected radio button - - :param opt1: Needed by PyQt4 - :param op2: future - :returns: Selected button role - """ - for button in self.radio_buttons: - if button.isChecked(): - self.radio_button_selected = button.button_role - break - return - def on_select_input(self, opt=None): """ Builds menu for 'Select Input' option, then calls the selected projector @@ -392,57 +366,21 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, :param opt: Needed by PyQt4 """ + self.get_settings() # In case the dialog interface setting was changed list_item = self.projector_list_widget.item(self.projector_list_widget.currentRow()) projector = list_item.data(QtCore.Qt.UserRole) # QTabwidget for source select - source_select_form = SourceSelectDialog(parent=self, + if self.source_select_dialog_type == DialogSourceStyle.Tabbed: + source_select_form = SourceSelectTabs(parent=self, projectordb=self.projectordb) - + else: + source_select_form = SourceSelectSingle(parent=self, + projectordb=self.projectordb) source = source_select_form.exec_(projector.link) log.debug('(%s) source_select_form() returned %s' % (projector.link.ip, source)) if source is not None and source > 0: projector.link.set_input_source(str(source)) return - # QDialog for source select - Delete when QTabWidget finished - layout = QtGui.QVBoxLayout() - box = QtGui.QDialog(parent=self) - box.setModal(True) - title = QtGui.QLabel(translate('OpenLP.ProjectorManager', 'Select the input source below')) - layout.addWidget(title) - self.radio_button_selected = None - self.radio_buttons = [] - source_list = self.projectordb.get_source_list(make=projector.link.manufacturer, - model=projector.link.model, - sources=projector.link.source_available - ) - if source_list is None: - return - sort = [] - for item in source_list.keys(): - sort.append(item) - sort.sort() - current = QtGui.QLabel(translate('OpenLP.ProjectorManager', 'Current source is %s' % - source_list[projector.link.source])) - layout.addWidget(current) - for item in sort: - button = self._select_input_widget(parent=self, - selected=projector.link.source, - code=item, - text=source_list[item]) - layout.addWidget(button) - button_box = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | - QtGui.QDialogButtonBox.Cancel) - button_box.accepted.connect(box.accept) - button_box.rejected.connect(box.reject) - layout.addWidget(button_box) - box.setLayout(layout) - check = box.exec_() - if check == 0: - # Cancel button clicked or window closed - don't set source - return - selected = self.radio_button_selected - projector.link.set_input_source(self.radio_button_selected) - self.radio_button_selected = None def on_add_projector(self, opt=None): """ diff --git a/openlp/core/ui/projector/sourceselectform.py b/openlp/core/ui/projector/sourceselectform.py index f25e2c5a8..4db279bea 100644 --- a/openlp/core/ui/projector/sourceselectform.py +++ b/openlp/core/ui/projector/sourceselectform.py @@ -183,27 +183,28 @@ class FingerTabWidget(QTabWidget): self.setTabBar(FingerTabBarWidget(self)) -class SourceSelectDialog(QDialog): +class SourceSelectTabs(QDialog): """ Class for handling selecting the source for the projector to use. + Uses tabbed interface. """ def __init__(self, parent, projectordb): """ - Build the source select dialog. + Build the source select dialog using tabbed interface. :param projectordb: ProjectorDB session to use """ - log.debug('Initializing SourceSelectDialog()') + log.debug('Initializing SourceSelectTabs()') self.projectordb = projectordb - super(SourceSelectDialog, self).__init__(parent) - self.setWindowTitle(translate('OpenLP.SourceSelectDialog', 'Select Projector Source')) - self.setObjectName('source_select_dialog') + super(SourceSelectTabs, self).__init__(parent) + self.setWindowTitle(translate('OpenLP.SourceSelectForm', 'Select Projector Source')) + self.setObjectName('source_select_tabs') self.setWindowIcon(build_icon(':/icon/openlp-log-32x32.png')) self.setModal(True) self.layout = QVBoxLayout() - self.layout.setObjectName('source_select_dialog_layout') + self.layout.setObjectName('source_select_tabs_layout') self.tabwidget = FingerTabWidget(self) - self.tabwidget.setObjectName('source_select_dialog_tabwidget') + self.tabwidget.setObjectName('source_select_tabs_tabwidget') self.tabwidget.setUsesScrollButtons(False) if is_macosx(): self.tabwidget.setTabPosition(QTabWidget.North) @@ -239,16 +240,122 @@ class SourceSelectDialog(QDialog): self.button_box.accepted.connect(self.accept_me) self.button_box.rejected.connect(self.reject_me) self.layout.addWidget(self.button_box) - selected = super(SourceSelectDialog, self).exec_() + selected = super(SourceSelectTabs, self).exec_() return selected @pyqtSlot() def accept_me(self): + """ + Slot to accept 'OK' button + """ + selected = self.button_group.checkedId() + log.debug('SourceSelectTabs().accepted() Setting source to %s' % selected) + self.done(selected) + + @pyqtSlot() + def reject_me(self): + """ + Slot to accept 'Cancel' button + """ + log.debug('SourceSelectTabs() - Rejected') + self.done(0) + + +class SourceSelectSingle(QDialog): + """ + Class for handling selecting the source for the projector to use. + Uses single dialog interface. + """ + def __init__(self, parent, projectordb): + """ + Build the source select dialog. + + :param projectordb: ProjectorDB session to use + """ + log.debug('Initializing SourceSelectSingle()') + self.projectordb = projectordb + super(SourceSelectSingle, self).__init__(parent) + self.setWindowTitle(translate('OpenLP.SourceSelectSingle', 'Select Projector Source')) + self.setObjectName('source_select_single') + self.setWindowIcon(build_icon(':/icon/openlp-log-32x32.png')) + self.setModal(True) + self.layout = QVBoxLayout() + self.layout.setObjectName('source_select_tabs_layout') + self.layout.setSpacing(10) + self.setLayout(self.layout) + self.setMinimumWidth(350) + self.button_group = QButtonGroup() + self.button_group.setObjectName('source_select_single_buttongroup') + + def exec_(self, projector): + """ + Override initial method so we can build the tabs. + + :param projector: Projector instance to build source list from + """ + self.projector = projector + self.source_text = self.projectordb.get_source_list(projector.manufacturer, + projector.model, + projector.source_available) + keys = list(self.source_text.keys()) + keys.sort() + key_count = len(keys) + button_list = [] + for key in keys: + button = QtGui.QRadioButton(self.source_text[key]) + button.setChecked(True if key == projector.source else False) + self.layout.addWidget(button) + self.button_group.addButton(button, int(key)) + button_list.append(key) + self.button_box = QDialogButtonBox(QtGui.QDialogButtonBox.Ok | + QtGui.QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept_me) + self.button_box.rejected.connect(self.reject_me) + self.layout.addWidget(self.button_box) + self.setMinimumHeight(key_count*25) + selected = super(SourceSelectSingle, self).exec_() + return selected + + title = QtGui.QLabel(translate('OpenLP.SourceSelectSingle', 'Select the input source below')) + self.layout.addWidget(title) + self.radio_buttons = [] + source_list = self.projectordb.get_source_list(make=projector.link.manufacturer, + model=projector.link.model, + sources=projector.link.source_available) + sort = [] + for item in source_list.keys(): + sort.append(item) + sort.sort() + current = QtGui.QLabel(translate('OpenLP.SourceSelectSingle', 'Current source is %s' % + source_list[projector.link.source])) + layout.addWidget(current) + for item in sort: + button = self._select_input_widget(parent=self, + selected=projector.link.source, + code=item, + text=source_list[item]) + layout.addWidget(button) + button_box = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | + QtGui.QDialogButtonBox.Cancel) + button_box.accepted.connect(box.accept_me) + button_box.rejected.connect(box.reject_me) + layout.addWidget(button_box) + selected = super(SourceSelectSingle, self).exec_() + return selected + + @pyqtSlot() + def accept_me(self): + """ + Slot to accept 'OK' button + """ selected = self.button_group.checkedId() log.debug('SourceSelectDialog().accepted() Setting source to %s' % selected) self.done(selected) @pyqtSlot() def reject_me(self): + """ + Slot to accept 'Cancel' button + """ log.debug('SourceSelectDialog() - Rejected') self.done(0) diff --git a/openlp/core/ui/projector/tab.py b/openlp/core/ui/projector/tab.py index e7d6fcafa..b256aa20b 100644 --- a/openlp/core/ui/projector/tab.py +++ b/openlp/core/ui/projector/tab.py @@ -40,6 +40,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.common import Settings, UiStrings, translate from openlp.core.lib import SettingsTab +from openlp.core.lib.projector import DialogSourceStyle class ProjectorTab(SettingsTab): @@ -66,7 +67,6 @@ class ProjectorTab(SettingsTab): self.connect_box.setObjectName('connect_box') self.connect_box_layout = QtGui.QFormLayout(self.connect_box) self.connect_box_layout.setObjectName('connect_box_layout') - # Start comms with projectors on startup self.connect_on_startup = QtGui.QCheckBox(self.connect_box) self.connect_on_startup.setObjectName('connect_on_startup') @@ -81,16 +81,22 @@ class ProjectorTab(SettingsTab): self.connect_box_layout.addRow(self.socket_timeout_label, self.socket_timeout_spin_box) # Poll interval self.socket_poll_label = QtGui.QLabel(self.connect_box) - self.socket_poll_label.setObjectName('socket_poll.label') + self.socket_poll_label.setObjectName('socket_poll_label') self.socket_poll_spin_box = QtGui.QSpinBox(self.connect_box) self.socket_poll_spin_box.setObjectName('socket_timeout_spin_box') self.socket_poll_spin_box.setMinimum(5) self.socket_poll_spin_box.setMaximum(60) self.connect_box_layout.addRow(self.socket_poll_label, self.socket_poll_spin_box) - self.left_layout.addWidget(self.connect_box) - + # Source input select dialog box type + self.dialog_type_label = QtGui.QLabel(self.connect_box) + self.dialog_type_label.setObjectName('dialog_type_label') + self.dialog_type_combo_box = QtGui.QComboBox(self.connect_box) + self.dialog_type_combo_box.setObjectName('dialog_type_combo_box') + self.dialog_type_combo_box.addItems(['', '']) + self.connect_box_layout.addRow(self.dialog_type_label, self.dialog_type_combo_box) self.left_layout.addStretch() + self.dialog_type_combo_box.activated.connect(self.on_dialog_type_combo_box_changed) def retranslateUi(self): """ @@ -105,6 +111,12 @@ class ProjectorTab(SettingsTab): translate('OpenLP.ProjectorTab', 'Socket timeout (seconds)')) self.socket_poll_label.setText( translate('OpenLP.ProjectorTab', 'Poll time (seconds)')) + self.dialog_type_label.setText( + translate('Openlp.ProjectorTab', 'Source select dialog interface')) + self.dialog_type_combo_box.setItemText(DialogSourceStyle.Tabbed, + translate('OpenLP.ProjectorTab', 'Tabbed dialog box')) + self.dialog_type_combo_box.setItemText(DialogSourceStyle.Single, + translate('OpenLP.ProjectorTab', 'Single dialog box')) def load(self): """ @@ -115,6 +127,7 @@ class ProjectorTab(SettingsTab): self.connect_on_startup.setChecked(settings.value('connect on start')) self.socket_timeout_spin_box.setValue(settings.value('socket timeout')) self.socket_poll_spin_box.setValue(settings.value('poll time')) + self.dialog_type_combo_box.setCurrentIndex(settings.value('source dialog type')) settings.endGroup() def save(self): @@ -126,4 +139,8 @@ class ProjectorTab(SettingsTab): settings.setValue('connect on start', self.connect_on_startup.isChecked()) settings.setValue('socket timeout', self.socket_timeout_spin_box.value()) settings.setValue('poll time', self.socket_poll_spin_box.value()) + settings.setValue('source dialog type', self.dialog_type_combo_box.currentIndex()) settings.endGroup + + def on_dialog_type_combo_box_changed(self): + self.dialog_type = self.dialog_type_combo_box.currentIndex()