Friday, August 15, 2014

Current Line, Again

Today I reviewed the editview module, the widget that contains the text editor and also a row of widgets to display the document name, the scanned image filename, the logical page number, cursor line# and cursor column#, all in a row at the bottom.

I'd made this widget using Qt Creator, which means that all the UI setup is in a separate file automatically generated, and merged into my widget using multiple inheritance. (I described the process in this post.)

The complexity of this setup was, I strongly suspected, causing an annoying problem in which the Notes panel, which is actually a second QPlainTextEditor, never got a proper highlight on its selection. A selection in Notes was always 50% gray, which should only be the case when it was visible but did not have the keyboard focus. In any case, the verbose and opaque code output by Creator and pyuic5 irked me. So, after reviewing the existing (and pretty much working) code, I tackled the job of bringing the UI initialization into my own module. It was a lengthy but basically clerical task of copying chunks from the generated module, pasting them into my own, and editing them to simplify them and throw out the redundant bits. (Example redundancy: every lineEdit got its text set to a null string, which is the default anyway.)

After fixing a few syntax errors and tweaking a couple of margin values, it worked. And: the annoying problem with selection highlighting was gone! Click in the Notes panel and make a selection, it's highlighted a nice green, while the selection in the main editor goes to gray. Click in the Edit panel, vice versa. Nice.

But now I had to face a bug that's been there right along (I was in denial). Remember a long time ago, well, May 6, when I wrote about setting a highlight on the current line? I did it by setting the Text Block Format of the current line. Bad Idea, it turns out.

Changing the text block format was causing two problems. First, as soon as I moved the cursor, the document status changed to "modified" (the document name in the lower corner got bold and red). This is because QTextEdit considers a change of text block format to be an undoable action. Anything that goes on the undo stack makes the document modified.

This wouldn't matter a great deal once the document actually was modified, but it is annoying that just hitting a down-arrow turns on the "save me!" indicator. I'm sure a user would complain. OK, I would complain.

But it had another problem also: it was effectively killing control-z undo. If I typed some characters and immediately hit ^z, the undo worked. But if I moved the cursor to another line first and then keyed ^z, the only effect was that the cursor moved down one line. Control-z had become down-arrow. What?!?

I figured it out with a little reading about undo. When QTextEdit performs Undo, it says it leaves the cursor at the end of the changed text. So here's what happens: move the cursor to another line by an arrow key or by clicking. That stacks two changes of TextBlockFormat, one on the old current line (to a white background) and one on the new current line (to a purty pale yellow one). Probably both go in as one undo action, I don't know.

Anyway, now key ^z. What gets undone? The last change of text block format. And the cursor is moved to the end of the restored area, which means, the start of the next line in the document. That's an edit cursor position change, which goes through my code to change the text block format of the new current line, stacking another undo action. Another ^z undoes that and moves down a line. Etc.

I now have to go back to trying to highlight the current line using "extra selections". I tried that initially and something didn't work, I forget what. Well... maƱana.

No comments: