Merge lp:~phill-ridout/openlp/path_edit into lp:openlp

Proposed by Phill
Status: Superseded
Proposed branch: lp:~phill-ridout/openlp/path_edit
Merge into: lp:openlp
Diff against target: 1488 lines (+632/-345) (has conflicts)
17 files modified
openlp/core/common/__init__.py (+1/-1)
openlp/core/lib/theme.py (+1/-1)
openlp/core/ui/advancedtab.py (+13/-78)
openlp/core/ui/generaltab.py (+11/-41)
openlp/core/ui/lib/__init__.py (+8/-6)
openlp/core/ui/lib/colorbutton.py (+1/-1)
openlp/core/ui/lib/pathedit.py (+197/-0)
openlp/core/ui/themeform.py (+18/-39)
openlp/core/ui/themewizard.py (+7/-21)
openlp/plugins/bibles/forms/bibleimportform.py (+8/-15)
openlp/plugins/presentations/lib/presentationtab.py (+16/-51)
openlp/plugins/songusage/forms/songusagedetaildialog.py (+5/-10)
openlp/plugins/songusage/forms/songusagedetailform.py (+4/-9)
tests/functional/openlp_core_ui/test_themeform.py (+17/-56)
tests/functional/openlp_core_ui_lib/test_color_button.py (+10/-13)
tests/functional/openlp_core_ui_lib/test_path_edit.py (+311/-0)
tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py (+4/-3)
Text conflict in openlp/plugins/presentations/lib/presentationtab.py
To merge this branch: bzr merge lp:~phill-ridout/openlp/path_edit
Reviewer Review Type Date Requested Status
Tomas Groth Needs Fixing
Tim Bentley Approve
Review via email: mp+324026@code.launchpad.net

This proposal supersedes a proposal from 2017-05-13.

This proposal has been superseded by a proposal from 2017-05-22.

Description of the change

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

You tracking head as you have conflicts!

review: Needs Fixing
Revision history for this message
Phill (phill-ridout) wrote :

I had merged with trunk, but forgot to update trunk!

Revision history for this message
Tim Bentley (trb143) wrote :

Looks good

review: Approve
Revision history for this message
Tomas Groth (tomasgroth) wrote :

Just tested the selection of custom pdf-bin, and the mask "*.*" causes issues since it filters out all files that does not contain a "."
So the all-files mask should maybe just be "*"?

review: Needs Fixing
lp:~phill-ridout/openlp/path_edit updated
2738. By Phill

Changed the allfiles filter from *.* to *

2739. By Phill

Added some extra params to the constructor

2740. By Phill

Head

2741. By Phill

More all file filters

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/common/__init__.py'
2--- openlp/core/common/__init__.py 2017-05-15 10:24:28 +0000
3+++ openlp/core/common/__init__.py 2017-05-22 16:32:39 +0000
4@@ -442,7 +442,7 @@
5 """
6 Function that checks whether a binary exists.
7
8- :param program_path:The full path to the binary to check.
9+ :param program_path: The full path to the binary to check.
10 :return: program output to be parsed
11 """
12 log.debug('testing program_path: {text}'.format(text=program_path))
13
14=== modified file 'openlp/core/lib/theme.py'
15--- openlp/core/lib/theme.py 2016-12-31 11:01:36 +0000
16+++ openlp/core/lib/theme.py 2017-05-22 16:32:39 +0000
17@@ -164,7 +164,7 @@
18 jsn = get_text_file_string(json_file)
19 jsn = json.loads(jsn)
20 self.expand_json(jsn)
21- self.background_filename = None
22+ self.background_filename = ''
23
24 def expand_json(self, var, prev=None):
25 """
26
27=== modified file 'openlp/core/ui/advancedtab.py'
28--- openlp/core/ui/advancedtab.py 2016-12-31 11:01:36 +0000
29+++ openlp/core/ui/advancedtab.py 2017-05-22 16:32:39 +0000
30@@ -25,13 +25,13 @@
31 from datetime import datetime, timedelta
32 import logging
33 import os
34-import sys
35
36 from PyQt5 import QtCore, QtGui, QtWidgets
37
38 from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate
39+from openlp.core.common.languagemanager import format_time
40 from openlp.core.lib import SettingsTab, build_icon
41-from openlp.core.common.languagemanager import format_time
42+from openlp.core.ui.lib import PathEdit, PathType
43
44 log = logging.getLogger(__name__)
45
46@@ -153,32 +153,18 @@
47 self.data_directory_group_box.setObjectName('data_directory_group_box')
48 self.data_directory_layout = QtWidgets.QFormLayout(self.data_directory_group_box)
49 self.data_directory_layout.setObjectName('data_directory_layout')
50- self.data_directory_current_label = QtWidgets.QLabel(self.data_directory_group_box)
51- self.data_directory_current_label.setObjectName('data_directory_current_label')
52- self.data_directory_label = QtWidgets.QLabel(self.data_directory_group_box)
53- self.data_directory_label.setObjectName('data_directory_label')
54 self.data_directory_new_label = QtWidgets.QLabel(self.data_directory_group_box)
55 self.data_directory_new_label.setObjectName('data_directory_current_label')
56- self.new_data_directory_edit = QtWidgets.QLineEdit(self.data_directory_group_box)
57- self.new_data_directory_edit.setObjectName('new_data_directory_edit')
58- self.new_data_directory_edit.setReadOnly(True)
59+ self.data_directory_path_edit = PathEdit(self.data_directory_group_box)
60+ self.data_directory_path_edit.path_type = PathType.Directories
61+ self.data_directory_path_edit.default_path = AppLocation.get_directory(AppLocation.DataDir)
62+ self.data_directory_layout.addRow(self.data_directory_new_label, self.data_directory_path_edit)
63 self.new_data_directory_has_files_label = QtWidgets.QLabel(self.data_directory_group_box)
64 self.new_data_directory_has_files_label.setObjectName('new_data_directory_has_files_label')
65 self.new_data_directory_has_files_label.setWordWrap(True)
66- self.data_directory_browse_button = QtWidgets.QToolButton(self.data_directory_group_box)
67- self.data_directory_browse_button.setObjectName('data_directory_browse_button')
68- self.data_directory_browse_button.setIcon(build_icon(':/general/general_open.png'))
69- self.data_directory_default_button = QtWidgets.QToolButton(self.data_directory_group_box)
70- self.data_directory_default_button.setObjectName('data_directory_default_button')
71- self.data_directory_default_button.setIcon(build_icon(':/general/general_revert.png'))
72 self.data_directory_cancel_button = QtWidgets.QToolButton(self.data_directory_group_box)
73 self.data_directory_cancel_button.setObjectName('data_directory_cancel_button')
74 self.data_directory_cancel_button.setIcon(build_icon(':/general/general_delete.png'))
75- self.new_data_directory_label_layout = QtWidgets.QHBoxLayout()
76- self.new_data_directory_label_layout.setObjectName('new_data_directory_label_layout')
77- self.new_data_directory_label_layout.addWidget(self.new_data_directory_edit)
78- self.new_data_directory_label_layout.addWidget(self.data_directory_browse_button)
79- self.new_data_directory_label_layout.addWidget(self.data_directory_default_button)
80 self.data_directory_copy_check_layout = QtWidgets.QHBoxLayout()
81 self.data_directory_copy_check_layout.setObjectName('data_directory_copy_check_layout')
82 self.data_directory_copy_check_box = QtWidgets.QCheckBox(self.data_directory_group_box)
83@@ -186,8 +172,6 @@
84 self.data_directory_copy_check_layout.addWidget(self.data_directory_copy_check_box)
85 self.data_directory_copy_check_layout.addStretch()
86 self.data_directory_copy_check_layout.addWidget(self.data_directory_cancel_button)
87- self.data_directory_layout.addRow(self.data_directory_current_label, self.data_directory_label)
88- self.data_directory_layout.addRow(self.data_directory_new_label, self.new_data_directory_label_layout)
89 self.data_directory_layout.addRow(self.data_directory_copy_check_layout)
90 self.data_directory_layout.addRow(self.new_data_directory_has_files_label)
91 self.left_layout.addWidget(self.data_directory_group_box)
92@@ -239,8 +223,7 @@
93 self.service_name_edit.textChanged.connect(self.update_service_name_example)
94 self.service_name_revert_button.clicked.connect(self.on_service_name_revert_button_clicked)
95 self.alternate_rows_check_box.toggled.connect(self.on_alternate_rows_check_box_toggled)
96- self.data_directory_browse_button.clicked.connect(self.on_data_directory_browse_button_clicked)
97- self.data_directory_default_button.clicked.connect(self.on_data_directory_default_button_clicked)
98+ self.data_directory_path_edit.pathChanged.connect(self.on_data_directory_path_edit_path_changed)
99 self.data_directory_cancel_button.clicked.connect(self.on_data_directory_cancel_button_clicked)
100 self.data_directory_copy_check_box.toggled.connect(self.on_data_directory_copy_check_box_toggled)
101 self.end_slide_radio_button.clicked.connect(self.on_end_slide_button_clicked)
102@@ -317,12 +300,7 @@
103 self.service_name_example_label.setText(translate('OpenLP.AdvancedTab', 'Example:'))
104 self.hide_mouse_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Mouse Cursor'))
105 self.hide_mouse_check_box.setText(translate('OpenLP.AdvancedTab', 'Hide mouse cursor when over display window'))
106- self.data_directory_current_label.setText(translate('OpenLP.AdvancedTab', 'Current path:'))
107- self.data_directory_new_label.setText(translate('OpenLP.AdvancedTab', 'Custom path:'))
108- self.data_directory_browse_button.setToolTip(translate('OpenLP.AdvancedTab',
109- 'Browse for new data file location.'))
110- self.data_directory_default_button.setToolTip(
111- translate('OpenLP.AdvancedTab', 'Set the data location to the default.'))
112+ self.data_directory_new_label.setText(translate('OpenLP.AdvancedTab', 'Path:'))
113 self.data_directory_cancel_button.setText(translate('OpenLP.AdvancedTab', 'Cancel'))
114 self.data_directory_cancel_button.setToolTip(
115 translate('OpenLP.AdvancedTab', 'Cancel OpenLP data directory location change.'))
116@@ -396,8 +374,7 @@
117 self.new_data_directory_has_files_label.hide()
118 self.data_directory_cancel_button.hide()
119 # Since data location can be changed, make sure the path is present.
120- self.current_data_path = AppLocation.get_data_path()
121- self.data_directory_label.setText(os.path.abspath(self.current_data_path))
122+ self.data_directory_path_edit.path = AppLocation.get_data_path()
123 # Don't allow data directory move if running portable.
124 if settings.value('advanced/is portable'):
125 self.data_directory_group_box.hide()
126@@ -509,24 +486,10 @@
127 self.service_name_edit.setText(UiStrings().DefaultServiceName)
128 self.service_name_edit.setFocus()
129
130- def on_data_directory_browse_button_clicked(self):
131+ def on_data_directory_path_edit_path_changed(self, new_data_path):
132 """
133 Browse for a new data directory location.
134 """
135- old_root_path = str(self.data_directory_label.text())
136- # Get the new directory location.
137- new_data_path = QtWidgets.QFileDialog.getExistingDirectory(self, translate('OpenLP.AdvancedTab',
138- 'Select Data Directory Location'),
139- old_root_path,
140- options=QtWidgets.QFileDialog.ShowDirsOnly)
141- # Set the new data path.
142- if new_data_path:
143- new_data_path = os.path.normpath(new_data_path)
144- if self.current_data_path.lower() == new_data_path.lower():
145- self.on_data_directory_cancel_button_clicked()
146- return
147- else:
148- return
149 # Make sure they want to change the data.
150 answer = QtWidgets.QMessageBox.question(self, translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'),
151 translate('OpenLP.AdvancedTab', 'Are you sure you want to change the '
152@@ -537,42 +500,14 @@
153 QtWidgets.QMessageBox.No),
154 QtWidgets.QMessageBox.No)
155 if answer != QtWidgets.QMessageBox.Yes:
156+ self.data_directory_path_edit.path = AppLocation.get_data_path()
157 return
158 # Check if data already exists here.
159 self.check_data_overwrite(new_data_path)
160 # Save the new location.
161 self.main_window.set_new_data_path(new_data_path)
162- self.new_data_directory_edit.setText(new_data_path)
163 self.data_directory_cancel_button.show()
164
165- def on_data_directory_default_button_clicked(self):
166- """
167- Re-set the data directory location to the 'default' location.
168- """
169- new_data_path = AppLocation.get_directory(AppLocation.DataDir)
170- if self.current_data_path.lower() != new_data_path.lower():
171- # Make sure they want to change the data location back to the
172- # default.
173- answer = QtWidgets.QMessageBox.question(self, translate('OpenLP.AdvancedTab', 'Reset Data Directory'),
174- translate('OpenLP.AdvancedTab', 'Are you sure you want to change '
175- 'the location of the OpenLP data '
176- 'directory to the default location?'
177- '\n\nThis location will be used '
178- 'after OpenLP is closed.'),
179- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
180- QtWidgets.QMessageBox.No),
181- QtWidgets.QMessageBox.No)
182- if answer != QtWidgets.QMessageBox.Yes:
183- return
184- self.check_data_overwrite(new_data_path)
185- # Save the new location.
186- self.main_window.set_new_data_path(new_data_path)
187- self.new_data_directory_edit.setText(os.path.abspath(new_data_path))
188- self.data_directory_cancel_button.show()
189- else:
190- # We cancel the change in case user changed their mind.
191- self.on_data_directory_cancel_button_clicked()
192-
193 def on_data_directory_copy_check_box_toggled(self):
194 """
195 Copy existing data when you change your data directory.
196@@ -589,7 +524,6 @@
197 Check if there's already data in the target directory.
198 """
199 test_path = os.path.join(data_path, 'songs')
200- self.data_directory_copy_check_box.show()
201 if os.path.exists(test_path):
202 self.data_exists = True
203 # Check is they want to replace existing data.
204@@ -603,6 +537,7 @@
205 QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
206 QtWidgets.QMessageBox.No),
207 QtWidgets.QMessageBox.No)
208+ self.data_directory_copy_check_box.show()
209 if answer == QtWidgets.QMessageBox.Yes:
210 self.data_directory_copy_check_box.setChecked(True)
211 self.new_data_directory_has_files_label.show()
212@@ -618,7 +553,7 @@
213 """
214 Cancel the data directory location change
215 """
216- self.new_data_directory_edit.clear()
217+ self.data_directory_path_edit.path = AppLocation.get_data_path()
218 self.data_directory_copy_check_box.setChecked(False)
219 self.main_window.set_new_data_path(None)
220 self.main_window.set_copy_data(False)
221
222=== modified file 'openlp/core/ui/generaltab.py'
223--- openlp/core/ui/generaltab.py 2016-12-31 11:01:36 +0000
224+++ openlp/core/ui/generaltab.py 2017-05-22 16:32:39 +0000
225@@ -27,8 +27,8 @@
226 from PyQt5 import QtCore, QtGui, QtWidgets
227
228 from openlp.core.common import Registry, Settings, UiStrings, translate, get_images_filter
229-from openlp.core.lib import SettingsTab, ScreenList, build_icon
230-from openlp.core.ui.lib.colorbutton import ColorButton
231+from openlp.core.lib import SettingsTab, ScreenList
232+from openlp.core.ui.lib import ColorButton, PathEdit
233
234 log = logging.getLogger(__name__)
235
236@@ -172,20 +172,10 @@
237 self.logo_layout.setObjectName('logo_layout')
238 self.logo_file_label = QtWidgets.QLabel(self.logo_group_box)
239 self.logo_file_label.setObjectName('logo_file_label')
240- self.logo_file_edit = QtWidgets.QLineEdit(self.logo_group_box)
241- self.logo_file_edit.setObjectName('logo_file_edit')
242- self.logo_browse_button = QtWidgets.QToolButton(self.logo_group_box)
243- self.logo_browse_button.setObjectName('logo_browse_button')
244- self.logo_browse_button.setIcon(build_icon(':/general/general_open.png'))
245- self.logo_revert_button = QtWidgets.QToolButton(self.logo_group_box)
246- self.logo_revert_button.setObjectName('logo_revert_button')
247- self.logo_revert_button.setIcon(build_icon(':/general/general_revert.png'))
248- self.logo_file_layout = QtWidgets.QHBoxLayout()
249- self.logo_file_layout.setObjectName('logo_file_layout')
250- self.logo_file_layout.addWidget(self.logo_file_edit)
251- self.logo_file_layout.addWidget(self.logo_browse_button)
252- self.logo_file_layout.addWidget(self.logo_revert_button)
253- self.logo_layout.addRow(self.logo_file_label, self.logo_file_layout)
254+ self.logo_file_path_edit = \
255+ PathEdit(self.logo_group_box)
256+ self.logo_file_path_edit.default_path = ':/graphics/openlp-splash-screen.png'
257+ self.logo_layout.addRow(self.logo_file_label, self.logo_file_path_edit)
258 self.logo_color_label = QtWidgets.QLabel(self.logo_group_box)
259 self.logo_color_label.setObjectName('logo_color_label')
260 self.logo_color_button = ColorButton(self.logo_group_box)
261@@ -196,8 +186,6 @@
262 self.logo_layout.addRow(self.logo_hide_on_startup_check_box)
263 self.right_layout.addWidget(self.logo_group_box)
264 self.logo_color_button.colorChanged.connect(self.on_logo_background_color_changed)
265- self.logo_browse_button.clicked.connect(self.on_logo_browse_button_clicked)
266- self.logo_revert_button.clicked.connect(self.on_logo_revert_button_clicked)
267 # Application Settings
268 self.settings_group_box = QtWidgets.QGroupBox(self.right_column)
269 self.settings_group_box.setObjectName('settings_group_box')
270@@ -254,8 +242,6 @@
271 self.logo_group_box.setTitle(translate('OpenLP.GeneralTab', 'Logo'))
272 self.logo_color_label.setText(UiStrings().BackgroundColorColon)
273 self.logo_file_label.setText(translate('OpenLP.GeneralTab', 'Logo file:'))
274- self.logo_browse_button.setToolTip(translate('OpenLP.GeneralTab', 'Browse for an image file to display.'))
275- self.logo_revert_button.setToolTip(translate('OpenLP.GeneralTab', 'Revert to the default OpenLP logo.'))
276 self.logo_hide_on_startup_check_box.setText(translate('OpenLP.GeneralTab', 'Don\'t show logo on startup'))
277 self.check_for_updates_check_box.setText(translate('OpenLP.GeneralTab', 'Check for updates to OpenLP'))
278 self.settings_group_box.setTitle(translate('OpenLP.GeneralTab', 'Application Settings'))
279@@ -282,6 +268,9 @@
280 self.audio_group_box.setTitle(translate('OpenLP.GeneralTab', 'Background Audio'))
281 self.start_paused_check_box.setText(translate('OpenLP.GeneralTab', 'Start background audio paused'))
282 self.repeat_list_check_box.setText(translate('OpenLP.GeneralTab', 'Repeat track list'))
283+ self.logo_file_path_edit.dialog_caption = dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File')
284+ self.logo_file_path_edit.filters = '{text};;{names} (*.*)'.format(
285+ text=get_images_filter(), names=UiStrings().AllFiles)
286
287 def load(self):
288 """
289@@ -304,7 +293,7 @@
290 self.auto_open_check_box.setChecked(settings.value('auto open'))
291 self.show_splash_check_box.setChecked(settings.value('show splash'))
292 self.logo_background_color = settings.value('logo background color')
293- self.logo_file_edit.setText(settings.value('logo file'))
294+ self.logo_file_path_edit.path = settings.value('logo file')
295 self.logo_hide_on_startup_check_box.setChecked(settings.value('logo hide on startup'))
296 self.logo_color_button.color = self.logo_background_color
297 self.check_for_updates_check_box.setChecked(settings.value('update check'))
298@@ -338,7 +327,7 @@
299 settings.setValue('auto open', self.auto_open_check_box.isChecked())
300 settings.setValue('show splash', self.show_splash_check_box.isChecked())
301 settings.setValue('logo background color', self.logo_background_color)
302- settings.setValue('logo file', self.logo_file_edit.text())
303+ settings.setValue('logo file', self.logo_file_path_edit.path)
304 settings.setValue('logo hide on startup', self.logo_hide_on_startup_check_box.isChecked())
305 settings.setValue('update check', self.check_for_updates_check_box.isChecked())
306 settings.setValue('save prompt', self.save_check_service_check_box.isChecked())
307@@ -404,25 +393,6 @@
308 """
309 self.display_changed = True
310
311- def on_logo_browse_button_clicked(self):
312- """
313- Select the logo file
314- """
315- file_filters = '{text};;{names} (*.*)'.format(text=get_images_filter(), names=UiStrings().AllFiles)
316- filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(self,
317- translate('OpenLP.AdvancedTab', 'Open File'), '',
318- file_filters)
319- if filename:
320- self.logo_file_edit.setText(filename)
321- self.logo_file_edit.setFocus()
322-
323- def on_logo_revert_button_clicked(self):
324- """
325- Revert the logo file back to the default setting.
326- """
327- self.logo_file_edit.setText(':/graphics/openlp-splash-screen.png')
328- self.logo_file_edit.setFocus()
329-
330 def on_logo_background_color_changed(self, color):
331 """
332 Select the background color for logo.
333
334=== modified file 'openlp/core/ui/lib/__init__.py'
335--- openlp/core/ui/lib/__init__.py 2016-12-31 11:01:36 +0000
336+++ openlp/core/ui/lib/__init__.py 2017-05-22 16:32:39 +0000
337@@ -21,14 +21,16 @@
338 ###############################################################################
339
340 from .colorbutton import ColorButton
341+from .listpreviewwidget import ListPreviewWidget
342 from .listwidgetwithdnd import ListWidgetWithDnD
343-from .treewidgetwithdnd import TreeWidgetWithDnD
344+from .mediadockmanager import MediaDockManager
345+from .dockwidget import OpenLPDockWidget
346 from .toolbar import OpenLPToolbar
347-from .dockwidget import OpenLPDockWidget
348 from .wizard import OpenLPWizard, WizardStrings
349-from .mediadockmanager import MediaDockManager
350-from .listpreviewwidget import ListPreviewWidget
351+from .pathedit import PathEdit, PathType
352 from .spelltextedit import SpellTextEdit
353+from .treewidgetwithdnd import TreeWidgetWithDnD
354
355-__all__ = ['ColorButton', 'ListPreviewWidget', 'ListWidgetWithDnD', 'OpenLPToolbar', 'OpenLPDockWidget',
356- 'OpenLPWizard', 'WizardStrings', 'MediaDockManager', 'ListPreviewWidget', 'SpellTextEdit']
357+__all__ = ['ColorButton', 'ListPreviewWidget', 'ListWidgetWithDnD', 'MediaDockManager', 'OpenLPDockWidget',
358+ 'OpenLPToolbar', 'OpenLPWizard', 'PathEdit', 'PathType', 'SpellTextEdit', 'TreeWidgetWithDnD',
359+ 'WizardStrings']
360
361=== modified file 'openlp/core/ui/lib/colorbutton.py'
362--- openlp/core/ui/lib/colorbutton.py 2016-12-31 11:01:36 +0000
363+++ openlp/core/ui/lib/colorbutton.py 2017-05-22 16:32:39 +0000
364@@ -39,7 +39,7 @@
365 """
366 Initialise the ColorButton
367 """
368- super(ColorButton, self).__init__()
369+ super().__init__(parent)
370 self.parent = parent
371 self.change_color('#ffffff')
372 self.setToolTip(translate('OpenLP.ColorButton', 'Click to select a color.'))
373
374=== added file 'openlp/core/ui/lib/pathedit.py'
375--- openlp/core/ui/lib/pathedit.py 1970-01-01 00:00:00 +0000
376+++ openlp/core/ui/lib/pathedit.py 2017-05-22 16:32:39 +0000
377@@ -0,0 +1,197 @@
378+# -*- coding: utf-8 -*-
379+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
380+
381+###############################################################################
382+# OpenLP - Open Source Lyrics Projection #
383+# --------------------------------------------------------------------------- #
384+# Copyright (c) 2008-2017 OpenLP Developers #
385+# --------------------------------------------------------------------------- #
386+# This program is free software; you can redistribute it and/or modify it #
387+# under the terms of the GNU General Public License as published by the Free #
388+# Software Foundation; version 2 of the License. #
389+# #
390+# This program is distributed in the hope that it will be useful, but WITHOUT #
391+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
392+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
393+# more details. #
394+# #
395+# You should have received a copy of the GNU General Public License along #
396+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
397+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
398+###############################################################################
399+from enum import Enum
400+import os.path
401+
402+from PyQt5 import QtCore, QtWidgets
403+
404+from openlp.core.common import UiStrings, translate
405+from openlp.core.lib import build_icon
406+
407+
408+class PathType(Enum):
409+ Files = 1
410+ Directories = 2
411+
412+
413+class PathEdit(QtWidgets.QWidget):
414+ """
415+ The :class:`~openlp.core.ui.lib.pathedit.PathEdit` class subclasses QWidget to create a custom widget for use when
416+ a file or directory needs to be selected.
417+ """
418+ pathChanged = QtCore.pyqtSignal(str)
419+
420+ def __init__(self, parent=None, show_revert=True):
421+ """
422+ Initalise the PathEdit widget
423+
424+ :param parent: The parent of the widget. This is just passed to the super method.
425+ :type parent: QWidget or None
426+
427+ :param show_revert: Used to determin if the 'revert button' should be visible.
428+ :type show_revert: bool
429+
430+ :ivar default_path: The default path. This is set as the path when the revert button is clicked
431+ :vartype default_path: str
432+
433+ :ivar dialog_caption: Used to customise the caption in the QFileDialog.
434+ :vartype dialog_caption: str
435+ """
436+ super().__init__(parent)
437+ self.default_path = ''
438+ self.dialog_caption = ''
439+ self._path_type = PathType.Files
440+ self._path = ''
441+ self.filters = '{all_files} (*)'.format(all_files=UiStrings().AllFiles)
442+ self._setup(show_revert)
443+
444+ def _setup(self, show_revert):
445+
446+ widget_layout = QtWidgets.QHBoxLayout()
447+ widget_layout.setContentsMargins(0, 0, 0, 0)
448+ self.line_edit = QtWidgets.QLineEdit(self)
449+ self.line_edit.setText(self._path)
450+ widget_layout.addWidget(self.line_edit)
451+ self.browse_button = QtWidgets.QToolButton(self)
452+ self.browse_button.setIcon(build_icon(':/general/general_open.png'))
453+ widget_layout.addWidget(self.browse_button)
454+ self.revert_button = QtWidgets.QToolButton(self)
455+ self.revert_button.setIcon(build_icon(':/general/general_revert.png'))
456+ self.revert_button.setVisible(show_revert)
457+ widget_layout.addWidget(self.revert_button)
458+ self.setLayout(widget_layout)
459+
460+ # Signals and Slots
461+ self.browse_button.clicked.connect(self.on_browse_button_clicked)
462+ self.revert_button.clicked.connect(self.on_revert_button_clicked)
463+ self.line_edit.editingFinished.connect(self.on_line_edit_editing_finished)
464+
465+ self.update_button_tool_tips()
466+
467+ @property
468+ def path(self):
469+ """
470+ A property getter method to return the selected path.
471+
472+ :return: The selected path
473+ :rtype: str
474+ """
475+ return self._path
476+
477+ @path.setter
478+ def path(self, path):
479+ """
480+ A Property setter method to set the selected path
481+
482+ :param path: The path to set the widget to
483+ :type path: str
484+ """
485+ self._path = path
486+ self.line_edit.setText(path)
487+ self.line_edit.setToolTip(path)
488+
489+ @property
490+ def path_type(self):
491+ """
492+ A property getter method to return the path_type. Path type allows you to sepecify if the user is restricted to
493+ selecting a file or directory.
494+
495+ :return: The type selected
496+ :rtype: Enum of PathEdit
497+ """
498+ return self._path_type
499+
500+ @path_type.setter
501+ def path_type(self, path_type):
502+ """
503+ A Property setter method to set the path type
504+
505+ :param path: The type of path to select
506+ :type path: Enum of PathEdit
507+ """
508+ self._path_type = path_type
509+ self.update_button_tool_tips()
510+
511+ def update_button_tool_tips(self):
512+ """
513+ Called to update the tooltips on the buttons. This is changing path types, and when the widget is initalised
514+ :return: None
515+ """
516+ if self._path_type == PathType.Directories:
517+ self.browse_button.setToolTip(translate('OpenLP.PathEdit', 'Browse for directory.'))
518+ self.revert_button.setToolTip(translate('OpenLP.PathEdit', 'Revert to default directory.'))
519+ else:
520+ self.browse_button.setToolTip(translate('OpenLP.PathEdit', 'Browse for file.'))
521+ self.revert_button.setToolTip(translate('OpenLP.PathEdit', 'Revert to default file.'))
522+
523+ def on_browse_button_clicked(self):
524+ """
525+ A handler to handle a click on the browse button.
526+
527+ Show the QFileDialog and process the input from the user
528+ :return: None
529+ """
530+ caption = self.dialog_caption
531+ path = ''
532+ if self._path_type == PathType.Directories:
533+ if not caption:
534+ caption = translate('OpenLP.PathEdit', 'Select Directory')
535+ path = QtWidgets.QFileDialog.getExistingDirectory(self, caption,
536+ self._path, QtWidgets.QFileDialog.ShowDirsOnly)
537+ elif self._path_type == PathType.Files:
538+ if not caption:
539+ caption = self.dialog_caption = translate('OpenLP.PathEdit', 'Select File')
540+ path, filter_used = QtWidgets.QFileDialog.getOpenFileName(self, caption, self._path, self.filters)
541+ if path:
542+ path = os.path.normpath(path)
543+ self.on_new_path(path)
544+
545+ def on_revert_button_clicked(self):
546+ """
547+ A handler to handle a click on the revert button.
548+
549+ Set the new path to the value of the default_path instance variable.
550+ :return: None
551+ """
552+ self.on_new_path(self.default_path)
553+
554+ def on_line_edit_editing_finished(self):
555+ """
556+ A handler to handle when the line edit has finished being edited.
557+ :return: None
558+ """
559+ self.on_new_path(self.line_edit.text())
560+
561+ def on_new_path(self, path):
562+ """
563+ A method called to validate and set a new path.
564+
565+ Emits the pathChanged Signal
566+
567+ :param path: The new path
568+ :type path: str
569+
570+ :return: None
571+ """
572+ if self._path != path:
573+ self.path = path
574+ self.pathChanged.emit(path)
575
576=== modified file 'openlp/core/ui/themeform.py'
577--- openlp/core/ui/themeform.py 2016-12-31 11:01:36 +0000
578+++ openlp/core/ui/themeform.py 2017-05-22 16:32:39 +0000
579@@ -69,10 +69,16 @@
580 self.video_color_button.colorChanged.connect(self.on_video_color_changed)
581 self.gradient_start_button.colorChanged.connect(self.on_gradient_start_color_changed)
582 self.gradient_end_button.colorChanged.connect(self.on_gradient_end_color_changed)
583- self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked)
584- self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished)
585- self.video_browse_button.clicked.connect(self.on_video_browse_button_clicked)
586- self.video_file_edit.editingFinished.connect(self.on_video_file_edit_editing_finished)
587+ self.image_path_edit.filters = \
588+ '{name};;{text} (*.*)'.format(name=get_images_filter(), text=UiStrings().AllFiles)
589+ self.image_path_edit.pathChanged.connect(self.on_image_path_edit_path_changed)
590+ # TODO: Should work
591+ visible_formats = '({name})'.format(name='; '.join(VIDEO_EXT))
592+ actual_formats = '({name})'.format(name=' '.join(VIDEO_EXT))
593+ video_filter = '{trans} {visible} {actual}'.format(trans=translate('OpenLP', 'Video Files'),
594+ visible=visible_formats, actual=actual_formats)
595+ self.video_path_edit.filters = '{video};;{ui} (*.*)'.format(video=video_filter, ui=UiStrings().AllFiles)
596+ self.video_path_edit.pathChanged.connect(self.on_video_path_edit_path_changed)
597 self.main_color_button.colorChanged.connect(self.on_main_color_changed)
598 self.outline_color_button.colorChanged.connect(self.on_outline_color_changed)
599 self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed)
600@@ -112,7 +118,8 @@
601 self.background_page.registerField('color', self.color_button)
602 self.background_page.registerField('gradient_start', self.gradient_start_button)
603 self.background_page.registerField('gradient_end', self.gradient_end_button)
604- self.background_page.registerField('background_image', self.image_file_edit)
605+ self.background_page.registerField('background_image', self.image_path_edit,
606+ 'path', self.image_path_edit.pathChanged)
607 self.background_page.registerField('gradient', self.gradient_combo_box)
608 self.main_area_page.registerField('main_color_button', self.main_color_button)
609 self.main_area_page.registerField('main_size_spin_box', self.main_size_spin_box)
610@@ -309,11 +316,11 @@
611 self.setField('background_type', 1)
612 elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Image):
613 self.image_color_button.color = self.theme.background_border_color
614- self.image_file_edit.setText(self.theme.background_filename)
615+ self.image_path_edit.path = self.theme.background_filename
616 self.setField('background_type', 2)
617 elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
618 self.video_color_button.color = self.theme.background_border_color
619- self.video_file_edit.setText(self.theme.background_filename)
620+ self.video_path_edit.path = self.theme.background_filename
621 self.setField('background_type', 4)
622 elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
623 self.setField('background_type', 3)
624@@ -441,48 +448,20 @@
625 """
626 self.theme.background_end_color = color
627
628- def on_image_browse_button_clicked(self):
629+ def on_image_path_edit_path_changed(self, filename):
630 """
631 Background Image button pushed.
632 """
633- images_filter = get_images_filter()
634- images_filter = '{name};;{text} (*.*)'.format(name=images_filter, text=UiStrings().AllFiles)
635- filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
636- self, translate('OpenLP.ThemeWizard', 'Select Image'),
637- self.image_file_edit.text(), images_filter)
638- if filename:
639- self.theme.background_filename = filename
640+ self.theme.background_filename = filename
641 self.set_background_page_values()
642
643- def on_image_file_edit_editing_finished(self):
644- """
645- Background image path edited
646- """
647- self.theme.background_filename = str(self.image_file_edit.text())
648-
649- def on_video_browse_button_clicked(self):
650+ def on_video_path_edit_path_changed(self, filename):
651 """
652 Background video button pushed.
653 """
654- # TODO: Should work
655- visible_formats = '({name})'.format(name='; '.join(VIDEO_EXT))
656- actual_formats = '({name})'.format(name=' '.join(VIDEO_EXT))
657- video_filter = '{trans} {visible} {actual}'.format(trans=translate('OpenLP', 'Video Files'),
658- visible=visible_formats, actual=actual_formats)
659- video_filter = '{video};;{ui} (*.*)'.format(video=video_filter, ui=UiStrings().AllFiles)
660- filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
661- self, translate('OpenLP.ThemeWizard', 'Select Video'),
662- self.video_file_edit.text(), video_filter)
663- if filename:
664- self.theme.background_filename = filename
665+ self.theme.background_filename = filename
666 self.set_background_page_values()
667
668- def on_video_file_edit_editing_finished(self):
669- """
670- Background video path edited
671- """
672- self.theme.background_filename = str(self.image_file_edit.text())
673-
674 def on_main_color_changed(self, color):
675 """
676 Set the main colour value
677
678=== modified file 'openlp/core/ui/themewizard.py'
679--- openlp/core/ui/themewizard.py 2016-12-31 11:01:36 +0000
680+++ openlp/core/ui/themewizard.py 2017-05-22 16:32:39 +0000
681@@ -28,7 +28,7 @@
682 from openlp.core.lib import build_icon
683 from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
684 from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
685-from openlp.core.ui.lib.colorbutton import ColorButton
686+from openlp.core.ui.lib import ColorButton, PathEdit
687
688
689 class Ui_ThemeWizard(object):
690@@ -116,16 +116,9 @@
691 self.image_layout.addRow(self.image_color_label, self.image_color_button)
692 self.image_label = QtWidgets.QLabel(self.image_widget)
693 self.image_label.setObjectName('image_label')
694- self.image_file_layout = QtWidgets.QHBoxLayout()
695- self.image_file_layout.setObjectName('image_file_layout')
696- self.image_file_edit = QtWidgets.QLineEdit(self.image_widget)
697- self.image_file_edit.setObjectName('image_file_edit')
698- self.image_file_layout.addWidget(self.image_file_edit)
699- self.image_browse_button = QtWidgets.QToolButton(self.image_widget)
700- self.image_browse_button.setObjectName('image_browse_button')
701- self.image_browse_button.setIcon(build_icon(':/general/general_open.png'))
702- self.image_file_layout.addWidget(self.image_browse_button)
703- self.image_layout.addRow(self.image_label, self.image_file_layout)
704+ self.image_path_edit = PathEdit(self.image_widget, show_revert=False)
705+ self.image_path_edit.dialog_caption = translate('OpenLP.ThemeWizard', 'Select Image')
706+ self.image_layout.addRow(self.image_label, self.image_path_edit)
707 self.image_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
708 self.background_stack.addWidget(self.image_widget)
709 self.transparent_widget = QtWidgets.QWidget(self.background_page)
710@@ -147,16 +140,9 @@
711 self.video_layout.addRow(self.video_color_label, self.video_color_button)
712 self.video_label = QtWidgets.QLabel(self.video_widget)
713 self.video_label.setObjectName('video_label')
714- self.video_file_layout = QtWidgets.QHBoxLayout()
715- self.video_file_layout.setObjectName('video_file_layout')
716- self.video_file_edit = QtWidgets.QLineEdit(self.video_widget)
717- self.video_file_edit.setObjectName('video_file_edit')
718- self.video_file_layout.addWidget(self.video_file_edit)
719- self.video_browse_button = QtWidgets.QToolButton(self.video_widget)
720- self.video_browse_button.setObjectName('video_browse_button')
721- self.video_browse_button.setIcon(build_icon(':/general/general_open.png'))
722- self.video_file_layout.addWidget(self.video_browse_button)
723- self.video_layout.addRow(self.video_label, self.video_file_layout)
724+ self.video_path_edit = PathEdit(self.video_widget, show_revert=False)
725+ self.video_path_edit.dialog_caption = translate('OpenLP.ThemeWizard', 'Select Video')
726+ self.video_layout.addRow(self.video_label, self.video_path_edit)
727 self.video_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
728 self.background_stack.addWidget(self.video_widget)
729 theme_wizard.addPage(self.background_page)
730
731=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
732--- openlp/plugins/bibles/forms/bibleimportform.py 2017-05-06 09:22:34 +0000
733+++ openlp/plugins/bibles/forms/bibleimportform.py 2017-05-22 16:32:39 +0000
734@@ -135,7 +135,6 @@
735 Add the bible import specific wizard pages.
736 """
737 # Select Page
738- self.spacers = []
739 self.select_page = QtWidgets.QWizardPage()
740 self.select_page.setObjectName('SelectPage')
741 self.select_page_layout = QtWidgets.QVBoxLayout(self.select_page)
742@@ -148,8 +147,8 @@
743 self.format_combo_box.addItems(['', '', '', '', '', '', ''])
744 self.format_combo_box.setObjectName('FormatComboBox')
745 self.format_layout.addRow(self.format_label, self.format_combo_box)
746- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
747- self.format_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
748+ self.spacer = QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
749+ self.format_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
750 self.select_page_layout.addLayout(self.format_layout)
751 self.select_stack = QtWidgets.QStackedLayout()
752 self.select_stack.setObjectName('SelectStack')
753@@ -171,8 +170,7 @@
754 self.osis_browse_button.setObjectName('OsisBrowseButton')
755 self.osis_file_layout.addWidget(self.osis_browse_button)
756 self.osis_layout.addRow(self.osis_file_label, self.osis_file_layout)
757- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
758- self.osis_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
759+ self.osis_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
760 self.select_stack.addWidget(self.osis_widget)
761 self.csv_widget = QtWidgets.QWidget(self.select_page)
762 self.csv_widget.setObjectName('CsvWidget')
763@@ -205,8 +203,7 @@
764 self.csv_verses_button.setObjectName('CsvVersesButton')
765 self.csv_verses_layout.addWidget(self.csv_verses_button)
766 self.csv_layout.addRow(self.csv_verses_label, self.csv_verses_layout)
767- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
768- self.csv_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
769+ self.csv_layout.setItem(3, QtWidgets.QFormLayout.LabelRole, self.spacer)
770 self.select_stack.addWidget(self.csv_widget)
771 self.open_song_widget = QtWidgets.QWidget(self.select_page)
772 self.open_song_widget.setObjectName('OpenSongWidget')
773@@ -226,8 +223,7 @@
774 self.open_song_browse_button.setObjectName('OpenSongBrowseButton')
775 self.open_song_file_layout.addWidget(self.open_song_browse_button)
776 self.open_song_layout.addRow(self.open_song_file_label, self.open_song_file_layout)
777- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
778- self.open_song_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
779+ self.open_song_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
780 self.select_stack.addWidget(self.open_song_widget)
781 self.web_tab_widget = QtWidgets.QTabWidget(self.select_page)
782 self.web_tab_widget.setObjectName('WebTabWidget')
783@@ -304,8 +300,7 @@
784 self.zefania_browse_button.setObjectName('ZefaniaBrowseButton')
785 self.zefania_file_layout.addWidget(self.zefania_browse_button)
786 self.zefania_layout.addRow(self.zefania_file_label, self.zefania_file_layout)
787- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
788- self.zefania_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
789+ self.zefania_layout.setItem(5, QtWidgets.QFormLayout.LabelRole, self.spacer)
790 self.select_stack.addWidget(self.zefania_widget)
791 self.sword_widget = QtWidgets.QWidget(self.select_page)
792 self.sword_widget.setObjectName('SwordWidget')
793@@ -386,8 +381,7 @@
794 self.wordproject_browse_button.setObjectName('WordProjectBrowseButton')
795 self.wordproject_file_layout.addWidget(self.wordproject_browse_button)
796 self.wordproject_layout.addRow(self.wordproject_file_label, self.wordproject_file_layout)
797- self.spacers.append(QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum))
798- self.wordproject_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacers[-1])
799+ self.wordproject_layout.setItem(5, QtWidgets.QFormLayout.LabelRole, self.spacer)
800 self.select_stack.addWidget(self.wordproject_widget)
801 self.select_page_layout.addLayout(self.select_stack)
802 self.addPage(self.select_page)
803@@ -505,8 +499,7 @@
804 self.csv_verses_label.minimumSizeHint().width(),
805 self.open_song_file_label.minimumSizeHint().width(),
806 self.zefania_file_label.minimumSizeHint().width())
807- for spacer in self.spacers:
808- spacer.changeSize(label_width, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
809+ self.spacer.changeSize(label_width, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
810
811 def validateCurrentPage(self):
812 """
813
814=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
815--- openlp/plugins/presentations/lib/presentationtab.py 2017-05-14 10:11:10 +0000
816+++ openlp/plugins/presentations/lib/presentationtab.py 2017-05-22 16:32:39 +0000
817@@ -25,7 +25,12 @@
818 from openlp.core.common import Settings, UiStrings, translate
819 from openlp.core.lib import SettingsTab, build_icon
820 from openlp.core.lib.ui import critical_error_message_box
821+<<<<<<< TREE
822 from openlp.plugins.presentations.lib.pdfcontroller import PdfController
823+=======
824+from openlp.core.ui.lib import PathEdit
825+from .pdfcontroller import PdfController
826+>>>>>>> MERGE-SOURCE
827
828
829 class PresentationTab(SettingsTab):
830@@ -88,26 +93,15 @@
831 self.pdf_program_check_box = QtWidgets.QCheckBox(self.pdf_group_box)
832 self.pdf_program_check_box.setObjectName('pdf_program_check_box')
833 self.pdf_layout.addRow(self.pdf_program_check_box)
834- self.pdf_program_path_layout = QtWidgets.QHBoxLayout()
835- self.pdf_program_path_layout.setObjectName('pdf_program_path_layout')
836- self.pdf_program_path = QtWidgets.QLineEdit(self.pdf_group_box)
837- self.pdf_program_path.setObjectName('pdf_program_path')
838- self.pdf_program_path.setReadOnly(True)
839- self.pdf_program_path.setPalette(self.get_grey_text_palette(True))
840- self.pdf_program_path_layout.addWidget(self.pdf_program_path)
841- self.pdf_program_browse_button = QtWidgets.QToolButton(self.pdf_group_box)
842- self.pdf_program_browse_button.setObjectName('pdf_program_browse_button')
843- self.pdf_program_browse_button.setIcon(build_icon(':/general/general_open.png'))
844- self.pdf_program_browse_button.setEnabled(False)
845- self.pdf_program_path_layout.addWidget(self.pdf_program_browse_button)
846- self.pdf_layout.addRow(self.pdf_program_path_layout)
847+ self.program_path_edit = PathEdit(self.pdf_group_box)
848+ self.pdf_layout.addRow(self.program_path_edit)
849 self.left_layout.addWidget(self.pdf_group_box)
850 self.left_layout.addStretch()
851 self.right_column.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
852 self.right_layout.addStretch()
853 # Signals and slots
854- self.pdf_program_browse_button.clicked.connect(self.on_pdf_program_browse_button_clicked)
855- self.pdf_program_check_box.clicked.connect(self.on_pdf_program_check_box_clicked)
856+ self.program_path_edit.pathChanged.connect(self.on_program_path_edit_path_changed)
857+ self.pdf_program_check_box.clicked.connect(self.program_path_edit.setEnabled)
858
859 def retranslateUi(self):
860 """
861@@ -132,6 +126,8 @@
862 '(This may fix PowerPoint scaling issues in Windows 8 and 10)'))
863 self.pdf_program_check_box.setText(
864 translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:'))
865+ self.program_path_edit.dialog_caption = translate('PresentationPlugin.PresentationTab',
866+ 'Select mudraw or ghostscript binary')
867
868 def set_controller_text(self, checkbox, controller):
869 if checkbox.isEnabled():
870@@ -161,11 +157,10 @@
871 # load pdf-program settings
872 enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program')
873 self.pdf_program_check_box.setChecked(enable_pdf_program)
874- self.pdf_program_path.setPalette(self.get_grey_text_palette(not enable_pdf_program))
875- self.pdf_program_browse_button.setEnabled(enable_pdf_program)
876+ self.program_path_edit.setEnabled(enable_pdf_program)
877 pdf_program = Settings().value(self.settings_section + '/pdf_program')
878 if pdf_program:
879- self.pdf_program_path.setText(pdf_program)
880+ self.program_path_edit.path = pdf_program
881
882 def save(self):
883 """
884@@ -201,7 +196,7 @@
885 Settings().setValue(setting_key, self.ppt_window_check_box.checkState())
886 changed = True
887 # Save pdf-settings
888- pdf_program = self.pdf_program_path.text()
889+ pdf_program = self.program_path_edit.path
890 enable_pdf_program = self.pdf_program_check_box.checkState()
891 # If the given program is blank disable using the program
892 if pdf_program == '':
893@@ -228,42 +223,12 @@
894 checkbox.setEnabled(controller.is_available())
895 self.set_controller_text(checkbox, controller)
896
897- def on_pdf_program_browse_button_clicked(self):
898+ def on_program_path_edit_path_changed(self, filename):
899 """
900 Select the mudraw or ghostscript binary that should be used.
901 """
902- filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
903- self, translate('PresentationPlugin.PresentationTab', 'Select mudraw or ghostscript binary.'),
904- self.pdf_program_path.text())
905 if filename:
906- program_type = PdfController.process_check_binary(filename)
907- if not program_type:
908+ if not PdfController.process_check_binary(filename):
909 critical_error_message_box(UiStrings().Error,
910 translate('PresentationPlugin.PresentationTab',
911 'The program is not ghostscript or mudraw which is required.'))
912- else:
913- self.pdf_program_path.setText(filename)
914-
915- def on_pdf_program_check_box_clicked(self, checked):
916- """
917- When checkbox for manual entering pdf-program is clicked,
918- enable or disable the textbox for the programpath and the browse-button.
919-
920- :param checked: If the box is checked or not.
921- """
922- self.pdf_program_path.setPalette(self.get_grey_text_palette(not checked))
923- self.pdf_program_browse_button.setEnabled(checked)
924-
925- def get_grey_text_palette(self, greyed):
926- """
927- Returns a QPalette with greyed out text as used for placeholderText.
928-
929- :param greyed: Determines whether the palette should be grayed.
930- :return: The created palette.
931- """
932- palette = QtGui.QPalette()
933- color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Text)
934- if greyed:
935- color.setAlpha(128)
936- palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
937- return palette
938
939=== modified file 'openlp/plugins/songusage/forms/songusagedetaildialog.py'
940--- openlp/plugins/songusage/forms/songusagedetaildialog.py 2016-12-31 11:01:36 +0000
941+++ openlp/plugins/songusage/forms/songusagedetaildialog.py 2017-05-22 16:32:39 +0000
942@@ -25,6 +25,7 @@
943 from openlp.core.common import translate
944 from openlp.core.lib import build_icon
945 from openlp.core.lib.ui import create_button_box
946+from openlp.core.ui.lib import PathEdit, PathType
947
948
949 class Ui_SongUsageDetailDialog(object):
950@@ -68,20 +69,14 @@
951 self.file_horizontal_layout.setSpacing(8)
952 self.file_horizontal_layout.setContentsMargins(8, 8, 8, 8)
953 self.file_horizontal_layout.setObjectName('file_horizontal_layout')
954- self.file_line_edit = QtWidgets.QLineEdit(self.file_group_box)
955- self.file_line_edit.setObjectName('file_line_edit')
956- self.file_line_edit.setReadOnly(True)
957- self.file_horizontal_layout.addWidget(self.file_line_edit)
958- self.save_file_push_button = QtWidgets.QPushButton(self.file_group_box)
959- self.save_file_push_button.setMaximumWidth(self.save_file_push_button.size().height())
960- self.save_file_push_button.setIcon(build_icon(':/general/general_open.png'))
961- self.save_file_push_button.setObjectName('save_file_push_button')
962- self.file_horizontal_layout.addWidget(self.save_file_push_button)
963+ self.report_path_edit = PathEdit(self.file_group_box, show_revert=False)
964+ self.report_path_edit.path_type = PathType.Directories
965+ self.file_horizontal_layout.addWidget(self.report_path_edit)
966 self.vertical_layout.addWidget(self.file_group_box)
967 self.button_box = create_button_box(song_usage_detail_dialog, 'button_box', ['cancel', 'ok'])
968 self.vertical_layout.addWidget(self.button_box)
969 self.retranslateUi(song_usage_detail_dialog)
970- self.save_file_push_button.clicked.connect(song_usage_detail_dialog.define_output_location)
971+ self.report_path_edit.pathChanged.connect(song_usage_detail_dialog.on_report_path_edit_path_changed)
972
973 def retranslateUi(self, song_usage_detail_dialog):
974 """
975
976=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
977--- openlp/plugins/songusage/forms/songusagedetailform.py 2016-12-31 11:01:36 +0000
978+++ openlp/plugins/songusage/forms/songusagedetailform.py 2017-05-22 16:32:39 +0000
979@@ -54,25 +54,20 @@
980 """
981 self.from_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/from date'))
982 self.to_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/to date'))
983- self.file_line_edit.setText(Settings().value(self.plugin.settings_section + '/last directory export'))
984+ self.report_path_edit.path = Settings().value(self.plugin.settings_section + '/last directory export')
985
986- def define_output_location(self):
987+ def on_report_path_edit_path_changed(self, file_path):
988 """
989 Triggered when the Directory selection button is clicked
990 """
991- path = QtWidgets.QFileDialog.getExistingDirectory(
992- self, translate('SongUsagePlugin.SongUsageDetailForm', 'Output File Location'),
993- Settings().value(self.plugin.settings_section + '/last directory export'))
994- if path:
995- Settings().setValue(self.plugin.settings_section + '/last directory export', path)
996- self.file_line_edit.setText(path)
997+ Settings().setValue(self.plugin.settings_section + '/last directory export', file_path)
998
999 def accept(self):
1000 """
1001 Ok was triggered so lets save the data and run the report
1002 """
1003 log.debug('accept')
1004- path = self.file_line_edit.text()
1005+ path = self.report_path_edit.path
1006 if not path:
1007 self.main_window.error_message(
1008 translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'),
1009
1010=== modified file 'tests/functional/openlp_core_ui/test_themeform.py'
1011--- tests/functional/openlp_core_ui/test_themeform.py 2017-04-24 05:17:55 +0000
1012+++ tests/functional/openlp_core_ui/test_themeform.py 2017-05-22 16:32:39 +0000
1013@@ -32,60 +32,21 @@
1014 """
1015 Test the functions in the ThemeManager Class
1016 """
1017- def test_select_image_file_dialog_cancelled(self):
1018- """
1019- Test the select image file dialog when the user presses cancel
1020- """
1021- # GIVEN: An instance of Theme Form and mocked QFileDialog which returns an empty string (similating a user
1022- # pressing cancel)
1023- with patch('openlp.core.ui.ThemeForm._setup'),\
1024- patch('openlp.core.ui.themeform.get_images_filter',
1025- **{'return_value': 'Image Files (*.bmp; *.gif)(*.bmp *.gif)'}),\
1026- patch('openlp.core.ui.themeform.QtWidgets.QFileDialog.getOpenFileName',
1027- **{'return_value': ('', '')}) as mocked_get_open_file_name,\
1028- patch('openlp.core.ui.themeform.translate', **{'return_value': 'Translated String'}),\
1029- patch('openlp.core.ui.ThemeForm.set_background_page_values') as mocked_set_background_page_values:
1030- instance = ThemeForm(None)
1031- mocked_image_file_edit = MagicMock()
1032- mocked_image_file_edit.text.return_value = '/original_path/file.ext'
1033- instance.image_file_edit = mocked_image_file_edit
1034-
1035- # WHEN: on_image_browse_button is clicked
1036- instance.on_image_browse_button_clicked()
1037-
1038- # THEN: The QFileDialog getOpenFileName and set_background_page_values moethods should have been called
1039- # with known arguments
1040- mocked_get_open_file_name.assert_called_once_with(instance, 'Translated String', '/original_path/file.ext',
1041- 'Image Files (*.bmp; *.gif)(*.bmp *.gif);;'
1042- 'All Files (*.*)')
1043+ def setUp(self):
1044+ with patch('openlp.core.ui.ThemeForm._setup'):
1045+ self.instance = ThemeForm(None)
1046+
1047+ def test_on_image_path_edit_path_changed(self):
1048+ """
1049+ Test the `image_path_edit.pathChanged` handler
1050+ """
1051+ # GIVEN: An instance of Theme Form
1052+ with patch.object(self.instance, 'set_background_page_values') as mocked_set_background_page_values:
1053+ self.instance.theme = MagicMock()
1054+
1055+ # WHEN: `on_image_path_edit_path_changed` is clicked
1056+ self.instance.on_image_path_edit_path_changed('/new/pat.h')
1057+
1058+ # THEN: The theme background file should be set and `set_background_page_values` should have been called
1059+ self.assertEqual(self.instance.theme.background_filename, '/new/pat.h')
1060 mocked_set_background_page_values.assert_called_once_with()
1061-
1062- def test_select_image_file_dialog_new_file(self):
1063- """
1064- Test the select image file dialog when the user presses ok
1065- """
1066- # GIVEN: An instance of Theme Form and mocked QFileDialog which returns a file path
1067- with patch('openlp.core.ui.ThemeForm._setup'),\
1068- patch('openlp.core.ui.themeform.get_images_filter',
1069- **{'return_value': 'Image Files (*.bmp; *.gif)(*.bmp *.gif)'}),\
1070- patch('openlp.core.ui.themeform.QtWidgets.QFileDialog.getOpenFileName',
1071- **{'return_value': ('/new_path/file.ext', '')}) as mocked_get_open_file_name,\
1072- patch('openlp.core.ui.themeform.translate', **{'return_value': 'Translated String'}),\
1073- patch('openlp.core.ui.ThemeForm.set_background_page_values') as mocked_background_page_values:
1074- instance = ThemeForm(None)
1075- mocked_image_file_edit = MagicMock()
1076- mocked_image_file_edit.text.return_value = '/original_path/file.ext'
1077- instance.image_file_edit = mocked_image_file_edit
1078- instance.theme = MagicMock()
1079-
1080- # WHEN: on_image_browse_button is clicked
1081- instance.on_image_browse_button_clicked()
1082-
1083- # THEN: The QFileDialog getOpenFileName and set_background_page_values moethods should have been called
1084- # with known arguments and theme.background_filename should be set
1085- mocked_get_open_file_name.assert_called_once_with(instance, 'Translated String', '/original_path/file.ext',
1086- 'Image Files (*.bmp; *.gif)(*.bmp *.gif);;'
1087- 'All Files (*.*)')
1088- self.assertEqual(instance.theme.background_filename, '/new_path/file.ext',
1089- 'theme.background_filename should be set to the path that the file dialog returns')
1090- mocked_background_page_values.assert_called_once_with()
1091
1092=== modified file 'tests/functional/openlp_core_ui_lib/test_color_button.py'
1093--- tests/functional/openlp_core_ui_lib/test_color_button.py 2017-04-24 05:17:55 +0000
1094+++ tests/functional/openlp_core_ui_lib/test_color_button.py 2017-05-22 16:32:39 +0000
1095@@ -20,12 +20,12 @@
1096 # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1097 ###############################################################################
1098 """
1099-This module contains tests for the openlp.core.lib.filedialog module
1100+This module contains tests for the openlp.core.ui.lib.colorbutton module
1101 """
1102 from unittest import TestCase
1103 from unittest.mock import MagicMock, call, patch
1104
1105-from openlp.core.ui.lib.colorbutton import ColorButton
1106+from openlp.core.ui.lib import ColorButton
1107
1108
1109 class TestColorDialog(TestCase):
1110@@ -148,11 +148,10 @@
1111 widget.on_clicked()
1112
1113 # THEN: change_color should not have been called and the colorChanged signal should not have been emitted
1114- self.assertEqual(
1115- self.mocked_change_color.call_count, 0, 'change_color should not have been called with an invalid color')
1116- self.assertEqual(
1117- self.mocked_color_changed.emit.call_count, 0,
1118- 'colorChange signal should not have been emitted with an invalid color')
1119+ self.assertFalse(self.mocked_change_color.called,
1120+ 'change_color should not have been called with an invalid color')
1121+ self.assertFalse(self.mocked_color_changed.emit.called,
1122+ 'colorChange signal should not have been emitted with an invalid color')
1123
1124 def test_on_clicked_same_color(self):
1125 """
1126@@ -171,12 +170,10 @@
1127 widget.on_clicked()
1128
1129 # THEN: change_color should not have been called and the colorChanged signal should not have been emitted
1130- self.assertEqual(
1131- self.mocked_change_color.call_count, 0,
1132- 'change_color should not have been called when the color has not changed')
1133- self.assertEqual(
1134- self.mocked_color_changed.emit.call_count, 0,
1135- 'colorChange signal should not have been emitted when the color has not changed')
1136+ self.assertFalse(self.mocked_change_color.called,
1137+ 'change_color should not have been called when the color has not changed')
1138+ self.assertFalse(self.mocked_color_changed.emit.called,
1139+ 'colorChange signal should not have been emitted when the color has not changed')
1140
1141 def test_on_clicked_new_color(self):
1142 """
1143
1144=== added file 'tests/functional/openlp_core_ui_lib/test_path_edit.py'
1145--- tests/functional/openlp_core_ui_lib/test_path_edit.py 1970-01-01 00:00:00 +0000
1146+++ tests/functional/openlp_core_ui_lib/test_path_edit.py 2017-05-22 16:32:39 +0000
1147@@ -0,0 +1,311 @@
1148+# -*- coding: utf-8 -*-
1149+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1150+
1151+###############################################################################
1152+# OpenLP - Open Source Lyrics Projection #
1153+# --------------------------------------------------------------------------- #
1154+# Copyright (c) 2008-2017 OpenLP Developers #
1155+# --------------------------------------------------------------------------- #
1156+# This program is free software; you can redistribute it and/or modify it #
1157+# under the terms of the GNU General Public License as published by the Free #
1158+# Software Foundation; version 2 of the License. #
1159+# #
1160+# This program is distributed in the hope that it will be useful, but WITHOUT #
1161+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
1162+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
1163+# more details. #
1164+# #
1165+# You should have received a copy of the GNU General Public License along #
1166+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
1167+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1168+###############################################################################
1169+"""
1170+This module contains tests for the openlp.core.ui.lib.pathedit module
1171+"""
1172+from unittest import TestCase
1173+
1174+from PyQt5 import QtWidgets
1175+
1176+from openlp.core.ui.lib import PathEdit, PathType
1177+from unittest.mock import MagicMock, PropertyMock, patch
1178+
1179+
1180+class TestPathEdit(TestCase):
1181+ """
1182+ Test the :class:`~openlp.core.lib.pathedit.PathEdit` class
1183+ """
1184+ def setUp(self):
1185+ with patch('openlp.core.ui.lib.pathedit.PathEdit._setup'):
1186+ self.widget = PathEdit()
1187+
1188+ def test_path_getter(self):
1189+ """
1190+ Test the `path` property getter.
1191+ """
1192+ # GIVEN: An instance of PathEdit with the `_path` instance variable set
1193+ self.widget._path = 'getter/test/pat.h'
1194+
1195+ # WHEN: Reading the `path` property
1196+ # THEN: The value that we set should be returned
1197+ self.assertEqual(self.widget.path, 'getter/test/pat.h')
1198+
1199+ def test_path_setter(self):
1200+ """
1201+ Test the `path` property setter.
1202+ """
1203+ # GIVEN: An instance of the PathEdit object and a mocked `line_edit`
1204+ self.widget.line_edit = MagicMock()
1205+
1206+ # WHEN: Writing to the `path` property
1207+ self.widget.path = 'setter/test/pat.h'
1208+
1209+ # THEN: The `_path` instance variable should be set with the test data. The `line_edit` text and tooltip
1210+ # should have also been set.
1211+ self.assertEqual(self.widget._path, 'setter/test/pat.h')
1212+ self.widget.line_edit.setToolTip.assert_called_once_with('setter/test/pat.h')
1213+ self.widget.line_edit.setText.assert_called_once_with('setter/test/pat.h')
1214+
1215+ def test_path_type_getter(self):
1216+ """
1217+ Test the `path_type` property getter.
1218+ """
1219+ # GIVEN: An instance of PathEdit
1220+ # WHEN: Reading the `path` property
1221+ # THEN: The default value should be returned
1222+ self.assertEqual(self.widget.path_type, PathType.Files)
1223+
1224+ def test_path_type_setter(self):
1225+ """
1226+ Test the `path_type` property setter.
1227+ """
1228+ # GIVEN: An instance of the PathEdit object and a mocked `update_button_tool_tips` method.
1229+ with patch.object(self.widget, 'update_button_tool_tips') as mocked_update_button_tool_tips:
1230+
1231+ # WHEN: Writing to a different value than default to the `path_type` property
1232+ self.widget.path_type = PathType.Directories
1233+
1234+ # THEN: The `_path_type` instance variable should be set with the test data and not the default. The
1235+ # update_button_tool_tips should have been called.
1236+ self.assertEqual(self.widget._path_type, PathType.Directories)
1237+ mocked_update_button_tool_tips.assert_called_once_with()
1238+
1239+ def test_update_button_tool_tips_directories(self):
1240+ """
1241+ Test the `update_button_tool_tips` method.
1242+ """
1243+ # GIVEN: An instance of PathEdit with the `path_type` set to `Directories`
1244+ self.widget.browse_button = MagicMock()
1245+ self.widget.revert_button = MagicMock()
1246+ self.widget._path_type = PathType.Directories
1247+
1248+ # WHEN: Calling update_button_tool_tips
1249+ self.widget.update_button_tool_tips()
1250+
1251+ self.widget.browse_button.setToolTip.assert_called_once_with('Browse for directory.')
1252+ self.widget.revert_button.setToolTip.assert_called_once_with('Revert to default directory.')
1253+
1254+ def test_update_button_tool_tips_files(self):
1255+ """
1256+ Test the `update_button_tool_tips` method.
1257+ """
1258+ # GIVEN: An instance of PathEdit with the `path_type` set to `Files`
1259+ self.widget.browse_button = MagicMock()
1260+ self.widget.revert_button = MagicMock()
1261+ self.widget._path_type = PathType.Files
1262+
1263+ # WHEN: Calling update_button_tool_tips
1264+ self.widget.update_button_tool_tips()
1265+
1266+ self.widget.browse_button.setToolTip.assert_called_once_with('Browse for file.')
1267+ self.widget.revert_button.setToolTip.assert_called_once_with('Revert to default file.')
1268+
1269+ def test_on_browse_button_clicked_directory(self):
1270+ """
1271+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the `path_type` is set to Directories.
1272+ """
1273+ # GIVEN: An instance of PathEdit with the `path_type` set to `Directories` and a mocked
1274+ # QFileDialog.getExistingDirectory
1275+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getExistingDirectory', return_value='') as \
1276+ mocked_get_existing_directory, \
1277+ patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName') as \
1278+ mocked_get_open_file_name, \
1279+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath:
1280+ self.widget._path_type = PathType.Directories
1281+ self.widget._path = 'test/path/'
1282+
1283+ # WHEN: Calling on_browse_button_clicked
1284+ self.widget.on_browse_button_clicked()
1285+
1286+ # THEN: The FileDialog.getExistingDirectory should have been called with the default caption
1287+ mocked_get_existing_directory.assert_called_once_with(self.widget, 'Select Directory', 'test/path/',
1288+ QtWidgets.QFileDialog.ShowDirsOnly)
1289+ self.assertFalse(mocked_get_open_file_name.called)
1290+ self.assertFalse(mocked_normpath.called)
1291+
1292+ def test_on_browse_button_clicked_directory_custom_caption(self):
1293+ """
1294+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the `path_type` is set to Directories,
1295+ and `dialog_caption` is set.
1296+ """
1297+ # GIVEN: An instance of PathEdit with the `path_type` set to `Directories` and a mocked
1298+ # QFileDialog.getExistingDirectory with `default_caption` set.
1299+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getExistingDirectory', return_value='') as \
1300+ mocked_get_existing_directory, \
1301+ patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName') as \
1302+ mocked_get_open_file_name, \
1303+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath:
1304+ self.widget._path_type = PathType.Directories
1305+ self.widget._path = 'test/path/'
1306+ self.widget.dialog_caption = 'Directory Caption'
1307+
1308+ # WHEN: Calling on_browse_button_clicked
1309+ self.widget.on_browse_button_clicked()
1310+
1311+ # THEN: The FileDialog.getExistingDirectory should have been called with the custom caption
1312+ mocked_get_existing_directory.assert_called_once_with(self.widget, 'Directory Caption', 'test/path/',
1313+ QtWidgets.QFileDialog.ShowDirsOnly)
1314+ self.assertFalse(mocked_get_open_file_name.called)
1315+ self.assertFalse(mocked_normpath.called)
1316+
1317+ def test_on_browse_button_clicked_file(self):
1318+ """
1319+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the `path_type` is set to Files.
1320+ """
1321+ # GIVEN: An instance of PathEdit with the `path_type` set to `Files` and a mocked QFileDialog.getOpenFileName
1322+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getExistingDirectory') as \
1323+ mocked_get_existing_directory, \
1324+ patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName', return_value=('', '')) as \
1325+ mocked_get_open_file_name, \
1326+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath:
1327+ self.widget._path_type = PathType.Files
1328+ self.widget._path = 'test/pat.h'
1329+
1330+ # WHEN: Calling on_browse_button_clicked
1331+ self.widget.on_browse_button_clicked()
1332+
1333+ # THEN: The FileDialog.getOpenFileName should have been called with the default caption
1334+ mocked_get_open_file_name.assert_called_once_with(self.widget, 'Select File', 'test/pat.h',
1335+ self.widget.filters)
1336+ self.assertFalse(mocked_get_existing_directory.called)
1337+ self.assertFalse(mocked_normpath.called)
1338+
1339+ def test_on_browse_button_clicked_file_custom_caption(self):
1340+ """
1341+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the `path_type` is set to Files and
1342+ `dialog_caption` is set.
1343+ """
1344+ # GIVEN: An instance of PathEdit with the `path_type` set to `Files` and a mocked QFileDialog.getOpenFileName
1345+ # with `default_caption` set.
1346+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getExistingDirectory') as \
1347+ mocked_get_existing_directory, \
1348+ patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName', return_value=('', '')) as \
1349+ mocked_get_open_file_name, \
1350+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath:
1351+ self.widget._path_type = PathType.Files
1352+ self.widget._path = 'test/pat.h'
1353+ self.widget.dialog_caption = 'File Caption'
1354+
1355+ # WHEN: Calling on_browse_button_clicked
1356+ self.widget.on_browse_button_clicked()
1357+
1358+ # THEN: The FileDialog.getOpenFileName should have been called with the custom caption
1359+ mocked_get_open_file_name.assert_called_once_with(self.widget, 'File Caption', 'test/pat.h',
1360+ self.widget.filters)
1361+ self.assertFalse(mocked_get_existing_directory.called)
1362+ self.assertFalse(mocked_normpath.called)
1363+
1364+ def test_on_browse_button_clicked_user_cancels(self):
1365+ """
1366+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the user cancels the FileDialog (an
1367+ empty str is returned)
1368+ """
1369+ # GIVEN: An instance of PathEdit with a mocked QFileDialog.getOpenFileName which returns an empty str for the
1370+ # file path.
1371+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName', return_value=('', '')) as \
1372+ mocked_get_open_file_name, \
1373+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath:
1374+
1375+ # WHEN: Calling on_browse_button_clicked
1376+ self.widget.on_browse_button_clicked()
1377+
1378+ # THEN: normpath should not have been called
1379+ self.assertTrue(mocked_get_open_file_name.called)
1380+ self.assertFalse(mocked_normpath.called)
1381+
1382+ def test_on_browse_button_clicked_user_accepts(self):
1383+ """
1384+ Test the `browse_button` `clicked` handler on_browse_button_clicked when the user accepts the FileDialog (a path
1385+ is returned)
1386+ """
1387+ # GIVEN: An instance of PathEdit with a mocked QFileDialog.getOpenFileName which returns a str for the file
1388+ # path.
1389+ with patch('openlp.core.ui.lib.pathedit.QtWidgets.QFileDialog.getOpenFileName',
1390+ return_value=('/test/pat.h', '')) as mocked_get_open_file_name, \
1391+ patch('openlp.core.ui.lib.pathedit.os.path.normpath') as mocked_normpath, \
1392+ patch.object(self.widget, 'on_new_path'):
1393+
1394+ # WHEN: Calling on_browse_button_clicked
1395+ self.widget.on_browse_button_clicked()
1396+
1397+ # THEN: normpath and `on_new_path` should have been called
1398+ self.assertTrue(mocked_get_open_file_name.called)
1399+ mocked_normpath.assert_called_once_with('/test/pat.h')
1400+ self.assertTrue(self.widget.on_new_path.called)
1401+
1402+ def test_on_revert_button_clicked(self):
1403+ """
1404+ Test that the default path is set as the path when the `revert_button.clicked` handler is called.
1405+ """
1406+ # GIVEN: An instance of PathEdit with a mocked `on_new_path`, and the `default_path` set.
1407+ with patch.object(self.widget, 'on_new_path') as mocked_on_new_path:
1408+ self.widget.default_path = '/default/pat.h'
1409+
1410+ # WHEN: Calling `on_revert_button_clicked`
1411+ self.widget.on_revert_button_clicked()
1412+
1413+ # THEN: on_new_path should have been called with the default path
1414+ mocked_on_new_path.assert_called_once_with('/default/pat.h')
1415+
1416+ def test_on_line_edit_editing_finished(self):
1417+ """
1418+ Test that the new path is set as the path when the `line_edit.editingFinished` handler is called.
1419+ """
1420+ # GIVEN: An instance of PathEdit with a mocked `line_edit` and `on_new_path`.
1421+ with patch.object(self.widget, 'on_new_path') as mocked_on_new_path:
1422+ self.widget.line_edit = MagicMock(**{'text.return_value': '/test/pat.h'})
1423+
1424+ # WHEN: Calling `on_line_edit_editing_finished`
1425+ self.widget.on_line_edit_editing_finished()
1426+
1427+ # THEN: on_new_path should have been called with the path enetered in `line_edit`
1428+ mocked_on_new_path.assert_called_once_with('/test/pat.h')
1429+
1430+ def test_on_new_path_no_change(self):
1431+ """
1432+ Test `on_new_path` when called with a path that is the same as the existing path.
1433+ """
1434+ # GIVEN: An instance of PathEdit with a test path and mocked `pathChanged` signal
1435+ with patch('openlp.core.ui.lib.pathedit.PathEdit.path', new_callable=PropertyMock):
1436+ self.widget._path = '/old/test/pat.h'
1437+ self.widget.pathChanged = MagicMock()
1438+
1439+ # WHEN: Calling `on_new_path` with the same path as the existing path
1440+ self.widget.on_new_path('/old/test/pat.h')
1441+
1442+ # THEN: The `pathChanged` signal should not be emitted
1443+ self.assertFalse(self.widget.pathChanged.emit.called)
1444+
1445+ def test_on_new_path_change(self):
1446+ """
1447+ Test `on_new_path` when called with a path that is the different to the existing path.
1448+ """
1449+ # GIVEN: An instance of PathEdit with a test path and mocked `pathChanged` signal
1450+ with patch('openlp.core.ui.lib.pathedit.PathEdit.path', new_callable=PropertyMock):
1451+ self.widget._path = '/old/test/pat.h'
1452+ self.widget.pathChanged = MagicMock()
1453+
1454+ # WHEN: Calling `on_new_path` with the a new path
1455+ self.widget.on_new_path('/new/test/pat.h')
1456+
1457+ # THEN: The `pathChanged` signal should be emitted
1458+ self.widget.pathChanged.emit.assert_called_once_with('/new/test/pat.h')
1459
1460=== modified file 'tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py'
1461--- tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py 2017-05-06 09:22:34 +0000
1462+++ tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py 2017-05-22 16:32:39 +0000
1463@@ -28,11 +28,12 @@
1464 from PyQt5 import QtWidgets
1465
1466 from openlp.core.common import Registry
1467-from openlp.plugins.bibles.forms import bibleimportform
1468+from openlp.plugins.bibles.forms.bibleimportform import BibleImportForm, PYSWORD_AVAILABLE
1469
1470 from tests.helpers.testmixin import TestMixin
1471
1472
1473+@skip('One of the QFormLayouts in the BibleImportForm is causing a segfault')
1474 class TestBibleImportForm(TestCase, TestMixin):
1475 """
1476 Test the BibleImportForm class
1477@@ -46,9 +47,9 @@
1478 self.setup_application()
1479 self.main_window = QtWidgets.QMainWindow()
1480 Registry().register('main_window', self.main_window)
1481- bibleimportform.PYSWORD_AVAILABLE = False
1482+ PYSWORD_AVAILABLE = False
1483 self.mocked_manager = MagicMock()
1484- self.form = bibleimportform.BibleImportForm(self.main_window, self.mocked_manager, MagicMock())
1485+ self.form = BibleImportForm(self.main_window, self.mocked_manager, MagicMock())
1486
1487 def tearDown(self):
1488 """