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

Fixes: https://launchpad.net/bugs/1676163
master
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
* Added importing of author types to the OpenLP 2 song importer
* 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()
# i18n Set Language
language = LanguageManager.get_language()
application_translator, default_translator = LanguageManager.get_translator(language)
if not application_translator.isEmpty():
application.installTranslator(application_translator)
if not default_translator.isEmpty():
application.installTranslator(default_translator)
else:
log.debug('Could not find default_translator.')
translators = LanguageManager.get_translators(language)
for translator in translators:
if not translator.isEmpty():
application.installTranslator(translator)
if not translators:
log.debug('Could not find translators.')
if args and not args.no_error_form:
sys.excepthook = application.hook_exception
sys.exit(application.run(qt_args))

View File

@ -45,7 +45,7 @@ class LanguageManager(object):
auto_language = False
@staticmethod
def get_translator(language):
def get_translators(language):
"""
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.
if not is_win() and not is_macosx():
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.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
def find_qm_files():
@ -71,8 +74,8 @@ class LanguageManager(object):
log.debug('Translation files: {files}'.format(files=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)
# Remove qm files from the list which start with "qt_".
file_names = [file_ for file_ in file_names if not file_.startswith('qt_')]
# Remove qm files from the list which start with "qt".
file_names = [file_ for file_ in file_names if not file_.startswith('qt')]
return list(map(trans_dir.filePath, file_names))
@staticmethod

View File

@ -20,7 +20,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
from PyQt5 import QtCore, QtWidgets
from sqlalchemy.sql import and_
@ -184,7 +183,7 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
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):
"""
@ -194,7 +193,7 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
:param edit: Are we editing the song?
"""
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):
"""
@ -205,9 +204,9 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
"""
books = self.manager.get_all_objects(
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.

View File

@ -25,7 +25,7 @@ Package to test the openlp.plugins.songs.forms.songmaintenanceform package.
from unittest import TestCase
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.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
@ -89,6 +89,7 @@ class TestSongMaintenanceForm(TestCase, TestMixin):
mocked_reset_song_books.assert_called_once_with()
mocked_type_list_widget.setFocus.assert_called_once_with()
mocked_exec.assert_called_once_with(self.form)
assert result is True
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.)')
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)
@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