← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/bug-772523 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/bug-772523 into lp:openlp.

Requested reviews:
  Andreas Preikschat (googol)
  Raoul Snyman (raoul-snyman)
Related bugs:
  Bug #772523 in OpenLP: ""Update service from song edit" does work "too much""
  https://bugs.launchpad.net/openlp/+bug/772523

For more details, see:
https://code.launchpad.net/~trb143/openlp/bug-772523/+merge/85224

This patch changes your song database so back it up!

When a service is imported at present and we do not wish to save the songs we do not.  This prevents the user from editing songs.
This change adds a "temporary" flag on the song database to allow those songs to be save and edited bit not via the plugin as the search will not show them.
On exit the songs will be deleted.

The code works until a service is loaded and then you get sqlalchemy errors. 
I have no idea what is wrong but some help would be appreciated.

Amended code to add songs as per my email.

The code does set a correct value on existing databases.


-- 
https://code.launchpad.net/~trb143/openlp/bug-772523/+merge/85224
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/db.py'
--- openlp/core/lib/db.py	2011-12-03 12:51:40 +0000
+++ openlp/core/lib/db.py	2011-12-10 14:43:26 +0000
@@ -358,10 +358,17 @@
 
     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``
             The type of object to delete
+
+        ``filter_clause``
+            The filter governing selection of objects to return. Defaults to
+            None.
         """
         try:
             query = self.session.query(object_class)

=== modified file 'openlp/core/lib/eventreceiver.py'
--- openlp/core/lib/eventreceiver.py	2011-10-22 11:28:47 +0000
+++ openlp/core/lib/eventreceiver.py	2011-12-10 14:43:26 +0000
@@ -115,8 +115,12 @@
     ``slidecontroller_live_stop_loop``
         Stop the loop on the main display.
 
+
     **Servicemanager related signals**
 
+    ``servicemanager_new_service``
+        A new service is being loaded or created.
+
     ``servicemanager_previous_item``
         Display the previous item in the service.
 

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2011-11-13 08:57:29 +0000
+++ openlp/core/lib/serviceitem.py	2011-12-10 14:43:26 +0000
@@ -119,6 +119,7 @@
         self.image_border = u'#000000'
         self.background_audio = []
         self.theme_overwritten = False
+        self.temporary_edit = False
         self._new_item()
 
     def _new_item(self):
@@ -365,6 +366,7 @@
         """
         self._uuid = other._uuid
         self.notes = other.notes
+        self.temporary_edit = other.temporary_edit
         # Copy theme over if present.
         if other.theme is not None:
             self.theme = other.theme

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2011-12-02 20:17:57 +0000
+++ openlp/core/ui/maindisplay.py	2011-12-10 14:43:26 +0000
@@ -45,7 +45,7 @@
 
 class Display(QtGui.QGraphicsView):
     """
-    This is a general display screen class. Here the general display settings 
+    This is a general display screen class. Here the general display settings
    will done. It will be used as specialized classes by Main Display and
    Preview display.
     """
@@ -66,7 +66,7 @@
         """
         Set up and build the screen base
         """
-        log.debug(u'Start Display base setup (live = %s)' % self.isLive)        
+        log.debug(u'Start Display base setup (live = %s)' % self.isLive)
         self.setGeometry(self.screen[u'size'])
         log.debug(u'Setup webView')
         self.webView = QtWebKit.QWebView(self)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2011-12-02 20:17:57 +0000
+++ openlp/core/ui/servicemanager.py	2011-12-10 14:43:26 +0000
@@ -37,7 +37,7 @@
 from PyQt4 import QtCore, QtGui
 
 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.ui import UiStrings, critical_error_message_box, \
     context_menu_action, context_menu_separator, find_and_set_in_combo_box
@@ -465,6 +465,7 @@
         self.setModified(False)
         QtCore.QSettings(). \
             setValue(u'servicemanager/last file',QtCore.QVariant(u''))
+        Receiver.send_message(u'servicemanager_new_service')
 
     def saveFile(self):
         """
@@ -670,6 +671,7 @@
                     # if the item has been processed
                     if serviceItem._uuid == self.loadItem_uuid:
                         serviceItem.edit_id = int(self.loadItem_editId)
+                        serviceItem.temporary_edit = self.loadItem_temporary
                     self.addServiceItem(serviceItem, repaint=False)
                 delete_file(p_file)
                 self.setFileName(fileName)
@@ -999,6 +1001,17 @@
                     painter.drawImage(0, 0, overlay)
                     painter.end()
                     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:
                     treewidgetitem.setIcon(0, serviceitem.iconic_representation)
             else:
@@ -1006,6 +1019,11 @@
                     build_icon(u':/general/general_delete.png'))
             treewidgetitem.setText(0, serviceitem.get_display_title())
             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:
                 tips.append(u'<strong>%s:</strong> <em>%s</em>' %
                     (unicode(translate('OpenLP.ServiceManager', 'Slide theme')),
@@ -1127,8 +1145,9 @@
         Triggered from plugins to update service items.
         Save the values as they will be used as part of the service load
         """
-        editId, self.loadItem_uuid = message.split(u':')
+        editId, self.loadItem_uuid, temporary = message.split(u':')
         self.loadItem_editId = int(editId)
+        self.loadItem_temporary = str_to_bool(temporary)
 
     def replaceServiceItem(self, newItem):
         """

=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py	2011-08-26 15:48:58 +0000
+++ openlp/plugins/songs/forms/songexportform.py	2011-12-10 14:43:26 +0000
@@ -252,6 +252,9 @@
         songs = self.plugin.manager.get_all_objects(Song)
         songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower())
         for song in songs:
+            # No need to export temporary songs.
+            if song.temporary:
+                continue
             authors = u', '.join([author.display_name
                 for author in song.authors])
             title = u'%s (%s)' % (unicode(song.title), authors)

=== modified file 'openlp/plugins/songs/lib/db.py'
--- openlp/plugins/songs/lib/db.py	2011-08-26 23:04:54 +0000
+++ openlp/plugins/songs/lib/db.py	2011-12-10 14:43:26 +0000
@@ -199,7 +199,8 @@
         Column(u'search_lyrics', types.UnicodeText, nullable=False),
         Column(u'create_date', 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

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2011-11-24 22:34:27 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2011-12-10 14:43:26 +0000
@@ -270,6 +270,9 @@
         searchresults.sort(
             cmp=locale.strcoll, key=lambda song: song.title.lower())
         for song in searchresults:
+            # Do not display temporary songs
+            if song.temporary:
+                continue
             author_list = [author.display_name for author in song.authors]
             song_title = unicode(song.title)
             song_detail = u'%s (%s)' % (song_title, u', '.join(author_list))
@@ -286,6 +289,9 @@
         self.listView.clear()
         for author in searchresults:
             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_name = QtGui.QListWidgetItem(song_detail)
                 song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
@@ -534,6 +540,7 @@
                 Song.search_title.asc())
         editId = 0
         add_song = True
+        temporary = False
         if search_results:
             for song in search_results:
                 author_list = item.data_string[u'authors']
@@ -559,13 +566,18 @@
                 self._updateBackgroundAudio(song, item)
             editId = song.id
             self.onSearchTextButtonClick()
-        else:
+        elif add_song and not self.addSongFromService:
             # 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.
         if editId:
             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):
         """

=== modified file 'openlp/plugins/songs/lib/upgrade.py'
--- openlp/plugins/songs/lib/upgrade.py	2011-12-02 20:17:57 +0000
+++ openlp/plugins/songs/lib/upgrade.py	2011-12-10 14:43:26 +0000
@@ -33,7 +33,9 @@
 from sqlalchemy.sql.expression import func
 from migrate.changeset.constraint import ForeignKeyConstraint
 
-__version__ = 2
+from openlp.plugins.songs.lib.db import Song
+
+__version__ = 3
 
 def upgrade_setup(metadata):
     """
@@ -86,3 +88,12 @@
     Column(u'last_modified', types.DateTime(), default=func.now())\
         .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'])
+

=== modified file 'openlp/plugins/songs/lib/xml.py'
--- openlp/plugins/songs/lib/xml.py	2011-10-09 19:51:44 +0000
+++ openlp/plugins/songs/lib/xml.py	2011-12-10 14:43:26 +0000
@@ -346,7 +346,7 @@
                     lines_element.set(u'break', u'optional')
         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
         we also export XML from external sources (e. g. OpenLyrics import), we
@@ -355,9 +355,9 @@
         ``xml``
             The XML to parse (unicode).
 
-        ``parse_and_not_save``
-            Switch to skip processing the whole song and to prevent storing the
-            songs to the database. Defaults to ``False``.
+        ``parse_and_temporary_save``
+            Switch to skip processing the whole song and storing the songs in
+            the database with a temporary flag. Defaults to ``False``.
         """
         # No xml get out of here.
         if not xml:
@@ -371,14 +371,13 @@
             return None
         # Formatting tags are new in OpenLyrics 0.8
         if float(song_xml.get(u'version')) > 0.7:
-            self._process_formatting_tags(song_xml, parse_and_not_save)
-        if parse_and_not_save:
-            return
+            self._process_formatting_tags(song_xml, parse_and_temporary_save)
         song = Song()
         # Values will be set when cleaning the song.
         song.search_lyrics = u''
         song.verse_order = u''
         song.search_title = u''
+        song.temporary = parse_and_temporary_save
         self._process_copyright(properties, song)
         self._process_cclinumber(properties, song)
         self._process_titles(properties, song)

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2011-12-03 13:32:19 +0000
+++ openlp/plugins/songs/songsplugin.py	2011-12-10 14:43:26 +0000
@@ -77,6 +77,9 @@
         action_list.add_action(self.songImportItem, UiStrings().Import)
         action_list.add_action(self.songExportItem, UiStrings().Export)
         action_list.add_action(self.toolsReindexItem, UiStrings().Tools)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'servicemanager_new_service'),
+        self.clearTemporarySongs)
 
     def addImportMenuItem(self, import_menu):
         """
@@ -264,6 +267,8 @@
         Time to tidy up on exit
         """
         log.info(u'Songs Finalising')
+        self.clearTemporarySongs()
+        # Clean up files and connections
         self.manager.finalise()
         self.songImportItem.setVisible(False)
         self.songExportItem.setVisible(False)
@@ -273,3 +278,9 @@
         action_list.remove_action(self.songExportItem, UiStrings().Export)
         action_list.remove_action(self.toolsReindexItem, UiStrings().Tools)
         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)


Follow ups