← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/latest-fixes into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/latest-fixes into lp:openlp.

Commit message:
Undo an incorrect change and replace missing code as pert of the display revamp.

Requested reviews:
  Raoul Snyman (raoul-snyman)
Related bugs:
  Bug #1840092 in OpenLP: "version 2889 song edit window 'save and preview' button only saves"
  https://bugs.launchpad.net/openlp/+bug/1840092
  Bug #1841196 in OpenLP: "V2892 Service Theme not working"
  https://bugs.launchpad.net/openlp/+bug/1841196

For more details, see:
https://code.launchpad.net/~trb143/openlp/latest-fixes/+merge/372057

The save Button did not need renaming it has been moved by QT.

Replace the logic to set the theme for a given item.

Replace the theme regeneration code which was removed in the refactor.
-- 
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/display/render.py'
--- openlp/core/display/render.py	2019-08-06 20:46:41 +0000
+++ openlp/core/display/render.py	2019-08-30 12:09:41 +0000
@@ -503,6 +503,26 @@
         self.force_page = False
         return None
 
+    def get_theme(self, item):
+        """
+        :param item: The :class:`~openlp.core.lib.serviceitem.ServiceItem` item object
+        :return string: The name of the theme to be used
+
+        """
+        # Just assume we use the global theme.
+        theme_name = Registry().get('theme_manager').global_theme
+        # The theme level is either set to Service or Item. Use the service theme if one is set. We also have to use the
+        # service theme, even when the theme level is set to Item, because the item does not necessarily have to have a
+        # theme.
+        if self.theme_level != ThemeLevel.Global:
+            # When the theme level is at Service and we actually have a service theme then use it.
+            if self.theme_level == ThemeLevel.Service:
+                theme_name = Registry().get('service_manager').service_theme
+        # If we have Item level and have an item theme then use it.
+        if self.theme_level == ThemeLevel.Song and item.theme:
+            theme_name = item.theme
+        return theme_name
+
     def format_slide(self, text, item):
         """
         Calculate how much text can fit on a slide.
@@ -515,7 +535,7 @@
             QtWidgets.QApplication.instance().processEvents()
         self.log_debug('format slide')
         if item:
-            theme_name = item.theme if item.theme else Registry().get('theme_manager').global_theme
+            theme_name = self.get_theme(item)
             theme_data = Registry().get('theme_manager').get_theme_data(theme_name)
             self.theme_height = theme_data.font_main_height
             # Set theme for preview

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2019-05-24 22:11:11 +0000
+++ openlp/core/lib/serviceitem.py	2019-08-30 12:09:41 +0000
@@ -321,6 +321,13 @@
                                      'display_title': slide['display_title'], 'notes': slide['notes']})
         return {'header': service_header, 'data': service_data}
 
+    def render_text_items(self):
+        """
+        This method forces the display to be regenerated
+        """
+        self._display_slides = []
+        self._rendered_slides = []
+
     def set_from_service(self, service_item, path=None):
         """
         This method takes a service item from a saved service file (passed from the ServiceManager) and extracts the
@@ -503,7 +510,6 @@
         :param row: The service item slide to be returned
         """
         if self.service_item_type == ServiceItemType.Text:
-            # return self.display_frames[row]['html'].split('\n')[0]
             return self.rendered_slides[row]['text']
         elif self.service_item_type == ServiceItemType.Image:
             return self.slides[row]['path']

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2019-08-04 13:13:33 +0000
+++ openlp/core/ui/mainwindow.py	2019-08-30 12:09:41 +0000
@@ -546,7 +546,8 @@
         Wait for the threads
         """
         # Sometimes the threads haven't finished, let's wait for them
-        wait_dialog = QtWidgets.QProgressDialog('Waiting for some things to finish...', '', 0, 0, self)
+        wait_dialog = QtWidgets.QProgressDialog(translate('OpenLP.MainWindow', 'Waiting for some things to finish...'),
+                                                '', 0, 0, self)
         wait_dialog.setWindowModality(QtCore.Qt.WindowModal)
         wait_dialog.setAutoClose(False)
         wait_dialog.setCancelButton(None)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2019-08-04 13:13:33 +0000
+++ openlp/core/ui/servicemanager.py	2019-08-30 12:09:41 +0000
@@ -46,7 +46,7 @@
 from openlp.core.lib import build_icon
 from openlp.core.lib.exceptions import ValidationError
 from openlp.core.lib.plugin import PluginStatus
-from openlp.core.lib.serviceitem import ItemCapabilities, ServiceItem
+from openlp.core.lib.serviceitem import ItemCapabilities, ServiceItem, ServiceItemType
 from openlp.core.lib.ui import create_widget_action, critical_error_message_box, find_and_set_in_combo_box
 from openlp.core.ui.icons import UiIcons
 from openlp.core.ui.media import AUDIO_EXT, VIDEO_EXT
@@ -749,9 +749,7 @@
                 if theme:
                     find_and_set_in_combo_box(self.theme_combo_box, theme, set_missing=False)
                     if theme == self.theme_combo_box.currentText():
-                        # TODO: Use a local display widget
-                        # self.preview_display.set_theme(get_theme_from_name(theme))
-                        pass
+                        self.service_theme = theme
             else:
                 if self._save_lite:
                     service_item.set_from_service(item)
@@ -1197,9 +1195,9 @@
             service_item_from_item = item['service_item']
             tree_widget_item = QtWidgets.QTreeWidgetItem(self.service_manager_list)
             if service_item_from_item.is_valid:
+                icon = service_item_from_item.icon.pixmap(80, 80).toImage()
+                icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                 if service_item_from_item.notes:
-                    icon = service_item_from_item.icon.pixmap(80, 80).toImage()
-                    icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                     overlay = UiIcons().notes.pixmap(40, 40).toImage()
                     overlay = overlay.scaled(40, 40, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                     painter = QtGui.QPainter(icon)
@@ -1207,8 +1205,6 @@
                     painter.end()
                     tree_widget_item.setIcon(0, build_icon(icon))
                 elif service_item_from_item.temporary_edit:
-                    icon = service_item_from_item.icon.pixmap(80, 80).toImage()
-                    icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                     overlay = QtGui.QImage(UiIcons().upload)
                     overlay = overlay.scaled(40, 40, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                     painter = QtGui.QPainter(icon)
@@ -1242,13 +1238,14 @@
             tree_widget_item.setData(0, QtCore.Qt.UserRole, item['order'])
             tree_widget_item.setSelected(item['selected'])
             # Add the children to their parent tree_widget_item.
-            for slide_index, slide in enumerate(service_item_from_item.slides):
+            for slide_index, slide in enumerate(service_item_from_item.get_frames()):
                 child = QtWidgets.QTreeWidgetItem(tree_widget_item)
                 # prefer to use a display_title
-                if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle):
-                    text = slide['display_title'].replace('\n', ' ')
-                else:
+                if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle) or \
+                        service_item_from_item.service_item_type == ServiceItemType.Image:
                     text = slide['title'].replace('\n', ' ')
+                else:
+                    text = service_item_from_item.get_rendered_frame(slide_index)
                 child.setText(0, text[:40])
                 child.setData(0, QtCore.Qt.UserRole, slide_index)
                 if service_item == item_index:
@@ -1275,8 +1272,6 @@
         :param current_index: The combo box index for the selected item
         """
         self.service_theme = self.theme_combo_box.currentText()
-        # TODO: Use a local display widget
-        # self.preview_display.set_theme(get_theme_from_name(theme))
         Settings().setValue(self.main_window.service_manager_settings_section + '/service theme', self.service_theme)
         self.regenerate_service_items(True)
 
@@ -1335,7 +1330,7 @@
         """
         for item_count, item in enumerate(self.service_items):
             if item['service_item'].edit_id == new_item.edit_id and item['service_item'].name == new_item.name:
-                new_item.render()
+                new_item.create_slides()
                 new_item.merge(item['service_item'])
                 item['service_item'] = new_item
                 self.repaint_service_list(item_count + 1, 0)
@@ -1368,7 +1363,7 @@
             self.repaint_service_list(s_item, child)
             self.live_controller.replace_service_manager_item(item)
         else:
-            # item.render()
+            item.render_text_items()
             # nothing selected for dnd
             if self.drop_position == -1:
                 if isinstance(item, list):
@@ -1617,8 +1612,6 @@
             theme_group.addAction(create_widget_action(self.theme_menu, theme, text=theme, checked=False,
                                   triggers=self.on_theme_change_action))
         find_and_set_in_combo_box(self.theme_combo_box, self.service_theme)
-        # TODO: Sort this out
-        # self.renderer.set_service_theme(self.service_theme)
         self.regenerate_service_items()
 
     def on_theme_change_action(self):

=== modified file 'openlp/plugins/presentations/lib/maclocontroller.py'
--- openlp/plugins/presentations/lib/maclocontroller.py	2019-06-05 04:57:26 +0000
+++ openlp/plugins/presentations/lib/maclocontroller.py	2019-08-30 12:09:41 +0000
@@ -27,6 +27,7 @@
 
 from openlp.core.common import delete_file, is_macosx
 from openlp.core.common.applocation import AppLocation
+from openlp.core.common.mixins import LogMixin
 from openlp.core.common.path import Path
 from openlp.core.common.registry import Registry
 from openlp.core.display.screens import ScreenList
@@ -47,7 +48,7 @@
 register_classes()
 
 
-class MacLOController(PresentationController):
+class MacLOController(PresentationController, LogMixin):
     """
     Class to control interactions with MacLO presentations on Mac OS X via Pyro4. It starts the Pyro4 nameserver,
     starts the LibreOfficeServer, and then controls MacLO via Pyro4.

=== modified file 'openlp/plugins/songs/forms/editsongdialog.py'
--- openlp/plugins/songs/forms/editsongdialog.py	2019-07-31 20:12:11 +0000
+++ openlp/plugins/songs/forms/editsongdialog.py	2019-08-30 12:09:41 +0000
@@ -291,7 +291,6 @@
         self.warning_label.setObjectName('warning_label')
         self.bottom_layout.addWidget(self.warning_label)
         self.button_box = create_button_box(edit_song_dialog, 'button_box', ['cancel', 'save'])
-        self.save_button = self.button_box.button(QtWidgets.QDialogButtonBox.Save)
         self.bottom_layout.addWidget(self.button_box)
         self.dialog_layout.addLayout(self.bottom_layout)
         self.retranslate_ui(edit_song_dialog)
@@ -342,7 +341,6 @@
             translate('SongsPlugin.EditSongForm', '<strong>Warning:</strong> Not all of the verses are in use.')
         self.no_verse_order_entered_warning =  \
             translate('SongsPlugin.EditSongForm', '<strong>Warning:</strong> You have not entered a verse order.')
-        self.save_button.setText(UiStrings().SaveAndPreview)
 
 
 def create_combo_box(parent, name, editable=True):

=== modified file 'tests/functional/openlp_core/display/test_render.py'
--- tests/functional/openlp_core/display/test_render.py	2019-04-13 13:00:22 +0000
+++ tests/functional/openlp_core/display/test_render.py	2019-08-30 12:09:41 +0000
@@ -22,10 +22,20 @@
 """
 Test the :mod:`~openlp.core.display.render` package.
 """
-from unittest.mock import patch
-
+import sys
+
+from unittest import TestCase
+from unittest.mock import MagicMock, patch
+
+from openlp.core.common import ThemeLevel
+from tests.helpers.testmixin import TestMixin
+
+from PyQt5 import QtWidgets
+sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
+
+from openlp.core.common.registry import Registry
 from openlp.core.display.render import compare_chord_lyric_width, find_formatting_tags, remove_tags, render_chords, \
-    render_chords_for_printing, render_tags
+    render_chords_for_printing, render_tags, ThemePreviewRenderer
 from openlp.core.lib.formattingtags import FormattingTags
 
 
@@ -208,3 +218,101 @@
 
     # THEN: The list of active tags should contain only 'st'
     assert active_tags == ['st'], 'The list of active tags should contain only "st"'
+
+
+class TestThemePreviewRenderer(TestMixin, TestCase):
+
+    def setUp(self):
+        """
+        Set up the components need for all tests.
+        """
+        # Create the Registry
+        self.application = QtWidgets.QApplication.instance()
+        Registry.create()
+        self.application.setOrganizationName('OpenLP-tests')
+        self.application.setOrganizationDomain('openlp.org')
+
+    def test_get_theme_global(self):
+        """
+        Test the return of the global theme if set to Global level
+        """
+        # GIVEN: A set up with a Global Theme and settings at Global
+        mocked_theme_manager = MagicMock()
+        mocked_theme_manager.global_theme = 'my_global_theme'
+        Registry().register('theme_manager', mocked_theme_manager)
+        with patch('openlp.core.display.webengine.WebEngineView'), \
+                patch('PyQt5.QtWidgets.QVBoxLayout'):
+            tpr = ThemePreviewRenderer()
+            tpr.theme_level = ThemeLevel.Global
+        # WHEN: I Request the theme to Use
+            theme = tpr.get_theme(MagicMock())
+
+        # THEN: The list of active tags should contain only 'st'
+            assert theme == mocked_theme_manager.global_theme, 'The Theme returned is not that of the global theme'
+
+    def test_get_theme_service(self):
+        """
+        Test the return of the global theme if set to Global level
+        """
+        # GIVEN: A set up with a Global Theme and settings at Global
+        mocked_theme_manager = MagicMock()
+        mocked_theme_manager.global_theme = 'my_global_theme'
+        mocked_service_manager = MagicMock()
+        mocked_service_manager.service_theme = 'my_service_theme'
+        Registry().register('theme_manager', mocked_theme_manager)
+        Registry().register('service_manager', mocked_service_manager)
+        with patch('openlp.core.display.webengine.WebEngineView'), \
+                patch('PyQt5.QtWidgets.QVBoxLayout'):
+            tpr = ThemePreviewRenderer()
+            tpr.theme_level = ThemeLevel.Service
+        # WHEN: I Request the theme to Use
+            theme = tpr.get_theme(MagicMock())
+
+        # THEN: The list of active tags should contain only 'st'
+            assert theme == mocked_service_manager.service_theme, 'The Theme returned is not that of the Service theme'
+
+    def test_get_theme_item_level_none(self):
+        """
+        Test the return of the global theme if set to Global level
+        """
+        # GIVEN: A set up with a Global Theme and settings at Global
+        mocked_theme_manager = MagicMock()
+        mocked_theme_manager.global_theme = 'my_global_theme'
+        mocked_service_manager = MagicMock()
+        mocked_service_manager.service_theme = 'my_service_theme'
+        mocked_item = MagicMock()
+        mocked_item.theme = None
+        Registry().register('theme_manager', mocked_theme_manager)
+        Registry().register('service_manager', mocked_service_manager)
+        with patch('openlp.core.display.webengine.WebEngineView'), \
+                patch('PyQt5.QtWidgets.QVBoxLayout'):
+            tpr = ThemePreviewRenderer()
+            tpr.theme_level = ThemeLevel.Song
+        # WHEN: I Request the theme to Use
+            theme = tpr.get_theme(mocked_item)
+
+        # THEN: The list of active tags should contain only 'st'
+            assert theme == mocked_theme_manager.global_theme, 'The Theme returned is not that of the global theme'
+
+    def test_get_theme_item_level_set(self):
+        """
+        Test the return of the global theme if set to Global level
+        """
+        # GIVEN: A set up with a Global Theme and settings at Global
+        mocked_theme_manager = MagicMock()
+        mocked_theme_manager.global_theme = 'my_global_theme'
+        mocked_service_manager = MagicMock()
+        mocked_service_manager.service_theme = 'my_service_theme'
+        mocked_item = MagicMock()
+        mocked_item.theme = "my_item_theme"
+        Registry().register('theme_manager', mocked_theme_manager)
+        Registry().register('service_manager', mocked_service_manager)
+        with patch('openlp.core.display.webengine.WebEngineView'), \
+                patch('PyQt5.QtWidgets.QVBoxLayout'):
+            tpr = ThemePreviewRenderer()
+            tpr.theme_level = ThemeLevel.Song
+        # WHEN: I Request the theme to Use
+            theme = tpr.get_theme(mocked_item)
+
+        # THEN: The list of active tags should contain only 'st'
+            assert theme == mocked_item.theme, 'The Theme returned is not that of the item theme'


Follow ups