Fix a problem with loading Qt's translation files, bug #1676163

Fixes: https://launchpad.net/bugs/1676163
This commit is contained in:
Raoul Snyman 2017-03-27 17:36:54 -07:00
parent 4183f186ce
commit 815c32b87f
5 changed files with 148 additions and 17 deletions

View File

@ -9,3 +9,4 @@ OpenLP 2.5.1
* Fix a problem with the new QMediaPlayer not controlling the playlist anymore * Fix a problem with the new QMediaPlayer not controlling the playlist anymore
* Added importing of author types to the OpenLP 2 song importer * Added importing of author types to the OpenLP 2 song importer
* Refactored the merge script and gave it some options * Refactored the merge script and gave it some options
* Fix a problem with loading Qt's translation files, bug #1676163

View File

@ -428,13 +428,12 @@ def main(args=None):
sys.exit() sys.exit()
# i18n Set Language # i18n Set Language
language = LanguageManager.get_language() language = LanguageManager.get_language()
application_translator, default_translator = LanguageManager.get_translator(language) translators = LanguageManager.get_translators(language)
if not application_translator.isEmpty(): for translator in translators:
application.installTranslator(application_translator) if not translator.isEmpty():
if not default_translator.isEmpty(): application.installTranslator(translator)
application.installTranslator(default_translator) if not translators:
else: log.debug('Could not find translators.')
log.debug('Could not find default_translator.')
if args and not args.no_error_form: if args and not args.no_error_form:
sys.excepthook = application.hook_exception sys.excepthook = application.hook_exception
sys.exit(application.run(qt_args)) sys.exit(application.run(qt_args))

View File

@ -45,7 +45,7 @@ class LanguageManager(object):
auto_language = False auto_language = False
@staticmethod @staticmethod
def get_translator(language): def get_translators(language):
""" """
Set up a translator to use in this instance of OpenLP Set up a translator to use in this instance of OpenLP
@ -59,9 +59,12 @@ class LanguageManager(object):
# A translator for buttons and other default strings provided by Qt. # A translator for buttons and other default strings provided by Qt.
if not is_win() and not is_macosx(): if not is_win() and not is_macosx():
lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath) lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
# As of Qt5, the core translations come in 2 files per language
default_translator = QtCore.QTranslator() default_translator = QtCore.QTranslator()
default_translator.load('qt_%s' % language, lang_path) default_translator.load('qt_%s' % language, lang_path)
return app_translator, default_translator base_translator = QtCore.QTranslator()
base_translator.load('qtbase_%s' % language, lang_path)
return app_translator, default_translator, base_translator
@staticmethod @staticmethod
def find_qm_files(): def find_qm_files():
@ -71,8 +74,8 @@ class LanguageManager(object):
log.debug('Translation files: {files}'.format(files=AppLocation.get_directory(AppLocation.LanguageDir))) log.debug('Translation files: {files}'.format(files=AppLocation.get_directory(AppLocation.LanguageDir)))
trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir)) trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir))
file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name) file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
# Remove qm files from the list which start with "qt_". # Remove qm files from the list which start with "qt".
file_names = [file_ for file_ in file_names if not file_.startswith('qt_')] file_names = [file_ for file_ in file_names if not file_.startswith('qt')]
return list(map(trans_dir.filePath, file_names)) return list(map(trans_dir.filePath, file_names))
@staticmethod @staticmethod

View File

@ -20,7 +20,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import logging import logging
import os
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
from sqlalchemy.sql import and_ from sqlalchemy.sql import and_
@ -184,7 +183,7 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
Author.display_name == new_author.display_name Author.display_name == new_author.display_name
) )
) )
return self.__check_object_exists(authors, new_author, edit) return self._check_object_exists(authors, new_author, edit)
def check_topic_exists(self, new_topic, edit=False): def check_topic_exists(self, new_topic, edit=False):
""" """
@ -194,7 +193,7 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
:param edit: Are we editing the song? :param edit: Are we editing the song?
""" """
topics = self.manager.get_all_objects(Topic, Topic.name == new_topic.name) topics = self.manager.get_all_objects(Topic, Topic.name == new_topic.name)
return self.__check_object_exists(topics, new_topic, edit) return self._check_object_exists(topics, new_topic, edit)
def check_song_book_exists(self, new_book, edit=False): def check_song_book_exists(self, new_book, edit=False):
""" """
@ -205,9 +204,9 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
""" """
books = self.manager.get_all_objects( books = self.manager.get_all_objects(
Book, and_(Book.name == new_book.name, Book.publisher == new_book.publisher)) Book, and_(Book.name == new_book.name, Book.publisher == new_book.publisher))
return self.__check_object_exists(books, new_book, edit) return self._check_object_exists(books, new_book, edit)
def __check_object_exists(self, existing_objects, new_object, edit): def _check_object_exists(self, existing_objects, new_object, edit):
""" """
Utility method to check for an existing object. Utility method to check for an existing object.

View File

@ -25,7 +25,7 @@ Package to test the openlp.plugins.songs.forms.songmaintenanceform package.
from unittest import TestCase from unittest import TestCase
from unittest.mock import MagicMock, patch, call from unittest.mock import MagicMock, patch, call
from PyQt5 import QtCore, QtTest, QtWidgets from PyQt5 import QtCore, QtWidgets
from openlp.core.common import Registry, UiStrings from openlp.core.common import Registry, UiStrings
from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
@ -89,6 +89,7 @@ class TestSongMaintenanceForm(TestCase, TestMixin):
mocked_reset_song_books.assert_called_once_with() mocked_reset_song_books.assert_called_once_with()
mocked_type_list_widget.setFocus.assert_called_once_with() mocked_type_list_widget.setFocus.assert_called_once_with()
mocked_exec.assert_called_once_with(self.form) mocked_exec.assert_called_once_with(self.form)
assert result is True
def test_get_current_item_id_no_item(self): def test_get_current_item_id_no_item(self):
""" """
@ -290,3 +291,131 @@ class TestSongMaintenanceForm(TestCase, TestMixin):
MockedQListWidgetItem.assert_called_once_with('Hymnal (Hymns and Psalms, Inc.)') MockedQListWidgetItem.assert_called_once_with('Hymnal (Hymns and Psalms, Inc.)')
mocked_song_book_item.setData.assert_called_once_with(QtCore.Qt.UserRole, 1) mocked_song_book_item.setData.assert_called_once_with(QtCore.Qt.UserRole, 1)
mocked_song_book_list_widget.addItem.assert_called_once_with(mocked_song_book_item) mocked_song_book_list_widget.addItem.assert_called_once_with(mocked_song_book_item)
@patch('openlp.plugins.songs.forms.songmaintenanceform.and_')
@patch('openlp.plugins.songs.forms.songmaintenanceform.Author')
def test_check_author_exists(self, MockedAuthor, mocked_and):
"""
Test the check_author_exists() method
"""
# GIVEN: A bunch of mocked out stuff
MockedAuthor.first_name = 'John'
MockedAuthor.last_name = 'Newton'
MockedAuthor.display_name = 'John Newton'
mocked_new_author = MagicMock()
mocked_new_author.first_name = 'John'
mocked_new_author.last_name = 'Newton'
mocked_new_author.display_name = 'John Newton'
mocked_and.return_value = True
mocked_authors = [MagicMock(), MagicMock()]
self.mocked_manager.get_all_objects.return_value = mocked_authors
# WHEN: check_author_exists() is called
with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
mocked_check_object_exists.return_value = True
result = self.form.check_author_exists(mocked_new_author, edit=True)
# THEN: The correct result is returned
mocked_and.assert_called_once_with(True, True, True)
self.mocked_manager.get_all_objects.assert_called_once_with(MockedAuthor, True)
mocked_check_object_exists.assert_called_once_with(mocked_authors, mocked_new_author, True)
assert result is True
@patch('openlp.plugins.songs.forms.songmaintenanceform.Topic')
def test_check_topic_exists(self, MockedTopic):
"""
Test the check_topic_exists() method
"""
# GIVEN: Some mocked stuff
MockedTopic.name = 'Grace'
mocked_new_topic = MagicMock()
mocked_new_topic.name = 'Grace'
mocked_topics = [MagicMock(), MagicMock()]
self.mocked_manager.get_all_objects.return_value = mocked_topics
# WHEN: check_topic_exists() is run
with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
mocked_check_object_exists.return_value = True
result = self.form.check_topic_exists(mocked_new_topic, True)
# THEN: The correct things should have been called
self.mocked_manager.get_all_objects.assert_called_once_with(MockedTopic, True)
mocked_check_object_exists.assert_called_once_with(mocked_topics, mocked_new_topic, True)
assert result is True
@patch('openlp.plugins.songs.forms.songmaintenanceform.and_')
@patch('openlp.plugins.songs.forms.songmaintenanceform.Book')
def test_check_song_book_exists(self, MockedBook, mocked_and):
"""
Test the check_song_book_exists() method
"""
# GIVEN: Some mocked stuff
MockedBook.name = 'Hymns'
MockedBook.publisher = 'Christian Songs'
mocked_new_book = MagicMock()
mocked_new_book.name = 'Hymns'
mocked_new_book.publisher = 'Christian Songs'
mocked_and.return_value = True
mocked_books = [MagicMock(), MagicMock()]
self.mocked_manager.get_all_objects.return_value = mocked_books
# WHEN: check_book_exists() is run
with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
mocked_check_object_exists.return_value = True
result = self.form.check_song_book_exists(mocked_new_book, True)
# THEN: The correct things should have been called
mocked_and.assert_called_once_with(True, True)
self.mocked_manager.get_all_objects.assert_called_once_with(MockedBook, True)
mocked_check_object_exists.assert_called_once_with(mocked_books, mocked_new_book, True)
assert result is True
def test_check_object_exists_no_existing_objects(self):
"""
Test the _check_object_exists() method when there are no existing objects
"""
# GIVEN: A SongMaintenanceForm instance
# WHEN: _check_object_exists() is called without existing objects
result = self.form._check_object_exists([], None, False)
# THEN: The result should be True
assert result is True
def test_check_object_exists_without_edit(self):
"""
Test the _check_object_exists() method when edit is false
"""
# GIVEN: A SongMaintenanceForm instance
# WHEN: _check_object_exists() is called with edit set to false
result = self.form._check_object_exists([MagicMock()], None, False)
# THEN: The result should be False
assert result is False
def test_check_object_exists_not_found(self):
"""
Test the _check_object_exists() method when the object is not found
"""
# GIVEN: A SongMaintenanceForm instance and some mocked objects
mocked_existing_objects = [MagicMock(id=1)]
mocked_new_object = MagicMock(id=2)
# WHEN: _check_object_exists() is called with edit set to false
result = self.form._check_object_exists(mocked_existing_objects, mocked_new_object, True)
# THEN: The result should be False
assert result is False
def test_check_object_exists(self):
"""
Test the _check_object_exists() method
"""
# GIVEN: A SongMaintenanceForm instance and some mocked objects
mocked_existing_objects = [MagicMock(id=1)]
mocked_new_object = MagicMock(id=1)
# WHEN: _check_object_exists() is called with edit set to false
result = self.form._check_object_exists(mocked_existing_objects, mocked_new_object, True)
# THEN: The result should be False
assert result is True