Merge lp:~tomasgroth/openlp/fix-theme-thumb into lp:openlp
- fix-theme-thumb
- Merge into trunk
Proposed by
Tomas Groth
Status: | Merged |
---|---|
Merged at revision: | 2877 |
Proposed branch: | lp:~tomasgroth/openlp/fix-theme-thumb |
Merge into: | lp:openlp |
Diff against target: |
541 lines (+148/-99) 9 files modified
openlp/core/display/render.py (+70/-27) openlp/core/ui/media/vlcplayer.py (+14/-13) openlp/core/ui/themeform.py (+20/-15) openlp/core/ui/thememanager.py (+12/-14) openlp/core/ui/themewizard.py (+9/-10) openlp/plugins/media/lib/mediaitem.py (+10/-9) openlp/plugins/songs/lib/songstab.py (+1/-1) tests/functional/openlp_core/ui/test_thememanager.py (+9/-9) tests/openlp_core/ui/test_themeform.py (+3/-1) |
To merge this branch: | bzr merge lp:~tomasgroth/openlp/fix-theme-thumb |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Bentley | Approve | ||
Raoul Snyman | Pending | ||
Review via email: mp+368596@code.launchpad.net |
This proposal supersedes a proposal from 2019-06-09.
Commit message
Add a webengine view for previewing themes.
Made VLC loading more robust.
A few minor fixes.
Description of the change
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 | # |
Revision history for this message
Tim Bentley (trb143) : Posted in a previous version of this proposal | # |
review:
Approve
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
I like it, but you'll just need to fix the tests.
review:
Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Linux tests failed, please see https:/
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Linux tests passed!
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Linting failed, please see https:/
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : | # |
Linux tests passed!
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : | # |
Linting passed!
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/display/render.py' |
2 | --- openlp/core/display/render.py 2019-04-13 13:00:22 +0000 |
3 | +++ openlp/core/display/render.py 2019-06-09 20:23:18 +0000 |
4 | @@ -24,6 +24,7 @@ |
5 | """ |
6 | import html |
7 | import logging |
8 | +import mako |
9 | import math |
10 | import os |
11 | import re |
12 | @@ -32,8 +33,10 @@ |
13 | from PyQt5 import QtWidgets, QtGui |
14 | |
15 | from openlp.core.common import ThemeLevel |
16 | +from openlp.core.common.i18n import translate |
17 | from openlp.core.common.mixins import LogMixin, RegistryProperties |
18 | from openlp.core.common.registry import Registry, RegistryBase |
19 | +from openlp.core.common.settings import Settings |
20 | from openlp.core.display.screens import ScreenList |
21 | from openlp.core.display.window import DisplayWindow |
22 | from openlp.core.lib import ItemCapabilities |
23 | @@ -58,8 +61,10 @@ |
24 | '{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \ |
25 | 'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n' |
26 | VERSE_FOR_LINE_COUNT = '\n'.join(map(str, range(100))) |
27 | -TITLE = 'Arky Arky (Unknown)' |
28 | -FOOTER = ['Public Domain', 'CCLI 123456'] |
29 | +TITLE = 'Arky Arky' |
30 | +AUTHOR = 'John Doe' |
31 | +FOOTER_COPYRIGHT = 'Public Domain' |
32 | +CCLI_NO = '123456' |
33 | |
34 | |
35 | def remove_tags(text, can_remove_chords=False): |
36 | @@ -425,7 +430,7 @@ |
37 | return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join(html_tags) |
38 | |
39 | |
40 | -class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): |
41 | +class ThemePreviewRenderer(LogMixin, DisplayWindow): |
42 | """ |
43 | A virtual display used for rendering thumbnails and other offscreen tasks |
44 | """ |
45 | @@ -435,24 +440,6 @@ |
46 | """ |
47 | super().__init__(*args, **kwargs) |
48 | self.force_page = False |
49 | - for screen in ScreenList(): |
50 | - if screen.is_display: |
51 | - self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(), |
52 | - screen.display_geometry.width(), screen.display_geometry.height()) |
53 | - break |
54 | - # If the display is not show'ed and hidden like this webegine will not render |
55 | - self.show() |
56 | - self.hide() |
57 | - self.theme_height = 0 |
58 | - self.theme_level = ThemeLevel.Global |
59 | - |
60 | - def set_theme_level(self, theme_level): |
61 | - """ |
62 | - Sets the theme level. |
63 | - |
64 | - :param theme_level: The theme level to be used. |
65 | - """ |
66 | - self.theme_level = theme_level |
67 | |
68 | def calculate_line_count(self): |
69 | """ |
70 | @@ -466,7 +453,30 @@ |
71 | """ |
72 | return self.run_javascript('Display.clearSlides();') |
73 | |
74 | - def generate_preview(self, theme_data, force_page=False): |
75 | + def generate_footer(self): |
76 | + """ |
77 | + """ |
78 | + footer_template = Settings().value('songs/footer template') |
79 | + # Keep this in sync with the list in songstab.py |
80 | + vars = { |
81 | + 'title': TITLE, |
82 | + 'authors_none_label': translate('OpenLP.Ui', 'Written by'), |
83 | + 'authors_words_label': translate('SongsPlugin.AuthorType', 'Words', |
84 | + 'Author who wrote the lyrics of a song'), |
85 | + 'authors_words': [AUTHOR], |
86 | + 'copyright': FOOTER_COPYRIGHT, |
87 | + 'ccli_license': Settings().value('core/ccli number'), |
88 | + 'ccli_license_label': translate('SongsPlugin.MediaItem', 'CCLI License'), |
89 | + 'ccli_number': CCLI_NO, |
90 | + } |
91 | + try: |
92 | + footer_html = mako.template.Template(footer_template).render_unicode(**vars).replace('\n', '') |
93 | + except mako.exceptions.SyntaxException: |
94 | + log.error('Failed to render Song footer html:\n' + mako.exceptions.text_error_template().render()) |
95 | + footer_html = 'Dummy footer text' |
96 | + return footer_html |
97 | + |
98 | + def generate_preview(self, theme_data, force_page=False, generate_screenshot=True): |
99 | """ |
100 | Generate a preview of a theme. |
101 | |
102 | @@ -479,14 +489,16 @@ |
103 | if not self.force_page: |
104 | self.set_theme(theme_data) |
105 | self.theme_height = theme_data.font_main_height |
106 | - slides = self.format_slide(render_tags(VERSE), None) |
107 | + slides = self.format_slide(VERSE, None) |
108 | verses = dict() |
109 | verses['title'] = TITLE |
110 | - verses['text'] = slides[0] |
111 | + verses['text'] = render_tags(slides[0]) |
112 | verses['verse'] = 'V1' |
113 | + verses['footer'] = self.generate_footer() |
114 | self.load_verses([verses]) |
115 | self.force_page = False |
116 | - return self.save_screenshot() |
117 | + if generate_screenshot: |
118 | + return self.save_screenshot() |
119 | self.force_page = False |
120 | return None |
121 | |
122 | @@ -515,7 +527,7 @@ |
123 | if item and item.is_capable(ItemCapabilities.CanWordSplit): |
124 | pages = self._paginate_slide_words(text.split('\n'), line_end) |
125 | # Songs and Custom |
126 | - elif item is None or item.is_capable(ItemCapabilities.CanSoftBreak): |
127 | + elif item is None or (item and item.is_capable(ItemCapabilities.CanSoftBreak)): |
128 | pages = [] |
129 | if '[---]' in text: |
130 | # Remove Overflow split if at start of the text |
131 | @@ -722,7 +734,8 @@ |
132 | :param text: The text to check. It may contain HTML tags. |
133 | """ |
134 | self.clear_slides() |
135 | - self.run_javascript('Display.addTextSlide("v1", "{text}", "Dummy Footer");'.format(text=text), is_sync=True) |
136 | + self.run_javascript('Display.addTextSlide("v1", "{text}", "Dummy Footer");' |
137 | + .format(text=text.replace('"', '\\"')), is_sync=True) |
138 | does_text_fits = self.run_javascript('Display.doesContentFit();', is_sync=True) |
139 | return does_text_fits |
140 | |
141 | @@ -745,3 +758,33 @@ |
142 | pixmap.save(fname, ext) |
143 | else: |
144 | return pixmap |
145 | + |
146 | + |
147 | +class Renderer(RegistryBase, RegistryProperties, ThemePreviewRenderer): |
148 | + """ |
149 | + A virtual display used for rendering thumbnails and other offscreen tasks |
150 | + """ |
151 | + def __init__(self, *args, **kwargs): |
152 | + """ |
153 | + Constructor |
154 | + """ |
155 | + super().__init__(*args, **kwargs) |
156 | + self.force_page = False |
157 | + for screen in ScreenList(): |
158 | + if screen.is_display: |
159 | + self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(), |
160 | + screen.display_geometry.width(), screen.display_geometry.height()) |
161 | + break |
162 | + # If the display is not show'ed and hidden like this webegine will not render |
163 | + self.show() |
164 | + self.hide() |
165 | + self.theme_height = 0 |
166 | + self.theme_level = ThemeLevel.Global |
167 | + |
168 | + def set_theme_level(self, theme_level): |
169 | + """ |
170 | + Sets the theme level. |
171 | + |
172 | + :param theme_level: The theme level to be used. |
173 | + """ |
174 | + self.theme_level = theme_level |
175 | |
176 | === modified file 'openlp/core/ui/media/vlcplayer.py' |
177 | --- openlp/core/ui/media/vlcplayer.py 2019-05-31 20:19:15 +0000 |
178 | +++ openlp/core/ui/media/vlcplayer.py 2019-06-09 20:23:18 +0000 |
179 | @@ -28,7 +28,6 @@ |
180 | import sys |
181 | import threading |
182 | from datetime import datetime |
183 | -import vlc |
184 | |
185 | from PyQt5 import QtWidgets |
186 | |
187 | @@ -62,25 +61,27 @@ |
188 | |
189 | :return: The "vlc" module, or None |
190 | """ |
191 | - if 'vlc' in sys.modules: |
192 | - # If VLC has already been imported, no need to do all the stuff below again |
193 | - is_vlc_available = False |
194 | + # Import the VLC module if not already done |
195 | + if 'vlc' not in sys.modules: |
196 | try: |
197 | - is_vlc_available = bool(sys.modules['vlc'].get_default_instance()) |
198 | - except Exception: |
199 | - pass |
200 | - if is_vlc_available: |
201 | - return sys.modules['vlc'] |
202 | - else: |
203 | + import vlc # noqa module is not used directly, but is used via sys.modules['vlc'] |
204 | + except ImportError: |
205 | return None |
206 | - else: |
207 | - return vlc |
208 | + # Verify that VLC is also loadable |
209 | + is_vlc_available = False |
210 | + try: |
211 | + is_vlc_available = bool(sys.modules['vlc'].get_default_instance()) |
212 | + except Exception: |
213 | + pass |
214 | + if is_vlc_available: |
215 | + return sys.modules['vlc'] |
216 | + return None |
217 | |
218 | |
219 | # On linux we need to initialise X threads, but not when running tests. |
220 | # This needs to happen on module load and not in get_vlc(), otherwise it can cause crashes on some DE on some setups |
221 | # (reported on Gnome3, Unity, Cinnamon, all GTK+ based) when using native filedialogs... |
222 | -if is_linux() and 'nose' not in sys.argv[0] and get_vlc(): |
223 | +if is_linux() and 'pytest' not in sys.argv[0] and get_vlc(): |
224 | try: |
225 | try: |
226 | x11 = ctypes.cdll.LoadLibrary('libX11.so.6') |
227 | |
228 | === modified file 'openlp/core/ui/themeform.py' |
229 | --- openlp/core/ui/themeform.py 2019-05-26 20:53:54 +0000 |
230 | +++ openlp/core/ui/themeform.py 2019-06-09 20:23:18 +0000 |
231 | @@ -172,16 +172,14 @@ |
232 | if not event: |
233 | event = QtGui.QResizeEvent(self.size(), self.size()) |
234 | QtWidgets.QWizard.resizeEvent(self, event) |
235 | - if hasattr(self, 'preview_page') and self.currentPage() == self.preview_page: |
236 | - frame_width = self.preview_box_label.lineWidth() |
237 | - pixmap_width = self.preview_area.width() - 2 * frame_width |
238 | - pixmap_height = self.preview_area.height() - 2 * frame_width |
239 | - aspect_ratio = float(pixmap_width) / pixmap_height |
240 | - if aspect_ratio < self.display_aspect_ratio: |
241 | - pixmap_height = int(pixmap_width / self.display_aspect_ratio + 0.5) |
242 | - else: |
243 | - pixmap_width = int(pixmap_height * self.display_aspect_ratio + 0.5) |
244 | - self.preview_box_label.setFixedSize(pixmap_width + 2 * frame_width, pixmap_height + 2 * frame_width) |
245 | + try: |
246 | + self.display_aspect_ratio = self.renderer.width() / self.renderer.height() |
247 | + except ZeroDivisionError: |
248 | + self.display_aspect_ratio = 1 |
249 | + # Make sure we don't resize before the widgets are actually created |
250 | + if hasattr(self, 'preview_area_layout'): |
251 | + self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio) |
252 | + self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width()) |
253 | |
254 | def validateCurrentPage(self): |
255 | """ |
256 | @@ -206,11 +204,17 @@ |
257 | self.setOption(QtWidgets.QWizard.HaveCustomButton1, enabled) |
258 | if self.page(page_id) == self.preview_page: |
259 | self.update_theme() |
260 | - frame = self.theme_manager.generate_image(self.theme) |
261 | - frame.setDevicePixelRatio(self.devicePixelRatio()) |
262 | - self.preview_box_label.setPixmap(frame) |
263 | - self.display_aspect_ratio = float(frame.width()) / frame.height() |
264 | + self.preview_box.set_theme(self.theme) |
265 | + self.preview_box.clear_slides() |
266 | + self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width()) |
267 | + try: |
268 | + self.display_aspect_ratio = self.renderer.width() / self.renderer.height() |
269 | + except ZeroDivisionError: |
270 | + self.display_aspect_ratio = 1 |
271 | + self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio) |
272 | self.resizeEvent() |
273 | + self.preview_box.show() |
274 | + self.preview_box.generate_preview(self.theme, False, False) |
275 | |
276 | def on_custom_1_button_clicked(self, number): |
277 | """ |
278 | @@ -398,6 +402,7 @@ |
279 | Handle the display and state of the Preview page. |
280 | """ |
281 | self.setField('name', self.theme.theme_name) |
282 | + self.preview_box.set_theme(self.theme) |
283 | |
284 | def on_background_combo_box_current_index_changed(self, index): |
285 | """ |
286 | @@ -558,5 +563,5 @@ |
287 | source_path = self.theme.background_filename |
288 | if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name): |
289 | return |
290 | - self.theme_manager.save_theme(self.theme, source_path, destination_path) |
291 | + self.theme_manager.save_theme(self.theme, source_path, destination_path, self.preview_box.save_screenshot()) |
292 | return QtWidgets.QDialog.accept(self) |
293 | |
294 | === modified file 'openlp/core/ui/thememanager.py' |
295 | --- openlp/core/ui/thememanager.py 2019-05-22 06:47:00 +0000 |
296 | +++ openlp/core/ui/thememanager.py 2019-06-09 20:23:18 +0000 |
297 | @@ -476,7 +476,7 @@ |
298 | if not theme_paths: |
299 | theme = Theme() |
300 | theme.theme_name = UiStrings().Default |
301 | - self._write_theme(theme) |
302 | + self.save_theme(theme) |
303 | Settings().setValue(self.settings_section + '/global theme', theme.theme_name) |
304 | self.application.set_normal_cursor() |
305 | |
306 | @@ -639,24 +639,14 @@ |
307 | return False |
308 | return True |
309 | |
310 | - def save_theme(self, theme, image_source_path, image_destination_path): |
311 | - """ |
312 | - Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list |
313 | - |
314 | - :param Theme theme: The theme data object. |
315 | - :param Path image_source_path: Where the theme image is currently located. |
316 | - :param Path image_destination_path: Where the Theme Image is to be saved to |
317 | - :rtype: None |
318 | - """ |
319 | - self._write_theme(theme, image_source_path, image_destination_path) |
320 | - |
321 | - def _write_theme(self, theme, image_source_path=None, image_destination_path=None): |
322 | + def save_theme(self, theme, image_source_path=None, image_destination_path=None, image=None): |
323 | """ |
324 | Writes the theme to the disk and handles the background image if necessary |
325 | |
326 | :param Theme theme: The theme data object. |
327 | :param Path image_source_path: Where the theme image is currently located. |
328 | :param Path image_destination_path: Where the Theme Image is to be saved to |
329 | + :param image: The example image of the theme. Optionally. |
330 | :rtype: None |
331 | """ |
332 | name = theme.theme_name |
333 | @@ -676,7 +666,15 @@ |
334 | shutil.copyfile(image_source_path, image_destination_path) |
335 | except OSError: |
336 | self.log_exception('Failed to save theme image') |
337 | - self.generate_and_save_image(name, theme) |
338 | + if image: |
339 | + sample_path_name = self.theme_path / '{file_name}.png'.format(file_name=name) |
340 | + if sample_path_name.exists(): |
341 | + sample_path_name.unlink() |
342 | + image.save(str(sample_path_name), 'png') |
343 | + thumb_path = self.thumb_path / '{name}.png'.format(name=name) |
344 | + create_thumb(sample_path_name, thumb_path, False) |
345 | + else: |
346 | + self.generate_and_save_image(name, theme) |
347 | |
348 | def generate_and_save_image(self, theme_name, theme): |
349 | """ |
350 | |
351 | === modified file 'openlp/core/ui/themewizard.py' |
352 | --- openlp/core/ui/themewizard.py 2019-04-13 13:00:22 +0000 |
353 | +++ openlp/core/ui/themewizard.py 2019-06-09 20:23:18 +0000 |
354 | @@ -31,6 +31,8 @@ |
355 | from openlp.core.ui.icons import UiIcons |
356 | from openlp.core.widgets.buttons import ColorButton |
357 | from openlp.core.widgets.edits import PathEdit |
358 | +from openlp.core.widgets.layouts import AspectRatioLayout |
359 | +from openlp.core.display.render import ThemePreviewRenderer |
360 | |
361 | |
362 | class Ui_ThemeWizard(object): |
363 | @@ -363,16 +365,13 @@ |
364 | self.preview_layout.addLayout(self.theme_name_layout) |
365 | self.preview_area = QtWidgets.QWidget(self.preview_page) |
366 | self.preview_area.setObjectName('PreviewArea') |
367 | - self.preview_area_layout = QtWidgets.QGridLayout(self.preview_area) |
368 | - self.preview_area_layout.setContentsMargins(0, 0, 0, 0) |
369 | - self.preview_area_layout.setColumnStretch(0, 1) |
370 | - self.preview_area_layout.setRowStretch(0, 1) |
371 | - self.preview_area_layout.setObjectName('preview_area_layout') |
372 | - self.preview_box_label = QtWidgets.QLabel(self.preview_area) |
373 | - self.preview_box_label.setFrameShape(QtWidgets.QFrame.Box) |
374 | - self.preview_box_label.setScaledContents(True) |
375 | - self.preview_box_label.setObjectName('preview_box_label') |
376 | - self.preview_area_layout.addWidget(self.preview_box_label) |
377 | + self.preview_area_layout = AspectRatioLayout(self.preview_area, 0.75) # Dummy ratio, will be update |
378 | + self.preview_area_layout.margin = 8 |
379 | + self.preview_area_layout.setSpacing(0) |
380 | + self.preview_area_layout.setObjectName('preview_web_layout') |
381 | + self.preview_box = ThemePreviewRenderer(self) |
382 | + self.preview_box.setObjectName('preview_box') |
383 | + self.preview_area_layout.addWidget(self.preview_box) |
384 | self.preview_layout.addWidget(self.preview_area) |
385 | theme_wizard.addPage(self.preview_page) |
386 | self.retranslate_ui(theme_wizard) |
387 | |
388 | === modified file 'openlp/plugins/media/lib/mediaitem.py' |
389 | --- openlp/plugins/media/lib/mediaitem.py 2019-06-01 06:59:45 +0000 |
390 | +++ openlp/plugins/media/lib/mediaitem.py 2019-06-09 20:23:18 +0000 |
391 | @@ -173,7 +173,7 @@ |
392 | item = self.list_view.currentItem() |
393 | if item is None: |
394 | return False |
395 | - filename = item.data(QtCore.Qt.UserRole) |
396 | + filename = str(item.data(QtCore.Qt.UserRole)) |
397 | # Special handling if the filename is a optical clip |
398 | if filename.startswith('optical:'): |
399 | (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename) |
400 | @@ -259,11 +259,12 @@ |
401 | # TODO needs to be fixed as no idea why this fails |
402 | # media.sort(key=lambda file_path: get_natural_key(file_path.name)) |
403 | for track in media: |
404 | - track_info = QtCore.QFileInfo(track) |
405 | + track_str = str(track) |
406 | + track_info = QtCore.QFileInfo(track_str) |
407 | item_name = None |
408 | - if track.startswith('optical:'): |
409 | + if track_str.startswith('optical:'): |
410 | # Handle optical based item |
411 | - (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track) |
412 | + (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str) |
413 | item_name = QtWidgets.QListWidgetItem(clip_name) |
414 | item_name.setIcon(UiIcons().optical) |
415 | item_name.setData(QtCore.Qt.UserRole, track) |
416 | @@ -272,22 +273,22 @@ |
417 | end=format_milliseconds(end))) |
418 | elif not os.path.exists(track): |
419 | # File doesn't exist, mark as error. |
420 | - file_name = os.path.split(str(track))[1] |
421 | + file_name = os.path.split(track_str)[1] |
422 | item_name = QtWidgets.QListWidgetItem(file_name) |
423 | item_name.setIcon(UiIcons().error) |
424 | item_name.setData(QtCore.Qt.UserRole, track) |
425 | - item_name.setToolTip(track) |
426 | + item_name.setToolTip(track_str) |
427 | elif track_info.isFile(): |
428 | # Normal media file handling. |
429 | - file_name = os.path.split(str(track))[1] |
430 | + file_name = os.path.split(track_str)[1] |
431 | item_name = QtWidgets.QListWidgetItem(file_name) |
432 | search = file_name.split('.')[-1].lower() |
433 | - if '*.{text}'.format(text=search) in self.media_controller.audio_extensions_list: |
434 | + if search in AUDIO_EXT: |
435 | item_name.setIcon(UiIcons().audio) |
436 | else: |
437 | item_name.setIcon(UiIcons().video) |
438 | item_name.setData(QtCore.Qt.UserRole, track) |
439 | - item_name.setToolTip(track) |
440 | + item_name.setToolTip(track_str) |
441 | if item_name: |
442 | self.list_view.addItem(item_name) |
443 | |
444 | |
445 | === modified file 'openlp/plugins/songs/lib/songstab.py' |
446 | --- openlp/plugins/songs/lib/songstab.py 2019-04-13 13:00:22 +0000 |
447 | +++ openlp/plugins/songs/lib/songstab.py 2019-06-09 20:23:18 +0000 |
448 | @@ -88,7 +88,7 @@ |
449 | self.footer_group_box = QtWidgets.QGroupBox(self.left_column) |
450 | self.footer_group_box.setObjectName('footer_group_box') |
451 | self.footer_layout = QtWidgets.QVBoxLayout(self.footer_group_box) |
452 | - self.footer_layout.setObjectName('chords_layout') |
453 | + self.footer_layout.setObjectName('footer_layout') |
454 | self.footer_info_label = QtWidgets.QLabel(self.footer_group_box) |
455 | self.footer_layout.addWidget(self.footer_info_label) |
456 | self.footer_placeholder_info = QtWidgets.QTextEdit(self.footer_group_box) |
457 | |
458 | === modified file 'tests/functional/openlp_core/ui/test_thememanager.py' |
459 | --- tests/functional/openlp_core/ui/test_thememanager.py 2019-05-22 06:47:00 +0000 |
460 | +++ tests/functional/openlp_core/ui/test_thememanager.py 2019-06-09 20:23:18 +0000 |
461 | @@ -83,7 +83,7 @@ |
462 | |
463 | @patch('openlp.core.ui.thememanager.shutil') |
464 | @patch('openlp.core.ui.thememanager.create_paths') |
465 | - def test_write_theme_same_image(self, mocked_create_paths, mocked_shutil): |
466 | + def test_save_theme_same_image(self, mocked_create_paths, mocked_shutil): |
467 | """ |
468 | Test that we don't try to overwrite a theme background image with itself |
469 | """ |
470 | @@ -98,16 +98,16 @@ |
471 | mocked_theme.extract_formatted_xml = MagicMock() |
472 | mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() |
473 | |
474 | - # WHEN: Calling _write_theme with path to the same image, but the path written slightly different |
475 | + # WHEN: Calling save_theme with path to the same image, but the path written slightly different |
476 | file_path_1 = RESOURCE_PATH / 'church.jpg' |
477 | - theme_manager._write_theme(mocked_theme, file_path_1, file_path_1) |
478 | + theme_manager.save_theme(mocked_theme, file_path_1, file_path_1) |
479 | |
480 | # THEN: The mocked_copyfile should not have been called |
481 | assert mocked_shutil.copyfile.called is False, 'copyfile should not be called' |
482 | |
483 | @patch('openlp.core.ui.thememanager.shutil') |
484 | @patch('openlp.core.ui.thememanager.create_paths') |
485 | - def test_write_theme_diff_images(self, mocked_create_paths, mocked_shutil): |
486 | + def test_save_theme_diff_images(self, mocked_create_paths, mocked_shutil): |
487 | """ |
488 | Test that we do overwrite a theme background image when a new is submitted |
489 | """ |
490 | @@ -121,15 +121,15 @@ |
491 | mocked_theme.theme_name = 'themename' |
492 | mocked_theme.filename = "filename" |
493 | |
494 | - # WHEN: Calling _write_theme with path to different images |
495 | + # WHEN: Calling save_theme with path to different images |
496 | file_path_1 = RESOURCE_PATH / 'church.jpg' |
497 | file_path_2 = RESOURCE_PATH / 'church2.jpg' |
498 | - theme_manager._write_theme(mocked_theme, file_path_1, file_path_2) |
499 | + theme_manager.save_theme(mocked_theme, file_path_1, file_path_2) |
500 | |
501 | # THEN: The mocked_copyfile should not have been called |
502 | assert mocked_shutil.copyfile.called is True, 'copyfile should be called' |
503 | |
504 | - def test_write_theme_special_char_name(self): |
505 | + def test_save_theme_special_char_name(self): |
506 | """ |
507 | Test that we can save themes with special characters in the name |
508 | """ |
509 | @@ -142,8 +142,8 @@ |
510 | mocked_theme.theme_name = 'theme 愛 name' |
511 | mocked_theme.export_theme.return_value = "{}" |
512 | |
513 | - # WHEN: Calling _write_theme with a theme with a name with special characters in it |
514 | - theme_manager._write_theme(mocked_theme) |
515 | + # WHEN: Calling save_theme with a theme with a name with special characters in it |
516 | + theme_manager.save_theme(mocked_theme) |
517 | |
518 | # THEN: It should have been created |
519 | assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \ |
520 | |
521 | === modified file 'tests/openlp_core/ui/test_themeform.py' |
522 | --- tests/openlp_core/ui/test_themeform.py 2019-04-13 13:00:22 +0000 |
523 | +++ tests/openlp_core/ui/test_themeform.py 2019-06-09 20:23:18 +0000 |
524 | @@ -23,6 +23,7 @@ |
525 | Interface tests to test the ThemeWizard class and related methods. |
526 | """ |
527 | from unittest import TestCase |
528 | +from unittest.mock import patch |
529 | |
530 | from openlp.core.common.registry import Registry |
531 | from openlp.core.ui.themeform import ThemeForm |
532 | @@ -39,7 +40,8 @@ |
533 | """ |
534 | Registry.create() |
535 | |
536 | - def test_create_theme_wizard(self): |
537 | + @patch('openlp.core.display.window.QtWidgets.QVBoxLayout') |
538 | + def test_create_theme_wizard(self, mocked_qvboxlayout): |
539 | """ |
540 | Test creating a ThemeForm instance |
541 | """ |
Linux tests failed, please see https:/ /ci.openlp. io/job/ MP-02-Linux_ Tests/176/ for more details