How to implement indentation based code folding in QScintilla?
[erased the previous answer, since in the light of the last question edit the only value it might probably have is historical; refer to the edit history if you`re still curious]
Finally, the optimized version — bundled with 80 kilolines of sample text to show off its performance.
from PyQt5.Qsci import QsciScintillafrom PyQt5.Qt import *def set_fold(prev, line, fold, full): if (prev[0] >= 0): fmax = max(fold, prev[1]) for iter in range(prev[0], line + 1): view.SendScintilla(view.SCI_SETFOLDLEVEL, iter, fmax | (0, view.SC_FOLDLEVELHEADERFLAG)[iter + 1 < full])def line_empty(line): return view.SendScintilla(view.SCI_GETLINEENDPOSITION, line) \ <= view.SendScintilla(view.SCI_GETLINEINDENTPOSITION, line)def modify(position, modificationType, text, length, linesAdded, line, foldLevelNow, foldLevelPrev, token, annotationLinesAdded): full = view.SC_MOD_INSERTTEXT | view.SC_MOD_DELETETEXT if (~modificationType & full == full): return prev = [-1, 0] full = view.SendScintilla(view.SCI_GETLINECOUNT) lbgn = view.SendScintilla(view.SCI_LINEFROMPOSITION, position) lend = view.SendScintilla(view.SCI_LINEFROMPOSITION, position + length) for iter in range(max(lbgn - 1, 0), -1, -1): if ((iter == 0) or not line_empty(iter)): lbgn = iter break for iter in range(min(lend + 1, full), full + 1): if ((iter == full) or not line_empty(iter)): lend = min(iter + 1, full) break for iter in range(lbgn, lend): if (line_empty(iter)): if (prev[0] == -1): prev[0] = iter else: fold = view.SendScintilla(view.SCI_GETLINEINDENTATION, iter) fold //= view.SendScintilla(view.SCI_GETTABWIDTH) set_fold(prev, iter - 1, fold, full) set_fold([iter, fold], iter, fold, full) prev = [-1, fold] set_fold(prev, lend - 1, 0, full)if __name__ == '__main__': import sys import textwrap app = QApplication(sys.argv) view = QsciScintilla() view.SendScintilla(view.SCI_SETMULTIPLESELECTION, True) view.SendScintilla(view.SCI_SETMULTIPASTE, 1) view.SendScintilla(view.SCI_SETADDITIONALSELECTIONTYPING, True) view.SendScintilla(view.SCI_SETINDENTATIONGUIDES, view.SC_IV_REAL); view.SendScintilla(view.SCI_SETTABWIDTH, 4) view.setFolding(view.BoxedFoldStyle) view.SCN_MODIFIED.connect(modify) NUM_CHUNKS = 20000 chunk = textwrap.dedent("""\ x = 1 x = 2 x = 3 """) view.setText("\n".join([chunk for i in range(NUM_CHUNKS)])) view.show() app.exec_()