This commit is contained in:
Tim Bentley 2013-01-02 22:05:54 +00:00
commit d6ad079a0b
7 changed files with 117 additions and 49 deletions

View File

@ -141,10 +141,21 @@ class Settings(QtCore.QSettings):
if defaultValue is None and not super(Settings, self).contains(key): if defaultValue is None and not super(Settings, self).contains(key):
return None return None
setting = super(Settings, self).value(key, defaultValue) setting = super(Settings, self).value(key, defaultValue)
# An empty list saved to the settings results in a None type being # On OS X (and probably on other platforms too) empty value from QSettings
# returned. # is represented as type PyQt4.QtCore.QPyNullVariant. This type has to be
# converted to proper 'None' Python type.
if isinstance(setting, QtCore.QPyNullVariant) and setting.isNull():
setting = None
# Handle 'None' type (empty value) properly.
if setting is None: if setting is None:
return [] # An empty string saved to the settings results in a None type being
# returned. Convert it to empty unicode string.
if isinstance(defaultValue, unicode):
return u''
# An empty list saved to the settings results in a None type being
# returned.
else:
return []
# Convert the setting to the correct type. # Convert the setting to the correct type.
if isinstance(defaultValue, bool): if isinstance(defaultValue, bool):
if isinstance(setting, bool): if isinstance(setting, bool):

View File

@ -40,7 +40,7 @@ log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, SettingsManager, \ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, SettingsManager, \
translate, str_to_bool, check_directory_exists, Settings translate, str_to_bool, check_directory_exists, Settings, PluginStatus
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.ui import UiStrings, critical_error_message_box, create_widget_action, find_and_set_in_combo_box from openlp.core.lib.ui import UiStrings, critical_error_message_box, create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
@ -252,6 +252,9 @@ class ServiceManager(QtGui.QWidget):
icon=u':/media/auto-start_active.png', triggers=self.onAutoStart) icon=u':/media/auto-start_active.png', triggers=self.onAutoStart)
# Add already existing delete action to the menu. # Add already existing delete action to the menu.
self.menu.addAction(self.serviceManagerList.delete) self.menu.addAction(self.serviceManagerList.delete)
self.create_custom_action = create_widget_action(self.menu,
text=translate('OpenLP.ServiceManager', 'Create New &Custom Slide'),
icon=u':/general/general_edit.png', triggers=self.create_custom)
self.menu.addSeparator() self.menu.addSeparator()
self.previewAction = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', 'Show &Preview'), self.previewAction = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', 'Show &Preview'),
icon=u':/general/general_preview.png', triggers=self.makePreview) icon=u':/general/general_preview.png', triggers=self.makePreview)
@ -751,6 +754,7 @@ class ServiceManager(QtGui.QWidget):
pos = item.data(0, QtCore.Qt.UserRole) pos = item.data(0, QtCore.Qt.UserRole)
serviceItem = self.serviceItems[pos - 1] serviceItem = self.serviceItems[pos - 1]
self.editAction.setVisible(False) self.editAction.setVisible(False)
self.create_custom_action.setVisible(False)
self.maintainAction.setVisible(False) self.maintainAction.setVisible(False)
self.notesAction.setVisible(False) self.notesAction.setVisible(False)
self.timeAction.setVisible(False) self.timeAction.setVisible(False)
@ -770,6 +774,11 @@ class ServiceManager(QtGui.QWidget):
if serviceItem[u'service_item'].will_auto_start: if serviceItem[u'service_item'].will_auto_start:
self.autoStartAction.setText(translate('OpenLP.ServiceManager', '&Auto Start - active')) self.autoStartAction.setText(translate('OpenLP.ServiceManager', '&Auto Start - active'))
self.autoStartAction.setIcon(self.active) self.autoStartAction.setIcon(self.active)
if serviceItem[u'service_item'].is_text():
for plugin in self.mainwindow.pluginManager.plugins:
if plugin.name == u'custom' and plugin.status == PluginStatus.Active:
self.create_custom_action.setVisible(True)
break
self.themeMenu.menuAction().setVisible(False) self.themeMenu.menuAction().setVisible(False)
# Set up the theme menu. # Set up the theme menu.
if serviceItem[u'service_item'].is_text() and self.mainwindow.renderer.theme_level == ThemeLevel.Song: if serviceItem[u'service_item'].is_text() and self.mainwindow.renderer.theme_level == ThemeLevel.Song:
@ -1306,6 +1315,13 @@ class ServiceManager(QtGui.QWidget):
Receiver.send_message(u'%s_edit' % self.serviceItems[item][u'service_item'].name.lower(), Receiver.send_message(u'%s_edit' % self.serviceItems[item][u'service_item'].name.lower(),
u'L:%s' % self.serviceItems[item][u'service_item'].edit_id) u'L:%s' % self.serviceItems[item][u'service_item'].edit_id)
def create_custom(self):
"""
Saves the current text item as a custom slide
"""
item = self.findServiceItem()[0]
Receiver.send_message(u'custom_create_from_service', self.serviceItems[item][u'service_item'])
def findServiceItem(self): def findServiceItem(self):
""" """
Finds the first selected ServiceItem in the list and returns the Finds the first selected ServiceItem in the list and returns the

View File

@ -125,8 +125,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
if not self._validate(): if not self._validate():
return False return False
sxml = CustomXMLBuilder() sxml = CustomXMLBuilder()
sxml.new_document()
sxml.add_lyrics_to_song()
for count in range(self.slideListView.count()): for count in range(self.slideListView.count()):
sxml.add_verse_to_lyrics(u'custom', unicode(count + 1), sxml.add_verse_to_lyrics(u'custom', unicode(count + 1),
self.slideListView.item(count).text()) self.slideListView.item(count).text())

View File

@ -48,18 +48,25 @@ class CustomTab(SettingsTab):
self.displayFooterCheckBox = QtGui.QCheckBox(self.customModeGroupBox) self.displayFooterCheckBox = QtGui.QCheckBox(self.customModeGroupBox)
self.displayFooterCheckBox.setObjectName(u'displayFooterCheckBox') self.displayFooterCheckBox.setObjectName(u'displayFooterCheckBox')
self.customModeLayout.addRow(self.displayFooterCheckBox) self.customModeLayout.addRow(self.displayFooterCheckBox)
self.add_from_service_checkbox = QtGui.QCheckBox(self.customModeGroupBox)
self.add_from_service_checkbox.setObjectName(u'add_from_service_checkbox')
self.customModeLayout.addRow(self.add_from_service_checkbox)
self.leftLayout.addWidget(self.customModeGroupBox) self.leftLayout.addWidget(self.customModeGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()
self.rightLayout.addStretch() self.rightLayout.addStretch()
QtCore.QObject.connect(self.displayFooterCheckBox, QtCore.QObject.connect(self.displayFooterCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), QtCore.SIGNAL(u'stateChanged(int)'),
self.onDisplayFooterCheckBoxChanged) self.onDisplayFooterCheckBoxChanged)
QtCore.QObject.connect(self.add_from_service_checkbox,
QtCore.SIGNAL(u'stateChanged(int)'), self.on_add_from_service_check_box_changed)
def retranslateUi(self): def retranslateUi(self):
self.customModeGroupBox.setTitle(translate('CustomPlugin.CustomTab', self.customModeGroupBox.setTitle(translate('CustomPlugin.CustomTab',
'Custom Display')) 'Custom Display'))
self.displayFooterCheckBox.setText( self.displayFooterCheckBox.setText(
translate('CustomPlugin.CustomTab', 'Display footer')) translate('CustomPlugin.CustomTab', 'Display footer'))
self.add_from_service_checkbox.setText(translate('CustomPlugin.CustomTab',
'Import missing custom slides from service files'))
def onDisplayFooterCheckBoxChanged(self, check_state): def onDisplayFooterCheckBoxChanged(self, check_state):
self.displayFooter = False self.displayFooter = False
@ -67,11 +74,21 @@ class CustomTab(SettingsTab):
if check_state == QtCore.Qt.Checked: if check_state == QtCore.Qt.Checked:
self.displayFooter = True self.displayFooter = True
def on_add_from_service_check_box_changed(self, check_state):
self.update_load = (check_state == QtCore.Qt.Checked)
def load(self): def load(self):
self.displayFooter = Settings().value( settings = Settings()
self.settingsSection + u'/display footer', True) settings.beginGroup(self.settingsSection)
self.displayFooter = settings.value(u'display footer', True)
self.update_load = settings.value(u'add custom from service', True)
self.displayFooterCheckBox.setChecked(self.displayFooter) self.displayFooterCheckBox.setChecked(self.displayFooter)
self.add_from_service_checkbox.setChecked(self.update_load)
settings.endGroup()
def save(self): def save(self):
Settings().setValue(self.settingsSection + u'/display footer', settings = Settings()
self.displayFooter) settings.beginGroup(self.settingsSection)
settings.setValue(u'display footer', self.displayFooter)
settings.setValue(u'add custom from service', self.update_load)
settings.endGroup()

View File

@ -62,6 +62,8 @@ class CustomXMLBuilder(object):
""" """
# Create the minidom document # Create the minidom document
self.custom_xml = Document() self.custom_xml = Document()
self.new_document()
self.add_lyrics_to_song()
def new_document(self): def new_document(self):
""" """

View File

@ -30,13 +30,13 @@
import logging import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_, func from sqlalchemy.sql import or_, func, and_
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, check_item_selected, translate, \
check_item_selected, translate, ServiceItemContext, Settings ServiceItemContext, Settings, PluginStatus
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.forms import EditCustomForm
from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib import CustomXMLParser, CustomXMLBuilder
from openlp.plugins.custom.lib.db import CustomSlide from openlp.plugins.custom.lib.db import CustomSlide
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -85,6 +85,12 @@ class CustomMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'custom_load_list'), self.loadList) QtCore.SIGNAL(u'custom_load_list'), self.loadList)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick) QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_create_from_service'), self.create_from_service_item)
def config_updated(self):
self.add_custom_from_service = Settings().value(self.settingsSection + u'/add custom from service', True)
def retranslateUi(self): def retranslateUi(self):
self.searchTextLabel.setText(u'%s:' % UiStrings().Search) self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
@ -102,6 +108,7 @@ class CustomMediaItem(MediaManagerItem):
CustomSlide, order_by_ref=CustomSlide.title)) CustomSlide, order_by_ref=CustomSlide.title))
self.searchTextEdit.setCurrentSearchType(Settings().value( self.searchTextEdit.setCurrentSearchType(Settings().value(
u'%s/last search type' % self.settingsSection, CustomSearch.Titles)) u'%s/last search type' % self.settingsSection, CustomSearch.Titles))
self.config_updated()
def loadList(self, custom_slides): def loadList(self, custom_slides):
# Sort out what custom we want to select after loading the list. # Sort out what custom we want to select after loading the list.
@ -198,6 +205,7 @@ class CustomMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.CanPreview) service_item.add_capability(ItemCapabilities.CanPreview)
service_item.add_capability(ItemCapabilities.CanLoop) service_item.add_capability(ItemCapabilities.CanLoop)
service_item.add_capability(ItemCapabilities.CanSoftBreak) service_item.add_capability(ItemCapabilities.CanSoftBreak)
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
customSlide = self.plugin.manager.get_object(CustomSlide, item_id) customSlide = self.plugin.manager.get_object(CustomSlide, item_id)
title = customSlide.title title = customSlide.title
credit = customSlide.credits credit = customSlide.credits
@ -252,6 +260,49 @@ class CustomMediaItem(MediaManagerItem):
elif not text: elif not text:
self.onClearTextButtonClick() self.onClearTextButtonClick()
def serviceLoad(self, item):
"""
Triggered by a song being loaded by the service manager.
"""
log.debug(u'serviceLoad')
if self.plugin.status != PluginStatus.Active:
return
custom = self.plugin.manager.get_object_filtered(CustomSlide,
and_(CustomSlide.title == item.title, CustomSlide.theme_name == item.theme,
CustomSlide.credits == item.raw_footer[0][len(item.title) + 1:]))
if custom:
Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item._uuid, False))
else:
if self.add_custom_from_service:
self.create_from_service_item(item)
def create_from_service_item(self, item):
"""
Create a custom slide from a text service item
"""
custom = CustomSlide()
custom.title = item.title
if item.theme:
custom.theme_name = item.theme
else:
custom.theme_name = u''
footer = u' '.join(item.raw_footer)
if footer:
if footer.startswith(item.title):
custom.credits = footer[len(item.title) + 1:]
else:
custom.credits = footer
else:
custom.credits = u''
custom_xml = CustomXMLBuilder()
for (idx, slide) in enumerate(item._raw_frames):
custom_xml.add_verse_to_lyrics(u'custom', unicode(idx + 1), slide['raw_slide'])
custom.text = unicode(custom_xml.extract_xml(), u'utf-8')
self.plugin.manager.save_object(custom)
self.onSearchTextButtonClicked()
if item.name.lower() == u'custom':
Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item._uuid, False))
def onClearTextButtonClick(self): def onClearTextButtonClick(self):
""" """
Clear the search text. Clear the search text.

View File

@ -93,6 +93,12 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.verseNumberBox.value()) self.verseNumberBox.value())
def onVerseTypeComboBoxChanged(self): def onVerseTypeComboBoxChanged(self):
self.updateSuggestedVerseNumber()
def onCursorPositionChanged(self):
self.updateSuggestedVerseNumber()
def updateSuggestedVerseNumber(self):
""" """
Adjusts the verse number SpinBox in regard to the selected verse type Adjusts the verse number SpinBox in regard to the selected verse type
and the cursor's position. and the cursor's position.
@ -116,43 +122,10 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
if match: if match:
verse_tag = match.group(1) verse_tag = match.group(1)
try: try:
verse_num = int(match.group(2)) verse_num = int(match.group(2)) + 1
except ValueError: except ValueError:
verse_num = 1 verse_num = 1
if VerseType.from_loose_input(verse_tag, False): self.verseNumberBox.setValue(verse_num)
self.verseNumberBox.setValue(verse_num)
def onCursorPositionChanged(self):
"""
Determines the previous verse type and number in regard to the cursor's
position and adjusts the ComboBox and SpinBox to these values.
"""
position = self.verseTextEdit.textCursor().position()
text = self.verseTextEdit.toPlainText()
if not text:
return
if text.rfind(u'[', 0, position) > text.rfind(u']', 0, position) and \
text.find(u']', position) < text.find(u'[', position):
return
position = text.rfind(u'---[', 0, position)
if position == -1:
return
text = text[position:]
position = text.find(u']---')
if position == -1:
return
text = text[:position + 4]
match = VERSE_REGEX.match(text)
if match:
verse_type = match.group(1)
verse_type_index = VerseType.from_loose_input(verse_type, None)
try:
verse_number = int(match.group(2))
except ValueError:
verse_number = 1
if verse_type_index is not None:
self.verseTypeComboBox.setCurrentIndex(verse_type_index)
self.verseNumberBox.setValue(verse_number)
def setVerse(self, text, single=False, def setVerse(self, text, single=False,
tag=u'%s1' % VerseType.Tags[VerseType.Verse]): tag=u'%s1' % VerseType.Tags[VerseType.Verse]):