Sat, 09 Mar 2019 18:44:13 +0100
Lexer: extended the basic support for sub-styles by a method to write the data to the settings file.
# -*- coding: utf-8 -*- # Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the lexer mixin class. """ from __future__ import unicode_literals import copy from PyQt5.QtGui import QColor from .Lexer import Lexer import Preferences class SubstyledLexer(Lexer): """ Class to implement the sub-styled lexer mixin class. """ def __init__(self): """ Constructor """ super(SubstyledLexer, self).__init__() self.baseStyles = [] # list of style numbers, that support # sub-styling self.defaultSubStyles = {} # dictionary with sub-styling data # main key: base style number, value : list of dict with # 'Description': string containing a short description # 'Words': string of whitespace separated words to be styled # 'Style': dictionary with styling data (only difference to the # base style is required # 'fore': foreground color (int containing RGB values) # 'paper': background color (int containing RGB values) # 'eolfill': fill to eol (bool) # 'font_family': font family (str) # 'font_size: point size (int) # 'font_bold: bold font (bool) # 'font_italic: italic font (bool) # 'font_underline: underlined font (bool) self.subStyles = {} self.__subStylesInitialized = False def loadSubstyles(self): """ Public method to load the sub-styles from the settings file """ settings = Preferences.Prefs.settings self.loadDefaultSubStyles() for baseStyle in self.baseStyles: key = "Scintilla/{0}/style{1}/SubStyleLength".format( self.language(), baseStyle) if settings.contains(key): subStyleLength = int(settings.value(key), 0) self.subStyles[baseStyle] = {} if subStyleLength: self.subStyles[baseStyle] = [] for subStyle in range(subStyleLength): baseKey = "Scintilla/{0}/style{1}/substyle{2}/".format( self.language(), baseStyle, subStyle) if settings.contains(baseKey): subStyleData = {} subStyleData["Description"] = settings.value( baseKey + "Description", "") subStyleData["Words"] = settings.value( baseKey + "Words", "") style = {} key = baseKey + "fore" if settings.contains(key): style["fore"] = int(settings.value(key)) key = baseKey + "paper" if settings.contains(key): style["paper"] = int(settings.value(key)) key = baseKey + "eolfill" if settings.contains(key): style["eolfill"] = Preferences.toBool( settings.value(key)) key = baseKey + "font_family" if settings.contains(key): style["font_family"] = settings.value(key) key = baseKey + "font_size" if settings.contains(key): style["font_size"] = int(settings.value(key)) key = baseKey + "font_bold" if settings.contains(key): style["font_bold"] = Preferences.toBool( settings.value(key)) key = baseKey + "font_italic" if settings.contains(key): style["font_italic"] = Preferences.toBool( settings.value(key)) key = baseKey + "font_underline" if settings.contains(key): style["font_underline"] = Preferences.toBool( settings.value(key)) subStyleData["Style"] = style self.subStyles[baseStyle].append(subStyleData) self.__subStylesInitialized = True def loadDefaultSubStyles(self): """ Public method to load the default sub-style definitions. """ self.subStyles = copy.deepcopy(self.defaultSubStyles) def readSubstyles(self, editor): """ Public method to load the sub-styles and configure the editor. @param editor reference to the editor object @type QsciScintilla """ subStyleBasesLength = editor.SendScintilla( editor.SCI_GETSUBSTYLEBASES, 0, None) if not subStyleBasesLength: # lexer does not support sub-styling return self.loadSubstyles() # free existing sub-styles first editor.SendScintilla(editor.SCI_FREESUBSTYLES) subStyleBases = b"\00" * (subStyleBasesLength + 1) editor.SendScintilla(editor.SCI_GETSUBSTYLEBASES, 0, subStyleBases) distanceToSecondary = editor.SendScintilla( editor.SCI_DISTANCETOSECONDARYSTYLES) subStyleBases = [b for b in bytearray(subStyleBases[:-1])] if distanceToSecondary: subStyleBases.extend(b + distanceToSecondary for b in subStyleBases[:]) for baseStyleNo in subStyleBases: if baseStyleNo in self.subStyles: subStylesData = self.subStyles[baseStyleNo] subStyleLength = len(subStylesData) subStyleStart = editor.SendScintilla( editor.SCI_ALLOCATESUBSTYLES, baseStyleNo, subStyleLength) if subStyleStart < 0: subStyleLength = 0 for subStyleIndex in range(subStyleLength): styleNo = subStyleStart + subStyleIndex subStyle = subStylesData[subStyleIndex] # set the words editor.SendScintilla( editor.SCI_SETIDENTIFIERS, styleNo, subStyle["Words"].encode()) # set the style style = subStyle["Style"] if "fore" in style: color = QColor( style["fore"] >> 16 & 0xff, style["fore"] >> 8 & 0xff, style["fore"] & 0xff, ) else: color = self.color(baseStyleNo) self.setColor(color, styleNo) if "paper" in style: color = QColor( style["paper"] >> 16 & 0xff, style["paper"] >> 8 & 0xff, style["paper"] & 0xff, ) else: color = self.paper(baseStyleNo) self.setPaper(color, styleNo) if "eolfill" in style: eolFill = style["eolFill"] else: eolFill = self.eolFill(baseStyleNo) self.setEolFill(eolFill, styleNo) font = self.font(baseStyleNo) if "font_family" in style: font.setFamily(style["font_family"]) if "font_size" in style: font.setPointSize(style["font_size"]) if "font_bold" in style: font.setBold(style["font_bold"]) if "font_italic" in style: font.setItalic(style["font_italic"]) if "font_underline" in style: font.setUnderline(style["font_underline"]) self.setFont(font, styleNo) def writeSubstyles(self): """ Public method to save the sub-styles. """ if not self.__subStylesInitialized: # make sure, the sub-styles have been initialized self.loadSubstyles() settings = Preferences.Prefs.settings for baseStyle in self.baseStyles: key = "Scintilla/{0}/style{1}/SubStyleLength".format( self.language(), baseStyle) settings.setValue(key, len(self.subStyles[baseStyle])) for subStyle in range(len(self.subStyles[baseStyle])): baseKey = "Scintilla/{0}/style{1}/substyle{2}/".format( self.language(), baseStyle, subStyle) subStyleData = self.subStyles[baseStyle][subStyle] settings.setValue(baseKey + "Description", subStyleData["Description"]) settings.setValue(baseKey + "Words", subStyleData["Words"]) style = subStyleData["Style"] if "fore" in style: color = style["fore"] else: col = self.color(baseStyle) color = col.red() << 16 | col.green() << 8 | col.blue() settings.setValue(baseKey + "fore", color) if "paper" in style: color = style["paper"] else: col = self.paper(baseStyle) color = col.red() << 16 | col.green() << 8 | col.blue() settings.setValue(baseKey + "paper", color) if "eolfill" in style: eolfill = style["eolfill"] else: eolfill = self.eolFill(baseStyle) settings.setValue(baseKey + "eolfill", eolfill) font = self.font(baseStyle) if "font_family" in style: family = style["font_family"] else: family = font.family() settings.setValue(baseKey + "font_family", family) if "font_size" in style: size = style["font_size"] else: size = font.pointSize() settings.setValue(baseKey + "font_size", size) if "font_bold" in style: bold = style["font_bold"] else: bold = font.bold() settings.setValue(baseKey + "font_bold", bold) if "font_italic" in style: italic = style["font_italic"] else: italic = font.italic() settings.setValue(baseKey + "font_italic", italic) if "font_underline" in style: underline = style["font_underline"] else: underline = font.underline() settings.setValue(baseKey + "font_underline", underline) def hasSubStyles(self): """ Public method to indicate the support of sub-styles. @return flag indicating sub-styling support @rtype bool """ return True def setSubstyleDescription(self, description, style, substyle): """ """ def substyleDescription(self, style, substyle): """ """ def setSubstyleColor(self, color, style, substyle): """ """ def substyleColor(self, style, substyle): """ """ def setSubstylePaper(self, color, style, substyle): """ """ def substylePaper(self, style, substyle): """ """ def setSubstyleEolFill(self, eolFill, style, substyle): """ """ def substyleEolFill(self, style, substyle): """ """ def setSubstyleFont(self, font, style, substyle): """ """ def substyleFont(self, style, substyle): """ """ def substyleDefaultDescription(self, style, substyle): """ """ def substyleDefaultColor(self, style, substyle): """ """ def substyleDefaultPaper(self, style, substyle): """ """ def substyleDefaultEolFill(self, style, substyle): """ """ def substyleDefaultFont(self, style, substyle): """ """