← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~suutari-olli/openlp/bug-fixes-2-4-3 into lp:openlp

 

Azaziah has proposed merging lp:~suutari-olli/openlp/bug-fixes-2-4-3 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #1487788 in OpenLP: "Importing photos does not give focus to OpenLP"
  https://bugs.launchpad.net/openlp/+bug/1487788
  Bug #1512040 in OpenLP: "Loop tooltip gets stuck to "Stop playing...""
  https://bugs.launchpad.net/openlp/+bug/1512040
  Bug #1513490 in OpenLP: "List of authors uses localized "and" instead of English"
  https://bugs.launchpad.net/openlp/+bug/1513490
  Bug #1624661 in OpenLP: "Missing DB in unmounted disk results in Traceback"
  https://bugs.launchpad.net/openlp/+bug/1624661

For more details, see:
https://code.launchpad.net/~suutari-olli/openlp/bug-fixes-2-4-3/+merge/307559

This branch fixes the following bugs:
Bug #1487788: Importing photos does not give focus to OpenLP
Bug #1512040: Loop tooltip gets stuck to "Stop playing..."
Bug #1513490: List of authors uses localized "and" instead of English
Bug #1624661: Missing DB in unmounted disk results in Traceback

lp:~suutari-olli/openlp/bug-fixes-2-4-3 (revision 2712)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1790/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1701/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1639/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1395/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/985/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/1053/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/921/
[SUCCESS] https://ci.openlp.io/job/Branch-05c-Code_Analysis2/84/

-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~suutari-olli/openlp/bug-fixes-2-4-3 into lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2016-04-27 12:49:55 +0000
+++ openlp/core/__init__.py	2016-10-04 12:42:26 +0000
@@ -208,8 +208,8 @@
         # If data_version is different from the current version ask if we should backup the data folder
         elif data_version != openlp_version:
             if QtWidgets.QMessageBox.question(None, translate('OpenLP', 'Backup'),
-                                              translate('OpenLP', 'OpenLP has been upgraded, do you want to create '
-                                                                  'a backup of OpenLPs data folder?'),
+                                              translate('OpenLP', 'OpenLP has been upgraded, do you want to create\n'
+                                                                  'a backup of the old data folder?'),
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                               QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
                 # Create copy of data folder
@@ -223,8 +223,8 @@
                                                   translate('OpenLP', 'Backup of the data folder failed!'))
                     return
                 message = translate('OpenLP',
-                                    'A backup of the data folder has been created'
-                                    'at {text}').format(text=data_folder_backup_path)
+                                    'A backup of the data folder has been created in:\n\n'
+                                    '{text}').format(text=data_folder_backup_path)
                 QtWidgets.QMessageBox.information(None, translate('OpenLP', 'Backup'), message)
 
             # Update the version in the settings

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2016-08-12 19:16:12 +0000
+++ openlp/core/lib/__init__.py	2016-10-04 12:42:26 +0000
@@ -310,30 +310,23 @@
 
 def create_separated_list(string_list):
     """
-    Returns a string that represents a join of a list of strings with a localized separator. This function corresponds
-
-    to QLocale::createSeparatedList which was introduced in Qt 4.8 and implements the algorithm from
-    http://www.unicode.org/reports/tr35/#ListPatterns
-
-     :param string_list: List of unicode strings
+    Returns a string that represents a join of a list of strings with a localized separator.
+    Localized separation will be done via the translate() function by the translators.
+
+    :param string_list: List of unicode strings
+    :return: Formatted string
     """
-    if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'):
-        return QtCore.QLocale().createSeparatedList(string_list)
-    if not string_list:
-        return ''
-    elif len(string_list) == 1:
-        return string_list[0]
-    # TODO: Verify mocking of translate() test before conversion
-    elif len(string_list) == 2:
-        return translate('OpenLP.core.lib', '%s and %s',
-                         'Locale list separator: 2 items') % (string_list[0], string_list[1])
+    list_length = len(string_list)
+    if list_length == 1:
+        return_list = string_list[0]
+    elif list_length == 2:
+        return_list = translate('OpenLP.core.lib', '{one} and {two}').format(one=string_list[0], two=string_list[1])
+    elif list_length > 2:
+        return_list = translate('OpenLP.core.lib', '{first}, and {last}').format(first=', '.join(string_list[:-1]),
+                                                                                 last=string_list[-1])
     else:
-        merged = translate('OpenLP.core.lib', '%s, and %s',
-                           'Locale list separator: end') % (string_list[-2], string_list[-1])
-        for index in reversed(list(range(1, len(string_list) - 2))):
-            merged = translate('OpenLP.core.lib', '%s, %s',
-                               'Locale list separator: middle') % (string_list[index], merged)
-        return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (string_list[0], merged)
+        return_list = ""
+    return return_list
 
 
 from .exceptions import ValidationError

=== modified file 'openlp/core/lib/db.py'
--- openlp/core/lib/db.py	2016-07-06 19:48:57 +0000
+++ openlp/core/lib/db.py	2016-10-04 12:42:26 +0000
@@ -83,11 +83,16 @@
     :param db_file_name: File name of database
     :return: None
     """
-    db_path = get_db_path(plugin_name, db_file_name)
-    log.exception('Error loading database: {db}'.format(db=db_path))
-    critical_error_message_box(translate('OpenLP.Manager', 'Database Error'),
-                               translate('OpenLP.Manager',
-                                         'OpenLP cannot load your database.\n\nDatabase: {db}').format(db=db_path))
+    try:
+        db_path = get_db_path(plugin_name, db_file_name)
+        log.exception('Error loading database: {db}'.format(db=db_path))
+        critical_error_message_box(translate('OpenLP.Manager', 'Database Error'),
+                                   translate('OpenLP.Manager',
+                                             'OpenLP cannot load your database.\n\nDatabase: {db}').format(db=db_path))
+    # If the path (Eg. C:/ or D:/) does not exists in the system, return.
+    # In this case def load in advancedtab.py will handle the missing database.
+    except FileNotFoundError:
+        return
 
 
 def init_url(plugin_name, db_file_name=None):

=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py	2016-08-11 22:12:50 +0000
+++ openlp/core/ui/advancedtab.py	2016-10-04 12:42:26 +0000
@@ -401,23 +401,32 @@
             log.error('Data path not found {path}'.format(path=self.current_data_path))
             answer = QtWidgets.QMessageBox.critical(
                 self, translate('OpenLP.AdvancedTab', 'Data Directory Error'),
-                translate('OpenLP.AdvancedTab', 'OpenLP data directory was not found\n\n{path}\n\n'
-                          'This data directory was previously changed from the OpenLP '
-                          'default location.  If the new location was on removable '
-                          'media, that media needs to be made available.\n\n'
-                          'Click "No" to stop loading OpenLP. allowing you to fix the the problem.\n\n'
-                          'Click "Yes" to reset the data directory to the default '
-                          'location.').format(path=self.current_data_path),
+                translate('OpenLP.AdvancedTab', 'OpenLP data folder was not found in:\n\n{path}\n\n'
+                          'The location of the data folder was previously changed from the OpenLP\'s\n'
+                          'default location. If the data was stored on removable device, that device\nneeds to '
+                          'be made available.\n\n You may reset the data location '
+                                                'back to the default settings, or you can try to make the current '
+                                                'location available.\n\n'
+                                                'Do you want to reset the default data location?\n\n'
+                          'If you click "No" you can try to fix the the problem.\n'
+                          'If you click "Yes" the data will be reset to the default location. \n\n'
+                          'You will need to re-start OpenLP after this decision.').format(path=self.current_data_path),
                 QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
                 QtWidgets.QMessageBox.No)
             if answer == QtWidgets.QMessageBox.No:
                 log.info('User requested termination')
-                self.main_window.clean_up()
-                sys.exit()
-            # Set data location to default.
-            settings.remove('advanced/data path')
-            self.current_data_path = AppLocation.get_data_path()
-            log.warning('User requested data path set to default {path}'.format(path=self.current_data_path))
+                # self.main_window.clean_up() is causing tracebacks, not sure if it's required in some cases.
+                try:
+                    self.main_window.clean_up()
+                except:
+                    pass
+                sys.exit()
+            # If answer was yes, Set data location to default and shut down OpenLP.
+            if answer == QtWidgets.QMessageBox.Yes:
+                settings.remove('advanced/data path')
+                self.current_data_path = AppLocation.get_data_path()
+                log.warning('User requested data path set to default {path}'.format(path=self.current_data_path))
+                sys.exit()
         self.data_directory_label.setText(os.path.abspath(self.current_data_path))
         # Don't allow data directory move if running portable.
         if settings.value('advanced/is portable'):

=== modified file 'openlp/core/ui/lib/treewidgetwithdnd.py'
--- openlp/core/ui/lib/treewidgetwithdnd.py	2016-04-17 19:32:15 +0000
+++ openlp/core/ui/lib/treewidgetwithdnd.py	2016-10-04 12:42:26 +0000
@@ -26,7 +26,7 @@
 
 from PyQt5 import QtCore, QtGui, QtWidgets
 
-from openlp.core.common import Registry
+from openlp.core.common import Registry, is_win
 
 
 class TreeWidgetWithDnD(QtWidgets.QTreeWidget):
@@ -108,6 +108,11 @@
 
         :param event: Handle of the event pint passed
         """
+        # If we are on Windows, OpenLP window will not be set on top. For example, user can drag images to Library and
+        # the folder stays on top of the group creation box. This piece of code fixes this issue.
+        if is_win():
+            self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
+            self.setWindowState(QtCore.Qt.WindowNoState)
         if event.mimeData().hasUrls():
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2016-08-10 18:50:40 +0000
+++ openlp/core/ui/slidecontroller.py	2016-10-04 12:42:26 +0000
@@ -732,8 +732,10 @@
         # Reset the button
         self.play_slides_once.setChecked(False)
         self.play_slides_once.setIcon(build_icon(':/media/media_time.png'))
+        self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
         self.play_slides_loop.setChecked(False)
         self.play_slides_loop.setIcon(build_icon(':/media/media_time.png'))
+        self.play_slides_loop.setText(UiStrings().PlaySlidesInLoop)
         if item.is_text():
             if (Settings().value(self.main_window.songs_settings_section + '/display songbar') and
                     not self.song_menu.menu().isEmpty()):

=== modified file 'tests/functional/openlp_core_lib/test_lib.py'
--- tests/functional/openlp_core_lib/test_lib.py	2016-08-09 06:24:04 +0000
+++ tests/functional/openlp_core_lib/test_lib.py	2016-10-04 12:42:26 +0000
@@ -689,50 +689,38 @@
         """
         Test the create_separated_list function with a list consisting of only one entry
         """
-        with patch('openlp.core.lib.Qt') as mocked_qt:
-            # GIVEN: A list with a string and the mocked Qt module.
-            mocked_qt.PYQT_VERSION_STR = '4.8'
-            mocked_qt.qVersion.return_value = '4.7'
-            string_list = ['Author 1']
-
-            # WHEN: We get a string build from the entries it the list and a separator.
-            string_result = create_separated_list(string_list)
-
-            # THEN: We should have "Author 1"
-            assert string_result == 'Author 1', 'The string should be u\'Author 1\'.'
+        # GIVEN: A list with a string.
+        string_list = ['Author 1']
+
+        # WHEN: We get a string build from the entries it the list and a separator.
+        string_result = create_separated_list(string_list)
+
+        # THEN: We should have "Author 1"
+        assert string_result == 'Author 1', 'The string should be u\'Author 1\'.'
 
     def test_create_separated_list_with_two_items(self):
         """
         Test the create_separated_list function with a list of two entries
         """
-        with patch('openlp.core.lib.Qt') as mocked_qt, patch('openlp.core.lib.translate') as mocked_translate:
-            # GIVEN: A list of strings and the mocked Qt module.
-            mocked_qt.PYQT_VERSION_STR = '4.8'
-            mocked_qt.qVersion.return_value = '4.7'
-            mocked_translate.return_value = '%s and %s'
-            string_list = ['Author 1', 'Author 2']
-
-            # WHEN: We get a string build from the entries it the list and a seperator.
-            string_result = create_separated_list(string_list)
-
-            # THEN: We should have "Author 1 and Author 2"
-            assert string_result == 'Author 1 and Author 2', 'The string should be u\'Author 1 and Author 2\'.'
+        # GIVEN: A list with two strings.
+        string_list = ['Author 1', 'Author 2']
+
+        # WHEN: We get a string build from the entries it the list and a seperator.
+        string_result = create_separated_list(string_list)
+
+        # THEN: We should have "Author 1 and Author 2"
+        assert string_result == 'Author 1 and Author 2', 'The string should be u\'Author 1 and Author 2\'.'
 
     def test_create_separated_list_with_three_items(self):
         """
         Test the create_separated_list function with a list of three items
         """
-        with patch('openlp.core.lib.Qt') as mocked_qt, patch('openlp.core.lib.translate') as mocked_translate:
-            # GIVEN: A list with a string and the mocked Qt module.
-            mocked_qt.PYQT_VERSION_STR = '4.8'
-            mocked_qt.qVersion.return_value = '4.7'
-            # Always return the untranslated string.
-            mocked_translate.side_effect = lambda module, string_to_translate, comment: string_to_translate
-            string_list = ['Author 1', 'Author 2', 'Author 3']
-
-            # WHEN: We get a string build from the entries it the list and a seperator.
-            string_result = create_separated_list(string_list)
-
-            # THEN: We should have "Author 1, Author 2, and Author 3"
-            assert string_result == 'Author 1, Author 2, and Author 3', 'The string should be u\'Author 1, ' \
-                'Author 2, and Author 3\'.'
+        # GIVEN: A list with three strings.
+        string_list = ['Author 1', 'Author 2', 'Author 3']
+
+        # WHEN: We get a string build from the entries it the list and a seperator.
+        string_result = create_separated_list(string_list)
+
+        # THEN: We should have "Author 1, Author 2, and Author 3"
+        assert string_result == 'Author 1, Author 2, and Author 3', 'The string should be u\'Author 1, ' \
+            'Author 2, and Author 3\'.'

=== modified file 'tests/functional/openlp_plugins/bibles/test_swordimport.py'
--- tests/functional/openlp_plugins/bibles/test_swordimport.py	2016-09-04 21:16:43 +0000
+++ tests/functional/openlp_plugins/bibles/test_swordimport.py	2016-10-04 12:42:26 +0000
@@ -70,8 +70,7 @@
 
     @patch('openlp.plugins.bibles.lib.importers.sword.SwordBible.application')
     @patch('openlp.plugins.bibles.lib.importers.sword.modules')
-    @patch('openlp.core.common.languages')
-    def test_simple_import(self, mocked_languages, mocked_pysword_modules, mocked_application):
+    def test_simple_import(self, mocked_pysword_modules, mocked_application):
         """
         Test that a simple SWORD import works
         """
@@ -88,7 +87,7 @@
         importer.create_verse = MagicMock()
         importer.create_book = MagicMock()
         importer.session = MagicMock()
-        mocked_languages.get_language.return_value = 'Danish'
+        importer.get_language = MagicMock(return_value='Danish')
         mocked_bible = MagicMock()
         mocked_genesis = MagicMock()
         mocked_genesis.name = 'Genesis'


Follow ups