Sunday, January 25, 2015

Progress in bits n pieces

Saturday I finished up adding a flexible Edit menu to the Words panel. It is really two panels in one, the Word table that lists the vocabulary, and beside it, a good-words list. When the focus is in the Word table, the Edit menu has the choices Copy, Find, and Find Next. When you slide right and click on the good-words list, the Edit menu has the choices Copy, Paste, and Delete. These represent new function compared to V1.

  • In the Word table you can now Edit>Copy (or control-c) the selected words (the table allows complex selections using shift-click and control-click). All selected words go to the clipboard as a space-separated list. In V1 you could do this with control-shift-click; the Edit menu choice had no effect because it was bound to the editor.
  • In the Word table, the Find and Find-Next are new features, a simple search for a word. The found word is scrolled to the middle of the window. The Word table can be quite large and this is handy.
  • In the good-words list, Edit>Copy/^c copies words selected in that list to the clipboard.
  • In the good-words list, Edit>Paste/^v adds any words on the clipboard to the list, which automatically makes them correctly-spelled in the Word table. This function was already there as drag-drop from the Word table so it was easy to implement.
  • In the good-words list, Edit>Delete removes selected words from the list, which automatically makes the Word table re-check their spelling. This function was already there for the Delete/Backspace key, so again it was easy to implement

This all went in very simply and cleanly, which I take as proof I've built a pretty decent software structure.

Saving me from some kind of shoulder injury from patting myself on the back, I noted in testing these features that the Refresh operation was taking a very long time. The test book has only 1,400 unique words (in a total of 4,500). When you open the book, the Word table is empty. You click Refresh and the program does these things:

  1. Tells the Qt table model beginResetModel().
  2. Runs through the entire text (25K in this case) using a regex to isolate word-like tokens, spell-checking them, and adding them to an ordered dict. This takes about 0.1 second.
  3. Tells the Qt table endResetModel(). This causes Qt to rebuild its table by calling rowCount() then calling the data() method for values for all the columns (3) and rows (1400). Then, one presumes, it calls the sortFilterProxy which is needed to support sorting columns.

Step 3 takes just over seven seconds. Not good. I spent some time instrumenting parts of this so I have some numbers to compare as I make changes. But it isn't clear just where I should look to make improvements. Much of this process happens outside my control. Yes, it is calling into the table model data() function at least 3*1400 times (probably many more, there are several different "roles" it can request for each cell). But here's the thing. The seven seconds only happens the first time I click Refresh. If I click it again, which goes through the exact same process, it takes much less time, less than a second!

So something very lengthy happens the first time an empty table is populated, that does not happen when the table is re-populated. Such work has to be down in Qt-land out of reach of my code. I think. So I may just leave this issue open for now.

Meanwhile, I got an updated version of Nuitka. It does all the right things about relativizing the links within DLLs. However, the compiled app then crashes with a warning that "you might be loading two sets of Qt binaries into the same process". This is a fairly common problem, as a quick duckduckgo search reveals. I spent an hour this morning trying to find the problem, sending several emails to Kay as I went. In the end it looks as if the problem can be resolved by including a qt.conf file. But that remains to be tried out tomorrow.

No comments: