Merge lp:~raoul-snyman/openlp/fix-translations into lp:openlp

Proposed by Raoul Snyman
Status: Merged
Merged at revision: 2729
Proposed branch: lp:~raoul-snyman/openlp/fix-translations
Merge into: lp:openlp
Diff against target: 265 lines (+148/-17)
5 files modified
CHANGELOG.rst (+1/-0)
openlp/core/__init__.py (+6/-7)
openlp/core/common/languagemanager.py (+7/-4)
openlp/plugins/songs/forms/songmaintenanceform.py (+4/-5)
tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py (+130/-1)
To merge this branch: bzr merge lp:~raoul-snyman/openlp/fix-translations
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Tomas Groth Approve
Review via email: mp+321132@code.launchpad.net

Commit message

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

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) :
review: Approve
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CHANGELOG.rst'
2--- CHANGELOG.rst 2017-03-23 05:08:14 +0000
3+++ CHANGELOG.rst 2017-03-28 01:20:30 +0000
4@@ -9,3 +9,4 @@
5 * Fix a problem with the new QMediaPlayer not controlling the playlist anymore
6 * Added importing of author types to the OpenLP 2 song importer
7 * Refactored the merge script and gave it some options
8+* Fix a problem with loading Qt's translation files, bug #1676163
9
10=== modified file 'openlp/core/__init__.py'
11--- openlp/core/__init__.py 2017-03-10 05:42:38 +0000
12+++ openlp/core/__init__.py 2017-03-28 01:20:30 +0000
13@@ -428,13 +428,12 @@
14 sys.exit()
15 # i18n Set Language
16 language = LanguageManager.get_language()
17- application_translator, default_translator = LanguageManager.get_translator(language)
18- if not application_translator.isEmpty():
19- application.installTranslator(application_translator)
20- if not default_translator.isEmpty():
21- application.installTranslator(default_translator)
22- else:
23- log.debug('Could not find default_translator.')
24+ translators = LanguageManager.get_translators(language)
25+ for translator in translators:
26+ if not translator.isEmpty():
27+ application.installTranslator(translator)
28+ if not translators:
29+ log.debug('Could not find translators.')
30 if args and not args.no_error_form:
31 sys.excepthook = application.hook_exception
32 sys.exit(application.run(qt_args))
33
34=== modified file 'openlp/core/common/languagemanager.py'
35--- openlp/core/common/languagemanager.py 2016-12-31 11:01:36 +0000
36+++ openlp/core/common/languagemanager.py 2017-03-28 01:20:30 +0000
37@@ -45,7 +45,7 @@
38 auto_language = False
39
40 @staticmethod
41- def get_translator(language):
42+ def get_translators(language):
43 """
44 Set up a translator to use in this instance of OpenLP
45
46@@ -59,9 +59,12 @@
47 # A translator for buttons and other default strings provided by Qt.
48 if not is_win() and not is_macosx():
49 lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
50+ # As of Qt5, the core translations come in 2 files per language
51 default_translator = QtCore.QTranslator()
52 default_translator.load('qt_%s' % language, lang_path)
53- return app_translator, default_translator
54+ base_translator = QtCore.QTranslator()
55+ base_translator.load('qtbase_%s' % language, lang_path)
56+ return app_translator, default_translator, base_translator
57
58 @staticmethod
59 def find_qm_files():
60@@ -71,8 +74,8 @@
61 log.debug('Translation files: {files}'.format(files=AppLocation.get_directory(AppLocation.LanguageDir)))
62 trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir))
63 file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
64- # Remove qm files from the list which start with "qt_".
65- file_names = [file_ for file_ in file_names if not file_.startswith('qt_')]
66+ # Remove qm files from the list which start with "qt".
67+ file_names = [file_ for file_ in file_names if not file_.startswith('qt')]
68 return list(map(trans_dir.filePath, file_names))
69
70 @staticmethod
71
72=== modified file 'openlp/plugins/songs/forms/songmaintenanceform.py'
73--- openlp/plugins/songs/forms/songmaintenanceform.py 2016-12-31 11:01:36 +0000
74+++ openlp/plugins/songs/forms/songmaintenanceform.py 2017-03-28 01:20:30 +0000
75@@ -20,7 +20,6 @@
76 # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
77 ###############################################################################
78 import logging
79-import os
80
81 from PyQt5 import QtCore, QtWidgets
82 from sqlalchemy.sql import and_
83@@ -184,7 +183,7 @@
84 Author.display_name == new_author.display_name
85 )
86 )
87- return self.__check_object_exists(authors, new_author, edit)
88+ return self._check_object_exists(authors, new_author, edit)
89
90 def check_topic_exists(self, new_topic, edit=False):
91 """
92@@ -194,7 +193,7 @@
93 :param edit: Are we editing the song?
94 """
95 topics = self.manager.get_all_objects(Topic, Topic.name == new_topic.name)
96- return self.__check_object_exists(topics, new_topic, edit)
97+ return self._check_object_exists(topics, new_topic, edit)
98
99 def check_song_book_exists(self, new_book, edit=False):
100 """
101@@ -205,9 +204,9 @@
102 """
103 books = self.manager.get_all_objects(
104 Book, and_(Book.name == new_book.name, Book.publisher == new_book.publisher))
105- return self.__check_object_exists(books, new_book, edit)
106+ return self._check_object_exists(books, new_book, edit)
107
108- def __check_object_exists(self, existing_objects, new_object, edit):
109+ def _check_object_exists(self, existing_objects, new_object, edit):
110 """
111 Utility method to check for an existing object.
112
113
114=== modified file 'tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py'
115--- tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py 2017-03-23 04:43:13 +0000
116+++ tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py 2017-03-28 01:20:30 +0000
117@@ -25,7 +25,7 @@
118 from unittest import TestCase
119 from unittest.mock import MagicMock, patch, call
120
121-from PyQt5 import QtCore, QtTest, QtWidgets
122+from PyQt5 import QtCore, QtWidgets
123
124 from openlp.core.common import Registry, UiStrings
125 from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
126@@ -89,6 +89,7 @@
127 mocked_reset_song_books.assert_called_once_with()
128 mocked_type_list_widget.setFocus.assert_called_once_with()
129 mocked_exec.assert_called_once_with(self.form)
130+ assert result is True
131
132 def test_get_current_item_id_no_item(self):
133 """
134@@ -290,3 +291,131 @@
135 MockedQListWidgetItem.assert_called_once_with('Hymnal (Hymns and Psalms, Inc.)')
136 mocked_song_book_item.setData.assert_called_once_with(QtCore.Qt.UserRole, 1)
137 mocked_song_book_list_widget.addItem.assert_called_once_with(mocked_song_book_item)
138+
139+ @patch('openlp.plugins.songs.forms.songmaintenanceform.and_')
140+ @patch('openlp.plugins.songs.forms.songmaintenanceform.Author')
141+ def test_check_author_exists(self, MockedAuthor, mocked_and):
142+ """
143+ Test the check_author_exists() method
144+ """
145+ # GIVEN: A bunch of mocked out stuff
146+ MockedAuthor.first_name = 'John'
147+ MockedAuthor.last_name = 'Newton'
148+ MockedAuthor.display_name = 'John Newton'
149+ mocked_new_author = MagicMock()
150+ mocked_new_author.first_name = 'John'
151+ mocked_new_author.last_name = 'Newton'
152+ mocked_new_author.display_name = 'John Newton'
153+ mocked_and.return_value = True
154+ mocked_authors = [MagicMock(), MagicMock()]
155+ self.mocked_manager.get_all_objects.return_value = mocked_authors
156+
157+ # WHEN: check_author_exists() is called
158+ with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
159+ mocked_check_object_exists.return_value = True
160+ result = self.form.check_author_exists(mocked_new_author, edit=True)
161+
162+ # THEN: The correct result is returned
163+ mocked_and.assert_called_once_with(True, True, True)
164+ self.mocked_manager.get_all_objects.assert_called_once_with(MockedAuthor, True)
165+ mocked_check_object_exists.assert_called_once_with(mocked_authors, mocked_new_author, True)
166+ assert result is True
167+
168+ @patch('openlp.plugins.songs.forms.songmaintenanceform.Topic')
169+ def test_check_topic_exists(self, MockedTopic):
170+ """
171+ Test the check_topic_exists() method
172+ """
173+ # GIVEN: Some mocked stuff
174+ MockedTopic.name = 'Grace'
175+ mocked_new_topic = MagicMock()
176+ mocked_new_topic.name = 'Grace'
177+ mocked_topics = [MagicMock(), MagicMock()]
178+ self.mocked_manager.get_all_objects.return_value = mocked_topics
179+
180+ # WHEN: check_topic_exists() is run
181+ with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
182+ mocked_check_object_exists.return_value = True
183+ result = self.form.check_topic_exists(mocked_new_topic, True)
184+
185+ # THEN: The correct things should have been called
186+ self.mocked_manager.get_all_objects.assert_called_once_with(MockedTopic, True)
187+ mocked_check_object_exists.assert_called_once_with(mocked_topics, mocked_new_topic, True)
188+ assert result is True
189+
190+ @patch('openlp.plugins.songs.forms.songmaintenanceform.and_')
191+ @patch('openlp.plugins.songs.forms.songmaintenanceform.Book')
192+ def test_check_song_book_exists(self, MockedBook, mocked_and):
193+ """
194+ Test the check_song_book_exists() method
195+ """
196+ # GIVEN: Some mocked stuff
197+ MockedBook.name = 'Hymns'
198+ MockedBook.publisher = 'Christian Songs'
199+ mocked_new_book = MagicMock()
200+ mocked_new_book.name = 'Hymns'
201+ mocked_new_book.publisher = 'Christian Songs'
202+ mocked_and.return_value = True
203+ mocked_books = [MagicMock(), MagicMock()]
204+ self.mocked_manager.get_all_objects.return_value = mocked_books
205+
206+ # WHEN: check_book_exists() is run
207+ with patch.object(self.form, '_check_object_exists') as mocked_check_object_exists:
208+ mocked_check_object_exists.return_value = True
209+ result = self.form.check_song_book_exists(mocked_new_book, True)
210+
211+ # THEN: The correct things should have been called
212+ mocked_and.assert_called_once_with(True, True)
213+ self.mocked_manager.get_all_objects.assert_called_once_with(MockedBook, True)
214+ mocked_check_object_exists.assert_called_once_with(mocked_books, mocked_new_book, True)
215+ assert result is True
216+
217+ def test_check_object_exists_no_existing_objects(self):
218+ """
219+ Test the _check_object_exists() method when there are no existing objects
220+ """
221+ # GIVEN: A SongMaintenanceForm instance
222+ # WHEN: _check_object_exists() is called without existing objects
223+ result = self.form._check_object_exists([], None, False)
224+
225+ # THEN: The result should be True
226+ assert result is True
227+
228+ def test_check_object_exists_without_edit(self):
229+ """
230+ Test the _check_object_exists() method when edit is false
231+ """
232+ # GIVEN: A SongMaintenanceForm instance
233+ # WHEN: _check_object_exists() is called with edit set to false
234+ result = self.form._check_object_exists([MagicMock()], None, False)
235+
236+ # THEN: The result should be False
237+ assert result is False
238+
239+ def test_check_object_exists_not_found(self):
240+ """
241+ Test the _check_object_exists() method when the object is not found
242+ """
243+ # GIVEN: A SongMaintenanceForm instance and some mocked objects
244+ mocked_existing_objects = [MagicMock(id=1)]
245+ mocked_new_object = MagicMock(id=2)
246+
247+ # WHEN: _check_object_exists() is called with edit set to false
248+ result = self.form._check_object_exists(mocked_existing_objects, mocked_new_object, True)
249+
250+ # THEN: The result should be False
251+ assert result is False
252+
253+ def test_check_object_exists(self):
254+ """
255+ Test the _check_object_exists() method
256+ """
257+ # GIVEN: A SongMaintenanceForm instance and some mocked objects
258+ mocked_existing_objects = [MagicMock(id=1)]
259+ mocked_new_object = MagicMock(id=1)
260+
261+ # WHEN: _check_object_exists() is called with edit set to false
262+ result = self.form._check_object_exists(mocked_existing_objects, mocked_new_object, True)
263+
264+ # THEN: The result should be False
265+ assert result is True