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