Merge lp:~phill-ridout/openlp/ftw-refactors into lp:openlp

Proposed by Phill
Status: Superseded
Proposed branch: lp:~phill-ridout/openlp/ftw-refactors
Merge into: lp:openlp
Diff against target: 984 lines (+322/-204)
13 files modified
openlp/core/app.py (+1/-1)
openlp/core/common/httputils.py (+16/-8)
openlp/core/threading.py (+2/-2)
openlp/core/ui/firsttimeform.py (+78/-93)
openlp/core/ui/firsttimewizard.py (+64/-55)
openlp/core/ui/mainwindow.py (+1/-2)
openlp/core/widgets/widgets.py (+28/-0)
openlp/plugins/songs/lib/importers/openlp.py (+1/-1)
openlp/plugins/songs/reporting.py (+0/-7)
tests/functional/openlp_core/common/test_httputils.py (+1/-1)
tests/functional/openlp_core/test_threading.py (+5/-9)
tests/functional/openlp_core/ui/test_firsttimeform.py (+119/-19)
tests/functional/openlp_plugins/songs/test_openlpimporter.py (+6/-6)
To merge this branch: bzr merge lp:~phill-ridout/openlp/ftw-refactors
Reviewer Review Type Date Requested Status
OpenLP Core Pending
Review via email: mp+363750@code.launchpad.net

This proposal supersedes a proposal from 2019-02-27.

This proposal has been superseded by a proposal from 2019-02-27.

Commit message

Add proxy settings to ftw. Option to skip sample data

Description of the change

Add option to skip downloading.
Add dialog for proxy settings to FTW
FTW refactors.
General fixes.

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

Linux tests failed, please see https://ci.openlp.io/job/MP-02-Linux_Tests/89/ for more details

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

Linux tests failed, please see https://ci.openlp.io/job/MP-02-Linux_Tests/90/ for more details

2849. By Phill

PEP fixes

2850. By Phill

PEP fixes

2851. By Phill

mac test fix?

2852. By Phill

Test fixes

2853. By Phill

HEAD

2854. By Phill

Test fix

2855. By Phill

PEP8

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/app.py'
2--- openlp/core/app.py 2019-02-14 15:09:09 +0000
3+++ openlp/core/app.py 2019-02-27 22:20:41 +0000
4@@ -101,7 +101,7 @@
5 ftw.initialize(screens)
6 if ftw.exec() == QtWidgets.QDialog.Accepted:
7 Settings().setValue('core/has run wizard', True)
8- elif ftw.was_cancelled:
9+ else:
10 QtCore.QCoreApplication.exit()
11 sys.exit()
12 # Correct stylesheet bugs
13
14=== modified file 'openlp/core/common/httputils.py'
15--- openlp/core/common/httputils.py 2019-02-21 21:29:00 +0000
16+++ openlp/core/common/httputils.py 2019-02-27 22:20:41 +0000
17@@ -158,16 +158,20 @@
18 return response.text
19
20
21-def get_url_file_size(url):
22+def get_url_file_size(url, proxy=None):
23 """
24 Get the size of a file.
25
26 :param url: The URL of the file we want to download.
27+ :param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
28+ as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
29 """
30 retries = 0
31+ if not isinstance(proxy, dict):
32+ proxy = get_proxy_settings(mode=proxy)
33 while True:
34 try:
35- response = requests.head(url, timeout=float(CONNECTION_TIMEOUT), allow_redirects=True)
36+ response = requests.head(url, proxies=proxy, timeout=float(CONNECTION_TIMEOUT), allow_redirects=True)
37 return int(response.headers['Content-Length'])
38 except OSError:
39 if retries > CONNECTION_RETRIES:
40@@ -178,7 +182,7 @@
41 continue
42
43
44-def download_file(update_object, url, file_path, sha256=None):
45+def download_file(update_object, url, file_path, sha256=None, proxy=None):
46 """"
47 Download a file given a URL. The file is retrieved in chunks, giving the ability to cancel the download at any
48 point. Returns False on download error.
49@@ -187,15 +191,19 @@
50 :param url: URL to download
51 :param file_path: Destination file
52 :param sha256: The check sum value to be checked against the download value
53+ :param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
54+ as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
55 """
56 block_count = 0
57 block_size = 4096
58 retries = 0
59+ if not isinstance(proxy, dict):
60+ proxy = get_proxy_settings(mode=proxy)
61 log.debug('url_get_file: %s', url)
62 while retries < CONNECTION_RETRIES:
63 try:
64 with file_path.open('wb') as saved_file:
65- response = requests.get(url, timeout=float(CONNECTION_TIMEOUT), stream=True)
66+ response = requests.get(url, proxies=proxy, timeout=float(CONNECTION_TIMEOUT), stream=True)
67 if sha256:
68 hasher = hashlib.sha256()
69 # Download until finished or canceled.
70@@ -244,21 +252,21 @@
71 """
72 self._base_url = base_url
73 self._file_name = file_name
74- self._download_cancelled = False
75+ self.was_cancelled = False
76 super().__init__()
77
78 def start(self):
79 """
80 Download the url to the temporary directory
81 """
82- if self._download_cancelled:
83+ if self.was_cancelled:
84 self.quit.emit()
85 return
86 try:
87 dest_path = Path(gettempdir()) / 'openlp' / self._file_name
88 url = '{url}{name}'.format(url=self._base_url, name=self._file_name)
89 is_success = download_file(self, url, dest_path)
90- if is_success and not self._download_cancelled:
91+ if is_success and not self.was_cancelled:
92 self.download_succeeded.emit(dest_path)
93 else:
94 self.download_failed.emit()
95@@ -273,4 +281,4 @@
96 """
97 A slot to allow the download to be cancelled from outside of the thread
98 """
99- self._download_cancelled = True
100+ self.was_cancelled = True
101
102=== modified file 'openlp/core/threading.py'
103--- openlp/core/threading.py 2019-02-14 15:09:09 +0000
104+++ openlp/core/threading.py 2019-02-27 22:20:41 +0000
105@@ -76,11 +76,11 @@
106 Get the worker by the thread name
107
108 :param str thread_name: The name of the thread
109- :returns: The worker for this thread name
110+ :returns: The worker for this thread name, or None
111 """
112 thread_info = Registry().get('application').worker_threads.get(thread_name)
113 if not thread_info:
114- raise KeyError('No thread named "{}" exists'.format(thread_name))
115+ return
116 return thread_info.get('worker')
117
118
119
120=== modified file 'openlp/core/ui/firsttimeform.py'
121--- openlp/core/ui/firsttimeform.py 2019-02-21 21:29:00 +0000
122+++ openlp/core/ui/firsttimeform.py 2019-02-27 22:20:41 +0000
123@@ -46,6 +46,7 @@
124 from openlp.core.threading import get_thread_worker, is_thread_finished, run_thread
125 from openlp.core.ui.firsttimewizard import FirstTimePage, UiFirstTimeWizard
126 from openlp.core.ui.icons import UiIcons
127+from openlp.core.widgets.widgets import ProxyDialog
128
129
130 log = logging.getLogger(__name__)
131@@ -91,7 +92,7 @@
132
133 class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
134 """
135- This is the Theme Import Wizard, which allows easy creation and editing of OpenLP themes.
136+ This is the FirstTimeWizard, designed to help new users to get up and running quickly.
137 """
138 log.info('ThemeWizardForm loaded')
139
140@@ -103,6 +104,7 @@
141 self.web_access = True
142 self.web = ''
143 self.setup_ui(self)
144+ self.customButtonClicked.connect(self._on_custom_button_clicked)
145 self.themes_list_widget.itemSelectionChanged.connect(self.on_themes_list_widget_selection_changed)
146 self.themes_deselect_all_button.clicked.connect(self.themes_list_widget.clearSelection)
147 self.themes_select_all_button.clicked.connect(self.themes_list_widget.selectAll)
148@@ -111,13 +113,13 @@
149 """
150 Returns the id of the next FirstTimePage to go to based on enabled plugins
151 """
152- if FirstTimePage.ScreenConfig < self.currentId() < FirstTimePage.Songs and self.songs_check_box.isChecked():
153+ if FirstTimePage.Download < self.currentId() < FirstTimePage.Songs and self.songs_check_box.isChecked():
154 # If the songs plugin is enabled then go to the songs page
155 return FirstTimePage.Songs
156- elif FirstTimePage.ScreenConfig < self.currentId() < FirstTimePage.Bibles and self.bible_check_box.isChecked():
157+ elif FirstTimePage.Download < self.currentId() < FirstTimePage.Bibles and self.bible_check_box.isChecked():
158 # Otherwise, if the Bibles plugin is enabled then go to the Bibles page
159 return FirstTimePage.Bibles
160- elif FirstTimePage.ScreenConfig < self.currentId() < FirstTimePage.Themes:
161+ elif FirstTimePage.Download < self.currentId() < FirstTimePage.Themes:
162 # Otherwise, if the current page is somewhere between the Welcome and the Themes pages, go to the themes
163 return FirstTimePage.Themes
164 else:
165@@ -133,9 +135,7 @@
166 if not self.web_access:
167 return FirstTimePage.NoInternet
168 else:
169- return FirstTimePage.Plugins
170- elif self.currentId() == FirstTimePage.Plugins:
171- return self.get_next_page_id()
172+ return FirstTimePage.Songs
173 elif self.currentId() == FirstTimePage.Progress:
174 return -1
175 elif self.currentId() == FirstTimePage.NoInternet:
176@@ -147,7 +147,7 @@
177 Run the wizard.
178 """
179 self.set_defaults()
180- return QtWidgets.QWizard.exec(self)
181+ return super().exec()
182
183 def initialize(self, screens):
184 """
185@@ -227,17 +227,13 @@
186 """
187 self.restart()
188 self.web = 'https://get.openlp.org/ftw/'
189- self.cancel_button.clicked.connect(self.on_cancel_button_clicked)
190- self.no_internet_finish_button.clicked.connect(self.on_no_internet_finish_button_clicked)
191- self.no_internet_cancel_button.clicked.connect(self.on_no_internet_cancel_button_clicked)
192 self.currentIdChanged.connect(self.on_current_id_changed)
193 Registry().register_function('config_screen_changed', self.screen_selection_widget.load)
194- self.no_internet_finish_button.setVisible(False)
195- self.no_internet_cancel_button.setVisible(False)
196 # Check if this is a re-run of the wizard.
197 self.has_run_wizard = Settings().value('core/has run wizard')
198 create_paths(Path(gettempdir(), 'openlp'))
199 self.theme_combo_box.clear()
200+ self.button(QtWidgets.QWizard.CustomButton1).setVisible(False)
201 if self.has_run_wizard:
202 self.songs_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songs').is_active())
203 self.bible_check_box.setChecked(self.plugin_manager.get_plugin_by_name('bibles').is_active())
204@@ -260,57 +256,85 @@
205 """
206 Detects Page changes and updates as appropriate.
207 """
208- # Keep track of the page we are at. Triggering "Cancel" causes page_id to be a -1.
209+ back_button = self.button(QtWidgets.QWizard.BackButton)
210+ cancel_button = self.button(QtWidgets.QWizard.CancelButton)
211+ internet_settings_button = self.button(QtWidgets.QWizard.CustomButton1)
212+ next_button = self.button(QtWidgets.QWizard.NextButton)
213+ back_button.setVisible(True)
214+ next_button.setVisible(True)
215+ internet_settings_button.setVisible(False)
216 self.application.process_events()
217- if page_id != -1:
218- self.last_id = page_id
219- if page_id == FirstTimePage.Download:
220- self.back_button.setVisible(False)
221- self.next_button.setVisible(False)
222- # Set the no internet page text.
223- if self.has_run_wizard:
224- self.no_internet_label.setText(self.no_internet_text)
225- else:
226- self.no_internet_label.setText(self.no_internet_text + self.cancel_wizard_text)
227+ if page_id == FirstTimePage.SampleOption:
228+ internet_settings_button.setVisible(True)
229+ elif page_id == FirstTimePage.Download:
230+ back_button.setVisible(False)
231+ next_button.setVisible(False)
232 self.application.set_busy_cursor()
233 self._download_index()
234 self.application.set_normal_cursor()
235- self.back_button.setVisible(False)
236- self.next_button.setVisible(True)
237 self.next()
238 elif page_id == FirstTimePage.NoInternet:
239- self.back_button.setVisible(False)
240- self.next_button.setVisible(False)
241- self.cancel_button.setVisible(False)
242- self.no_internet_finish_button.setVisible(True)
243- if self.has_run_wizard:
244- self.no_internet_cancel_button.setVisible(False)
245- else:
246- self.no_internet_cancel_button.setVisible(True)
247- elif page_id == FirstTimePage.Plugins:
248- self.back_button.setVisible(False)
249+ next_button.setVisible(False)
250+ cancel_button.setVisible(False)
251+ internet_settings_button.setVisible(True)
252 elif page_id == FirstTimePage.Progress:
253+ back_button.setVisible(False)
254+ next_button.setVisible(False)
255 self.application.set_busy_cursor()
256 self._pre_wizard()
257 self._perform_wizard()
258 self._post_wizard()
259 self.application.set_normal_cursor()
260
261- def on_cancel_button_clicked(self):
262- """
263- Process the triggering of the cancel button.
264+ def accept(self):
265+ """
266+ Called when the user clicks 'Finish'. Reimplement it to to save the plugin status
267+
268+ :rtype: None
269+ """
270+ self._set_plugin_status(self.songs_check_box, 'songs/status')
271+ self._set_plugin_status(self.bible_check_box, 'bibles/status')
272+ self._set_plugin_status(self.presentation_check_box, 'presentations/status')
273+ self._set_plugin_status(self.image_check_box, 'images/status')
274+ self._set_plugin_status(self.media_check_box, 'media/status')
275+ self._set_plugin_status(self.custom_check_box, 'custom/status')
276+ self._set_plugin_status(self.song_usage_check_box, 'songusage/status')
277+ self._set_plugin_status(self.alert_check_box, 'alerts/status')
278+ self.screen_selection_widget.save()
279+ if self.theme_combo_box.currentIndex() != -1:
280+ Settings().setValue('themes/global theme', self.theme_combo_box.currentText())
281+ super().accept()
282+
283+ def reject(self):
284+ """
285+ Called when the user clicks the cancel button. Reimplement it to clean up the threads.
286+
287+ :rtype: None
288 """
289 self.was_cancelled = True
290- if self.thumbnail_download_threads: # TODO: Use main thread list
291- for thread_name in self.thumbnail_download_threads:
292- worker = get_thread_worker(thread_name)
293- if worker:
294- worker.cancel_download()
295+ for thread_name in self.thumbnail_download_threads:
296+ worker = get_thread_worker(thread_name)
297+ if worker:
298+ worker.cancel_download()
299 # Was the thread created.
300 if self.thumbnail_download_threads:
301 while any([not is_thread_finished(thread_name) for thread_name in self.thumbnail_download_threads]):
302 time.sleep(0.1)
303 self.application.set_normal_cursor()
304+ super().reject()
305+
306+ def _on_custom_button_clicked(self, which):
307+ """
308+ Slot to handle the a click on one of the wizards custom buttons.
309+
310+ :param int QtWidgets.QWizard which: The button pressed
311+ :rtype: None
312+ """
313+ # Internet settings button
314+ if which == QtWidgets.QWizard.CustomButton1:
315+ proxy_dialog = ProxyDialog(self)
316+ proxy_dialog.retranslate_ui()
317+ proxy_dialog.exec()
318
319 def on_themes_list_widget_selection_changed(self):
320 """
321@@ -330,23 +354,6 @@
322 elif not item.isSelected() and cbox_index != -1:
323 self.theme_combo_box.removeItem(cbox_index)
324
325- def on_no_internet_finish_button_clicked(self):
326- """
327- Process the triggering of the "Finish" button on the No Internet page.
328- """
329- self.application.set_busy_cursor()
330- self._perform_wizard()
331- self.application.set_normal_cursor()
332- Settings().setValue('core/has run wizard', True)
333- self.close()
334-
335- def on_no_internet_cancel_button_clicked(self):
336- """
337- Process the triggering of the "Cancel" button on the No Internet page.
338- """
339- self.was_cancelled = True
340- self.close()
341-
342 def update_progress(self, count, block_size):
343 """
344 Calculate and display the download progress. This method is called by download_file().
345@@ -373,7 +380,7 @@
346 Prepare the UI for the process.
347 """
348 self.max_progress = 0
349- self.finish_button.setVisible(False)
350+ self.button(QtWidgets.QWizard.FinishButton).setEnabled(False)
351 self.application.process_events()
352 try:
353 # Loop through the songs list and increase for each selected item
354@@ -428,58 +435,36 @@
355 """
356 Clean up the UI after the process has finished.
357 """
358+ complete_str = ''
359 if self.max_progress:
360 self.progress_bar.setValue(self.progress_bar.maximum())
361 if self.has_run_wizard:
362 text = translate('OpenLP.FirstTimeWizard',
363- 'Download complete. Click the {button} button to return to OpenLP.'
364- ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
365- self.progress_label.setText(text)
366+ 'Download complete. Click the \'{finish_button}\' button to return to OpenLP.')
367 else:
368 text = translate('OpenLP.FirstTimeWizard',
369- 'Download complete. Click the {button} button to start OpenLP.'
370- ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
371- self.progress_label.setText(text)
372+ 'Download complete. Click the \'{finish_button}\' button to start OpenLP.')
373 else:
374 if self.has_run_wizard:
375- text = translate('OpenLP.FirstTimeWizard',
376- 'Click the {button} button to return to OpenLP.'
377- ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
378- self.progress_label.setText(text)
379+ text = translate('OpenLP.FirstTimeWizard', 'Click the \'{finish_button}\' button to return to OpenLP.')
380 else:
381- text = translate('OpenLP.FirstTimeWizard',
382- 'Click the {button} button to start OpenLP.'
383- ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
384- self.progress_label.setText(text)
385- self.finish_button.setVisible(True)
386- self.finish_button.setEnabled(True)
387- self.cancel_button.setVisible(False)
388- self.next_button.setVisible(False)
389+ text = translate('OpenLP.FirstTimeWizard', 'Click the \'{finish_button}\' button to start OpenLP.')
390+ self.progress_label.setText(text.format(finish_button=self.finish_button_text))
391+ self.button(QtWidgets.QWizard.FinishButton).setEnabled(True)
392+ self.button(QtWidgets.QWizard.CancelButton).setVisible(False)
393 self.application.process_events()
394
395 def _perform_wizard(self):
396 """
397 Run the tasks in the wizard.
398 """
399- # Set plugin states
400- self._increment_progress_bar(translate('OpenLP.FirstTimeWizard', 'Enabling selected plugins...'))
401- self._set_plugin_status(self.songs_check_box, 'songs/status')
402- self._set_plugin_status(self.bible_check_box, 'bibles/status')
403- self._set_plugin_status(self.presentation_check_box, 'presentations/status')
404- self._set_plugin_status(self.image_check_box, 'images/status')
405- self._set_plugin_status(self.media_check_box, 'media/status')
406- self._set_plugin_status(self.custom_check_box, 'custom/status')
407- self._set_plugin_status(self.song_usage_check_box, 'songusage/status')
408- self._set_plugin_status(self.alert_check_box, 'alerts/status')
409+
410 if self.web_access:
411 if not self._download_selected():
412 critical_error_message_box(translate('OpenLP.FirstTimeWizard', 'Download Error'),
413 translate('OpenLP.FirstTimeWizard', 'There was a connection problem while '
414 'downloading, so further downloads will be skipped. Try to re-run '
415 'the First Time Wizard later.'))
416- self.screen_selection_widget.save()
417- if self.theme_combo_box.currentIndex() != -1:
418- Settings().setValue('themes/global theme', self.theme_combo_box.currentText())
419
420 def _download_selected(self):
421 """
422
423=== modified file 'openlp/core/ui/firsttimewizard.py'
424--- openlp/core/ui/firsttimewizard.py 2019-02-15 22:34:53 +0000
425+++ openlp/core/ui/firsttimewizard.py 2019-02-27 22:20:41 +0000
426@@ -39,14 +39,15 @@
427 An enumeration class with each of the pages of the wizard.
428 """
429 Welcome = 0
430- ScreenConfig = 1
431- Download = 2
432- NoInternet = 3
433- Plugins = 4
434- Songs = 5
435- Bibles = 6
436- Themes = 7
437- Progress = 8
438+ Plugins = 1
439+ ScreenConfig = 2
440+ SampleOption = 3
441+ Download = 4
442+ NoInternet = 5
443+ Songs = 6
444+ Bibles = 7
445+ Themes = 8
446+ Progress = 9
447
448
449 class ThemeListWidget(QtWidgets.QListWidget):
450@@ -97,20 +98,13 @@
451 first_time_wizard.resize(550, 386)
452 first_time_wizard.setModal(True)
453 first_time_wizard.setOptions(QtWidgets.QWizard.IndependentPages | QtWidgets.QWizard.NoBackButtonOnStartPage |
454- QtWidgets.QWizard.NoBackButtonOnLastPage | QtWidgets.QWizard.HaveCustomButton1 |
455- QtWidgets.QWizard.HaveCustomButton2)
456+ QtWidgets.QWizard.NoBackButtonOnLastPage | QtWidgets.QWizard.HaveCustomButton1)
457 if is_macosx(): # pragma: nocover
458 first_time_wizard.setPixmap(QtWidgets.QWizard.BackgroundPixmap,
459 QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
460 first_time_wizard.resize(634, 386)
461 else:
462 first_time_wizard.setWizardStyle(QtWidgets.QWizard.ModernStyle)
463- self.finish_button = self.button(QtWidgets.QWizard.FinishButton)
464- self.no_internet_finish_button = self.button(QtWidgets.QWizard.CustomButton1)
465- self.cancel_button = self.button(QtWidgets.QWizard.CancelButton)
466- self.no_internet_cancel_button = self.button(QtWidgets.QWizard.CustomButton2)
467- self.next_button = self.button(QtWidgets.QWizard.NextButton)
468- self.back_button = self.button(QtWidgets.QWizard.BackButton)
469 add_welcome_page(first_time_wizard, ':/wizards/wizard_firsttime.bmp')
470 # The screen config page
471 self.screen_page = QtWidgets.QWizardPage()
472@@ -121,6 +115,18 @@
473 self.screen_selection_widget.load()
474 self.screen_page_layout.addRow(self.screen_selection_widget)
475 first_time_wizard.setPage(FirstTimePage.ScreenConfig, self.screen_page)
476+ # Download Samples page
477+ self.resource_page = QtWidgets.QWizardPage()
478+ self.resource_page.setObjectName('resource_page')
479+ self.resource_page.setFinalPage(True)
480+ self.resource_layout = QtWidgets.QVBoxLayout(self.resource_page)
481+ self.resource_layout.setContentsMargins(50, 20, 50, 20)
482+ self.resource_layout.setObjectName('resource_layout')
483+ self.resource_label = QtWidgets.QLabel(self.resource_page)
484+ self.resource_label.setObjectName('resource_label')
485+ self.resource_label.setWordWrap(True)
486+ self.resource_layout.addWidget(self.resource_label)
487+ first_time_wizard.setPage(FirstTimePage.SampleOption, self.resource_page)
488 # The download page
489 self.download_page = QtWidgets.QWizardPage()
490 self.download_page.setObjectName('download_page')
491@@ -134,6 +140,7 @@
492 # The "you don't have an internet connection" page.
493 self.no_internet_page = QtWidgets.QWizardPage()
494 self.no_internet_page.setObjectName('no_internet_page')
495+ self.no_internet_page.setFinalPage(True)
496 self.no_internet_layout = QtWidgets.QVBoxLayout(self.no_internet_page)
497 self.no_internet_layout.setContentsMargins(50, 30, 50, 40)
498 self.no_internet_layout.setObjectName('no_internet_layout')
499@@ -242,27 +249,32 @@
500 self.progress_bar.setObjectName('progress_bar')
501 self.progress_layout.addWidget(self.progress_bar)
502 first_time_wizard.setPage(FirstTimePage.Progress, self.progress_page)
503- self.retranslate_ui(first_time_wizard)
504+ self.retranslate_ui()
505
506- def retranslate_ui(self, first_time_wizard):
507+ def retranslate_ui(self):
508 """
509 Translate the UI on the fly
510
511 :param first_time_wizard: The wizard form
512 """
513- first_time_wizard.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard'))
514+ self.finish_button_text = clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton))
515+ back_button_text = clean_button_text(self.buttonText(QtWidgets.QWizard.BackButton))
516+ next_button_text = clean_button_text(self.buttonText(QtWidgets.QWizard.NextButton))
517+
518+ self.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard'))
519 text = translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard')
520- first_time_wizard.title_label.setText('<span style="font-size:14pt; font-weight:600;">{text}'
521- '</span>'.format(text=text))
522- button = clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.NextButton))
523- first_time_wizard.information_label.setText(
524+ self.title_label.setText('<span style="font-size:14pt; font-weight:600;">{text}</span>'.format(text=text))
525+ self.information_label.setText(
526 translate('OpenLP.FirstTimeWizard', 'This wizard will help you to configure OpenLP for initial use. '
527- 'Click the {button} button below to start.').format(button=button))
528+ 'Click the \'{next_button}\' button below to start.'
529+ ).format(next_button=next_button_text))
530+ self.setButtonText(
531+ QtWidgets.QWizard.CustomButton1, translate('OpenLP.FirstTimeWizard', 'Internet Settings'))
532 self.download_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Downloading Resource Index'))
533- self.download_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Please wait while the resource index is '
534- 'downloaded.'))
535- self.download_label.setText(translate('OpenLP.FirstTimeWizard', 'Please wait while OpenLP downloads the '
536- 'resource index file...'))
537+ self.download_page.setSubTitle(translate('OpenLP.FirstTimeWizard',
538+ 'Please wait while the resource index is downloaded.'))
539+ self.download_label.setText(translate('OpenLP.FirstTimeWizard',
540+ 'Please wait while OpenLP downloads the resource index file...'))
541 self.plugin_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Select parts of the program you wish to use'))
542 self.plugin_page.setSubTitle(translate('OpenLP.FirstTimeWizard',
543 'You can also change these settings after the Wizard.'))
544@@ -270,11 +282,10 @@
545 self.screen_page.setSubTitle(translate('OpenLP.FirstTimeWizard',
546 'Choose the main display screen for OpenLP.'))
547 self.songs_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
548- self.custom_check_box.setText(translate('OpenLP.FirstTimeWizard',
549- 'Custom Slides – Easier to manage than songs and they have their own'
550- ' list of slides'))
551- self.bible_check_box.setText(translate('OpenLP.FirstTimeWizard',
552- 'Bibles – Import and show Bibles'))
553+ self.custom_check_box.setText(
554+ translate('OpenLP.FirstTimeWizard',
555+ 'Custom Slides – Easier to manage than songs and they have their own list of slides'))
556+ self.bible_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Bibles – Import and show Bibles'))
557 self.image_check_box.setText(translate('OpenLP.FirstTimeWizard',
558 'Images – Show images or replace background with them'))
559 self.presentation_check_box.setText(translate('OpenLP.FirstTimeWizard',
560@@ -283,22 +294,25 @@
561 self.song_usage_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Song Usage Monitor'))
562 self.alert_check_box.setText(translate('OpenLP.FirstTimeWizard',
563 'Alerts – Display informative messages while showing other slides'))
564+ self.resource_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Resource Data'))
565+ self.resource_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Can OpenLP download some resource data?'))
566+ self.resource_label.setText(
567+ translate('OpenLP.FirstTimeWizard',
568+ 'OpenLP has collected some resources that we have permission to distribute.\n\n'
569+ 'If you would like to download some of these resources click the \'{next_button}\' button, '
570+ 'otherwise click the \'{finish_button}\' button.'
571+ ).format(next_button=next_button_text, finish_button=self.finish_button_text))
572 self.no_internet_page.setTitle(translate('OpenLP.FirstTimeWizard', 'No Internet Connection'))
573- self.no_internet_page.setSubTitle(
574- translate('OpenLP.FirstTimeWizard', 'Unable to detect an Internet connection.'))
575- button = clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.FinishButton))
576- self.no_internet_text = translate('OpenLP.FirstTimeWizard',
577- 'No Internet connection was found. The First Time Wizard needs an Internet '
578- 'connection in order to be able to download sample songs, Bibles and themes.'
579- ' Click the {button} button now to start OpenLP with initial settings and '
580- 'no sample data.\n\nTo re-run the First Time Wizard and import this sample '
581- 'data at a later time, check your Internet connection and re-run this '
582- 'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.'
583- ).format(button=button)
584- button = clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.CancelButton))
585- self.cancel_wizard_text = translate('OpenLP.FirstTimeWizard',
586- '\n\nTo cancel the First Time Wizard completely (and not start OpenLP), '
587- 'click the {button} button now.').format(button=button)
588+ self.no_internet_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Cannot connect to the internet.'))
589+ self.no_internet_label.setText(
590+ translate('OpenLP.FirstTimeWizard',
591+ 'OpenLP could not connect to the internet to get information about the sample data available.\n\n'
592+ 'Please check your internet connection. If your church uses a proxy server click the '
593+ '\'Internet Settings\' button below and enter the server details there.\n\nClick the '
594+ '\'{back_button}\' button to try again.\n\nIf you click the \'{finish_button}\' '
595+ 'button you can download the data at a later time by selecting \'Re-run First Time Wizard\' '
596+ 'from the \'Tools\' menu in OpenLP.'
597+ ).format(back_button=back_button_text, finish_button=self.finish_button_text))
598 self.songs_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Songs'))
599 self.songs_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select and download public domain songs.'))
600 self.bibles_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Bibles'))
601@@ -310,13 +324,8 @@
602 self.themes_select_all_button.setToolTip(translate('OpenLP.FirstTimeWizard', 'Select all'))
603 self.themes_deselect_all_button.setToolTip(translate('OpenLP.FirstTimeWizard', 'Deselect all'))
604 self.progress_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Downloading and Configuring'))
605- self.progress_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Please wait while resources are downloaded '
606- 'and OpenLP is configured.'))
607- self.progress_label.setText(translate('OpenLP.FirstTimeWizard', 'Starting configuration process...'))
608- first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton1,
609- clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.FinishButton)))
610- first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton2,
611- clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.CancelButton)))
612+ self.progress_page.setSubTitle(
613+ translate('OpenLP.FirstTimeWizard', 'Please wait while resources are downloaded and OpenLP is configured.'))
614
615 def on_projectors_check_box_clicked(self):
616 # When clicking projectors_check box, change the visibility setting for Projectors panel.
617
618=== modified file 'openlp/core/ui/mainwindow.py'
619--- openlp/core/ui/mainwindow.py 2019-02-14 15:09:09 +0000
620+++ openlp/core/ui/mainwindow.py 2019-02-27 22:20:41 +0000
621@@ -681,8 +681,7 @@
622 return
623 first_run_wizard = FirstTimeForm(self)
624 first_run_wizard.initialize(ScreenList())
625- first_run_wizard.exec()
626- if first_run_wizard.was_cancelled:
627+ if first_run_wizard.exec() == QtWidgets.QDialog.Rejected:
628 return
629 self.application.set_busy_cursor()
630 self.first_time()
631
632=== modified file 'openlp/core/widgets/widgets.py'
633--- openlp/core/widgets/widgets.py 2019-02-14 15:09:09 +0000
634+++ openlp/core/widgets/widgets.py 2019-02-27 22:20:41 +0000
635@@ -150,6 +150,34 @@
636 settings.setValue('advanced/proxy password', self.password_edit.text())
637
638
639+class ProxyDialog(QtWidgets.QDialog):
640+ """
641+ A basic dialog to show proxy settingd
642+ """
643+ def __init__(self, *args, **kwargs):
644+ super().__init__(*args, **kwargs)
645+ self.layout = QtWidgets.QVBoxLayout(self)
646+ self.proxy_widget = ProxyWidget(self)
647+ self.layout.addWidget(self.proxy_widget)
648+ self.button_box = \
649+ QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, self)
650+ self.layout.addWidget(self.button_box)
651+ self.button_box.accepted.connect(self.accept)
652+ self.button_box.rejected.connect(self.reject)
653+
654+ def accept(self):
655+ """
656+ Reimplement the the accept slot so that the ProxyWidget settings can be saved.
657+ :rtype: None
658+ """
659+ self.proxy_widget.save()
660+ super().accept()
661+
662+ def retranslate_ui(self):
663+ self.proxy_widget.retranslate_ui()
664+ self.setWindowTitle(translate('OpenLP.ProxyDialog', 'Proxy Server Settings'))
665+
666+
667 class ScreenButton(QtWidgets.QPushButton):
668 """
669 A special button class that holds the screen information about it
670
671=== modified file 'openlp/plugins/songs/lib/importers/openlp.py'
672--- openlp/plugins/songs/lib/importers/openlp.py 2019-02-14 15:09:09 +0000
673+++ openlp/plugins/songs/lib/importers/openlp.py 2019-02-27 22:20:41 +0000
674@@ -106,7 +106,7 @@
675 pass
676
677 # Check the file type
678- if not isinstance(self.import_source, str) or not self.import_source.endswith('.sqlite'):
679+ if self.import_source.suffix != '.sqlite':
680 self.log_error(self.import_source, translate('SongsPlugin.OpenLPSongImport',
681 'Not a valid OpenLP 2 song database.'))
682 return
683
684=== modified file 'openlp/plugins/songs/reporting.py'
685--- openlp/plugins/songs/reporting.py 2019-02-14 15:09:09 +0000
686+++ openlp/plugins/songs/reporting.py 2019-02-27 22:20:41 +0000
687@@ -49,13 +49,6 @@
688 Path(translate('SongPlugin.ReportSongList', 'song_extract.csv')),
689 translate('SongPlugin.ReportSongList', 'CSV format (*.csv)'))
690
691- if report_file_path is None:
692- main_window.error_message(
693- translate('SongPlugin.ReportSongList', 'Output Path Not Selected'),
694- translate('SongPlugin.ReportSongList', 'You have not set a valid output location for your report. \n'
695- 'Please select an existing path on your computer.')
696- )
697- return
698 report_file_path.with_suffix('.csv')
699 Registry().get('application').set_busy_cursor()
700 try:
701
702=== modified file 'run_openlp.py' (properties changed: +x to -x)
703=== modified file 'setup.py' (properties changed: +x to -x)
704=== modified file 'tests/functional/openlp_core/common/test_httputils.py'
705--- tests/functional/openlp_core/common/test_httputils.py 2019-02-14 15:09:09 +0000
706+++ tests/functional/openlp_core/common/test_httputils.py 2019-02-27 22:20:41 +0000
707@@ -224,7 +224,7 @@
708 file_size = get_url_file_size(fake_url)
709
710 # THEN: The correct methods are called with the correct arguments and a web page is returned
711- mocked_requests.head.assert_called_once_with(fake_url, allow_redirects=True, timeout=30.0)
712+ mocked_requests.head.assert_called_once_with(fake_url, allow_redirects=True, proxies=None, timeout=30.0)
713 assert file_size == 100
714
715 @patch('openlp.core.common.httputils.requests')
716
717=== modified file 'tests/functional/openlp_core/test_threading.py'
718--- tests/functional/openlp_core/test_threading.py 2019-02-14 15:09:09 +0000
719+++ tests/functional/openlp_core/test_threading.py 2019-02-27 22:20:41 +0000
720@@ -133,15 +133,11 @@
721 # GIVEN: A mocked thread worker
722 MockRegistry.return_value.get.return_value.worker_threads = {}
723
724- try:
725- # WHEN: get_thread_worker() is called
726- get_thread_worker('test_thread')
727- assert False, 'A KeyError should have been raised'
728- except KeyError:
729- # THEN: The mocked worker is returned
730- pass
731- except Exception:
732- assert False, 'A KeyError should have been raised'
733+ # WHEN: get_thread_worker() is called
734+ result = get_thread_worker('test_thread')
735+
736+ # THEN: None should have been returned
737+ assert result is None
738
739
740 @patch('openlp.core.threading.Registry')
741
742=== modified file 'tests/functional/openlp_core/ui/test_firsttimeform.py'
743--- tests/functional/openlp_core/ui/test_firsttimeform.py 2019-02-16 08:57:11 +0000
744+++ tests/functional/openlp_core/ui/test_firsttimeform.py 2019-02-27 22:20:41 +0000
745@@ -27,6 +27,8 @@
746 from unittest import TestCase
747 from unittest.mock import MagicMock, call, patch, DEFAULT
748
749+from PyQt5 import QtWidgets
750+
751 from openlp.core.common.path import Path
752 from openlp.core.common.registry import Registry
753 from openlp.core.ui.firsttimeform import FirstTimeForm, ThemeListWidgetItem
754@@ -120,10 +122,23 @@
755 # THEN: The screens should be set up, and the default values initialised
756 assert expected_screens == frw.screens, 'The screens should be correct'
757 assert frw.web_access is True, 'The default value of self.web_access should be True'
758- assert frw.was_cancelled is False, 'The default value of self.was_cancelled should be False'
759 assert [] == frw.thumbnail_download_threads, 'The list of threads should be empty'
760 assert frw.has_run_wizard is False, 'has_run_wizard should be False'
761
762+ @patch('openlp.core.ui.firsttimewizard.QtWidgets.QWizard.exec')
763+ def test_exec(self, mocked_qwizard_exec):
764+
765+ # GIVEN: An instance of FirstTimeForm
766+ frw = FirstTimeForm(None)
767+ with patch.object(frw, 'set_defaults') as mocked_set_defaults:
768+
769+ # WHEN: exec is called
770+ frw.exec()
771+
772+ # THEN: The wizard should be reset and the exec methon on the super class should have been called
773+ mocked_set_defaults.assert_called_once()
774+ mocked_qwizard_exec.assert_called_once()
775+
776 def test_set_defaults(self):
777 """
778 Test that the default values are set when set_defaults() is run
779@@ -134,8 +149,6 @@
780 mocked_settings = MagicMock()
781 mocked_settings.value.side_effect = lambda key: {'core/has run wizard': False}[key]
782 with patch.object(frw, 'restart') as mocked_restart, \
783- patch.object(frw, 'cancel_button') as mocked_cancel_button, \
784- patch.object(frw, 'no_internet_finish_button') as mocked_no_internet_finish_btn, \
785 patch.object(frw, 'currentIdChanged') as mocked_currentIdChanged, \
786 patch.object(frw, 'theme_combo_box') as mocked_theme_combo_box, \
787 patch.object(frw, 'songs_check_box') as mocked_songs_check_box, \
788@@ -153,12 +166,8 @@
789 # THEN: The default values should have been set
790 mocked_restart.assert_called_once()
791 assert 'https://get.openlp.org/ftw/' == frw.web, 'The default URL should be set'
792- mocked_cancel_button.clicked.connect.assert_called_once_with(frw.on_cancel_button_clicked)
793- mocked_no_internet_finish_btn.clicked.connect.assert_called_once_with(
794- frw.on_no_internet_finish_button_clicked)
795 mocked_currentIdChanged.connect.assert_called_once_with(frw.on_current_id_changed)
796 mocked_register_function.assert_called_once_with('config_screen_changed', frw.screen_selection_widget.load)
797- mocked_no_internet_finish_btn.setVisible.assert_called_once_with(False)
798 mocked_settings.value.assert_has_calls([call('core/has run wizard')])
799 mocked_gettempdir.assert_called_once()
800 mocked_create_paths.assert_called_once_with(Path('temp', 'openlp'))
801@@ -177,8 +186,6 @@
802 mocked_settings.value.side_effect = \
803 lambda key: {'core/has run wizard': True, 'themes/global theme': 'Default Theme'}[key]
804 with patch.object(frw, 'restart') as mocked_restart, \
805- patch.object(frw, 'cancel_button') as mocked_cancel_button, \
806- patch.object(frw, 'no_internet_finish_button') as mocked_no_internet_finish_btn, \
807 patch.object(frw, 'currentIdChanged') as mocked_currentIdChanged, \
808 patch.object(frw, 'theme_combo_box', **{'findText.return_value': 3}) as mocked_theme_combo_box, \
809 patch.multiple(frw, songs_check_box=DEFAULT, bible_check_box=DEFAULT, presentation_check_box=DEFAULT,
810@@ -200,12 +207,8 @@
811 # THEN: The default values should have been set
812 mocked_restart.assert_called_once()
813 assert 'https://get.openlp.org/ftw/' == frw.web, 'The default URL should be set'
814- mocked_cancel_button.clicked.connect.assert_called_once_with(frw.on_cancel_button_clicked)
815- mocked_no_internet_finish_btn.clicked.connect.assert_called_once_with(
816- frw.on_no_internet_finish_button_clicked)
817 mocked_currentIdChanged.connect.assert_called_once_with(frw.on_current_id_changed)
818 mocked_register_function.assert_called_once_with('config_screen_changed', frw.screen_selection_widget.load)
819- mocked_no_internet_finish_btn.setVisible.assert_called_once_with(False)
820 mocked_settings.value.assert_has_calls([call('core/has run wizard'), call('themes/global theme')])
821 mocked_gettempdir.assert_called_once()
822 mocked_create_paths.assert_called_once_with(Path('temp', 'openlp'))
823@@ -219,12 +222,79 @@
824 mocked_theme_combo_box.findText.assert_called_once_with('Default Theme')
825 mocked_theme_combo_box.setCurrentIndex(3)
826
827+ @patch('openlp.core.ui.firsttimewizard.QtWidgets.QWizard.accept')
828+ @patch('openlp.core.ui.firsttimewizard.Settings')
829+ def test_accept_method(self, mocked_settings, mocked_qwizard_accept):
830+ """
831+ Test the FirstTimeForm.accept method
832+ """
833+ # GIVEN: An instance of FirstTimeForm
834+ frw = FirstTimeForm(None)
835+ with patch.object(frw, '_set_plugin_status') as mocked_set_plugin_status, \
836+ patch.multiple(frw, songs_check_box=DEFAULT, bible_check_box=DEFAULT, presentation_check_box=DEFAULT,
837+ image_check_box=DEFAULT, media_check_box=DEFAULT, custom_check_box=DEFAULT,
838+ song_usage_check_box=DEFAULT, alert_check_box=DEFAULT) as mocked_check_boxes, \
839+ patch.object(frw, 'screen_selection_widget') as mocked_screen_selection_widget:
840+
841+ # WHEN: Calling accept
842+ frw.accept()
843+
844+ # THEN: The selected plugins should be enabled, the screen selection saved and the super method called
845+ mocked_set_plugin_status.assert_has_calls([
846+ call(mocked_check_boxes['songs_check_box'], 'songs/status'),
847+ call(mocked_check_boxes['bible_check_box'], 'bibles/status'),
848+ call(mocked_check_boxes['presentation_check_box'], 'presentations/status'),
849+ call(mocked_check_boxes['image_check_box'], 'images/status'),
850+ call(mocked_check_boxes['media_check_box'], 'media/status'),
851+ call(mocked_check_boxes['custom_check_box'], 'custom/status'),
852+ call(mocked_check_boxes['song_usage_check_box'], 'songusage/status'),
853+ call(mocked_check_boxes['alert_check_box'], 'alerts/status')])
854+ mocked_screen_selection_widget.save.assert_called_once()
855+ mocked_qwizard_accept.assert_called_once()
856+
857+ @patch('openlp.core.ui.firsttimewizard.Settings')
858+ def test_accept_method_theme_not_selected(self, mocked_settings):
859+ """
860+ Test the FirstTimeForm.accept method when there is no default theme selected
861+ """
862+ # GIVEN: An instance of FirstTimeForm
863+ frw = FirstTimeForm(None)
864+ with patch.object(frw, '_set_plugin_status'), \
865+ patch.object(frw, 'screen_selection_widget'), \
866+ patch.object(frw, 'theme_combo_box', **{'currentIndex.return_value': '-1'}):
867+
868+ # WHEN: Calling accept and the currentIndex method of the theme_combo_box returns -1
869+ frw.accept()
870+
871+ # THEN: OpenLP should not try to save a theme name
872+ mocked_settings.setValue.assert_not_called()
873+
874+ @patch('openlp.core.ui.firsttimeform.Settings')
875+ def test_accept_method_theme_selected(self, mocked_settings):
876+ """
877+ Test the FirstTimeForm.accept method when a default theme is selected
878+ """
879+ # GIVEN: An instance of FirstTimeForm
880+ frw = FirstTimeForm(None)
881+ with patch.object(frw, '_set_plugin_status'), \
882+ patch.object(frw, 'screen_selection_widget'), \
883+ patch.object(
884+ frw, 'theme_combo_box', **{'currentIndex.return_value': 0, 'currentText.return_value': 'Test Item'}):
885+
886+ # WHEN: Calling accept and the currentIndex method of the theme_combo_box returns 0
887+ frw.accept()
888+
889+ # THEN: The 'currentItem' in the combobox should have been set as the default theme.
890+ mocked_settings().setValue.assert_called_once_with('themes/global theme', 'Test Item')
891+
892+ @patch('openlp.core.ui.firsttimewizard.QtWidgets.QWizard.reject')
893 @patch('openlp.core.ui.firsttimeform.time')
894 @patch('openlp.core.ui.firsttimeform.get_thread_worker')
895 @patch('openlp.core.ui.firsttimeform.is_thread_finished')
896- def test_on_cancel_button_clicked(self, mocked_is_thread_finished, mocked_get_thread_worker, mocked_time):
897+ def test_reject_method(
898+ self, mocked_is_thread_finished, mocked_get_thread_worker, mocked_time, mocked_qwizard_reject):
899 """
900- Test that the cancel button click slot shuts down the threads correctly
901+ Test that the reject method shuts down the threads correctly
902 """
903 # GIVEN: A FRW, some mocked threads and workers (that isn't quite done) and other mocked stuff
904 mocked_worker = MagicMock()
905@@ -235,17 +305,47 @@
906 frw.thumbnail_download_threads = ['test_thread']
907 with patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor:
908
909- # WHEN: on_cancel_button_clicked() is called
910- frw.on_cancel_button_clicked()
911+ # WHEN: the reject method is called
912+ frw.reject()
913
914 # THEN: The right things should be called in the right order
915- assert frw.was_cancelled is True, 'The was_cancelled property should have been set to True'
916 mocked_get_thread_worker.assert_called_once_with('test_thread')
917 mocked_worker.cancel_download.assert_called_once()
918 mocked_is_thread_finished.assert_called_with('test_thread')
919 assert mocked_is_thread_finished.call_count == 2, 'isRunning() should have been called twice'
920 mocked_time.sleep.assert_called_once_with(0.1)
921- mocked_set_normal_cursor.assert_called_once_with()
922+ mocked_set_normal_cursor.assert_called_once()
923+ mocked_qwizard_reject.assert_called_once()
924+
925+ @patch('openlp.core.ui.firsttimeform.ProxyDialog')
926+ def test_on_custom_button_clicked(self, mocked_proxy_dialog):
927+ """
928+ Test _on_custom_button when it is called whe the 'internet settings' (CustomButton1) button is not clicked.
929+ """
930+ # GIVEN: An instance of the FirstTimeForm
931+ frw = FirstTimeForm(None)
932+
933+ # WHEN: Calling _on_custom_button_clicked with a different button to the 'internet settings button.
934+ frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton2)
935+
936+ # THEN: The ProxyDialog should not be shown.
937+ mocked_proxy_dialog.assert_not_called()
938+
939+ @patch('openlp.core.ui.firsttimeform.ProxyDialog')
940+ def test_on_custom_button_clicked_internet_settings(self, mocked_proxy_dialog):
941+ """
942+ Test _on_custom_button when it is called when the 'internet settings' (CustomButton1) button is clicked.
943+ """
944+ # GIVEN: An instance of the FirstTimeForm
945+ frw = FirstTimeForm(None)
946+
947+ # WHEN: Calling _on_custom_button_clicked with the constant for the 'internet settings' button (CustomButton1)
948+ frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton1)
949+
950+ # THEN: The ProxyDialog should be shown.
951+ mocked_proxy_dialog.assert_called_with(frw)
952+ mocked_proxy_dialog().retranslate_ui.assert_called_once()
953+ mocked_proxy_dialog().exec.assert_called_once()
954
955 @patch('openlp.core.ui.firsttimeform.critical_error_message_box')
956 def test__parse_config_invalid_config(self, mocked_critical_error_message_box):
957
958=== modified file 'tests/functional/openlp_plugins/songs/test_openlpimporter.py'
959--- tests/functional/openlp_plugins/songs/test_openlpimporter.py 2019-02-14 15:09:09 +0000
960+++ tests/functional/openlp_plugins/songs/test_openlpimporter.py 2019-02-27 22:20:41 +0000
961@@ -22,6 +22,7 @@
962 """
963 This module contains tests for the OpenLP song importer.
964 """
965+from pathlib import Path
966 from unittest import TestCase
967 from unittest.mock import MagicMock, patch
968
969@@ -66,10 +67,9 @@
970 importer.stop_import_flag = True
971
972 # WHEN: Import source is not a list
973- for source in ['not a list', 0]:
974- importer.import_source = source
975+ importer.import_source = Path()
976
977- # THEN: do_import should return none and the progress bar maximum should not be set.
978- assert importer.do_import() is None, 'do_import should return None when import_source is not a list'
979- assert mocked_import_wizard.progress_bar.setMaximum.called is False, \
980- 'setMaximum on import_wizard.progress_bar should not have been called'
981+ # THEN: do_import should return none and the progress bar maximum should not be set.
982+ assert importer.do_import() is None, 'do_import should return None when import_source is not a list'
983+ assert mocked_import_wizard.progress_bar.setMaximum.called is False, \
984+ 'setMaximum on import_wizard.progress_bar should not have been called'