Monday, December 22, 2014

Preferences done, still waiting

I completed the Preferences dialog. It looks about the same as the test version shown in the prior post, plus the addition of buttons for Defaults, Cancel, Apply and OK.

Getting things to work smoothly with the "Apply" button took a bit of work. There are four highlight types the user can change: the editor current line, the text of a limited Find/Replace range, spelling error words, and scanno words. The first two use one mechanism, the second two use a completely different one.

As noted in some post I can't be arsed to look up now, the current-line highlight is done using an "extra selection", and the find-range highlight is done using another. An extra selection is a peculiar thing unlike any other class in Qt (that I know of; maybe the graphics area has similar things). It has no behaviors, no methods; it is basically a two-ple of a cursor and a format (QTextCursor and QTextCharFormat). You give your QTextDocument a list of your extra selection objects and it applies each one's format on its cursor's selection.

The current line's cursor gets updated whenever the edit cursor moves. The find-range cursor gets updated only when the user toggles the In Selection switch in the Find panel.

Their formats get updated only when the Preferences dialog calls the colors module set_current_line_format or set_find_range_format. At that time, the colors module emits a signal, ColorsChanged, which is fielded by editview, and it refreshes the formats in its list of two extra selections.

Therein lies one problem. The user can choose a new format for current line or find range, and click the Apply button in Preferences, and the the highlighting in the visible part of the Edit panel should change immediately. But it didn't, apparently because signals don't get processed while a modal dialog is up. However, I added a call to QCoreApplication.processEvents() in the Apply logic, and then, ta-daa, those two highlights changed instantly upon Apply.

The spellcheck and scanno highlights are created by a different mechanism. They are applied by a QSyntaxHighlighter. Syntax highlighting is turned on by assigning a document to the highlighter, and turned off by assigning a null document to it. But the highlights it applies don't change once they are set until the highlighted text is hidden and shown again, e.g. by paging the document in the editor.

So those two highlights didn't change even though the editor was getting control in its ColorsChanged signal slot. I had to add logic to this slot to ask, is highlighting of either scanno or spelling now active? If so, turn highlighting off, and turn it on again. That forces re-tagging of visible words. With that change, the visible highlighting changes instantly when Apply is clicked.

I am a bit concerned about this last, because in Version 1, there was a significant delay when you turned on the syntax highlighter in a large document. I assumed this was because at that time it would go over the whole document passing every text block through the highlighter. If Qt5 behaves like Qt4, clicking the Apply button in Preferences might incur a significant (1-3 second) stall when the spelling or scanno highlight has changed. That delay isn't noticeable now. There's no perceptible delay with a 25-page document. I hope that Qt5 is smarter and only invokes the highlighter for visible text. Even if there is a delay, these highlights are not something you'd change often.

For now it all works nicely. Doing Preferences was supposed to fill the time until PyQt5.4 was out. I'm done, and it isn't. Now what?

No comments: