From ad61defdae087489603f70412df5491adc447270 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 20 Aug 2011 12:45:06 +0100 Subject: [PATCH 01/22] Add border colors and fix song usage --- openlp/core/lib/__init__.py | 2 +- openlp/core/lib/imagemanager.py | 20 +++++++++++++++----- openlp/core/lib/renderer.py | 5 +++-- openlp/core/lib/serviceitem.py | 8 ++++++-- openlp/core/lib/theme.py | 7 +++++-- openlp/core/ui/printserviceform.py | 5 ++++- openlp/core/ui/themeform.py | 12 ++++++++++++ openlp/core/ui/themewizard.py | 12 +++++++++++- openlp/plugins/images/imageplugin.py | 5 +++-- openlp/plugins/images/lib/__init__.py | 1 + openlp/plugins/images/lib/mediaitem.py | 4 +++- openlp/plugins/songusage/songusageplugin.py | 3 +++ 12 files changed, 67 insertions(+), 17 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index f83e92de7..d9d29efab 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -137,7 +137,7 @@ def image_to_byte(image): # convert to base64 encoding so does not get missed! return byte_array.toBase64() -def resize_image(image_path, width, height, background=QtCore.Qt.black): +def resize_image(image_path, width, height, background): """ Resize an image to fit on the current screen. diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 37d1de79c..a4a60b2f4 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -36,7 +36,7 @@ import Queue from PyQt4 import QtCore -from openlp.core.lib import resize_image, image_to_byte +from openlp.core.lib import resize_image, image_to_byte, Receiver from openlp.core.ui import ScreenList log = logging.getLogger(__name__) @@ -100,12 +100,14 @@ class Image(object): variables ``image`` and ``image_bytes`` to ``None`` and add the image object to the queue of images to process. """ - def __init__(self, name='', path=''): + def __init__(self, name, path, source, background): self.name = name self.path = path self.image = None self.image_bytes = None self.priority = Priority.Normal + self.source = source + self.background = background class PriorityQueue(Queue.PriorityQueue): @@ -151,6 +153,8 @@ class ImageManager(QtCore.QObject): self._cache = {} self._imageThread = ImageThread(self) self._conversion_queue = PriorityQueue() + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_updated'), self.config_updated) def update_display(self): """ @@ -168,6 +172,11 @@ class ImageManager(QtCore.QObject): image.image = None image.image_bytes = None self._conversion_queue.put((image.priority, image)) + + def config_updated(self): + """ + Flush the queue to updated any data to update + """ # We want only one thread. if not self._imageThread.isRunning(): self._imageThread.start() @@ -215,13 +224,13 @@ class ImageManager(QtCore.QObject): self._conversion_queue.remove(self._cache[name]) del self._cache[name] - def add_image(self, name, path): + def add_image(self, name, path, source, background): """ Add image to cache if it is not already there. """ log.debug(u'add_image %s:%s' % (name, path)) if not name in self._cache: - image = Image(name, path) + image = Image(name, path, source, background) self._cache[name] = image self._conversion_queue.put((image.priority, image)) else: @@ -247,7 +256,8 @@ class ImageManager(QtCore.QObject): image = self._conversion_queue.get()[1] # Generate the QImage for the image. if image.image is None: - image.image = resize_image(image.path, self.width, self.height) + image.image = resize_image(image.path, self.width, self.height, + image.background) # Set the priority to Lowest and stop here as we need to process # more important images first. if image.priority == Priority.Normal: diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index ac7e95c4c..9ea9c8094 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -27,7 +27,7 @@ import logging -from PyQt4 import QtCore, QtWebKit +from PyQt4 import QtGui, QtCore, QtWebKit from openlp.core.lib import ServiceItem, expand_tags, \ build_lyrics_format_css, build_lyrics_outline_css, Receiver, \ @@ -166,7 +166,8 @@ class Renderer(object): # if No file do not update cache if self.theme_data.background_filename: self.imageManager.add_image(self.theme_data.theme_name, - self.theme_data.background_filename) + self.theme_data.background_filename, u'theme', + QtGui.QColor(self.theme_data.background_border_color)) return self._rect, self._rect_footer def generate_preview(self, theme_data, force_page=False): diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 15c16c551..7be28520c 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -115,6 +115,7 @@ class ServiceItem(object): self.end_time = 0 self.media_length = 0 self.from_service = False + self.image_border = u'#000000' self._new_item() def _new_item(self): @@ -195,7 +196,7 @@ class ServiceItem(object): self.foot_text = \ u'
'.join([footer for footer in self.raw_footer if footer]) - def add_from_image(self, path, title): + def add_from_image(self, path, title, background=None): """ Add an image slide to the service item. @@ -205,9 +206,12 @@ class ServiceItem(object): ``title`` A title for the slide in the service item. """ + if background: + self.image_border = background self.service_item_type = ServiceItemType.Image self._raw_frames.append({u'title': title, u'path': path}) - self.renderer.imageManager.add_image(title, path) + self.renderer.imageManager.add_image(title, path, u'image', + self.image_border) self._new_item() def add_from_text(self, title, raw_slide, verse_tag=None): diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index c87f9aa2e..3b0a62f5b 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -44,6 +44,7 @@ BLANK_THEME_XML = \ + #000000 #000000 @@ -282,7 +283,7 @@ class ThemeXML(object): # Create direction element self.child_element(background, u'direction', unicode(direction)) - def add_background_image(self, filename): + def add_background_image(self, filename, borderColor): """ Add a image background. @@ -294,6 +295,8 @@ class ThemeXML(object): self.theme.appendChild(background) # Create Filename element self.child_element(background, u'filename', filename) + # Create endColor element + self.child_element(background, u'borderColor', unicode(borderColor)) def add_font(self, name, color, size, override, fonttype=u'main', bold=u'False', italics=u'False', line_adjustment=0, @@ -597,7 +600,7 @@ class ThemeXML(object): self.background_direction) else: filename = os.path.split(self.background_filename)[1] - self.add_background_image(filename) + self.add_background_image(filename, self.background_border_color) self.add_font(self.font_main_name, self.font_main_color, self.font_main_size, diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index 55fc6eb3c..f33092061 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -31,7 +31,7 @@ import os from PyQt4 import QtCore, QtGui from lxml import html -from openlp.core.lib import translate, get_text_file_string +from openlp.core.lib import translate, get_text_file_string, Receiver from openlp.core.lib.ui import UiStrings from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize from openlp.core.utils import AppLocation @@ -188,6 +188,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): html_data.body, classId=u'serviceTitle') for index, item in enumerate(self.serviceManager.serviceItems): self._addPreviewItem(html_data.body, item[u'service_item'], index) + # Trigger Audit requests + Receiver.send_message(u'print_service_started', + [item[u'service_item']]) # Add the custom service notes: if self.footerTextEdit.toPlainText(): div = self._addElement(u'div', parent=html_data.body, diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index d5d955926..b56b68b5b 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -66,6 +66,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.onGradientComboBoxCurrentIndexChanged) QtCore.QObject.connect(self.colorButton, QtCore.SIGNAL(u'clicked()'), self.onColorButtonClicked) + QtCore.QObject.connect(self.imageColorButton, + QtCore.SIGNAL(u'clicked()'), self.onImageColorButtonClicked) QtCore.QObject.connect(self.gradientStartButton, QtCore.SIGNAL(u'clicked()'), self.onGradientStartButtonClicked) QtCore.QObject.connect(self.gradientEndButton, @@ -330,6 +332,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.theme.background_end_color) self.setField(u'background_type', QtCore.QVariant(1)) else: + self.imageColorButton.setStyleSheet(u'background-color: %s' % + self.theme.background_border_color) self.imageFileEdit.setText(self.theme.background_filename) self.setField(u'background_type', QtCore.QVariant(2)) if self.theme.background_direction == \ @@ -464,6 +468,14 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self._colorButton(self.theme.background_color) self.setBackgroundPageValues() + def onImageColorButtonClicked(self): + """ + Background / Gradient 1 Color button pushed. + """ + self.theme.background_border_color = \ + self._colorButton(self.theme.background_border_color) + self.setBackgroundPageValues() + def onGradientStartButtonClicked(self): """ Gradient 2 Color button pushed. diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 27ac3a182..805ce876b 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -64,6 +64,7 @@ class Ui_ThemeWizard(object): self.backgroundStack.setObjectName(u'BackgroundStack') self.colorWidget = QtGui.QWidget(self.backgroundPage) self.colorWidget.setObjectName(u'ColorWidget') + self.colorLayout = QtGui.QFormLayout(self.colorWidget) self.colorLayout.setMargin(0) self.colorLayout.setObjectName(u'ColorLayout') @@ -73,6 +74,7 @@ class Ui_ThemeWizard(object): self.colorButton.setObjectName(u'ColorButton') self.colorLayout.addRow(self.colorLabel, self.colorButton) self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer) + self.backgroundStack.addWidget(self.colorWidget) self.gradientWidget = QtGui.QWidget(self.backgroundPage) self.gradientWidget.setObjectName(u'GradientWidget') @@ -100,11 +102,17 @@ class Ui_ThemeWizard(object): self.gradientComboBox) self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer) self.backgroundStack.addWidget(self.gradientWidget) + self.imageWidget = QtGui.QWidget(self.backgroundPage) self.imageWidget.setObjectName(u'ImageWidget') self.imageLayout = QtGui.QFormLayout(self.imageWidget) self.imageLayout.setMargin(0) self.imageLayout.setObjectName(u'ImageLayout') + self.imageColorLabel = QtGui.QLabel(self.colorWidget) + self.imageColorLabel.setObjectName(u'ImageColorLabel') + self.imageColorButton = QtGui.QPushButton(self.colorWidget) + self.imageColorButton.setObjectName(u'ImageColorButton') + self.imageLayout.addRow(self.imageColorLabel, self.imageColorButton) self.imageLabel = QtGui.QLabel(self.imageWidget) self.imageLabel.setObjectName(u'ImageLabel') self.imageFileLayout = QtGui.QHBoxLayout() @@ -118,7 +126,7 @@ class Ui_ThemeWizard(object): build_icon(u':/general/general_open.png')) self.imageFileLayout.addWidget(self.imageBrowseButton) self.imageLayout.addRow(self.imageLabel, self.imageFileLayout) - self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer) + self.imageLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.spacer) self.backgroundStack.addWidget(self.imageWidget) self.backgroundLayout.addLayout(self.backgroundStack) themeWizard.addPage(self.backgroundPage) @@ -443,6 +451,8 @@ class Ui_ThemeWizard(object): translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right')) self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom, translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) + self.imageColorLabel.setText( + translate(u'OpenLP.ThemeWizard', 'Border color:')) self.imageLabel.setText(u'%s:' % UiStrings().Image) self.mainAreaPage.setTitle( translate('OpenLP.ThemeWizard', 'Main Area Font Details')) diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 1ddbe8357..aeeee5c5d 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -28,7 +28,7 @@ import logging from openlp.core.lib import Plugin, StringContent, build_icon, translate -from openlp.plugins.images.lib import ImageMediaItem +from openlp.plugins.images.lib import ImageMediaItem, ImageTab log = logging.getLogger(__name__) @@ -36,7 +36,8 @@ class ImagePlugin(Plugin): log.info(u'Image Plugin loaded') def __init__(self, plugin_helpers): - Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem) + Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem, + ImageTab) self.weight = -7 self.icon_path = u':/plugins/plugin_images.png' self.icon = build_icon(self.icon_path) diff --git a/openlp/plugins/images/lib/__init__.py b/openlp/plugins/images/lib/__init__.py index b26d00184..e216623cd 100644 --- a/openlp/plugins/images/lib/__init__.py +++ b/openlp/plugins/images/lib/__init__.py @@ -26,3 +26,4 @@ ############################################################################### from mediaitem import ImageMediaItem +from imagetab import ImageTab diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index acd420880..d88cf47e7 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -140,6 +140,8 @@ class ImageMediaItem(MediaManagerItem): self.plugin.formparent.finishedProgressBar() def generateSlideData(self, service_item, item=None, xmlVersion=False): + background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + + u'/background color', QtCore.QVariant(u'#000000'))) if item: items = [item] else: @@ -183,7 +185,7 @@ class ImageMediaItem(MediaManagerItem): for bitem in items: filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) (path, name) = os.path.split(filename) - service_item.add_from_image(filename, name) + service_item.add_from_image(filename, name, background) return True def onResetClick(self): diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 4ca23aeb0..55e968360 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -121,6 +121,9 @@ class SongUsagePlugin(Plugin): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_started'), self.onReceiveSongUsage) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'print_service_started'), + self.onReceiveSongUsage) self.songUsageActive = QtCore.QSettings().value( self.settingsSection + u'/active', QtCore.QVariant(False)).toBool() From cc1e174d6246a56eed19944bbe0c1ede43fca4ae Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 20 Aug 2011 14:21:25 +0100 Subject: [PATCH 02/22] Updates --- openlp/core/lib/imagemanager.py | 16 ++++++++++++++++ openlp/core/ui/themewizard.py | 3 --- openlp/plugins/images/imageplugin.py | 12 +++++++++++- openlp/plugins/images/lib/mediaitem.py | 4 ++-- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index a4a60b2f4..3de1ff532 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -173,6 +173,22 @@ class ImageManager(QtCore.QObject): image.image_bytes = None self._conversion_queue.put((image.priority, image)) + def update_images(self, background): + """ + Screen has changed size so rebuild the cache to new size. + """ + log.debug(u'update_images') + # Mark the images as dirty for a rebuild by setting the image and byte + # stream to None. + self._conversion_queue = PriorityQueue() + for key, image in self._cache.iteritems(): + if image.source == u'images': + image.background = background + image.priority = Priority.Normal + image.image = None + image.image_bytes = None + self._conversion_queue.put((image.priority, image)) + def config_updated(self): """ Flush the queue to updated any data to update diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 805ce876b..12fc70760 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -64,7 +64,6 @@ class Ui_ThemeWizard(object): self.backgroundStack.setObjectName(u'BackgroundStack') self.colorWidget = QtGui.QWidget(self.backgroundPage) self.colorWidget.setObjectName(u'ColorWidget') - self.colorLayout = QtGui.QFormLayout(self.colorWidget) self.colorLayout.setMargin(0) self.colorLayout.setObjectName(u'ColorLayout') @@ -74,7 +73,6 @@ class Ui_ThemeWizard(object): self.colorButton.setObjectName(u'ColorButton') self.colorLayout.addRow(self.colorLabel, self.colorButton) self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer) - self.backgroundStack.addWidget(self.colorWidget) self.gradientWidget = QtGui.QWidget(self.backgroundPage) self.gradientWidget.setObjectName(u'GradientWidget') @@ -102,7 +100,6 @@ class Ui_ThemeWizard(object): self.gradientComboBox) self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer) self.backgroundStack.addWidget(self.gradientWidget) - self.imageWidget = QtGui.QWidget(self.backgroundPage) self.imageWidget.setObjectName(u'ImageWidget') self.imageLayout = QtGui.QFormLayout(self.imageWidget) diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index aeeee5c5d..1d1ef46ee 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -25,9 +25,12 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +from PyQt4 import QtCore, QtGui + import logging -from openlp.core.lib import Plugin, StringContent, build_icon, translate +from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ + Receiver from openlp.plugins.images.lib import ImageMediaItem, ImageTab log = logging.getLogger(__name__) @@ -41,6 +44,8 @@ class ImagePlugin(Plugin): self.weight = -7 self.icon_path = u':/plugins/plugin_images.png' self.icon = build_icon(self.icon_path) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'image_updated'), self.image_updated) def about(self): about_text = translate('ImagePlugin', 'Image Plugin' @@ -82,3 +87,8 @@ class ImagePlugin(Plugin): 'Add the selected image to the service.') } self.setPluginUiTextStrings(tooltips) + + def image_updated(self): + background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + + u'/background color', QtCore.QVariant(u'#000000'))) + self.liveController.imageManager.update_images(background) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index d88cf47e7..d00b8c9f0 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -140,8 +140,8 @@ class ImageMediaItem(MediaManagerItem): self.plugin.formparent.finishedProgressBar() def generateSlideData(self, service_item, item=None, xmlVersion=False): - background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + - u'/background color', QtCore.QVariant(u'#000000'))) + background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + + u'/background color', QtCore.QVariant(u'#000000'))) if item: items = [item] else: From 3c17af592dc75940b367e93d693087ef1c453a71 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 20 Aug 2011 16:02:57 +0100 Subject: [PATCH 03/22] Fix autoupdates --- openlp/core/lib/imagemanager.py | 8 ++++---- openlp/core/ui/themeform.py | 2 +- openlp/core/ui/thememanager.py | 5 +++++ openlp/plugins/images/imageplugin.py | 7 ++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 3de1ff532..87501602e 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -154,7 +154,7 @@ class ImageManager(QtCore.QObject): self._imageThread = ImageThread(self) self._conversion_queue = PriorityQueue() QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'config_updated'), self.config_updated) + QtCore.SIGNAL(u'config_updated'), self.process_updates) def update_display(self): """ @@ -173,7 +173,7 @@ class ImageManager(QtCore.QObject): image.image_bytes = None self._conversion_queue.put((image.priority, image)) - def update_images(self, background): + def update_images(self, image_type, background): """ Screen has changed size so rebuild the cache to new size. """ @@ -182,14 +182,14 @@ class ImageManager(QtCore.QObject): # stream to None. self._conversion_queue = PriorityQueue() for key, image in self._cache.iteritems(): - if image.source == u'images': + if image.source == image_type: image.background = background image.priority = Priority.Normal image.image = None image.image_bytes = None self._conversion_queue.put((image.priority, image)) - def config_updated(self): + def process_updates(self): """ Flush the queue to updated any data to update """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index b56b68b5b..dc3c23d0d 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -576,7 +576,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): def accept(self): """ - Lets save the them as Finish has been pressed + Lets save the theme as Finish has been pressed """ # Save the theme name self.theme.theme_name = unicode(self.field(u'name').toString()) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 69c229532..40b39b7fd 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -610,6 +610,11 @@ class ThemeManager(QtGui.QWidget): and to trigger the reload of the theme list """ self._writeTheme(theme, imageFrom, imageTo) + if theme.background_type == \ + BackgroundType.to_string(BackgroundType.Image): + self.mainwindow.imageManager.update_images(u'theme', + QtGui.QColor(theme.background_border_color)) + self.mainwindow.imageManager.process_updates() self.loadThemes() def _writeTheme(self, theme, imageFrom, imageTo): diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 1d1ef46ee..4b5a6f3c0 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -89,6 +89,11 @@ class ImagePlugin(Plugin): self.setPluginUiTextStrings(tooltips) def image_updated(self): + """ + Triggered by saving and changing the image border. Sets the images in + image manager to require updates. Actual update is triggered by the + last part of saving the config. + """ background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + u'/background color', QtCore.QVariant(u'#000000'))) - self.liveController.imageManager.update_images(background) + self.liveController.imageManager.update_images(u'image', background) From d660d1d5aea1036a1d638420e194aba12a63c714 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 21 Aug 2011 05:51:03 +0100 Subject: [PATCH 04/22] Add missing file --- openlp/plugins/images/lib/imagetab.py | 99 +++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 openlp/plugins/images/lib/imagetab.py diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py new file mode 100644 index 000000000..640cd4495 --- /dev/null +++ b/openlp/plugins/images/lib/imagetab.py @@ -0,0 +1,99 @@ +# -*- 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, Gerald Britton, Jonathan # +# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # +# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # +# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# 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 # +############################################################################### + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import SettingsTab, translate, Receiver +from openlp.core.lib.ui import UiStrings, create_valign_combo + +class ImageTab(SettingsTab): + """ + ImageTab is the images settings tab in the settings dialog. + """ + def __init__(self, parent, name, visible_title, icon_path): + SettingsTab.__init__(self, parent, name, visible_title, icon_path) + + def setupUi(self): + self.setObjectName(u'ImagesTab') + SettingsTab.setupUi(self) + self.fontGroupBox = QtGui.QGroupBox(self.leftColumn) + self.fontGroupBox.setObjectName(u'FontGroupBox') + self.formLayout = QtGui.QFormLayout(self.fontGroupBox) + self.formLayout.setObjectName(u'FormLayout') + self.colorLayout = QtGui.QHBoxLayout() + self.backgroundColorLabel = QtGui.QLabel(self.fontGroupBox) + self.backgroundColorLabel.setObjectName(u'BackgroundColorLabel') + self.colorLayout.addWidget(self.backgroundColorLabel) + self.backgroundColorButton = QtGui.QPushButton(self.fontGroupBox) + self.backgroundColorButton.setObjectName(u'BackgroundColorButton') + self.colorLayout.addWidget(self.backgroundColorButton) + self.formLayout.addRow(self.colorLayout) + self.informationLabel = QtGui.QLabel(self.fontGroupBox) + self.informationLabel.setObjectName(u'InformationLabel') + self.formLayout.addRow(self.informationLabel) + self.leftLayout.addWidget(self.fontGroupBox) + self.leftLayout.addStretch() + self.rightLayout.addStretch() + # Signals and slots + QtCore.QObject.connect(self.backgroundColorButton, + QtCore.SIGNAL(u'pressed()'), self.onbackgroundColorButtonClicked) + + def retranslateUi(self): + self.fontGroupBox.setTitle( + translate('ImagesPlugin.ImageTab', 'Background Font')) + self.backgroundColorLabel.setText( + translate('ImagesPlugin.ImageTab', 'Background color:')) + self.informationLabel.setText( + translate('ImagesPlugin.ImageTab', 'Provides border where image ' + 'is not the correct dimensions for the screen when resized.')) + + def onbackgroundColorButtonClicked(self): + new_color = QtGui.QColorDialog.getColor( + QtGui.QColor(self.bg_color), self) + if new_color.isValid(): + self.bg_color = new_color.name() + self.backgroundColorButton.setStyleSheet( + u'background-color: %s' % self.bg_color) + + def load(self): + settings = QtCore.QSettings() + settings.beginGroup(self.settingsSection) + self.bg_color = unicode(settings.value( + u'background color', QtCore.QVariant(u'#000000')).toString()) + self.initial_color = self.bg_color + settings.endGroup() + self.backgroundColorButton.setStyleSheet( + u'background-color: %s' % self.bg_color) + + def save(self): + settings = QtCore.QSettings() + settings.beginGroup(self.settingsSection) + settings.setValue(u'background color', QtCore.QVariant(self.bg_color)) + settings.endGroup() + if self.initial_color != self.bg_color: + Receiver.send_message(u'image_updated') + From 21bf34c436c70389a14ad8f2bc14cf148032d557 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 21 Aug 2011 06:33:07 +0100 Subject: [PATCH 05/22] Theme fix --- openlp/core/lib/imagemanager.py | 18 +++++++++++++++++- openlp/core/ui/thememanager.py | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 87501602e..70d4b46ec 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -175,7 +175,7 @@ class ImageManager(QtCore.QObject): def update_images(self, image_type, background): """ - Screen has changed size so rebuild the cache to new size. + Border has changed so update all the images affected. """ log.debug(u'update_images') # Mark the images as dirty for a rebuild by setting the image and byte @@ -189,6 +189,22 @@ class ImageManager(QtCore.QObject): image.image_bytes = None self._conversion_queue.put((image.priority, image)) + def update_image(self, name, image_type, background): + """ + Border has changed so update the image affected. + """ + log.debug(u'update_images') + # Mark the images as dirty for a rebuild by setting the image and byte + # stream to None. + self._conversion_queue = PriorityQueue() + for key, image in self._cache.iteritems(): + if image.source == image_type and image.name == name: + image.background = background + image.priority = Priority.Normal + image.image = None + image.image_bytes = None + self._conversion_queue.put((image.priority, image)) + def process_updates(self): """ Flush the queue to updated any data to update diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 40b39b7fd..fdd0d74f3 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -612,8 +612,8 @@ class ThemeManager(QtGui.QWidget): self._writeTheme(theme, imageFrom, imageTo) if theme.background_type == \ BackgroundType.to_string(BackgroundType.Image): - self.mainwindow.imageManager.update_images(u'theme', - QtGui.QColor(theme.background_border_color)) + self.mainwindow.imageManager.update_image(theme.theme_name, + u'theme', QtGui.QColor(theme.background_border_color)) self.mainwindow.imageManager.process_updates() self.loadThemes() From 62cffbb3b6e1bcf98cb5b4f5ac287670814f2bd5 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 21 Aug 2011 17:13:45 +0100 Subject: [PATCH 06/22] Review fixes and improvements --- openlp/core/lib/imagemanager.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 70d4b46ec..1201d9431 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -166,12 +166,8 @@ class ImageManager(QtCore.QObject): self.height = current_screen[u'size'].height() # Mark the images as dirty for a rebuild by setting the image and byte # stream to None. - self._conversion_queue = PriorityQueue() for key, image in self._cache.iteritems(): - image.priority = Priority.Normal - image.image = None - image.image_bytes = None - self._conversion_queue.put((image.priority, image)) + self.add_to_queue(image) def update_images(self, image_type, background): """ @@ -180,14 +176,10 @@ class ImageManager(QtCore.QObject): log.debug(u'update_images') # Mark the images as dirty for a rebuild by setting the image and byte # stream to None. - self._conversion_queue = PriorityQueue() for key, image in self._cache.iteritems(): if image.source == image_type: image.background = background - image.priority = Priority.Normal - image.image = None - image.image_bytes = None - self._conversion_queue.put((image.priority, image)) + self.add_to_queue(image) def update_image(self, name, image_type, background): """ @@ -196,14 +188,16 @@ class ImageManager(QtCore.QObject): log.debug(u'update_images') # Mark the images as dirty for a rebuild by setting the image and byte # stream to None. - self._conversion_queue = PriorityQueue() for key, image in self._cache.iteritems(): if image.source == image_type and image.name == name: image.background = background - image.priority = Priority.Normal - image.image = None - image.image_bytes = None - self._conversion_queue.put((image.priority, image)) + self.add_to_queue(image) + + def add_to_queue(self, image): + image.priority = Priority.Normal + image.image = None + image.image_bytes = None + self._conversion_queue.put((image.priority, image)) def process_updates(self): """ From 6c55362eee1f5d0455343c6bbb0663068c559878 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 21 Aug 2011 17:59:03 +0100 Subject: [PATCH 07/22] More fixes --- openlp/core/lib/imagemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 1201d9431..2280cc2a6 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -197,7 +197,7 @@ class ImageManager(QtCore.QObject): image.priority = Priority.Normal image.image = None image.image_bytes = None - self._conversion_queue.put((image.priority, image)) + self._conversion_queue.modify_priority(image, image.priority) def process_updates(self): """ From d1f823d86435a842d8e574cbdab7e41f69647d78 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 21 Aug 2011 19:02:58 +0100 Subject: [PATCH 08/22] More fixes 2 --- openlp/core/lib/imagemanager.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 2280cc2a6..4d6c90078 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -167,7 +167,7 @@ class ImageManager(QtCore.QObject): # Mark the images as dirty for a rebuild by setting the image and byte # stream to None. for key, image in self._cache.iteritems(): - self.add_to_queue(image) + self._reset_image(image) def update_images(self, image_type, background): """ @@ -179,7 +179,7 @@ class ImageManager(QtCore.QObject): for key, image in self._cache.iteritems(): if image.source == image_type: image.background = background - self.add_to_queue(image) + self._reset_image(image) def update_image(self, name, image_type, background): """ @@ -191,13 +191,12 @@ class ImageManager(QtCore.QObject): for key, image in self._cache.iteritems(): if image.source == image_type and image.name == name: image.background = background - self.add_to_queue(image) + self._reset_image(image) - def add_to_queue(self, image): - image.priority = Priority.Normal + def _reset_image(self, image): image.image = None image.image_bytes = None - self._conversion_queue.modify_priority(image, image.priority) + self._conversion_queue.modify_priority(image, Priority.Normal) def process_updates(self): """ From 957a86b11e76a3532921d1d288dc6e9f7dadf9b9 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 22 Aug 2011 18:32:18 +0100 Subject: [PATCH 09/22] fexes --- openlp/core/ui/maindisplay.py | 4 ++-- openlp/core/ui/printserviceform.py | 12 +++++++++--- openlp/plugins/images/lib/mediaitem.py | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 9904868ce..77f2e2f7c 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -228,11 +228,11 @@ class MainDisplay(QtGui.QGraphicsView): shrinkItem.setVisible(False) self.setGeometry(self.screen[u'size']) - def directImage(self, name, path): + def directImage(self, name, path, background): """ API for replacement backgrounds so Images are added directly to cache """ - self.imageManager.add_image(name, path) + self.imageManager.add_image(name, path, u'image', background) if hasattr(self, u'serviceItem'): self.override[u'image'] = name self.override[u'theme'] = self.serviceItem.themedata.theme_name diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index f33092061..b9c1cc4a0 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -188,9 +188,6 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): html_data.body, classId=u'serviceTitle') for index, item in enumerate(self.serviceManager.serviceItems): self._addPreviewItem(html_data.body, item[u'service_item'], index) - # Trigger Audit requests - Receiver.send_message(u'print_service_started', - [item[u'service_item']]) # Add the custom service notes: if self.footerTextEdit.toPlainText(): div = self._addElement(u'div', parent=html_data.body, @@ -299,6 +296,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): ``printer`` A *QPrinter* object. """ + self.update_song_usage() self.document.print_(printer) def displaySizeChanged(self, display): @@ -330,12 +328,14 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): """ Copies the display text to the clipboard as plain text """ + self.update_song_usage() self.mainWindow.clipboard.setText(self.document.toPlainText()) def copyHtmlText(self): """ Copies the display text to the clipboard as Html """ + self.update_song_usage() self.mainWindow.clipboard.setText(self.document.toHtml()) def printServiceOrder(self): @@ -400,3 +400,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): settings.setValue(u'print notes', QtCore.QVariant(self.notesCheckBox.isChecked())) settings.endGroup() + + def update_song_usage(self): + for index, item in enumerate(self.serviceManager.serviceItems): + # Trigger Audit requests + Receiver.send_message(u'print_service_started', + [item[u'service_item']]) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index d00b8c9f0..18d5d2a1c 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -208,13 +208,16 @@ class ImageMediaItem(MediaManagerItem): if check_item_selected(self.listView, translate('ImagePlugin.MediaItem', 'You must select an image to replace the background with.')): + background = QtGui.QColor(QtCore.QSettings().value( + self.settingsSection + u'/background color', + QtCore.QVariant(u'#000000'))) item = self.listView.selectedIndexes()[0] bitem = self.listView.item(item.row()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) if os.path.exists(filename): (path, name) = os.path.split(filename) if self.plugin.liveController.display.directImage(name, - filename): + filename, background): self.resetAction.setVisible(True) else: critical_error_message_box(UiStrings().LiveBGError, From 7e572cd0c2dc8fee5b9c457e799ee22c777284cb Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 11:02:59 +0200 Subject: [PATCH 10/22] Database upgrading, revision 1. --- openlp/core/lib/db.py | 55 +++++++++++++++++++++++-- openlp/plugins/songs/lib/db.py | 51 ++++++++++++----------- openlp/plugins/songs/lib/upgrade.py | 63 +++++++++++++++++++++++++++++ openlp/plugins/songs/songsplugin.py | 4 +- 4 files changed, 142 insertions(+), 31 deletions(-) create mode 100644 openlp/plugins/songs/lib/upgrade.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 41b445cd5..93cd293a5 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -31,9 +31,9 @@ import logging import os from PyQt4 import QtCore -from sqlalchemy import create_engine, MetaData +from sqlalchemy import Table, MetaData, Column, types, create_engine from sqlalchemy.exc import InvalidRequestError -from sqlalchemy.orm import scoped_session, sessionmaker +from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.pool import NullPool from openlp.core.utils import AppLocation, delete_file @@ -59,6 +59,42 @@ def init_db(url, auto_flush=True, auto_commit=False): autocommit=auto_commit, bind=engine)) return session, metadata + +def upgrade_db(url, upgrade): + """ + Upgrade a database. + + ``url`` + The url of the database to upgrade. + + ``upgrade`` + The python module that contains the upgrade instructions. + """ + session, metadata = init_db(url) + tables = upgrade.upgrade_setup(metadata) + metadata_table = Table(u'metadata', metadata, + Column(u'key', types.Unicode(64), primary_key=True), + Column(u'value', types.UnicodeText(), default=None) + ) + metadata_table.create(checkfirst=True) + mapper(Metadata, metadata_table) + version_meta = session.query(Metadata).get(u'version') + if version_meta is None: + version_meta = Metadata.populate(key=u'version', value=u'0') + version = 0 + else: + version = int(version_meta.value) + version += 1 + while hasattr(upgrade, u'upgrade_%d' % version): + log.debug(u'Running upgrade_%d', version) + do_upgrade = getattr(upgrade, u'upgrade_%d' % version) + if not do_upgrade(session, metadata, tables): + break + version += 1 + version_meta.value = unicode(version) + session.add(version_meta) + session.commit() + def delete_database(plugin_name, db_file_name=None): """ Remove a database file from the system. @@ -79,6 +115,7 @@ def delete_database(plugin_name, db_file_name=None): AppLocation.get_section_data_path(plugin_name), plugin_name) return delete_file(db_file_path) + class BaseModel(object): """ BaseModel provides a base object with a set of generic functions @@ -94,11 +131,18 @@ class BaseModel(object): return instance +class Metadata(BaseModel): + """ + Provides a class for the metadata table. + """ + pass + + class Manager(object): """ Provide generic object persistence management """ - def __init__(self, plugin_name, init_schema, db_file_name=None): + def __init__(self, plugin_name, init_schema, db_file_name=None, upgrade_schema=None): """ Runs the initialisation process that includes creating the connection to the database and the tables if they don't exist. @@ -109,6 +153,9 @@ class Manager(object): ``init_schema`` The init_schema function for this database + ``upgrade_schema`` + The upgrade_schema function for this database + ``db_file_name`` The file name to use for this database. Defaults to None resulting in the plugin_name being used. @@ -134,6 +181,8 @@ class Manager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() + if upgrade_schema: + upgrade_schema(self.db_url) self.session = init_schema(self.db_url) def save_object(self, object_instance, commit=True): diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index c5c019c3c..f37aed29f 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -32,7 +32,8 @@ the Songs plugin from sqlalchemy import Column, ForeignKey, Table, types from sqlalchemy.orm import mapper, relation -from openlp.core.lib.db import BaseModel, init_db +from openlp.core.lib.db import BaseModel, init_db, upgrade_db +from openlp.plugins.songs.lib import upgrade class Author(BaseModel): """ @@ -70,6 +71,14 @@ class Topic(BaseModel): """ pass +def upgrade_schema(url): + """ + Upgrades the songs database. + + ``url`` + The database to upgrade + """ + upgrade_db(url, upgrade) def init_schema(url): """ @@ -111,10 +120,6 @@ def init_schema(url): * file_name * type - **media_files_songs Table** - * media_file_id - * song_id - **song_books Table** The *song_books* table holds a list of books that a congregation gets their songs from, or old hymnals now no longer used. This table has the @@ -162,7 +167,7 @@ def init_schema(url): # Definition of the "authors" table authors_table = Table(u'authors', metadata, - Column(u'id', types.Integer, primary_key=True), + Column(u'id', types.Integer(), primary_key=True), Column(u'first_name', types.Unicode(128)), Column(u'last_name', types.Unicode(128)), Column(u'display_name', types.Unicode(255), index=True, nullable=False) @@ -170,22 +175,25 @@ def init_schema(url): # Definition of the "media_files" table media_files_table = Table(u'media_files', metadata, - Column(u'id', types.Integer, primary_key=True), + Column(u'id', types.Integer(), primary_key=True), + Column(u'song_id', types.Integer(), ForeignKey(u'songs.id'), + default=None), Column(u'file_name', types.Unicode(255), nullable=False), - Column(u'type', types.Unicode(64), nullable=False, default=u'audio') + Column(u'type', types.Unicode(64), nullable=False, default=u'audio'), + Column(u'weight', types.Integer(), default=0) ) # Definition of the "song_books" table song_books_table = Table(u'song_books', metadata, - Column(u'id', types.Integer, primary_key=True), + Column(u'id', types.Integer(), primary_key=True), Column(u'name', types.Unicode(128), nullable=False), Column(u'publisher', types.Unicode(128)) ) # Definition of the "songs" table songs_table = Table(u'songs', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'song_book_id', types.Integer, + Column(u'id', types.Integer(), primary_key=True), + Column(u'song_book_id', types.Integer(), ForeignKey(u'song_books.id'), default=None), Column(u'title', types.Unicode(255), nullable=False), Column(u'alternate_title', types.Unicode(255)), @@ -202,31 +210,23 @@ def init_schema(url): # Definition of the "topics" table topics_table = Table(u'topics', metadata, - Column(u'id', types.Integer, primary_key=True), + Column(u'id', types.Integer(), primary_key=True), Column(u'name', types.Unicode(128), index=True, nullable=False) ) # Definition of the "authors_songs" table authors_songs_table = Table(u'authors_songs', metadata, - Column(u'author_id', types.Integer, + Column(u'author_id', types.Integer(), ForeignKey(u'authors.id'), primary_key=True), - Column(u'song_id', types.Integer, - ForeignKey(u'songs.id'), primary_key=True) - ) - - # Definition of the "media_files_songs" table - media_files_songs_table = Table(u'media_files_songs', metadata, - Column(u'media_file_id', types.Integer, - ForeignKey(u'media_files.id'), primary_key=True), - Column(u'song_id', types.Integer, + Column(u'song_id', types.Integer(), ForeignKey(u'songs.id'), primary_key=True) ) # Definition of the "songs_topics" table songs_topics_table = Table(u'songs_topics', metadata, - Column(u'song_id', types.Integer, + Column(u'song_id', types.Integer(), ForeignKey(u'songs.id'), primary_key=True), - Column(u'topic_id', types.Integer, + Column(u'topic_id', types.Integer(), ForeignKey(u'topics.id'), primary_key=True) ) @@ -238,8 +238,7 @@ def init_schema(url): 'authors': relation(Author, backref='songs', secondary=authors_songs_table, lazy=False), 'book': relation(Book, backref='songs'), - 'media_files': relation(MediaFile, backref='songs', - secondary=media_files_songs_table), + 'media_files': relation(MediaFile, backref='songs'), 'topics': relation(Topic, backref='songs', secondary=songs_topics_table) }) diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py new file mode 100644 index 000000000..09b7cc2e0 --- /dev/null +++ b/openlp/plugins/songs/lib/upgrade.py @@ -0,0 +1,63 @@ +# -*- 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, Gerald Britton, Jonathan # +# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # +# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # +# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# 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 # +############################################################################### +""" +The :mod:`upgrade` module provides a way for the database and schema that is the backend for +the Songs plugin +""" + +from sqlalchemy import Column, ForeignKey, Table, types +from migrate import changeset +from migrate.changeset.constraint import ForeignKeyConstraint + +def upgrade_setup(metadata): + """ + Set up the latest revision all tables, with reflection, needed for the + upgrade process. If you want to drop a table, you need to remove it from + here, and add it to your upgrade function. + """ + tables = { + u'authors': Table(u'authors', metadata, autoload=True), + u'media_files': Table(u'media_files', metadata, autoload=True), + u'song_books': Table(u'song_books', metadata, autoload=True), + u'songs': Table(u'songs', metadata, autoload=True), + u'topics': Table(u'topics', metadata, autoload=True), + u'authors_songs': Table(u'authors_songs', metadata, autoload=True), + u'songs_topics': Table(u'songs_topics', metadata, autoload=True) + } + return tables + + +def upgrade_1(session, metadata, tables): + Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) + Column(u'song_id', types.Integer(), default=None)\ + .create(table=tables[u'media_files'], populate_default=True) + Column(u'weight', types.Integer(), default=0)\ + .create(table=tables[u'media_files'], populate_default=True) + if metadata.bind.url.get_dialect().name != 'sqlite': + ForeignKeyConstraint([u'song_id'], [u'songs.id'], + table=tables[u'media_files']).create() + return True \ No newline at end of file diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 8a773be90..9fd113186 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -37,7 +37,7 @@ from openlp.core.lib.db import Manager from openlp.core.lib.ui import UiStrings, base_action, icon_action from openlp.core.utils.actions import ActionList from openlp.plugins.songs.lib import clean_song, SongMediaItem, SongsTab -from openlp.plugins.songs.lib.db import init_schema, Song +from openlp.plugins.songs.lib.db import init_schema, upgrade_schema, Song from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.olpimport import OpenLPSongImport @@ -58,8 +58,8 @@ class SongsPlugin(Plugin): Create and set up the Songs plugin. """ Plugin.__init__(self, u'songs', plugin_helpers, SongMediaItem, SongsTab) + self.manager = Manager(u'songs', init_schema, upgrade_schema=upgrade_schema) self.weight = -10 - self.manager = Manager(u'songs', init_schema) self.icon_path = u':/plugins/plugin_songs.png' self.icon = build_icon(self.icon_path) From 923261c59c90bd54d1da72f6656612a31147ae87 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 11:22:48 +0200 Subject: [PATCH 11/22] Even better, got rid of 'upgrade_schema' function which is not really needed. --- openlp/core/lib/db.py | 7 ++++--- openlp/plugins/songs/lib/db.py | 12 +----------- openlp/plugins/songs/songsplugin.py | 7 ++++--- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 93cd293a5..fab20d36f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -142,7 +142,8 @@ class Manager(object): """ Provide generic object persistence management """ - def __init__(self, plugin_name, init_schema, db_file_name=None, upgrade_schema=None): + def __init__(self, plugin_name, init_schema, db_file_name=None, + upgrade_mod=None): """ Runs the initialisation process that includes creating the connection to the database and the tables if they don't exist. @@ -181,8 +182,8 @@ class Manager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() - if upgrade_schema: - upgrade_schema(self.db_url) + if upgrade_mod: + upgrade_db(self.db_url, upgrade_mod) self.session = init_schema(self.db_url) def save_object(self, object_instance, commit=True): diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index f37aed29f..bee64b3ba 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -32,8 +32,7 @@ the Songs plugin from sqlalchemy import Column, ForeignKey, Table, types from sqlalchemy.orm import mapper, relation -from openlp.core.lib.db import BaseModel, init_db, upgrade_db -from openlp.plugins.songs.lib import upgrade +from openlp.core.lib.db import BaseModel, init_db class Author(BaseModel): """ @@ -71,15 +70,6 @@ class Topic(BaseModel): """ pass -def upgrade_schema(url): - """ - Upgrades the songs database. - - ``url`` - The database to upgrade - """ - upgrade_db(url, upgrade) - def init_schema(url): """ Setup the songs database connection and initialise the database schema. diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 9fd113186..f2bf36790 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -36,8 +36,9 @@ from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ from openlp.core.lib.db import Manager from openlp.core.lib.ui import UiStrings, base_action, icon_action from openlp.core.utils.actions import ActionList -from openlp.plugins.songs.lib import clean_song, SongMediaItem, SongsTab -from openlp.plugins.songs.lib.db import init_schema, upgrade_schema, Song +from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \ + SongsTab +from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.olpimport import OpenLPSongImport @@ -58,7 +59,7 @@ class SongsPlugin(Plugin): Create and set up the Songs plugin. """ Plugin.__init__(self, u'songs', plugin_helpers, SongMediaItem, SongsTab) - self.manager = Manager(u'songs', init_schema, upgrade_schema=upgrade_schema) + self.manager = Manager(u'songs', init_schema, upgrade_mod=upgrade) self.weight = -10 self.icon_path = u':/plugins/plugin_songs.png' self.icon = build_icon(self.icon_path) From ddf148449d253e7fdf541e7fedb69b657d793349 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 13:47:07 +0200 Subject: [PATCH 12/22] Now with exception handling. --- openlp/core/lib/db.py | 13 ++++++++----- openlp/plugins/songs/lib/upgrade.py | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index fab20d36f..12f35ad1f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -32,7 +32,7 @@ import os from PyQt4 import QtCore from sqlalchemy import Table, MetaData, Column, types, create_engine -from sqlalchemy.exc import InvalidRequestError +from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.pool import NullPool @@ -87,11 +87,14 @@ def upgrade_db(url, upgrade): version += 1 while hasattr(upgrade, u'upgrade_%d' % version): log.debug(u'Running upgrade_%d', version) - do_upgrade = getattr(upgrade, u'upgrade_%d' % version) - if not do_upgrade(session, metadata, tables): + try: + getattr(upgrade, u'upgrade_%d' % version)(session, metadata, tables) + version += 1 + version_meta.value = unicode(version) + except SQLAlchemyError, DBAPIError: + log.exception(u'Could not run database upgrade script "upgrade_%s"'\ + ', upgrade process has been halted.', version) break - version += 1 - version_meta.value = unicode(version) session.add(version_meta) session.commit() diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index 09b7cc2e0..278b6fe86 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -60,4 +60,4 @@ def upgrade_1(session, metadata, tables): if metadata.bind.url.get_dialect().name != 'sqlite': ForeignKeyConstraint([u'song_id'], [u'songs.id'], table=tables[u'media_files']).create() - return True \ No newline at end of file + From ff7a7d734a76152ca6751ce7979e17254762cd32 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 17:24:47 +0200 Subject: [PATCH 13/22] Added migrate dependency to deb package. --- resources/debian/debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/debian/debian/control b/resources/debian/debian/control index 220b500d2..423d81df0 100644 --- a/resources/debian/debian/control +++ b/resources/debian/debian/control @@ -11,7 +11,7 @@ Package: openlp Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-qt4, python-qt4-phonon, python-sqlalchemy, python-chardet, python-beautifulsoup, - python-lxml, python-sqlite, python-enchant + python-lxml, python-sqlite, python-enchant, python-migrate Conflicts: python-openlp Description: Church lyrics projection application OpenLP is free church presentation software, or lyrics projection software, From 803adc92c0b45d474975a73d5f3f5da26a4ee463 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 25 Aug 2011 19:33:25 +0100 Subject: [PATCH 14/22] Fixes --- openlp/core/ui/themewizard.py | 2 +- openlp/plugins/images/lib/imagetab.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 12fc70760..6001c83d6 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -449,7 +449,7 @@ class Ui_ThemeWizard(object): self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom, translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) self.imageColorLabel.setText( - translate(u'OpenLP.ThemeWizard', 'Border color:')) + translate(u'OpenLP.ThemeWizard', 'Background color:')) self.imageLabel.setText(u'%s:' % UiStrings().Image) self.mainAreaPage.setTitle( translate('OpenLP.ThemeWizard', 'Main Area Font Details')) diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index 640cd4495..05e998d81 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -57,6 +57,8 @@ class ImageTab(SettingsTab): self.formLayout.addRow(self.informationLabel) self.leftLayout.addWidget(self.fontGroupBox) self.leftLayout.addStretch() + self.rightColumn.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) self.rightLayout.addStretch() # Signals and slots QtCore.QObject.connect(self.backgroundColorButton, @@ -64,9 +66,9 @@ class ImageTab(SettingsTab): def retranslateUi(self): self.fontGroupBox.setTitle( - translate('ImagesPlugin.ImageTab', 'Background Font')) + translate('ImagesPlugin.ImageTab', 'Background Color')) self.backgroundColorLabel.setText( - translate('ImagesPlugin.ImageTab', 'Background color:')) + translate('ImagesPlugin.ImageTab', 'Default Color:')) self.informationLabel.setText( translate('ImagesPlugin.ImageTab', 'Provides border where image ' 'is not the correct dimensions for the screen when resized.')) From 5f6b315c4af9c9d0ceb492b4237d86df8c7654ff Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 25 Aug 2011 20:52:07 +0100 Subject: [PATCH 15/22] fix trace --- openlp/plugins/custom/lib/mediaitem.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 667434a8b..693e1ef8d 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -217,8 +217,7 @@ class CustomMediaItem(MediaManagerItem): for item in self.listView.selectedIndexes()] for id in id_list: self.plugin.manager.delete_object(CustomSlide, id) - for row in row_list: - self.listView.takeItem(row) + self.onSearchTextButtonClick() def onFocus(self): self.searchTextEdit.setFocus() From bcf9b174ff12cf9c4223c1964bb19ad7033066ee Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 22:02:55 +0200 Subject: [PATCH 16/22] Fixed a bug where the version number saved to the database was incorrect. Added the ability to throw an error message and not load the database if the db is too new or incorrect. --- openlp/core/lib/db.py | 29 ++++++++++++++++++++++++++--- openlp/plugins/songs/lib/upgrade.py | 2 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 12f35ad1f..fb8a38b1f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -36,6 +36,8 @@ from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.pool import NullPool +from openlp.core.lib import translate +from openlp.core.lib.ui import critical_error_message_box from openlp.core.utils import AppLocation, delete_file log = logging.getLogger(__name__) @@ -84,19 +86,22 @@ def upgrade_db(url, upgrade): version = 0 else: version = int(version_meta.value) + if version > upgrade.__version__: + return version, upgrade.__version__ version += 1 while hasattr(upgrade, u'upgrade_%d' % version): log.debug(u'Running upgrade_%d', version) try: getattr(upgrade, u'upgrade_%d' % version)(session, metadata, tables) - version += 1 version_meta.value = unicode(version) except SQLAlchemyError, DBAPIError: log.exception(u'Could not run database upgrade script "upgrade_%s"'\ ', upgrade process has been halted.', version) break + version += 1 session.add(version_meta) session.commit() + return int(version_meta.value), upgrade.__version__ def delete_database(plugin_name, db_file_name=None): """ @@ -186,8 +191,26 @@ class Manager(object): unicode(settings.value(u'db database').toString())) settings.endGroup() if upgrade_mod: - upgrade_db(self.db_url, upgrade_mod) - self.session = init_schema(self.db_url) + db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod) + if db_ver > up_ver: + critical_error_message_box( + translate('OpenLP.Manager', 'Database Error'), + unicode(translate('OpenLP.Manager', 'The database being ' + 'loaded was created in a more recent version of ' + 'OpenLP. The database is version %d, while OpenLP ' + 'expects version %d. The database will not be loaded.' + '\n\nDatabase: %s')) % \ + (db_ver, up_ver, self.db_url) + ) + return + try: + self.session = init_schema(self.db_url) + except: + critical_error_message_box( + translate('OpenLP.Manager', 'Database Error'), + unicode(translate('OpenLP.Manager', 'OpenLP cannot load your ' + 'database.\n\nDatabase: %s')) % self.db_url + ) def save_object(self, object_instance, commit=True): """ diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index 278b6fe86..56b04bb01 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -33,6 +33,8 @@ from sqlalchemy import Column, ForeignKey, Table, types from migrate import changeset from migrate.changeset.constraint import ForeignKeyConstraint +__version__ = 1 + def upgrade_setup(metadata): """ Set up the latest revision all tables, with reflection, needed for the From 4b1ce7102e48e2d71bc63a49f7f928903517cbb9 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 25 Aug 2011 22:14:02 +0200 Subject: [PATCH 17/22] A few more tweaks as requested by Andreas. --- openlp/plugins/songs/lib/upgrade.py | 12 ++++++++++++ scripts/check_dependencies.py | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index 56b04bb01..e0f2668d9 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -54,12 +54,24 @@ def upgrade_setup(metadata): def upgrade_1(session, metadata, tables): + """ + Version 1 upgrade. + + This upgrade removes the many-to-many relationship between songs and + media_files and replaces it with a one-to-many, which is far more + representative of the real relationship between the two entities. + + In order to facilitate this one-to-many relationship, a song_id column is + added to the media_files table, and a weight column so that the media + files can be ordered. + """ Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) Column(u'song_id', types.Integer(), default=None)\ .create(table=tables[u'media_files'], populate_default=True) Column(u'weight', types.Integer(), default=0)\ .create(table=tables[u'media_files'], populate_default=True) if metadata.bind.url.get_dialect().name != 'sqlite': + # SQLite doesn't support ALTER TABLE ADD CONSTRAINT ForeignKeyConstraint([u'song_id'], [u'songs.id'], table=tables[u'media_files']).create() diff --git a/scripts/check_dependencies.py b/scripts/check_dependencies.py index 7048ceeab..5f2e4c148 100755 --- a/scripts/check_dependencies.py +++ b/scripts/check_dependencies.py @@ -46,14 +46,14 @@ VERS = { 'sqlalchemy': '0.5', # pyenchant 1.6 required on Windows 'enchant': '1.6' if is_win else '1.3' - } +} # pywin32 WIN32_MODULES = [ 'win32com', 'win32ui', 'pywintypes', - ] +] MODULES = [ 'PyQt4', @@ -72,7 +72,8 @@ MODULES = [ 'enchant', 'BeautifulSoup', 'mako', - ] + 'migrate', +] OPTIONAL_MODULES = [ From 869bc9bb209190d3920e112e89e284c63a93964c Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 26 Aug 2011 09:21:27 +0100 Subject: [PATCH 18/22] Fix field name --- openlp/plugins/images/lib/imagetab.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index 05e998d81..98fbd203f 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -40,22 +40,22 @@ class ImageTab(SettingsTab): def setupUi(self): self.setObjectName(u'ImagesTab') SettingsTab.setupUi(self) - self.fontGroupBox = QtGui.QGroupBox(self.leftColumn) - self.fontGroupBox.setObjectName(u'FontGroupBox') - self.formLayout = QtGui.QFormLayout(self.fontGroupBox) + self.bgColorGroupBox = QtGui.QGroupBox(self.leftColumn) + self.bgColorGroupBox.setObjectName(u'FontGroupBox') + self.formLayout = QtGui.QFormLayout(self.bgColorGroupBox) self.formLayout.setObjectName(u'FormLayout') self.colorLayout = QtGui.QHBoxLayout() - self.backgroundColorLabel = QtGui.QLabel(self.fontGroupBox) + self.backgroundColorLabel = QtGui.QLabel(self.bgColorGroupBox) self.backgroundColorLabel.setObjectName(u'BackgroundColorLabel') self.colorLayout.addWidget(self.backgroundColorLabel) - self.backgroundColorButton = QtGui.QPushButton(self.fontGroupBox) + self.backgroundColorButton = QtGui.QPushButton(self.bgColorGroupBox) self.backgroundColorButton.setObjectName(u'BackgroundColorButton') self.colorLayout.addWidget(self.backgroundColorButton) self.formLayout.addRow(self.colorLayout) - self.informationLabel = QtGui.QLabel(self.fontGroupBox) + self.informationLabel = QtGui.QLabel(self.bgColorGroupBox) self.informationLabel.setObjectName(u'InformationLabel') self.formLayout.addRow(self.informationLabel) - self.leftLayout.addWidget(self.fontGroupBox) + self.leftLayout.addWidget(self.bgColorGroupBox) self.leftLayout.addStretch() self.rightColumn.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) @@ -65,7 +65,7 @@ class ImageTab(SettingsTab): QtCore.SIGNAL(u'pressed()'), self.onbackgroundColorButtonClicked) def retranslateUi(self): - self.fontGroupBox.setTitle( + self.bgColorGroupBox.setTitle( translate('ImagesPlugin.ImageTab', 'Background Color')) self.backgroundColorLabel.setText( translate('ImagesPlugin.ImageTab', 'Default Color:')) From 61feddd34e81947424a3576dd1cc90351bc2c5cc Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 26 Aug 2011 11:21:47 +0100 Subject: [PATCH 19/22] Fix method call --- openlp/core/ui/printserviceform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index b9c1cc4a0..c08b6293e 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -296,7 +296,6 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): ``printer`` A *QPrinter* object. """ - self.update_song_usage() self.document.print_(printer) def displaySizeChanged(self, display): @@ -344,6 +343,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): """ if not self.printDialog.exec_(): return + self.update_song_usage() # Print the document. self.document.print_(self.printer) From 1adac78588f63aea8cf110c54ce6fed8415c92a5 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 26 Aug 2011 13:02:06 +0100 Subject: [PATCH 20/22] Add date fields to songs --- openlp/plugins/songs/lib/db.py | 5 ++++- openlp/plugins/songs/lib/upgrade.py | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index bee64b3ba..13ce24266 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -31,6 +31,7 @@ the Songs plugin from sqlalchemy import Column, ForeignKey, Table, types from sqlalchemy.orm import mapper, relation +from sqlalchemy.sql.expression import func from openlp.core.lib.db import BaseModel, init_db @@ -195,7 +196,9 @@ def init_schema(url): Column(u'song_number', types.Unicode(64)), Column(u'theme_name', types.Unicode(128)), Column(u'search_title', types.Unicode(255), index=True, nullable=False), - 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'last_modified', types.DateTime(), onupdate=func.now()) ) # Definition of the "topics" table diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index e0f2668d9..fae3400c2 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -25,15 +25,16 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`upgrade` module provides a way for the database and schema that is the backend for -the Songs plugin +The :mod:`upgrade` module provides a way for the database and schema that is the +backend for the Songs plugin """ from sqlalchemy import Column, ForeignKey, Table, types +from sqlalchemy.sql.expression import func from migrate import changeset from migrate.changeset.constraint import ForeignKeyConstraint -__version__ = 1 +__version__ = 2 def upgrade_setup(metadata): """ @@ -57,7 +58,7 @@ def upgrade_1(session, metadata, tables): """ Version 1 upgrade. - This upgrade removes the many-to-many relationship between songs and + This upgrade removes the many-to-many relationship between songs and media_files and replaces it with a one-to-many, which is far more representative of the real relationship between the two entities. @@ -75,3 +76,13 @@ def upgrade_1(session, metadata, tables): ForeignKeyConstraint([u'song_id'], [u'songs.id'], table=tables[u'media_files']).create() +def upgrade_2(session, metadata, tables): + """ + Version 2 upgrade. + + This upgrade adds a create_date and last_modified date to the songs table + """ + Column(u'create_date', types.DateTime(), default=func.now())\ + .create(table=tables[u'songs'], populate_default=True) + Column(u'last_modified', types.DateTime(), default=func.now())\ + .create(table=tables[u'songs'], populate_default=True) From 8f2b2381eea910d3c58f0a1ed8aa367e89bd65df Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 26 Aug 2011 14:14:21 +0200 Subject: [PATCH 21/22] Fixed a missing dependency (which already exists on the build server). --- resources/debian/debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/debian/debian/control b/resources/debian/debian/control index 423d81df0..a1c2298e9 100644 --- a/resources/debian/debian/control +++ b/resources/debian/debian/control @@ -11,7 +11,7 @@ Package: openlp Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-qt4, python-qt4-phonon, python-sqlalchemy, python-chardet, python-beautifulsoup, - python-lxml, python-sqlite, python-enchant, python-migrate + python-lxml, python-sqlite, python-enchant, python-mako, python-migrate Conflicts: python-openlp Description: Church lyrics projection application OpenLP is free church presentation software, or lyrics projection software, From 4f0c7716bc2c53067de6722716a05f17bbc0981d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 26 Aug 2011 14:13:32 +0100 Subject: [PATCH 22/22] Fix default value --- openlp/plugins/songs/lib/db.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 13ce24266..5bfa0c830 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -198,7 +198,8 @@ def init_schema(url): Column(u'search_title', types.Unicode(255), index=True, nullable=False), Column(u'search_lyrics', types.UnicodeText, nullable=False), Column(u'create_date', types.DateTime(), default=func.now()), - Column(u'last_modified', types.DateTime(), onupdate=func.now()) + Column(u'last_modified', types.DateTime(), default=func.now(), + onupdate=func.now()) ) # Definition of the "topics" table