Merge lp:~raoul-snyman/openlp/dark-style into lp:openlp
- dark-style
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 2772 |
Proposed branch: | lp:~raoul-snyman/openlp/dark-style |
Merge into: | lp:openlp |
Diff against target: |
500 lines (+280/-92) 6 files modified
openlp/core/__init__.py (+3/-30) openlp/core/common/settings.py (+1/-0) openlp/core/ui/advancedtab.py (+54/-41) openlp/core/ui/mainwindow.py (+2/-21) openlp/core/ui/style.py (+109/-0) tests/functional/openlp_core_ui/test_style.py (+111/-0) |
To merge this branch: | bzr merge lp:~raoul-snyman/openlp/dark-style |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Bentley | Approve | ||
Review via email: mp+331593@code.launchpad.net |
This proposal supersedes a proposal from 2017-09-29.
Commit message
Description of the change
Enable the use of QDarkStyle, if it is installed. This is mainly for those users on Windows and macOS who want a dark theme.
QDarkStyle is only pip-installable at present, but we can include it in the PyInstaller builds.
Add this to your merge proposal:
-------
lp:~raoul-snyman/openlp/dark-style (revision 2773)
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[FAILURE] https:/
Stopping after failure
Tim Bentley (trb143) : | # |
Preview Diff
1 | === modified file 'openlp/core/__init__.py' |
2 | --- openlp/core/__init__.py 2017-09-23 04:04:41 +0000 |
3 | +++ openlp/core/__init__.py 2017-09-29 17:16:28 +0000 |
4 | @@ -46,34 +46,14 @@ |
5 | from openlp.core.ui.firsttimeform import FirstTimeForm |
6 | from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm |
7 | from openlp.core.ui.mainwindow import MainWindow |
8 | +from openlp.core.ui.style import get_application_stylesheet |
9 | + |
10 | |
11 | __all__ = ['OpenLP', 'main'] |
12 | |
13 | |
14 | log = logging.getLogger() |
15 | |
16 | -WIN_REPAIR_STYLESHEET = """ |
17 | -QMainWindow::separator |
18 | -{ |
19 | - border: none; |
20 | -} |
21 | - |
22 | -QDockWidget::title |
23 | -{ |
24 | - border: 1px solid palette(dark); |
25 | - padding-left: 5px; |
26 | - padding-top: 2px; |
27 | - margin: 1px 0; |
28 | -} |
29 | - |
30 | -QToolBar |
31 | -{ |
32 | - border: none; |
33 | - margin: 0; |
34 | - padding: 0; |
35 | -} |
36 | -""" |
37 | - |
38 | |
39 | class OpenLP(OpenLPMixin, QtWidgets.QApplication): |
40 | """ |
41 | @@ -118,14 +98,7 @@ |
42 | QtCore.QCoreApplication.exit() |
43 | sys.exit() |
44 | # Correct stylesheet bugs |
45 | - application_stylesheet = '' |
46 | - if not Settings().value('advanced/alternate rows'): |
47 | - base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) |
48 | - alternate_rows_repair_stylesheet = \ |
49 | - 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' |
50 | - application_stylesheet += alternate_rows_repair_stylesheet |
51 | - if is_win(): |
52 | - application_stylesheet += WIN_REPAIR_STYLESHEET |
53 | + application_stylesheet = get_application_stylesheet() |
54 | if application_stylesheet: |
55 | self.setStyleSheet(application_stylesheet) |
56 | can_show_splash = Settings().value('core/show splash') |
57 | |
58 | === modified file 'openlp/core/common/settings.py' |
59 | --- openlp/core/common/settings.py 2017-09-09 20:00:48 +0000 |
60 | +++ openlp/core/common/settings.py 2017-09-29 17:16:28 +0000 |
61 | @@ -136,6 +136,7 @@ |
62 | 'advanced/single click service preview': False, |
63 | 'advanced/x11 bypass wm': X11_BYPASS_DEFAULT, |
64 | 'advanced/search as type': True, |
65 | + 'advanced/use_dark_style': False, |
66 | 'api/twelve hour': True, |
67 | 'api/port': 4316, |
68 | 'api/websocket port': 4317, |
69 | |
70 | === modified file 'openlp/core/ui/advancedtab.py' |
71 | --- openlp/core/ui/advancedtab.py 2017-09-24 20:26:39 +0000 |
72 | +++ openlp/core/ui/advancedtab.py 2017-09-29 17:16:28 +0000 |
73 | @@ -32,6 +32,7 @@ |
74 | from openlp.core.common.path import path_to_str |
75 | from openlp.core.lib import SettingsTab, build_icon |
76 | from openlp.core.ui.lib import PathEdit, PathType |
77 | +from openlp.core.ui.style import HAS_DARK_STYLE |
78 | |
79 | log = logging.getLogger(__name__) |
80 | |
81 | @@ -109,45 +110,10 @@ |
82 | self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box') |
83 | self.ui_layout.addRow(self.enable_auto_close_check_box) |
84 | self.left_layout.addWidget(self.ui_group_box) |
85 | - # Default service name |
86 | - self.service_name_group_box = QtWidgets.QGroupBox(self.left_column) |
87 | - self.service_name_group_box.setObjectName('service_name_group_box') |
88 | - self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box) |
89 | - self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box) |
90 | - self.service_name_check_box.setObjectName('service_name_check_box') |
91 | - self.service_name_layout.setObjectName('service_name_layout') |
92 | - self.service_name_layout.addRow(self.service_name_check_box) |
93 | - self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box) |
94 | - self.service_name_time_label.setObjectName('service_name_time_label') |
95 | - self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box) |
96 | - self.service_name_day.addItems(['', '', '', '', '', '', '', '']) |
97 | - self.service_name_day.setObjectName('service_name_day') |
98 | - self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box) |
99 | - self.service_name_time.setObjectName('service_name_time') |
100 | - self.service_name_time_layout = QtWidgets.QHBoxLayout() |
101 | - self.service_name_time_layout.setObjectName('service_name_time_layout') |
102 | - self.service_name_time_layout.addWidget(self.service_name_day) |
103 | - self.service_name_time_layout.addWidget(self.service_name_time) |
104 | - self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout) |
105 | - self.service_name_label = QtWidgets.QLabel(self.service_name_group_box) |
106 | - self.service_name_label.setObjectName('service_name_label') |
107 | - self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box) |
108 | - self.service_name_edit.setObjectName('service_name_edit') |
109 | - self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self)) |
110 | - self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box) |
111 | - self.service_name_revert_button.setObjectName('service_name_revert_button') |
112 | - self.service_name_revert_button.setIcon(build_icon(':/general/general_revert.png')) |
113 | - self.service_name_button_layout = QtWidgets.QHBoxLayout() |
114 | - self.service_name_button_layout.setObjectName('service_name_button_layout') |
115 | - self.service_name_button_layout.addWidget(self.service_name_edit) |
116 | - self.service_name_button_layout.addWidget(self.service_name_revert_button) |
117 | - self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout) |
118 | - self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box) |
119 | - self.service_name_example_label.setObjectName('service_name_example_label') |
120 | - self.service_name_example = QtWidgets.QLabel(self.service_name_group_box) |
121 | - self.service_name_example.setObjectName('service_name_example') |
122 | - self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example) |
123 | - self.left_layout.addWidget(self.service_name_group_box) |
124 | + if HAS_DARK_STYLE: |
125 | + self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box) |
126 | + self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox') |
127 | + self.ui_layout.addRow(self.use_dark_style_checkbox) |
128 | # Data Directory |
129 | self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column) |
130 | self.data_directory_group_box.setObjectName('data_directory_group_box') |
131 | @@ -174,7 +140,6 @@ |
132 | self.data_directory_layout.addRow(self.data_directory_copy_check_layout) |
133 | self.data_directory_layout.addRow(self.new_data_directory_has_files_label) |
134 | self.left_layout.addWidget(self.data_directory_group_box) |
135 | - self.left_layout.addStretch() |
136 | # Hide mouse |
137 | self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column) |
138 | self.hide_mouse_group_box.setObjectName('hide_mouse_group_box') |
139 | @@ -203,7 +168,7 @@ |
140 | self.slide_layout.addWidget(self.next_item_radio_button) |
141 | self.right_layout.addWidget(self.slide_group_box) |
142 | # Display Workarounds |
143 | - self.display_workaround_group_box = QtWidgets.QGroupBox(self.left_column) |
144 | + self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column) |
145 | self.display_workaround_group_box.setObjectName('display_workaround_group_box') |
146 | self.display_workaround_layout = QtWidgets.QVBoxLayout(self.display_workaround_group_box) |
147 | self.display_workaround_layout.setObjectName('display_workaround_layout') |
148 | @@ -217,7 +182,49 @@ |
149 | self.alternate_rows_check_box.setObjectName('alternate_rows_check_box') |
150 | self.display_workaround_layout.addWidget(self.alternate_rows_check_box) |
151 | self.right_layout.addWidget(self.display_workaround_group_box) |
152 | + # Default service name |
153 | + self.service_name_group_box = QtWidgets.QGroupBox(self.right_column) |
154 | + self.service_name_group_box.setObjectName('service_name_group_box') |
155 | + self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box) |
156 | + self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box) |
157 | + self.service_name_check_box.setObjectName('service_name_check_box') |
158 | + self.service_name_layout.setObjectName('service_name_layout') |
159 | + self.service_name_layout.addRow(self.service_name_check_box) |
160 | + self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box) |
161 | + self.service_name_time_label.setObjectName('service_name_time_label') |
162 | + self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box) |
163 | + self.service_name_day.addItems(['', '', '', '', '', '', '', '']) |
164 | + self.service_name_day.setObjectName('service_name_day') |
165 | + self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box) |
166 | + self.service_name_time.setObjectName('service_name_time') |
167 | + self.service_name_time_layout = QtWidgets.QHBoxLayout() |
168 | + self.service_name_time_layout.setObjectName('service_name_time_layout') |
169 | + self.service_name_time_layout.addWidget(self.service_name_day) |
170 | + self.service_name_time_layout.addWidget(self.service_name_time) |
171 | + self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout) |
172 | + self.service_name_label = QtWidgets.QLabel(self.service_name_group_box) |
173 | + self.service_name_label.setObjectName('service_name_label') |
174 | + self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box) |
175 | + self.service_name_edit.setObjectName('service_name_edit') |
176 | + self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self)) |
177 | + self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box) |
178 | + self.service_name_revert_button.setObjectName('service_name_revert_button') |
179 | + self.service_name_revert_button.setIcon(build_icon(':/general/general_revert.png')) |
180 | + self.service_name_button_layout = QtWidgets.QHBoxLayout() |
181 | + self.service_name_button_layout.setObjectName('service_name_button_layout') |
182 | + self.service_name_button_layout.addWidget(self.service_name_edit) |
183 | + self.service_name_button_layout.addWidget(self.service_name_revert_button) |
184 | + self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout) |
185 | + self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box) |
186 | + self.service_name_example_label.setObjectName('service_name_example_label') |
187 | + self.service_name_example = QtWidgets.QLabel(self.service_name_group_box) |
188 | + self.service_name_example.setObjectName('service_name_example') |
189 | + self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example) |
190 | + self.right_layout.addWidget(self.service_name_group_box) |
191 | + # After the last item on each side, add some spacing |
192 | + self.left_layout.addStretch() |
193 | self.right_layout.addStretch() |
194 | + # Set up all the connections and things |
195 | self.should_update_service_name_example = False |
196 | self.service_name_check_box.toggled.connect(self.service_name_check_box_toggled) |
197 | self.service_name_day.currentIndexChanged.connect(self.on_service_name_day_changed) |
198 | @@ -282,6 +289,8 @@ |
199 | 'Auto-scroll the next slide to bottom')) |
200 | self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', |
201 | 'Enable application exit confirmation')) |
202 | + if HAS_DARK_STYLE: |
203 | + self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) |
204 | self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name')) |
205 | self.service_name_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable default service name')) |
206 | self.service_name_time_label.setText(translate('OpenLP.AdvancedTab', 'Date and Time:')) |
207 | @@ -349,6 +358,8 @@ |
208 | if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count(): |
209 | self.autoscroll_combo_box.setCurrentIndex(i) |
210 | self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation')) |
211 | + if HAS_DARK_STYLE: |
212 | + self.use_dark_style_checkbox.setChecked(settings.value('use_dark_style')) |
213 | self.hide_mouse_check_box.setChecked(settings.value('hide mouse')) |
214 | self.service_name_day.setCurrentIndex(settings.value('default service day')) |
215 | self.service_name_time.setTime(QtCore.QTime(settings.value('default service hour'), |
216 | @@ -420,6 +431,8 @@ |
217 | self.settings_form.register_post_process('config_screen_changed') |
218 | self.settings_form.register_post_process('slidecontroller_update_slide_limits') |
219 | settings.setValue('search as type', self.is_search_as_you_type_enabled) |
220 | + if HAS_DARK_STYLE: |
221 | + settings.setValue('use_dark_style', self.use_dark_style_checkbox.isChecked()) |
222 | settings.endGroup() |
223 | |
224 | def on_search_as_type_check_box_changed(self, check_state): |
225 | |
226 | === modified file 'openlp/core/ui/mainwindow.py' |
227 | --- openlp/core/ui/mainwindow.py 2017-09-25 19:55:33 +0000 |
228 | +++ openlp/core/ui/mainwindow.py 2017-09-29 17:16:28 +0000 |
229 | @@ -51,31 +51,12 @@ |
230 | from openlp.core.ui.lib.dockwidget import OpenLPDockWidget |
231 | from openlp.core.ui.lib.filedialog import FileDialog |
232 | from openlp.core.ui.lib.mediadockmanager import MediaDockManager |
233 | +from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet |
234 | from openlp.core.version import get_version |
235 | |
236 | |
237 | log = logging.getLogger(__name__) |
238 | |
239 | -MEDIA_MANAGER_STYLE = """ |
240 | -::tab#media_tool_box { |
241 | - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
242 | - stop: 0 palette(button), stop: 1.0 palette(mid)); |
243 | - border: 0; |
244 | - border-radius: 2px; |
245 | - margin-top: 0; |
246 | - margin-bottom: 0; |
247 | - text-align: left; |
248 | -} |
249 | -/* This is here to make the tabs on KDE with the Breeze theme work */ |
250 | -::tab:selected {} |
251 | -""" |
252 | - |
253 | -PROGRESSBAR_STYLE = """ |
254 | -QProgressBar{ |
255 | - height: 10px; |
256 | -} |
257 | -""" |
258 | - |
259 | |
260 | class Ui_MainWindow(object): |
261 | """ |
262 | @@ -155,7 +136,7 @@ |
263 | # Create the MediaManager |
264 | self.media_manager_dock = OpenLPDockWidget(main_window, 'media_manager_dock', |
265 | ':/system/system_mediamanager.png') |
266 | - self.media_manager_dock.setStyleSheet(MEDIA_MANAGER_STYLE) |
267 | + self.media_manager_dock.setStyleSheet(get_library_stylesheet()) |
268 | # Create the media toolbox |
269 | self.media_tool_box = QtWidgets.QToolBox(self.media_manager_dock) |
270 | self.media_tool_box.setObjectName('media_tool_box') |
271 | |
272 | === added file 'openlp/core/ui/style.py' |
273 | --- openlp/core/ui/style.py 1970-01-01 00:00:00 +0000 |
274 | +++ openlp/core/ui/style.py 2017-09-29 17:16:28 +0000 |
275 | @@ -0,0 +1,109 @@ |
276 | +# -*- coding: utf-8 -*- |
277 | +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 |
278 | + |
279 | +############################################################################### |
280 | +# OpenLP - Open Source Lyrics Projection # |
281 | +# --------------------------------------------------------------------------- # |
282 | +# Copyright (c) 2008-2017 OpenLP Developers # |
283 | +# --------------------------------------------------------------------------- # |
284 | +# This program is free software; you can redistribute it and/or modify it # |
285 | +# under the terms of the GNU General Public License as published by the Free # |
286 | +# Software Foundation; version 2 of the License. # |
287 | +# # |
288 | +# This program is distributed in the hope that it will be useful, but WITHOUT # |
289 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # |
290 | +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # |
291 | +# more details. # |
292 | +# # |
293 | +# You should have received a copy of the GNU General Public License along # |
294 | +# with this program; if not, write to the Free Software Foundation, Inc., 59 # |
295 | +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
296 | +############################################################################### |
297 | +""" |
298 | +The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme |
299 | +""" |
300 | +from PyQt5 import QtGui |
301 | + |
302 | +from openlp.core.common import is_macosx, is_win |
303 | +from openlp.core.common.registry import Registry |
304 | +from openlp.core.common.settings import Settings |
305 | + |
306 | +try: |
307 | + import qdarkstyle |
308 | + HAS_DARK_STYLE = True |
309 | +except ImportError: |
310 | + HAS_DARK_STYLE = False |
311 | + |
312 | +WIN_REPAIR_STYLESHEET = """ |
313 | +QMainWindow::separator |
314 | +{ |
315 | + border: none; |
316 | +} |
317 | + |
318 | +QDockWidget::title |
319 | +{ |
320 | + border: 1px solid palette(dark); |
321 | + padding-left: 5px; |
322 | + padding-top: 2px; |
323 | + margin: 1px 0; |
324 | +} |
325 | + |
326 | +QToolBar |
327 | +{ |
328 | + border: none; |
329 | + margin: 0; |
330 | + padding: 0; |
331 | +} |
332 | +""" |
333 | + |
334 | +MEDIA_MANAGER_STYLE = """ |
335 | +::tab#media_tool_box { |
336 | + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
337 | + stop: 0 palette(button), stop: 1.0 palette(mid)); |
338 | + border: 0; |
339 | + border-radius: 2px; |
340 | + margin-top: 0; |
341 | + margin-bottom: 0; |
342 | + text-align: left; |
343 | +} |
344 | +/* This is here to make the tabs on KDE with the Breeze theme work */ |
345 | +::tab:selected {} |
346 | +""" |
347 | + |
348 | +PROGRESSBAR_STYLE = """ |
349 | +QProgressBar{ |
350 | + height: 10px; |
351 | +} |
352 | +""" |
353 | + |
354 | + |
355 | +def get_application_stylesheet(): |
356 | + """ |
357 | + Return the correct application stylesheet based on the current style and operating system |
358 | + |
359 | + :return str: The correct stylesheet as a string |
360 | + """ |
361 | + stylesheet = '' |
362 | + if HAS_DARK_STYLE and Settings().value('advanced/use_dark_style'): |
363 | + stylesheet = qdarkstyle.load_stylesheet_pyqt5() |
364 | + else: |
365 | + if not Settings().value('advanced/alternate rows'): |
366 | + base_color = Registry().get('application').palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) |
367 | + alternate_rows_repair_stylesheet = \ |
368 | + 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' |
369 | + stylesheet += alternate_rows_repair_stylesheet |
370 | + if is_win(): |
371 | + stylesheet += WIN_REPAIR_STYLESHEET |
372 | + return stylesheet |
373 | + |
374 | + |
375 | +def get_library_stylesheet(): |
376 | + """ |
377 | + Return the correct stylesheet for the main window |
378 | + |
379 | + :return str: The correct stylesheet as a string |
380 | + """ |
381 | + if not HAS_DARK_STYLE or not Settings().value('advanced/use_dark_style'): |
382 | + return MEDIA_MANAGER_STYLE |
383 | + else: |
384 | + return '' |
385 | |
386 | === added file 'tests/functional/openlp_core_ui/test_style.py' |
387 | --- tests/functional/openlp_core_ui/test_style.py 1970-01-01 00:00:00 +0000 |
388 | +++ tests/functional/openlp_core_ui/test_style.py 2017-09-29 17:16:28 +0000 |
389 | @@ -0,0 +1,111 @@ |
390 | +# -*- coding: utf-8 -*- |
391 | +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 |
392 | + |
393 | +############################################################################### |
394 | +# OpenLP - Open Source Lyrics Projection # |
395 | +# --------------------------------------------------------------------------- # |
396 | +# Copyright (c) 2008-2017 OpenLP Developers # |
397 | +# --------------------------------------------------------------------------- # |
398 | +# This program is free software; you can redistribute it and/or modify it # |
399 | +# under the terms of the GNU General Public License as published by the Free # |
400 | +# Software Foundation; version 2 of the License. # |
401 | +# # |
402 | +# This program is distributed in the hope that it will be useful, but WITHOUT # |
403 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # |
404 | +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # |
405 | +# more details. # |
406 | +# # |
407 | +# You should have received a copy of the GNU General Public License along # |
408 | +# with this program; if not, write to the Free Software Foundation, Inc., 59 # |
409 | +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
410 | +############################################################################### |
411 | +""" |
412 | +Package to test the :mod:`~openlp.core.ui.style` module. |
413 | +""" |
414 | +from unittest.mock import MagicMock, patch |
415 | + |
416 | +import openlp.core.ui.style |
417 | +from openlp.core.ui.style import MEDIA_MANAGER_STYLE, WIN_REPAIR_STYLESHEET, get_application_stylesheet, \ |
418 | + get_library_stylesheet |
419 | + |
420 | + |
421 | +@patch('openlp.core.ui.style.HAS_DARK_STYLE', True) |
422 | +@patch('openlp.core.ui.style.Settings') |
423 | +@patch.object(openlp.core.ui.style, 'qdarkstyle') |
424 | +def test_get_application_stylesheet_dark(mocked_qdarkstyle, MockSettings): |
425 | + """Test that the dark stylesheet is returned when available and enabled""" |
426 | + # GIVEN: We're on Windows and no dark style is set |
427 | + mocked_settings = MagicMock() |
428 | + mocked_settings.value.return_value = True |
429 | + MockSettings.return_value = mocked_settings |
430 | + mocked_qdarkstyle.load_stylesheet_pyqt5.return_value = 'dark_style' |
431 | + |
432 | + # WHEN: can_show_icon() is called |
433 | + result = get_application_stylesheet() |
434 | + |
435 | + # THEN: the result should be false |
436 | + assert result == 'dark_style' |
437 | + |
438 | + |
439 | +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) |
440 | +@patch('openlp.core.ui.style.is_win') |
441 | +@patch('openlp.core.ui.style.Settings') |
442 | +@patch('openlp.core.ui.style.Registry') |
443 | +def test_get_application_stylesheet_not_alternate_rows(MockRegistry, MockSettings, mocked_is_win): |
444 | + """Test that the alternate rows stylesheet is returned when enabled in settings""" |
445 | + # GIVEN: We're on Windows and no dark style is set |
446 | + mocked_is_win.return_value = False |
447 | + MockSettings.return_value.value.return_value = False |
448 | + MockRegistry.return_value.get.return_value.palette.return_value.color.return_value.name.return_value = 'color' |
449 | + |
450 | + # WHEN: can_show_icon() is called |
451 | + result = get_application_stylesheet() |
452 | + |
453 | + # THEN: the result should be false |
454 | + MockSettings.return_value.value.assert_called_once_with('advanced/alternate rows') |
455 | + assert result == 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: color;}\n', result |
456 | + |
457 | + |
458 | +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) |
459 | +@patch('openlp.core.ui.style.is_win') |
460 | +@patch('openlp.core.ui.style.Settings') |
461 | +def test_get_application_stylesheet_win_repair(MockSettings, mocked_is_win): |
462 | + """Test that the Windows repair stylesheet is returned when on Windows""" |
463 | + # GIVEN: We're on Windows and no dark style is set |
464 | + mocked_is_win.return_value = True |
465 | + MockSettings.return_value.value.return_value = True |
466 | + |
467 | + # WHEN: can_show_icon() is called |
468 | + result = get_application_stylesheet() |
469 | + |
470 | + # THEN: the result should be false |
471 | + MockSettings.return_value.value.assert_called_once_with('advanced/alternate rows') |
472 | + assert result == WIN_REPAIR_STYLESHEET |
473 | + |
474 | + |
475 | +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) |
476 | +@patch('openlp.core.ui.style.Settings') |
477 | +def test_get_library_stylesheet_no_dark_style(MockSettings): |
478 | + """Test that the media manager stylesheet is returned when there's no dark theme available""" |
479 | + # GIVEN: No dark style |
480 | + MockSettings.return_value.value.return_value = False |
481 | + |
482 | + # WHEN: get_library_stylesheet() is called |
483 | + result = get_library_stylesheet() |
484 | + |
485 | + # THEN: The correct stylesheet should be returned |
486 | + assert result == MEDIA_MANAGER_STYLE |
487 | + |
488 | + |
489 | +@patch('openlp.core.ui.style.HAS_DARK_STYLE', True) |
490 | +@patch('openlp.core.ui.style.Settings') |
491 | +def test_get_library_stylesheet_dark_style(MockSettings): |
492 | + """Test that no stylesheet is returned when the dark theme is enabled""" |
493 | + # GIVEN: No dark style |
494 | + MockSettings.return_value.value.return_value = True |
495 | + |
496 | + # WHEN: get_library_stylesheet() is called |
497 | + result = get_library_stylesheet() |
498 | + |
499 | + # THEN: The correct stylesheet should be returned |
500 | + assert result == '' |