Status: | Merged |
---|---|
Merged at revision: | 2771 |
Proposed branch: | lp:~phill-ridout/openlp/pathlib7 |
Merge into: | lp:openlp |
Diff against target: |
1282 lines (+304/-310) 13 files modified
openlp/core/lib/json/theme.json (+1/-1) openlp/core/lib/renderer.py (+4/-3) openlp/core/lib/theme.py (+19/-15) openlp/core/ui/maindisplay.py (+4/-4) openlp/core/ui/themeform.py (+31/-27) openlp/core/ui/thememanager.py (+184/-209) openlp/core/ui/themestab.py (+2/-2) openlp/plugins/images/lib/upgrade.py (+0/-1) tests/functional/openlp_core_lib/test_theme.py (+6/-5) tests/functional/openlp_core_ui/test_maindisplay.py (+9/-9) tests/functional/openlp_core_ui/test_themeform.py (+1/-1) tests/functional/openlp_core_ui/test_thememanager.py (+22/-29) tests/interfaces/openlp_core_ui/test_thememanager.py (+21/-4) |
To merge this branch: | bzr merge lp:~phill-ridout/openlp/pathlib7 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tomas Groth | Approve | ||
Tim Bentley | Approve | ||
Review via email: mp+331364@code.launchpad.net |
Commit message
Description of the change
pathlib changes to the theme code
lp:~phill-ridout/openlp/pathlib7 (revision 2773)
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
To post a comment you must log in.
Revision history for this message
Phill (phill-ridout) wrote : | # |
Revision history for this message
Tim Bentley (trb143) wrote : | # |
Looks good and finishes my changes from XML to json. Thanks
review:
Approve
Revision history for this message
Tomas Groth (tomasgroth) wrote : | # |
Seems legit ;-)
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'openlp/core/lib/json/theme.json' | |||
2 | --- openlp/core/lib/json/theme.json 2013-10-18 18:10:47 +0000 | |||
3 | +++ openlp/core/lib/json/theme.json 2017-09-26 17:09:04 +0000 | |||
4 | @@ -4,7 +4,7 @@ | |||
5 | 4 | "color": "#000000", | 4 | "color": "#000000", |
6 | 5 | "direction": "vertical", | 5 | "direction": "vertical", |
7 | 6 | "end_color": "#000000", | 6 | "end_color": "#000000", |
9 | 7 | "filename": "", | 7 | "filename": null, |
10 | 8 | "start_color": "#000000", | 8 | "start_color": "#000000", |
11 | 9 | "type": "solid" | 9 | "type": "solid" |
12 | 10 | }, | 10 | }, |
13 | 11 | 11 | ||
14 | === modified file 'openlp/core/lib/renderer.py' | |||
15 | --- openlp/core/lib/renderer.py 2017-01-25 21:17:27 +0000 | |||
16 | +++ openlp/core/lib/renderer.py 2017-09-26 17:09:04 +0000 | |||
17 | @@ -26,6 +26,7 @@ | |||
18 | 26 | from PyQt5 import QtGui, QtCore, QtWebKitWidgets | 26 | from PyQt5 import QtGui, QtCore, QtWebKitWidgets |
19 | 27 | 27 | ||
20 | 28 | from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, RegistryMixin, Settings | 28 | from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, RegistryMixin, Settings |
21 | 29 | from openlp.core.common.path import path_to_str | ||
22 | 29 | from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ScreenList, ServiceItem, expand_tags, \ | 30 | from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ScreenList, ServiceItem, expand_tags, \ |
23 | 30 | build_lyrics_format_css, build_lyrics_outline_css, build_chords_css | 31 | build_lyrics_format_css, build_lyrics_outline_css, build_chords_css |
24 | 31 | from openlp.core.common import ThemeLevel | 32 | from openlp.core.common import ThemeLevel |
25 | @@ -118,7 +119,7 @@ | |||
26 | 118 | theme_data, main_rect, footer_rect = self._theme_dimensions[theme_name] | 119 | theme_data, main_rect, footer_rect = self._theme_dimensions[theme_name] |
27 | 119 | # if No file do not update cache | 120 | # if No file do not update cache |
28 | 120 | if theme_data.background_filename: | 121 | if theme_data.background_filename: |
30 | 121 | self.image_manager.add_image(theme_data.background_filename, | 122 | self.image_manager.add_image(path_to_str(theme_data.background_filename), |
31 | 122 | ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) | 123 | ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) |
32 | 123 | 124 | ||
33 | 124 | def pre_render(self, override_theme_data=None): | 125 | def pre_render(self, override_theme_data=None): |
34 | @@ -207,8 +208,8 @@ | |||
35 | 207 | service_item.raw_footer = FOOTER | 208 | service_item.raw_footer = FOOTER |
36 | 208 | # if No file do not update cache | 209 | # if No file do not update cache |
37 | 209 | if theme_data.background_filename: | 210 | if theme_data.background_filename: |
40 | 210 | self.image_manager.add_image( | 211 | self.image_manager.add_image(path_to_str(theme_data.background_filename), |
41 | 211 | theme_data.background_filename, ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) | 212 | ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) |
42 | 212 | theme_data, main, footer = self.pre_render(theme_data) | 213 | theme_data, main, footer = self.pre_render(theme_data) |
43 | 213 | service_item.theme_data = theme_data | 214 | service_item.theme_data = theme_data |
44 | 214 | service_item.main = main | 215 | service_item.main = main |
45 | 215 | 216 | ||
46 | === modified file 'openlp/core/lib/theme.py' | |||
47 | --- openlp/core/lib/theme.py 2017-08-12 17:45:56 +0000 | |||
48 | +++ openlp/core/lib/theme.py 2017-09-26 17:09:04 +0000 | |||
49 | @@ -22,13 +22,13 @@ | |||
50 | 22 | """ | 22 | """ |
51 | 23 | Provide the theme XML and handling functions for OpenLP v2 themes. | 23 | Provide the theme XML and handling functions for OpenLP v2 themes. |
52 | 24 | """ | 24 | """ |
54 | 25 | import os | 25 | import json |
55 | 26 | import logging | 26 | import logging |
56 | 27 | import json | ||
57 | 28 | 27 | ||
58 | 29 | from lxml import etree, objectify | 28 | from lxml import etree, objectify |
59 | 30 | from openlp.core.common import AppLocation, de_hump | 29 | from openlp.core.common import AppLocation, de_hump |
61 | 31 | 30 | from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder | |
62 | 31 | from openlp.core.common.path import Path, str_to_path | ||
63 | 32 | from openlp.core.lib import str_to_bool, ScreenList, get_text_file_string | 32 | from openlp.core.lib import str_to_bool, ScreenList, get_text_file_string |
64 | 33 | 33 | ||
65 | 34 | log = logging.getLogger(__name__) | 34 | log = logging.getLogger(__name__) |
66 | @@ -160,9 +160,8 @@ | |||
67 | 160 | # basic theme object with defaults | 160 | # basic theme object with defaults |
68 | 161 | json_path = AppLocation.get_directory(AppLocation.AppDir) / 'core' / 'lib' / 'json' / 'theme.json' | 161 | json_path = AppLocation.get_directory(AppLocation.AppDir) / 'core' / 'lib' / 'json' / 'theme.json' |
69 | 162 | jsn = get_text_file_string(json_path) | 162 | jsn = get_text_file_string(json_path) |
73 | 163 | jsn = json.loads(jsn) | 163 | self.load_theme(jsn) |
74 | 164 | self.expand_json(jsn) | 164 | self.background_filename = None |
72 | 165 | self.background_filename = '' | ||
75 | 166 | 165 | ||
76 | 167 | def expand_json(self, var, prev=None): | 166 | def expand_json(self, var, prev=None): |
77 | 168 | """ | 167 | """ |
78 | @@ -174,8 +173,6 @@ | |||
79 | 174 | for key, value in var.items(): | 173 | for key, value in var.items(): |
80 | 175 | if prev: | 174 | if prev: |
81 | 176 | key = prev + "_" + key | 175 | key = prev + "_" + key |
82 | 177 | else: | ||
83 | 178 | key = key | ||
84 | 179 | if isinstance(value, dict): | 176 | if isinstance(value, dict): |
85 | 180 | self.expand_json(value, key) | 177 | self.expand_json(value, key) |
86 | 181 | else: | 178 | else: |
87 | @@ -185,13 +182,13 @@ | |||
88 | 185 | """ | 182 | """ |
89 | 186 | Add the path name to the image name so the background can be rendered. | 183 | Add the path name to the image name so the background can be rendered. |
90 | 187 | 184 | ||
92 | 188 | :param path: The path name to be added. | 185 | :param openlp.core.common.path.Path path: The path name to be added. |
93 | 186 | :rtype: None | ||
94 | 189 | """ | 187 | """ |
95 | 190 | if self.background_type == 'image' or self.background_type == 'video': | 188 | if self.background_type == 'image' or self.background_type == 'video': |
96 | 191 | if self.background_filename and path: | 189 | if self.background_filename and path: |
97 | 192 | self.theme_name = self.theme_name.strip() | 190 | self.theme_name = self.theme_name.strip() |
100 | 193 | self.background_filename = self.background_filename.strip() | 191 | self.background_filename = path / self.theme_name / self.background_filename |
99 | 194 | self.background_filename = os.path.join(path, self.theme_name, self.background_filename) | ||
101 | 195 | 192 | ||
102 | 196 | def set_default_header_footer(self): | 193 | def set_default_header_footer(self): |
103 | 197 | """ | 194 | """ |
104 | @@ -206,16 +203,21 @@ | |||
105 | 206 | self.font_footer_y = current_screen['size'].height() * 9 / 10 | 203 | self.font_footer_y = current_screen['size'].height() * 9 / 10 |
106 | 207 | self.font_footer_height = current_screen['size'].height() / 10 | 204 | self.font_footer_height = current_screen['size'].height() / 10 |
107 | 208 | 205 | ||
109 | 209 | def load_theme(self, theme): | 206 | def load_theme(self, theme, theme_path=None): |
110 | 210 | """ | 207 | """ |
111 | 211 | Convert the JSON file and expand it. | 208 | Convert the JSON file and expand it. |
112 | 212 | 209 | ||
113 | 213 | :param theme: the theme string | 210 | :param theme: the theme string |
114 | 211 | :param openlp.core.common.path.Path theme_path: The path to the theme | ||
115 | 212 | :rtype: None | ||
116 | 214 | """ | 213 | """ |
118 | 215 | jsn = json.loads(theme) | 214 | if theme_path: |
119 | 215 | jsn = json.loads(theme, cls=OpenLPJsonDecoder, base_path=theme_path) | ||
120 | 216 | else: | ||
121 | 217 | jsn = json.loads(theme, cls=OpenLPJsonDecoder) | ||
122 | 216 | self.expand_json(jsn) | 218 | self.expand_json(jsn) |
123 | 217 | 219 | ||
125 | 218 | def export_theme(self): | 220 | def export_theme(self, theme_path=None): |
126 | 219 | """ | 221 | """ |
127 | 220 | Loop through the fields and build a dictionary of them | 222 | Loop through the fields and build a dictionary of them |
128 | 221 | 223 | ||
129 | @@ -223,7 +225,9 @@ | |||
130 | 223 | theme_data = {} | 225 | theme_data = {} |
131 | 224 | for attr, value in self.__dict__.items(): | 226 | for attr, value in self.__dict__.items(): |
132 | 225 | theme_data["{attr}".format(attr=attr)] = value | 227 | theme_data["{attr}".format(attr=attr)] = value |
134 | 226 | return json.dumps(theme_data) | 228 | if theme_path: |
135 | 229 | return json.dumps(theme_data, cls=OpenLPJsonEncoder, base_path=theme_path) | ||
136 | 230 | return json.dumps(theme_data, cls=OpenLPJsonEncoder) | ||
137 | 227 | 231 | ||
138 | 228 | def parse(self, xml): | 232 | def parse(self, xml): |
139 | 229 | """ | 233 | """ |
140 | 230 | 234 | ||
141 | === modified file 'openlp/core/ui/maindisplay.py' | |||
142 | --- openlp/core/ui/maindisplay.py 2017-09-05 04:28:50 +0000 | |||
143 | +++ openlp/core/ui/maindisplay.py 2017-09-26 17:09:04 +0000 | |||
144 | @@ -346,7 +346,7 @@ | |||
145 | 346 | if not hasattr(self, 'service_item'): | 346 | if not hasattr(self, 'service_item'): |
146 | 347 | return False | 347 | return False |
147 | 348 | self.override['image'] = path | 348 | self.override['image'] = path |
149 | 349 | self.override['theme'] = self.service_item.theme_data.background_filename | 349 | self.override['theme'] = path_to_str(self.service_item.theme_data.background_filename) |
150 | 350 | self.image(path) | 350 | self.image(path) |
151 | 351 | # Update the preview frame. | 351 | # Update the preview frame. |
152 | 352 | if self.is_live: | 352 | if self.is_live: |
153 | @@ -454,7 +454,7 @@ | |||
154 | 454 | Registry().execute('video_background_replaced') | 454 | Registry().execute('video_background_replaced') |
155 | 455 | self.override = {} | 455 | self.override = {} |
156 | 456 | # We have a different theme. | 456 | # We have a different theme. |
158 | 457 | elif self.override['theme'] != service_item.theme_data.background_filename: | 457 | elif self.override['theme'] != path_to_str(service_item.theme_data.background_filename): |
159 | 458 | Registry().execute('live_theme_changed') | 458 | Registry().execute('live_theme_changed') |
160 | 459 | self.override = {} | 459 | self.override = {} |
161 | 460 | else: | 460 | else: |
162 | @@ -466,7 +466,7 @@ | |||
163 | 466 | if self.service_item.theme_data.background_type == 'image': | 466 | if self.service_item.theme_data.background_type == 'image': |
164 | 467 | if self.service_item.theme_data.background_filename: | 467 | if self.service_item.theme_data.background_filename: |
165 | 468 | self.service_item.bg_image_bytes = self.image_manager.get_image_bytes( | 468 | self.service_item.bg_image_bytes = self.image_manager.get_image_bytes( |
167 | 469 | self.service_item.theme_data.background_filename, ImageSource.Theme) | 469 | path_to_str(self.service_item.theme_data.background_filename), ImageSource.Theme) |
168 | 470 | if image_path: | 470 | if image_path: |
169 | 471 | image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin) | 471 | image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin) |
170 | 472 | created_html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes, | 472 | created_html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes, |
171 | @@ -488,7 +488,7 @@ | |||
172 | 488 | path = os.path.join(str(AppLocation.get_section_data_path('themes')), | 488 | path = os.path.join(str(AppLocation.get_section_data_path('themes')), |
173 | 489 | self.service_item.theme_data.theme_name) | 489 | self.service_item.theme_data.theme_name) |
174 | 490 | service_item.add_from_command(path, | 490 | service_item.add_from_command(path, |
176 | 491 | self.service_item.theme_data.background_filename, | 491 | path_to_str(self.service_item.theme_data.background_filename), |
177 | 492 | ':/media/slidecontroller_multimedia.png') | 492 | ':/media/slidecontroller_multimedia.png') |
178 | 493 | self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True) | 493 | self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True) |
179 | 494 | self._hide_mouse() | 494 | self._hide_mouse() |
180 | 495 | 495 | ||
181 | === modified file 'openlp/core/ui/themeform.py' | |||
182 | --- openlp/core/ui/themeform.py 2017-08-25 20:03:25 +0000 | |||
183 | +++ openlp/core/ui/themeform.py 2017-09-26 17:09:04 +0000 | |||
184 | @@ -28,7 +28,6 @@ | |||
185 | 28 | from PyQt5 import QtCore, QtGui, QtWidgets | 28 | from PyQt5 import QtCore, QtGui, QtWidgets |
186 | 29 | 29 | ||
187 | 30 | from openlp.core.common import Registry, RegistryProperties, UiStrings, translate, get_images_filter, is_not_image_file | 30 | from openlp.core.common import Registry, RegistryProperties, UiStrings, translate, get_images_filter, is_not_image_file |
188 | 31 | from openlp.core.common.path import Path, path_to_str, str_to_path | ||
189 | 32 | from openlp.core.lib.theme import BackgroundType, BackgroundGradientType | 31 | from openlp.core.lib.theme import BackgroundType, BackgroundGradientType |
190 | 33 | from openlp.core.lib.ui import critical_error_message_box | 32 | from openlp.core.lib.ui import critical_error_message_box |
191 | 34 | from openlp.core.ui import ThemeLayoutForm | 33 | from openlp.core.ui import ThemeLayoutForm |
192 | @@ -61,7 +60,7 @@ | |||
193 | 61 | self.setupUi(self) | 60 | self.setupUi(self) |
194 | 62 | self.registerFields() | 61 | self.registerFields() |
195 | 63 | self.update_theme_allowed = True | 62 | self.update_theme_allowed = True |
197 | 64 | self.temp_background_filename = '' | 63 | self.temp_background_filename = None |
198 | 65 | self.theme_layout_form = ThemeLayoutForm(self) | 64 | self.theme_layout_form = ThemeLayoutForm(self) |
199 | 66 | self.background_combo_box.currentIndexChanged.connect(self.on_background_combo_box_current_index_changed) | 65 | self.background_combo_box.currentIndexChanged.connect(self.on_background_combo_box_current_index_changed) |
200 | 67 | self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed) | 66 | self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed) |
201 | @@ -188,8 +187,7 @@ | |||
202 | 188 | """ | 187 | """ |
203 | 189 | background_image = BackgroundType.to_string(BackgroundType.Image) | 188 | background_image = BackgroundType.to_string(BackgroundType.Image) |
204 | 190 | if self.page(self.currentId()) == self.background_page and \ | 189 | if self.page(self.currentId()) == self.background_page and \ |
207 | 191 | self.theme.background_type == background_image and \ | 190 | self.theme.background_type == background_image and is_not_image_file(self.theme.background_filename): |
206 | 192 | is_not_image_file(Path(self.theme.background_filename)): | ||
208 | 193 | QtWidgets.QMessageBox.critical(self, translate('OpenLP.ThemeWizard', 'Background Image Empty'), | 191 | QtWidgets.QMessageBox.critical(self, translate('OpenLP.ThemeWizard', 'Background Image Empty'), |
209 | 194 | translate('OpenLP.ThemeWizard', 'You have not selected a ' | 192 | translate('OpenLP.ThemeWizard', 'You have not selected a ' |
210 | 195 | 'background image. Please select one before continuing.')) | 193 | 'background image. Please select one before continuing.')) |
211 | @@ -273,7 +271,7 @@ | |||
212 | 273 | Run the wizard. | 271 | Run the wizard. |
213 | 274 | """ | 272 | """ |
214 | 275 | log.debug('Editing theme {name}'.format(name=self.theme.theme_name)) | 273 | log.debug('Editing theme {name}'.format(name=self.theme.theme_name)) |
216 | 276 | self.temp_background_filename = '' | 274 | self.temp_background_filename = None |
217 | 277 | self.update_theme_allowed = False | 275 | self.update_theme_allowed = False |
218 | 278 | self.set_defaults() | 276 | self.set_defaults() |
219 | 279 | self.update_theme_allowed = True | 277 | self.update_theme_allowed = True |
220 | @@ -318,11 +316,11 @@ | |||
221 | 318 | self.setField('background_type', 1) | 316 | self.setField('background_type', 1) |
222 | 319 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Image): | 317 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Image): |
223 | 320 | self.image_color_button.color = self.theme.background_border_color | 318 | self.image_color_button.color = self.theme.background_border_color |
225 | 321 | self.image_path_edit.path = str_to_path(self.theme.background_filename) | 319 | self.image_path_edit.path = self.theme.background_filename |
226 | 322 | self.setField('background_type', 2) | 320 | self.setField('background_type', 2) |
227 | 323 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video): | 321 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video): |
228 | 324 | self.video_color_button.color = self.theme.background_border_color | 322 | self.video_color_button.color = self.theme.background_border_color |
230 | 325 | self.video_path_edit.path = str_to_path(self.theme.background_filename) | 323 | self.video_path_edit.path = self.theme.background_filename |
231 | 326 | self.setField('background_type', 4) | 324 | self.setField('background_type', 4) |
232 | 327 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent): | 325 | elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent): |
233 | 328 | self.setField('background_type', 3) | 326 | self.setField('background_type', 3) |
234 | @@ -402,14 +400,14 @@ | |||
235 | 402 | self.theme.background_type = BackgroundType.to_string(index) | 400 | self.theme.background_type = BackgroundType.to_string(index) |
236 | 403 | if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \ | 401 | if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \ |
237 | 404 | self.theme.background_type != BackgroundType.to_string(BackgroundType.Video) and \ | 402 | self.theme.background_type != BackgroundType.to_string(BackgroundType.Video) and \ |
239 | 405 | self.temp_background_filename == '': | 403 | self.temp_background_filename is None: |
240 | 406 | self.temp_background_filename = self.theme.background_filename | 404 | self.temp_background_filename = self.theme.background_filename |
242 | 407 | self.theme.background_filename = '' | 405 | self.theme.background_filename = None |
243 | 408 | if (self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or | 406 | if (self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or |
244 | 409 | self.theme.background_type != BackgroundType.to_string(BackgroundType.Video)) and \ | 407 | self.theme.background_type != BackgroundType.to_string(BackgroundType.Video)) and \ |
246 | 410 | self.temp_background_filename != '': | 408 | self.temp_background_filename is not None: |
247 | 411 | self.theme.background_filename = self.temp_background_filename | 409 | self.theme.background_filename = self.temp_background_filename |
249 | 412 | self.temp_background_filename = '' | 410 | self.temp_background_filename = None |
250 | 413 | self.set_background_page_values() | 411 | self.set_background_page_values() |
251 | 414 | 412 | ||
252 | 415 | def on_gradient_combo_box_current_index_changed(self, index): | 413 | def on_gradient_combo_box_current_index_changed(self, index): |
253 | @@ -450,18 +448,24 @@ | |||
254 | 450 | """ | 448 | """ |
255 | 451 | self.theme.background_end_color = color | 449 | self.theme.background_end_color = color |
256 | 452 | 450 | ||
262 | 453 | def on_image_path_edit_path_changed(self, file_path): | 451 | def on_image_path_edit_path_changed(self, new_path): |
263 | 454 | """ | 452 | """ |
264 | 455 | Background Image button pushed. | 453 | Handle the `pathEditChanged` signal from image_path_edit |
265 | 456 | """ | 454 | |
266 | 457 | self.theme.background_filename = path_to_str(file_path) | 455 | :param openlp.core.common.path.Path new_path: Path to the new image |
267 | 456 | :rtype: None | ||
268 | 457 | """ | ||
269 | 458 | self.theme.background_filename = new_path | ||
270 | 458 | self.set_background_page_values() | 459 | self.set_background_page_values() |
271 | 459 | 460 | ||
277 | 460 | def on_video_path_edit_path_changed(self, file_path): | 461 | def on_video_path_edit_path_changed(self, new_path): |
278 | 461 | """ | 462 | """ |
279 | 462 | Background video button pushed. | 463 | Handle the `pathEditChanged` signal from video_path_edit |
280 | 463 | """ | 464 | |
281 | 464 | self.theme.background_filename = path_to_str(file_path) | 465 | :param openlp.core.common.path.Path new_path: Path to the new video |
282 | 466 | :rtype: None | ||
283 | 467 | """ | ||
284 | 468 | self.theme.background_filename = new_path | ||
285 | 465 | self.set_background_page_values() | 469 | self.set_background_page_values() |
286 | 466 | 470 | ||
287 | 467 | def on_main_color_changed(self, color): | 471 | def on_main_color_changed(self, color): |
288 | @@ -537,14 +541,14 @@ | |||
289 | 537 | translate('OpenLP.ThemeWizard', 'Theme Name Invalid'), | 541 | translate('OpenLP.ThemeWizard', 'Theme Name Invalid'), |
290 | 538 | translate('OpenLP.ThemeWizard', 'Invalid theme name. Please enter one.')) | 542 | translate('OpenLP.ThemeWizard', 'Invalid theme name. Please enter one.')) |
291 | 539 | return | 543 | return |
294 | 540 | save_from = None | 544 | source_path = None |
295 | 541 | save_to = None | 545 | destination_path = None |
296 | 542 | if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \ | 546 | if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \ |
297 | 543 | self.theme.background_type == BackgroundType.to_string(BackgroundType.Video): | 547 | self.theme.background_type == BackgroundType.to_string(BackgroundType.Video): |
301 | 544 | filename = os.path.split(str(self.theme.background_filename))[1] | 548 | file_name = self.theme.background_filename.name |
302 | 545 | save_to = os.path.join(self.path, self.theme.theme_name, filename) | 549 | destination_path = self.path / self.theme.theme_name / file_name |
303 | 546 | save_from = self.theme.background_filename | 550 | source_path = self.theme.background_filename |
304 | 547 | if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name): | 551 | if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name): |
305 | 548 | return | 552 | return |
307 | 549 | self.theme_manager.save_theme(self.theme, save_from, save_to) | 553 | self.theme_manager.save_theme(self.theme, source_path, destination_path) |
308 | 550 | return QtWidgets.QDialog.accept(self) | 554 | return QtWidgets.QDialog.accept(self) |
309 | 551 | 555 | ||
310 | === modified file 'openlp/core/ui/thememanager.py' | |||
311 | --- openlp/core/ui/thememanager.py 2017-09-17 19:43:15 +0000 | |||
312 | +++ openlp/core/ui/thememanager.py 2017-09-26 17:09:04 +0000 | |||
313 | @@ -24,14 +24,14 @@ | |||
314 | 24 | """ | 24 | """ |
315 | 25 | import os | 25 | import os |
316 | 26 | import zipfile | 26 | import zipfile |
317 | 27 | import shutil | ||
318 | 28 | |||
319 | 29 | from xml.etree.ElementTree import ElementTree, XML | 27 | from xml.etree.ElementTree import ElementTree, XML |
320 | 28 | |||
321 | 30 | from PyQt5 import QtCore, QtGui, QtWidgets | 29 | from PyQt5 import QtCore, QtGui, QtWidgets |
322 | 31 | 30 | ||
323 | 32 | from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, OpenLPMixin, RegistryMixin, \ | 31 | from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, OpenLPMixin, RegistryMixin, \ |
326 | 33 | UiStrings, check_directory_exists, translate, is_win, get_filesystem_encoding, delete_file | 32 | UiStrings, check_directory_exists, translate, delete_file |
327 | 34 | from openlp.core.common.path import Path, path_to_str, str_to_path | 33 | from openlp.core.common.languagemanager import get_locale_key |
328 | 34 | from openlp.core.common.path import Path, copyfile, path_to_str, rmtree | ||
329 | 35 | from openlp.core.lib import ImageSource, ValidationError, get_text_file_string, build_icon, \ | 35 | from openlp.core.lib import ImageSource, ValidationError, get_text_file_string, build_icon, \ |
330 | 36 | check_item_selected, create_thumb, validate_thumb | 36 | check_item_selected, create_thumb, validate_thumb |
331 | 37 | from openlp.core.lib.theme import Theme, BackgroundType | 37 | from openlp.core.lib.theme import Theme, BackgroundType |
332 | @@ -39,7 +39,6 @@ | |||
333 | 39 | from openlp.core.ui import FileRenameForm, ThemeForm | 39 | from openlp.core.ui import FileRenameForm, ThemeForm |
334 | 40 | from openlp.core.ui.lib import OpenLPToolbar | 40 | from openlp.core.ui.lib import OpenLPToolbar |
335 | 41 | from openlp.core.ui.lib.filedialog import FileDialog | 41 | from openlp.core.ui.lib.filedialog import FileDialog |
336 | 42 | from openlp.core.common.languagemanager import get_locale_key | ||
337 | 43 | 42 | ||
338 | 44 | 43 | ||
339 | 45 | class Ui_ThemeManager(object): | 44 | class Ui_ThemeManager(object): |
340 | @@ -135,7 +134,7 @@ | |||
341 | 135 | self.settings_section = 'themes' | 134 | self.settings_section = 'themes' |
342 | 136 | # Variables | 135 | # Variables |
343 | 137 | self.theme_list = [] | 136 | self.theme_list = [] |
345 | 138 | self.old_background_image = None | 137 | self.old_background_image_path = None |
346 | 139 | 138 | ||
347 | 140 | def bootstrap_initialise(self): | 139 | def bootstrap_initialise(self): |
348 | 141 | """ | 140 | """ |
349 | @@ -145,25 +144,41 @@ | |||
350 | 145 | self.global_theme = Settings().value(self.settings_section + '/global theme') | 144 | self.global_theme = Settings().value(self.settings_section + '/global theme') |
351 | 146 | self.build_theme_path() | 145 | self.build_theme_path() |
352 | 147 | self.load_first_time_themes() | 146 | self.load_first_time_themes() |
353 | 147 | self.upgrade_themes() | ||
354 | 148 | 148 | ||
355 | 149 | def bootstrap_post_set_up(self): | 149 | def bootstrap_post_set_up(self): |
356 | 150 | """ | 150 | """ |
357 | 151 | process the bootstrap post setup request | 151 | process the bootstrap post setup request |
358 | 152 | """ | 152 | """ |
359 | 153 | self.theme_form = ThemeForm(self) | 153 | self.theme_form = ThemeForm(self) |
361 | 154 | self.theme_form.path = self.path | 154 | self.theme_form.path = self.theme_path |
362 | 155 | self.file_rename_form = FileRenameForm() | 155 | self.file_rename_form = FileRenameForm() |
363 | 156 | Registry().register_function('theme_update_global', self.change_global_from_tab) | 156 | Registry().register_function('theme_update_global', self.change_global_from_tab) |
364 | 157 | self.load_themes() | 157 | self.load_themes() |
365 | 158 | 158 | ||
366 | 159 | def upgrade_themes(self): | ||
367 | 160 | """ | ||
368 | 161 | Upgrade the xml files to json. | ||
369 | 162 | |||
370 | 163 | :rtype: None | ||
371 | 164 | """ | ||
372 | 165 | xml_file_paths = AppLocation.get_section_data_path('themes').glob('*/*.xml') | ||
373 | 166 | for xml_file_path in xml_file_paths: | ||
374 | 167 | theme_data = get_text_file_string(xml_file_path) | ||
375 | 168 | theme = self._create_theme_from_xml(theme_data, self.theme_path) | ||
376 | 169 | self._write_theme(theme) | ||
377 | 170 | xml_file_path.unlink() | ||
378 | 171 | |||
379 | 159 | def build_theme_path(self): | 172 | def build_theme_path(self): |
380 | 160 | """ | 173 | """ |
381 | 161 | Set up the theme path variables | 174 | Set up the theme path variables |
382 | 175 | |||
383 | 176 | :rtype: None | ||
384 | 162 | """ | 177 | """ |
389 | 163 | self.path = str(AppLocation.get_section_data_path(self.settings_section)) | 178 | self.theme_path = AppLocation.get_section_data_path(self.settings_section) |
390 | 164 | check_directory_exists(Path(self.path)) | 179 | check_directory_exists(self.theme_path) |
391 | 165 | self.thumb_path = os.path.join(self.path, 'thumbnails') | 180 | self.thumb_path = self.theme_path / 'thumbnails' |
392 | 166 | check_directory_exists(Path(self.thumb_path)) | 181 | check_directory_exists(self.thumb_path) |
393 | 167 | 182 | ||
394 | 168 | def check_list_state(self, item, field=None): | 183 | def check_list_state(self, item, field=None): |
395 | 169 | """ | 184 | """ |
396 | @@ -298,17 +313,18 @@ | |||
397 | 298 | """ | 313 | """ |
398 | 299 | Takes a theme and makes a new copy of it as well as saving it. | 314 | Takes a theme and makes a new copy of it as well as saving it. |
399 | 300 | 315 | ||
402 | 301 | :param theme_data: The theme to be used | 316 | :param Theme theme_data: The theme to be used |
403 | 302 | :param new_theme_name: The new theme name to save the data to | 317 | :param str new_theme_name: The new theme name of the theme |
404 | 318 | :rtype: None | ||
405 | 303 | """ | 319 | """ |
408 | 304 | save_to = None | 320 | destination_path = None |
409 | 305 | save_from = None | 321 | source_path = None |
410 | 306 | if theme_data.background_type == 'image' or theme_data.background_type == 'video': | 322 | if theme_data.background_type == 'image' or theme_data.background_type == 'video': |
413 | 307 | save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1]) | 323 | destination_path = self.theme_path / new_theme_name / theme_data.background_filename.name |
414 | 308 | save_from = theme_data.background_filename | 324 | source_path = theme_data.background_filename |
415 | 309 | theme_data.theme_name = new_theme_name | 325 | theme_data.theme_name = new_theme_name |
418 | 310 | theme_data.extend_image_filename(self.path) | 326 | theme_data.extend_image_filename(self.theme_path) |
419 | 311 | self.save_theme(theme_data, save_from, save_to) | 327 | self.save_theme(theme_data, source_path, destination_path) |
420 | 312 | self.load_themes() | 328 | self.load_themes() |
421 | 313 | 329 | ||
422 | 314 | def on_edit_theme(self, field=None): | 330 | def on_edit_theme(self, field=None): |
423 | @@ -322,10 +338,10 @@ | |||
424 | 322 | item = self.theme_list_widget.currentItem() | 338 | item = self.theme_list_widget.currentItem() |
425 | 323 | theme = self.get_theme_data(item.data(QtCore.Qt.UserRole)) | 339 | theme = self.get_theme_data(item.data(QtCore.Qt.UserRole)) |
426 | 324 | if theme.background_type == 'image' or theme.background_type == 'video': | 340 | if theme.background_type == 'image' or theme.background_type == 'video': |
428 | 325 | self.old_background_image = theme.background_filename | 341 | self.old_background_image_path = theme.background_filename |
429 | 326 | self.theme_form.theme = theme | 342 | self.theme_form.theme = theme |
430 | 327 | self.theme_form.exec(True) | 343 | self.theme_form.exec(True) |
432 | 328 | self.old_background_image = None | 344 | self.old_background_image_path = None |
433 | 329 | self.renderer.update_theme(theme.theme_name) | 345 | self.renderer.update_theme(theme.theme_name) |
434 | 330 | self.load_themes() | 346 | self.load_themes() |
435 | 331 | 347 | ||
436 | @@ -355,77 +371,76 @@ | |||
437 | 355 | """ | 371 | """ |
438 | 356 | self.theme_list.remove(theme) | 372 | self.theme_list.remove(theme) |
439 | 357 | thumb = '{name}.png'.format(name=theme) | 373 | thumb = '{name}.png'.format(name=theme) |
442 | 358 | delete_file(Path(self.path, thumb)) | 374 | delete_file(self.theme_path / thumb) |
443 | 359 | delete_file(Path(self.thumb_path, thumb)) | 375 | delete_file(self.thumb_path / thumb) |
444 | 360 | try: | 376 | try: |
453 | 361 | # Windows is always unicode, so no need to encode filenames | 377 | rmtree(self.theme_path / theme) |
454 | 362 | if is_win(): | 378 | except OSError: |
447 | 363 | shutil.rmtree(os.path.join(self.path, theme)) | ||
448 | 364 | else: | ||
449 | 365 | encoding = get_filesystem_encoding() | ||
450 | 366 | shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) | ||
451 | 367 | except OSError as os_error: | ||
452 | 368 | shutil.Error = os_error | ||
455 | 369 | self.log_exception('Error deleting theme {name}'.format(name=theme)) | 379 | self.log_exception('Error deleting theme {name}'.format(name=theme)) |
456 | 370 | 380 | ||
458 | 371 | def on_export_theme(self, field=None): | 381 | def on_export_theme(self, checked=None): |
459 | 372 | """ | 382 | """ |
462 | 373 | Export the theme in a zip file | 383 | Export the theme to a zip file |
463 | 374 | :param field: | 384 | |
464 | 385 | :param bool checked: Sent by the QAction.triggered signal. It's not used in this method. | ||
465 | 386 | :rtype: None | ||
466 | 375 | """ | 387 | """ |
467 | 376 | item = self.theme_list_widget.currentItem() | 388 | item = self.theme_list_widget.currentItem() |
468 | 377 | if item is None: | 389 | if item is None: |
469 | 378 | critical_error_message_box(message=translate('OpenLP.ThemeManager', 'You have not selected a theme.')) | 390 | critical_error_message_box(message=translate('OpenLP.ThemeManager', 'You have not selected a theme.')) |
470 | 379 | return | 391 | return |
472 | 380 | theme = item.data(QtCore.Qt.UserRole) | 392 | theme_name = item.data(QtCore.Qt.UserRole) |
473 | 381 | export_path, filter_used = \ | 393 | export_path, filter_used = \ |
474 | 382 | FileDialog.getSaveFileName(self.main_window, | 394 | FileDialog.getSaveFileName(self.main_window, |
477 | 383 | translate('OpenLP.ThemeManager', 'Save Theme - ({name})'). | 395 | translate('OpenLP.ThemeManager', |
478 | 384 | format(name=theme), | 396 | 'Save Theme - ({name})').format(name=theme_name), |
479 | 385 | Settings().value(self.settings_section + '/last directory export'), | 397 | Settings().value(self.settings_section + '/last directory export'), |
480 | 398 | translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)'), | ||
481 | 386 | translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)')) | 399 | translate('OpenLP.ThemeManager', 'OpenLP Themes (*.otz)')) |
482 | 387 | self.application.set_busy_cursor() | 400 | self.application.set_busy_cursor() |
483 | 388 | if export_path: | 401 | if export_path: |
484 | 389 | Settings().setValue(self.settings_section + '/last directory export', export_path.parent) | 402 | Settings().setValue(self.settings_section + '/last directory export', export_path.parent) |
486 | 390 | if self._export_theme(str(export_path), theme): | 403 | if self._export_theme(export_path.with_suffix('.otz'), theme_name): |
487 | 391 | QtWidgets.QMessageBox.information(self, | 404 | QtWidgets.QMessageBox.information(self, |
488 | 392 | translate('OpenLP.ThemeManager', 'Theme Exported'), | 405 | translate('OpenLP.ThemeManager', 'Theme Exported'), |
489 | 393 | translate('OpenLP.ThemeManager', | 406 | translate('OpenLP.ThemeManager', |
490 | 394 | 'Your theme has been successfully exported.')) | 407 | 'Your theme has been successfully exported.')) |
491 | 395 | self.application.set_normal_cursor() | 408 | self.application.set_normal_cursor() |
492 | 396 | 409 | ||
494 | 397 | def _export_theme(self, theme_path, theme): | 410 | def _export_theme(self, theme_path, theme_name): |
495 | 398 | """ | 411 | """ |
496 | 399 | Create the zipfile with the theme contents. | 412 | Create the zipfile with the theme contents. |
499 | 400 | :param theme_path: Location where the zip file will be placed | 413 | |
500 | 401 | :param theme: The name of the theme to be exported | 414 | :param openlp.core.common.path.Path theme_path: Location where the zip file will be placed |
501 | 415 | :param str theme_name: The name of the theme to be exported | ||
502 | 416 | :return: The success of creating the zip file | ||
503 | 417 | :rtype: bool | ||
504 | 402 | """ | 418 | """ |
505 | 403 | theme_zip = None | ||
506 | 404 | try: | 419 | try: |
513 | 405 | theme_zip = zipfile.ZipFile(theme_path, 'w') | 420 | with zipfile.ZipFile(str(theme_path), 'w') as theme_zip: |
514 | 406 | source = os.path.join(self.path, theme) | 421 | source_path = self.theme_path / theme_name |
515 | 407 | for files in os.walk(source): | 422 | for file_path in source_path.iterdir(): |
516 | 408 | for name in files[2]: | 423 | theme_zip.write(str(file_path), os.path.join(theme_name, file_path.name)) |
511 | 409 | theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) | ||
512 | 410 | theme_zip.close() | ||
517 | 411 | return True | 424 | return True |
518 | 412 | except OSError as ose: | 425 | except OSError as ose: |
519 | 413 | self.log_exception('Export Theme Failed') | 426 | self.log_exception('Export Theme Failed') |
520 | 414 | critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), | 427 | critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), |
526 | 415 | translate('OpenLP.ThemeManager', 'The theme export failed because this error ' | 428 | translate('OpenLP.ThemeManager', |
527 | 416 | 'occurred: {err}').format(err=ose.strerror)) | 429 | 'The theme_name export failed because this error occurred: {err}') |
528 | 417 | if theme_zip: | 430 | .format(err=ose.strerror)) |
529 | 418 | theme_zip.close() | 431 | if theme_path.exists(): |
530 | 419 | shutil.rmtree(theme_path, True) | 432 | rmtree(theme_path, True) |
531 | 420 | return False | 433 | return False |
532 | 421 | 434 | ||
534 | 422 | def on_import_theme(self, field=None): | 435 | def on_import_theme(self, checked=None): |
535 | 423 | """ | 436 | """ |
536 | 424 | Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from | 437 | Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from |
537 | 425 | those files. This process will only load version 2 themes. | 438 | those files. This process will only load version 2 themes. |
539 | 426 | :param field: | 439 | |
540 | 440 | :param bool checked: Sent by the QAction.triggered signal. It's not used in this method. | ||
541 | 441 | :rtype: None | ||
542 | 427 | """ | 442 | """ |
544 | 428 | file_paths, selected_filter = FileDialog.getOpenFileNames( | 443 | file_paths, filter_used = FileDialog.getOpenFileNames( |
545 | 429 | self, | 444 | self, |
546 | 430 | translate('OpenLP.ThemeManager', 'Select Theme Import File'), | 445 | translate('OpenLP.ThemeManager', 'Select Theme Import File'), |
547 | 431 | Settings().value(self.settings_section + '/last directory import'), | 446 | Settings().value(self.settings_section + '/last directory import'), |
548 | @@ -435,8 +450,8 @@ | |||
549 | 435 | return | 450 | return |
550 | 436 | self.application.set_busy_cursor() | 451 | self.application.set_busy_cursor() |
551 | 437 | for file_path in file_paths: | 452 | for file_path in file_paths: |
554 | 438 | self.unzip_theme(path_to_str(file_path), self.path) | 453 | self.unzip_theme(file_path, self.theme_path) |
555 | 439 | Settings().setValue(self.settings_section + '/last directory import', file_path) | 454 | Settings().setValue(self.settings_section + '/last directory import', file_path.parent) |
556 | 440 | self.load_themes() | 455 | self.load_themes() |
557 | 441 | self.application.set_normal_cursor() | 456 | self.application.set_normal_cursor() |
558 | 442 | 457 | ||
559 | @@ -445,17 +460,17 @@ | |||
560 | 445 | Imports any themes on start up and makes sure there is at least one theme | 460 | Imports any themes on start up and makes sure there is at least one theme |
561 | 446 | """ | 461 | """ |
562 | 447 | self.application.set_busy_cursor() | 462 | self.application.set_busy_cursor() |
569 | 448 | files = AppLocation.get_files(self.settings_section, '.otz') | 463 | theme_paths = AppLocation.get_files(self.settings_section, '.otz') |
570 | 449 | for theme_file in files: | 464 | for theme_path in theme_paths: |
571 | 450 | theme_file = os.path.join(self.path, str(theme_file)) | 465 | theme_path = self.theme_path / theme_path |
572 | 451 | self.unzip_theme(theme_file, self.path) | 466 | self.unzip_theme(theme_path, self.theme_path) |
573 | 452 | delete_file(Path(theme_file)) | 467 | delete_file(theme_path) |
574 | 453 | files = AppLocation.get_files(self.settings_section, '.png') | 468 | theme_paths = AppLocation.get_files(self.settings_section, '.png') |
575 | 454 | # No themes have been found so create one | 469 | # No themes have been found so create one |
577 | 455 | if not files: | 470 | if not theme_paths: |
578 | 456 | theme = Theme() | 471 | theme = Theme() |
579 | 457 | theme.theme_name = UiStrings().Default | 472 | theme.theme_name = UiStrings().Default |
581 | 458 | self._write_theme(theme, None, None) | 473 | self._write_theme(theme) |
582 | 459 | Settings().setValue(self.settings_section + '/global theme', theme.theme_name) | 474 | Settings().setValue(self.settings_section + '/global theme', theme.theme_name) |
583 | 460 | self.application.set_normal_cursor() | 475 | self.application.set_normal_cursor() |
584 | 461 | 476 | ||
585 | @@ -471,22 +486,21 @@ | |||
586 | 471 | # Sort the themes by its name considering language specific | 486 | # Sort the themes by its name considering language specific |
587 | 472 | files.sort(key=lambda file_name: get_locale_key(str(file_name))) | 487 | files.sort(key=lambda file_name: get_locale_key(str(file_name))) |
588 | 473 | # now process the file list of png files | 488 | # now process the file list of png files |
591 | 474 | for name in files: | 489 | for file in files: |
590 | 475 | name = str(name) | ||
592 | 476 | # check to see file is in theme root directory | 490 | # check to see file is in theme root directory |
596 | 477 | theme = os.path.join(self.path, name) | 491 | theme_path = self.theme_path / file |
597 | 478 | if os.path.exists(theme): | 492 | if theme_path.exists(): |
598 | 479 | text_name = os.path.splitext(name)[0] | 493 | text_name = theme_path.stem |
599 | 480 | if text_name == self.global_theme: | 494 | if text_name == self.global_theme: |
600 | 481 | name = translate('OpenLP.ThemeManager', '{name} (default)').format(name=text_name) | 495 | name = translate('OpenLP.ThemeManager', '{name} (default)').format(name=text_name) |
601 | 482 | else: | 496 | else: |
602 | 483 | name = text_name | 497 | name = text_name |
604 | 484 | thumb = os.path.join(self.thumb_path, '{name}.png'.format(name=text_name)) | 498 | thumb = self.thumb_path / '{name}.png'.format(name=text_name) |
605 | 485 | item_name = QtWidgets.QListWidgetItem(name) | 499 | item_name = QtWidgets.QListWidgetItem(name) |
607 | 486 | if validate_thumb(Path(theme), Path(thumb)): | 500 | if validate_thumb(theme_path, thumb): |
608 | 487 | icon = build_icon(thumb) | 501 | icon = build_icon(thumb) |
609 | 488 | else: | 502 | else: |
611 | 489 | icon = create_thumb(theme, thumb) | 503 | icon = create_thumb(str(theme_path), str(thumb)) |
612 | 490 | item_name.setIcon(icon) | 504 | item_name.setIcon(icon) |
613 | 491 | item_name.setData(QtCore.Qt.UserRole, text_name) | 505 | item_name.setData(QtCore.Qt.UserRole, text_name) |
614 | 492 | self.theme_list_widget.addItem(item_name) | 506 | self.theme_list_widget.addItem(item_name) |
615 | @@ -507,27 +521,19 @@ | |||
616 | 507 | 521 | ||
617 | 508 | def get_theme_data(self, theme_name): | 522 | def get_theme_data(self, theme_name): |
618 | 509 | """ | 523 | """ |
620 | 510 | Returns a theme object from an XML or JSON file | 524 | Returns a theme object from a JSON file |
621 | 511 | 525 | ||
624 | 512 | :param theme_name: Name of the theme to load from file | 526 | :param str theme_name: Name of the theme to load from file |
625 | 513 | :return: The theme object. | 527 | :return: The theme object. |
626 | 528 | :rtype: Theme | ||
627 | 514 | """ | 529 | """ |
630 | 515 | self.log_debug('get theme data for theme {name}'.format(name=theme_name)) | 530 | theme_name = str(theme_name) |
631 | 516 | theme_file_path = Path(self.path, str(theme_name), '{file_name}.json'.format(file_name=theme_name)) | 531 | theme_file_path = self.theme_path / theme_name / '{file_name}.json'.format(file_name=theme_name) |
632 | 517 | theme_data = get_text_file_string(theme_file_path) | 532 | theme_data = get_text_file_string(theme_file_path) |
633 | 518 | jsn = True | ||
634 | 519 | if not theme_data: | ||
635 | 520 | theme_file_path = theme_file_path.with_suffix('.xml') | ||
636 | 521 | theme_data = get_text_file_string(theme_file_path) | ||
637 | 522 | jsn = False | ||
638 | 523 | if not theme_data: | 533 | if not theme_data: |
639 | 524 | self.log_debug('No theme data - using default theme') | 534 | self.log_debug('No theme data - using default theme') |
640 | 525 | return Theme() | 535 | return Theme() |
646 | 526 | else: | 536 | return self._create_theme_from_json(theme_data, self.theme_path) |
642 | 527 | if jsn: | ||
643 | 528 | return self._create_theme_from_json(theme_data, self.path) | ||
644 | 529 | else: | ||
645 | 530 | return self._create_theme_from_xml(theme_data, self.path) | ||
647 | 531 | 537 | ||
648 | 532 | def over_write_message_box(self, theme_name): | 538 | def over_write_message_box(self, theme_name): |
649 | 533 | """ | 539 | """ |
650 | @@ -543,172 +549,148 @@ | |||
651 | 543 | defaultButton=QtWidgets.QMessageBox.No) | 549 | defaultButton=QtWidgets.QMessageBox.No) |
652 | 544 | return ret == QtWidgets.QMessageBox.Yes | 550 | return ret == QtWidgets.QMessageBox.Yes |
653 | 545 | 551 | ||
655 | 546 | def unzip_theme(self, file_name, directory): | 552 | def unzip_theme(self, file_path, directory_path): |
656 | 547 | """ | 553 | """ |
657 | 548 | Unzip the theme, remove the preview file if stored. Generate a new preview file. Check the XML theme version | 554 | Unzip the theme, remove the preview file if stored. Generate a new preview file. Check the XML theme version |
658 | 549 | and upgrade if necessary. | 555 | and upgrade if necessary. |
661 | 550 | :param file_name: | 556 | :param openlp.core.common.path.Path file_path: |
662 | 551 | :param directory: | 557 | :param openlp.core.common.path.Path directory_path: |
663 | 552 | """ | 558 | """ |
667 | 553 | self.log_debug('Unzipping theme {name}'.format(name=file_name)) | 559 | self.log_debug('Unzipping theme {name}'.format(name=file_path)) |
665 | 554 | theme_zip = None | ||
666 | 555 | out_file = None | ||
668 | 556 | file_xml = None | 560 | file_xml = None |
669 | 557 | abort_import = True | 561 | abort_import = True |
670 | 558 | json_theme = False | 562 | json_theme = False |
671 | 559 | theme_name = "" | 563 | theme_name = "" |
672 | 560 | try: | 564 | try: |
715 | 561 | theme_zip = zipfile.ZipFile(file_name) | 565 | with zipfile.ZipFile(str(file_path)) as theme_zip: |
716 | 562 | json_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.json'] | 566 | json_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.json'] |
717 | 563 | if len(json_file) != 1: | 567 | if len(json_file) != 1: |
718 | 564 | # TODO: remove XML handling at some point but would need a auto conversion to run first. | 568 | # TODO: remove XML handling after the 2.6 release. |
719 | 565 | xml_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.xml'] | 569 | xml_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.xml'] |
720 | 566 | if len(xml_file) != 1: | 570 | if len(xml_file) != 1: |
721 | 567 | self.log_error('Theme contains "{val:d}" theme files'.format(val=len(xml_file))) | 571 | self.log_error('Theme contains "{val:d}" theme files'.format(val=len(xml_file))) |
722 | 568 | raise ValidationError | 572 | raise ValidationError |
723 | 569 | xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot() | 573 | xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot() |
724 | 570 | theme_version = xml_tree.get('version', default=None) | 574 | theme_version = xml_tree.get('version', default=None) |
725 | 571 | if not theme_version or float(theme_version) < 2.0: | 575 | if not theme_version or float(theme_version) < 2.0: |
726 | 572 | self.log_error('Theme version is less than 2.0') | 576 | self.log_error('Theme version is less than 2.0') |
727 | 573 | raise ValidationError | 577 | raise ValidationError |
728 | 574 | theme_name = xml_tree.find('name').text.strip() | 578 | theme_name = xml_tree.find('name').text.strip() |
729 | 575 | else: | 579 | else: |
730 | 576 | new_theme = Theme() | 580 | new_theme = Theme() |
731 | 577 | new_theme.load_theme(theme_zip.read(json_file[0]).decode("utf-8")) | 581 | new_theme.load_theme(theme_zip.read(json_file[0]).decode("utf-8")) |
732 | 578 | theme_name = new_theme.theme_name | 582 | theme_name = new_theme.theme_name |
733 | 579 | json_theme = True | 583 | json_theme = True |
734 | 580 | theme_folder = os.path.join(directory, theme_name) | 584 | theme_folder = directory_path / theme_name |
735 | 581 | theme_exists = os.path.exists(theme_folder) | 585 | if theme_folder.exists() and not self.over_write_message_box(theme_name): |
736 | 582 | if theme_exists and not self.over_write_message_box(theme_name): | 586 | abort_import = True |
737 | 583 | abort_import = True | 587 | return |
738 | 584 | return | 588 | else: |
739 | 585 | else: | 589 | abort_import = False |
740 | 586 | abort_import = False | 590 | for zipped_file in theme_zip.namelist(): |
741 | 587 | for name in theme_zip.namelist(): | 591 | zipped_file_rel_path = Path(zipped_file) |
742 | 588 | out_name = name.replace('/', os.path.sep) | 592 | split_name = zipped_file_rel_path.parts |
743 | 589 | split_name = out_name.split(os.path.sep) | 593 | if split_name[-1] == '' or len(split_name) == 1: |
744 | 590 | if split_name[-1] == '' or len(split_name) == 1: | 594 | # is directory or preview file |
745 | 591 | # is directory or preview file | 595 | continue |
746 | 592 | continue | 596 | full_name = directory_path / zipped_file_rel_path |
747 | 593 | full_name = os.path.join(directory, out_name) | 597 | check_directory_exists(full_name.parent) |
748 | 594 | check_directory_exists(Path(os.path.dirname(full_name))) | 598 | if zipped_file_rel_path.suffix.lower() == '.xml' or zipped_file_rel_path.suffix.lower() == '.json': |
749 | 595 | if os.path.splitext(name)[1].lower() == '.xml' or os.path.splitext(name)[1].lower() == '.json': | 599 | file_xml = str(theme_zip.read(zipped_file), 'utf-8') |
750 | 596 | file_xml = str(theme_zip.read(name), 'utf-8') | 600 | with full_name.open('w', encoding='utf-8') as out_file: |
751 | 597 | out_file = open(full_name, 'w', encoding='utf-8') | 601 | out_file.write(file_xml) |
752 | 598 | out_file.write(file_xml) | 602 | else: |
753 | 599 | else: | 603 | with full_name.open('wb') as out_file: |
754 | 600 | out_file = open(full_name, 'wb') | 604 | out_file.write(theme_zip.read(zipped_file)) |
713 | 601 | out_file.write(theme_zip.read(name)) | ||
714 | 602 | out_file.close() | ||
755 | 603 | except (IOError, zipfile.BadZipfile): | 605 | except (IOError, zipfile.BadZipfile): |
757 | 604 | self.log_exception('Importing theme from zip failed {name}'.format(name=file_name)) | 606 | self.log_exception('Importing theme from zip failed {name}'.format(name=file_path)) |
758 | 605 | raise ValidationError | 607 | raise ValidationError |
759 | 606 | except ValidationError: | 608 | except ValidationError: |
760 | 607 | critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'), | 609 | critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'), |
761 | 608 | translate('OpenLP.ThemeManager', 'File is not a valid theme.')) | 610 | translate('OpenLP.ThemeManager', 'File is not a valid theme.')) |
762 | 609 | finally: | 611 | finally: |
763 | 610 | # Close the files, to be able to continue creating the theme. | ||
764 | 611 | if theme_zip: | ||
765 | 612 | theme_zip.close() | ||
766 | 613 | if out_file: | ||
767 | 614 | out_file.close() | ||
768 | 615 | if not abort_import: | 612 | if not abort_import: |
769 | 616 | # As all files are closed, we can create the Theme. | 613 | # As all files are closed, we can create the Theme. |
770 | 617 | if file_xml: | 614 | if file_xml: |
771 | 618 | if json_theme: | 615 | if json_theme: |
773 | 619 | theme = self._create_theme_from_json(file_xml, self.path) | 616 | theme = self._create_theme_from_json(file_xml, self.theme_path) |
774 | 620 | else: | 617 | else: |
776 | 621 | theme = self._create_theme_from_xml(file_xml, self.path) | 618 | theme = self._create_theme_from_xml(file_xml, self.theme_path) |
777 | 622 | self.generate_and_save_image(theme_name, theme) | 619 | self.generate_and_save_image(theme_name, theme) |
778 | 623 | # Only show the error message, when IOError was not raised (in | ||
779 | 624 | # this case the error message has already been shown). | ||
780 | 625 | elif theme_zip is not None: | ||
781 | 626 | critical_error_message_box( | ||
782 | 627 | translate('OpenLP.ThemeManager', 'Validation Error'), | ||
783 | 628 | translate('OpenLP.ThemeManager', 'File is not a valid theme.')) | ||
784 | 629 | self.log_error('Theme file does not contain XML data {name}'.format(name=file_name)) | ||
785 | 630 | 620 | ||
786 | 631 | def check_if_theme_exists(self, theme_name): | 621 | def check_if_theme_exists(self, theme_name): |
787 | 632 | """ | 622 | """ |
788 | 633 | Check if theme already exists and displays error message | 623 | Check if theme already exists and displays error message |
789 | 634 | 624 | ||
791 | 635 | :param theme_name: Name of the Theme to test | 625 | :param str theme_name: Name of the Theme to test |
792 | 636 | :return: True or False if theme exists | 626 | :return: True or False if theme exists |
793 | 627 | :rtype: bool | ||
794 | 637 | """ | 628 | """ |
797 | 638 | theme_dir = os.path.join(self.path, theme_name) | 629 | if (self.theme_path / theme_name).exists(): |
796 | 639 | if os.path.exists(theme_dir): | ||
798 | 640 | critical_error_message_box( | 630 | critical_error_message_box( |
799 | 641 | translate('OpenLP.ThemeManager', 'Validation Error'), | 631 | translate('OpenLP.ThemeManager', 'Validation Error'), |
800 | 642 | translate('OpenLP.ThemeManager', 'A theme with this name already exists.')) | 632 | translate('OpenLP.ThemeManager', 'A theme with this name already exists.')) |
801 | 643 | return False | 633 | return False |
802 | 644 | return True | 634 | return True |
803 | 645 | 635 | ||
805 | 646 | def save_theme(self, theme, image_from, image_to): | 636 | def save_theme(self, theme, image_source_path, image_destination_path): |
806 | 647 | """ | 637 | """ |
807 | 648 | Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list | 638 | Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list |
808 | 649 | 639 | ||
812 | 650 | :param theme: The theme data object. | 640 | :param Theme theme: The theme data object. |
813 | 651 | :param image_from: Where the theme image is currently located. | 641 | :param openlp.core.common.path.Path image_source_path: Where the theme image is currently located. |
814 | 652 | :param image_to: Where the Theme Image is to be saved to | 642 | :param openlp.core.common.path.Path image_destination_path: Where the Theme Image is to be saved to |
815 | 643 | :rtype: None | ||
816 | 653 | """ | 644 | """ |
818 | 654 | self._write_theme(theme, image_from, image_to) | 645 | self._write_theme(theme, image_source_path, image_destination_path) |
819 | 655 | if theme.background_type == BackgroundType.to_string(BackgroundType.Image): | 646 | if theme.background_type == BackgroundType.to_string(BackgroundType.Image): |
821 | 656 | self.image_manager.update_image_border(theme.background_filename, | 647 | self.image_manager.update_image_border(path_to_str(theme.background_filename), |
822 | 657 | ImageSource.Theme, | 648 | ImageSource.Theme, |
823 | 658 | QtGui.QColor(theme.background_border_color)) | 649 | QtGui.QColor(theme.background_border_color)) |
824 | 659 | self.image_manager.process_updates() | 650 | self.image_manager.process_updates() |
825 | 660 | 651 | ||
827 | 661 | def _write_theme(self, theme, image_from, image_to): | 652 | def _write_theme(self, theme, image_source_path=None, image_destination_path=None): |
828 | 662 | """ | 653 | """ |
829 | 663 | Writes the theme to the disk and handles the background image if necessary | 654 | Writes the theme to the disk and handles the background image if necessary |
830 | 664 | 655 | ||
834 | 665 | :param theme: The theme data object. | 656 | :param Theme theme: The theme data object. |
835 | 666 | :param image_from: Where the theme image is currently located. | 657 | :param openlp.core.common.path.Path image_source_path: Where the theme image is currently located. |
836 | 667 | :param image_to: Where the Theme Image is to be saved to | 658 | :param openlp.core.common.path.Path image_destination_path: Where the Theme Image is to be saved to |
837 | 659 | :rtype: None | ||
838 | 668 | """ | 660 | """ |
839 | 669 | name = theme.theme_name | 661 | name = theme.theme_name |
847 | 670 | theme_pretty = theme.export_theme() | 662 | theme_pretty = theme.export_theme(self.theme_path) |
848 | 671 | theme_dir = os.path.join(self.path, name) | 663 | theme_dir = self.theme_path / name |
849 | 672 | check_directory_exists(Path(theme_dir)) | 664 | check_directory_exists(theme_dir) |
850 | 673 | theme_file = os.path.join(theme_dir, name + '.json') | 665 | theme_path = theme_dir / '{file_name}.json'.format(file_name=name) |
844 | 674 | if self.old_background_image and image_to != self.old_background_image: | ||
845 | 675 | delete_file(Path(self.old_background_image)) | ||
846 | 676 | out_file = None | ||
851 | 677 | try: | 666 | try: |
854 | 678 | out_file = open(theme_file, 'w', encoding='utf-8') | 667 | theme_path.write_text(theme_pretty) |
853 | 679 | out_file.write(theme_pretty) | ||
855 | 680 | except IOError: | 668 | except IOError: |
856 | 681 | self.log_exception('Saving theme to file failed') | 669 | self.log_exception('Saving theme to file failed') |
871 | 682 | finally: | 670 | if image_source_path and image_destination_path: |
872 | 683 | if out_file: | 671 | if self.old_background_image_path and image_destination_path != self.old_background_image_path: |
873 | 684 | out_file.close() | 672 | delete_file(self.old_background_image_path) |
874 | 685 | if image_from and os.path.abspath(image_from) != os.path.abspath(image_to): | 673 | if image_source_path != image_destination_path: |
875 | 686 | try: | 674 | try: |
876 | 687 | # Windows is always unicode, so no need to encode filenames | 675 | copyfile(image_source_path, image_destination_path) |
877 | 688 | if is_win(): | 676 | except IOError: |
878 | 689 | shutil.copyfile(image_from, image_to) | 677 | self.log_exception('Failed to save theme image') |
865 | 690 | else: | ||
866 | 691 | encoding = get_filesystem_encoding() | ||
867 | 692 | shutil.copyfile(image_from.encode(encoding), image_to.encode(encoding)) | ||
868 | 693 | except IOError as xxx_todo_changeme: | ||
869 | 694 | shutil.Error = xxx_todo_changeme | ||
870 | 695 | self.log_exception('Failed to save theme image') | ||
879 | 696 | self.generate_and_save_image(name, theme) | 678 | self.generate_and_save_image(name, theme) |
880 | 697 | 679 | ||
882 | 698 | def generate_and_save_image(self, name, theme): | 680 | def generate_and_save_image(self, theme_name, theme): |
883 | 699 | """ | 681 | """ |
884 | 700 | Generate and save a preview image | 682 | Generate and save a preview image |
885 | 701 | 683 | ||
887 | 702 | :param name: The name of the theme. | 684 | :param str theme_name: The name of the theme. |
888 | 703 | :param theme: The theme data object. | 685 | :param theme: The theme data object. |
889 | 704 | """ | 686 | """ |
890 | 705 | frame = self.generate_image(theme) | 687 | frame = self.generate_image(theme) |
897 | 706 | sample_path_name = os.path.join(self.path, name + '.png') | 688 | sample_path_name = self.theme_path / '{file_name}.png'.format(file_name=theme_name) |
898 | 707 | if os.path.exists(sample_path_name): | 689 | if sample_path_name.exists(): |
899 | 708 | os.unlink(sample_path_name) | 690 | sample_path_name.unlink() |
900 | 709 | frame.save(sample_path_name, 'png') | 691 | frame.save(str(sample_path_name), 'png') |
901 | 710 | thumb = os.path.join(self.thumb_path, '{name}.png'.format(name=name)) | 692 | thumb_path = self.thumb_path / '{name}.png'.format(name=theme_name) |
902 | 711 | create_thumb(sample_path_name, thumb, False) | 693 | create_thumb(str(sample_path_name), str(thumb_path), False) |
903 | 712 | 694 | ||
904 | 713 | def update_preview_images(self): | 695 | def update_preview_images(self): |
905 | 714 | """ | 696 | """ |
906 | @@ -730,39 +712,32 @@ | |||
907 | 730 | """ | 712 | """ |
908 | 731 | return self.renderer.generate_preview(theme_data, force_page) | 713 | return self.renderer.generate_preview(theme_data, force_page) |
909 | 732 | 714 | ||
910 | 733 | def get_preview_image(self, theme): | ||
911 | 734 | """ | ||
912 | 735 | Return an image representing the look of the theme | ||
913 | 736 | |||
914 | 737 | :param theme: The theme to return the image for. | ||
915 | 738 | """ | ||
916 | 739 | return os.path.join(self.path, theme + '.png') | ||
917 | 740 | |||
918 | 741 | @staticmethod | 715 | @staticmethod |
919 | 742 | def _create_theme_from_xml(theme_xml, image_path): | 716 | def _create_theme_from_xml(theme_xml, image_path): |
920 | 743 | """ | 717 | """ |
921 | 744 | Return a theme object using information parsed from XML | 718 | Return a theme object using information parsed from XML |
922 | 745 | 719 | ||
923 | 746 | :param theme_xml: The Theme data object. | 720 | :param theme_xml: The Theme data object. |
925 | 747 | :param image_path: Where the theme image is stored | 721 | :param openlp.core.common.path.Path image_path: Where the theme image is stored |
926 | 748 | :return: Theme data. | 722 | :return: Theme data. |
927 | 723 | :rtype: Theme | ||
928 | 749 | """ | 724 | """ |
929 | 750 | theme = Theme() | 725 | theme = Theme() |
930 | 751 | theme.parse(theme_xml) | 726 | theme.parse(theme_xml) |
931 | 752 | theme.extend_image_filename(image_path) | 727 | theme.extend_image_filename(image_path) |
932 | 753 | return theme | 728 | return theme |
933 | 754 | 729 | ||
936 | 755 | @staticmethod | 730 | def _create_theme_from_json(self, theme_json, image_path): |
935 | 756 | def _create_theme_from_json(theme_json, image_path): | ||
937 | 757 | """ | 731 | """ |
938 | 758 | Return a theme object using information parsed from JSON | 732 | Return a theme object using information parsed from JSON |
939 | 759 | 733 | ||
940 | 760 | :param theme_json: The Theme data object. | 734 | :param theme_json: The Theme data object. |
942 | 761 | :param image_path: Where the theme image is stored | 735 | :param openlp.core.common.path.Path image_path: Where the theme image is stored |
943 | 762 | :return: Theme data. | 736 | :return: Theme data. |
944 | 737 | :rtype: Theme | ||
945 | 763 | """ | 738 | """ |
946 | 764 | theme = Theme() | 739 | theme = Theme() |
948 | 765 | theme.load_theme(theme_json) | 740 | theme.load_theme(theme_json, self.theme_path) |
949 | 766 | theme.extend_image_filename(image_path) | 741 | theme.extend_image_filename(image_path) |
950 | 767 | return theme | 742 | return theme |
951 | 768 | 743 | ||
952 | 769 | 744 | ||
953 | === modified file 'openlp/core/ui/themestab.py' | |||
954 | --- openlp/core/ui/themestab.py 2016-12-31 11:01:36 +0000 | |||
955 | +++ openlp/core/ui/themestab.py 2017-09-26 17:09:04 +0000 | |||
956 | @@ -211,8 +211,8 @@ | |||
957 | 211 | """ | 211 | """ |
958 | 212 | Utility method to update the global theme preview image. | 212 | Utility method to update the global theme preview image. |
959 | 213 | """ | 213 | """ |
962 | 214 | image = self.theme_manager.get_preview_image(self.global_theme) | 214 | image_path = self.theme_manager.theme_path / '{file_name}.png'.format(file_name=self.global_theme) |
963 | 215 | preview = QtGui.QPixmap(str(image)) | 215 | preview = QtGui.QPixmap(str(image_path)) |
964 | 216 | if not preview.isNull(): | 216 | if not preview.isNull(): |
965 | 217 | preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) | 217 | preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) |
966 | 218 | self.default_list_view.setPixmap(preview) | 218 | self.default_list_view.setPixmap(preview) |
967 | 219 | 219 | ||
968 | === modified file 'openlp/plugins/images/lib/upgrade.py' | |||
969 | --- openlp/plugins/images/lib/upgrade.py 2017-09-23 13:06:42 +0000 | |||
970 | +++ openlp/plugins/images/lib/upgrade.py 2017-09-26 17:09:04 +0000 | |||
971 | @@ -48,7 +48,6 @@ | |||
972 | 48 | """ | 48 | """ |
973 | 49 | Version 2 upgrade - Move file path from old db to JSON encoded path to new db. Added during 2.5 dev | 49 | Version 2 upgrade - Move file path from old db to JSON encoded path to new db. Added during 2.5 dev |
974 | 50 | """ | 50 | """ |
975 | 51 | # TODO: Update tests | ||
976 | 52 | log.debug('Starting upgrade_2 for file_path to JSON') | 51 | log.debug('Starting upgrade_2 for file_path to JSON') |
977 | 53 | old_table = Table('image_filenames', metadata, autoload=True) | 52 | old_table = Table('image_filenames', metadata, autoload=True) |
978 | 54 | if 'file_path' not in [col.name for col in old_table.c.values()]: | 53 | if 'file_path' not in [col.name for col in old_table.c.values()]: |
979 | 55 | 54 | ||
980 | === modified file 'tests/functional/openlp_core_lib/test_theme.py' | |||
981 | --- tests/functional/openlp_core_lib/test_theme.py 2017-05-24 20:04:48 +0000 | |||
982 | +++ tests/functional/openlp_core_lib/test_theme.py 2017-09-26 17:09:04 +0000 | |||
983 | @@ -22,8 +22,9 @@ | |||
984 | 22 | """ | 22 | """ |
985 | 23 | Package to test the openlp.core.lib.theme package. | 23 | Package to test the openlp.core.lib.theme package. |
986 | 24 | """ | 24 | """ |
987 | 25 | import os | ||
988 | 26 | from pathlib import Path | ||
989 | 25 | from unittest import TestCase | 27 | from unittest import TestCase |
990 | 26 | import os | ||
991 | 27 | 28 | ||
992 | 28 | from openlp.core.lib.theme import Theme | 29 | from openlp.core.lib.theme import Theme |
993 | 29 | 30 | ||
994 | @@ -79,16 +80,16 @@ | |||
995 | 79 | """ | 80 | """ |
996 | 80 | # GIVEN: A theme object | 81 | # GIVEN: A theme object |
997 | 81 | theme = Theme() | 82 | theme = Theme() |
1000 | 82 | theme.theme_name = 'MyBeautifulTheme ' | 83 | theme.theme_name = 'MyBeautifulTheme' |
1001 | 83 | theme.background_filename = ' video.mp4' | 84 | theme.background_filename = Path('video.mp4') |
1002 | 84 | theme.background_type = 'video' | 85 | theme.background_type = 'video' |
1004 | 85 | path = os.path.expanduser('~') | 86 | path = Path.home() |
1005 | 86 | 87 | ||
1006 | 87 | # WHEN: Theme.extend_image_filename is run | 88 | # WHEN: Theme.extend_image_filename is run |
1007 | 88 | theme.extend_image_filename(path) | 89 | theme.extend_image_filename(path) |
1008 | 89 | 90 | ||
1009 | 90 | # THEN: The filename of the background should be correct | 91 | # THEN: The filename of the background should be correct |
1011 | 91 | expected_filename = os.path.join(path, 'MyBeautifulTheme', 'video.mp4') | 92 | expected_filename = path / 'MyBeautifulTheme' / 'video.mp4' |
1012 | 92 | self.assertEqual(expected_filename, theme.background_filename) | 93 | self.assertEqual(expected_filename, theme.background_filename) |
1013 | 93 | self.assertEqual('MyBeautifulTheme', theme.theme_name) | 94 | self.assertEqual('MyBeautifulTheme', theme.theme_name) |
1014 | 94 | 95 | ||
1015 | 95 | 96 | ||
1016 | === modified file 'tests/functional/openlp_core_ui/test_maindisplay.py' | |||
1017 | --- tests/functional/openlp_core_ui/test_maindisplay.py 2017-07-08 13:12:31 +0000 | |||
1018 | +++ tests/functional/openlp_core_ui/test_maindisplay.py 2017-09-26 17:09:04 +0000 | |||
1019 | @@ -27,10 +27,10 @@ | |||
1020 | 27 | 27 | ||
1021 | 28 | from PyQt5 import QtCore | 28 | from PyQt5 import QtCore |
1022 | 29 | 29 | ||
1024 | 30 | from openlp.core.common import Registry, is_macosx, Settings | 30 | from openlp.core.common import Registry, is_macosx |
1025 | 31 | from openlp.core.common.path import Path | ||
1026 | 31 | from openlp.core.lib import ScreenList, PluginManager | 32 | from openlp.core.lib import ScreenList, PluginManager |
1027 | 32 | from openlp.core.ui import MainDisplay, AudioPlayer | 33 | from openlp.core.ui import MainDisplay, AudioPlayer |
1028 | 33 | from openlp.core.ui.media import MediaController | ||
1029 | 34 | from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET | 34 | from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET |
1030 | 35 | 35 | ||
1031 | 36 | from tests.helpers.testmixin import TestMixin | 36 | from tests.helpers.testmixin import TestMixin |
1032 | @@ -184,7 +184,7 @@ | |||
1033 | 184 | self.assertEqual(pyobjc_nsview.window().collectionBehavior(), NSWindowCollectionBehaviorManaged, | 184 | self.assertEqual(pyobjc_nsview.window().collectionBehavior(), NSWindowCollectionBehaviorManaged, |
1034 | 185 | 'Window collection behavior should be NSWindowCollectionBehaviorManaged') | 185 | 'Window collection behavior should be NSWindowCollectionBehaviorManaged') |
1035 | 186 | 186 | ||
1037 | 187 | @patch(u'openlp.core.ui.maindisplay.Settings') | 187 | @patch('openlp.core.ui.maindisplay.Settings') |
1038 | 188 | def test_show_display_startup_logo(self, MockedSettings): | 188 | def test_show_display_startup_logo(self, MockedSettings): |
1039 | 189 | # GIVEN: Mocked show_display, setting for logo visibility | 189 | # GIVEN: Mocked show_display, setting for logo visibility |
1040 | 190 | display = MagicMock() | 190 | display = MagicMock() |
1041 | @@ -204,7 +204,7 @@ | |||
1042 | 204 | # THEN: setVisible should had been called with "True" | 204 | # THEN: setVisible should had been called with "True" |
1043 | 205 | main_display.setVisible.assert_called_once_with(True) | 205 | main_display.setVisible.assert_called_once_with(True) |
1044 | 206 | 206 | ||
1046 | 207 | @patch(u'openlp.core.ui.maindisplay.Settings') | 207 | @patch('openlp.core.ui.maindisplay.Settings') |
1047 | 208 | def test_show_display_hide_startup_logo(self, MockedSettings): | 208 | def test_show_display_hide_startup_logo(self, MockedSettings): |
1048 | 209 | # GIVEN: Mocked show_display, setting for logo visibility | 209 | # GIVEN: Mocked show_display, setting for logo visibility |
1049 | 210 | display = MagicMock() | 210 | display = MagicMock() |
1050 | @@ -224,8 +224,8 @@ | |||
1051 | 224 | # THEN: setVisible should had not been called | 224 | # THEN: setVisible should had not been called |
1052 | 225 | main_display.setVisible.assert_not_called() | 225 | main_display.setVisible.assert_not_called() |
1053 | 226 | 226 | ||
1056 | 227 | @patch(u'openlp.core.ui.maindisplay.Settings') | 227 | @patch('openlp.core.ui.maindisplay.Settings') |
1057 | 228 | @patch(u'openlp.core.ui.maindisplay.build_html') | 228 | @patch('openlp.core.ui.maindisplay.build_html') |
1058 | 229 | def test_build_html_no_video(self, MockedSettings, Mocked_build_html): | 229 | def test_build_html_no_video(self, MockedSettings, Mocked_build_html): |
1059 | 230 | # GIVEN: Mocked display | 230 | # GIVEN: Mocked display |
1060 | 231 | display = MagicMock() | 231 | display = MagicMock() |
1061 | @@ -252,8 +252,8 @@ | |||
1062 | 252 | self.assertEquals(main_display.media_controller.video.call_count, 0, | 252 | self.assertEquals(main_display.media_controller.video.call_count, 0, |
1063 | 253 | 'Media Controller video should not have been called') | 253 | 'Media Controller video should not have been called') |
1064 | 254 | 254 | ||
1067 | 255 | @patch(u'openlp.core.ui.maindisplay.Settings') | 255 | @patch('openlp.core.ui.maindisplay.Settings') |
1068 | 256 | @patch(u'openlp.core.ui.maindisplay.build_html') | 256 | @patch('openlp.core.ui.maindisplay.build_html') |
1069 | 257 | def test_build_html_video(self, MockedSettings, Mocked_build_html): | 257 | def test_build_html_video(self, MockedSettings, Mocked_build_html): |
1070 | 258 | # GIVEN: Mocked display | 258 | # GIVEN: Mocked display |
1071 | 259 | display = MagicMock() | 259 | display = MagicMock() |
1072 | @@ -270,7 +270,7 @@ | |||
1073 | 270 | service_item.theme_data = MagicMock() | 270 | service_item.theme_data = MagicMock() |
1074 | 271 | service_item.theme_data.background_type = 'video' | 271 | service_item.theme_data.background_type = 'video' |
1075 | 272 | service_item.theme_data.theme_name = 'name' | 272 | service_item.theme_data.theme_name = 'name' |
1077 | 273 | service_item.theme_data.background_filename = 'background_filename' | 273 | service_item.theme_data.background_filename = Path('background_filename') |
1078 | 274 | mocked_plugin = MagicMock() | 274 | mocked_plugin = MagicMock() |
1079 | 275 | display.plugin_manager = PluginManager() | 275 | display.plugin_manager = PluginManager() |
1080 | 276 | display.plugin_manager.plugins = [mocked_plugin] | 276 | display.plugin_manager.plugins = [mocked_plugin] |
1081 | 277 | 277 | ||
1082 | === modified file 'tests/functional/openlp_core_ui/test_themeform.py' | |||
1083 | --- tests/functional/openlp_core_ui/test_themeform.py 2017-08-25 20:03:25 +0000 | |||
1084 | +++ tests/functional/openlp_core_ui/test_themeform.py 2017-09-26 17:09:04 +0000 | |||
1085 | @@ -49,5 +49,5 @@ | |||
1086 | 49 | self.instance.on_image_path_edit_path_changed(Path('/', 'new', 'pat.h')) | 49 | self.instance.on_image_path_edit_path_changed(Path('/', 'new', 'pat.h')) |
1087 | 50 | 50 | ||
1088 | 51 | # THEN: The theme background file should be set and `set_background_page_values` should have been called | 51 | # THEN: The theme background file should be set and `set_background_page_values` should have been called |
1090 | 52 | self.assertEqual(self.instance.theme.background_filename, '/new/pat.h') | 52 | self.assertEqual(self.instance.theme.background_filename, Path('/', 'new', 'pat.h')) |
1091 | 53 | mocked_set_background_page_values.assert_called_once_with() | 53 | mocked_set_background_page_values.assert_called_once_with() |
1092 | 54 | 54 | ||
1093 | === modified file 'tests/functional/openlp_core_ui/test_thememanager.py' | |||
1094 | --- tests/functional/openlp_core_ui/test_thememanager.py 2017-08-12 17:45:56 +0000 | |||
1095 | +++ tests/functional/openlp_core_ui/test_thememanager.py 2017-09-26 17:09:04 +0000 | |||
1096 | @@ -30,8 +30,9 @@ | |||
1097 | 30 | 30 | ||
1098 | 31 | from PyQt5 import QtWidgets | 31 | from PyQt5 import QtWidgets |
1099 | 32 | 32 | ||
1100 | 33 | from openlp.core.common import Registry | ||
1101 | 34 | from openlp.core.common.path import Path | ||
1102 | 33 | from openlp.core.ui import ThemeManager | 35 | from openlp.core.ui import ThemeManager |
1103 | 34 | from openlp.core.common import Registry | ||
1104 | 35 | 36 | ||
1105 | 36 | from tests.utils.constants import TEST_RESOURCES_PATH | 37 | from tests.utils.constants import TEST_RESOURCES_PATH |
1106 | 37 | 38 | ||
1107 | @@ -57,13 +58,13 @@ | |||
1108 | 57 | """ | 58 | """ |
1109 | 58 | # GIVEN: A new ThemeManager instance. | 59 | # GIVEN: A new ThemeManager instance. |
1110 | 59 | theme_manager = ThemeManager() | 60 | theme_manager = ThemeManager() |
1112 | 60 | theme_manager.path = os.path.join(TEST_RESOURCES_PATH, 'themes') | 61 | theme_manager.theme_path = Path(TEST_RESOURCES_PATH, 'themes') |
1113 | 61 | with patch('zipfile.ZipFile.__init__') as mocked_zipfile_init, \ | 62 | with patch('zipfile.ZipFile.__init__') as mocked_zipfile_init, \ |
1114 | 62 | patch('zipfile.ZipFile.write') as mocked_zipfile_write: | 63 | patch('zipfile.ZipFile.write') as mocked_zipfile_write: |
1115 | 63 | mocked_zipfile_init.return_value = None | 64 | mocked_zipfile_init.return_value = None |
1116 | 64 | 65 | ||
1117 | 65 | # WHEN: The theme is exported | 66 | # WHEN: The theme is exported |
1119 | 66 | theme_manager._export_theme(os.path.join('some', 'path', 'Default.otz'), 'Default') | 67 | theme_manager._export_theme(Path('some', 'path', 'Default.otz'), 'Default') |
1120 | 67 | 68 | ||
1121 | 68 | # THEN: The zipfile should be created at the given path | 69 | # THEN: The zipfile should be created at the given path |
1122 | 69 | mocked_zipfile_init.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w') | 70 | mocked_zipfile_init.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w') |
1123 | @@ -86,57 +87,49 @@ | |||
1124 | 86 | """ | 87 | """ |
1125 | 87 | Test that we don't try to overwrite a theme background image with itself | 88 | Test that we don't try to overwrite a theme background image with itself |
1126 | 88 | """ | 89 | """ |
1128 | 89 | # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, | 90 | # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, |
1129 | 90 | # theme, check_directory_exists and thememanager-attributes. | 91 | # theme, check_directory_exists and thememanager-attributes. |
1132 | 91 | with patch('builtins.open') as mocked_open, \ | 92 | with patch('openlp.core.ui.thememanager.copyfile') as mocked_copyfile, \ |
1131 | 92 | patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ | ||
1133 | 93 | patch('openlp.core.ui.thememanager.check_directory_exists'): | 93 | patch('openlp.core.ui.thememanager.check_directory_exists'): |
1134 | 94 | mocked_open.return_value = MagicMock() | ||
1135 | 95 | theme_manager = ThemeManager(None) | 94 | theme_manager = ThemeManager(None) |
1136 | 96 | theme_manager.old_background_image = None | 95 | theme_manager.old_background_image = None |
1137 | 97 | theme_manager.generate_and_save_image = MagicMock() | 96 | theme_manager.generate_and_save_image = MagicMock() |
1139 | 98 | theme_manager.path = '' | 97 | theme_manager.theme_path = MagicMock() |
1140 | 99 | mocked_theme = MagicMock() | 98 | mocked_theme = MagicMock() |
1141 | 100 | mocked_theme.theme_name = 'themename' | 99 | mocked_theme.theme_name = 'themename' |
1142 | 101 | mocked_theme.extract_formatted_xml = MagicMock() | 100 | mocked_theme.extract_formatted_xml = MagicMock() |
1143 | 102 | mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() | 101 | mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() |
1144 | 103 | 102 | ||
1145 | 104 | # WHEN: Calling _write_theme with path to the same image, but the path written slightly different | 103 | # WHEN: Calling _write_theme with path to the same image, but the path written slightly different |
1150 | 105 | file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') | 104 | file_name1 = Path(TEST_RESOURCES_PATH, 'church.jpg') |
1151 | 106 | # Do replacement from end of string to avoid problems with path start | 105 | theme_manager._write_theme(mocked_theme, file_name1, file_name1) |
1148 | 107 | file_name2 = file_name1[::-1].replace(os.sep, os.sep + os.sep, 2)[::-1] | ||
1149 | 108 | theme_manager._write_theme(mocked_theme, file_name1, file_name2) | ||
1152 | 109 | 106 | ||
1153 | 110 | # THEN: The mocked_copyfile should not have been called | 107 | # THEN: The mocked_copyfile should not have been called |
1155 | 111 | self.assertFalse(mocked_copyfile.called, 'shutil.copyfile should not be called') | 108 | self.assertFalse(mocked_copyfile.called, 'copyfile should not be called') |
1156 | 112 | 109 | ||
1157 | 113 | def test_write_theme_diff_images(self): | 110 | def test_write_theme_diff_images(self): |
1158 | 114 | """ | 111 | """ |
1159 | 115 | Test that we do overwrite a theme background image when a new is submitted | 112 | Test that we do overwrite a theme background image when a new is submitted |
1160 | 116 | """ | 113 | """ |
1162 | 117 | # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, | 114 | # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, |
1163 | 118 | # theme, check_directory_exists and thememanager-attributes. | 115 | # theme, check_directory_exists and thememanager-attributes. |
1166 | 119 | with patch('builtins.open') as mocked_open, \ | 116 | with patch('openlp.core.ui.thememanager.copyfile') as mocked_copyfile, \ |
1165 | 120 | patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ | ||
1167 | 121 | patch('openlp.core.ui.thememanager.check_directory_exists'): | 117 | patch('openlp.core.ui.thememanager.check_directory_exists'): |
1168 | 122 | mocked_open.return_value = MagicMock() | ||
1169 | 123 | theme_manager = ThemeManager(None) | 118 | theme_manager = ThemeManager(None) |
1170 | 124 | theme_manager.old_background_image = None | 119 | theme_manager.old_background_image = None |
1171 | 125 | theme_manager.generate_and_save_image = MagicMock() | 120 | theme_manager.generate_and_save_image = MagicMock() |
1173 | 126 | theme_manager.path = '' | 121 | theme_manager.theme_path = MagicMock() |
1174 | 127 | mocked_theme = MagicMock() | 122 | mocked_theme = MagicMock() |
1175 | 128 | mocked_theme.theme_name = 'themename' | 123 | mocked_theme.theme_name = 'themename' |
1176 | 129 | mocked_theme.filename = "filename" | 124 | mocked_theme.filename = "filename" |
1177 | 130 | # mocked_theme.extract_formatted_xml = MagicMock() | ||
1178 | 131 | # mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() | ||
1179 | 132 | 125 | ||
1180 | 133 | # WHEN: Calling _write_theme with path to different images | 126 | # WHEN: Calling _write_theme with path to different images |
1183 | 134 | file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') | 127 | file_name1 = Path(TEST_RESOURCES_PATH, 'church.jpg') |
1184 | 135 | file_name2 = os.path.join(TEST_RESOURCES_PATH, 'church2.jpg') | 128 | file_name2 = Path(TEST_RESOURCES_PATH, 'church2.jpg') |
1185 | 136 | theme_manager._write_theme(mocked_theme, file_name1, file_name2) | 129 | theme_manager._write_theme(mocked_theme, file_name1, file_name2) |
1186 | 137 | 130 | ||
1187 | 138 | # THEN: The mocked_copyfile should not have been called | 131 | # THEN: The mocked_copyfile should not have been called |
1189 | 139 | self.assertTrue(mocked_copyfile.called, 'shutil.copyfile should be called') | 132 | self.assertTrue(mocked_copyfile.called, 'copyfile should be called') |
1190 | 140 | 133 | ||
1191 | 141 | def test_write_theme_special_char_name(self): | 134 | def test_write_theme_special_char_name(self): |
1192 | 142 | """ | 135 | """ |
1193 | @@ -146,7 +139,7 @@ | |||
1194 | 146 | theme_manager = ThemeManager(None) | 139 | theme_manager = ThemeManager(None) |
1195 | 147 | theme_manager.old_background_image = None | 140 | theme_manager.old_background_image = None |
1196 | 148 | theme_manager.generate_and_save_image = MagicMock() | 141 | theme_manager.generate_and_save_image = MagicMock() |
1198 | 149 | theme_manager.path = self.temp_folder | 142 | theme_manager.theme_path = Path(self.temp_folder) |
1199 | 150 | mocked_theme = MagicMock() | 143 | mocked_theme = MagicMock() |
1200 | 151 | mocked_theme.theme_name = 'theme 愛 name' | 144 | mocked_theme.theme_name = 'theme 愛 name' |
1201 | 152 | mocked_theme.export_theme.return_value = "{}" | 145 | mocked_theme.export_theme.return_value = "{}" |
1202 | @@ -208,17 +201,17 @@ | |||
1203 | 208 | theme_manager = ThemeManager(None) | 201 | theme_manager = ThemeManager(None) |
1204 | 209 | theme_manager._create_theme_from_xml = MagicMock() | 202 | theme_manager._create_theme_from_xml = MagicMock() |
1205 | 210 | theme_manager.generate_and_save_image = MagicMock() | 203 | theme_manager.generate_and_save_image = MagicMock() |
1209 | 211 | theme_manager.path = '' | 204 | theme_manager.theme_path = None |
1210 | 212 | folder = mkdtemp() | 205 | folder = Path(mkdtemp()) |
1211 | 213 | theme_file = os.path.join(TEST_RESOURCES_PATH, 'themes', 'Moss_on_tree.otz') | 206 | theme_file = Path(TEST_RESOURCES_PATH, 'themes', 'Moss_on_tree.otz') |
1212 | 214 | 207 | ||
1213 | 215 | # WHEN: We try to unzip it | 208 | # WHEN: We try to unzip it |
1214 | 216 | theme_manager.unzip_theme(theme_file, folder) | 209 | theme_manager.unzip_theme(theme_file, folder) |
1215 | 217 | 210 | ||
1216 | 218 | # THEN: Files should be unpacked | 211 | # THEN: Files should be unpacked |
1218 | 219 | self.assertTrue(os.path.exists(os.path.join(folder, 'Moss on tree', 'Moss on tree.xml'))) | 212 | self.assertTrue((folder / 'Moss on tree' / 'Moss on tree.xml').exists()) |
1219 | 220 | self.assertEqual(mocked_critical_error_message_box.call_count, 0, 'No errors should have happened') | 213 | self.assertEqual(mocked_critical_error_message_box.call_count, 0, 'No errors should have happened') |
1221 | 221 | shutil.rmtree(folder) | 214 | shutil.rmtree(str(folder)) |
1222 | 222 | 215 | ||
1223 | 223 | def test_unzip_theme_invalid_version(self): | 216 | def test_unzip_theme_invalid_version(self): |
1224 | 224 | """ | 217 | """ |
1225 | 225 | 218 | ||
1226 | === modified file 'tests/interfaces/openlp_core_ui/test_thememanager.py' | |||
1227 | --- tests/interfaces/openlp_core_ui/test_thememanager.py 2017-04-24 05:17:55 +0000 | |||
1228 | +++ tests/interfaces/openlp_core_ui/test_thememanager.py 2017-09-26 17:09:04 +0000 | |||
1229 | @@ -26,7 +26,8 @@ | |||
1230 | 26 | from unittest.mock import patch, MagicMock | 26 | from unittest.mock import patch, MagicMock |
1231 | 27 | 27 | ||
1232 | 28 | from openlp.core.common import Registry, Settings | 28 | from openlp.core.common import Registry, Settings |
1234 | 29 | from openlp.core.ui import ThemeManager, ThemeForm, FileRenameForm | 29 | from openlp.core.common.path import Path |
1235 | 30 | from openlp.core.ui import ThemeManager | ||
1236 | 30 | 31 | ||
1237 | 31 | from tests.helpers.testmixin import TestMixin | 32 | from tests.helpers.testmixin import TestMixin |
1238 | 32 | 33 | ||
1239 | @@ -91,6 +92,23 @@ | |||
1240 | 91 | assert self.theme_manager.thumb_path.startswith(self.theme_manager.path) is True, \ | 92 | assert self.theme_manager.thumb_path.startswith(self.theme_manager.path) is True, \ |
1241 | 92 | 'The thumb path and the main path should start with the same value' | 93 | 'The thumb path and the main path should start with the same value' |
1242 | 93 | 94 | ||
1243 | 95 | def test_build_theme_path(self): | ||
1244 | 96 | """ | ||
1245 | 97 | Test the thememanager build_theme_path - basic test | ||
1246 | 98 | """ | ||
1247 | 99 | # GIVEN: A new a call to initialise | ||
1248 | 100 | with patch('openlp.core.common.AppLocation.get_section_data_path', return_value=Path('test/path')): | ||
1249 | 101 | Settings().setValue('themes/global theme', 'my_theme') | ||
1250 | 102 | |||
1251 | 103 | self.theme_manager.theme_form = MagicMock() | ||
1252 | 104 | self.theme_manager.load_first_time_themes = MagicMock() | ||
1253 | 105 | |||
1254 | 106 | # WHEN: the build_theme_path is run | ||
1255 | 107 | self.theme_manager.build_theme_path() | ||
1256 | 108 | |||
1257 | 109 | # THEN: The thumbnail path should be a sub path of the test path | ||
1258 | 110 | self.assertEqual(self.theme_manager.thumb_path, Path('test/path/thumbnails')) | ||
1259 | 111 | |||
1260 | 94 | def test_click_on_new_theme(self): | 112 | def test_click_on_new_theme(self): |
1261 | 95 | """ | 113 | """ |
1262 | 96 | Test the on_add_theme event handler is called by the UI | 114 | Test the on_add_theme event handler is called by the UI |
1263 | @@ -109,17 +127,16 @@ | |||
1264 | 109 | 127 | ||
1265 | 110 | @patch('openlp.core.ui.themeform.ThemeForm._setup') | 128 | @patch('openlp.core.ui.themeform.ThemeForm._setup') |
1266 | 111 | @patch('openlp.core.ui.filerenameform.FileRenameForm._setup') | 129 | @patch('openlp.core.ui.filerenameform.FileRenameForm._setup') |
1268 | 112 | def test_bootstrap_post(self, mocked_theme_form, mocked_rename_form): | 130 | def test_bootstrap_post(self, mocked_rename_form, mocked_theme_form): |
1269 | 113 | """ | 131 | """ |
1270 | 114 | Test the functions of bootstrap_post_setup are called. | 132 | Test the functions of bootstrap_post_setup are called. |
1271 | 115 | """ | 133 | """ |
1272 | 116 | # GIVEN: | 134 | # GIVEN: |
1273 | 117 | self.theme_manager.load_themes = MagicMock() | 135 | self.theme_manager.load_themes = MagicMock() |
1275 | 118 | self.theme_manager.path = MagicMock() | 136 | self.theme_manager.theme_path = MagicMock() |
1276 | 119 | 137 | ||
1277 | 120 | # WHEN: | 138 | # WHEN: |
1278 | 121 | self.theme_manager.bootstrap_post_set_up() | 139 | self.theme_manager.bootstrap_post_set_up() |
1279 | 122 | 140 | ||
1280 | 123 | # THEN: | 141 | # THEN: |
1281 | 124 | self.assertEqual(self.theme_manager.path, self.theme_manager.theme_form.path) | ||
1282 | 125 | self.assertEqual(1, self.theme_manager.load_themes.call_count, "load_themes should have been called once") | 142 | self.assertEqual(1, self.theme_manager.load_themes.call_count, "load_themes should have been called once") |
Also automatically upgrades themes from XML to json.