On Thu, Feb 4, 2016 at 10:25 AM, john lunzer <[email protected]> wrote:
> From here > <http://stackoverflow.com/questions/26505729/how-to-display-non-printable-symbols-in-qtextedit-pyqt4> > I > found a little snippet of code which makes tabs and spaces visible: > > doc = QtGui.QTextDocument() > > option = QtGui.QTextOption() > option.setFlags(QtGui.QTextOption.ShowTabsAndSpaces) > > doc.setDefaultTextOption(option) > textEdit = QtGui.QTextEdit() > textEdit.setDocument(doc) > > From a different post > <http://stackoverflow.com/questions/32147592/color-whitespace-and-paragraph-separators-in-qtextedit-with-qsyntaxhighlighter> > (although > it is a C++ example) it shows that a custom highlighter can be used to > colorize these visible tabs and spaces. > Thanks for this! It would be a good addition. > > I have for a while wanted to make this change because the way Leo > currently handles "invisibles" is too conspicuous to keep on all the time. > > I'm looking for some direction on how this might be integrated into Leo? > Any help would be greatly appreciated. > In general, the best approach is use the search command. Nowadays, I would use cff. Let's try a search on setDocument...I get the following headlines: ctor (LeoQtSyntaxHighlighter) pqsh.setDocument pqsh.Birth & death These are out of context, so let's use Alt-N (goto-next-clone) to find the context. They are all in leoColorizer.py, which is a good sign. The python_qsh switch is True at the top of leoColorizer.py, which means that the PythonQSyntaxHighlighter class is in effect. Looking at pqsh.setDocument, it's clear that it is one place to apply the patch. Indeed, there is this assert: assert isinstance(d, QtGui.QTextDocument), d So let's apply the patch! Right after the above assert: assert isinstance(d, QtGui.QTextDocument), d if d: if 1: # Show invisibles option = QtGui.QTextOption() option.setFlags(QtGui.QTextOption.ShowTabsAndSpaces) d.setDefaultTextOption(option) d.contentsChange.connect(self.q_reformatBlocks) d.rehighlightPending = True # Set d's pending flag. QtCore.QTimer.singleShot(0, self.delayedRehighlight) And it works! So let's connect it for real. Again, the only effective way is to start with a search. Let's guess showInvisibles, because there is a show-invisibles command. Heh, the first hit is: self.showInvisibles = c.config.getBool("show_invisibles_by_default") in the leoColorizer.py. Now it gets really tricky. showInvisibles is an ivar of the JEditColorizer class, but the code we are adding is in the PythonQSyntaxHighlighter class. Actually, it's in the LeoQtSyntaxHighlighter class, a subclass of pqsh. The ctor for LeoQtSyntaxHighlighter creates this ivar: self.colorer = JEditColorizer(...) So the test we want in pqsh.setDocument is: if self.colorer.showInvisibles: Let's try it. Still throws an AttributeError, but we are close. The problem is that LeoQtSyntaxHighlighter creates the pqsh class *before* creating the colorer ivar. So the solution is to create the pqsh class *last*. Yup, that works, or at least doesn't crash on startup :-) But the toggle-invisibles command still doesn't work. Searching for 'toggle-invisibles' gets us to c.showInvisiblesHelper. Hmm. It sets colorizer.showInvisibles, not colorer.showInvisibles. So let's add this line to c.showInvisiblesHelper: colorizer.highlighter.showInvisibles = val Traces show that this is the correct ivar, but doh, pqsh.setDocument is called only during startup. So it looks like we are going to have to dynamically set the flags in pqsh.rehighlight_helper. A trace confirms that this helper is called when we do a toggle-invisibles. Let's add this code: if self.colorer.showInvisibles: option = QtGui.QTextOption() option.setFlags(QtGui.QTextOption.ShowTabsAndSpaces) self.d.setDefaultTextOption(option) That works, but there are two problems. First, the *old* way of showing invisibles is still in effect, and second, there is no way to turn off the new way of showing invisibles. To handle the second problem, let's add an else clause. Like this: option = QtGui.QTextOption() if self.colorer.showInvisibles: option.setFlags(QtGui.QTextOption.ShowTabsAndSpaces) self.d.setDefaultTextOption(option) And that works. But we still have to turn off the old way of highlighting invisibles. Let's try commenting out a line in c. showInvisiblesHelper: # colorizer.showInvisibles = val Nope. That doesn't work. Searching on showInvisibles gets us to: JEditColorizer.configure_variable_tags. So what we want is to disable the code there, or to disable JEditColorizer.showInvisibles. Let's try the latter. There is a comment that JEditColorizer is c.frame.body.colorizer.highlighter.colorer So let's *add* the following line to c.showInvisiblesHelper: colorizer.highlighter.colorer.showInvisibles = val Still no joy. Ah. JEditColorizer.configure_variable_tags is only called at startup. Looking further, we see that JEditColorizer.match_blanks tests showInvisibles. So let's just have it always return. Yup. That works. I haven't upped this change. I suppose it could be yet another option, but I think we should use the new code. It is the recommended Qt way. I plan to do this soon, unless there are objections. A long answer to your question. The short answer is, use cff to find the code to look at, and then play around and see what happens. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/leo-editor. For more options, visit https://groups.google.com/d/optout.
