diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index a4f683e81..1080cd2f5 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -75,7 +75,7 @@ class EventReceiver(QtCore.QObject): 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 @@ class EventReceiver(QtCore.QObject): ``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 @@ class EventReceiver(QtCore.QObject): ``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 @@ class EventReceiver(QtCore.QObject): ``{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 diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 71d364b2e..457249b35 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui 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 @@ class MediaManagerItem(QtGui.QWidget): 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 @@ class MediaManagerItem(QtGui.QWidget): 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 @@ class MediaManagerItem(QtGui.QWidget): 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 @@ class MediaManagerItem(QtGui.QWidget): 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 @@ class MediaManagerItem(QtGui.QWidget): 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 + diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 398606422..b4dc263e9 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -58,6 +58,9 @@ class ItemCapabilities(object): AllowsLoop = 5 AllowsAdditions = 6 NoLineBreaks = 7 + OnLoadUpdate = 8 + AddIfNewItem = 9 + class ServiceItem(object): """ @@ -98,6 +101,9 @@ class ServiceItem(object): 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 @@ class ServiceItem(object): 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 @@ class ServiceItem(object): 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) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 319725790..d751b76be 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -223,6 +223,8 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): # 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 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): 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 @@ class ServiceManager(QtGui.QWidget): 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) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index b9c4526cf..b50005486 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -60,6 +60,7 @@ class SongMediaItem(MediaManagerItem): # 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 @@ class SongMediaItem(MediaManagerItem): 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 @@ class SongMediaItem(MediaManagerItem): 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 @@ class SongMediaItem(MediaManagerItem): 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 @@ class SongMediaItem(MediaManagerItem): 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 @@ class SongMediaItem(MediaManagerItem): 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 @@ class SongMediaItem(MediaManagerItem): 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)) + diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 39a53f1c6..03c1e8844 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -51,8 +51,14 @@ class SongsTab(SettingsTab): 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 @@ class SongsTab(SettingsTab): 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 @@ class SongsTab(SettingsTab): 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 @@ class SongsTab(SettingsTab): 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 @@ class SongsTab(SettingsTab): 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 @@ class SongsTab(SettingsTab): 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()