Merge lp:~phill-ridout/openlp/bug1367141-2 into lp:openlp

Proposed by Phill
Status: Merged
Merged at revision: 2487
Proposed branch: lp:~phill-ridout/openlp/bug1367141-2
Merge into: lp:openlp
Diff against target: 315 lines (+100/-29)
10 files modified
openlp/core/__init__.py (+24/-15)
openlp/core/lib/mediamanageritem.py (+1/-2)
openlp/plugins/images/imageplugin.py (+10/-0)
openlp/plugins/images/lib/mediaitem.py (+2/-1)
openlp/plugins/presentations/lib/mediaitem.py (+13/-4)
openlp/plugins/presentations/lib/presentationcontroller.py (+13/-3)
openlp/plugins/presentations/presentationplugin.py (+16/-2)
tests/functional/openlp_plugins/presentations/test_impresscontroller.py (+3/-0)
tests/functional/openlp_plugins/presentations/test_pdfcontroller.py (+2/-1)
tests/functional/test_init.py (+16/-1)
To merge this branch: bzr merge lp:~phill-ridout/openlp/bug1367141-2
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Raoul Snyman Approve
Review via email: mp+247503@code.launchpad.net

This proposal supersedes a proposal from 2015-01-22.

Description of the change

Fixes Bug #1367141: Presentations/Images with same name gets the same thumbnail
Uses the database id for thumbnails. Uses an md5 hash of the path and file name for presentations (as there is no db for presentations)

Also added code to remove the old thumbnails.

Add this to your merge proposal:
--------------------------------
lp:~phill-ridout/openlp/bug1367141-2 (revision 2486)
[SUCCESS] http://ci.openlp.org/job/Branch-01-Pull/906/
[SUCCESS] http://ci.openlp.org/job/Branch-02-Functional-Tests/837/
[SUCCESS] http://ci.openlp.org/job/Branch-03-Interface-Tests/783/
[SUCCESS] http://ci.openlp.org/job/Branch-04a-Windows_Functional_Tests/694/
[SUCCESS] http://ci.openlp.org/job/Branch-04b-Windows_Interface_Tests/293/
[SUCCESS] http://ci.openlp.org/job/Branch-05a-Code_Analysis/435/
[SUCCESS] http://ci.openlp.org/job/Branch-05b-Test_Coverage/306/

Process finished with exit code 0

To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

No print statements!

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) :
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
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py 2015-01-18 13:39:21 +0000
+++ openlp/core/__init__.py 2015-01-24 10:31:06 +0000
@@ -263,6 +263,29 @@
263 return QtGui.QApplication.event(self, event)263 return QtGui.QApplication.event(self, event)
264264
265265
266def parse_options(args):
267 """
268 Parse the command line arguments
269
270 :param args: list of command line arguments
271 :return: a tuple of parsed options of type optparse.Value and a list of remaining argsZ
272 """
273 # Set up command line options.
274 usage = 'Usage: %prog [options] [qt-options]'
275 parser = OptionParser(usage=usage)
276 parser.add_option('-e', '--no-error-form', dest='no_error_form', action='store_true',
277 help='Disable the error notification form.')
278 parser.add_option('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
279 help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
280 parser.add_option('-p', '--portable', dest='portable', action='store_true',
281 help='Specify if this should be run as a portable app, off a USB flash drive (not implemented).')
282 parser.add_option('-d', '--dev-version', dest='dev_version', action='store_true',
283 help='Ignore the version file and pull the version directly from Bazaar')
284 parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).')
285 # Parse command line options and deal with them. Use args supplied pragmatically if possible.
286 return parser.parse_args(args) if args else parser.parse_args()
287
288
266def set_up_logging(log_path):289def set_up_logging(log_path):
267 """290 """
268 Setup our logging using log_path291 Setup our logging using log_path
@@ -284,21 +307,7 @@
284307
285 :param args: Some args308 :param args: Some args
286 """309 """
287 # Set up command line options.310 (options, args) = parse_options(args)
288 usage = 'Usage: %prog [options] [qt-options]'
289 parser = OptionParser(usage=usage)
290 parser.add_option('-e', '--no-error-form', dest='no_error_form', action='store_true',
291 help='Disable the error notification form.')
292 parser.add_option('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
293 help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
294 parser.add_option('-p', '--portable', dest='portable', action='store_true',
295 help='Specify if this should be run as a portable app, off a USB flash drive (not implemented).')
296 parser.add_option('-d', '--dev-version', dest='dev_version', action='store_true',
297 help='Ignore the version file and pull the version directly from Bazaar')
298 parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).')
299 # Parse command line options and deal with them.
300 # Use args supplied pragmatically if possible.
301 (options, args) = parser.parse_args(args) if args else parser.parse_args()
302 qt_args = []311 qt_args = []
303 if options.loglevel.lower() in ['d', 'debug']:312 if options.loglevel.lower() in ['d', 'debug']:
304 log.setLevel(logging.DEBUG)313 log.setLevel(logging.DEBUG)
305314
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2015-01-18 13:39:21 +0000
+++ openlp/core/lib/mediamanageritem.py 2015-01-24 10:31:06 +0000
@@ -366,8 +366,7 @@
366 duplicates_found = False366 duplicates_found = False
367 files_added = False367 files_added = False
368 for file_path in files:368 for file_path in files:
369 filename = os.path.split(str(file_path))[1]369 if file_path in full_list:
370 if filename in names:
371 duplicates_found = True370 duplicates_found = True
372 else:371 else:
373 files_added = True372 files_added = True
374373
=== modified file 'openlp/plugins/images/imageplugin.py'
--- openlp/plugins/images/imageplugin.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/images/imageplugin.py 2015-01-24 10:31:06 +0000
@@ -23,6 +23,7 @@
23from PyQt4 import QtGui23from PyQt4 import QtGui
2424
25import logging25import logging
26import os
2627
27from openlp.core.common import Registry, Settings, translate28from openlp.core.common import Registry, Settings, translate
28from openlp.core.lib import Plugin, StringContent, ImageSource, build_icon29from openlp.core.lib import Plugin, StringContent, ImageSource, build_icon
@@ -66,10 +67,18 @@
66 """67 """
67 Perform tasks on application startup.68 Perform tasks on application startup.
68 """69 """
70 # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
69 Plugin.app_startup(self)71 Plugin.app_startup(self)
70 # Convert old settings-based image list to the database.72 # Convert old settings-based image list to the database.
71 files_from_config = Settings().get_files_from_config(self)73 files_from_config = Settings().get_files_from_config(self)
72 if files_from_config:74 if files_from_config:
75 for file in files_from_config:
76 filename = os.path.split(file)[1]
77 thumb = os.path.join(self.media_item.service_path, filename)
78 try:
79 os.remove(thumb)
80 except:
81 pass
73 log.debug('Importing images list from old config: %s' % files_from_config)82 log.debug('Importing images list from old config: %s' % files_from_config)
74 self.media_item.save_new_images_list(files_from_config)83 self.media_item.save_new_images_list(files_from_config)
7584
@@ -79,6 +88,7 @@
7988
80 :param settings: The Settings object containing the old settings.89 :param settings: The Settings object containing the old settings.
81 """90 """
91 # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
82 files_from_config = settings.get_files_from_config(self)92 files_from_config = settings.get_files_from_config(self)
83 if files_from_config:93 if files_from_config:
84 log.debug('Importing images list from old config: %s' % files_from_config)94 log.debug('Importing images list from old config: %s' % files_from_config)
8595
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2015-01-19 22:49:18 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2015-01-24 10:31:06 +0000
@@ -338,7 +338,8 @@
338 for imageFile in images:338 for imageFile in images:
339 log.debug('Loading image: %s', imageFile.filename)339 log.debug('Loading image: %s', imageFile.filename)
340 filename = os.path.split(imageFile.filename)[1]340 filename = os.path.split(imageFile.filename)[1]
341 thumb = os.path.join(self.service_path, filename)341 ext = os.path.splitext(imageFile.filename)[1].lower()
342 thumb = os.path.join(self.service_path, "%s%s" % (str(imageFile.id), ext))
342 if not os.path.exists(imageFile.filename):343 if not os.path.exists(imageFile.filename):
343 icon = build_icon(':/general/general_delete.png')344 icon = build_icon(':/general/general_delete.png')
344 else:345 else:
345346
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2015-01-24 10:31:06 +0000
@@ -222,10 +222,7 @@
222 self.main_window.display_progress_bar(len(row_list))222 self.main_window.display_progress_bar(len(row_list))
223 for item in items:223 for item in items:
224 filepath = str(item.data(QtCore.Qt.UserRole))224 filepath = str(item.data(QtCore.Qt.UserRole))
225 for cidx in self.controllers:225 self.clean_up_thumbnails(filepath)
226 doc = self.controllers[cidx].add_document(filepath)
227 doc.presentation_deleted()
228 doc.close_presentation()
229 self.main_window.increment_progress_bar()226 self.main_window.increment_progress_bar()
230 self.main_window.finished_progress_bar()227 self.main_window.finished_progress_bar()
231 self.application.set_busy_cursor()228 self.application.set_busy_cursor()
@@ -233,6 +230,18 @@
233 self.list_view.takeItem(row)230 self.list_view.takeItem(row)
234 Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())231 Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
235232
233 def clean_up_thumbnails(self, filepath):
234 """
235 Clean up the files created such as thumbnails
236
237 :param filepath: File path of the presention to clean up after
238 :return: None
239 """
240 for cidx in self.controllers:
241 doc = self.controllers[cidx].add_document(filepath)
242 doc.presentation_deleted()
243 doc.close_presentation()
244
236 def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,245 def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
237 context=ServiceItemContext.Service, presentation_file=None):246 context=ServiceItemContext.Service, presentation_file=None):
238 """247 """
239248
=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py 2015-01-24 10:31:06 +0000
@@ -26,7 +26,7 @@
2626
27from PyQt4 import QtCore27from PyQt4 import QtCore
2828
29from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists29from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, md5_hash
30from openlp.core.lib import create_thumb, validate_thumb30from openlp.core.lib import create_thumb, validate_thumb
3131
32log = logging.getLogger(__name__)32log = logging.getLogger(__name__)
@@ -132,13 +132,23 @@
132 """132 """
133 The location where thumbnail images will be stored133 The location where thumbnail images will be stored
134 """134 """
135 return os.path.join(self.controller.thumbnail_folder, self.get_file_name())135 # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
136 if Settings().value('presentations/thumbnail_scheme') == 'md5':
137 folder = md5_hash('', self.file_path)
138 else:
139 folder = self.get_file_name()
140 return os.path.join(self.controller.thumbnail_folder, folder)
136141
137 def get_temp_folder(self):142 def get_temp_folder(self):
138 """143 """
139 The location where thumbnail images will be stored144 The location where thumbnail images will be stored
140 """145 """
141 return os.path.join(self.controller.temp_folder, self.get_file_name())146 # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
147 if Settings().value('presentations/thumbnail_scheme') == 'md5':
148 folder = md5_hash('', self.file_path)
149 else:
150 folder = folder = self.get_file_name()
151 return os.path.join(self.controller.temp_folder, folder)
142152
143 def check_thumbnails(self):153 def check_thumbnails(self):
144 """154 """
145155
=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/presentations/presentationplugin.py 2015-01-24 10:31:06 +0000
@@ -28,7 +28,7 @@
2828
29from PyQt4 import QtCore29from PyQt4 import QtCore
3030
31from openlp.core.common import AppLocation, translate31from openlp.core.common import AppLocation, Settings, translate
32from openlp.core.lib import Plugin, StringContent, build_icon32from openlp.core.lib import Plugin, StringContent, build_icon
33from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab33from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab
3434
@@ -43,7 +43,8 @@
43 'presentations/Powerpoint': QtCore.Qt.Checked,43 'presentations/Powerpoint': QtCore.Qt.Checked,
44 'presentations/Powerpoint Viewer': QtCore.Qt.Checked,44 'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
45 'presentations/Pdf': QtCore.Qt.Checked,45 'presentations/Pdf': QtCore.Qt.Checked,
46 'presentations/presentations files': []46 'presentations/presentations files': [],
47 'presentations/thumbnail_scheme': ''
47 }48 }
4849
4950
@@ -134,6 +135,19 @@
134 self.register_controllers(controller)135 self.register_controllers(controller)
135 return bool(self.controllers)136 return bool(self.controllers)
136137
138 def app_startup(self):
139 """
140 Perform tasks on application startup.
141 """
142 # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
143 super().app_startup()
144 files_from_config = Settings().value('presentations/presentations files')
145 for file in files_from_config:
146 self.media_item.clean_up_thumbnails(file)
147 self.media_item.list_view.clear()
148 Settings().setValue('presentations/thumbnail_scheme', 'md5')
149 self.media_item.validate_and_load(files_from_config)
150
137 def about(self):151 def about(self):
138 """152 """
139 Return information about this plugin.153 Return information about this plugin.
140154
=== modified file 'tests/functional/openlp_plugins/presentations/test_impresscontroller.py'
--- tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2015-01-18 13:39:21 +0000
+++ tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2015-01-24 10:31:06 +0000
@@ -31,8 +31,10 @@
31from tests.utils.constants import TEST_RESOURCES_PATH31from tests.utils.constants import TEST_RESOURCES_PATH
32from tests.helpers.testmixin import TestMixin32from tests.helpers.testmixin import TestMixin
3333
34from openlp.core.common import Settings
34from openlp.plugins.presentations.lib.impresscontroller import \35from openlp.plugins.presentations.lib.impresscontroller import \
35 ImpressController, ImpressDocument, TextType36 ImpressController, ImpressDocument, TextType
37from openlp.plugins.presentations.presentationplugin import __default_settings__
3638
3739
38class TestImpressController(TestCase, TestMixin):40class TestImpressController(TestCase, TestMixin):
@@ -79,6 +81,7 @@
79 def setUp(self):81 def setUp(self):
80 mocked_plugin = MagicMock()82 mocked_plugin = MagicMock()
81 mocked_plugin.settings_section = 'presentations'83 mocked_plugin.settings_section = 'presentations'
84 Settings().extend_default_settings(__default_settings__)
82 self.file_name = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx')85 self.file_name = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx')
83 self.ppc = ImpressController(mocked_plugin)86 self.ppc = ImpressController(mocked_plugin)
84 self.doc = ImpressDocument(self.ppc, self.file_name)87 self.doc = ImpressDocument(self.ppc, self.file_name)
8588
=== modified file 'tests/functional/openlp_plugins/presentations/test_pdfcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-01-18 13:39:21 +0000
+++ tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-01-24 10:31:06 +0000
@@ -36,7 +36,8 @@
36from tests.helpers.testmixin import TestMixin36from tests.helpers.testmixin import TestMixin
3737
38__default_settings__ = {38__default_settings__ = {
39 'presentations/enable_pdf_program': False39 'presentations/enable_pdf_program': False,
40 'presentations/thumbnail_scheme': ''
40}41}
4142
42SCREEN = {43SCREEN = {
4344
=== modified file 'tests/functional/test_init.py'
--- tests/functional/test_init.py 2015-01-18 13:39:21 +0000
+++ tests/functional/test_init.py 2015-01-24 10:31:06 +0000
@@ -22,13 +22,14 @@
22"""22"""
23Package to test the openlp.core.__init__ package.23Package to test the openlp.core.__init__ package.
24"""24"""
25from optparse import Values
25import os26import os
2627
27from unittest import TestCase28from unittest import TestCase
28from unittest.mock import MagicMock, patch29from unittest.mock import MagicMock, patch
29from PyQt4 import QtCore, QtGui30from PyQt4 import QtCore, QtGui
3031
31from openlp.core import OpenLP32from openlp.core import OpenLP, parse_options
32from openlp.core.common import Settings33from openlp.core.common import Settings
33from tests.helpers.testmixin import TestMixin34from tests.helpers.testmixin import TestMixin
3435
@@ -112,3 +113,17 @@
112 # THEN: It should ask if we want to create a backup113 # THEN: It should ask if we want to create a backup
113 self.assertEqual(Settings().value('core/application version'), '2.2.0', 'Version should be upgraded!')114 self.assertEqual(Settings().value('core/application version'), '2.2.0', 'Version should be upgraded!')
114 self.assertEqual(mocked_question.call_count, 1, 'A question should have been asked!')115 self.assertEqual(mocked_question.call_count, 1, 'A question should have been asked!')
116
117 def parse_options_short_options_test(self):
118 """
119 Test that parse_options parses short options correctly
120 """
121 # GIVEN: A list of vaild short options
122 options = ['-e', '-l', 'debug', '-pd', '-s', 'style', 'extra', 'qt', 'args']
123
124 # WHEN: Calling parse_options
125 resluts = parse_options(options)
126
127 # THEN: A tuple should be returned with the parsed options and left over args
128 self.assertEqual(resluts, (Values({'no_error_form': True, 'dev_version': True, 'portable': True,
129 'style': 'style', 'loglevel': 'debug'}), ['extra', 'qt', 'args']))