forked from openlp/openlp
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. bzr-revno: 2529
This commit is contained in:
commit
63bdf756ee
@ -121,6 +121,8 @@ class UiStrings(object):
|
|||||||
self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')
|
self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')
|
||||||
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
||||||
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
|
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
|
||||||
|
self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available on this '
|
||||||
|
'platform in this version of OpenLP.')
|
||||||
self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
|
self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
|
||||||
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
|
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
|
||||||
self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
|
self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
|
||||||
|
@ -95,7 +95,7 @@ class ListWidgetWithDnD(QtGui.QListWidget):
|
|||||||
event.accept()
|
event.accept()
|
||||||
files = []
|
files = []
|
||||||
for url in event.mimeData().urls():
|
for url in event.mimeData().urls():
|
||||||
local_file = url.toLocalFile()
|
local_file = os.path.normpath(url.toLocalFile())
|
||||||
if os.path.isfile(local_file):
|
if os.path.isfile(local_file):
|
||||||
files.append(local_file)
|
files.append(local_file)
|
||||||
elif os.path.isdir(local_file):
|
elif os.path.isdir(local_file):
|
||||||
|
@ -193,13 +193,15 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog, RegistryProperties)
|
|||||||
# Add the text of the service item.
|
# Add the text of the service item.
|
||||||
if item.is_text():
|
if item.is_text():
|
||||||
verse_def = None
|
verse_def = None
|
||||||
|
verse_html = None
|
||||||
for slide in item.get_frames():
|
for slide in item.get_frames():
|
||||||
if not verse_def or verse_def != slide['verseTag']:
|
if not verse_def or verse_def != slide['verseTag'] or verse_html == slide['html']:
|
||||||
text_div = self._add_element('div', parent=div, classId='itemText')
|
text_div = self._add_element('div', parent=div, classId='itemText')
|
||||||
else:
|
else:
|
||||||
self._add_element('br', parent=text_div)
|
self._add_element('br', parent=text_div)
|
||||||
self._add_element('span', slide['html'], text_div)
|
self._add_element('span', slide['html'], text_div)
|
||||||
verse_def = slide['verseTag']
|
verse_def = slide['verseTag']
|
||||||
|
verse_html = slide['html']
|
||||||
# Break the page before the div element.
|
# Break the page before the div element.
|
||||||
if index != 0 and self.page_break_after_text.isChecked():
|
if index != 0 and self.page_break_after_text.isChecked():
|
||||||
div.set('class', 'item newPage')
|
div.set('class', 'item newPage')
|
||||||
|
@ -849,7 +849,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
service_item.add_capability(ItemCapabilities.CanWordSplit)
|
service_item.add_capability(ItemCapabilities.CanWordSplit)
|
||||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||||
# Service Item: Title
|
# Service Item: Title
|
||||||
service_item.title = create_separated_list(raw_title)
|
service_item.title = '%s %s' % (verses.format_verses(), verses.format_versions())
|
||||||
# Service Item: Theme
|
# Service Item: Theme
|
||||||
if not self.settings.bible_theme:
|
if not self.settings.bible_theme:
|
||||||
service_item.theme = None
|
service_item.theme = None
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
from openlp.plugins.bibles.lib import get_reference_separator
|
||||||
|
|
||||||
|
|
||||||
class VerseReferenceList(object):
|
class VerseReferenceList(object):
|
||||||
"""
|
"""
|
||||||
@ -53,29 +55,39 @@ class VerseReferenceList(object):
|
|||||||
self.version_list.append({'version': version, 'copyright': copyright, 'permission': permission})
|
self.version_list.append({'version': version, 'copyright': copyright, 'permission': permission})
|
||||||
|
|
||||||
def format_verses(self):
|
def format_verses(self):
|
||||||
|
verse_sep = get_reference_separator('sep_v_display')
|
||||||
|
range_sep = get_reference_separator('sep_r_display')
|
||||||
|
list_sep = get_reference_separator('sep_l_display')
|
||||||
result = ''
|
result = ''
|
||||||
for index, verse in enumerate(self.verse_list):
|
for index, verse in enumerate(self.verse_list):
|
||||||
if index == 0:
|
if index == 0:
|
||||||
result = '%s %s:%s' % (verse['book'], verse['chapter'], verse['start'])
|
result = '%s %s%s%s' % (verse['book'], verse['chapter'], verse_sep, verse['start'])
|
||||||
if verse['start'] != verse['end']:
|
if verse['start'] != verse['end']:
|
||||||
result = '%s-%s' % (result, verse['end'])
|
result = '%s%s%s' % (result, range_sep, verse['end'])
|
||||||
continue
|
continue
|
||||||
prev = index - 1
|
prev = index - 1
|
||||||
if self.verse_list[prev]['version'] != verse['version']:
|
if self.verse_list[prev]['version'] != verse['version']:
|
||||||
result = '%s (%s)' % (result, self.verse_list[prev]['version'])
|
result = '%s (%s)' % (result, self.verse_list[prev]['version'])
|
||||||
result += ', '
|
result += '%s ' % list_sep
|
||||||
if self.verse_list[prev]['book'] != verse['book']:
|
if self.verse_list[prev]['book'] != verse['book']:
|
||||||
result = '%s%s %s:' % (result, verse['book'], verse['chapter'])
|
result = '%s%s %s%s' % (result, verse['book'], verse['chapter'], verse_sep)
|
||||||
elif self.verse_list[prev]['chapter'] != verse['chapter']:
|
elif self.verse_list[prev]['chapter'] != verse['chapter']:
|
||||||
result = '%s%s:' % (result, verse['chapter'])
|
result = '%s%s%s' % (result, verse['chapter'], verse_sep)
|
||||||
result += str(verse['start'])
|
result += str(verse['start'])
|
||||||
if verse['start'] != verse['end']:
|
if verse['start'] != verse['end']:
|
||||||
result = '%s-%s' % (result, verse['end'])
|
result = '%s%s%s' % (result, range_sep, verse['end'])
|
||||||
if len(self.version_list) > 1:
|
if len(self.version_list) > 1:
|
||||||
result = '%s (%s)' % (result, verse['version'])
|
result = '%s (%s)' % (result, verse['version'])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def format_versions(self):
|
def format_versions(self, copyright=True, permission=True):
|
||||||
|
"""
|
||||||
|
Format a string with the bible versions used
|
||||||
|
|
||||||
|
:param copyright: If the copyright info should be included, default is true.
|
||||||
|
:param permission: If the permission info should be included, default is true.
|
||||||
|
:return: A formatted string with the bible versions used
|
||||||
|
"""
|
||||||
result = ''
|
result = ''
|
||||||
for index, version in enumerate(self.version_list):
|
for index, version in enumerate(self.version_list):
|
||||||
if index > 0:
|
if index > 0:
|
||||||
@ -83,9 +95,9 @@ class VerseReferenceList(object):
|
|||||||
result += ';'
|
result += ';'
|
||||||
result += ' '
|
result += ' '
|
||||||
result += version['version']
|
result += version['version']
|
||||||
if version['copyright'].strip():
|
if copyright and version['copyright'].strip():
|
||||||
result += ', ' + version['copyright']
|
result += ', ' + version['copyright']
|
||||||
if version['permission'].strip():
|
if permission and version['permission'].strip():
|
||||||
result += ', ' + version['permission']
|
result += ', ' + version['permission']
|
||||||
result = result.rstrip()
|
result = result.rstrip()
|
||||||
if result.endswith(','):
|
if result.endswith(','):
|
||||||
|
@ -205,6 +205,7 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
|
images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
|
||||||
for image in images:
|
for image in images:
|
||||||
delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
|
delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
|
||||||
|
delete_file(self.generate_thumbnail_path(image))
|
||||||
self.manager.delete_object(ImageFilenames, image.id)
|
self.manager.delete_object(ImageFilenames, image.id)
|
||||||
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
|
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
|
||||||
for group in image_groups:
|
for group in image_groups:
|
||||||
@ -227,6 +228,7 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
item_data = row_item.data(0, QtCore.Qt.UserRole)
|
item_data = row_item.data(0, QtCore.Qt.UserRole)
|
||||||
if isinstance(item_data, ImageFilenames):
|
if isinstance(item_data, ImageFilenames):
|
||||||
delete_file(os.path.join(self.service_path, row_item.text(0)))
|
delete_file(os.path.join(self.service_path, row_item.text(0)))
|
||||||
|
delete_file(self.generate_thumbnail_path(item_data))
|
||||||
if item_data.group_id == 0:
|
if item_data.group_id == 0:
|
||||||
self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
|
self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
|
||||||
else:
|
else:
|
||||||
|
@ -91,7 +91,10 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
||||||
self.replace_action.setText(UiStrings().ReplaceBG)
|
self.replace_action.setText(UiStrings().ReplaceBG)
|
||||||
self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
|
if 'webkit' in get_media_players()[0]:
|
||||||
|
self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
|
||||||
|
else:
|
||||||
|
self.replace_action.setToolTip(UiStrings().ReplaceLiveBGDisabled)
|
||||||
self.reset_action.setText(UiStrings().ResetBG)
|
self.reset_action.setText(UiStrings().ResetBG)
|
||||||
self.reset_action.setToolTip(UiStrings().ResetLiveBG)
|
self.reset_action.setToolTip(UiStrings().ResetLiveBG)
|
||||||
self.automatic = UiStrings().Automatic
|
self.automatic = UiStrings().Automatic
|
||||||
@ -139,6 +142,8 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
|||||||
# Replace backgrounds do not work at present so remove functionality.
|
# Replace backgrounds do not work at present so remove functionality.
|
||||||
self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png',
|
self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png',
|
||||||
triggers=self.on_replace_click)
|
triggers=self.on_replace_click)
|
||||||
|
if 'webkit' not in get_media_players()[0]:
|
||||||
|
self.replace_action.setDisabled(True)
|
||||||
self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png',
|
self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png',
|
||||||
visible=False, triggers=self.on_reset_click)
|
visible=False, triggers=self.on_reset_click)
|
||||||
self.media_widget = QtGui.QWidget(self)
|
self.media_widget = QtGui.QWidget(self)
|
||||||
|
@ -97,8 +97,8 @@ class TestImageMediaItem(TestCase):
|
|||||||
self.media_item.save_new_images_list(image_list)
|
self.media_item.save_new_images_list(image_list)
|
||||||
|
|
||||||
# THEN: The save_object() method should not have been called
|
# THEN: The save_object() method should not have been called
|
||||||
assert self.media_item.manager.save_object.call_count == 0, \
|
self.assertEquals(self.media_item.manager.save_object.call_count, 0,
|
||||||
'The save_object() method should not have been called'
|
'The save_object() method should not have been called')
|
||||||
|
|
||||||
def save_new_images_list_single_image_with_reload_test(self):
|
def save_new_images_list_single_image_with_reload_test(self):
|
||||||
"""
|
"""
|
||||||
@ -114,7 +114,7 @@ class TestImageMediaItem(TestCase):
|
|||||||
self.media_item.save_new_images_list(image_list, reload_list=True)
|
self.media_item.save_new_images_list(image_list, reload_list=True)
|
||||||
|
|
||||||
# THEN: load_full_list() should have been called
|
# THEN: load_full_list() should have been called
|
||||||
assert mocked_load_full_list.call_count == 1, 'load_full_list() should have been called'
|
self.assertEquals(mocked_load_full_list.call_count, 1, 'load_full_list() should have been called')
|
||||||
|
|
||||||
# CLEANUP: Remove added attribute from ImageFilenames
|
# CLEANUP: Remove added attribute from ImageFilenames
|
||||||
delattr(ImageFilenames, 'filename')
|
delattr(ImageFilenames, 'filename')
|
||||||
@ -132,7 +132,7 @@ class TestImageMediaItem(TestCase):
|
|||||||
self.media_item.save_new_images_list(image_list, reload_list=False)
|
self.media_item.save_new_images_list(image_list, reload_list=False)
|
||||||
|
|
||||||
# THEN: load_full_list() should not have been called
|
# THEN: load_full_list() should not have been called
|
||||||
assert mocked_load_full_list.call_count == 0, 'load_full_list() should not have been called'
|
self.assertEquals(mocked_load_full_list.call_count, 0, 'load_full_list() should not have been called')
|
||||||
|
|
||||||
def save_new_images_list_multiple_images_test(self):
|
def save_new_images_list_multiple_images_test(self):
|
||||||
"""
|
"""
|
||||||
@ -147,8 +147,8 @@ class TestImageMediaItem(TestCase):
|
|||||||
self.media_item.save_new_images_list(image_list, reload_list=False)
|
self.media_item.save_new_images_list(image_list, reload_list=False)
|
||||||
|
|
||||||
# THEN: load_full_list() should not have been called
|
# THEN: load_full_list() should not have been called
|
||||||
assert self.media_item.manager.save_object.call_count == 3, \
|
self.assertEquals(self.media_item.manager.save_object.call_count, 3,
|
||||||
'load_full_list() should have been called three times'
|
'load_full_list() should have been called three times')
|
||||||
|
|
||||||
def save_new_images_list_other_objects_in_list_test(self):
|
def save_new_images_list_other_objects_in_list_test(self):
|
||||||
"""
|
"""
|
||||||
@ -163,8 +163,8 @@ class TestImageMediaItem(TestCase):
|
|||||||
self.media_item.save_new_images_list(image_list, reload_list=False)
|
self.media_item.save_new_images_list(image_list, reload_list=False)
|
||||||
|
|
||||||
# THEN: load_full_list() should not have been called
|
# THEN: load_full_list() should not have been called
|
||||||
assert self.media_item.manager.save_object.call_count == 2, \
|
self.assertEquals(self.media_item.manager.save_object.call_count, 2,
|
||||||
'load_full_list() should have been called only once'
|
'load_full_list() should have been called only once')
|
||||||
|
|
||||||
def on_reset_click_test(self):
|
def on_reset_click_test(self):
|
||||||
"""
|
"""
|
||||||
@ -185,22 +185,22 @@ class TestImageMediaItem(TestCase):
|
|||||||
Test that recursively_delete_group() works
|
Test that recursively_delete_group() works
|
||||||
"""
|
"""
|
||||||
# GIVEN: An ImageGroups object and mocked functions
|
# GIVEN: An ImageGroups object and mocked functions
|
||||||
with patch('openlp.core.utils.delete_file') as mocked_delete_file:
|
with patch('openlp.plugins.images.lib.mediaitem.delete_file') as mocked_delete_file:
|
||||||
ImageFilenames.group_id = 1
|
ImageFilenames.group_id = 1
|
||||||
ImageGroups.parent_id = 1
|
ImageGroups.parent_id = 1
|
||||||
self.media_item.manager = MagicMock()
|
self.media_item.manager = MagicMock()
|
||||||
self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect
|
self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect
|
||||||
self.media_item.service_path = ""
|
self.media_item.service_path = ''
|
||||||
test_group = ImageGroups()
|
test_group = ImageGroups()
|
||||||
test_group.id = 1
|
test_group.id = 1
|
||||||
|
|
||||||
# WHEN: recursively_delete_group() is called
|
# WHEN: recursively_delete_group() is called
|
||||||
self.media_item.recursively_delete_group(test_group)
|
self.media_item.recursively_delete_group(test_group)
|
||||||
|
|
||||||
# THEN:
|
# THEN: delete_file() should have been called 12 times and manager.delete_object() 7 times.
|
||||||
assert mocked_delete_file.call_count == 0, 'delete_file() should not be called'
|
self.assertEquals(mocked_delete_file.call_count, 12, 'delete_file() should have been called 12 times')
|
||||||
assert self.media_item.manager.delete_object.call_count == 7, \
|
self.assertEquals(self.media_item.manager.delete_object.call_count, 7,
|
||||||
'manager.delete_object() should be called exactly 7 times'
|
'manager.delete_object() should be called exactly 7 times')
|
||||||
|
|
||||||
# CLEANUP: Remove added attribute from Image Filenames and ImageGroups
|
# CLEANUP: Remove added attribute from Image Filenames and ImageGroups
|
||||||
delattr(ImageFilenames, 'group_id')
|
delattr(ImageFilenames, 'group_id')
|
||||||
@ -230,3 +230,29 @@ class TestImageMediaItem(TestCase):
|
|||||||
returned_object1.id = 1
|
returned_object1.id = 1
|
||||||
return [returned_object1]
|
return [returned_object1]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def on_delete_click_test(self):
|
||||||
|
"""
|
||||||
|
Test that on_delete_click() works
|
||||||
|
"""
|
||||||
|
# GIVEN: An ImageGroups object and mocked functions
|
||||||
|
with patch('openlp.plugins.images.lib.mediaitem.delete_file') as mocked_delete_file, \
|
||||||
|
patch('openlp.plugins.images.lib.mediaitem.check_item_selected') as mocked_check_item_selected:
|
||||||
|
mocked_check_item_selected.return_value = True
|
||||||
|
test_image = ImageFilenames()
|
||||||
|
test_image.id = 1
|
||||||
|
test_image.group_id = 1
|
||||||
|
test_image.filename = 'imagefile.png'
|
||||||
|
self.media_item.manager = MagicMock()
|
||||||
|
self.media_item.service_path = ''
|
||||||
|
self.media_item.list_view = MagicMock()
|
||||||
|
mocked_row_item = MagicMock()
|
||||||
|
mocked_row_item.data.return_value = test_image
|
||||||
|
mocked_row_item.text.return_value = ''
|
||||||
|
self.media_item.list_view.selectedItems.return_value = [mocked_row_item]
|
||||||
|
|
||||||
|
# WHEN: Calling on_delete_click
|
||||||
|
self.media_item.on_delete_click()
|
||||||
|
|
||||||
|
# THEN: delete_file should have been called twice
|
||||||
|
self.assertEquals(mocked_delete_file.call_count, 2, 'delete_file() should have been called twice')
|
||||||
|
Loading…
Reference in New Issue
Block a user