Commits

Henning Schröder committed 972c646

added pure Python implementation of QSyntaxHighlighter for further customization

Comments (0)

Files changed (3)

 import sys
 import os
 from PyQt4.QtGui import QApplication, QMainWindow, QPlainTextEdit, QFont
-from highlighter import SyntaxHighlighter, load_syntax
+from highlighter import SyntaxHighlighter, load_syntax, Format
 from highlighter.python27 import syntax
 
 scheme = {
         self.edit = QPlainTextEdit(self)
         self.setCentralWidget(self.edit)
         self.edit.setPlainText(src)
-        
+        self.edit.cursorPositionChanged.connect(self.on_cursor_position_changed)
         font = QFont()
         font.setFamily("Courier")
         font.setPointSize(10)
             parts_scanner, code_scanner, formats, default_font=font)
 
 
+    def on_cursor_position_changed(self):
+        tc = self.edit.textCursor()
+        row = tc.blockNumber()
+        col = tc.positionInBlock()
+        cf = tc.charFormat()
+        name = cf.stringProperty(Format.NAME)
+        self.setWindowTitle("cf: %s (%s,%s)" % (name, row, col))
 
 
 if __name__ == "__main__":

highlighter/__init__.py

     QColor, QTextCharFormat, QFont, QBrush, QTextFormat)
 
 
+from customhighlighter import CustomHighlighter as QSyntaxHighlighter
+    
+class TextCharFormat(QTextCharFormat):
+    pass
+
 
 class Format(object):
 
 
     def __init__(self, name, color=None, bold=None, italic=None, base_format=None):
         self.name = name
-        tcf = QTextCharFormat()
+        tcf = TextCharFormat()
         if base_format is not None:
             if isinstance(base_format, Format):
                 base_format = base_format.tcf
             The name is the name of a partition or token
             
         """
-        QSyntaxHighlighter.__init__(self, parent)
+        super(SyntaxHighlighter, self).__init__(parent)
         if default_font:
             parent.setDefaultFont(default_font)
         

highlighter/customhighlighter.py

+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import QObject, SIGNAL, QTimer
+from PyQt4.QtGui import QTextDocument, QTextLayout, QTextEdit, QPlainTextEdit, QTextBlock
+
+
+class CustomHighlighter(QObject):
+
+    def __init__(self, parent=None):
+        QObject.__init__(self, parent)
+        self._overrides = []
+        self._add_override = self._overrides.append
+        if parent:
+            if isinstance(parent, QTextEdit) or isinstance(parent, QPlainTextEdit):
+                self.add_to_document(parent.document())
+            elif isinstance(parent, QTextDocument):
+                self.add_to_document(parent)
+
+
+    def add_to_document(self, doc):
+        self.connect(doc, SIGNAL("contentsChange(int, int, int)"), self.highlight)
+        QTimer.singleShot(0, lambda:self._rehighlight_all(doc))
+        
+
+    def _rehighlight_all(self, doc):
+        block = doc.begin()
+        while block and block.isValid():
+            self._highlight_block(block)
+            block = block.next()
+        
+        
+    def highlight(self, position, removed, added):
+        doc = self.sender()
+    
+        block = doc.findBlock(position)
+        if not block.isValid():
+            return
+    
+        endBlock = QTextBlock()
+        if added > removed:
+            endBlock = doc.findBlock(position + added)
+        else:
+            endBlock = block
+    
+        # XXX: why highlight whole block only if some chars changed?
+        while block.isValid() and not (endBlock < block):
+            self._highlight_block(block)
+            block = block.next()
+
+            
+    def setFormat(self, pos, length, format, _FormatRange=QTextLayout.FormatRange):
+        trange = _FormatRange()
+        trange.start = pos
+        trange.length = length
+        trange.format = format
+        self._add_override(trange)
+        
+
+    def _highlight_block(self, block):
+        del self._overrides[:]
+    
+        self.previousBlockState = block.previous().userState
+        self.setCurrentBlockState = block.setUserState
+        
+        layout = block.layout()
+        text = block.text()
+        
+        self.highlightBlock(text)
+        
+        layout.setAdditionalFormats(self._overrides)
+        block.document().markContentsDirty(block.position(), block.length())
+
+    
+        
+    def highlightBlock(self, text):
+        pass