Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 2850 | ||||||||||||||||
Proposed branch: | lp:~phill-ridout/openlp/fixes-I | ||||||||||||||||
Merge into: | lp:openlp | ||||||||||||||||
Diff against target: |
1333 lines (+187/-208) 47 files modified
openlp/core/api/deploy.py (+2/-2) openlp/core/app.py (+8/-4) openlp/core/common/__init__.py (+2/-2) openlp/core/common/path.py (+1/-1) openlp/core/common/settings.py (+1/-1) openlp/core/display/html/display.html (+1/-1) openlp/core/display/html/display.js (+1/-1) openlp/core/lib/__init__.py (+6/-8) openlp/core/lib/db.py (+15/-11) openlp/core/lib/mediamanageritem.py (+6/-6) openlp/core/lib/serviceitem.py (+3/-3) openlp/core/ui/advancedtab.py (+1/-1) openlp/core/ui/exceptiondialog.py (+3/-3) openlp/core/ui/exceptionform.py (+14/-7) openlp/core/ui/generaltab.py (+0/-1) openlp/core/ui/mainwindow.py (+1/-1) openlp/core/ui/servicemanager.py (+13/-12) openlp/core/ui/thememanager.py (+10/-10) openlp/core/version.py (+1/-1) openlp/core/widgets/edits.py (+1/-1) openlp/core/widgets/wizard.py (+1/-41) openlp/plugins/bibles/forms/bibleimportform.py (+2/-2) openlp/plugins/bibles/lib/bibleimport.py (+2/-2) openlp/plugins/bibles/lib/db.py (+6/-6) openlp/plugins/bibles/lib/importers/wordproject.py (+1/-1) openlp/plugins/bibles/lib/manager.py (+1/-1) openlp/plugins/bibles/lib/mediaitem.py (+3/-3) openlp/plugins/custom/lib/mediaitem.py (+3/-6) openlp/plugins/images/lib/mediaitem.py (+3/-3) openlp/plugins/media/lib/mediaitem.py (+7/-7) openlp/plugins/presentations/lib/mediaitem.py (+3/-3) openlp/plugins/presentations/lib/messagelistener.py (+2/-8) openlp/plugins/songs/forms/songimportform.py (+7/-2) openlp/plugins/songs/lib/importers/cclifile.py (+4/-3) openlp/plugins/songs/lib/mediaitem.py (+2/-4) openlp/plugins/songusage/forms/songusagedetailform.py (+2/-2) run_openlp.py (+8/-2) tests/functional/openlp_core/api/test_deploy.py (+2/-2) tests/functional/openlp_core/common/test_init.py (+14/-8) tests/functional/openlp_core/common/test_path.py (+3/-5) tests/functional/openlp_core/lib/test_serviceitem.py (+4/-4) tests/functional/openlp_core/ui/test_thememanager.py (+3/-3) tests/functional/openlp_plugins/bibles/test_manager.py (+3/-2) tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py (+2/-2) tests/openlp_core/common/test_network_interfaces.py (+1/-1) tests/openlp_core/projectors/test_projector_pjlink_commands_01.py (+6/-6) tests/openlp_core/projectors/test_projector_sourceform.py (+2/-2) |
||||||||||||||||
To merge this branch: | bzr merge lp:~phill-ridout/openlp/fixes-I | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Bentley | Pending | ||
Review via email: mp+364652@code.launchpad.net |
This proposal supersedes a proposal from 2019-03-17.
Commit message
Fixes a few bugs, and some path lib refactors
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
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 : 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
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal | # |
Looks ok.
Please do not try and change vlcplayer as you will be on a mission of despair!
review:
Approve
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
Raoul Snyman (raoul-snyman) wrote : | # |
macOS tests failed, please see https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'openlp/core/api/deploy.py' | |||
2 | --- openlp/core/api/deploy.py 2019-02-14 15:09:09 +0000 | |||
3 | +++ openlp/core/api/deploy.py 2019-03-17 21:06:27 +0000 | |||
4 | @@ -39,8 +39,8 @@ | |||
5 | 39 | :return: None | 39 | :return: None |
6 | 40 | """ | 40 | """ |
7 | 41 | zip_path = app_root_path / zip_name | 41 | zip_path = app_root_path / zip_name |
10 | 42 | web_zip = ZipFile(str(zip_path)) | 42 | web_zip = ZipFile(zip_path) |
11 | 43 | web_zip.extractall(str(app_root_path)) | 43 | web_zip.extractall(app_root_path) |
12 | 44 | 44 | ||
13 | 45 | 45 | ||
14 | 46 | def download_sha256(): | 46 | def download_sha256(): |
15 | 47 | 47 | ||
16 | === modified file 'openlp/core/app.py' | |||
17 | --- openlp/core/app.py 2019-02-14 15:09:09 +0000 | |||
18 | +++ openlp/core/app.py 2019-03-17 21:06:27 +0000 | |||
19 | @@ -317,8 +317,7 @@ | |||
20 | 317 | """ | 317 | """ |
21 | 318 | create_paths(log_path, do_not_log=True) | 318 | create_paths(log_path, do_not_log=True) |
22 | 319 | file_path = log_path / 'openlp.log' | 319 | file_path = log_path / 'openlp.log' |
25 | 320 | # TODO: FileHandler accepts a Path object in Py3.6 | 320 | logfile = logging.FileHandler(file_path, 'w', encoding='UTF-8') |
24 | 321 | logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8') | ||
26 | 322 | logfile.setFormatter(logging.Formatter('%(asctime)s %(threadName)s %(name)-55s %(levelname)-8s %(message)s')) | 321 | logfile.setFormatter(logging.Formatter('%(asctime)s %(threadName)s %(name)-55s %(levelname)-8s %(message)s')) |
27 | 323 | log.addHandler(logfile) | 322 | log.addHandler(logfile) |
28 | 324 | if log.isEnabledFor(logging.DEBUG): | 323 | if log.isEnabledFor(logging.DEBUG): |
29 | @@ -364,7 +363,7 @@ | |||
30 | 364 | portable_settings_path = data_path / 'OpenLP.ini' | 363 | portable_settings_path = data_path / 'OpenLP.ini' |
31 | 365 | # Make this our settings file | 364 | # Make this our settings file |
32 | 366 | log.info('INI file: {name}'.format(name=portable_settings_path)) | 365 | log.info('INI file: {name}'.format(name=portable_settings_path)) |
34 | 367 | Settings.set_filename(str(portable_settings_path)) | 366 | Settings.set_filename(portable_settings_path) |
35 | 368 | portable_settings = Settings() | 367 | portable_settings = Settings() |
36 | 369 | # Set our data path | 368 | # Set our data path |
37 | 370 | log.info('Data path: {name}'.format(name=data_path)) | 369 | log.info('Data path: {name}'.format(name=data_path)) |
38 | @@ -405,7 +404,12 @@ | |||
39 | 405 | None, translate('OpenLP', 'Settings Upgrade'), | 404 | None, translate('OpenLP', 'Settings Upgrade'), |
40 | 406 | translate('OpenLP', 'Your settings are about to be upgraded. A backup will be created at ' | 405 | translate('OpenLP', 'Your settings are about to be upgraded. A backup will be created at ' |
41 | 407 | '{back_up_path}').format(back_up_path=back_up_path)) | 406 | '{back_up_path}').format(back_up_path=back_up_path)) |
43 | 408 | settings.export(back_up_path) | 407 | try: |
44 | 408 | settings.export(back_up_path) | ||
45 | 409 | except OSError: | ||
46 | 410 | QtWidgets.QMessageBox.warning( | ||
47 | 411 | None, translate('OpenLP', 'Settings Upgrade'), | ||
48 | 412 | translate('OpenLP', 'Settings back up failed.\n\nContinuining to upgrade.')) | ||
49 | 409 | settings.upgrade_settings() | 413 | settings.upgrade_settings() |
50 | 410 | # First time checks in settings | 414 | # First time checks in settings |
51 | 411 | if not Settings().value('core/has run wizard'): | 415 | if not Settings().value('core/has run wizard'): |
52 | 412 | 416 | ||
53 | === modified file 'openlp/core/common/__init__.py' | |||
54 | --- openlp/core/common/__init__.py 2019-02-14 15:09:09 +0000 | |||
55 | +++ openlp/core/common/__init__.py 2019-03-17 21:06:27 +0000 | |||
56 | @@ -474,10 +474,10 @@ | |||
57 | 474 | if not chunk: | 474 | if not chunk: |
58 | 475 | break | 475 | break |
59 | 476 | detector.feed(chunk) | 476 | detector.feed(chunk) |
60 | 477 | detector.close() | ||
61 | 478 | return detector.result | ||
62 | 479 | except OSError: | 477 | except OSError: |
63 | 480 | log.exception('Error detecting file encoding') | 478 | log.exception('Error detecting file encoding') |
64 | 479 | finally: | ||
65 | 480 | return detector.close() | ||
66 | 481 | 481 | ||
67 | 482 | 482 | ||
68 | 483 | def normalize_str(irregular_string): | 483 | def normalize_str(irregular_string): |
69 | 484 | 484 | ||
70 | === modified file 'openlp/core/common/path.py' | |||
71 | --- openlp/core/common/path.py 2019-02-14 15:09:09 +0000 | |||
72 | +++ openlp/core/common/path.py 2019-03-17 21:06:27 +0000 | |||
73 | @@ -78,7 +78,7 @@ | |||
74 | 78 | :param onerror: Handler function to handle any errors | 78 | :param onerror: Handler function to handle any errors |
75 | 79 | :rtype: None | 79 | :rtype: None |
76 | 80 | """ | 80 | """ |
78 | 81 | shutil.rmtree(str(self), ignore_errors, onerror) | 81 | shutil.rmtree(self, ignore_errors, onerror) |
79 | 82 | 82 | ||
80 | 83 | 83 | ||
81 | 84 | def replace_params(args, kwargs, params): | 84 | def replace_params(args, kwargs, params): |
82 | 85 | 85 | ||
83 | === modified file 'openlp/core/common/settings.py' | |||
84 | --- openlp/core/common/settings.py 2019-02-14 15:09:09 +0000 | |||
85 | +++ openlp/core/common/settings.py 2019-03-17 21:06:27 +0000 | |||
86 | @@ -540,7 +540,7 @@ | |||
87 | 540 | old_values = [self._convert_value(old_value, default_value) | 540 | old_values = [self._convert_value(old_value, default_value) |
88 | 541 | for old_value, default_value in zip(old_values, default_values)] | 541 | for old_value, default_value in zip(old_values, default_values)] |
89 | 542 | # Iterate over our rules and check what the old_value should be "converted" to. | 542 | # Iterate over our rules and check what the old_value should be "converted" to. |
91 | 543 | new_value = None | 543 | new_value = old_values[0] |
92 | 544 | for new_rule, old_rule in rules: | 544 | for new_rule, old_rule in rules: |
93 | 545 | # If the value matches with the condition (rule), then use the provided value. This is used to | 545 | # If the value matches with the condition (rule), then use the provided value. This is used to |
94 | 546 | # convert values. E. g. an old value 1 results in True, and 0 in False. | 546 | # convert values. E. g. an old value 1 results in True, and 0 in False. |
95 | 547 | 547 | ||
96 | === modified file 'openlp/core/display/html/display.html' | |||
97 | --- openlp/core/display/html/display.html 2018-10-12 19:51:51 +0000 | |||
98 | +++ openlp/core/display/html/display.html 2019-03-17 21:06:27 +0000 | |||
99 | @@ -6,7 +6,7 @@ | |||
100 | 6 | <style type="text/css"> | 6 | <style type="text/css"> |
101 | 7 | body { | 7 | body { |
102 | 8 | background: transparent !important; | 8 | background: transparent !important; |
104 | 9 | color: #fff !important; | 9 | color: rgb(255, 255, 255) !important; |
105 | 10 | } | 10 | } |
106 | 11 | sup { | 11 | sup { |
107 | 12 | vertical-align: super !important; | 12 | vertical-align: super !important; |
108 | 13 | 13 | ||
109 | === modified file 'openlp/core/display/html/display.js' | |||
110 | --- openlp/core/display/html/display.js 2019-02-05 21:26:30 +0000 | |||
111 | +++ openlp/core/display/html/display.js 2019-03-17 21:06:27 +0000 | |||
112 | @@ -315,7 +315,7 @@ | |||
113 | 315 | section.setAttribute("style", "height: 100%; width: 100%; position: relative;"); | 315 | section.setAttribute("style", "height: 100%; width: 100%; position: relative;"); |
114 | 316 | var img = document.createElement('img'); | 316 | var img = document.createElement('img'); |
115 | 317 | img.src = image; | 317 | img.src = image; |
117 | 318 | img.setAttribute("style", "position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto;"); | 318 | img.setAttribute("style", "position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; max-height: 100%; max-width: 100%"); |
118 | 319 | section.appendChild(img); | 319 | section.appendChild(img); |
119 | 320 | slidesDiv.appendChild(section); | 320 | slidesDiv.appendChild(section); |
120 | 321 | Display._slides['0'] = 0; | 321 | Display._slides['0'] = 0; |
121 | 322 | 322 | ||
122 | === modified file 'openlp/core/lib/__init__.py' | |||
123 | --- openlp/core/lib/__init__.py 2019-02-14 15:09:09 +0000 | |||
124 | +++ openlp/core/lib/__init__.py 2019-03-17 21:06:27 +0000 | |||
125 | @@ -242,16 +242,16 @@ | |||
126 | 242 | """ | 242 | """ |
127 | 243 | Resize an image to fit on the current screen for the web and returns it as a byte stream. | 243 | Resize an image to fit on the current screen for the web and returns it as a byte stream. |
128 | 244 | 244 | ||
130 | 245 | :param image: The image to converted. | 245 | :param image: The image to be converted. |
131 | 246 | :param base_64: If True returns the image as Base64 bytes, otherwise the image is returned as a byte array. | 246 | :param base_64: If True returns the image as Base64 bytes, otherwise the image is returned as a byte array. |
132 | 247 | To preserve original intention, this defaults to True | 247 | To preserve original intention, this defaults to True |
133 | 248 | """ | 248 | """ |
134 | 249 | log.debug('image_to_byte - start') | 249 | log.debug('image_to_byte - start') |
135 | 250 | byte_array = QtCore.QByteArray() | 250 | byte_array = QtCore.QByteArray() |
136 | 251 | # use buffer to store pixmap into byteArray | 251 | # use buffer to store pixmap into byteArray |
140 | 252 | buffie = QtCore.QBuffer(byte_array) | 252 | buffer = QtCore.QBuffer(byte_array) |
141 | 253 | buffie.open(QtCore.QIODevice.WriteOnly) | 253 | buffer.open(QtCore.QIODevice.WriteOnly) |
142 | 254 | image.save(buffie, "PNG") | 254 | image.save(buffer, "PNG") |
143 | 255 | log.debug('image_to_byte - end') | 255 | log.debug('image_to_byte - end') |
144 | 256 | if not base_64: | 256 | if not base_64: |
145 | 257 | return byte_array | 257 | return byte_array |
146 | @@ -263,15 +263,13 @@ | |||
147 | 263 | """ | 263 | """ |
148 | 264 | Create a thumbnail from the given image path and depending on ``return_icon`` it returns an icon from this thumb. | 264 | Create a thumbnail from the given image path and depending on ``return_icon`` it returns an icon from this thumb. |
149 | 265 | 265 | ||
152 | 266 | :param image_path: The image file to create the icon from. | 266 | :param openlp.core.common.path.Path image_path: The image file to create the icon from. |
153 | 267 | :param thumb_path: The filename to save the thumbnail to. | 267 | :param openlp.core.common.path.Path thumb_path: The filename to save the thumbnail to. |
154 | 268 | :param return_icon: States if an icon should be build and returned from the thumb. Defaults to ``True``. | 268 | :param return_icon: States if an icon should be build and returned from the thumb. Defaults to ``True``. |
155 | 269 | :param size: Allows to state a own size (QtCore.QSize) to use. Defaults to ``None``, which means that a default | 269 | :param size: Allows to state a own size (QtCore.QSize) to use. Defaults to ``None``, which means that a default |
156 | 270 | height of 88 is used. | 270 | height of 88 is used. |
157 | 271 | :return: The final icon. | 271 | :return: The final icon. |
158 | 272 | """ | 272 | """ |
159 | 273 | # TODO: To path object | ||
160 | 274 | thumb_path = Path(thumb_path) | ||
161 | 275 | reader = QtGui.QImageReader(str(image_path)) | 273 | reader = QtGui.QImageReader(str(image_path)) |
162 | 276 | if size is None: | 274 | if size is None: |
163 | 277 | # No size given; use default height of 88 | 275 | # No size given; use default height of 88 |
164 | 278 | 276 | ||
165 | === modified file 'openlp/core/lib/db.py' | |||
166 | --- openlp/core/lib/db.py 2019-02-14 15:09:09 +0000 | |||
167 | +++ openlp/core/lib/db.py 2019-03-17 21:06:27 +0000 | |||
168 | @@ -132,8 +132,9 @@ | |||
169 | 132 | Create a path to a database from the plugin name and database name | 132 | Create a path to a database from the plugin name and database name |
170 | 133 | 133 | ||
171 | 134 | :param plugin_name: Name of plugin | 134 | :param plugin_name: Name of plugin |
174 | 135 | :param db_file_name: File name of database | 135 | :param openlp.core.common.path.Path | str | None db_file_name: File name of database |
175 | 136 | :return: The path to the database as type str | 136 | :return: The path to the database |
176 | 137 | :rtype: str | ||
177 | 137 | """ | 138 | """ |
178 | 138 | if db_file_name is None: | 139 | if db_file_name is None: |
179 | 139 | return 'sqlite:///{path}/{plugin}.sqlite'.format(path=AppLocation.get_section_data_path(plugin_name), | 140 | return 'sqlite:///{path}/{plugin}.sqlite'.format(path=AppLocation.get_section_data_path(plugin_name), |
180 | @@ -144,15 +145,15 @@ | |||
181 | 144 | return 'sqlite:///{path}/{name}'.format(path=AppLocation.get_section_data_path(plugin_name), name=db_file_name) | 145 | return 'sqlite:///{path}/{name}'.format(path=AppLocation.get_section_data_path(plugin_name), name=db_file_name) |
182 | 145 | 146 | ||
183 | 146 | 147 | ||
185 | 147 | def handle_db_error(plugin_name, db_file_name): | 148 | def handle_db_error(plugin_name, db_file_path): |
186 | 148 | """ | 149 | """ |
187 | 149 | Log and report to the user that a database cannot be loaded | 150 | Log and report to the user that a database cannot be loaded |
188 | 150 | 151 | ||
189 | 151 | :param plugin_name: Name of plugin | 152 | :param plugin_name: Name of plugin |
191 | 152 | :param db_file_name: File name of database | 153 | :param openlp.core.common.path.Path db_file_path: File name of database |
192 | 153 | :return: None | 154 | :return: None |
193 | 154 | """ | 155 | """ |
195 | 155 | db_path = get_db_path(plugin_name, db_file_name) | 156 | db_path = get_db_path(plugin_name, db_file_path) |
196 | 156 | log.exception('Error loading database: {db}'.format(db=db_path)) | 157 | log.exception('Error loading database: {db}'.format(db=db_path)) |
197 | 157 | critical_error_message_box(translate('OpenLP.Manager', 'Database Error'), | 158 | critical_error_message_box(translate('OpenLP.Manager', 'Database Error'), |
198 | 158 | translate('OpenLP.Manager', | 159 | translate('OpenLP.Manager', |
199 | @@ -161,10 +162,13 @@ | |||
200 | 161 | 162 | ||
201 | 162 | def init_url(plugin_name, db_file_name=None): | 163 | def init_url(plugin_name, db_file_name=None): |
202 | 163 | """ | 164 | """ |
204 | 164 | Return the database URL. | 165 | Construct the connection string for a database. |
205 | 165 | 166 | ||
206 | 166 | :param plugin_name: The name of the plugin for the database creation. | 167 | :param plugin_name: The name of the plugin for the database creation. |
208 | 167 | :param db_file_name: The database file name. Defaults to None resulting in the plugin_name being used. | 168 | :param openlp.core.common.path.Path | str | None db_file_name: The database file name. Defaults to None resulting |
209 | 169 | in the plugin_name being used. | ||
210 | 170 | :return: The database URL | ||
211 | 171 | :rtype: str | ||
212 | 168 | """ | 172 | """ |
213 | 169 | settings = Settings() | 173 | settings = Settings() |
214 | 170 | settings.beginGroup(plugin_name) | 174 | settings.beginGroup(plugin_name) |
215 | @@ -345,7 +349,7 @@ | |||
216 | 345 | Runs the initialisation process that includes creating the connection to the database and the tables if they do | 349 | Runs the initialisation process that includes creating the connection to the database and the tables if they do |
217 | 346 | not exist. | 350 | not exist. |
218 | 347 | 351 | ||
220 | 348 | :param plugin_name: The name to setup paths and settings section names | 352 | :param plugin_name: The name to setup paths and settings section names |
221 | 349 | :param init_schema: The init_schema function for this database | 353 | :param init_schema: The init_schema function for this database |
222 | 350 | :param openlp.core.common.path.Path db_file_path: The file name to use for this database. Defaults to None | 354 | :param openlp.core.common.path.Path db_file_path: The file name to use for this database. Defaults to None |
223 | 351 | resulting in the plugin_name being used. | 355 | resulting in the plugin_name being used. |
224 | @@ -357,14 +361,14 @@ | |||
225 | 357 | self.db_url = None | 361 | self.db_url = None |
226 | 358 | if db_file_path: | 362 | if db_file_path: |
227 | 359 | log.debug('Manager: Creating new DB url') | 363 | log.debug('Manager: Creating new DB url') |
229 | 360 | self.db_url = init_url(plugin_name, str(db_file_path)) | 364 | self.db_url = init_url(plugin_name, str(db_file_path)) # TOdO :PATHLIB |
230 | 361 | else: | 365 | else: |
231 | 362 | self.db_url = init_url(plugin_name) | 366 | self.db_url = init_url(plugin_name) |
232 | 363 | if upgrade_mod: | 367 | if upgrade_mod: |
233 | 364 | try: | 368 | try: |
234 | 365 | db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod) | 369 | db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod) |
235 | 366 | except (SQLAlchemyError, DBAPIError): | 370 | except (SQLAlchemyError, DBAPIError): |
237 | 367 | handle_db_error(plugin_name, str(db_file_path)) | 371 | handle_db_error(plugin_name, db_file_path) |
238 | 368 | return | 372 | return |
239 | 369 | if db_ver > up_ver: | 373 | if db_ver > up_ver: |
240 | 370 | critical_error_message_box( | 374 | critical_error_message_box( |
241 | @@ -379,7 +383,7 @@ | |||
242 | 379 | try: | 383 | try: |
243 | 380 | self.session = init_schema(self.db_url) | 384 | self.session = init_schema(self.db_url) |
244 | 381 | except (SQLAlchemyError, DBAPIError): | 385 | except (SQLAlchemyError, DBAPIError): |
246 | 382 | handle_db_error(plugin_name, str(db_file_path)) | 386 | handle_db_error(plugin_name, db_file_path) |
247 | 383 | else: | 387 | else: |
248 | 384 | self.session = session | 388 | self.session = session |
249 | 385 | 389 | ||
250 | 386 | 390 | ||
251 | === modified file 'openlp/core/lib/mediamanageritem.py' | |||
252 | --- openlp/core/lib/mediamanageritem.py 2019-02-14 15:09:09 +0000 | |||
253 | +++ openlp/core/lib/mediamanageritem.py 2019-03-17 21:06:27 +0000 | |||
254 | @@ -454,15 +454,16 @@ | |||
255 | 454 | """ | 454 | """ |
256 | 455 | pass | 455 | pass |
257 | 456 | 456 | ||
260 | 457 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 457 | def generate_slide_data(self, service_item, *, item=None, remote=False, context=ServiceItemContext.Live, |
261 | 458 | context=ServiceItemContext.Live): | 458 | file_path=None): |
262 | 459 | """ | 459 | """ |
263 | 460 | Generate the slide data. Needs to be implemented by the plugin. | 460 | Generate the slide data. Needs to be implemented by the plugin. |
264 | 461 | |||
265 | 461 | :param service_item: The service Item to be processed | 462 | :param service_item: The service Item to be processed |
266 | 462 | :param item: The database item to be used to build the service item | 463 | :param item: The database item to be used to build the service item |
267 | 463 | :param xml_version: | ||
268 | 464 | :param remote: Was this remote triggered (False) | 464 | :param remote: Was this remote triggered (False) |
269 | 465 | :param context: The service context | 465 | :param context: The service context |
270 | 466 | :param openlp.core.common.path.Path file_path: | ||
271 | 466 | """ | 467 | """ |
272 | 467 | raise NotImplementedError('MediaManagerItem.generate_slide_data needs to be defined by the plugin') | 468 | raise NotImplementedError('MediaManagerItem.generate_slide_data needs to be defined by the plugin') |
273 | 468 | 469 | ||
274 | @@ -624,17 +625,16 @@ | |||
275 | 624 | 'You must select a {title} ' | 625 | 'You must select a {title} ' |
276 | 625 | 'service item.').format(title=self.title)) | 626 | 'service item.').format(title=self.title)) |
277 | 626 | 627 | ||
279 | 627 | def build_service_item(self, item=None, xml_version=False, remote=False, context=ServiceItemContext.Live): | 628 | def build_service_item(self, item=None, remote=False, context=ServiceItemContext.Live): |
280 | 628 | """ | 629 | """ |
281 | 629 | Common method for generating a service item | 630 | Common method for generating a service item |
282 | 630 | :param item: Service Item to be built. | 631 | :param item: Service Item to be built. |
283 | 631 | :param xml_version: version of XML (False) | ||
284 | 632 | :param remote: Remote triggered (False) | 632 | :param remote: Remote triggered (False) |
285 | 633 | :param context: The context on which this is called | 633 | :param context: The context on which this is called |
286 | 634 | """ | 634 | """ |
287 | 635 | service_item = ServiceItem(self.plugin) | 635 | service_item = ServiceItem(self.plugin) |
288 | 636 | service_item.add_icon() | 636 | service_item.add_icon() |
290 | 637 | if self.generate_slide_data(service_item, item, xml_version, remote, context): | 637 | if self.generate_slide_data(service_item, item=item, remote=remote, context=context): |
291 | 638 | return service_item | 638 | return service_item |
292 | 639 | else: | 639 | else: |
293 | 640 | return None | 640 | return None |
294 | 641 | 641 | ||
295 | === modified file 'openlp/core/lib/serviceitem.py' | |||
296 | --- openlp/core/lib/serviceitem.py 2019-02-14 15:09:09 +0000 | |||
297 | +++ openlp/core/lib/serviceitem.py 2019-03-17 21:06:27 +0000 | |||
298 | @@ -263,7 +263,7 @@ | |||
299 | 263 | file_location = os.path.join(path, file_name) | 263 | file_location = os.path.join(path, file_name) |
300 | 264 | file_location_hash = md5_hash(file_location.encode('utf-8')) | 264 | file_location_hash = md5_hash(file_location.encode('utf-8')) |
301 | 265 | image = os.path.join(str(AppLocation.get_section_data_path(self.name)), 'thumbnails', | 265 | image = os.path.join(str(AppLocation.get_section_data_path(self.name)), 'thumbnails', |
303 | 266 | file_location_hash, ntpath.basename(image)) | 266 | file_location_hash, ntpath.basename(image)) # TODO: Pathlib |
304 | 267 | self.slides.append({'title': file_name, 'image': image, 'path': path, 'display_title': display_title, | 267 | self.slides.append({'title': file_name, 'image': image, 'path': path, 'display_title': display_title, |
305 | 268 | 'notes': notes, 'thumbnail': image}) | 268 | 'notes': notes, 'thumbnail': image}) |
306 | 269 | # if self.is_capable(ItemCapabilities.HasThumbnails): | 269 | # if self.is_capable(ItemCapabilities.HasThumbnails): |
307 | @@ -361,7 +361,7 @@ | |||
308 | 361 | if isinstance(file_path, str): | 361 | if isinstance(file_path, str): |
309 | 362 | # Handle service files prior to OpenLP 3.0 | 362 | # Handle service files prior to OpenLP 3.0 |
310 | 363 | # Windows can handle both forward and backward slashes, so we use ntpath to get the basename | 363 | # Windows can handle both forward and backward slashes, so we use ntpath to get the basename |
312 | 364 | file_path = Path(path, ntpath.basename(file_path)) | 364 | file_path = path / ntpath.basename(file_path) |
313 | 365 | self.background_audio.append(file_path) | 365 | self.background_audio.append(file_path) |
314 | 366 | self.theme_overwritten = header.get('theme_overwritten', False) | 366 | self.theme_overwritten = header.get('theme_overwritten', False) |
315 | 367 | if self.service_item_type == ServiceItemType.Text: | 367 | if self.service_item_type == ServiceItemType.Text: |
316 | @@ -374,7 +374,7 @@ | |||
317 | 374 | if path: | 374 | if path: |
318 | 375 | self.has_original_files = False | 375 | self.has_original_files = False |
319 | 376 | for text_image in service_item['serviceitem']['data']: | 376 | for text_image in service_item['serviceitem']['data']: |
321 | 377 | file_path = os.path.join(path, text_image) | 377 | file_path = path / text_image |
322 | 378 | self.add_from_image(file_path, text_image, background) | 378 | self.add_from_image(file_path, text_image, background) |
323 | 379 | else: | 379 | else: |
324 | 380 | for text_image in service_item['serviceitem']['data']: | 380 | for text_image in service_item['serviceitem']['data']: |
325 | 381 | 381 | ||
326 | === modified file 'openlp/core/ui/advancedtab.py' | |||
327 | --- openlp/core/ui/advancedtab.py 2019-03-09 03:53:20 +0000 | |||
328 | +++ openlp/core/ui/advancedtab.py 2019-03-17 21:06:27 +0000 | |||
329 | @@ -478,7 +478,7 @@ | |||
330 | 478 | minute=self.service_name_time.time().minute() | 478 | minute=self.service_name_time.time().minute() |
331 | 479 | ) | 479 | ) |
332 | 480 | try: | 480 | try: |
334 | 481 | service_name_example = format_time(str(self.service_name_edit.text()), local_time) | 481 | service_name_example = format_time(self.service_name_edit.text(), local_time) |
335 | 482 | except ValueError: | 482 | except ValueError: |
336 | 483 | preset_is_valid = False | 483 | preset_is_valid = False |
337 | 484 | service_name_example = translate('OpenLP.AdvancedTab', 'Syntax error.') | 484 | service_name_example = translate('OpenLP.AdvancedTab', 'Syntax error.') |
338 | 485 | 485 | ||
339 | === modified file 'openlp/core/ui/exceptiondialog.py' | |||
340 | --- openlp/core/ui/exceptiondialog.py 2019-02-14 15:09:09 +0000 | |||
341 | +++ openlp/core/ui/exceptiondialog.py 2019-03-17 21:06:27 +0000 | |||
342 | @@ -77,11 +77,11 @@ | |||
343 | 77 | self.save_report_button = create_button(exception_dialog, 'save_report_button', | 77 | self.save_report_button = create_button(exception_dialog, 'save_report_button', |
344 | 78 | icon=UiIcons().save, | 78 | icon=UiIcons().save, |
345 | 79 | click=self.on_save_report_button_clicked) | 79 | click=self.on_save_report_button_clicked) |
347 | 80 | self.attach_tile_button = create_button(exception_dialog, 'attach_tile_button', | 80 | self.attach_file_button = create_button(exception_dialog, 'attach_file_button', |
348 | 81 | icon=UiIcons().open, | 81 | icon=UiIcons().open, |
349 | 82 | click=self.on_attach_file_button_clicked) | 82 | click=self.on_attach_file_button_clicked) |
350 | 83 | self.button_box = create_button_box(exception_dialog, 'button_box', ['close'], | 83 | self.button_box = create_button_box(exception_dialog, 'button_box', ['close'], |
352 | 84 | [self.send_report_button, self.save_report_button, self.attach_tile_button]) | 84 | [self.send_report_button, self.save_report_button, self.attach_file_button]) |
353 | 85 | self.exception_layout.addWidget(self.button_box) | 85 | self.exception_layout.addWidget(self.button_box) |
354 | 86 | 86 | ||
355 | 87 | self.retranslate_ui(exception_dialog) | 87 | self.retranslate_ui(exception_dialog) |
356 | @@ -112,4 +112,4 @@ | |||
357 | 112 | ).format(first_part=exception_part1)) | 112 | ).format(first_part=exception_part1)) |
358 | 113 | self.send_report_button.setText(translate('OpenLP.ExceptionDialog', 'Send E-Mail')) | 113 | self.send_report_button.setText(translate('OpenLP.ExceptionDialog', 'Send E-Mail')) |
359 | 114 | self.save_report_button.setText(translate('OpenLP.ExceptionDialog', 'Save to File')) | 114 | self.save_report_button.setText(translate('OpenLP.ExceptionDialog', 'Save to File')) |
361 | 115 | self.attach_tile_button.setText(translate('OpenLP.ExceptionDialog', 'Attach File')) | 115 | self.attach_file_button.setText(translate('OpenLP.ExceptionDialog', 'Attach File')) |
362 | 116 | 116 | ||
363 | === modified file 'openlp/core/ui/exceptionform.py' | |||
364 | --- openlp/core/ui/exceptionform.py 2019-02-14 15:09:09 +0000 | |||
365 | +++ openlp/core/ui/exceptionform.py 2019-03-17 21:06:27 +0000 | |||
366 | @@ -95,12 +95,14 @@ | |||
367 | 95 | """ | 95 | """ |
368 | 96 | Saving exception log and system information to a file. | 96 | Saving exception log and system information to a file. |
369 | 97 | """ | 97 | """ |
376 | 98 | file_path, filter_used = FileDialog.getSaveFileName( | 98 | while True: |
377 | 99 | self, | 99 | file_path, filter_used = FileDialog.getSaveFileName( |
378 | 100 | translate('OpenLP.ExceptionForm', 'Save Crash Report'), | 100 | self, |
379 | 101 | Settings().value(self.settings_section + '/last directory'), | 101 | translate('OpenLP.ExceptionForm', 'Save Crash Report'), |
380 | 102 | translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)')) | 102 | Settings().value(self.settings_section + '/last directory'), |
381 | 103 | if file_path: | 103 | translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)')) |
382 | 104 | if file_path is None: | ||
383 | 105 | break | ||
384 | 104 | Settings().setValue(self.settings_section + '/last directory', file_path.parent) | 106 | Settings().setValue(self.settings_section + '/last directory', file_path.parent) |
385 | 105 | opts = self._create_report() | 107 | opts = self._create_report() |
386 | 106 | report_text = self.report_text.format(version=opts['version'], description=opts['description'], | 108 | report_text = self.report_text.format(version=opts['version'], description=opts['description'], |
387 | @@ -108,8 +110,13 @@ | |||
388 | 108 | try: | 110 | try: |
389 | 109 | with file_path.open('w') as report_file: | 111 | with file_path.open('w') as report_file: |
390 | 110 | report_file.write(report_text) | 112 | report_file.write(report_text) |
392 | 111 | except OSError: | 113 | break |
393 | 114 | except OSError as e: | ||
394 | 112 | log.exception('Failed to write crash report') | 115 | log.exception('Failed to write crash report') |
395 | 116 | QtWidgets.QMessageBox.warning( | ||
396 | 117 | self, translate('OpenLP.ExceptionDialog', 'Failed to Save Report'), | ||
397 | 118 | translate('OpenLP.ExceptionDialog', 'The following error occured when saving the report.\n\n' | ||
398 | 119 | '{exception}').format(file_name=file_path, exception=e)) | ||
399 | 113 | 120 | ||
400 | 114 | def on_send_report_button_clicked(self): | 121 | def on_send_report_button_clicked(self): |
401 | 115 | """ | 122 | """ |
402 | 116 | 123 | ||
403 | === modified file 'openlp/core/ui/generaltab.py' | |||
404 | --- openlp/core/ui/generaltab.py 2019-02-14 15:09:09 +0000 | |||
405 | +++ openlp/core/ui/generaltab.py 2019-03-17 21:06:27 +0000 | |||
406 | @@ -47,7 +47,6 @@ | |||
407 | 47 | """ | 47 | """ |
408 | 48 | Initialise the general settings tab | 48 | Initialise the general settings tab |
409 | 49 | """ | 49 | """ |
410 | 50 | self.logo_file = ':/graphics/openlp-splash-screen.png' | ||
411 | 51 | self.logo_background_color = '#ffffff' | 50 | self.logo_background_color = '#ffffff' |
412 | 52 | self.screens = ScreenList() | 51 | self.screens = ScreenList() |
413 | 53 | self.icon_path = ':/icon/openlp-logo.svg' | 52 | self.icon_path = ':/icon/openlp-logo.svg' |
414 | 54 | 53 | ||
415 | === modified file 'openlp/core/ui/mainwindow.py' | |||
416 | --- openlp/core/ui/mainwindow.py 2019-02-14 15:09:09 +0000 | |||
417 | +++ openlp/core/ui/mainwindow.py 2019-03-17 21:06:27 +0000 | |||
418 | @@ -1334,7 +1334,7 @@ | |||
419 | 1334 | self.show_status_message( | 1334 | self.show_status_message( |
420 | 1335 | translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - {path} ' | 1335 | translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - {path} ' |
421 | 1336 | '- Please wait for copy to finish').format(path=self.new_data_path)) | 1336 | '- Please wait for copy to finish').format(path=self.new_data_path)) |
423 | 1337 | dir_util.copy_tree(str(old_data_path), str(self.new_data_path)) | 1337 | dir_util.copy_tree(old_data_path, self.new_data_path) |
424 | 1338 | self.log_info('Copy successful') | 1338 | self.log_info('Copy successful') |
425 | 1339 | except (OSError, DistutilsFileError) as why: | 1339 | except (OSError, DistutilsFileError) as why: |
426 | 1340 | self.application.set_normal_cursor() | 1340 | self.application.set_normal_cursor() |
427 | 1341 | 1341 | ||
428 | === modified file 'openlp/core/ui/servicemanager.py' | |||
429 | --- openlp/core/ui/servicemanager.py 2019-02-14 15:09:09 +0000 | |||
430 | +++ openlp/core/ui/servicemanager.py 2019-03-17 21:06:27 +0000 | |||
431 | @@ -25,7 +25,6 @@ | |||
432 | 25 | import html | 25 | import html |
433 | 26 | import json | 26 | import json |
434 | 27 | import os | 27 | import os |
435 | 28 | import shutil | ||
436 | 29 | import zipfile | 28 | import zipfile |
437 | 30 | from contextlib import suppress | 29 | from contextlib import suppress |
438 | 31 | from datetime import datetime, timedelta | 30 | from datetime import datetime, timedelta |
439 | @@ -234,7 +233,7 @@ | |||
440 | 234 | self.service_manager_list.itemExpanded.connect(self.expanded) | 233 | self.service_manager_list.itemExpanded.connect(self.expanded) |
441 | 235 | # Last little bits of setting up | 234 | # Last little bits of setting up |
442 | 236 | self.service_theme = Settings().value(self.main_window.service_manager_settings_section + '/service theme') | 235 | self.service_theme = Settings().value(self.main_window.service_manager_settings_section + '/service theme') |
444 | 237 | self.service_path = str(AppLocation.get_section_data_path('servicemanager')) | 236 | self.service_path = AppLocation.get_section_data_path('servicemanager') |
445 | 238 | # build the drag and drop context menu | 237 | # build the drag and drop context menu |
446 | 239 | self.dnd_menu = QtWidgets.QMenu() | 238 | self.dnd_menu = QtWidgets.QMenu() |
447 | 240 | self.new_action = self.dnd_menu.addAction(translate('OpenLP.ServiceManager', '&Add New Item')) | 239 | self.new_action = self.dnd_menu.addAction(translate('OpenLP.ServiceManager', '&Add New Item')) |
448 | @@ -590,11 +589,11 @@ | |||
449 | 590 | self.main_window.increment_progress_bar(service_content_size) | 589 | self.main_window.increment_progress_bar(service_content_size) |
450 | 591 | # Finally add all the listed media files. | 590 | # Finally add all the listed media files. |
451 | 592 | for write_path in write_list: | 591 | for write_path in write_list: |
453 | 593 | zip_file.write(str(write_path), str(write_path)) | 592 | zip_file.write(write_path, write_path) |
454 | 594 | self.main_window.increment_progress_bar(write_path.stat().st_size) | 593 | self.main_window.increment_progress_bar(write_path.stat().st_size) |
455 | 595 | with suppress(FileNotFoundError): | 594 | with suppress(FileNotFoundError): |
456 | 596 | file_path.unlink() | 595 | file_path.unlink() |
458 | 597 | os.link(temp_file.name, str(file_path)) | 596 | os.link(temp_file.name, file_path) |
459 | 598 | Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent) | 597 | Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent) |
460 | 599 | except (PermissionError, OSError) as error: | 598 | except (PermissionError, OSError) as error: |
461 | 600 | self.log_exception('Failed to save service to disk: {name}'.format(name=file_path)) | 599 | self.log_exception('Failed to save service to disk: {name}'.format(name=file_path)) |
462 | @@ -679,7 +678,7 @@ | |||
463 | 679 | service_data = None | 678 | service_data = None |
464 | 680 | self.application.set_busy_cursor() | 679 | self.application.set_busy_cursor() |
465 | 681 | try: | 680 | try: |
467 | 682 | with zipfile.ZipFile(str(file_path)) as zip_file: | 681 | with zipfile.ZipFile(file_path) as zip_file: |
468 | 683 | compressed_size = 0 | 682 | compressed_size = 0 |
469 | 684 | for zip_info in zip_file.infolist(): | 683 | for zip_info in zip_file.infolist(): |
470 | 685 | compressed_size += zip_info.compress_size | 684 | compressed_size += zip_info.compress_size |
471 | @@ -692,7 +691,7 @@ | |||
472 | 692 | service_data = json_file.read() | 691 | service_data = json_file.read() |
473 | 693 | else: | 692 | else: |
474 | 694 | zip_info.filename = os.path.basename(zip_info.filename) | 693 | zip_info.filename = os.path.basename(zip_info.filename) |
476 | 695 | zip_file.extract(zip_info, str(self.service_path)) | 694 | zip_file.extract(zip_info, self.service_path) |
477 | 696 | self.main_window.increment_progress_bar(zip_info.compress_size) | 695 | self.main_window.increment_progress_bar(zip_info.compress_size) |
478 | 697 | if service_data: | 696 | if service_data: |
479 | 698 | items = json.loads(service_data, cls=OpenLPJsonDecoder) | 697 | items = json.loads(service_data, cls=OpenLPJsonDecoder) |
480 | @@ -705,11 +704,13 @@ | |||
481 | 705 | else: | 704 | else: |
482 | 706 | raise ValidationError(msg='No service data found') | 705 | raise ValidationError(msg='No service data found') |
483 | 707 | except (NameError, OSError, ValidationError, zipfile.BadZipFile): | 706 | except (NameError, OSError, ValidationError, zipfile.BadZipFile): |
484 | 707 | self.application.set_normal_cursor() | ||
485 | 708 | self.log_exception('Problem loading service file {name}'.format(name=file_path)) | 708 | self.log_exception('Problem loading service file {name}'.format(name=file_path)) |
486 | 709 | critical_error_message_box( | 709 | critical_error_message_box( |
487 | 710 | message=translate('OpenLP.ServiceManager', | 710 | message=translate('OpenLP.ServiceManager', |
490 | 711 | 'The service file {file_path} could not be loaded because it is either corrupt, or ' | 711 | 'The service file {file_path} could not be loaded because it is either corrupt, ' |
491 | 712 | 'not a valid OpenLP 2 or OpenLP 3 service file.'.format(file_path=file_path))) | 712 | 'inaccessible, or not a valid OpenLP 2 or OpenLP 3 service file.' |
492 | 713 | ).format(file_path=file_path)) | ||
493 | 713 | self.main_window.finished_progress_bar() | 714 | self.main_window.finished_progress_bar() |
494 | 714 | self.application.set_normal_cursor() | 715 | self.application.set_normal_cursor() |
495 | 715 | self.repaint_service_list(-1, -1) | 716 | self.repaint_service_list(-1, -1) |
496 | @@ -1237,11 +1238,11 @@ | |||
497 | 1237 | """ | 1238 | """ |
498 | 1238 | Empties the service_path of temporary files on system exit. | 1239 | Empties the service_path of temporary files on system exit. |
499 | 1239 | """ | 1240 | """ |
502 | 1240 | for file_name in os.listdir(self.service_path): | 1241 | for file_path in self.service_path.iterdir(): |
501 | 1241 | file_path = Path(self.service_path, file_name) | ||
503 | 1242 | delete_file(file_path) | 1242 | delete_file(file_path) |
506 | 1243 | if os.path.exists(os.path.join(self.service_path, 'audio')): | 1243 | audio_path = self.service_path / 'audio' |
507 | 1244 | shutil.rmtree(os.path.join(self.service_path, 'audio'), True) | 1244 | if audio_path.exists(): |
508 | 1245 | audio_path.rmtree(True) | ||
509 | 1245 | 1246 | ||
510 | 1246 | def on_theme_combo_box_selected(self, current_index): | 1247 | def on_theme_combo_box_selected(self, current_index): |
511 | 1247 | """ | 1248 | """ |
512 | 1248 | 1249 | ||
513 | === modified file 'openlp/core/ui/thememanager.py' | |||
514 | --- openlp/core/ui/thememanager.py 2019-02-14 15:09:09 +0000 | |||
515 | +++ openlp/core/ui/thememanager.py 2019-03-17 21:06:27 +0000 | |||
516 | @@ -150,7 +150,7 @@ | |||
517 | 150 | self.global_theme = Settings().value(self.settings_section + '/global theme') | 150 | self.global_theme = Settings().value(self.settings_section + '/global theme') |
518 | 151 | self.build_theme_path() | 151 | self.build_theme_path() |
519 | 152 | self.load_first_time_themes() | 152 | self.load_first_time_themes() |
521 | 153 | self.upgrade_themes() | 153 | self.upgrade_themes() # TODO: Can be removed when upgrade path from OpenLP 2.4 no longer needed |
522 | 154 | 154 | ||
523 | 155 | def bootstrap_post_set_up(self): | 155 | def bootstrap_post_set_up(self): |
524 | 156 | """ | 156 | """ |
525 | @@ -422,10 +422,10 @@ | |||
526 | 422 | :rtype: bool | 422 | :rtype: bool |
527 | 423 | """ | 423 | """ |
528 | 424 | try: | 424 | try: |
530 | 425 | with zipfile.ZipFile(str(theme_path), 'w') as theme_zip: | 425 | with zipfile.ZipFile(theme_path, 'w') as theme_zip: |
531 | 426 | source_path = self.theme_path / theme_name | 426 | source_path = self.theme_path / theme_name |
532 | 427 | for file_path in source_path.iterdir(): | 427 | for file_path in source_path.iterdir(): |
534 | 428 | theme_zip.write(str(file_path), os.path.join(theme_name, file_path.name)) | 428 | theme_zip.write(file_path, Path(theme_name, file_path.name)) |
535 | 429 | return True | 429 | return True |
536 | 430 | except OSError as ose: | 430 | except OSError as ose: |
537 | 431 | self.log_exception('Export Theme Failed') | 431 | self.log_exception('Export Theme Failed') |
538 | @@ -567,10 +567,10 @@ | |||
539 | 567 | json_theme = False | 567 | json_theme = False |
540 | 568 | theme_name = "" | 568 | theme_name = "" |
541 | 569 | try: | 569 | try: |
543 | 570 | with zipfile.ZipFile(str(file_path)) as theme_zip: | 570 | with zipfile.ZipFile(file_path) as theme_zip: |
544 | 571 | json_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.json'] | 571 | json_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.json'] |
545 | 572 | if len(json_file) != 1: | 572 | if len(json_file) != 1: |
547 | 573 | # TODO: remove XML handling after the 2.6 release. | 573 | # TODO: remove XML handling after once the upgrade path from 2.4 is no longer required |
548 | 574 | xml_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.xml'] | 574 | xml_file = [name for name in theme_zip.namelist() if os.path.splitext(name)[1].lower() == '.xml'] |
549 | 575 | if len(xml_file) != 1: | 575 | if len(xml_file) != 1: |
550 | 576 | self.log_error('Theme contains "{val:d}" theme files'.format(val=len(xml_file))) | 576 | self.log_error('Theme contains "{val:d}" theme files'.format(val=len(xml_file))) |
551 | @@ -607,12 +607,12 @@ | |||
552 | 607 | else: | 607 | else: |
553 | 608 | with full_name.open('wb') as out_file: | 608 | with full_name.open('wb') as out_file: |
554 | 609 | out_file.write(theme_zip.read(zipped_file)) | 609 | out_file.write(theme_zip.read(zipped_file)) |
556 | 610 | except (OSError, zipfile.BadZipFile): | 610 | except (OSError, ValidationError, zipfile.BadZipFile): |
557 | 611 | self.log_exception('Importing theme from zip failed {name}'.format(name=file_path)) | 611 | self.log_exception('Importing theme from zip failed {name}'.format(name=file_path)) |
562 | 612 | raise ValidationError | 612 | critical_error_message_box( |
563 | 613 | except ValidationError: | 613 | translate('OpenLP.ThemeManager', 'Import Error'), |
564 | 614 | critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'), | 614 | translate('OpenLP.ThemeManager', 'There was a problem imoorting {file_name}.\n\nIt is corrupt,' |
565 | 615 | translate('OpenLP.ThemeManager', 'File is not a valid theme.')) | 615 | 'inaccessible or not a valid theme.').format(file_name=file_path)) |
566 | 616 | finally: | 616 | finally: |
567 | 617 | if not abort_import: | 617 | if not abort_import: |
568 | 618 | # As all files are closed, we can create the Theme. | 618 | # As all files are closed, we can create the Theme. |
569 | 619 | 619 | ||
570 | === modified file 'openlp/core/version.py' | |||
571 | --- openlp/core/version.py 2019-02-14 15:09:09 +0000 | |||
572 | +++ openlp/core/version.py 2019-03-17 21:06:27 +0000 | |||
573 | @@ -200,7 +200,7 @@ | |||
574 | 200 | """ | 200 | """ |
575 | 201 | library_versions = OrderedDict([(library, _get_lib_version(*args)) for library, args in LIBRARIES.items()]) | 201 | library_versions = OrderedDict([(library, _get_lib_version(*args)) for library, args in LIBRARIES.items()]) |
576 | 202 | # Just update the dict for display purposes, changing the None to a '-' | 202 | # Just update the dict for display purposes, changing the None to a '-' |
578 | 203 | for library, version in library_versions: | 203 | for library, version in library_versions.items(): |
579 | 204 | if version is None: | 204 | if version is None: |
580 | 205 | library_versions[library] = '-' | 205 | library_versions[library] = '-' |
581 | 206 | return library_versions | 206 | return library_versions |
582 | 207 | 207 | ||
583 | === modified file 'openlp/core/widgets/edits.py' | |||
584 | --- openlp/core/widgets/edits.py 2019-02-14 15:09:09 +0000 | |||
585 | +++ openlp/core/widgets/edits.py 2019-03-17 21:06:27 +0000 | |||
586 | @@ -352,7 +352,7 @@ | |||
587 | 352 | :rtype: None | 352 | :rtype: None |
588 | 353 | """ | 353 | """ |
589 | 354 | if self._path != path: | 354 | if self._path != path: |
591 | 355 | self._path = path | 355 | self.path = path |
592 | 356 | self.pathChanged.emit(path) | 356 | self.pathChanged.emit(path) |
593 | 357 | 357 | ||
594 | 358 | 358 | ||
595 | 359 | 359 | ||
596 | === modified file 'openlp/core/widgets/wizard.py' | |||
597 | --- openlp/core/widgets/wizard.py 2019-02-14 15:09:09 +0000 | |||
598 | +++ openlp/core/widgets/wizard.py 2019-03-17 21:06:27 +0000 | |||
599 | @@ -27,13 +27,11 @@ | |||
600 | 27 | from PyQt5 import QtCore, QtGui, QtWidgets | 27 | from PyQt5 import QtCore, QtGui, QtWidgets |
601 | 28 | 28 | ||
602 | 29 | from openlp.core.common import is_macosx | 29 | from openlp.core.common import is_macosx |
604 | 30 | from openlp.core.common.i18n import UiStrings, translate | 30 | from openlp.core.common.i18n import translate |
605 | 31 | from openlp.core.common.mixins import RegistryProperties | 31 | from openlp.core.common.mixins import RegistryProperties |
606 | 32 | from openlp.core.common.registry import Registry | 32 | from openlp.core.common.registry import Registry |
607 | 33 | from openlp.core.common.settings import Settings | ||
608 | 34 | from openlp.core.lib.ui import add_welcome_page | 33 | from openlp.core.lib.ui import add_welcome_page |
609 | 35 | from openlp.core.ui.icons import UiIcons | 34 | from openlp.core.ui.icons import UiIcons |
610 | 36 | from openlp.core.widgets.dialogs import FileDialog | ||
611 | 37 | 35 | ||
612 | 38 | 36 | ||
613 | 39 | log = logging.getLogger(__name__) | 37 | log = logging.getLogger(__name__) |
614 | @@ -280,41 +278,3 @@ | |||
615 | 280 | self.finish_button.setVisible(True) | 278 | self.finish_button.setVisible(True) |
616 | 281 | self.cancel_button.setVisible(False) | 279 | self.cancel_button.setVisible(False) |
617 | 282 | self.application.process_events() | 280 | self.application.process_events() |
618 | 283 | |||
619 | 284 | def get_file_name(self, title, editbox, setting_name, filters=''): | ||
620 | 285 | """ | ||
621 | 286 | Opens a FileDialog and saves the filename to the given editbox. | ||
622 | 287 | |||
623 | 288 | :param str title: The title of the dialog. | ||
624 | 289 | :param QtWidgets.QLineEdit editbox: An QLineEdit. | ||
625 | 290 | :param str setting_name: The place where to save the last opened directory. | ||
626 | 291 | :param str filters: The file extension filters. It should contain the file description | ||
627 | 292 | as well as the file extension. For example:: | ||
628 | 293 | |||
629 | 294 | 'OpenLP 2 Databases (*.sqlite)' | ||
630 | 295 | :rtype: None | ||
631 | 296 | """ | ||
632 | 297 | if filters: | ||
633 | 298 | filters += ';;' | ||
634 | 299 | filters += '%s (*)' % UiStrings().AllFiles | ||
635 | 300 | file_path, filter_used = FileDialog.getOpenFileName( | ||
636 | 301 | self, title, Settings().value(self.plugin.settings_section + '/' + setting_name), filters) | ||
637 | 302 | if file_path: | ||
638 | 303 | editbox.setText(str(file_path)) | ||
639 | 304 | Settings().setValue(self.plugin.settings_section + '/' + setting_name, file_path.parent) | ||
640 | 305 | |||
641 | 306 | def get_folder(self, title, editbox, setting_name): | ||
642 | 307 | """ | ||
643 | 308 | Opens a FileDialog and saves the selected folder to the given editbox. | ||
644 | 309 | |||
645 | 310 | :param str title: The title of the dialog. | ||
646 | 311 | :param QtWidgets.QLineEdit editbox: An QLineEditbox. | ||
647 | 312 | :param str setting_name: The place where to save the last opened directory. | ||
648 | 313 | :rtype: None | ||
649 | 314 | """ | ||
650 | 315 | folder_path = FileDialog.getExistingDirectory( | ||
651 | 316 | self, title, Settings().value(self.plugin.settings_section + '/' + setting_name), | ||
652 | 317 | FileDialog.ShowDirsOnly) | ||
653 | 318 | if folder_path: | ||
654 | 319 | editbox.setText(str(folder_path)) | ||
655 | 320 | Settings().setValue(self.plugin.settings_section + '/' + setting_name, folder_path) | ||
656 | 321 | 281 | ||
657 | === modified file 'openlp/plugins/bibles/forms/bibleimportform.py' | |||
658 | --- openlp/plugins/bibles/forms/bibleimportform.py 2019-02-14 15:09:09 +0000 | |||
659 | +++ openlp/plugins/bibles/forms/bibleimportform.py 2019-03-17 21:06:27 +0000 | |||
660 | @@ -463,14 +463,14 @@ | |||
661 | 463 | UiStrings().NFSs, translate('BiblesPlugin.ImportWizardForm', | 463 | UiStrings().NFSs, translate('BiblesPlugin.ImportWizardForm', |
662 | 464 | 'You need to specify a file with books of the Bible to use in the ' | 464 | 'You need to specify a file with books of the Bible to use in the ' |
663 | 465 | 'import.')) | 465 | 'import.')) |
665 | 466 | self.csv_books_edit.setFocus() | 466 | self.csv_books_path_edit.setFocus() |
666 | 467 | return False | 467 | return False |
667 | 468 | elif not self.field('csv_versefile'): | 468 | elif not self.field('csv_versefile'): |
668 | 469 | critical_error_message_box( | 469 | critical_error_message_box( |
669 | 470 | UiStrings().NFSs, | 470 | UiStrings().NFSs, |
670 | 471 | translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file of Bible verses to ' | 471 | translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file of Bible verses to ' |
671 | 472 | 'import.')) | 472 | 'import.')) |
673 | 473 | self.csv_verses_edit.setFocus() | 473 | self.csv_verses_pathedit.setFocus() |
674 | 474 | return False | 474 | return False |
675 | 475 | elif self.field('source_format') == BibleFormat.OpenSong: | 475 | elif self.field('source_format') == BibleFormat.OpenSong: |
676 | 476 | if not self.field('opensong_file'): | 476 | if not self.field('opensong_file'): |
677 | 477 | 477 | ||
678 | === modified file 'openlp/plugins/bibles/lib/bibleimport.py' | |||
679 | --- openlp/plugins/bibles/lib/bibleimport.py 2019-02-14 15:09:09 +0000 | |||
680 | +++ openlp/plugins/bibles/lib/bibleimport.py 2019-03-17 21:06:27 +0000 | |||
681 | @@ -48,9 +48,9 @@ | |||
682 | 48 | """ | 48 | """ |
683 | 49 | Check if the supplied file is compressed | 49 | Check if the supplied file is compressed |
684 | 50 | 50 | ||
686 | 51 | :param file_path: A path to the file to check | 51 | :param openlp.core.common.path.Path file_path: A path to the file to check |
687 | 52 | """ | 52 | """ |
689 | 53 | if is_zipfile(str(file_path)): | 53 | if is_zipfile(file_path): |
690 | 54 | critical_error_message_box( | 54 | critical_error_message_box( |
691 | 55 | message=translate('BiblesPlugin.BibleImport', | 55 | message=translate('BiblesPlugin.BibleImport', |
692 | 56 | 'The file "{file}" you supplied is compressed. You must decompress it before import.' | 56 | 'The file "{file}" you supplied is compressed. You must decompress it before import.' |
693 | 57 | 57 | ||
694 | === modified file 'openlp/plugins/bibles/lib/db.py' | |||
695 | --- openlp/plugins/bibles/lib/db.py 2019-02-14 15:09:09 +0000 | |||
696 | +++ openlp/plugins/bibles/lib/db.py 2019-03-17 21:06:27 +0000 | |||
697 | @@ -158,11 +158,10 @@ | |||
698 | 158 | self.name = kwargs['name'] | 158 | self.name = kwargs['name'] |
699 | 159 | if not isinstance(self.name, str): | 159 | if not isinstance(self.name, str): |
700 | 160 | self.name = str(self.name, 'utf-8') | 160 | self.name = str(self.name, 'utf-8') |
703 | 161 | # TODO: To path object | 161 | self.file_path = Path(clean_filename(self.name) + '.sqlite') |
702 | 162 | file_path = Path(clean_filename(self.name) + '.sqlite') | ||
704 | 163 | if 'file' in kwargs: | 162 | if 'file' in kwargs: |
707 | 164 | file_path = kwargs['file'] | 163 | self.file_path = kwargs['file'] |
708 | 165 | Manager.__init__(self, 'bibles', init_schema, file_path, upgrade) | 164 | Manager.__init__(self, 'bibles', init_schema, self.file_path, upgrade) |
709 | 166 | if self.session and 'file' in kwargs: | 165 | if self.session and 'file' in kwargs: |
710 | 167 | self.get_name() | 166 | self.get_name() |
711 | 168 | self._is_web_bible = None | 167 | self._is_web_bible = None |
712 | @@ -750,7 +749,7 @@ | |||
713 | 750 | ] | 749 | ] |
714 | 751 | 750 | ||
715 | 752 | 751 | ||
717 | 753 | class AlternativeBookNamesDB(QtCore.QObject, Manager): | 752 | class AlternativeBookNamesDB(Manager): |
718 | 754 | """ | 753 | """ |
719 | 755 | This class represents a database-bound alternative book names system. | 754 | This class represents a database-bound alternative book names system. |
720 | 756 | """ | 755 | """ |
721 | @@ -765,8 +764,9 @@ | |||
722 | 765 | """ | 764 | """ |
723 | 766 | if AlternativeBookNamesDB.cursor is None: | 765 | if AlternativeBookNamesDB.cursor is None: |
724 | 767 | file_path = AppLocation.get_directory(AppLocation.DataDir) / 'bibles' / 'alternative_book_names.sqlite' | 766 | file_path = AppLocation.get_directory(AppLocation.DataDir) / 'bibles' / 'alternative_book_names.sqlite' |
725 | 767 | exists = file_path.exists() | ||
726 | 768 | AlternativeBookNamesDB.conn = sqlite3.connect(str(file_path)) | 768 | AlternativeBookNamesDB.conn = sqlite3.connect(str(file_path)) |
728 | 769 | if not file_path.exists(): | 769 | if not exists: |
729 | 770 | # create new DB, create table alternative_book_names | 770 | # create new DB, create table alternative_book_names |
730 | 771 | AlternativeBookNamesDB.conn.execute( | 771 | AlternativeBookNamesDB.conn.execute( |
731 | 772 | 'CREATE TABLE alternative_book_names(id INTEGER NOT NULL, ' | 772 | 'CREATE TABLE alternative_book_names(id INTEGER NOT NULL, ' |
732 | 773 | 773 | ||
733 | === modified file 'openlp/plugins/bibles/lib/importers/wordproject.py' | |||
734 | --- openlp/plugins/bibles/lib/importers/wordproject.py 2019-02-14 15:09:09 +0000 | |||
735 | +++ openlp/plugins/bibles/lib/importers/wordproject.py 2019-03-17 21:06:27 +0000 | |||
736 | @@ -51,7 +51,7 @@ | |||
737 | 51 | Unzip the file to a temporary directory | 51 | Unzip the file to a temporary directory |
738 | 52 | """ | 52 | """ |
739 | 53 | self.tmp = TemporaryDirectory() | 53 | self.tmp = TemporaryDirectory() |
741 | 54 | with ZipFile(str(self.file_path)) as zip_file: | 54 | with ZipFile(self.file_path) as zip_file: |
742 | 55 | zip_file.extractall(self.tmp.name) | 55 | zip_file.extractall(self.tmp.name) |
743 | 56 | self.base_path = Path(self.tmp.name, self.file_path.stem) | 56 | self.base_path = Path(self.tmp.name, self.file_path.stem) |
744 | 57 | 57 | ||
745 | 58 | 58 | ||
746 | === modified file 'openlp/plugins/bibles/lib/manager.py' | |||
747 | --- openlp/plugins/bibles/lib/manager.py 2019-02-14 15:09:09 +0000 | |||
748 | +++ openlp/plugins/bibles/lib/manager.py 2019-03-17 21:06:27 +0000 | |||
749 | @@ -187,7 +187,7 @@ | |||
750 | 187 | bible = self.db_cache[name] | 187 | bible = self.db_cache[name] |
751 | 188 | bible.session.close_all() | 188 | bible.session.close_all() |
752 | 189 | bible.session = None | 189 | bible.session = None |
754 | 190 | return delete_file(Path(bible.path, bible.file)) | 190 | return delete_file(bible.path, bible.file_path) |
755 | 191 | 191 | ||
756 | 192 | def get_bibles(self): | 192 | def get_bibles(self): |
757 | 193 | """ | 193 | """ |
758 | 194 | 194 | ||
759 | === modified file 'openlp/plugins/bibles/lib/mediaitem.py' | |||
760 | --- openlp/plugins/bibles/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
761 | +++ openlp/plugins/bibles/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
762 | @@ -911,16 +911,16 @@ | |||
763 | 911 | list_widget_items.append(bible_verse) | 911 | list_widget_items.append(bible_verse) |
764 | 912 | return list_widget_items | 912 | return list_widget_items |
765 | 913 | 913 | ||
768 | 914 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 914 | def generate_slide_data(self, service_item, *, item=None, remote=False, context=ServiceItemContext.Service, |
769 | 915 | context=ServiceItemContext.Service): | 915 | **kwargs): |
770 | 916 | """ | 916 | """ |
771 | 917 | Generate the slide data. Needs to be implemented by the plugin. | 917 | Generate the slide data. Needs to be implemented by the plugin. |
772 | 918 | 918 | ||
773 | 919 | :param service_item: The service item to be built on | 919 | :param service_item: The service item to be built on |
774 | 920 | :param item: The Song item to be used | 920 | :param item: The Song item to be used |
775 | 921 | :param xml_version: The xml version (not used) | ||
776 | 922 | :param remote: Triggered from remote | 921 | :param remote: Triggered from remote |
777 | 923 | :param context: Why is it being generated | 922 | :param context: Why is it being generated |
778 | 923 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. | ||
779 | 924 | """ | 924 | """ |
780 | 925 | log.debug('generating slide data') | 925 | log.debug('generating slide data') |
781 | 926 | if item: | 926 | if item: |
782 | 927 | 927 | ||
783 | === modified file 'openlp/plugins/custom/lib/mediaitem.py' | |||
784 | --- openlp/plugins/custom/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
785 | +++ openlp/plugins/custom/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
786 | @@ -28,7 +28,7 @@ | |||
787 | 28 | from openlp.core.common.i18n import UiStrings, translate | 28 | from openlp.core.common.i18n import UiStrings, translate |
788 | 29 | from openlp.core.common.registry import Registry | 29 | from openlp.core.common.registry import Registry |
789 | 30 | from openlp.core.common.settings import Settings | 30 | from openlp.core.common.settings import Settings |
791 | 31 | from openlp.core.lib import ServiceItemContext, check_item_selected | 31 | from openlp.core.lib import check_item_selected |
792 | 32 | from openlp.core.lib.mediamanageritem import MediaManagerItem | 32 | from openlp.core.lib.mediamanageritem import MediaManagerItem |
793 | 33 | from openlp.core.lib.plugin import PluginStatus | 33 | from openlp.core.lib.plugin import PluginStatus |
794 | 34 | from openlp.core.lib.serviceitem import ItemCapabilities | 34 | from openlp.core.lib.serviceitem import ItemCapabilities |
795 | @@ -219,15 +219,12 @@ | |||
796 | 219 | self.search_text_edit.setFocus() | 219 | self.search_text_edit.setFocus() |
797 | 220 | self.search_text_edit.selectAll() | 220 | self.search_text_edit.selectAll() |
798 | 221 | 221 | ||
801 | 222 | def generate_slide_data(self, service_item, item=None, xml_version=False, | 222 | def generate_slide_data(self, service_item, *, item=None, **kwargs): |
800 | 223 | remote=False, context=ServiceItemContext.Service): | ||
802 | 224 | """ | 223 | """ |
803 | 225 | Generate the slide data. Needs to be implemented by the plugin. | 224 | Generate the slide data. Needs to be implemented by the plugin. |
804 | 226 | :param service_item: To be updated | 225 | :param service_item: To be updated |
805 | 227 | :param item: The custom database item to be used | 226 | :param item: The custom database item to be used |
809 | 228 | :param xml_version: No used | 227 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. |
807 | 229 | :param remote: Is this triggered by the Preview Controller or Service Manager. | ||
808 | 230 | :param context: Why is this item required to be build (Default Service). | ||
810 | 231 | """ | 228 | """ |
811 | 232 | item_id = self._get_id_of_item_to_generate(item, self.remote_custom) | 229 | item_id = self._get_id_of_item_to_generate(item, self.remote_custom) |
812 | 233 | service_item.add_capability(ItemCapabilities.CanEdit) | 230 | service_item.add_capability(ItemCapabilities.CanEdit) |
813 | 234 | 231 | ||
814 | === modified file 'openlp/plugins/images/lib/mediaitem.py' | |||
815 | --- openlp/plugins/images/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
816 | +++ openlp/plugins/images/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
817 | @@ -542,16 +542,16 @@ | |||
818 | 542 | image_items.sort(key=lambda item: get_natural_key(item.text(0))) | 542 | image_items.sort(key=lambda item: get_natural_key(item.text(0))) |
819 | 543 | target_group.addChildren(image_items) | 543 | target_group.addChildren(image_items) |
820 | 544 | 544 | ||
823 | 545 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 545 | def generate_slide_data(self, service_item, *, item=None, remote=False, context=ServiceItemContext.Service, |
824 | 546 | context=ServiceItemContext.Service): | 546 | **kwargs): |
825 | 547 | """ | 547 | """ |
826 | 548 | Generate the slide data. Needs to be implemented by the plugin. | 548 | Generate the slide data. Needs to be implemented by the plugin. |
827 | 549 | 549 | ||
828 | 550 | :param service_item: The service item to be built on | 550 | :param service_item: The service item to be built on |
829 | 551 | :param item: The Song item to be used | 551 | :param item: The Song item to be used |
830 | 552 | :param xml_version: The xml version (not used) | ||
831 | 553 | :param remote: Triggered from remote | 552 | :param remote: Triggered from remote |
832 | 554 | :param context: Why is it being generated | 553 | :param context: Why is it being generated |
833 | 554 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. | ||
834 | 555 | """ | 555 | """ |
835 | 556 | background = QtGui.QColor(Settings().value(self.settings_section + '/background color')) | 556 | background = QtGui.QColor(Settings().value(self.settings_section + '/background color')) |
836 | 557 | if item: | 557 | if item: |
837 | 558 | 558 | ||
838 | === modified file 'openlp/plugins/media/lib/mediaitem.py' | |||
839 | --- openlp/plugins/media/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
840 | +++ openlp/plugins/media/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
841 | @@ -29,7 +29,7 @@ | |||
842 | 29 | from openlp.core.common.applocation import AppLocation | 29 | from openlp.core.common.applocation import AppLocation |
843 | 30 | from openlp.core.common.i18n import UiStrings, get_natural_key, translate | 30 | from openlp.core.common.i18n import UiStrings, get_natural_key, translate |
844 | 31 | from openlp.core.common.mixins import RegistryProperties | 31 | from openlp.core.common.mixins import RegistryProperties |
846 | 32 | from openlp.core.common.path import Path, create_paths, path_to_str | 32 | from openlp.core.common.path import create_paths, path_to_str |
847 | 33 | from openlp.core.common.registry import Registry | 33 | from openlp.core.common.registry import Registry |
848 | 34 | from openlp.core.common.settings import Settings | 34 | from openlp.core.common.settings import Settings |
849 | 35 | from openlp.core.lib import MediaType, ServiceItemContext, check_item_selected | 35 | from openlp.core.lib import MediaType, ServiceItemContext, check_item_selected |
850 | @@ -166,16 +166,16 @@ | |||
851 | 166 | # self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed) | 166 | # self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed) |
852 | 167 | pass | 167 | pass |
853 | 168 | 168 | ||
856 | 169 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 169 | def generate_slide_data(self, service_item, *, item=None, remote=False, context=ServiceItemContext.Service, |
857 | 170 | context=ServiceItemContext.Service): | 170 | **kwargs): |
858 | 171 | """ | 171 | """ |
859 | 172 | Generate the slide data. Needs to be implemented by the plugin. | 172 | Generate the slide data. Needs to be implemented by the plugin. |
860 | 173 | 173 | ||
861 | 174 | :param service_item: The service item to be built on | 174 | :param service_item: The service item to be built on |
862 | 175 | :param item: The Song item to be used | 175 | :param item: The Song item to be used |
863 | 176 | :param xml_version: The xml version (not used) | ||
864 | 177 | :param remote: Triggered from remote | 176 | :param remote: Triggered from remote |
865 | 178 | :param context: Why is it being generated | 177 | :param context: Why is it being generated |
866 | 178 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. | ||
867 | 179 | """ | 179 | """ |
868 | 180 | if item is None: | 180 | if item is None: |
869 | 181 | item = self.list_view.currentItem() | 181 | item = self.list_view.currentItem() |
870 | @@ -229,8 +229,8 @@ | |||
871 | 229 | Initialize media item. | 229 | Initialize media item. |
872 | 230 | """ | 230 | """ |
873 | 231 | self.list_view.clear() | 231 | self.list_view.clear() |
876 | 232 | self.service_path = str(AppLocation.get_section_data_path(self.settings_section) / 'thumbnails') | 232 | self.service_path = AppLocation.get_section_data_path(self.settings_section) / 'thumbnails' |
877 | 233 | create_paths(Path(self.service_path)) | 233 | create_paths(self.service_path) |
878 | 234 | self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')]) | 234 | self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')]) |
879 | 235 | self.rebuild_players() | 235 | self.rebuild_players() |
880 | 236 | 236 | ||
881 | @@ -264,7 +264,7 @@ | |||
882 | 264 | :param media: The media | 264 | :param media: The media |
883 | 265 | :param target_group: | 265 | :param target_group: |
884 | 266 | """ | 266 | """ |
886 | 267 | media.sort(key=lambda file_name: get_natural_key(os.path.split(str(file_name))[1])) | 267 | media.sort(key=lambda file_path: get_natural_key(file_path.name)) |
887 | 268 | for track in media: | 268 | for track in media: |
888 | 269 | track_info = QtCore.QFileInfo(track) | 269 | track_info = QtCore.QFileInfo(track) |
889 | 270 | item_name = None | 270 | item_name = None |
890 | 271 | 271 | ||
891 | === modified file 'openlp/plugins/presentations/lib/mediaitem.py' | |||
892 | --- openlp/plugins/presentations/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
893 | +++ openlp/plugins/presentations/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
894 | @@ -260,16 +260,16 @@ | |||
895 | 260 | doc.presentation_deleted() | 260 | doc.presentation_deleted() |
896 | 261 | doc.close_presentation() | 261 | doc.close_presentation() |
897 | 262 | 262 | ||
900 | 263 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 263 | def generate_slide_data(self, service_item, *, item=None, remote=False, context=ServiceItemContext.Service, |
901 | 264 | context=ServiceItemContext.Service, file_path=None): | 264 | file_path=None, **kwargs): |
902 | 265 | """ | 265 | """ |
903 | 266 | Generate the slide data. Needs to be implemented by the plugin. | 266 | Generate the slide data. Needs to be implemented by the plugin. |
904 | 267 | 267 | ||
905 | 268 | :param service_item: The service item to be built on | 268 | :param service_item: The service item to be built on |
906 | 269 | :param item: The Song item to be used | 269 | :param item: The Song item to be used |
907 | 270 | :param xml_version: The xml version (not used) | ||
908 | 271 | :param remote: Triggered from remote | 270 | :param remote: Triggered from remote |
909 | 272 | :param context: Why is it being generated | 271 | :param context: Why is it being generated |
910 | 272 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. | ||
911 | 273 | """ | 273 | """ |
912 | 274 | if item: | 274 | if item: |
913 | 275 | items = [item] | 275 | items = [item] |
914 | 276 | 276 | ||
915 | === modified file 'openlp/plugins/presentations/lib/messagelistener.py' | |||
916 | --- openlp/plugins/presentations/lib/messagelistener.py 2019-02-14 15:09:09 +0000 | |||
917 | +++ openlp/plugins/presentations/lib/messagelistener.py 2019-03-17 21:06:27 +0000 | |||
918 | @@ -337,14 +337,8 @@ | |||
919 | 337 | # Create a copy of the original item, and then clear the original item so it can be filled with images | 337 | # Create a copy of the original item, and then clear the original item so it can be filled with images |
920 | 338 | item_cpy = copy.copy(item) | 338 | item_cpy = copy.copy(item) |
921 | 339 | item.__init__(None) | 339 | item.__init__(None) |
930 | 340 | if is_live: | 340 | context = ServiceItemContext.Live if is_live else ServiceItemContext.Preview |
931 | 341 | # TODO: To Path object | 341 | self.media_item.generate_slide_data(item, item=item_cpy, context=context, file_path=file_path) |
924 | 342 | self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Live, | ||
925 | 343 | str(file_path)) | ||
926 | 344 | else: | ||
927 | 345 | # TODO: To Path object | ||
928 | 346 | self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Preview, | ||
929 | 347 | str(file_path)) | ||
932 | 348 | # Some of the original serviceitem attributes is needed in the new serviceitem | 342 | # Some of the original serviceitem attributes is needed in the new serviceitem |
933 | 349 | item.footer = item_cpy.footer | 343 | item.footer = item_cpy.footer |
934 | 350 | item.from_service = item_cpy.from_service | 344 | item.from_service = item_cpy.from_service |
935 | 351 | 345 | ||
936 | === modified file 'openlp/plugins/songs/forms/songimportform.py' | |||
937 | --- openlp/plugins/songs/forms/songimportform.py 2019-02-14 15:09:09 +0000 | |||
938 | +++ openlp/plugins/songs/forms/songimportform.py 2019-03-17 21:06:27 +0000 | |||
939 | @@ -329,8 +329,13 @@ | |||
940 | 329 | importer = self.plugin.import_songs( | 329 | importer = self.plugin.import_songs( |
941 | 330 | source_format, | 330 | source_format, |
942 | 331 | file_paths=self.get_list_of_paths(self.format_widgets[source_format]['file_list_widget'])) | 331 | file_paths=self.get_list_of_paths(self.format_widgets[source_format]['file_list_widget'])) |
945 | 332 | importer.do_import() | 332 | try: |
946 | 333 | self.progress_label.setText(WizardStrings.FinishedImport) | 333 | importer.do_import() |
947 | 334 | self.progress_label.setText(WizardStrings.FinishedImport) | ||
948 | 335 | except OSError as e: | ||
949 | 336 | log.exception('Importing songs failed') | ||
950 | 337 | self.progress_label.setText(translate('SongsPlugin.ImportWizardForm', | ||
951 | 338 | 'Your Song import failed. {error}').format(error=e)) | ||
952 | 334 | 339 | ||
953 | 335 | def on_error_copy_to_button_clicked(self): | 340 | def on_error_copy_to_button_clicked(self): |
954 | 336 | """ | 341 | """ |
955 | 337 | 342 | ||
956 | === modified file 'openlp/plugins/songs/lib/importers/cclifile.py' | |||
957 | --- openlp/plugins/songs/lib/importers/cclifile.py 2019-02-14 15:09:09 +0000 | |||
958 | +++ openlp/plugins/songs/lib/importers/cclifile.py 2019-03-17 21:06:27 +0000 | |||
959 | @@ -67,7 +67,7 @@ | |||
960 | 67 | details = {'confidence': 1, 'encoding': 'utf-8'} | 67 | details = {'confidence': 1, 'encoding': 'utf-8'} |
961 | 68 | except UnicodeDecodeError: | 68 | except UnicodeDecodeError: |
962 | 69 | details = chardet.detect(detect_content) | 69 | details = chardet.detect(detect_content) |
964 | 70 | in_file = codecs.open(str(file_path), 'r', details['encoding']) | 70 | in_file = codecs.open(file_path, 'r', details['encoding']) |
965 | 71 | if not in_file.read(1) == '\ufeff': | 71 | if not in_file.read(1) == '\ufeff': |
966 | 72 | # not UTF or no BOM was found | 72 | # not UTF or no BOM was found |
967 | 73 | in_file.seek(0) | 73 | in_file.seek(0) |
968 | @@ -251,10 +251,10 @@ | |||
969 | 251 | line_number = 0 | 251 | line_number = 0 |
970 | 252 | check_first_verse_line = False | 252 | check_first_verse_line = False |
971 | 253 | verse_text = '' | 253 | verse_text = '' |
972 | 254 | verse_type = VerseType.tags[VerseType.Verse] | ||
973 | 254 | song_author = '' | 255 | song_author = '' |
974 | 255 | verse_start = False | 256 | verse_start = False |
975 | 256 | for line in text_list: | 257 | for line in text_list: |
976 | 257 | verse_type = 'v' | ||
977 | 258 | clean_line = line.strip() | 258 | clean_line = line.strip() |
978 | 259 | if not clean_line: | 259 | if not clean_line: |
979 | 260 | if line_number == 0: | 260 | if line_number == 0: |
980 | @@ -263,6 +263,7 @@ | |||
981 | 263 | if verse_text: | 263 | if verse_text: |
982 | 264 | self.add_verse(verse_text, verse_type) | 264 | self.add_verse(verse_text, verse_type) |
983 | 265 | verse_text = '' | 265 | verse_text = '' |
984 | 266 | verse_type = VerseType.tags[VerseType.Verse] | ||
985 | 266 | verse_start = False | 267 | verse_start = False |
986 | 267 | else: | 268 | else: |
987 | 268 | # line_number=0, song title | 269 | # line_number=0, song title |
988 | @@ -279,7 +280,7 @@ | |||
989 | 279 | elif not verse_start: | 280 | elif not verse_start: |
990 | 280 | # We have the verse descriptor | 281 | # We have the verse descriptor |
991 | 281 | verse_desc_parts = clean_line.split(' ') | 282 | verse_desc_parts = clean_line.split(' ') |
993 | 282 | if len(verse_desc_parts) == 2: | 283 | if len(verse_desc_parts): |
994 | 283 | if verse_desc_parts[0].startswith('Ver'): | 284 | if verse_desc_parts[0].startswith('Ver'): |
995 | 284 | verse_type = VerseType.tags[VerseType.Verse] | 285 | verse_type = VerseType.tags[VerseType.Verse] |
996 | 285 | elif verse_desc_parts[0].startswith('Ch'): | 286 | elif verse_desc_parts[0].startswith('Ch'): |
997 | 286 | 287 | ||
998 | === modified file 'openlp/plugins/songs/lib/mediaitem.py' | |||
999 | --- openlp/plugins/songs/lib/mediaitem.py 2019-02-14 15:09:09 +0000 | |||
1000 | +++ openlp/plugins/songs/lib/mediaitem.py 2019-03-17 21:06:27 +0000 | |||
1001 | @@ -557,16 +557,14 @@ | |||
1002 | 557 | self.plugin.manager.save_object(new_song) | 557 | self.plugin.manager.save_object(new_song) |
1003 | 558 | self.on_song_list_load() | 558 | self.on_song_list_load() |
1004 | 559 | 559 | ||
1007 | 560 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, | 560 | def generate_slide_data(self, service_item, *, item=None, context=ServiceItemContext.Service, **kwargs): |
1006 | 561 | context=ServiceItemContext.Service): | ||
1008 | 562 | """ | 561 | """ |
1009 | 563 | Generate the slide data. Needs to be implemented by the plugin. | 562 | Generate the slide data. Needs to be implemented by the plugin. |
1010 | 564 | 563 | ||
1011 | 565 | :param service_item: The service item to be built on | 564 | :param service_item: The service item to be built on |
1012 | 566 | :param item: The Song item to be used | 565 | :param item: The Song item to be used |
1013 | 567 | :param xml_version: The xml version (not used) | ||
1014 | 568 | :param remote: Triggered from remote | ||
1015 | 569 | :param context: Why is it being generated | 566 | :param context: Why is it being generated |
1016 | 567 | :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. | ||
1017 | 570 | """ | 568 | """ |
1018 | 571 | log.debug('generate_slide_data: {service}, {item}, {remote}'.format(service=service_item, item=item, | 569 | log.debug('generate_slide_data: {service}, {item}, {remote}'.format(service=service_item, item=item, |
1019 | 572 | remote=self.remote_song)) | 570 | remote=self.remote_song)) |
1020 | 573 | 571 | ||
1021 | === modified file 'openlp/plugins/songusage/forms/songusagedetailform.py' | |||
1022 | --- openlp/plugins/songusage/forms/songusagedetailform.py 2019-02-14 15:09:09 +0000 | |||
1023 | +++ openlp/plugins/songusage/forms/songusagedetailform.py 2019-03-17 21:06:27 +0000 | |||
1024 | @@ -85,7 +85,7 @@ | |||
1025 | 85 | self.main_window.error_message( | 85 | self.main_window.error_message( |
1026 | 86 | translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'), | 86 | translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'), |
1027 | 87 | translate('SongUsagePlugin.SongUsageDetailForm', 'You have not set a valid output location for your' | 87 | translate('SongUsagePlugin.SongUsageDetailForm', 'You have not set a valid output location for your' |
1029 | 88 | ' song usage report. \nPlease select an existing path on your computer.') | 88 | ' song usage report.\nPlease select an existing path on your computer.') |
1030 | 89 | ) | 89 | ) |
1031 | 90 | return | 90 | return |
1032 | 91 | create_paths(path) | 91 | create_paths(path) |
1033 | @@ -112,7 +112,7 @@ | |||
1034 | 112 | self.main_window.information_message( | 112 | self.main_window.information_message( |
1035 | 113 | translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation'), | 113 | translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation'), |
1036 | 114 | translate('SongUsagePlugin.SongUsageDetailForm', | 114 | translate('SongUsagePlugin.SongUsageDetailForm', |
1038 | 115 | 'Report \n{name} \nhas been successfully created. ').format(name=report_file_name) | 115 | 'Report\n{name}\nhas been successfully created.').format(name=report_file_name) |
1039 | 116 | ) | 116 | ) |
1040 | 117 | except OSError as ose: | 117 | except OSError as ose: |
1041 | 118 | log.exception('Failed to write out song usage records') | 118 | log.exception('Failed to write out song usage records') |
1042 | 119 | 119 | ||
1043 | === modified file 'run_openlp.py' | |||
1044 | --- run_openlp.py 2019-02-14 15:09:09 +0000 | |||
1045 | +++ run_openlp.py 2019-03-17 21:06:27 +0000 | |||
1046 | @@ -24,6 +24,7 @@ | |||
1047 | 24 | The entrypoint for OpenLP | 24 | The entrypoint for OpenLP |
1048 | 25 | """ | 25 | """ |
1049 | 26 | import faulthandler | 26 | import faulthandler |
1050 | 27 | import logging | ||
1051 | 27 | import multiprocessing | 28 | import multiprocessing |
1052 | 28 | import sys | 29 | import sys |
1053 | 29 | 30 | ||
1054 | @@ -34,14 +35,19 @@ | |||
1055 | 34 | from openlp.core.common.applocation import AppLocation | 35 | from openlp.core.common.applocation import AppLocation |
1056 | 35 | from openlp.core.common.path import create_paths | 36 | from openlp.core.common.path import create_paths |
1057 | 36 | 37 | ||
1058 | 38 | log = logging.getLogger(__name__) | ||
1059 | 39 | |||
1060 | 37 | 40 | ||
1061 | 38 | def set_up_fault_handling(): | 41 | def set_up_fault_handling(): |
1062 | 39 | """ | 42 | """ |
1063 | 40 | Set up the Python fault handler | 43 | Set up the Python fault handler |
1064 | 41 | """ | 44 | """ |
1065 | 42 | # Create the cache directory if it doesn't exist, and enable the fault handler to log to an error log file | 45 | # Create the cache directory if it doesn't exist, and enable the fault handler to log to an error log file |
1068 | 43 | create_paths(AppLocation.get_directory(AppLocation.CacheDir)) | 46 | try: |
1069 | 44 | faulthandler.enable((AppLocation.get_directory(AppLocation.CacheDir) / 'error.log').open('wb')) | 47 | create_paths(AppLocation.get_directory(AppLocation.CacheDir)) |
1070 | 48 | faulthandler.enable((AppLocation.get_directory(AppLocation.CacheDir) / 'error.log').open('wb')) | ||
1071 | 49 | except OSError: | ||
1072 | 50 | log.exception('An exception occurred when enabling the fault handler') | ||
1073 | 45 | 51 | ||
1074 | 46 | 52 | ||
1075 | 47 | def start(): | 53 | def start(): |
1076 | 48 | 54 | ||
1077 | === modified file 'tests/functional/openlp_core/api/test_deploy.py' | |||
1078 | --- tests/functional/openlp_core/api/test_deploy.py 2019-02-14 21:19:26 +0000 | |||
1079 | +++ tests/functional/openlp_core/api/test_deploy.py 2019-03-17 21:06:27 +0000 | |||
1080 | @@ -63,8 +63,8 @@ | |||
1081 | 63 | deploy_zipfile(root_path, 'site.zip') | 63 | deploy_zipfile(root_path, 'site.zip') |
1082 | 64 | 64 | ||
1083 | 65 | # THEN: the zip file should have been extracted to the right location | 65 | # THEN: the zip file should have been extracted to the right location |
1086 | 66 | MockZipFile.assert_called_once_with(root_path_str + os.sep + 'site.zip') | 66 | MockZipFile.assert_called_once_with(Path('/tmp/remotes/site.zip')) |
1087 | 67 | mocked_zipfile.extractall.assert_called_once_with(root_path_str) | 67 | mocked_zipfile.extractall.assert_called_once_with(Path('/tmp/remotes')) |
1088 | 68 | 68 | ||
1089 | 69 | @patch('openlp.core.api.deploy.Registry') | 69 | @patch('openlp.core.api.deploy.Registry') |
1090 | 70 | @patch('openlp.core.api.deploy.get_web_page') | 70 | @patch('openlp.core.api.deploy.get_web_page') |
1091 | 71 | 71 | ||
1092 | === modified file 'tests/functional/openlp_core/common/test_init.py' | |||
1093 | --- tests/functional/openlp_core/common/test_init.py 2019-02-14 15:09:09 +0000 | |||
1094 | +++ tests/functional/openlp_core/common/test_init.py 2019-03-17 21:06:27 +0000 | |||
1095 | @@ -309,9 +309,9 @@ | |||
1096 | 309 | """ | 309 | """ |
1097 | 310 | # GIVEN: A mocked UniversalDetector instance with done attribute set to True after first iteration | 310 | # GIVEN: A mocked UniversalDetector instance with done attribute set to True after first iteration |
1098 | 311 | with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ | 311 | with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ |
1100 | 312 | patch.object(Path, 'open', return_value=BytesIO(b"data" * 260)) as mocked_open: | 312 | patch.object(Path, 'open', return_value=BytesIO(b'data' * 260)) as mocked_open: |
1101 | 313 | encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} | 313 | encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} |
1103 | 314 | mocked_universal_detector_inst = MagicMock(result=encoding_result) | 314 | mocked_universal_detector_inst = MagicMock(**{'close.return_value': encoding_result}) |
1104 | 315 | type(mocked_universal_detector_inst).done = PropertyMock(side_effect=[False, True]) | 315 | type(mocked_universal_detector_inst).done = PropertyMock(side_effect=[False, True]) |
1105 | 316 | mocked_universal_detector.return_value = mocked_universal_detector_inst | 316 | mocked_universal_detector.return_value = mocked_universal_detector_inst |
1106 | 317 | 317 | ||
1107 | @@ -320,7 +320,7 @@ | |||
1108 | 320 | 320 | ||
1109 | 321 | # THEN: The feed method of UniversalDetector should only br called once before returning a result | 321 | # THEN: The feed method of UniversalDetector should only br called once before returning a result |
1110 | 322 | mocked_open.assert_called_once_with('rb') | 322 | mocked_open.assert_called_once_with('rb') |
1112 | 323 | assert mocked_universal_detector_inst.feed.mock_calls == [call(b"data" * 256)] | 323 | assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256)] |
1113 | 324 | mocked_universal_detector_inst.close.assert_called_once_with() | 324 | mocked_universal_detector_inst.close.assert_called_once_with() |
1114 | 325 | assert result == encoding_result | 325 | assert result == encoding_result |
1115 | 326 | 326 | ||
1116 | @@ -331,10 +331,10 @@ | |||
1117 | 331 | # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test | 331 | # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test |
1118 | 332 | # data (enough to run the iterator twice) | 332 | # data (enough to run the iterator twice) |
1119 | 333 | with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ | 333 | with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ |
1121 | 334 | patch.object(Path, 'open', return_value=BytesIO(b"data" * 260)) as mocked_open: | 334 | patch.object(Path, 'open', return_value=BytesIO(b'data' * 260)) as mocked_open: |
1122 | 335 | encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} | 335 | encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} |
1123 | 336 | mocked_universal_detector_inst = MagicMock(mock=mocked_universal_detector, | 336 | mocked_universal_detector_inst = MagicMock(mock=mocked_universal_detector, |
1125 | 337 | **{'done': False, 'result': encoding_result}) | 337 | **{'done': False, 'close.return_value': encoding_result}) |
1126 | 338 | mocked_universal_detector.return_value = mocked_universal_detector_inst | 338 | mocked_universal_detector.return_value = mocked_universal_detector_inst |
1127 | 339 | 339 | ||
1128 | 340 | # WHEN: Calling get_file_encoding | 340 | # WHEN: Calling get_file_encoding |
1129 | @@ -342,7 +342,7 @@ | |||
1130 | 342 | 342 | ||
1131 | 343 | # THEN: The feed method of UniversalDetector should have been called twice before returning a result | 343 | # THEN: The feed method of UniversalDetector should have been called twice before returning a result |
1132 | 344 | mocked_open.assert_called_once_with('rb') | 344 | mocked_open.assert_called_once_with('rb') |
1134 | 345 | assert mocked_universal_detector_inst.feed.mock_calls == [call(b"data" * 256), call(b"data" * 4)] | 345 | assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256), call(b'data' * 4)] |
1135 | 346 | mocked_universal_detector_inst.close.assert_called_once_with() | 346 | mocked_universal_detector_inst.close.assert_called_once_with() |
1136 | 347 | assert result == encoding_result | 347 | assert result == encoding_result |
1137 | 348 | 348 | ||
1138 | @@ -352,13 +352,19 @@ | |||
1139 | 352 | """ | 352 | """ |
1140 | 353 | # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test | 353 | # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test |
1141 | 354 | # data (enough to run the iterator twice) | 354 | # data (enough to run the iterator twice) |
1143 | 355 | with patch('openlp.core.common.UniversalDetector'), \ | 355 | with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ |
1144 | 356 | patch('builtins.open', side_effect=OSError), \ | 356 | patch('builtins.open', side_effect=OSError), \ |
1145 | 357 | patch('openlp.core.common.log') as mocked_log: | 357 | patch('openlp.core.common.log') as mocked_log: |
1146 | 358 | encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} | ||
1147 | 359 | mocked_universal_detector_inst = MagicMock(mock=mocked_universal_detector, | ||
1148 | 360 | **{'done': False, 'close.return_value': encoding_result}) | ||
1149 | 361 | mocked_universal_detector.return_value = mocked_universal_detector_inst | ||
1150 | 358 | 362 | ||
1151 | 359 | # WHEN: Calling get_file_encoding | 363 | # WHEN: Calling get_file_encoding |
1152 | 360 | result = get_file_encoding(Path('file name')) | 364 | result = get_file_encoding(Path('file name')) |
1153 | 361 | 365 | ||
1154 | 362 | # THEN: log.exception should be called and get_file_encoding should return None | 366 | # THEN: log.exception should be called and get_file_encoding should return None |
1155 | 363 | mocked_log.exception.assert_called_once_with('Error detecting file encoding') | 367 | mocked_log.exception.assert_called_once_with('Error detecting file encoding') |
1157 | 364 | assert result is None | 368 | mocked_universal_detector_inst.feed.assert_not_called() |
1158 | 369 | mocked_universal_detector_inst.close.assert_called_once_with() | ||
1159 | 370 | assert result == encoding_result | ||
1160 | 365 | 371 | ||
1161 | === modified file 'tests/functional/openlp_core/common/test_path.py' | |||
1162 | --- tests/functional/openlp_core/common/test_path.py 2019-02-14 21:19:26 +0000 | |||
1163 | +++ tests/functional/openlp_core/common/test_path.py 2019-03-17 21:06:27 +0000 | |||
1164 | @@ -179,9 +179,8 @@ | |||
1165 | 179 | # WHEN: Calling :func:`openlp.core.common.path.rmtree` with the path parameter as Path object type | 179 | # WHEN: Calling :func:`openlp.core.common.path.rmtree` with the path parameter as Path object type |
1166 | 180 | path.rmtree() | 180 | path.rmtree() |
1167 | 181 | 181 | ||
1171 | 182 | # THEN: :func:`shutil.rmtree` should have been called with the str equivalents of the Path object. | 182 | # THEN: :func:`shutil.rmtree` should have been called with the the Path object. |
1172 | 183 | mocked_shutil_rmtree.assert_called_once_with( | 183 | mocked_shutil_rmtree.assert_called_once_with(Path('test', 'path'), False, None) |
1170 | 184 | os.path.join('test', 'path'), False, None) | ||
1173 | 185 | 184 | ||
1174 | 186 | def test_rmtree_optional_params(self): | 185 | def test_rmtree_optional_params(self): |
1175 | 187 | """ | 186 | """ |
1176 | @@ -198,8 +197,7 @@ | |||
1177 | 198 | 197 | ||
1178 | 199 | # THEN: :func:`shutil.rmtree` should have been called with the optional parameters, with out any of the | 198 | # THEN: :func:`shutil.rmtree` should have been called with the optional parameters, with out any of the |
1179 | 200 | # values being modified | 199 | # values being modified |
1182 | 201 | mocked_shutil_rmtree.assert_called_once_with( | 200 | mocked_shutil_rmtree.assert_called_once_with(path, True, mocked_on_error) |
1181 | 202 | os.path.join('test', 'path'), True, mocked_on_error) | ||
1183 | 203 | 201 | ||
1184 | 204 | def test_which_no_command(self): | 202 | def test_which_no_command(self): |
1185 | 205 | """ | 203 | """ |
1186 | 206 | 204 | ||
1187 | === modified file 'tests/functional/openlp_core/lib/test_serviceitem.py' | |||
1188 | --- tests/functional/openlp_core/lib/test_serviceitem.py 2019-02-14 15:09:09 +0000 | |||
1189 | +++ tests/functional/openlp_core/lib/test_serviceitem.py 2019-03-17 21:06:27 +0000 | |||
1190 | @@ -141,7 +141,7 @@ | |||
1191 | 141 | """ | 141 | """ |
1192 | 142 | # GIVEN: A new service item and a mocked add icon function | 142 | # GIVEN: A new service item and a mocked add icon function |
1193 | 143 | image_name = 'image_1.jpg' | 143 | image_name = 'image_1.jpg' |
1195 | 144 | test_file = os.path.join(str(TEST_PATH), image_name) | 144 | test_file = TEST_PATH / image_name |
1196 | 145 | frame_array = {'path': test_file, 'title': image_name} | 145 | frame_array = {'path': test_file, 'title': image_name} |
1197 | 146 | 146 | ||
1198 | 147 | service_item = ServiceItem(None) | 147 | service_item = ServiceItem(None) |
1199 | @@ -154,13 +154,13 @@ | |||
1200 | 154 | mocked_get_section_data_path: | 154 | mocked_get_section_data_path: |
1201 | 155 | mocked_exists.return_value = True | 155 | mocked_exists.return_value = True |
1202 | 156 | mocked_get_section_data_path.return_value = Path('/path/') | 156 | mocked_get_section_data_path.return_value = Path('/path/') |
1204 | 157 | service_item.set_from_service(line, str(TEST_PATH)) | 157 | service_item.set_from_service(line, TEST_PATH) |
1205 | 158 | 158 | ||
1206 | 159 | # THEN: We should get back a valid service item | 159 | # THEN: We should get back a valid service item |
1207 | 160 | assert service_item.is_valid is True, 'The new service item should be valid' | 160 | assert service_item.is_valid is True, 'The new service item should be valid' |
1208 | 161 | assert test_file == service_item.get_rendered_frame(0), 'The first frame should match the path to the image' | 161 | assert test_file == service_item.get_rendered_frame(0), 'The first frame should match the path to the image' |
1209 | 162 | assert frame_array == service_item.get_frames()[0], 'The return should match frame array1' | 162 | assert frame_array == service_item.get_frames()[0], 'The return should match frame array1' |
1211 | 163 | assert test_file == str(service_item.get_frame_path(0)), \ | 163 | assert test_file == service_item.get_frame_path(0), \ |
1212 | 164 | 'The frame path should match the full path to the image' | 164 | 'The frame path should match the full path to the image' |
1213 | 165 | assert image_name == service_item.get_frame_title(0), 'The frame title should match the image name' | 165 | assert image_name == service_item.get_frame_title(0), 'The frame title should match the image name' |
1214 | 166 | assert image_name == service_item.get_display_title(), 'The display title should match the first image name' | 166 | assert image_name == service_item.get_display_title(), 'The display title should match the first image name' |
1215 | @@ -328,7 +328,7 @@ | |||
1216 | 328 | 328 | ||
1217 | 329 | # WHEN: We add a custom from a saved service | 329 | # WHEN: We add a custom from a saved service |
1218 | 330 | line = convert_file_service_item(TEST_PATH, 'serviceitem-song-linked-audio.osj') | 330 | line = convert_file_service_item(TEST_PATH, 'serviceitem-song-linked-audio.osj') |
1220 | 331 | service_item.set_from_service(line, '/test/') | 331 | service_item.set_from_service(line, Path('/test/')) |
1221 | 332 | 332 | ||
1222 | 333 | # THEN: We should get back a valid service item | 333 | # THEN: We should get back a valid service item |
1223 | 334 | assert service_item.is_valid is True, 'The new service item should be valid' | 334 | assert service_item.is_valid is True, 'The new service item should be valid' |
1224 | 335 | 335 | ||
1225 | === modified file 'tests/functional/openlp_core/ui/test_thememanager.py' | |||
1226 | --- tests/functional/openlp_core/ui/test_thememanager.py 2019-02-14 15:09:09 +0000 | |||
1227 | +++ tests/functional/openlp_core/ui/test_thememanager.py 2019-03-17 21:06:27 +0000 | |||
1228 | @@ -66,9 +66,9 @@ | |||
1229 | 66 | theme_manager._export_theme(Path('some', 'path', 'Default.otz'), 'Default') | 66 | theme_manager._export_theme(Path('some', 'path', 'Default.otz'), 'Default') |
1230 | 67 | 67 | ||
1231 | 68 | # THEN: The zipfile should be created at the given path | 68 | # THEN: The zipfile should be created at the given path |
1235 | 69 | mocked_zipfile_init.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w') | 69 | mocked_zipfile_init.assert_called_with(Path('some', 'path', 'Default.otz'), 'w') |
1236 | 70 | mocked_zipfile_write.assert_called_with(str(RESOURCE_PATH / 'themes' / 'Default' / 'Default.xml'), | 70 | mocked_zipfile_write.assert_called_with(RESOURCE_PATH / 'themes' / 'Default' / 'Default.xml', |
1237 | 71 | os.path.join('Default', 'Default.xml')) | 71 | Path('Default', 'Default.xml')) |
1238 | 72 | 72 | ||
1239 | 73 | def test_initial_theme_manager(self): | 73 | def test_initial_theme_manager(self): |
1240 | 74 | """ | 74 | """ |
1241 | 75 | 75 | ||
1242 | === modified file 'tests/functional/openlp_plugins/bibles/test_manager.py' | |||
1243 | --- tests/functional/openlp_plugins/bibles/test_manager.py 2019-02-14 15:09:09 +0000 | |||
1244 | +++ tests/functional/openlp_plugins/bibles/test_manager.py 2019-03-17 21:06:27 +0000 | |||
1245 | @@ -55,7 +55,8 @@ | |||
1246 | 55 | instance = BibleManager(MagicMock()) | 55 | instance = BibleManager(MagicMock()) |
1247 | 56 | # We need to keep a reference to the mock for close_all as it gets set to None later on! | 56 | # We need to keep a reference to the mock for close_all as it gets set to None later on! |
1248 | 57 | mocked_close_all = MagicMock() | 57 | mocked_close_all = MagicMock() |
1250 | 58 | mocked_bible = MagicMock(file='KJV.sqlite', path='bibles', **{'session.close_all': mocked_close_all}) | 58 | mocked_bible = MagicMock(file_path='KJV.sqlite', path=Path('bibles'), |
1251 | 59 | **{'session.close_all': mocked_close_all}) | ||
1252 | 59 | instance.db_cache = {'KJV': mocked_bible} | 60 | instance.db_cache = {'KJV': mocked_bible} |
1253 | 60 | 61 | ||
1254 | 61 | # WHEN: Calling delete_bible with 'KJV' | 62 | # WHEN: Calling delete_bible with 'KJV' |
1255 | @@ -66,4 +67,4 @@ | |||
1256 | 66 | assert result is True | 67 | assert result is True |
1257 | 67 | mocked_close_all.assert_called_once_with() | 68 | mocked_close_all.assert_called_once_with() |
1258 | 68 | assert mocked_bible.session is None | 69 | assert mocked_bible.session is None |
1260 | 69 | mocked_delete_file.assert_called_once_with(Path('bibles', 'KJV.sqlite')) | 70 | mocked_delete_file.assert_called_once_with(Path('bibles'), 'KJV.sqlite') |
1261 | 70 | 71 | ||
1262 | === modified file 'tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py' | |||
1263 | --- tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py 2019-02-14 15:09:09 +0000 | |||
1264 | +++ tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py 2019-03-17 21:06:27 +0000 | |||
1265 | @@ -236,8 +236,8 @@ | |||
1266 | 236 | assert MockedQListWidgetItem.call_args_list == expected_widget_item_calls, MockedQListWidgetItem.call_args_list | 236 | assert MockedQListWidgetItem.call_args_list == expected_widget_item_calls, MockedQListWidgetItem.call_args_list |
1267 | 237 | mocked_author_item1.setData.assert_called_once_with(QtCore.Qt.UserRole, 2) | 237 | mocked_author_item1.setData.assert_called_once_with(QtCore.Qt.UserRole, 2) |
1268 | 238 | mocked_author_item2.setData.assert_called_once_with(QtCore.Qt.UserRole, 1) | 238 | mocked_author_item2.setData.assert_called_once_with(QtCore.Qt.UserRole, 1) |
1271 | 239 | mocked_authors_list_widget.addItem.call_args_list == [ | 239 | mocked_authors_list_widget.addItem.assert_has_calls([ |
1272 | 240 | call(mocked_author_item1), call(mocked_author_item2)] | 240 | call(mocked_author_item1), call(mocked_author_item2)]) |
1273 | 241 | 241 | ||
1274 | 242 | @patch('openlp.plugins.songs.forms.songmaintenanceform.QtWidgets.QListWidgetItem') | 242 | @patch('openlp.plugins.songs.forms.songmaintenanceform.QtWidgets.QListWidgetItem') |
1275 | 243 | @patch('openlp.plugins.songs.forms.songmaintenanceform.Topic') | 243 | @patch('openlp.plugins.songs.forms.songmaintenanceform.Topic') |
1276 | 244 | 244 | ||
1277 | === modified file 'tests/openlp_core/common/test_network_interfaces.py' | |||
1278 | --- tests/openlp_core/common/test_network_interfaces.py 2019-02-14 15:09:09 +0000 | |||
1279 | +++ tests/openlp_core/common/test_network_interfaces.py 2019-03-17 21:06:27 +0000 | |||
1280 | @@ -70,7 +70,7 @@ | |||
1281 | 70 | """ | 70 | """ |
1282 | 71 | Return a QFlags enum with IsUp and IsRunning | 71 | Return a QFlags enum with IsUp and IsRunning |
1283 | 72 | """ | 72 | """ |
1285 | 73 | return (QNetworkInterface.IsUp | QNetworkInterface.IsRunning) | 73 | return QNetworkInterface.IsUp | QNetworkInterface.IsRunning |
1286 | 74 | 74 | ||
1287 | 75 | def name(self): | 75 | def name(self): |
1288 | 76 | return self.my_name | 76 | return self.my_name |
1289 | 77 | 77 | ||
1290 | === modified file 'tests/openlp_core/projectors/test_projector_pjlink_commands_01.py' | |||
1291 | --- tests/openlp_core/projectors/test_projector_pjlink_commands_01.py 2019-03-08 15:19:57 +0000 | |||
1292 | +++ tests/openlp_core/projectors/test_projector_pjlink_commands_01.py 2019-03-17 21:06:27 +0000 | |||
1293 | @@ -605,9 +605,9 @@ | |||
1294 | 605 | 605 | ||
1295 | 606 | # THEN: Power should be set to ON | 606 | # THEN: Power should be set to ON |
1296 | 607 | assert pjlink.power == S_STANDBY, 'Power should not have changed' | 607 | assert pjlink.power == S_STANDBY, 'Power should not have changed' |
1300 | 608 | assert mock_UpdateIcons.emit.called is False, 'projectorUpdateIcons() should not have been called' | 608 | mock_UpdateIcons.emit.assert_not_called() |
1301 | 609 | mock_change_status.called is False, 'change_status() should not have been called' | 609 | mock_change_status.assert_not_called() |
1302 | 610 | mock_send_command.called is False, 'send_command() should not have been called' | 610 | mock_send_command.assert_not_called() |
1303 | 611 | mock_log.warning.assert_has_calls(log_warn_calls) | 611 | mock_log.warning.assert_has_calls(log_warn_calls) |
1304 | 612 | 612 | ||
1305 | 613 | def test_projector_process_powr_off(self): | 613 | def test_projector_process_powr_off(self): |
1306 | @@ -627,9 +627,9 @@ | |||
1307 | 627 | 627 | ||
1308 | 628 | # THEN: Power should be set to ON | 628 | # THEN: Power should be set to ON |
1309 | 629 | assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY' | 629 | assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY' |
1313 | 630 | assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called' | 630 | mock_UpdateIcons.emit.assert_called_with() |
1314 | 631 | mock_change_status.called is True, 'change_status should have been called' | 631 | mock_change_status.assert_called_with(313) |
1315 | 632 | mock_send_command.called is False, 'send_command should not have been called' | 632 | mock_send_command.assert_not_called() |
1316 | 633 | 633 | ||
1317 | 634 | def test_projector_process_rfil_save(self): | 634 | def test_projector_process_rfil_save(self): |
1318 | 635 | """ | 635 | """ |
1319 | 636 | 636 | ||
1320 | === modified file 'tests/openlp_core/projectors/test_projector_sourceform.py' | |||
1321 | --- tests/openlp_core/projectors/test_projector_sourceform.py 2019-02-14 15:09:09 +0000 | |||
1322 | +++ tests/openlp_core/projectors/test_projector_sourceform.py 2019-03-17 21:06:27 +0000 | |||
1323 | @@ -83,8 +83,8 @@ | |||
1324 | 83 | Delete all C++ objects at end so we don't segfault. | 83 | Delete all C++ objects at end so we don't segfault. |
1325 | 84 | """ | 84 | """ |
1326 | 85 | self.projectordb.session.close() | 85 | self.projectordb.session.close() |
1329 | 86 | del(self.projectordb) | 86 | del self.projectordb |
1330 | 87 | del(self.projector) | 87 | del self.projector |
1331 | 88 | retries = 0 | 88 | retries = 0 |
1332 | 89 | while retries < 5: | 89 | while retries < 5: |
1333 | 90 | try: | 90 | try: |
Linux tests passed!