Source code for mu.interface.themes

"""
Theme and presentation related code for the Mu editor.

Copyright (c) 2015-2017 Nicholas H.Tollervey and others (see the AUTHORS file).

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, either version 3 of the License, or
(at your option) any later version.

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, see <http://www.gnu.org/licenses/>.
"""
import logging
import platform

from PyQt5.QtGui import QColor, QFontDatabase
from mu.resources import load_stylesheet, load_font_data


logger = logging.getLogger(__name__)


[docs]def should_patch_osx_mojave_font(): """ OSX mojave and qt5/qtscintilla has a bug where non-system installed fonts are always rendered as black, regardless of the theme color. This is inconvenient for light themes, but makes dark themes unusable. Using a system-installed font doesn't exhibit this behaviour, so update FONT_NAME to use the default terminal font in OSX on mojave. This patch should be removed once the underlying issue has been resolved github issue #552 """ return platform.platform().startswith("Darwin-18.")
# The default font size. DEFAULT_FONT_SIZE = 14 # All editor windows use the same font if should_patch_osx_mojave_font(): # pragma: no cover logger.warning("Overriding built-in editor font due to Issue #552") FONT_NAME = "Monaco" else: # pragma: no cover FONT_NAME = "Inconsolata" FONT_FILENAME= "Inconsolata.otf" # Load the three themes from resources/css/[night|day|contrast].css # NIGHT_STYLE is a dark theme. NIGHT_STYLE = load_stylesheet('night.css') # DAY_STYLE is a light conventional theme. DAY_STYLE = load_stylesheet('day.css') # CONTRAST_STYLE is a high contrast theme. CONTRAST_STYLE = load_stylesheet('contrast.css') logger = logging.getLogger(__name__)
[docs]class Font: """ Utility class that makes it easy to set font related values within the editor. """ _DATABASE = None def __init__(self, color='#181818', paper='#FEFEF7', bold=False, italic=False): self.color = color self.paper = paper self.bold = bold self.italic = italic
[docs] @classmethod def get_database(cls): """ Create a font database and load the MU builtin fonts into it. This is a cached classmethod so the font files aren't re-loaded every time a font is refereced """ if cls._DATABASE is None: cls._DATABASE = QFontDatabase() filename = FONT_FILENAME font_data = load_font_data(filename) cls._DATABASE.addApplicationFontFromData(font_data) return cls._DATABASE
[docs] def load(self, size=DEFAULT_FONT_SIZE): """ Load the font from the font database, using the correct size and style """ return Font.get_database().font(FONT_NAME, self.stylename, size)
@property def stylename(self): """ Map the bold and italic boolean flags here to a relevant font style name. """ if self.bold: if self.italic: return "Semibold Italic" return "Semibold" if self.italic: return "Italic" return "Regular"
[docs]class Theme: """ Defines a font and other theme specific related information. """ @classmethod def apply_to(cls, lexer): # Apply a font for all styles lexer.setFont(Font().load()) for name, font in cls.__dict__.items(): if not isinstance(font, Font): continue if hasattr(lexer, name): style_num = getattr(lexer, name) lexer.setColor(QColor(font.color), style_num) lexer.setEolFill(True, style_num) lexer.setPaper(QColor(font.paper), style_num) lexer.setFont(font.load(), style_num)
[docs]class DayTheme(Theme): """ Defines a Python related theme including the various font colours for syntax highlighting. This is a light theme. """ FunctionMethodName = ClassName = Font(color='#0000a0') UnclosedString = Font(paper='#FFDDDD') Comment = CommentBlock = Font(color='gray') Keyword = Font(color='#005050', bold=True) SingleQuotedString = DoubleQuotedString = Font(color='#800000') TripleSingleQuotedString = TripleDoubleQuotedString = Font(color='#060') Number = Font(color='#00008B') Decorator = Font(color='#cc6600') Default = Identifier = Font() Operator = Font(color='#400040') HighlightedIdentifier = Font(color='#0000a0') Paper = QColor('#FEFEF7') Caret = QColor('#181818') Margin = QColor('#EEE') IndicatorError = QColor('red') IndicatorStyle = QColor('blue') DebugStyle = QColor('#ffcc33') IndicatorWordMatch = QColor('lightGrey') BraceBackground = QColor('lightGrey') BraceForeground = QColor('blue') UnmatchedBraceBackground = QColor('#FFDDDD') UnmatchedBraceForeground = QColor('black') BreakpointMarker = QColor('#D80000') # HTML Tag = Keyword UnknownTag = Tag XMLTagEnd = Tag XMLStart = Tag XMLEnd = Tag Attribute = ClassName UnknownAttribute = Attribute HTMLNumber = Number HTMLDoubleQuotedString = DoubleQuotedString HTMLSingleQuotedString = SingleQuotedString OtherInTag = Default HTMLComment = Comment Entity = Operator CDATA = Decorator # CSS ClassSelector = Tag PseudoClass = ClassSelector UnknownPseudoClass = ClassSelector CSS1Property = CSS2Property = CSS3Property = UnknownProperty = \ SingleQuotedString Value = Number IDSelector = Tag Important = UnmatchedBraceBackground AtRule = Decorator MediaRule = Decorator Variable = HighlightedIdentifier
[docs]class NightTheme(Theme): """ Defines a Python related theme including the various font colours for syntax highlighting. This is the dark theme. """ # Python / General FunctionMethodName = ClassName = Font(color='#81a2be', paper='#222') UnclosedString = Font(paper='#c93827') Comment = CommentBlock = CommentLine = Font(color='#969896', paper='#222') Keyword = Font(color='#73a46a', bold=True, paper='#222') SingleQuotedString = DoubleQuotedString = Font(color='#f0c674', paper='#222') TripleSingleQuotedString = TripleDoubleQuotedString = Font(color='#f0c674', paper='#222') Number = Font(color='#b5bd68', paper='#222') Decorator = Font(color='#cc6666', paper='#222') Default = Identifier = Font(color='#DDD', paper='#222') Operator = Font(color='#b294bb', paper='#222') HighlightedIdentifier = Font(color='#de935f', paper='#222') Paper = QColor('#222') Caret = QColor('#c6c6c6') Margin = QColor('#424446') IndicatorError = QColor('#c93827') IndicatorStyle = QColor('#2f5692') DebugStyle = QColor('#444') IndicatorWordMatch = QColor('#f14721') BraceBackground = QColor('#ed1596') BraceForeground = QColor('#222') UnmatchedBraceBackground = QColor('#c93827') UnmatchedBraceForeground = QColor('#222') BreakpointMarker = QColor('#c93827') # HTML Tag = Keyword UnknownTag = Tag XMLTagEnd = Tag XMLStart = Tag XMLEnd = Tag Attribute = ClassName UnknownAttribute = Attribute HTMLNumber = Number HTMLDoubleQuotedString = DoubleQuotedString HTMLSingleQuotedString = SingleQuotedString OtherInTag = Default HTMLComment = Comment Entity = Operator CDATA = Decorator # CSS ClassSelector = Tag PseudoClass = ClassSelector UnknownPseudoClass = ClassSelector CSS1Property = CSS2Property = CSS3Property = UnknownProperty = \ SingleQuotedString Value = Number IDSelector = Tag Important = UnmatchedBraceBackground AtRule = Decorator MediaRule = Decorator Variable = HighlightedIdentifier
[docs]class ContrastTheme(Theme): """ Defines a Python related theme including the various font colours for syntax highlighting. This is the high contrast theme. """ FunctionMethodName = ClassName = Font(color='#AAA', paper='black') UnclosedString = Font(paper='#666') Comment = CommentBlock = Font(color='#AAA', paper='black') Keyword = Font(color='#EEE', bold=True, paper='black') SingleQuotedString = DoubleQuotedString = Font(color='#AAA', paper='black') TripleSingleQuotedString = TripleDoubleQuotedString = Font(color='#AAA', paper='black') Number = Font(color='#AAA', paper='black') Decorator = Font(color='#cccccc', paper='black') Default = Identifier = Font(color='#fff', paper='black') Operator = Font(color='#CCC', paper='black') HighlightedIdentifier = Font(color='#ffffff', paper='black') Paper = QColor('black') Caret = QColor('white') Margin = QColor('#333') IndicatorError = QColor('white') IndicatorStyle = QColor('cyan') DebugStyle = QColor('#666') IndicatorWordMatch = QColor('grey') BraceBackground = QColor('white') BraceForeground = QColor('black') UnmatchedBraceBackground = QColor('#666') UnmatchedBraceForeground = QColor('black') BreakpointMarker = QColor('lightGrey') # HTML Tag = Keyword UnknownTag = Tag XMLTagEnd = Tag XMLStart = Tag XMLEnd = Tag Attribute = ClassName UnknownAttribute = Attribute HTMLNumber = Number HTMLDoubleQuotedString = DoubleQuotedString HTMLSingleQuotedString = SingleQuotedString OtherInTag = Default HTMLComment = Comment Entity = Operator CDATA = Decorator # CSS ClassSelector = Tag PseudoClass = ClassSelector UnknownPseudoClass = ClassSelector CSS1Property = CSS2Property = CSS3Property = UnknownProperty = \ SingleQuotedString Value = Number IDSelector = Tag Important = UnmatchedBraceBackground AtRule = Decorator MediaRule = Decorator Variable = HighlightedIdentifier