← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/bugfixes1 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/bugfixes1 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  #637547 Editing a song in a loaded service file crashes
  https://bugs.launchpad.net/bugs/637547
  #637886 Replacing live video background with nothing live causes crash
  https://bugs.launchpad.net/bugs/637886
  #642778 enchant.DictNotFoundError: Dictionary for language 'ja_JP' could not be found
  https://bugs.launchpad.net/bugs/642778


Add new features:
- Update Service Song item from Edit in Song plugin (with option)
- Allow editing from Service Manager of songs saved
- Frame work for Adding Songs from Service Manager load (with Option)
-- 
https://code.launchpad.net/~trb143/openlp/bugfixes1/+merge/37786
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/bugfixes1 into lp:openlp.
=== modified file 'openlp/core/lib/eventreceiver.py'
--- openlp/core/lib/eventreceiver.py	2010-09-14 18:18:47 +0000
+++ openlp/core/lib/eventreceiver.py	2010-10-06 20:32:48 +0000
@@ -75,7 +75,7 @@
         Broadcasts that an item has been made live/previewed
 
     ``slidecontroller_{live|preview}_change``
-        Informs the slidecontroller that a slide change has occurred and to 
+        Informs the slidecontroller that a slide change has occurred and to
         update itself
 
     ``slidecontroller_{live|preview}_changed``
@@ -83,7 +83,7 @@
 
     ``slidecontroller_{live|preview}_text_request``
         Request the text for the current item in the controller
-        Returns a slidecontroller_{live|preview}_text_response with an 
+        Returns a slidecontroller_{live|preview}_text_response with an
         array of dictionaries with the tag and verse text
 
     ``slidecontroller_{live|preview}_blank``
@@ -106,23 +106,23 @@
 
     ``servicemanager_set_item``
         Go live on a specific item, by index
-        
+
     ``servicemanager_list_request``
         Request the service list. Responds with servicemanager_list_response
         containing a array of dictionaries
 
     ``maindisplay_blank``
-        Blank the maindisplay window 
+        Blank the maindisplay window
 
     ``maindisplay_hide``
-        Hide the maindisplay window 
+        Hide the maindisplay window
 
     ``maindisplay_show``
-        Return the maindisplay window 
+        Return the maindisplay window
 
     ``maindisplay_active``
         The maindisplay has been made active
-    
+
     ``maindisplay_status_text``
         Changes the bottom status bar text on the maindisplay window
 
@@ -193,9 +193,17 @@
     ``{plugin}_add_service_item``
         Ask the plugin to push the selected items to the service item
 
+    ``{plugin}_service_load``
+        Ask the plugin to process an individual service item after it has been
+        loaded
+
+    ``service_item_update``
+        Passes back to the service manager the service item after it has been
+        processed by the plugin
+
     ``alerts_text``
         Displays an alert message
-    
+
     ``bibles_nobook``
         Attempt to find book resulted in no match
 

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2010-09-27 18:15:55 +0000
+++ openlp/core/lib/mediamanageritem.py	2010-10-06 20:32:48 +0000
@@ -33,7 +33,7 @@
 
 from openlp.core.lib import context_menu_action, context_menu_separator, \
     SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \
-    translate
+    translate, Receiver
 
 log = logging.getLogger(__name__)
 
@@ -94,7 +94,7 @@
         QtGui.QWidget.__init__(self)
         self.parent = parent
         #TODO: plugin should not be the parent in future
-        self.plugin = parent#plugin
+        self.plugin = parent # plugin
         visible_title = self.plugin.getString(StringContent.VisibleName)
         self.title = visible_title[u'title']
         self.settingsSection = self.plugin.name.lower()
@@ -115,6 +115,9 @@
         self.requiredIcons()
         self.setupUi()
         self.retranslateUi()
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
+            self.serviceLoad)
 
     def requiredIcons(self):
         """
@@ -471,8 +474,8 @@
                 translate('OpenLP.MediaManagerItem',
                     'You must select one or more items.'))
         else:
-            #Is it posssible to process multiple list items to generate multiple
-            #service items?
+            # Is it posssible to process multiple list items to generate multiple
+            # service items?
             if self.singleServiceItem or self.remoteTriggered:
                 log.debug(self.plugin.name + u' Add requested')
                 service_item = self.buildServiceItem()
@@ -501,7 +504,7 @@
             log.debug(self.plugin.name + u' Add requested')
             service_item = self.parent.serviceManager.getServiceItem()
             if not service_item:
-                QtGui.QMessageBox.information(self,
+                 QtGui.QMessageBox.information(self,
                     translate('OpenLP.MediaManagerItem',
                         'No Service Item Selected'),
                     translate('OpenLP.MediaManagerItem',
@@ -531,3 +534,11 @@
             return service_item
         else:
             return None
+
+    def serviceLoad(self, message):
+        """
+        Method to add processing when a service has been loaded and
+        individual service items need to be processed by the plugins
+        """
+        pass
+

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2010-09-29 20:39:15 +0000
+++ openlp/core/lib/serviceitem.py	2010-10-06 20:32:48 +0000
@@ -58,6 +58,9 @@
     AllowsLoop = 5
     AllowsAdditions = 6
     NoLineBreaks = 7
+    OnLoadUpdate = 8
+    AddIfNewItem = 9
+
 
 class ServiceItem(object):
     """
@@ -98,6 +101,9 @@
         self.main = None
         self.footer = None
         self.bg_image_bytes = None
+        self._new_item()
+        self.search_string = u''
+        self.data_string = u''
 
     def _new_item(self):
         """
@@ -255,7 +261,9 @@
             u'audit':self.audit,
             u'notes':self.notes,
             u'from_plugin':self.from_plugin,
-            u'capabilities':self.capabilities
+            u'capabilities':self.capabilities,
+            u'search':self.search_string,
+            u'data':self.data_string
         }
         service_data = []
         if self.service_item_type == ServiceItemType.Text:
@@ -293,6 +301,10 @@
         self.notes = header[u'notes']
         self.from_plugin = header[u'from_plugin']
         self.capabilities = header[u'capabilities']
+        # Added later so may not be present in older services.
+        if u'search' in header:
+            self.search_string = header[u'search']
+            self.data_string = header[u'data']
         if self.service_item_type == ServiceItemType.Text:
             for slide in serviceitem[u'serviceitem'][u'data']:
                 self._raw_frames.append(slide)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2010-09-27 18:34:40 +0000
+++ openlp/core/ui/servicemanager.py	2010-10-06 20:32:48 +0000
@@ -223,6 +223,8 @@
             QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'theme_update_global'), self.themeChange)
+        QtCore.QObject.connect(Receiver.get_receiver(),
+            QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
         # Last little bits of setting up
         self.service_theme = unicode(QtCore.QSettings().value(
             self.parent.serviceSettingsSection + u'/service theme',
@@ -711,6 +713,9 @@
                         serviceitem.set_from_service(item, self.servicePath)
                         self.validateItem(serviceitem)
                         self.addServiceItem(serviceitem)
+                        if serviceitem.is_capable(ItemCapabilities.OnLoadUpdate):
+                            Receiver.send_message(u'%s_service_load' %
+                                serviceitem.name.lower(), serviceitem)
                     try:
                         if os.path.isfile(p_file):
                             os.remove(p_file)
@@ -801,7 +806,31 @@
             # does not impact the saved song so True may also be valid
             self.parent.serviceChanged(False, self.serviceName)
 
-    def addServiceItem(self, item, rebuild=False, expand=True, replace=False):
+    def serviceItemUpdate(self, message):
+        """
+        Triggered from plugins to update service items.
+        """
+        editId, uuid = message.split(u':')
+        for item in self.serviceItems:
+            if item[u'service_item']._uuid == uuid:
+                item[u'service_item'].editId = editId
+
+    def replaceServiceItem(self, newItem):
+        """
+        Using the service item passed replace the one with the same edit id
+        if found.
+        """
+        newItem.render()
+        for itemcount, item in enumerate(self.serviceItems):
+            if item[u'service_item'].editId == newItem.editId and \
+                item[u'service_item'].name == newItem.name:
+                newItem.merge(item[u'service_item'])
+                item[u'service_item'] = newItem
+                self.repaintServiceList(itemcount + 1, 0)
+                self.parent.LiveController.replaceServiceManagerItem(newItem)
+        self.parent.serviceChanged(False, self.serviceName)
+
+    def addServiceItem(self, item, rebuild=False, expand=False, replace=False):
         """
         Add a Service item to the list
 
@@ -817,7 +846,7 @@
             self.repaintServiceList(sitem + 1, 0)
             self.parent.LiveController.replaceServiceManagerItem(item)
         else:
-            #nothing selected for dnd
+            # nothing selected for dnd
             if self.droppos == 0:
                 if isinstance(item, list):
                     for inditem in item:
@@ -834,7 +863,7 @@
                     u'order': self.droppos,
                     u'expanded':expand})
                 self.repaintServiceList(self.droppos, 0)
-            #if rebuilding list make sure live is fixed.
+            # if rebuilding list make sure live is fixed.
             if rebuild:
                 self.parent.LiveController.replaceServiceManagerItem(item)
         self.droppos = 0
@@ -914,7 +943,7 @@
             else:
                 pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
                 count = item.data(0, QtCore.Qt.UserRole).toInt()[0]
-        #adjust for zero based arrays
+        # adjust for zero based arrays
         pos = pos - 1
         return pos, count
 
@@ -940,7 +969,7 @@
         if link.hasText():
             plugin = event.mimeData().text()
             item = self.serviceManagerList.itemAt(event.pos())
-            #ServiceManager started the drag and drop
+            # ServiceManager started the drag and drop
             if plugin == u'ServiceManager':
                 startpos, startCount = self.findServiceItem()
                 if item is None:
@@ -952,22 +981,22 @@
                 self.serviceItems.insert(endpos, serviceItem)
                 self.repaintServiceList(endpos, startCount)
             else:
-                #we are not over anything so drop
+                # we are not over anything so drop
                 replace = False
                 if item is None:
                     self.droppos = len(self.serviceItems)
                 else:
-                    #we are over somthing so lets investigate
+                    # we are over somthing so lets investigate
                     pos = self._getParentItemData(item) - 1
                     serviceItem = self.serviceItems[pos]
                     if (plugin == serviceItem[u'service_item'].name and
                         serviceItem[u'service_item'].is_capable(
                         ItemCapabilities.AllowsAdditions)):
                         action = self.dndMenu.exec_(QtGui.QCursor.pos())
-                        #New action required
+                        # New action required
                         if action == self.newAction:
                             self.droppos = self._getParentItemData(item)
-                        #Append to existing action
+                        # Append to existing action
                         if action == self.addToAction:
                             self.droppos = self._getParentItemData(item)
                             item.setSelected(True)

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2010-09-27 18:34:40 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2010-10-06 20:32:48 +0000
@@ -60,6 +60,7 @@
         # Holds information about whether the edit is remotly triggered and
         # which Song is required.
         self.remoteSong = -1
+        self.editItem = None
 
     def requiredIcons(self):
         MediaManagerItem.requiredIcons(self)
@@ -123,7 +124,7 @@
             QtCore.SIGNAL(u'textChanged(const QString&)'),
             self.onSearchTextEditChanged)
         QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'songs_load_list'), self.onSearchTextButtonClick)
+            QtCore.SIGNAL(u'songs_load_list'), self.onSongListLoad)
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'config_updated'), self.configUpdated)
         QtCore.QObject.connect(Receiver.get_receiver(),
@@ -137,6 +138,12 @@
         self.searchAsYouType = QtCore.QSettings().value(
             self.settingsSection + u'/search as type',
             QtCore.QVariant(u'False')).toBool()
+        self.updateServiceOnEdit = QtCore.QSettings().value(
+            self.settingsSection + u'/update service on edit',
+            QtCore.QVariant(u'False')).toBool()
+        self.AddSongFromServide = QtCore.QSettings().value(
+            self.settingsSection + u'/add song from service',
+            QtCore.QVariant(u'True')).toBool()
 
     def retranslateUi(self):
         self.SearchTextLabel.setText(
@@ -179,14 +186,26 @@
                 Author.display_name.like(u'%' + search_keywords + u'%'),
                 Author.display_name.asc())
             self.displayResultsAuthor(search_results)
-        #Called to redisplay the song list screen edith from a search
-        #or from the exit of the Song edit dialog.  If remote editing is active
-        #Trigger it and clean up so it will not update again.
+
+    def onSongListLoad(self):
+        """
+        Handle the exit from the edit dialog and trigger remote updates
+        of songs
+        """
+        # Called to redisplay the song list screen edit from a search
+        # or from the exit of the Song edit dialog.  If remote editing is active
+        # Trigger it and clean up so it will not update again.
         if self.remoteTriggered == u'L':
             self.onAddClick()
         if self.remoteTriggered == u'P':
             self.onPreviewClick()
+        # Push edits to the service manager to update items
+        if self.editItem and self.updateServiceOnEdit and \
+            not self.remoteTriggered:
+            item = self.buildServiceItem(self.editItem)
+            self.parent.serviceManager.replaceServiceItem(item)
         self.onRemoteEditClear()
+        self.onSearchTextButtonClick()
 
     def displayResultsSong(self, searchresults):
         log.debug(u'display results Song')
@@ -271,8 +290,8 @@
         if check_item_selected(self.listView,
             translate('SongsPlugin.MediaItem',
             'You must select an item to edit.')):
-            item = self.listView.currentItem()
-            item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
+            self.editItem = self.listView.currentItem()
+            item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
             self.edit_song_form.loadSong(item_id, False)
             self.edit_song_form.exec_()
 
@@ -322,6 +341,8 @@
         service_item.add_capability(ItemCapabilities.AllowsEdit)
         service_item.add_capability(ItemCapabilities.AllowsPreview)
         service_item.add_capability(ItemCapabilities.AllowsLoop)
+        service_item.add_capability(ItemCapabilities.OnLoadUpdate)
+        service_item.add_capability(ItemCapabilities.AddIfNewItem)
         song = self.parent.manager.get_object(Song, item_id)
         service_item.theme = song.theme_name
         service_item.editId = item_id
@@ -368,4 +389,31 @@
         service_item.audit = [
             song.title, author_audit, song.copyright, unicode(song.ccli_number)
         ]
+        service_item.data_string = {u'title':song.search_title,  u'authors':author_list}
         return True
+
+    def serviceLoad(self, item):
+        """
+        Triggered by a song being loaded by the service item
+        """
+        if item.data_string:
+            search_results = self.parent.manager.get_all_objects(Song,
+                Song.search_title.like(u'%' +
+                    item.data_string[u'title'].split(u'@')[0] + u'%'),
+                Song.search_title.asc())
+            author_list = item.data_string[u'authors'].split(u',')
+            editId = 0
+            uuid = 0
+            if search_results:
+                for song in search_results:
+                    count = 0
+                    for author in song.authors:
+                        if author.display_name in author_list:
+                           count += 1
+                    if count == len(author_list):
+                        editId = song.id
+                        uuid = item._uuid
+            if editId != 0:
+                Receiver.send_message(u'service_item_update',
+                    u'%s:%s' %(editId, uuid))
+

=== modified file 'openlp/plugins/songs/lib/songstab.py'
--- openlp/plugins/songs/lib/songstab.py	2010-09-16 21:10:36 +0000
+++ openlp/plugins/songs/lib/songstab.py	2010-10-06 20:32:48 +0000
@@ -51,8 +51,14 @@
         self.SearchAsTypeCheckBox.setObjectName(u'SearchAsTypeCheckBox')
         self.SongsModeLayout.addWidget(self.SearchAsTypeCheckBox)
         self.SongBarActiveCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
-        self.SongBarActiveCheckBox.setObjectName(u'SearchAsTypeCheckBox')
+        self.SongBarActiveCheckBox.setObjectName(u'SongBarActiveCheckBox')
         self.SongsModeLayout.addWidget(self.SongBarActiveCheckBox)
+        self.SongUpdateOnEditCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
+        self.SongUpdateOnEditCheckBox.setObjectName(u'SongUpdateOnEditCheckBox')
+        self.SongsModeLayout.addWidget(self.SongUpdateOnEditCheckBox)
+        self.SongAddFromServiceCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
+        self.SongAddFromServiceCheckBox.setObjectName(u'SongAddFromServiceCheckBox')
+        self.SongsModeLayout.addWidget(self.SongAddFromServiceCheckBox)
         self.SongsLayout.setWidget(
             0, QtGui.QFormLayout.LabelRole, self.SongsModeGroupBox)
         QtCore.QObject.connect(self.SearchAsTypeCheckBox,
@@ -60,7 +66,13 @@
             self.onSearchAsTypeCheckBoxChanged)
         QtCore.QObject.connect(self.SongBarActiveCheckBox,
             QtCore.SIGNAL(u'stateChanged(int)'),
-            self.SongBarActiveCheckBoxChanged)
+            self.onSongBarActiveCheckBoxChanged)
+        QtCore.QObject.connect(self.SongUpdateOnEditCheckBox,
+            QtCore.SIGNAL(u'stateChanged(int)'),
+            self.onSongUpdateOnEditCheckBoxChanged)
+        QtCore.QObject.connect(self.SongBarActiveCheckBox,
+            QtCore.SIGNAL(u'stateChanged(int)'),
+            self.onSongAddFromServiceCheckBoxChanged)
 
     def retranslateUi(self):
         self.SongsModeGroupBox.setTitle(
@@ -69,6 +81,10 @@
             translate('SongsPlugin.SongsTab', 'Enable search as you type'))
         self.SongBarActiveCheckBox.setText(translate('SongsPlugin.SongsTab',
             'Display verses on live tool bar'))
+        self.SongUpdateOnEditCheckBox.setText(
+            translate('SongsPlugin.SongsTab', 'Update service from song edit'))
+        self.SongAddFromServiceCheckBox.setText(translate('SongsPlugin.SongsTab',
+            'Add missing songs when opening service'))
 
     def onSearchAsTypeCheckBoxChanged(self, check_state):
         self.song_search = False
@@ -76,12 +92,24 @@
         if check_state == QtCore.Qt.Checked:
             self.song_search = True
 
-    def SongBarActiveCheckBoxChanged(self, check_state):
+    def onSongBarActiveCheckBoxChanged(self, check_state):
         self.song_bar = False
         # we have a set value convert to True/False
         if check_state == QtCore.Qt.Checked:
             self.song_bar = True
 
+    def onSongUpdateOnEditCheckBoxChanged(self, check_state):
+        self.update_edit = False
+        # we have a set value convert to True/False
+        if check_state == QtCore.Qt.Checked:
+            self.update_edit = True
+
+    def onSongAddFromServiceCheckBoxChanged(self, check_state):
+        self.update_load = False
+        # we have a set value convert to True/False
+        if check_state == QtCore.Qt.Checked:
+            self.update_load = True
+
     def load(self):
         settings = QtCore.QSettings()
         settings.beginGroup(self.settingsSection)
@@ -89,8 +117,14 @@
             u'search as type', QtCore.QVariant(False)).toBool()
         self.song_bar = settings.value(
             u'display songbar', QtCore.QVariant(True)).toBool()
+        self.update_edit = settings.value(
+            u'update service on edit', QtCore.QVariant(False)).toBool()
+        self.update_load = settings.value(
+            u'add song from service', QtCore.QVariant(True)).toBool()
         self.SearchAsTypeCheckBox.setChecked(self.song_search)
         self.SongBarActiveCheckBox.setChecked(self.song_bar)
+        self.SongUpdateOnEditCheckBox.setChecked(self.update_edit)
+        self.SongAddFromServiceCheckBox.setChecked(self.update_load)
         settings.endGroup()
 
     def save(self):
@@ -98,4 +132,6 @@
         settings.beginGroup(self.settingsSection)
         settings.setValue(u'search as type', QtCore.QVariant(self.song_search))
         settings.setValue(u'display songbar', QtCore.QVariant(self.song_bar))
+        settings.setValue(u'update service on edit', QtCore.QVariant(self.update_edit))
+        settings.setValue(u'add song from service', QtCore.QVariant(self.update_load))
         settings.endGroup()


Follow ups