forked from openlp/openlp
Fix a problem with loading Qt's translation files
Add this to your merge proposal: -------------------------------- lp:~raoul-snyman/openlp/fix-translations-2.4 (revision 2680) [SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1943/ [SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1854/ [SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1795/ [SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1521/ [SUCCESS] https://ci.openlp.io/job/Branch-04b-Windo... bzr-revno: 2679
This commit is contained in:
commit
6ca65fd758
@ -8,3 +8,4 @@ OpenLP 2.4.6
|
|||||||
* Fix opening the data folder (KDE thought the old way was an SMB share)
|
* Fix opening the data folder (KDE thought the old way was an SMB share)
|
||||||
* 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
|
||||||
|
* Fix a problem with loading Qt's translation files, bug #1676163
|
||||||
|
@ -426,13 +426,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_translator(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))
|
||||||
|
@ -24,7 +24,6 @@ The :mod:`languagemanager` module provides all the translation settings and lang
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
|
|
||||||
@ -56,9 +55,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():
|
||||||
@ -69,7 +71,7 @@ class LanguageManager(object):
|
|||||||
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_') or file_.startswith('qtbase_')]
|
||||||
return list(map(trans_dir.filePath, file_names))
|
return list(map(trans_dir.filePath, file_names))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -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_
|
||||||
@ -167,7 +166,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):
|
||||||
"""
|
"""
|
||||||
@ -177,7 +176,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):
|
||||||
"""
|
"""
|
||||||
@ -188,9 +187,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.
|
||||||
|
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
@ -291,3 +292,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
|
||||||
|
Loading…
Reference in New Issue
Block a user