[PyQt] Problem to make the use of folder with QScintilla (even with traditional lexer)

projetmbc projetmbc at club-internet.fr
Wed Jul 15 01:37:41 BST 2009


Hello,
normally,  
self.editor.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)  asks to 
the QScintilla widget to reduce or expand foldings by using the mouse. 
This doesn't work in the joined code even if foldings are marked by a 
vertical line.

What's the problem with the way I define options of the editor ? Here is 
a piece of code :
=============================================
class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle('Custom Lexer Example')
        self.setGeometry(QtCore.QRect(50,200,400,400))
        self.editor = Qsci.QsciScintilla(self)
        self.editor.setUtf8(True)

        self.editor.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
       
        self.setCentralWidget(self.editor)
        self.lexer = CustomLexer(self.editor)
        self.editor.setLexer(self.lexer)
        self.editor.setText('\n# sample source\n\nfoo = 1\nbar = 2\n')

class CustomLexer(Qsci.QsciLexerCustom):
       ..........
=============================================

Best regards.
Christophe.
-------------- next part --------------
#!/usr/bin/env python
#coding=utf-8
import sys
from PyQt4 import QtCore, QtGui, Qsci

# Code given by Baz WALTER on the PyQt list

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle('Custom Lexer Example')
        self.setGeometry(QtCore.QRect(50,200,400,400))
        self.editor = Qsci.QsciScintilla(self)
        self.editor.setUtf8(True)

        self.editor.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
        
        self.setCentralWidget(self.editor)
        self.lexer = CustomLexer(self.editor)
        self.editor.setLexer(self.lexer)
      
        self.editor.setText('\n# sample source\n\nfoo = 1\nbar = 2\n')


class CustomLexer(Qsci.QsciLexerCustom):
    def __init__(self, parent):
        Qsci.QsciLexerCustom.__init__(self, parent)
        self._styles = {
            0: 'Default',
            1: 'Comment',
            2: 'Key',
            3: 'Assignment',
            4: 'Value',
            }
        for key,value in self._styles.iteritems():
            setattr(self, value, key)

    def description(self, style):
        return self._styles.get(style, '')

    def defaultColor(self, style):
        if style == self.Default:
            return QtGui.QColor('#000000')
        elif style == self.Comment:
            return QtGui.QColor('#C0C0C0')
        elif style == self.Key:
            return QtGui.QColor('#0000CC')
        elif style == self.Assignment:
            return QtGui.QColor('#CC0000')
        elif style == self.Value:
            return QtGui.QColor('#00CC00')
        return Qsci.QsciLexerCustom.defaultColor(self, style)

    def styleText(self, start, end):
        editor = self.editor()
        if editor is None:
            return

        # scintilla works with encoded bytes, not decoded characters.
        # this matters if the source contains non-ascii characters and
        # a multi-byte encoding is used (e.g. utf-8)
        source = ''
        if end > editor.length():
            end = editor.length()
        if end > start:
            if sys.hexversion >= 0x02060000:
                # faster when styling big files, but needs python 2.6
                source = bytearray(end - start)
                editor.SendScintilla(
                    editor.SCI_GETTEXTRANGE, start, end, source)
            else:
                source = unicode(editor.text()
                                ).encode('utf-8')[start:end]
        if not source:
            return

        # the line index will also be needed to implement folding
        index = editor.SendScintilla(editor.SCI_LINEFROMPOSITION, start)
        if index > 0:
            # the previous state may be needed for multi-line styling
            pos = editor.SendScintilla(editor.SCI_GETLINEENDPOSITION,
                                       index - 1)
            state = editor.SendScintilla(editor.SCI_GETSTYLEAT, pos)
        else:
            state = self.Default

        set_style = self.setStyling
        self.startStyling(start, 0x1f)

        # scintilla always asks to style whole lines
        for line in source.splitlines(True):
            length = len(line)
            levelFolder = editor.SendScintilla(editor.SCI_GETFOLDLEVEL, index)
            if line.startswith('+ '):
                state = self.Comment
                editor.SendScintilla(editor.SCI_SETFOLDLEVEL, index, levelFolder+10)
            else:
                # the following will style lines like "x = 0"
                pos = line.find('=')
                if pos > 0:
                    set_style(pos, self.Key)
                    set_style(1, self.Assignment)
                    length = length - pos - 1
                    state = self.Value
                else:
                    state = self.Default
            set_style(length, state)
            # folding implementation goes here


# PB PB PB PB PB PB PB PB PB PB PB PB PB PB PB PB PB 
           
            index += 1


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    app.connect(app, QtCore.SIGNAL('lastWindowClosed()'),
                QtCore.SLOT('quit()'))
    win = MainWindow()
    win.show()
    sys.exit(app.exec_()) 


More information about the PyQt mailing list