Merge lp:~tomasgroth/openlp/bugfixes19 into lp:openlp

Proposed by Tomas Groth
Status: Merged
Approved by: Tim Bentley
Approved revision: 2535
Merged at revision: 2529
Proposed branch: lp:~tomasgroth/openlp/bugfixes19
Merge into: lp:openlp
Diff against target: 290 lines (+76/-27)
8 files modified
openlp/core/common/uistrings.py (+2/-0)
openlp/core/lib/listwidgetwithdnd.py (+1/-1)
openlp/core/ui/printserviceform.py (+3/-1)
openlp/plugins/bibles/lib/mediaitem.py (+1/-1)
openlp/plugins/bibles/lib/versereferencelist.py (+21/-9)
openlp/plugins/images/lib/mediaitem.py (+2/-0)
openlp/plugins/media/lib/mediaitem.py (+6/-1)
tests/functional/openlp_plugins/images/test_lib.py (+40/-14)
To merge this branch: bzr merge lp:~tomasgroth/openlp/bugfixes19
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Raoul Snyman Approve
Review via email: mp+257184@code.launchpad.net

Description of the change

Delete image thumbnails when the image is removed. Fixes bug 1446491.
Make sure we always add a blank line between verses. Fixes bug 1439311.
Normalize file path to OS standard after drag-and-drop. Fixes bug 1440571.
Make the way we display verse ranges consistent and make use of localized or custom separators. Fixes bug 1081807
Disable button for replacing live background if the webkit player is not available.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) wrote :

lp:~tomasgroth/openlp/bugfixes19 (revision 2535)
[SUCCESS] https//ci.openlp.io/job/Branch-01-Pull/1005/
[SUCCESS] https//ci.openlp.io/job/Branch-02-Functional-Tests/928/
[SUCCESS] https//ci.openlp.io/job/Branch-03-Interface-Tests/870/
[SUCCESS] https//ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/760/
[SUCCESS] https//ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/358/
[SUCCESS] https//ci.openlp.io/job/Branch-05a-Code_Analysis/491/
[SUCCESS] https//ci.openlp.io/job/Branch-05b-Test_Coverage/362/

Revision history for this message
Raoul Snyman (raoul-snyman) :
review: Approve
Revision history for this message
Tim Bentley (trb143) wrote :

Approved

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/common/uistrings.py'
--- openlp/core/common/uistrings.py 2015-02-09 20:49:24 +0000
+++ openlp/core/common/uistrings.py 2015-04-22 21:11:34 +0000
@@ -121,6 +121,8 @@
121 self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')121 self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')
122 self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')122 self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
123 self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')123 self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
124 self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available on this '
125 'platform in this version of OpenLP.')
124 self.ResetBG = translate('OpenLP.Ui', 'Reset Background')126 self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
125 self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')127 self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
126 self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')128 self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
127129
=== modified file 'openlp/core/lib/listwidgetwithdnd.py'
--- openlp/core/lib/listwidgetwithdnd.py 2015-01-18 13:39:21 +0000
+++ openlp/core/lib/listwidgetwithdnd.py 2015-04-22 21:11:34 +0000
@@ -95,7 +95,7 @@
95 event.accept()95 event.accept()
96 files = []96 files = []
97 for url in event.mimeData().urls():97 for url in event.mimeData().urls():
98 local_file = url.toLocalFile()98 local_file = os.path.normpath(url.toLocalFile())
99 if os.path.isfile(local_file):99 if os.path.isfile(local_file):
100 files.append(local_file)100 files.append(local_file)
101 elif os.path.isdir(local_file):101 elif os.path.isdir(local_file):
102102
=== modified file 'openlp/core/ui/printserviceform.py'
--- openlp/core/ui/printserviceform.py 2015-01-18 13:39:21 +0000
+++ openlp/core/ui/printserviceform.py 2015-04-22 21:11:34 +0000
@@ -193,13 +193,15 @@
193 # Add the text of the service item.193 # Add the text of the service item.
194 if item.is_text():194 if item.is_text():
195 verse_def = None195 verse_def = None
196 verse_html = None
196 for slide in item.get_frames():197 for slide in item.get_frames():
197 if not verse_def or verse_def != slide['verseTag']:198 if not verse_def or verse_def != slide['verseTag'] or verse_html == slide['html']:
198 text_div = self._add_element('div', parent=div, classId='itemText')199 text_div = self._add_element('div', parent=div, classId='itemText')
199 else:200 else:
200 self._add_element('br', parent=text_div)201 self._add_element('br', parent=text_div)
201 self._add_element('span', slide['html'], text_div)202 self._add_element('span', slide['html'], text_div)
202 verse_def = slide['verseTag']203 verse_def = slide['verseTag']
204 verse_html = slide['html']
203 # Break the page before the div element.205 # Break the page before the div element.
204 if index != 0 and self.page_break_after_text.isChecked():206 if index != 0 and self.page_break_after_text.isChecked():
205 div.set('class', 'item newPage')207 div.set('class', 'item newPage')
206208
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py 2015-04-22 21:11:34 +0000
@@ -849,7 +849,7 @@
849 service_item.add_capability(ItemCapabilities.CanWordSplit)849 service_item.add_capability(ItemCapabilities.CanWordSplit)
850 service_item.add_capability(ItemCapabilities.CanEditTitle)850 service_item.add_capability(ItemCapabilities.CanEditTitle)
851 # Service Item: Title851 # Service Item: Title
852 service_item.title = create_separated_list(raw_title)852 service_item.title = '%s %s' % (verses.format_verses(), verses.format_versions())
853 # Service Item: Theme853 # Service Item: Theme
854 if not self.settings.bible_theme:854 if not self.settings.bible_theme:
855 service_item.theme = None855 service_item.theme = None
856856
=== modified file 'openlp/plugins/bibles/lib/versereferencelist.py'
--- openlp/plugins/bibles/lib/versereferencelist.py 2015-02-13 20:19:05 +0000
+++ openlp/plugins/bibles/lib/versereferencelist.py 2015-04-22 21:11:34 +0000
@@ -20,6 +20,8 @@
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
2222
23from openlp.plugins.bibles.lib import get_reference_separator
24
2325
24class VerseReferenceList(object):26class VerseReferenceList(object):
25 """27 """
@@ -53,29 +55,39 @@
53 self.version_list.append({'version': version, 'copyright': copyright, 'permission': permission})55 self.version_list.append({'version': version, 'copyright': copyright, 'permission': permission})
5456
55 def format_verses(self):57 def format_verses(self):
58 verse_sep = get_reference_separator('sep_v_display')
59 range_sep = get_reference_separator('sep_r_display')
60 list_sep = get_reference_separator('sep_l_display')
56 result = ''61 result = ''
57 for index, verse in enumerate(self.verse_list):62 for index, verse in enumerate(self.verse_list):
58 if index == 0:63 if index == 0:
59 result = '%s %s:%s' % (verse['book'], verse['chapter'], verse['start'])64 result = '%s %s%s%s' % (verse['book'], verse['chapter'], verse_sep, verse['start'])
60 if verse['start'] != verse['end']:65 if verse['start'] != verse['end']:
61 result = '%s-%s' % (result, verse['end'])66 result = '%s%s%s' % (result, range_sep, verse['end'])
62 continue67 continue
63 prev = index - 168 prev = index - 1
64 if self.verse_list[prev]['version'] != verse['version']:69 if self.verse_list[prev]['version'] != verse['version']:
65 result = '%s (%s)' % (result, self.verse_list[prev]['version'])70 result = '%s (%s)' % (result, self.verse_list[prev]['version'])
66 result += ', '71 result += '%s ' % list_sep
67 if self.verse_list[prev]['book'] != verse['book']:72 if self.verse_list[prev]['book'] != verse['book']:
68 result = '%s%s %s:' % (result, verse['book'], verse['chapter'])73 result = '%s%s %s%s' % (result, verse['book'], verse['chapter'], verse_sep)
69 elif self.verse_list[prev]['chapter'] != verse['chapter']:74 elif self.verse_list[prev]['chapter'] != verse['chapter']:
70 result = '%s%s:' % (result, verse['chapter'])75 result = '%s%s%s' % (result, verse['chapter'], verse_sep)
71 result += str(verse['start'])76 result += str(verse['start'])
72 if verse['start'] != verse['end']:77 if verse['start'] != verse['end']:
73 result = '%s-%s' % (result, verse['end'])78 result = '%s%s%s' % (result, range_sep, verse['end'])
74 if len(self.version_list) > 1:79 if len(self.version_list) > 1:
75 result = '%s (%s)' % (result, verse['version'])80 result = '%s (%s)' % (result, verse['version'])
76 return result81 return result
7782
78 def format_versions(self):83 def format_versions(self, copyright=True, permission=True):
84 """
85 Format a string with the bible versions used
86
87 :param copyright: If the copyright info should be included, default is true.
88 :param permission: If the permission info should be included, default is true.
89 :return: A formatted string with the bible versions used
90 """
79 result = ''91 result = ''
80 for index, version in enumerate(self.version_list):92 for index, version in enumerate(self.version_list):
81 if index > 0:93 if index > 0:
@@ -83,9 +95,9 @@
83 result += ';'95 result += ';'
84 result += ' '96 result += ' '
85 result += version['version']97 result += version['version']
86 if version['copyright'].strip():98 if copyright and version['copyright'].strip():
87 result += ', ' + version['copyright']99 result += ', ' + version['copyright']
88 if version['permission'].strip():100 if permission and version['permission'].strip():
89 result += ', ' + version['permission']101 result += ', ' + version['permission']
90 result = result.rstrip()102 result = result.rstrip()
91 if result.endswith(','):103 if result.endswith(','):
92104
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2015-01-30 21:03:53 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2015-04-22 21:11:34 +0000
@@ -205,6 +205,7 @@
205 images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)205 images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
206 for image in images:206 for image in images:
207 delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))207 delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
208 delete_file(self.generate_thumbnail_path(image))
208 self.manager.delete_object(ImageFilenames, image.id)209 self.manager.delete_object(ImageFilenames, image.id)
209 image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)210 image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
210 for group in image_groups:211 for group in image_groups:
@@ -227,6 +228,7 @@
227 item_data = row_item.data(0, QtCore.Qt.UserRole)228 item_data = row_item.data(0, QtCore.Qt.UserRole)
228 if isinstance(item_data, ImageFilenames):229 if isinstance(item_data, ImageFilenames):
229 delete_file(os.path.join(self.service_path, row_item.text(0)))230 delete_file(os.path.join(self.service_path, row_item.text(0)))
231 delete_file(self.generate_thumbnail_path(item_data))
230 if item_data.group_id == 0:232 if item_data.group_id == 0:
231 self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))233 self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
232 else:234 else:
233235
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2015-03-10 21:33:35 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2015-04-22 21:11:34 +0000
@@ -91,7 +91,10 @@
91 """91 """
92 self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')92 self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
93 self.replace_action.setText(UiStrings().ReplaceBG)93 self.replace_action.setText(UiStrings().ReplaceBG)
94 self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)94 if 'webkit' in get_media_players()[0]:
95 self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
96 else:
97 self.replace_action.setToolTip(UiStrings().ReplaceLiveBGDisabled)
95 self.reset_action.setText(UiStrings().ResetBG)98 self.reset_action.setText(UiStrings().ResetBG)
96 self.reset_action.setToolTip(UiStrings().ResetLiveBG)99 self.reset_action.setToolTip(UiStrings().ResetLiveBG)
97 self.automatic = UiStrings().Automatic100 self.automatic = UiStrings().Automatic
@@ -139,6 +142,8 @@
139 # Replace backgrounds do not work at present so remove functionality.142 # Replace backgrounds do not work at present so remove functionality.
140 self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png',143 self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png',
141 triggers=self.on_replace_click)144 triggers=self.on_replace_click)
145 if 'webkit' not in get_media_players()[0]:
146 self.replace_action.setDisabled(True)
142 self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png',147 self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png',
143 visible=False, triggers=self.on_reset_click)148 visible=False, triggers=self.on_reset_click)
144 self.media_widget = QtGui.QWidget(self)149 self.media_widget = QtGui.QWidget(self)
145150
=== modified file 'tests/functional/openlp_plugins/images/test_lib.py'
--- tests/functional/openlp_plugins/images/test_lib.py 2015-01-20 07:14:58 +0000
+++ tests/functional/openlp_plugins/images/test_lib.py 2015-04-22 21:11:34 +0000
@@ -97,8 +97,8 @@
97 self.media_item.save_new_images_list(image_list)97 self.media_item.save_new_images_list(image_list)
9898
99 # THEN: The save_object() method should not have been called99 # THEN: The save_object() method should not have been called
100 assert self.media_item.manager.save_object.call_count == 0, \100 self.assertEquals(self.media_item.manager.save_object.call_count, 0,
101 'The save_object() method should not have been called'101 'The save_object() method should not have been called')
102102
103 def save_new_images_list_single_image_with_reload_test(self):103 def save_new_images_list_single_image_with_reload_test(self):
104 """104 """
@@ -114,7 +114,7 @@
114 self.media_item.save_new_images_list(image_list, reload_list=True)114 self.media_item.save_new_images_list(image_list, reload_list=True)
115115
116 # THEN: load_full_list() should have been called116 # THEN: load_full_list() should have been called
117 assert mocked_load_full_list.call_count == 1, 'load_full_list() should have been called'117 self.assertEquals(mocked_load_full_list.call_count, 1, 'load_full_list() should have been called')
118118
119 # CLEANUP: Remove added attribute from ImageFilenames119 # CLEANUP: Remove added attribute from ImageFilenames
120 delattr(ImageFilenames, 'filename')120 delattr(ImageFilenames, 'filename')
@@ -132,7 +132,7 @@
132 self.media_item.save_new_images_list(image_list, reload_list=False)132 self.media_item.save_new_images_list(image_list, reload_list=False)
133133
134 # THEN: load_full_list() should not have been called134 # THEN: load_full_list() should not have been called
135 assert mocked_load_full_list.call_count == 0, 'load_full_list() should not have been called'135 self.assertEquals(mocked_load_full_list.call_count, 0, 'load_full_list() should not have been called')
136136
137 def save_new_images_list_multiple_images_test(self):137 def save_new_images_list_multiple_images_test(self):
138 """138 """
@@ -147,8 +147,8 @@
147 self.media_item.save_new_images_list(image_list, reload_list=False)147 self.media_item.save_new_images_list(image_list, reload_list=False)
148148
149 # THEN: load_full_list() should not have been called149 # THEN: load_full_list() should not have been called
150 assert self.media_item.manager.save_object.call_count == 3, \150 self.assertEquals(self.media_item.manager.save_object.call_count, 3,
151 'load_full_list() should have been called three times'151 'load_full_list() should have been called three times')
152152
153 def save_new_images_list_other_objects_in_list_test(self):153 def save_new_images_list_other_objects_in_list_test(self):
154 """154 """
@@ -163,8 +163,8 @@
163 self.media_item.save_new_images_list(image_list, reload_list=False)163 self.media_item.save_new_images_list(image_list, reload_list=False)
164164
165 # THEN: load_full_list() should not have been called165 # THEN: load_full_list() should not have been called
166 assert self.media_item.manager.save_object.call_count == 2, \166 self.assertEquals(self.media_item.manager.save_object.call_count, 2,
167 'load_full_list() should have been called only once'167 'load_full_list() should have been called only once')
168168
169 def on_reset_click_test(self):169 def on_reset_click_test(self):
170 """170 """
@@ -185,22 +185,22 @@
185 Test that recursively_delete_group() works185 Test that recursively_delete_group() works
186 """186 """
187 # GIVEN: An ImageGroups object and mocked functions187 # GIVEN: An ImageGroups object and mocked functions
188 with patch('openlp.core.utils.delete_file') as mocked_delete_file:188 with patch('openlp.plugins.images.lib.mediaitem.delete_file') as mocked_delete_file:
189 ImageFilenames.group_id = 1189 ImageFilenames.group_id = 1
190 ImageGroups.parent_id = 1190 ImageGroups.parent_id = 1
191 self.media_item.manager = MagicMock()191 self.media_item.manager = MagicMock()
192 self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect192 self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect
193 self.media_item.service_path = ""193 self.media_item.service_path = ''
194 test_group = ImageGroups()194 test_group = ImageGroups()
195 test_group.id = 1195 test_group.id = 1
196196
197 # WHEN: recursively_delete_group() is called197 # WHEN: recursively_delete_group() is called
198 self.media_item.recursively_delete_group(test_group)198 self.media_item.recursively_delete_group(test_group)
199199
200 # THEN:200 # THEN: delete_file() should have been called 12 times and manager.delete_object() 7 times.
201 assert mocked_delete_file.call_count == 0, 'delete_file() should not be called'201 self.assertEquals(mocked_delete_file.call_count, 12, 'delete_file() should have been called 12 times')
202 assert self.media_item.manager.delete_object.call_count == 7, \202 self.assertEquals(self.media_item.manager.delete_object.call_count, 7,
203 'manager.delete_object() should be called exactly 7 times'203 'manager.delete_object() should be called exactly 7 times')
204204
205 # CLEANUP: Remove added attribute from Image Filenames and ImageGroups205 # CLEANUP: Remove added attribute from Image Filenames and ImageGroups
206 delattr(ImageFilenames, 'group_id')206 delattr(ImageFilenames, 'group_id')
@@ -230,3 +230,29 @@
230 returned_object1.id = 1230 returned_object1.id = 1
231 return [returned_object1]231 return [returned_object1]
232 return []232 return []
233
234 def on_delete_click_test(self):
235 """
236 Test that on_delete_click() works
237 """
238 # GIVEN: An ImageGroups object and mocked functions
239 with patch('openlp.plugins.images.lib.mediaitem.delete_file') as mocked_delete_file, \
240 patch('openlp.plugins.images.lib.mediaitem.check_item_selected') as mocked_check_item_selected:
241 mocked_check_item_selected.return_value = True
242 test_image = ImageFilenames()
243 test_image.id = 1
244 test_image.group_id = 1
245 test_image.filename = 'imagefile.png'
246 self.media_item.manager = MagicMock()
247 self.media_item.service_path = ''
248 self.media_item.list_view = MagicMock()
249 mocked_row_item = MagicMock()
250 mocked_row_item.data.return_value = test_image
251 mocked_row_item.text.return_value = ''
252 self.media_item.list_view.selectedItems.return_value = [mocked_row_item]
253
254 # WHEN: Calling on_delete_click
255 self.media_item.on_delete_click()
256
257 # THEN: delete_file should have been called twice
258 self.assertEquals(mocked_delete_file.call_count, 2, 'delete_file() should have been called twice')