openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #32139
[Merge] lp:~raoul-snyman/openlp/dark-style into lp:openlp
Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/dark-style into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~raoul-snyman/openlp/dark-style/+merge/331539
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.
--
Your team OpenLP Core is requested to review the proposed merge of lp:~raoul-snyman/openlp/dark-style into lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py 2017-09-23 04:04:41 +0000
+++ openlp/core/__init__.py 2017-09-29 00:06:52 +0000
@@ -46,34 +46,14 @@
from openlp.core.ui.firsttimeform import FirstTimeForm
from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
from openlp.core.ui.mainwindow import MainWindow
+from openlp.core.ui.style import get_application_stylesheet
+
__all__ = ['OpenLP', 'main']
log = logging.getLogger()
-WIN_REPAIR_STYLESHEET = """
-QMainWindow::separator
-{
- border: none;
-}
-
-QDockWidget::title
-{
- border: 1px solid palette(dark);
- padding-left: 5px;
- padding-top: 2px;
- margin: 1px 0;
-}
-
-QToolBar
-{
- border: none;
- margin: 0;
- padding: 0;
-}
-"""
-
class OpenLP(OpenLPMixin, QtWidgets.QApplication):
"""
@@ -118,14 +98,7 @@
QtCore.QCoreApplication.exit()
sys.exit()
# Correct stylesheet bugs
- application_stylesheet = ''
- if not Settings().value('advanced/alternate rows'):
- base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base)
- alternate_rows_repair_stylesheet = \
- 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n'
- application_stylesheet += alternate_rows_repair_stylesheet
- if is_win():
- application_stylesheet += WIN_REPAIR_STYLESHEET
+ application_stylesheet = get_application_stylesheet()
if application_stylesheet:
self.setStyleSheet(application_stylesheet)
can_show_splash = Settings().value('core/show splash')
=== modified file 'openlp/core/common/settings.py'
--- openlp/core/common/settings.py 2017-09-09 20:00:48 +0000
+++ openlp/core/common/settings.py 2017-09-29 00:06:52 +0000
@@ -136,6 +136,7 @@
'advanced/single click service preview': False,
'advanced/x11 bypass wm': X11_BYPASS_DEFAULT,
'advanced/search as type': True,
+ 'advanced/use_dark_style': False,
'api/twelve hour': True,
'api/port': 4316,
'api/websocket port': 4317,
=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py 2017-09-24 20:26:39 +0000
+++ openlp/core/ui/advancedtab.py 2017-09-29 00:06:52 +0000
@@ -32,6 +32,7 @@
from openlp.core.common.path import path_to_str
from openlp.core.lib import SettingsTab, build_icon
from openlp.core.ui.lib import PathEdit, PathType
+from openlp.core.ui.style import HAS_DARK_STYLE
log = logging.getLogger(__name__)
@@ -109,45 +110,10 @@
self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box')
self.ui_layout.addRow(self.enable_auto_close_check_box)
self.left_layout.addWidget(self.ui_group_box)
- # Default service name
- self.service_name_group_box = QtWidgets.QGroupBox(self.left_column)
- self.service_name_group_box.setObjectName('service_name_group_box')
- self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box)
- self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box)
- self.service_name_check_box.setObjectName('service_name_check_box')
- self.service_name_layout.setObjectName('service_name_layout')
- self.service_name_layout.addRow(self.service_name_check_box)
- self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box)
- self.service_name_time_label.setObjectName('service_name_time_label')
- self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box)
- self.service_name_day.addItems(['', '', '', '', '', '', '', ''])
- self.service_name_day.setObjectName('service_name_day')
- self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box)
- self.service_name_time.setObjectName('service_name_time')
- self.service_name_time_layout = QtWidgets.QHBoxLayout()
- self.service_name_time_layout.setObjectName('service_name_time_layout')
- self.service_name_time_layout.addWidget(self.service_name_day)
- self.service_name_time_layout.addWidget(self.service_name_time)
- self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout)
- self.service_name_label = QtWidgets.QLabel(self.service_name_group_box)
- self.service_name_label.setObjectName('service_name_label')
- self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box)
- self.service_name_edit.setObjectName('service_name_edit')
- self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self))
- self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box)
- self.service_name_revert_button.setObjectName('service_name_revert_button')
- self.service_name_revert_button.setIcon(build_icon(':/general/general_revert.png'))
- self.service_name_button_layout = QtWidgets.QHBoxLayout()
- self.service_name_button_layout.setObjectName('service_name_button_layout')
- self.service_name_button_layout.addWidget(self.service_name_edit)
- self.service_name_button_layout.addWidget(self.service_name_revert_button)
- self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout)
- self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box)
- self.service_name_example_label.setObjectName('service_name_example_label')
- self.service_name_example = QtWidgets.QLabel(self.service_name_group_box)
- self.service_name_example.setObjectName('service_name_example')
- self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example)
- self.left_layout.addWidget(self.service_name_group_box)
+ if HAS_DARK_STYLE:
+ self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box)
+ self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox')
+ self.ui_layout.addRow(self.use_dark_style_checkbox)
# Data Directory
self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column)
self.data_directory_group_box.setObjectName('data_directory_group_box')
@@ -174,7 +140,6 @@
self.data_directory_layout.addRow(self.data_directory_copy_check_layout)
self.data_directory_layout.addRow(self.new_data_directory_has_files_label)
self.left_layout.addWidget(self.data_directory_group_box)
- self.left_layout.addStretch()
# Hide mouse
self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column)
self.hide_mouse_group_box.setObjectName('hide_mouse_group_box')
@@ -203,7 +168,7 @@
self.slide_layout.addWidget(self.next_item_radio_button)
self.right_layout.addWidget(self.slide_group_box)
# Display Workarounds
- self.display_workaround_group_box = QtWidgets.QGroupBox(self.left_column)
+ self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column)
self.display_workaround_group_box.setObjectName('display_workaround_group_box')
self.display_workaround_layout = QtWidgets.QVBoxLayout(self.display_workaround_group_box)
self.display_workaround_layout.setObjectName('display_workaround_layout')
@@ -217,7 +182,49 @@
self.alternate_rows_check_box.setObjectName('alternate_rows_check_box')
self.display_workaround_layout.addWidget(self.alternate_rows_check_box)
self.right_layout.addWidget(self.display_workaround_group_box)
+ # Default service name
+ self.service_name_group_box = QtWidgets.QGroupBox(self.right_column)
+ self.service_name_group_box.setObjectName('service_name_group_box')
+ self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box)
+ self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box)
+ self.service_name_check_box.setObjectName('service_name_check_box')
+ self.service_name_layout.setObjectName('service_name_layout')
+ self.service_name_layout.addRow(self.service_name_check_box)
+ self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box)
+ self.service_name_time_label.setObjectName('service_name_time_label')
+ self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box)
+ self.service_name_day.addItems(['', '', '', '', '', '', '', ''])
+ self.service_name_day.setObjectName('service_name_day')
+ self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box)
+ self.service_name_time.setObjectName('service_name_time')
+ self.service_name_time_layout = QtWidgets.QHBoxLayout()
+ self.service_name_time_layout.setObjectName('service_name_time_layout')
+ self.service_name_time_layout.addWidget(self.service_name_day)
+ self.service_name_time_layout.addWidget(self.service_name_time)
+ self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout)
+ self.service_name_label = QtWidgets.QLabel(self.service_name_group_box)
+ self.service_name_label.setObjectName('service_name_label')
+ self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box)
+ self.service_name_edit.setObjectName('service_name_edit')
+ self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self))
+ self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box)
+ self.service_name_revert_button.setObjectName('service_name_revert_button')
+ self.service_name_revert_button.setIcon(build_icon(':/general/general_revert.png'))
+ self.service_name_button_layout = QtWidgets.QHBoxLayout()
+ self.service_name_button_layout.setObjectName('service_name_button_layout')
+ self.service_name_button_layout.addWidget(self.service_name_edit)
+ self.service_name_button_layout.addWidget(self.service_name_revert_button)
+ self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout)
+ self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box)
+ self.service_name_example_label.setObjectName('service_name_example_label')
+ self.service_name_example = QtWidgets.QLabel(self.service_name_group_box)
+ self.service_name_example.setObjectName('service_name_example')
+ self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example)
+ self.right_layout.addWidget(self.service_name_group_box)
+ # After the last item on each side, add some spacing
+ self.left_layout.addStretch()
self.right_layout.addStretch()
+ # Set up all the connections and things
self.should_update_service_name_example = False
self.service_name_check_box.toggled.connect(self.service_name_check_box_toggled)
self.service_name_day.currentIndexChanged.connect(self.on_service_name_day_changed)
@@ -282,6 +289,8 @@
'Auto-scroll the next slide to bottom'))
self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab',
'Enable application exit confirmation'))
+ if HAS_DARK_STYLE:
+ self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)'))
self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name'))
self.service_name_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable default service name'))
self.service_name_time_label.setText(translate('OpenLP.AdvancedTab', 'Date and Time:'))
@@ -349,6 +358,8 @@
if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count():
self.autoscroll_combo_box.setCurrentIndex(i)
self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation'))
+ if HAS_DARK_STYLE:
+ self.use_dark_style_checkbox.setChecked(settings.value('use_dark_style'))
self.hide_mouse_check_box.setChecked(settings.value('hide mouse'))
self.service_name_day.setCurrentIndex(settings.value('default service day'))
self.service_name_time.setTime(QtCore.QTime(settings.value('default service hour'),
@@ -420,6 +431,8 @@
self.settings_form.register_post_process('config_screen_changed')
self.settings_form.register_post_process('slidecontroller_update_slide_limits')
settings.setValue('search as type', self.is_search_as_you_type_enabled)
+ if HAS_DARK_STYLE:
+ settings.setValue('use_dark_style', self.use_dark_style_checkbox.isChecked())
settings.endGroup()
def on_search_as_type_check_box_changed(self, check_state):
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2017-09-25 19:55:33 +0000
+++ openlp/core/ui/mainwindow.py 2017-09-29 00:06:52 +0000
@@ -51,31 +51,12 @@
from openlp.core.ui.lib.dockwidget import OpenLPDockWidget
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.ui.lib.mediadockmanager import MediaDockManager
+from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet
from openlp.core.version import get_version
log = logging.getLogger(__name__)
-MEDIA_MANAGER_STYLE = """
-::tab#media_tool_box {
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 palette(button), stop: 1.0 palette(mid));
- border: 0;
- border-radius: 2px;
- margin-top: 0;
- margin-bottom: 0;
- text-align: left;
-}
-/* This is here to make the tabs on KDE with the Breeze theme work */
-::tab:selected {}
-"""
-
-PROGRESSBAR_STYLE = """
-QProgressBar{
- height: 10px;
-}
-"""
-
class Ui_MainWindow(object):
"""
@@ -155,7 +136,7 @@
# Create the MediaManager
self.media_manager_dock = OpenLPDockWidget(main_window, 'media_manager_dock',
':/system/system_mediamanager.png')
- self.media_manager_dock.setStyleSheet(MEDIA_MANAGER_STYLE)
+ self.media_manager_dock.setStyleSheet(get_library_stylesheet())
# Create the media toolbox
self.media_tool_box = QtWidgets.QToolBox(self.media_manager_dock)
self.media_tool_box.setObjectName('media_tool_box')
=== added file 'openlp/core/ui/style.py'
--- openlp/core/ui/style.py 1970-01-01 00:00:00 +0000
+++ openlp/core/ui/style.py 2017-09-29 00:06:52 +0000
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2017 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme
+"""
+from PyQt5 import QtGui
+
+from openlp.core.common import is_macosx, is_win
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+
+try:
+ import qdarkstyle
+ HAS_DARK_STYLE = True
+except ImportError:
+ HAS_DARK_STYLE = False
+
+WIN_REPAIR_STYLESHEET = """
+QMainWindow::separator
+{
+ border: none;
+}
+
+QDockWidget::title
+{
+ border: 1px solid palette(dark);
+ padding-left: 5px;
+ padding-top: 2px;
+ margin: 1px 0;
+}
+
+QToolBar
+{
+ border: none;
+ margin: 0;
+ padding: 0;
+}
+"""
+
+MEDIA_MANAGER_STYLE = """
+::tab#media_tool_box {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 palette(button), stop: 1.0 palette(mid));
+ border: 0;
+ border-radius: 2px;
+ margin-top: 0;
+ margin-bottom: 0;
+ text-align: left;
+}
+/* This is here to make the tabs on KDE with the Breeze theme work */
+::tab:selected {}
+"""
+
+PROGRESSBAR_STYLE = """
+QProgressBar{
+ height: 10px;
+}
+"""
+
+
+def can_show_icon():
+ """
+ A global method to determine if an icon can be shown on a widget
+
+ .. note::
+ This method uses internal imports to prevent circular imports.
+ """
+ return not is_macosx() or Settings().value('advanced/use_dark_style')
+
+
+def get_application_stylesheet():
+ """
+ Return the correct application stylesheet based on the current style and operating system
+
+ :return str: The correct stylesheet as a string
+ """
+ stylesheet = ''
+ if HAS_DARK_STYLE and Settings().value('advanced/use_dark_style'):
+ stylesheet = qdarkstyle.load_stylesheet_pyqt5()
+ else:
+ if not Settings().value('advanced/alternate rows'):
+ base_color = Registry().get('application').palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base)
+ alternate_rows_repair_stylesheet = \
+ 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n'
+ stylesheet += alternate_rows_repair_stylesheet
+ if is_win():
+ stylesheet += WIN_REPAIR_STYLESHEET
+ return stylesheet
+
+
+def get_library_stylesheet():
+ """
+ Return the correct stylesheet for the main window
+
+ :return str: The correct stylesheet as a string
+ """
+ if not HAS_DARK_STYLE or not Settings().value('advanced/use_dark_style'):
+ return MEDIA_MANAGER_STYLE
+ else:
+ return ''
References