Head r1834

This commit is contained in:
Jon Tibble 2011-12-12 21:25:23 +00:00
commit b560981702
18 changed files with 146 additions and 37 deletions

View File

@ -358,10 +358,17 @@ class Manager(object):
def delete_all_objects(self, object_class, filter_clause=None): def delete_all_objects(self, object_class, filter_clause=None):
""" """
Delete all object records Delete all object records.
This method should only be used for simple tables and not ones with
relationships. The relationships are not deleted from the database and
this will lead to database corruptions.
``object_class`` ``object_class``
The type of object to delete The type of object to delete
``filter_clause``
The filter governing selection of objects to return. Defaults to
None.
""" """
try: try:
query = self.session.query(object_class) query = self.session.query(object_class)

View File

@ -115,8 +115,12 @@ class EventReceiver(QtCore.QObject):
``slidecontroller_live_stop_loop`` ``slidecontroller_live_stop_loop``
Stop the loop on the main display. Stop the loop on the main display.
**Servicemanager related signals** **Servicemanager related signals**
``servicemanager_new_service``
A new service is being loaded or created.
``servicemanager_previous_item`` ``servicemanager_previous_item``
Display the previous item in the service. Display the previous item in the service.

View File

@ -119,6 +119,7 @@ class ServiceItem(object):
self.image_border = u'#000000' self.image_border = u'#000000'
self.background_audio = [] self.background_audio = []
self.theme_overwritten = False self.theme_overwritten = False
self.temporary_edit = False
self._new_item() self._new_item()
def _new_item(self): def _new_item(self):
@ -365,6 +366,7 @@ class ServiceItem(object):
""" """
self._uuid = other._uuid self._uuid = other._uuid
self.notes = other.notes self.notes = other.notes
self.temporary_edit = other.temporary_edit
# Copy theme over if present. # Copy theme over if present.
if other.theme is not None: if other.theme is not None:
self.theme = other.theme self.theme = other.theme

View File

@ -125,3 +125,9 @@ class SettingsTab(QtGui.QWidget):
""" """
pass pass
def tabVisible(self):
"""
Tab has just been made visible to the user
"""
pass

View File

@ -37,7 +37,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, \ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
ItemCapabilities, SettingsManager, translate ItemCapabilities, SettingsManager, translate, str_to_bool
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, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
context_menu_action, context_menu_separator, find_and_set_in_combo_box context_menu_action, context_menu_separator, find_and_set_in_combo_box
@ -465,6 +465,7 @@ class ServiceManager(QtGui.QWidget):
self.setModified(False) self.setModified(False)
QtCore.QSettings(). \ QtCore.QSettings(). \
setValue(u'servicemanager/last file',QtCore.QVariant(u'')) setValue(u'servicemanager/last file',QtCore.QVariant(u''))
Receiver.send_message(u'servicemanager_new_service')
def saveFile(self): def saveFile(self):
""" """
@ -663,13 +664,14 @@ class ServiceManager(QtGui.QWidget):
serviceItem.renderer = self.mainwindow.renderer serviceItem.renderer = self.mainwindow.renderer
serviceItem.set_from_service(item, self.servicePath) serviceItem.set_from_service(item, self.servicePath)
self.validateItem(serviceItem) self.validateItem(serviceItem)
self.loadItem_uuid = 0 self.load_item_uuid = 0
if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate): if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate):
Receiver.send_message(u'%s_service_load' % Receiver.send_message(u'%s_service_load' %
serviceItem.name.lower(), serviceItem) serviceItem.name.lower(), serviceItem)
# if the item has been processed # if the item has been processed
if serviceItem._uuid == self.loadItem_uuid: if serviceItem._uuid == self.load_item_uuid:
serviceItem.edit_id = int(self.loadItem_editId) serviceItem.edit_id = int(self.load_item_edit_id)
serviceItem.temporary_edit = self.load_item_temporary
self.addServiceItem(serviceItem, repaint=False) self.addServiceItem(serviceItem, repaint=False)
delete_file(p_file) delete_file(p_file)
self.setFileName(fileName) self.setFileName(fileName)
@ -999,6 +1001,17 @@ class ServiceManager(QtGui.QWidget):
painter.drawImage(0, 0, overlay) painter.drawImage(0, 0, overlay)
painter.end() painter.end()
treewidgetitem.setIcon(0, build_icon(icon)) treewidgetitem.setIcon(0, build_icon(icon))
elif serviceitem.temporary_edit:
icon = QtGui.QImage(serviceitem.icon)
icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
overlay = QtGui.QImage(':/general/general_export.png')
overlay = overlay.scaled(40, 40, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
painter = QtGui.QPainter(icon)
painter.drawImage(40, 0, overlay)
painter.end()
treewidgetitem.setIcon(0, build_icon(icon))
else: else:
treewidgetitem.setIcon(0, serviceitem.iconic_representation) treewidgetitem.setIcon(0, serviceitem.iconic_representation)
else: else:
@ -1006,6 +1019,11 @@ class ServiceManager(QtGui.QWidget):
build_icon(u':/general/general_delete.png')) build_icon(u':/general/general_delete.png'))
treewidgetitem.setText(0, serviceitem.get_display_title()) treewidgetitem.setText(0, serviceitem.get_display_title())
tips = [] tips = []
if serviceitem.temporary_edit:
tips.append(u'<strong>%s:</strong> <em>%s</em>' %
(unicode(translate('OpenLP.ServiceManager', 'Edit')),
(unicode(translate('OpenLP.ServiceManager',
'Service copy only')))))
if serviceitem.theme and serviceitem.theme != -1: if serviceitem.theme and serviceitem.theme != -1:
tips.append(u'<strong>%s:</strong> <em>%s</em>' % tips.append(u'<strong>%s:</strong> <em>%s</em>' %
(unicode(translate('OpenLP.ServiceManager', 'Slide theme')), (unicode(translate('OpenLP.ServiceManager', 'Slide theme')),
@ -1127,8 +1145,9 @@ class ServiceManager(QtGui.QWidget):
Triggered from plugins to update service items. Triggered from plugins to update service items.
Save the values as they will be used as part of the service load Save the values as they will be used as part of the service load
""" """
editId, self.loadItem_uuid = message.split(u':') edit_id, self.load_item_uuid, temporary = message.split(u':')
self.loadItem_editId = int(editId) self.load_item_edit_id = int(edit_id)
self.load_item_temporary = str_to_bool(temporary)
def replaceServiceItem(self, newItem): def replaceServiceItem(self, newItem):
""" """

View File

@ -55,7 +55,7 @@ class Ui_SettingsDialog(object):
QtCore.QMetaObject.connectSlotsByName(settingsDialog) QtCore.QMetaObject.connectSlotsByName(settingsDialog)
QtCore.QObject.connect(self.settingListWidget, QtCore.QObject.connect(self.settingListWidget,
QtCore.SIGNAL(u'currentRowChanged(int)'), QtCore.SIGNAL(u'currentRowChanged(int)'),
self.stackedLayout.setCurrentIndex) self.tabChanged)
def retranslateUi(self, settingsDialog): def retranslateUi(self, settingsDialog):
settingsDialog.setWindowTitle(translate('OpenLP.SettingsForm', settingsDialog.setWindowTitle(translate('OpenLP.SettingsForm',

View File

@ -116,3 +116,10 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
for plugin in self.plugins: for plugin in self.plugins:
if plugin.settings_tab: if plugin.settings_tab:
plugin.settings_tab.postSetUp() plugin.settings_tab.postSetUp()
def tabChanged(self, tabIndex):
"""
A different settings tab is selected
"""
self.stackedLayout.setCurrentIndex(tabIndex)
self.stackedLayout.currentWidget().tabVisible()

View File

@ -184,7 +184,15 @@ class ImpressController(PresentationController):
if not desktop: if not desktop:
return return
docs = desktop.getComponents() docs = desktop.getComponents()
cnt = 0
if docs.hasElements(): if docs.hasElements():
list = docs.createEnumeration()
while list.hasMoreElements():
doc = list.nextElement()
if doc.getImplementationName() != \
u'com.sun.star.comp.framework.BackingComp':
cnt = cnt + 1
if cnt > 0:
log.debug(u'OpenOffice not terminated as docs are still open') log.debug(u'OpenOffice not terminated as docs are still open')
else: else:
try: try:

View File

@ -378,7 +378,7 @@ class PresentationController(object):
self.name = name self.name = name
self.document_class = document_class self.document_class = document_class
self.settings_section = self.plugin.settingsSection self.settings_section = self.plugin.settingsSection
self.available = self.check_available() self.available = None
self.temp_folder = os.path.join( self.temp_folder = os.path.join(
AppLocation.get_section_data_path(self.settings_section), name) AppLocation.get_section_data_path(self.settings_section), name)
self.thumbnail_folder = os.path.join( self.thumbnail_folder = os.path.join(
@ -392,14 +392,19 @@ class PresentationController(object):
""" """
Return whether the controller is currently enabled Return whether the controller is currently enabled
""" """
if self.available: if QtCore.QSettings().value(
return QtCore.QSettings().value( self.settings_section + u'/' + self.name,
self.settings_section + u'/' + self.name, QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \
QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \ QtCore.Qt.Checked:
QtCore.Qt.Checked return self.is_available()
else: else:
return False return False
def is_available(self):
if self.available is None:
self.available = self.check_available()
return self.available
def check_available(self): def check_available(self):
""" """
Presentation app is able to run on this machine Presentation app is able to run on this machine

View File

@ -55,7 +55,6 @@ class PresentationTab(SettingsTab):
for key in self.controllers: for key in self.controllers:
controller = self.controllers[key] controller = self.controllers[key]
checkbox = QtGui.QCheckBox(self.ControllersGroupBox) checkbox = QtGui.QCheckBox(self.ControllersGroupBox)
checkbox.setEnabled(controller.available)
checkbox.setObjectName(controller.name + u'CheckBox') checkbox.setObjectName(controller.name + u'CheckBox')
self.PresenterCheckboxes[controller.name] = checkbox self.PresenterCheckboxes[controller.name] = checkbox
self.ControllersLayout.addWidget(checkbox) self.ControllersLayout.addWidget(checkbox)
@ -81,17 +80,20 @@ class PresentationTab(SettingsTab):
for key in self.controllers: for key in self.controllers:
controller = self.controllers[key] controller = self.controllers[key]
checkbox = self.PresenterCheckboxes[controller.name] checkbox = self.PresenterCheckboxes[controller.name]
if controller.available: self.setControllerText(checkbox, controller)
checkbox.setText(controller.name)
else:
checkbox.setText(
unicode(translate('PresentationPlugin.PresentationTab',
'%s (unavailable)')) % controller.name)
self.AdvancedGroupBox.setTitle(UiStrings().Advanced) self.AdvancedGroupBox.setTitle(UiStrings().Advanced)
self.OverrideAppCheckBox.setText( self.OverrideAppCheckBox.setText(
translate('PresentationPlugin.PresentationTab', translate('PresentationPlugin.PresentationTab',
'Allow presentation application to be overriden')) 'Allow presentation application to be overriden'))
def setControllerText(self, checkbox, controller):
if checkbox.isEnabled():
checkbox.setText(controller.name)
else:
checkbox.setText(
unicode(translate('PresentationPlugin.PresentationTab',
'%s (unavailable)')) % controller.name)
def load(self): def load(self):
""" """
Load the settings. Load the settings.
@ -113,7 +115,7 @@ class PresentationTab(SettingsTab):
changed = False changed = False
for key in self.controllers: for key in self.controllers:
controller = self.controllers[key] controller = self.controllers[key]
if controller.available: if controller.is_available():
checkbox = self.PresenterCheckboxes[controller.name] checkbox = self.PresenterCheckboxes[controller.name]
setting_key = self.settingsSection + u'/' + controller.name setting_key = self.settingsSection + u'/' + controller.name
if QtCore.QSettings().value(setting_key) != \ if QtCore.QSettings().value(setting_key) != \
@ -133,3 +135,13 @@ class PresentationTab(SettingsTab):
changed = True changed = True
if changed: if changed:
Receiver.send_message(u'mediaitem_presentation_rebuild') Receiver.send_message(u'mediaitem_presentation_rebuild')
def tabVisible(self):
"""
Tab has just been made visible to the user
"""
for key in self.controllers:
controller = self.controllers[key]
checkbox = self.PresenterCheckboxes[controller.name]
checkbox.setEnabled(controller.is_available())
self.setControllerText(checkbox, controller)

View File

@ -252,6 +252,9 @@ class SongExportForm(OpenLPWizard):
songs = self.plugin.manager.get_all_objects(Song) songs = self.plugin.manager.get_all_objects(Song)
songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower()) songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower())
for song in songs: for song in songs:
# No need to export temporary songs.
if song.temporary:
continue
authors = u', '.join([author.display_name authors = u', '.join([author.display_name
for author in song.authors]) for author in song.authors])
title = u'%s (%s)' % (unicode(song.title), authors) title = u'%s (%s)' % (unicode(song.title), authors)

View File

@ -199,7 +199,8 @@ def init_schema(url):
Column(u'search_lyrics', types.UnicodeText, nullable=False), Column(u'search_lyrics', types.UnicodeText, nullable=False),
Column(u'create_date', types.DateTime(), default=func.now()), Column(u'create_date', types.DateTime(), default=func.now()),
Column(u'last_modified', types.DateTime(), default=func.now(), Column(u'last_modified', types.DateTime(), default=func.now(),
onupdate=func.now()) onupdate=func.now()),
Column(u'temporary', types.Boolean(), default=False)
) )
# Definition of the "topics" table # Definition of the "topics" table

View File

@ -270,6 +270,9 @@ class SongMediaItem(MediaManagerItem):
searchresults.sort( searchresults.sort(
cmp=locale.strcoll, key=lambda song: song.title.lower()) cmp=locale.strcoll, key=lambda song: song.title.lower())
for song in searchresults: for song in searchresults:
# Do not display temporary songs
if song.temporary:
continue
author_list = [author.display_name for author in song.authors] author_list = [author.display_name for author in song.authors]
song_title = unicode(song.title) song_title = unicode(song.title)
song_detail = u'%s (%s)' % (song_title, u', '.join(author_list)) song_detail = u'%s (%s)' % (song_title, u', '.join(author_list))
@ -286,6 +289,9 @@ class SongMediaItem(MediaManagerItem):
self.listView.clear() self.listView.clear()
for author in searchresults: for author in searchresults:
for song in author.songs: for song in author.songs:
# Do not display temporary songs
if song.temporary:
continue
song_detail = u'%s (%s)' % (author.display_name, song.title) song_detail = u'%s (%s)' % (author.display_name, song.title)
song_name = QtGui.QListWidgetItem(song_detail) song_name = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id)) song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
@ -534,6 +540,7 @@ class SongMediaItem(MediaManagerItem):
Song.search_title.asc()) Song.search_title.asc())
editId = 0 editId = 0
add_song = True add_song = True
temporary = False
if search_results: if search_results:
for song in search_results: for song in search_results:
author_list = item.data_string[u'authors'] author_list = item.data_string[u'authors']
@ -559,13 +566,18 @@ class SongMediaItem(MediaManagerItem):
self._updateBackgroundAudio(song, item) self._updateBackgroundAudio(song, item)
editId = song.id editId = song.id
self.onSearchTextButtonClick() self.onSearchTextButtonClick()
else: elif add_song and not self.addSongFromService:
# Make sure we temporary import formatting tags. # Make sure we temporary import formatting tags.
self.openLyrics.xml_to_song(item.xml_version, True) song = self.openLyrics.xml_to_song(item.xml_version, True)
# If there's any backing tracks, copy them over.
if len(item.background_audio) > 0:
self._updateBackgroundAudio(song, item)
editId = song.id
temporary = True
# Update service with correct song id. # Update service with correct song id.
if editId: if editId:
Receiver.send_message(u'service_item_update', Receiver.send_message(u'service_item_update',
u'%s:%s' % (editId, item._uuid)) u'%s:%s:%s' % (editId, item._uuid, temporary))
def search(self, string): def search(self, string):
""" """

View File

@ -345,7 +345,8 @@ class SofImport(OooImport):
u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS',
u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH',
u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S',
u'FATHER\'S', u'ELIJAH'): u'FATHER\'S', u'ELIJAH' u'MARTHA', u'CHRISTMAS', u'ALPHA',
u'OMEGA'):
textarr[i] = textarr[i].capitalize() textarr[i] = textarr[i].capitalize()
else: else:
textarr[i] = textarr[i].lower() textarr[i] = textarr[i].lower()

View File

@ -33,7 +33,9 @@ from sqlalchemy import Column, Table, types
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from migrate.changeset.constraint import ForeignKeyConstraint from migrate.changeset.constraint import ForeignKeyConstraint
__version__ = 2 from openlp.plugins.songs.lib.db import Song
__version__ = 3
def upgrade_setup(metadata): def upgrade_setup(metadata):
""" """
@ -86,3 +88,12 @@ def upgrade_2(session, metadata, tables):
Column(u'last_modified', types.DateTime(), default=func.now())\ Column(u'last_modified', types.DateTime(), default=func.now())\
.create(table=tables[u'songs']) .create(table=tables[u'songs'])
def upgrade_3(session, metadata, tables):
"""
Version 3 upgrade.
This upgrade adds a temporary song flag to the songs table
"""
Column(u'temporary', types.Boolean(), default=False)\
.create(table=tables[u'songs'])

View File

@ -346,7 +346,7 @@ class OpenLyrics(object):
lines_element.set(u'break', u'optional') lines_element.set(u'break', u'optional')
return self._extract_xml(song_xml) return self._extract_xml(song_xml)
def xml_to_song(self, xml, parse_and_not_save=False): def xml_to_song(self, xml, parse_and_temporary_save=False):
""" """
Create and save a song from OpenLyrics format xml to the database. Since Create and save a song from OpenLyrics format xml to the database. Since
we also export XML from external sources (e. g. OpenLyrics import), we we also export XML from external sources (e. g. OpenLyrics import), we
@ -355,9 +355,9 @@ class OpenLyrics(object):
``xml`` ``xml``
The XML to parse (unicode). The XML to parse (unicode).
``parse_and_not_save`` ``parse_and_temporary_save``
Switch to skip processing the whole song and to prevent storing the Switch to skip processing the whole song and storing the songs in
songs to the database. Defaults to ``False``. the database with a temporary flag. Defaults to ``False``.
""" """
# No xml get out of here. # No xml get out of here.
if not xml: if not xml:
@ -371,14 +371,13 @@ class OpenLyrics(object):
return None return None
# Formatting tags are new in OpenLyrics 0.8 # Formatting tags are new in OpenLyrics 0.8
if float(song_xml.get(u'version')) > 0.7: if float(song_xml.get(u'version')) > 0.7:
self._process_formatting_tags(song_xml, parse_and_not_save) self._process_formatting_tags(song_xml, parse_and_temporary_save)
if parse_and_not_save:
return
song = Song() song = Song()
# Values will be set when cleaning the song. # Values will be set when cleaning the song.
song.search_lyrics = u'' song.search_lyrics = u''
song.verse_order = u'' song.verse_order = u''
song.search_title = u'' song.search_title = u''
song.temporary = parse_and_temporary_save
self._process_copyright(properties, song) self._process_copyright(properties, song)
self._process_cclinumber(properties, song) self._process_cclinumber(properties, song)
self._process_titles(properties, song) self._process_titles(properties, song)

View File

@ -78,6 +78,10 @@ class SongsPlugin(Plugin):
action_list.add_action(self.songExportItem, unicode(UiStrings().Export)) action_list.add_action(self.songExportItem, unicode(UiStrings().Export))
action_list.add_action(self.toolsReindexItem, action_list.add_action(self.toolsReindexItem,
unicode(UiStrings().Tools)) unicode(UiStrings().Tools))
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_new_service'),
self.clearTemporarySongs)
def addImportMenuItem(self, import_menu): def addImportMenuItem(self, import_menu):
""" """
@ -265,6 +269,8 @@ class SongsPlugin(Plugin):
Time to tidy up on exit Time to tidy up on exit
""" """
log.info(u'Songs Finalising') log.info(u'Songs Finalising')
self.clearTemporarySongs()
# Clean up files and connections
self.manager.finalise() self.manager.finalise()
self.songImportItem.setVisible(False) self.songImportItem.setVisible(False)
self.songExportItem.setVisible(False) self.songExportItem.setVisible(False)
@ -277,3 +283,9 @@ class SongsPlugin(Plugin):
action_list.remove_action(self.toolsReindexItem, action_list.remove_action(self.toolsReindexItem,
unicode(UiStrings().Tools)) unicode(UiStrings().Tools))
Plugin.finalise(self) Plugin.finalise(self)
def clearTemporarySongs(self):
# Remove temporary songs
songs = self.manager.get_all_objects(Song, Song.temporary == True)
for song in songs:
self.manager.delete_object(Song, song.id)