← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~jasperge/openlp/versenumbers into lp:openlp

 

Jasper van Nieuwenhuizen has proposed merging lp:~jasperge/openlp/versenumbers into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~jasperge/openlp/versenumbers/+merge/255439

This branch adds the ability to display the verse numbers of a song in the footer, like this: "<song title>: 1, 2, 3". The current verse number is bold. Chorus, Bridge etc. are only displayed in the footer if they are currently on the screen. So for example if you display the chorus, it might look like this: "<song title>: 1, 2, Chorus, 3". In the unlikely event of a second chorus, bridge etc. the number will be added: "Chorus 2".
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~jasperge/openlp/versenumbers into lp:openlp.
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2015-01-18 13:39:21 +0000
+++ openlp/core/lib/serviceitem.py	2015-04-07 22:07:03 +0000
@@ -118,6 +118,9 @@
     ``HasThumbnails``
             The item has related thumbnails available
 
+    ``HasVerseNumbers``
+            The item has verse numbers in the title
+
     """
     CanPreview = 1
     CanEdit = 2
@@ -140,6 +143,7 @@
     HasDisplayTitle = 19
     HasNotes = 20
     HasThumbnails = 21
+    HasVerseNumbers = 22
 
 
 class ServiceItem(RegistryProperties):

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2015-03-18 22:02:51 +0000
+++ openlp/core/ui/slidecontroller.py	2015-04-07 22:07:03 +0000
@@ -1062,6 +1062,74 @@
         """
         self.slide_selected()
 
+    def list_verse_numbers_with_progress(self, item, row):
+        """
+        Generates a list of the verse numbers that are in the service item.
+        It only return the number if the verse is of type 'Verse'. For other types
+        it will only return the translated type if this verse is beeing displayed.
+        The verse that is being displayed will be <bold>.
+
+        :param item: The sercice item that is being displayed
+        :return: List of verse numbers
+        """
+        try:
+            from openlp.plugins.songs.lib import VerseType
+        except ImportError:
+            class VerseType(object):
+                """
+                This empty class is mostly just to satisfy Python, PEP8 and PyCharm
+                """
+                pass
+            return
+
+        def format_display_tag(tag):
+            verse_type = VerseType.from_translated_tag(tag)
+            if verse_type == 0:
+                # The verse is of type 'Verse'
+            # if tag[0].upper() == "v":
+                tag_append = "<b>{}</b>".format(tag[1:])
+            else:
+                # The verse is not of type 'Verse'
+                if tag[1:] != "1":
+                    tag_append = "<b>{0} {1}</b>".format(VerseType.translated_names[verse_type], tag[1:])
+                else:
+                    tag_append = "<b>{}</b>".format(VerseType.translated_names[verse_type])
+
+            return tag_append
+
+        raw_verse_list = []
+        verse_list = []
+        for i, f in enumerate(item.get_frames()):
+            tag = f['verseTag']
+            tag_replace = False
+            if raw_verse_list and raw_verse_list[-1] == tag:
+                if i == row:
+                    if VerseType.from_translated_tag(tag) == 0:
+                    # if tag[0].lower() == "v":
+                        # The verse is of type 'Verse'
+                        tag_replace = True
+                    tag_append = format_display_tag(tag)
+                else:
+                    tag_append = None
+            else:
+                if i == row:
+                    tag_append = format_display_tag(tag)
+                else:
+                    if VerseType.from_translated_tag(tag) == 0:
+                        # The verse is of type 'Verse'
+                    # if tag[0].lower() == "v":
+                        tag_append = tag[1:]
+                    else:
+                        tag_append = " "
+            if tag_append:
+                raw_verse_list.append(tag)
+                if tag_append.strip():
+                    if tag_replace:
+                        verse_list[-1] = tag_append
+                    else:
+                        verse_list.append(tag_append)
+        return verse_list
+
     def slide_selected(self, start=False):
         """
         Generate the preview when you click on a slide. If this is the Live Controller also display on the screen
@@ -1088,6 +1156,18 @@
                 to_display = self.service_item.get_rendered_frame(row)
                 if self.service_item.is_text():
                     self.display.text(to_display)
+                    try:
+                        display_verse_numbers = Settings().value('songs/display verse numbers')
+                    except KeyError:
+                        display_verse_numbers = True
+                    if self.service_item.is_capable(ItemCapabilities.HasVerseNumbers) and display_verse_numbers:
+                        verse_list = self.list_verse_numbers_with_progress(self.service_item, row)
+                        if verse_list:
+                            verse_list = ", ".join(verse_list)
+                            foot_text = self.service_item.foot_text.split("<br>")
+                            foot_text[0] = ": ".join((foot_text[0].split(": ")[0], verse_list))
+                            foot_text = "<br>".join(foot_text)
+                            self.display.footer(foot_text)
                 else:
                     if start:
                         self.display.build_html(self.service_item, to_display)

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2015-01-18 13:39:21 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2015-04-07 22:07:03 +0000
@@ -118,6 +118,7 @@
         self.search_as_you_type = Settings().value(self.settings_section + '/search as type')
         self.update_service_on_edit = Settings().value(self.settings_section + '/update service on edit')
         self.add_song_from_service = Settings().value(self.settings_section + '/add song from service')
+        self.display_verse_numbers = Settings().value(self.settings_section + '/display verse numbers')
         self.display_songbook = Settings().value(self.settings_section + '/display songbook')
         self.display_copyright_symbol = Settings().value(self.settings_section + '/display copyright symbol')
 
@@ -468,8 +469,32 @@
         if song.media_files:
             service_item.add_capability(ItemCapabilities.HasBackgroundAudio)
             service_item.background_audio = [m.file_name for m in song.media_files]
+        if self.display_verse_numbers and len(verse_list) > 1:
+            service_item.add_capability(ItemCapabilities.HasVerseNumbers)
         return True
 
+    def list_verse_numbers(self, song):
+        """
+        Generates a list of the verse numbers. It will only return the number
+        if the verse is of type 'Verse'. If a verse order is found for
+        the song, this will be used. Else the verse numbers will be displayed
+        in order.
+
+        :param item: The song to be used to generate the list
+        :return: List of verse numbers
+        """
+        if not song.verse_order.strip():
+            # No verse order found
+            verse_list = SongXML().get_verses(song.lyrics)
+            if len(verse_list) > 1:
+                # Only return a list if there is more than 1 verse
+                return [v[0]['label'] for v in verse_list if v[0]['type'] == 'v']
+        else:
+            # Use verse order
+            verse_list = song.verse_order.split()
+            # If a verse oreder is used, also return a list if there is just 1 verse
+            return [v[1:] for v in verse_list if v[0] == 'v']
+
     def generate_footer(self, item, song):
         """
         Generates the song footer based on a song and adds details to a service item.
@@ -499,7 +524,13 @@
             song.title, authors_all, song.copyright, str(song.ccli_number)
         ]
         item.raw_footer = []
-        item.raw_footer.append(song.title)
+        if self.display_verse_numbers:
+            verse_list = self.list_verse_numbers(song)
+            if verse_list:
+                verses = ", ".join(self.list_verse_numbers(song))
+                item.raw_footer.append(": ".join((song.title, verses)))
+        else:
+            item.raw_footer.append(song.title)
         if authors_none:
             item.raw_footer.append("%s: %s" % (translate('OpenLP.Ui', 'Written by'),
                                                create_separated_list(authors_none)))
@@ -564,6 +595,13 @@
         # Update service with correct song id and return it to caller.
         item.edit_id = edit_id
         self.generate_footer(item, song)
+        # Enable verse display for the song if it's enabled, but was not enabled when the service was created.
+        if self.display_verse_numbers:
+            if not add_song:
+                song = self.open_lyrics.xml_to_song(item.xml_version, True)
+            verse_list = SongXML().get_verses(song.lyrics)
+            if len(verse_list) > 1 and not item.is_capable(ItemCapabilities.HasVerseNumbers):
+                item.add_capability(ItemCapabilities.HasVerseNumbers)
         return item
 
     def _authors_match(self, song, authors):

=== modified file 'openlp/plugins/songs/lib/songstab.py'
--- openlp/plugins/songs/lib/songstab.py	2015-01-18 13:39:21 +0000
+++ openlp/plugins/songs/lib/songstab.py	2015-04-07 22:07:03 +0000
@@ -53,6 +53,9 @@
         self.add_from_service_check_box = QtGui.QCheckBox(self.mode_group_box)
         self.add_from_service_check_box.setObjectName('add_from_service_check_box')
         self.mode_layout.addWidget(self.add_from_service_check_box)
+        self.display_verse_numbers_check_box = QtGui.QCheckBox(self.mode_group_box)
+        self.display_verse_numbers_check_box.setObjectName('verse_numbers_check_box')
+        self.mode_layout.addWidget(self.display_verse_numbers_check_box)
         self.display_songbook_check_box = QtGui.QCheckBox(self.mode_group_box)
         self.display_songbook_check_box.setObjectName('songbook_check_box')
         self.mode_layout.addWidget(self.display_songbook_check_box)
@@ -66,6 +69,7 @@
         self.tool_bar_active_check_box.stateChanged.connect(self.on_tool_bar_active_check_box_changed)
         self.update_on_edit_check_box.stateChanged.connect(self.on_update_on_edit_check_box_changed)
         self.add_from_service_check_box.stateChanged.connect(self.on_add_from_service_check_box_changed)
+        self.display_verse_numbers_check_box.stateChanged.connect(self.on_verse_numbers_check_box_changed)
         self.display_songbook_check_box.stateChanged.connect(self.on_songbook_check_box_changed)
         self.display_copyright_check_box.stateChanged.connect(self.on_copyright_check_box_changed)
 
@@ -77,6 +81,8 @@
         self.update_on_edit_check_box.setText(translate('SongsPlugin.SongsTab', 'Update service from song edit'))
         self.add_from_service_check_box.setText(translate('SongsPlugin.SongsTab',
                                                           'Import missing songs from service files'))
+        self.display_verse_numbers_check_box.setText(translate('SongsPlugin.SongsTab',
+                                                                'Display verse numbers after the title'))
         self.display_songbook_check_box.setText(translate('SongsPlugin.SongsTab', 'Display songbook in footer'))
         self.display_copyright_check_box.setText(translate('SongsPlugin.SongsTab',
                                                            'Display "%s" symbol before copyright info' %
@@ -94,6 +100,9 @@
     def on_add_from_service_check_box_changed(self, check_state):
         self.update_load = (check_state == QtCore.Qt.Checked)
 
+    def on_verse_numbers_check_box_changed(self, check_state):
+        self.display_verse_numbers = (check_state == QtCore.Qt.Checked)
+
     def on_songbook_check_box_changed(self, check_state):
         self.display_songbook = (check_state == QtCore.Qt.Checked)
 
@@ -107,12 +116,14 @@
         self.tool_bar = settings.value('display songbar')
         self.update_edit = settings.value('update service on edit')
         self.update_load = settings.value('add song from service')
+        self.display_verse_numbers = settings.value('display verse numbers')
         self.display_songbook = settings.value('display songbook')
         self.display_copyright_symbol = settings.value('display copyright symbol')
         self.search_as_type_check_box.setChecked(self.song_search)
         self.tool_bar_active_check_box.setChecked(self.tool_bar)
         self.update_on_edit_check_box.setChecked(self.update_edit)
         self.add_from_service_check_box.setChecked(self.update_load)
+        self.display_verse_numbers_check_box.setChecked(self.display_verse_numbers)
         self.display_songbook_check_box.setChecked(self.display_songbook)
         self.display_copyright_check_box.setChecked(self.display_copyright_symbol)
         settings.endGroup()
@@ -124,6 +135,7 @@
         settings.setValue('display songbar', self.tool_bar)
         settings.setValue('update service on edit', self.update_edit)
         settings.setValue('add song from service', self.update_load)
+        settings.setValue('display verse numbers', self.display_verse_numbers)
         settings.setValue('display songbook', self.display_songbook)
         settings.setValue('display copyright symbol', self.display_copyright_symbol)
         settings.endGroup()

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2015-02-11 20:56:13 +0000
+++ openlp/plugins/songs/songsplugin.py	2015-04-07 22:07:03 +0000
@@ -60,6 +60,7 @@
     'songs/search as type': True,
     'songs/add song from service': True,
     'songs/display songbar': True,
+    'songs/display verse numbers': False,
     'songs/display songbook': False,
     'songs/display copyright symbol': False,
     'songs/last directory import': '',


Follow ups