# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 OpenLP Developers #
# --------------------------------------------------------------------------- #
# 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.sourceselectform` module
Provides the dialog window for selecting video source for projector.
"""
import logging
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import translate, is_macosx
from openlp.core.lib import build_icon
from openlp.core.lib.projector.db import ProjectorSource
from openlp.core.lib.projector.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES
log = logging.getLogger(__name__)
[docs]def source_group(inputs, source_text):
"""
Return a dictionary where key is source[0] and values are inputs
grouped by source[0].
::
source_text = dict{"key1": "key1-text",
"key2": "key2-text",
...}
return:
dict{key1[0]: {"key11": "key11-text",
"key12": "key12-text",
"key13": "key13-text",
...}
key2[0]: {"key21": "key21-text",
"key22": "key22-text",
...}
:param inputs: List of inputs
:param source_text: Dictionary of {code: text} values to display
:returns: dict
"""
groupdict = {}
keydict = {}
checklist = inputs
key = checklist[0][0]
for item in checklist:
if item[0] == key:
groupdict[item] = source_text[item]
continue
else:
keydict[key] = groupdict
key = item[0]
groupdict = {item: source_text[item]}
keydict[key] = groupdict
return keydict
[docs]def build_tab(group, source_key, default, projector, projectordb, edit=False):
"""
Create the radio button page for a tab.
Dictionary will be a 1-key entry where key=tab to setup, val=list of inputs.
::
source_key: {"groupkey1": {"key11": "key11-text",
"key12": "key12-text",
...
},
"groupkey2": {"key21": "key21-text",
"key22": "key22-text",
...
},
...
}
:param group: Button group widget to add buttons to
:param source_key: Dictionary of sources for radio buttons
:param default: Default radio button to check
:param projector: Projector instance
:param projectordb: ProjectorDB instance for session
:param edit: If we're editing the source text
"""
buttonchecked = False
widget = QtWidgets.QWidget()
layout = QtWidgets.QFormLayout() if edit else QtWidgets.QVBoxLayout()
layout.setSpacing(10)
widget.setLayout(layout)
tempkey = list(source_key.keys())[0] # Should only be 1 key
sourcelist = list(source_key[tempkey])
sourcelist.sort()
button_count = len(sourcelist)
if edit:
for key in sourcelist:
item = QtWidgets.QLineEdit()
item.setObjectName('source_key_{key}'.format(key=key))
source_item = projectordb.get_source_by_code(code=key, projector_id=projector.db_item.id)
if source_item is None:
item.setText(PJLINK_DEFAULT_CODES[key])
else:
item.setText(source_item.text)
layout.addRow(PJLINK_DEFAULT_CODES[key], item)
group.append(item)
else:
for key in sourcelist:
source_item = projectordb.get_source_by_code(code=key, projector_id=projector.db_item.id)
if source_item is None:
text = source_key[tempkey][key]
else:
text = source_item.text
itemwidget = QtWidgets.QRadioButton(text)
itemwidget.setAutoExclusive(True)
if default == key:
itemwidget.setChecked(True)
buttonchecked = itemwidget.isChecked() or buttonchecked
group.addButton(itemwidget, int(key))
layout.addWidget(itemwidget)
layout.addStretch()
return widget, button_count, buttonchecked
[docs]class SourceSelectTabs(QtWidgets.QDialog):
"""
Class for handling selecting the source for the projector to use.
Uses tabbed interface.
"""
def __init__(self, parent, projectordb, edit=False):
"""
Build the source select dialog using tabbed interface.
:param projectordb: ProjectorDB session to use
"""
log.debug('Initializing SourceSelectTabs()')
super(SourceSelectTabs, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
self.setMinimumWidth(350)
self.projectordb = projectordb
self.edit = edit
if self.edit:
title = translate('OpenLP.SourceSelectForm', 'Edit Projector Source Text')
else:
title = translate('OpenLP.SourceSelectForm', 'Select Projector Source')
self.setWindowTitle(title)
self.setObjectName('source_select_tabs')
self.setWindowIcon(build_icon(':/icon/openlp-log.svg'))
self.setModal(True)
self.layout = QtWidgets.QVBoxLayout()
self.layout.setObjectName('source_select_tabs_layout')
if is_macosx():
self.tabwidget = QtWidgets.QTabWidget(self)
else:
self.tabwidget = FingerTabWidget(self)
self.tabwidget.setObjectName('source_select_tabs_tabwidget')
self.tabwidget.setUsesScrollButtons(False)
if is_macosx():
self.tabwidget.setTabPosition(QtWidgets.QTabWidget.North)
else:
self.tabwidget.setTabPosition(QtWidgets.QTabWidget.West)
self.layout.addWidget(self.tabwidget)
self.setLayout(self.layout)
[docs] 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=projector)
self.source_group = source_group(projector.source_available, self.source_text)
self.button_group = [] if self.edit else QtWidgets.QButtonGroup()
keys = list(self.source_group.keys())
keys.sort()
if self.edit:
for key in keys:
(tab, button_count, buttonchecked) = build_tab(group=self.button_group,
source_key={key: self.source_group[key]},
default=self.projector.source,
projector=self.projector,
projectordb=self.projectordb,
edit=self.edit)
thistab = self.tabwidget.addTab(tab, PJLINK_DEFAULT_SOURCES[key])
if buttonchecked:
self.tabwidget.setCurrentIndex(thistab)
self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset |
QtWidgets.QDialogButtonBox.Discard |
QtWidgets.QDialogButtonBox.Ok |
QtWidgets.QDialogButtonBox.Cancel)
else:
for key in keys:
(tab, button_count, buttonchecked) = build_tab(group=self.button_group,
source_key={key: self.source_group[key]},
default=self.projector.source,
projector=self.projector,
projectordb=self.projectordb,
edit=self.edit)
thistab = self.tabwidget.addTab(tab, PJLINK_DEFAULT_SOURCES[key])
if buttonchecked:
self.tabwidget.setCurrentIndex(thistab)
self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok |
QtWidgets.QDialogButtonBox.Cancel)
self.button_box.clicked.connect(self.button_clicked)
self.layout.addWidget(self.button_box)
set_button_tooltip(self.button_box)
selected = super(SourceSelectTabs, self).exec()
return selected
[docs] def delete_sources(self):
"""
Delete the sources for this projector
"""
msg = QtWidgets.QMessageBox()
msg.setText(translate('OpenLP.SourceSelectForm', 'Delete entries for this projector'))
msg.setInformativeText(translate('OpenLP.SourceSelectForm',
'Are you sure you want to delete ALL user-defined '
'source input text for this projector?'))
msg.setStandardButtons(msg.Cancel | msg.Ok)
msg.setDefaultButton(msg.Cancel)
ans = msg.exec()
if ans == msg.Cancel:
return
self.projectordb.delete_all_objects(ProjectorSource, ProjectorSource.projector_id == self.projector.db_item.id)
self.done(100)
[docs] def accept_me(self):
"""
Slot to accept 'OK' button
"""
projector = self.projector.db_item
if self.edit:
for key in self.button_group:
code = key.objectName().split("_")[-1]
text = key.text().strip()
if key.text().strip().lower() == PJLINK_DEFAULT_CODES[code].strip().lower():
continue
item = self.projectordb.get_source_by_code(code=code, projector_id=projector.id)
if item is None:
log.debug("({ip}) Adding new source text {code}: {text}".format(ip=projector.ip,
code=code,
text=text))
item = ProjectorSource(projector_id=projector.id, code=code, text=text)
else:
item.text = text
log.debug('({ip}) Updating source code {code} with text="{text}"'.format(ip=projector.ip,
code=item.code,
text=item.text))
self.projectordb.add_source(item)
selected = 0
else:
selected = self.button_group.checkedId()
log.debug('SourceSelectTabs().accepted() Setting source to {selected}'.format(selected=selected))
self.done(selected)
[docs]class SourceSelectSingle(QtWidgets.QDialog):
"""
Class for handling selecting the source for the projector to use.
Uses single dialog interface.
"""
def __init__(self, parent, projectordb, edit=False):
"""
Build the source select dialog.
:param projectordb: ProjectorDB session to use
"""
log.debug('Initializing SourceSelectSingle()')
self.projectordb = projectordb
super(SourceSelectSingle, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
self.edit = edit
if self.edit:
title = translate('OpenLP.SourceSelectForm', 'Edit Projector Source Text')
else:
title = translate('OpenLP.SourceSelectForm', 'Select Projector Source')
self.setObjectName('source_select_single')
self.setWindowIcon(build_icon(':/icon/openlp-log.svg'))
self.setModal(True)
self.edit = edit
[docs] def exec(self, projector, edit=False):
"""
Override initial method so we can build the tabs.
:param projector: Projector instance to build source list from
"""
self.projector = projector
self.layout = QtWidgets.QFormLayout() if self.edit else QtWidgets.QVBoxLayout()
self.layout.setObjectName('source_select_tabs_layout')
self.layout.setSpacing(10)
self.setLayout(self.layout)
self.setMinimumWidth(350)
self.button_group = [] if self.edit else QtWidgets.QButtonGroup()
self.source_text = self.projectordb.get_source_list(projector=projector)
keys = list(self.source_text.keys())
keys.sort()
key_count = len(keys)
button_list = []
if self.edit:
for key in keys:
item = QtWidgets.QLineEdit()
item.setObjectName('source_key_{key}'.format(key=key))
source_item = self.projectordb.get_source_by_code(code=key, projector_id=self.projector.db_item.id)
if source_item is None:
item.setText(PJLINK_DEFAULT_CODES[key])
else:
item.old_text = item.text()
item.setText(source_item.text)
self.layout.addRow(PJLINK_DEFAULT_CODES[key], item)
self.button_group.append(item)
self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset |
QtWidgets.QDialogButtonBox.Discard |
QtWidgets.QDialogButtonBox.Ok |
QtWidgets.QDialogButtonBox.Cancel)
else:
for key in keys:
source_text = self.projectordb.get_source_by_code(code=key, projector_id=self.projector.db_item.id)
text = self.source_text[key] if source_text is None else source_text.text
button = QtWidgets.QRadioButton(text)
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 = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok |
QtWidgets.QDialogButtonBox.Cancel)
self.button_box.clicked.connect(self.button_clicked)
self.layout.addWidget(self.button_box)
self.setMinimumHeight(key_count * 25)
set_button_tooltip(self.button_box)
selected = super(SourceSelectSingle, self).exec()
return selected
[docs] def delete_sources(self):
msg = QtWidgets.QMessageBox()
msg.setText(translate('OpenLP.SourceSelectForm', 'Delete entries for this projector'))
msg.setInformativeText(translate('OpenLP.SourceSelectForm',
'Are you sure you want to delete ALL user-defined '
'source input text for this projector?'))
msg.setStandardButtons(msg.Cancel | msg.Ok)
msg.setDefaultButton(msg.Cancel)
ans = msg.exec()
if ans == msg.Cancel:
return
self.projectordb.delete_all_objects(ProjectorSource, ProjectorSource.projector_id == self.projector.db_item.id)
self.done(100)
[docs] @QtCore.pyqtSlot()
def accept_me(self):
"""
Slot to accept 'OK' button
"""
projector = self.projector.db_item
if self.edit:
for key in self.button_group:
code = key.objectName().split("_")[-1]
text = key.text().strip()
if key.text().strip().lower() == PJLINK_DEFAULT_CODES[code].strip().lower():
continue
item = self.projectordb.get_source_by_code(code=code, projector_id=projector.id)
if item is None:
log.debug("({ip}) Adding new source text {code}: {text}".format(ip=projector.ip,
code=code,
text=text))
item = ProjectorSource(projector_id=projector.id, code=code, text=text)
else:
item.text = text
log.debug('({ip}) Updating source code {code} with text="{text}"'.format(ip=projector.ip,
code=item.code,
text=item.text))
self.projectordb.add_source(item)
selected = 0
else:
selected = self.button_group.checkedId()
log.debug('SourceSelectDialog().accepted() Setting source to {selected}'.format(selected=selected))
self.done(selected)