2010-04-22 8 views
1

Mon but final est d'obtenir la coloration syntaxique d'Erlang dans QsciScintilla en utilisant PyQt4 et Python 2.6. Je cours sous Windows 7, mais j'aurai aussi besoin du support d'Ubuntu.Pourquoi ma sous-classe QsciLexerCustom ne fonctionne-t-elle pas dans PyQt4 avec QsciScintilla?

PyQt4 ne dispose pas du code de wrapper nécessaire pour le lexer/surligneur Erlang que scintilla "base" a, donc j'ai pensé que j'écrirais un léger sur le QsciLexerCustom. C'est un peu problématique, car le wrapper Qsci semble vraiment vouloir parler de line + index plutôt que offset-from-start lors de l'obtention/configuration de sous-classes de texte. Pendant ce temps, le lexer obtient des arguments comme offset-from-start. Pour l'instant, je reçois une copie du texte entier, et je le scinde le cas échéant.

J'ai le lexer suivant, et je l'applique avec setLexer(). Il obtient tous les appels appropriés lorsque j'ouvre un nouveau fichier et le définit comme lexer, et imprime un tas de lignes appropriées en fonction de ce qu'il fait ... mais il n'y a pas de style dans le document. J'ai essayé de rendre tous les styles définis rouges, et le document est toujours obstinément noir sur blanc, donc apparemment les styles ne prennent pas vraiment "effet"

Qu'est-ce que je fais mal? Si personne ici ne le sait, quel est le forum de discussion approprié où les gens pourraient réellement savoir ces choses? (C'est une intersection intéressante entre Python, Qt et Scintilla, donc j'imagine que l'ensemble des gens qui savent est petit)

Supposons que prefs.declare() configure juste un dict qui retourne la valeur de la clé donnée (J'ai vérifié ceci - ce n'est pas le problème). Supposons que scintilla est raisonnablement correctement construit dans sa fenêtre hôte QWidget. Plus précisément, si j'applique une lexer groupée (telle que QsciLexerPython), elle prend effet et affiche le texte stylé.

prefs.declare('font.name.margin', "MS Dlg") 
prefs.declare('font.size.margin', 8) 
prefs.declare('font.name.code', "Courier New") 
prefs.declare('font.size.code', 10) 
prefs.declare('color.editline', "#d0e0ff") 

class LexerErlang(Qsci.QsciLexerCustom): 
    def __init__(self, obj = None): 
    Qsci.QsciLexerCustom.__init__(self, obj) 
    self.sci = None 
    self.plainFont = QtGui.QFont() 
    self.plainFont.setPointSize(int(prefs.get('font.size.code'))) 
    self.plainFont.setFamily(prefs.get('font.name.code')) 
    self.marginFont = QtGui.QFont() 
    self.marginFont.setPointSize(int(prefs.get('font.size.code'))) 
    self.marginFont.setFamily(prefs.get('font.name.margin')) 
    self.boldFont = QtGui.QFont() 
    self.boldFont.setPointSize(int(prefs.get('font.size.code'))) 
    self.boldFont.setFamily(prefs.get('font.name.code')) 
    self.boldFont.setBold(True) 
    self.styles = [ 
     Qsci.QsciStyle(0, QtCore.QString("base"), QtGui.QColor("#000000"), QtGui.QColor("#ffffff"), self.plainFont, True), 
     Qsci.QsciStyle(1, QtCore.QString("comment"), QtGui.QColor("#008000"), QtGui.QColor("#eeffee"), self.marginFont, True), 
     Qsci.QsciStyle(2, QtCore.QString("keyword"), QtGui.QColor("#000080"), QtGui.QColor("#ffffff"), self.boldFont, True), 
     Qsci.QsciStyle(3, QtCore.QString("string"), QtGui.QColor("#800000"), QtGui.QColor("#ffffff"), self.marginFont, True), 
     Qsci.QsciStyle(4, QtCore.QString("atom"), QtGui.QColor("#008080"), QtGui.QColor("#ffffff"), self.plainFont, True), 
     Qsci.QsciStyle(5, QtCore.QString("macro"), QtGui.QColor("#808000"), QtGui.QColor("#ffffff"), self.boldFont, True), 
     Qsci.QsciStyle(6, QtCore.QString("error"), QtGui.QColor("#000000"), QtGui.QColor("#ffd0d0"), self.plainFont, True), 
    ] 
    print("LexerErlang created") 
    def description(self, ix): 
    for i in self.styles: 
     if i.style() == ix: 
     return QtCore.QString(i.description()) 
    return QtCore.QString("") 
    def setEditor(self, sci): 
    self.sci = sci 
    Qsci.QsciLexerCustom.setEditor(self, sci) 
    print("LexerErlang.setEditor()") 
    def styleText(self, start, end): 
    print("LexerErlang.styleText(%d,%d)" % (start, end)) 
    lines = self.getText(start, end) 
    offset = start 
    self.startStyling(offset, 0) 
    print("startStyling()") 
    for i in lines: 
     if i == "": 
     self.setStyling(1, self.styles[0]) 
     print("setStyling(1)") 
     offset += 1 
     continue 
     if i[0] == '%': 
     self.setStyling(len(i)+1, self.styles[1]) 
     print("setStyling(%)") 
     offset += len(i)+1 
     continue 
     self.setStyling(len(i)+1, self.styles[0]) 
     print("setStyling(n)") 
     offset += len(i)+1 
    def getText(self, start, end): 
    data = self.sci.text() 
    print("LexerErlang.getText(): " + str(len(data)) + " chars") 
    return data[start:end].split('\n') 

Appliqué au widget QsciScintilla comme suit:

_lexers = { 
    'erl': (Q.SCLEX_ERLANG, LexerErlang), 
    'hrl': (Q.SCLEX_ERLANG, LexerErlang), 
    'html': (Q.SCLEX_HTML, Qsci.QsciLexerHTML), 
    'css': (Q.SCLEX_CSS, Qsci.QsciLexerCSS), 
    'py': (Q.SCLEX_PYTHON, Qsci.QsciLexerPython), 
    'php': (Q.SCLEX_PHP, Qsci.QsciLexerHTML), 
    'inc': (Q.SCLEX_PHP, Qsci.QsciLexerHTML), 
    'js': (Q.SCLEX_CPP, Qsci.QsciLexerJavaScript), 
    'cpp': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'h': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'cxx': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'hpp': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'c': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'hxx': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'tpl': (Q.SCLEX_CPP, Qsci.QsciLexerCPP), 
    'xml': (Q.SCLEX_XML, Qsci.QsciLexerXML), 
} 

... dans ma classe de document fenêtre ...

def addContentsDocument(self, contents, title): 
    handler = self.makeScintilla() 
    handler.title = title 
    sci = handler.sci 
    sci.append(contents) 
    self.tabWidget.addTab(sci, title) 
    self.tabWidget.setCurrentWidget(sci) 
    self.applyLexer(sci, title) 
    EventBus.bus.broadcast('command.done', {'text': 'Opened ' + title}) 
    return handler 

    def applyLexer(self, sci, title): 
    (language, lexer) = language_and_lexer_from_title(title) 
    if lexer: 
     l = lexer() 
     print("making lexer: " + str(l)) 
     sci.setLexer(l) 
    else: 
     print("setting lexer by id: " + str(language)) 
     sci.SendScintilla(Qsci.QsciScintillaBase.SCI_SETLEXER, language) 
    linst = sci.lexer() 
    print("lexer: " + str(linst)) 

    def makeScintilla(self): 
    sci = Qsci.QsciScintilla() 
    sci.setUtf8(True) 
    sci.setTabIndents(True) 
    sci.setIndentationsUseTabs(False) 
    sci.setIndentationWidth(4) 
    sci.setMarginsFont(self.smallFont) 
    sci.setMarginWidth(0, self.smallFontMetrics.width('00000')) 
    sci.setFont(self.monoFont) 
    sci.setAutoIndent(True) 
    sci.setBraceMatching(Qsci.QsciScintilla.StrictBraceMatch) 
    handler = SciHandler(sci) 
    self.handlers[sci] = handler 
    sci.setMarginLineNumbers(0, True) 
    sci.setCaretLineVisible(True) 
    sci.setCaretLineBackgroundColor(QtGui.QColor(prefs.get('color.editline'))) 
    return handler 

Supposons que le reste des travaux d'application, aussi (parce qu'il le fait :-)

Répondre

3

La réponse a été que la documentation de QsciLexerCustom est trompeuse. Il ne suffit pas d'appeler setStyling() avec un objet QsciStyle. Seul l'index numérique de cet objet semble réellement avoir de l'importance. En outre, votre lexeur personnalisé doit remplacer les polices font(), color() et autres fonctions de style qui prennent un index de style et renvoyer le style que vous souhaitez avoir pour cet index.