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
1=== modified file 'openlp/core/__init__.py'
2--- openlp/core/__init__.py 2015-01-18 13:39:21 +0000
3+++ openlp/core/__init__.py 2015-01-24 10:31:06 +0000
4@@ -263,6 +263,29 @@
5 return QtGui.QApplication.event(self, event)
6
7
8+def parse_options(args):
9+ """
10+ Parse the command line arguments
11+
12+ :param args: list of command line arguments
13+ :return: a tuple of parsed options of type optparse.Value and a list of remaining argsZ
14+ """
15+ # Set up command line options.
16+ usage = 'Usage: %prog [options] [qt-options]'
17+ parser = OptionParser(usage=usage)
18+ parser.add_option('-e', '--no-error-form', dest='no_error_form', action='store_true',
19+ help='Disable the error notification form.')
20+ parser.add_option('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
21+ help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
22+ parser.add_option('-p', '--portable', dest='portable', action='store_true',
23+ help='Specify if this should be run as a portable app, off a USB flash drive (not implemented).')
24+ parser.add_option('-d', '--dev-version', dest='dev_version', action='store_true',
25+ help='Ignore the version file and pull the version directly from Bazaar')
26+ parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).')
27+ # Parse command line options and deal with them. Use args supplied pragmatically if possible.
28+ return parser.parse_args(args) if args else parser.parse_args()
29+
30+
31 def set_up_logging(log_path):
32 """
33 Setup our logging using log_path
34@@ -284,21 +307,7 @@
35
36 :param args: Some args
37 """
38- # Set up command line options.
39- usage = 'Usage: %prog [options] [qt-options]'
40- parser = OptionParser(usage=usage)
41- parser.add_option('-e', '--no-error-form', dest='no_error_form', action='store_true',
42- help='Disable the error notification form.')
43- parser.add_option('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
44- help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
45- parser.add_option('-p', '--portable', dest='portable', action='store_true',
46- help='Specify if this should be run as a portable app, off a USB flash drive (not implemented).')
47- parser.add_option('-d', '--dev-version', dest='dev_version', action='store_true',
48- help='Ignore the version file and pull the version directly from Bazaar')
49- parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).')
50- # Parse command line options and deal with them.
51- # Use args supplied pragmatically if possible.
52- (options, args) = parser.parse_args(args) if args else parser.parse_args()
53+ (options, args) = parse_options(args)
54 qt_args = []
55 if options.loglevel.lower() in ['d', 'debug']:
56 log.setLevel(logging.DEBUG)
57
58=== modified file 'openlp/core/lib/mediamanageritem.py'
59--- openlp/core/lib/mediamanageritem.py 2015-01-18 13:39:21 +0000
60+++ openlp/core/lib/mediamanageritem.py 2015-01-24 10:31:06 +0000
61@@ -366,8 +366,7 @@
62 duplicates_found = False
63 files_added = False
64 for file_path in files:
65- filename = os.path.split(str(file_path))[1]
66- if filename in names:
67+ if file_path in full_list:
68 duplicates_found = True
69 else:
70 files_added = True
71
72=== modified file 'openlp/plugins/images/imageplugin.py'
73--- openlp/plugins/images/imageplugin.py 2015-01-18 13:39:21 +0000
74+++ openlp/plugins/images/imageplugin.py 2015-01-24 10:31:06 +0000
75@@ -23,6 +23,7 @@
76 from PyQt4 import QtGui
77
78 import logging
79+import os
80
81 from openlp.core.common import Registry, Settings, translate
82 from openlp.core.lib import Plugin, StringContent, ImageSource, build_icon
83@@ -66,10 +67,18 @@
84 """
85 Perform tasks on application startup.
86 """
87+ # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
88 Plugin.app_startup(self)
89 # Convert old settings-based image list to the database.
90 files_from_config = Settings().get_files_from_config(self)
91 if files_from_config:
92+ for file in files_from_config:
93+ filename = os.path.split(file)[1]
94+ thumb = os.path.join(self.media_item.service_path, filename)
95+ try:
96+ os.remove(thumb)
97+ except:
98+ pass
99 log.debug('Importing images list from old config: %s' % files_from_config)
100 self.media_item.save_new_images_list(files_from_config)
101
102@@ -79,6 +88,7 @@
103
104 :param settings: The Settings object containing the old settings.
105 """
106+ # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
107 files_from_config = settings.get_files_from_config(self)
108 if files_from_config:
109 log.debug('Importing images list from old config: %s' % files_from_config)
110
111=== modified file 'openlp/plugins/images/lib/mediaitem.py'
112--- openlp/plugins/images/lib/mediaitem.py 2015-01-19 22:49:18 +0000
113+++ openlp/plugins/images/lib/mediaitem.py 2015-01-24 10:31:06 +0000
114@@ -338,7 +338,8 @@
115 for imageFile in images:
116 log.debug('Loading image: %s', imageFile.filename)
117 filename = os.path.split(imageFile.filename)[1]
118- thumb = os.path.join(self.service_path, filename)
119+ ext = os.path.splitext(imageFile.filename)[1].lower()
120+ thumb = os.path.join(self.service_path, "%s%s" % (str(imageFile.id), ext))
121 if not os.path.exists(imageFile.filename):
122 icon = build_icon(':/general/general_delete.png')
123 else:
124
125=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
126--- openlp/plugins/presentations/lib/mediaitem.py 2015-01-18 13:39:21 +0000
127+++ openlp/plugins/presentations/lib/mediaitem.py 2015-01-24 10:31:06 +0000
128@@ -222,10 +222,7 @@
129 self.main_window.display_progress_bar(len(row_list))
130 for item in items:
131 filepath = str(item.data(QtCore.Qt.UserRole))
132- for cidx in self.controllers:
133- doc = self.controllers[cidx].add_document(filepath)
134- doc.presentation_deleted()
135- doc.close_presentation()
136+ self.clean_up_thumbnails(filepath)
137 self.main_window.increment_progress_bar()
138 self.main_window.finished_progress_bar()
139 self.application.set_busy_cursor()
140@@ -233,6 +230,18 @@
141 self.list_view.takeItem(row)
142 Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
143
144+ def clean_up_thumbnails(self, filepath):
145+ """
146+ Clean up the files created such as thumbnails
147+
148+ :param filepath: File path of the presention to clean up after
149+ :return: None
150+ """
151+ for cidx in self.controllers:
152+ doc = self.controllers[cidx].add_document(filepath)
153+ doc.presentation_deleted()
154+ doc.close_presentation()
155+
156 def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
157 context=ServiceItemContext.Service, presentation_file=None):
158 """
159
160=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
161--- openlp/plugins/presentations/lib/presentationcontroller.py 2015-01-18 13:39:21 +0000
162+++ openlp/plugins/presentations/lib/presentationcontroller.py 2015-01-24 10:31:06 +0000
163@@ -26,7 +26,7 @@
164
165 from PyQt4 import QtCore
166
167-from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists
168+from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, md5_hash
169 from openlp.core.lib import create_thumb, validate_thumb
170
171 log = logging.getLogger(__name__)
172@@ -132,13 +132,23 @@
173 """
174 The location where thumbnail images will be stored
175 """
176- return os.path.join(self.controller.thumbnail_folder, self.get_file_name())
177+ # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
178+ if Settings().value('presentations/thumbnail_scheme') == 'md5':
179+ folder = md5_hash('', self.file_path)
180+ else:
181+ folder = self.get_file_name()
182+ return os.path.join(self.controller.thumbnail_folder, folder)
183
184 def get_temp_folder(self):
185 """
186 The location where thumbnail images will be stored
187 """
188- return os.path.join(self.controller.temp_folder, self.get_file_name())
189+ # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
190+ if Settings().value('presentations/thumbnail_scheme') == 'md5':
191+ folder = md5_hash('', self.file_path)
192+ else:
193+ folder = folder = self.get_file_name()
194+ return os.path.join(self.controller.temp_folder, folder)
195
196 def check_thumbnails(self):
197 """
198
199=== modified file 'openlp/plugins/presentations/presentationplugin.py'
200--- openlp/plugins/presentations/presentationplugin.py 2015-01-18 13:39:21 +0000
201+++ openlp/plugins/presentations/presentationplugin.py 2015-01-24 10:31:06 +0000
202@@ -28,7 +28,7 @@
203
204 from PyQt4 import QtCore
205
206-from openlp.core.common import AppLocation, translate
207+from openlp.core.common import AppLocation, Settings, translate
208 from openlp.core.lib import Plugin, StringContent, build_icon
209 from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab
210
211@@ -43,7 +43,8 @@
212 'presentations/Powerpoint': QtCore.Qt.Checked,
213 'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
214 'presentations/Pdf': QtCore.Qt.Checked,
215- 'presentations/presentations files': []
216+ 'presentations/presentations files': [],
217+ 'presentations/thumbnail_scheme': ''
218 }
219
220
221@@ -134,6 +135,19 @@
222 self.register_controllers(controller)
223 return bool(self.controllers)
224
225+ def app_startup(self):
226+ """
227+ Perform tasks on application startup.
228+ """
229+ # TODO: Can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
230+ super().app_startup()
231+ files_from_config = Settings().value('presentations/presentations files')
232+ for file in files_from_config:
233+ self.media_item.clean_up_thumbnails(file)
234+ self.media_item.list_view.clear()
235+ Settings().setValue('presentations/thumbnail_scheme', 'md5')
236+ self.media_item.validate_and_load(files_from_config)
237+
238 def about(self):
239 """
240 Return information about this plugin.
241
242=== modified file 'tests/functional/openlp_plugins/presentations/test_impresscontroller.py'
243--- tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2015-01-18 13:39:21 +0000
244+++ tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2015-01-24 10:31:06 +0000
245@@ -31,8 +31,10 @@
246 from tests.utils.constants import TEST_RESOURCES_PATH
247 from tests.helpers.testmixin import TestMixin
248
249+from openlp.core.common import Settings
250 from openlp.plugins.presentations.lib.impresscontroller import \
251 ImpressController, ImpressDocument, TextType
252+from openlp.plugins.presentations.presentationplugin import __default_settings__
253
254
255 class TestImpressController(TestCase, TestMixin):
256@@ -79,6 +81,7 @@
257 def setUp(self):
258 mocked_plugin = MagicMock()
259 mocked_plugin.settings_section = 'presentations'
260+ Settings().extend_default_settings(__default_settings__)
261 self.file_name = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx')
262 self.ppc = ImpressController(mocked_plugin)
263 self.doc = ImpressDocument(self.ppc, self.file_name)
264
265=== modified file 'tests/functional/openlp_plugins/presentations/test_pdfcontroller.py'
266--- tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-01-18 13:39:21 +0000
267+++ tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-01-24 10:31:06 +0000
268@@ -36,7 +36,8 @@
269 from tests.helpers.testmixin import TestMixin
270
271 __default_settings__ = {
272- 'presentations/enable_pdf_program': False
273+ 'presentations/enable_pdf_program': False,
274+ 'presentations/thumbnail_scheme': ''
275 }
276
277 SCREEN = {
278
279=== modified file 'tests/functional/test_init.py'
280--- tests/functional/test_init.py 2015-01-18 13:39:21 +0000
281+++ tests/functional/test_init.py 2015-01-24 10:31:06 +0000
282@@ -22,13 +22,14 @@
283 """
284 Package to test the openlp.core.__init__ package.
285 """
286+from optparse import Values
287 import os
288
289 from unittest import TestCase
290 from unittest.mock import MagicMock, patch
291 from PyQt4 import QtCore, QtGui
292
293-from openlp.core import OpenLP
294+from openlp.core import OpenLP, parse_options
295 from openlp.core.common import Settings
296 from tests.helpers.testmixin import TestMixin
297
298@@ -112,3 +113,17 @@
299 # THEN: It should ask if we want to create a backup
300 self.assertEqual(Settings().value('core/application version'), '2.2.0', 'Version should be upgraded!')
301 self.assertEqual(mocked_question.call_count, 1, 'A question should have been asked!')
302+
303+ def parse_options_short_options_test(self):
304+ """
305+ Test that parse_options parses short options correctly
306+ """
307+ # GIVEN: A list of vaild short options
308+ options = ['-e', '-l', 'debug', '-pd', '-s', 'style', 'extra', 'qt', 'args']
309+
310+ # WHEN: Calling parse_options
311+ resluts = parse_options(options)
312+
313+ # THEN: A tuple should be returned with the parsed options and left over args
314+ self.assertEqual(resluts, (Values({'no_error_form': True, 'dev_version': True, 'portable': True,
315+ 'style': 'style', 'loglevel': 'debug'}), ['extra', 'qt', 'args']))