Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Initial support for Spyder's dark theme #8020

Merged
merged 12 commits into from
Oct 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ a Python version greater than 2.7 or 3.4 (Python <=3.3 is no longer supported).
* **Cloudpickle**: Serialize variables in the IPython kernel to send to Spyder.
* **spyder-kernels** 1.0+: Jupyter kernels for the Spyder console.
* **keyring**: Save Github credentials to report errors securely.
* **QDarkStyle**: A dark stylesheet for Qt applications, used for Spyder's dark theme.
* **pexpect**/**paramiko**: Connect to remote kernels through SSH.

### Optional dependencies
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ environment:
sympy cython keyring
PIP_DEPENDENCIES: >
pytest-qt pytest-mock pytest-timeout flaky codecov
python-language-server[all]
python-language-server[all] qdarkstyle
APPVEYOR_RDP_PASSWORD: "dcca4c4863E30d56c2e0dda6327370b3#"

matrix:
Expand Down
2 changes: 1 addition & 1 deletion continuous_integration/posix/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ else
pytest pytest-cov numpydoc scipy cython pillow jedi pycodestyle sympy \
keyring pexpect"
export PIP_DEPENDENCIES="coveralls pytest-qt pytest-mock pytest-timeout flaky \
python-language-server[all]"
python-language-server[all] qdarkstyle"
fi


Expand Down
1 change: 1 addition & 0 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ pyqt5
keyring
spyder-kernels>=1.0
python-language-server
qdarkstyle
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ def run(self):
'pyqt5<5.10;python_version>="3"',
# Pyls with all its dependencies
'python-language-server[all]',
'qdarkstyle',
# Required to get SSH connections to remote kernels
'pexpect;platform_system!="Windows"',
'paramiko;platform_system=="Windows"'
Expand Down
17 changes: 15 additions & 2 deletions spyder/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@
from spyder.utils.misc import select_port, getcwd_or_home, get_python_executable
from spyder.widgets.fileswitcher import FileSwitcher
from spyder.plugins.lspmanager import LSPManager


from spyder.config.gui import is_dark_font_color

#==============================================================================
# Local gui imports
Expand All @@ -188,6 +187,10 @@
from spyder.otherplugins import get_spyderplugins_mods
from spyder.app import tour

#==============================================================================
# Third-party library imports
#==============================================================================
import qdarkstyle

#==============================================================================
# Get the cwd before initializing WorkingDirectory, which sets it to the one
Expand Down Expand Up @@ -553,6 +556,16 @@ def create_toolbar(self, title, object_name, iconsize=24):
def setup(self):
"""Setup main window"""
self.debug_print("*** Start of MainWindow setup ***")
self.debug_print(" ..theme configuration")
ui_theme = CONF.get('color_schemes', 'ui_theme')
color_scheme = CONF.get('color_schemes', 'selected')
if ui_theme == 'dark':
self.setStyleSheet(qdarkstyle.load_stylesheet_from_environment())
elif ui_theme == 'automatic':
if not is_dark_font_color(color_scheme):
self.setStyleSheet(
qdarkstyle.load_stylesheet_from_environment())

self.debug_print(" ..core actions")
self.close_dockwidget_action = create_action(self,
icon=ima.icon('DialogCloseButton'),
Expand Down
9 changes: 9 additions & 0 deletions spyder/config/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
from spyder.py3compat import to_text_string
from spyder.utils import syntaxhighlighters as sh

# Third-party imports
from qtconsole.styles import dark_color

# To save metadata about widget shortcuts (needed to build our
# preferences page)
Expand Down Expand Up @@ -164,5 +166,12 @@ def set_default_color_scheme(name, replace=True):
set_color_scheme(name, sh.get_color_scheme(name), replace=replace)


def is_dark_font_color(color_scheme):
"""Check if the font color used in the color scheme is dark."""
color_scheme = get_color_scheme(color_scheme)
font_color, fon_fw, fon_fs = color_scheme['normal']
return dark_color(font_color)


for _name in sh.COLOR_SCHEME_NAMES:
set_default_color_scheme(_name, replace=False)
1 change: 1 addition & 0 deletions spyder/config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@
}),
('color_schemes',
{
'ui_theme': 'automatic',
'names': ['emacs', 'idle', 'monokai', 'pydev', 'scintilla',
'spyder', 'spyder/dark', 'zenburn', 'solarized/light',
'solarized/dark'],
Expand Down
77 changes: 60 additions & 17 deletions spyder/preferences/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from spyder.widgets.colors import ColorLayout
from spyder.widgets.comboboxes import FileComboBox
from spyder.plugins.editor.widgets.codeeditor import CodeEditor
from spyder.config.gui import is_dark_font_color


HDPI_QT_PAGE = "https://doc.qt.io/qt-5/highdpi.html"
Expand Down Expand Up @@ -911,7 +912,6 @@ def setup_page(self):
icons_combo = self.create_combobox(_('Icon theme'), icon_choices,
'icon_theme', restart=True)


vertdock_box = newcb(_("Vertical title bars in panes"),
'vertical_dockwidget_titlebars')
verttabs_box = newcb(_("Vertical tabs in panes"),
Expand Down Expand Up @@ -1166,23 +1166,32 @@ def setup_page(self):
# Widget setup
self.scheme_choices_dict = {}
about_label.setWordWrap(True)
schemes_combobox_widget = self.create_combobox(_('Scheme:'),
schemes_combobox_widget = self.create_combobox(_('Syntax scheme:'),
[('', '')],
'selected')
self.schemes_combobox = schemes_combobox_widget.combobox

# Layouts
vlayout = QVBoxLayout()
ui_themes = ['Automatic', 'Light', 'Dark']
ui_theme_choices = list(zip(ui_themes, [ui_theme.lower()
for ui_theme in ui_themes]))
ui_theme_combo = self.create_combobox(_('Interface theme:'),
ui_theme_choices,
'ui_theme',
restart=True)

# Layouts
manage_layout = QVBoxLayout()
manage_layout.addWidget(about_label)

combo_layout = QHBoxLayout()
combo_layout.addWidget(schemes_combobox_widget.label)
combo_layout.addWidget(schemes_combobox_widget.combobox)
comboboxes_layout = QGridLayout()
comboboxes_layout.addWidget(ui_theme_combo.label, 0, 0)
comboboxes_layout.addWidget(ui_theme_combo.combobox, 0, 1)

comboboxes_layout.addWidget(schemes_combobox_widget.label, 1, 0)
comboboxes_layout.addWidget(schemes_combobox_widget.combobox, 1, 1)

buttons_layout = QVBoxLayout()
buttons_layout.addLayout(combo_layout)
buttons_layout.addLayout(comboboxes_layout)
buttons_layout.addWidget(edit_button)
buttons_layout.addWidget(self.reset_button)
buttons_layout.addWidget(self.delete_button)
Expand All @@ -1200,6 +1209,7 @@ def setup_page(self):
manage_group = QGroupBox(_("Manage color schemes"))
manage_group.setLayout(manage_layout)

vlayout = QVBoxLayout()
vlayout.addWidget(manage_group)
self.setLayout(vlayout)

Expand All @@ -1223,15 +1233,46 @@ def setup_page(self):

def apply_settings(self, options):
self.set_option('selected', self.current_scheme)
self.main.editor.apply_plugin_settings(['color_scheme_name'])
if self.main.ipyconsole is not None:
self.main.ipyconsole.apply_plugin_settings(['color_scheme_name'])
if self.main.historylog is not None:
self.main.historylog.apply_plugin_settings(['color_scheme_name'])
if self.main.help is not None:
self.main.help.apply_plugin_settings(['color_scheme_name'])
self.update_combobox()
self.update_preview()
color_scheme = self.get_option('selected')
ui_theme = self.get_option('ui_theme')
style_sheet = self.main.styleSheet()
if ui_theme == 'automatic':
if ((not is_dark_font_color(color_scheme) and not style_sheet)
or (is_dark_font_color(color_scheme) and style_sheet)):
self.changed_options.add('ui_theme')
elif 'ui_theme' in self.changed_options:
self.changed_options.remove('ui_theme')

if 'ui_theme' not in self.changed_options:
self.main.editor.apply_plugin_settings(['color_scheme_name'])
if self.main.ipyconsole is not None:
self.main.ipyconsole.apply_plugin_settings(
['color_scheme_name'])
if self.main.historylog is not None:
self.main.historylog.apply_plugin_settings(
['color_scheme_name'])
if self.main.help is not None:
self.main.help.apply_plugin_settings(['color_scheme_name'])
self.update_combobox()
self.update_preview()
else:
if 'ui_theme' in self.changed_options:
if (style_sheet and ui_theme == 'dark' or
not style_sheet and ui_theme == 'light'):
self.changed_options.remove('ui_theme')

if 'ui_theme' not in self.changed_options:
self.main.editor.apply_plugin_settings(['color_scheme_name'])
if self.main.ipyconsole is not None:
self.main.ipyconsole.apply_plugin_settings(
['color_scheme_name'])
if self.main.historylog is not None:
self.main.historylog.apply_plugin_settings(
['color_scheme_name'])
if self.main.help is not None:
self.main.help.apply_plugin_settings(['color_scheme_name'])
self.update_combobox()
self.update_preview()

# Helpers
# -------------------------------------------------------------------------
Expand Down Expand Up @@ -1532,6 +1573,8 @@ def add_color_scheme_stack(self, scheme_name, custom=False):

if not custom:
line_edit.textbox.setDisabled(True)
if not self.isVisible():
line_edit.setVisible(False)

cs_layout = QVBoxLayout()
cs_layout.addLayout(name_layout)
Expand Down
Loading