Skip to content

Redesigning Lokalize's Translation Memory Tab - Mid-GSoC

Monday, 13 July 2026  |  Navya Sai Sadu

The past three weeks were a mix of cleanup, debugging, completing the work concerning UI and understanding TMView( since I did not look into it during proposal period) and TMTab again to review my design choices and see if I'm going in the right direction.

Cleaning up TMManager and getting checkboxes working

First up was cleaning TMManagerWin, reformatting, removing now obsolete references and code. With that done, I resumed work on the per-project TM selection checkboxes.

The checkboxes are backed directly by DBFilesModel rather than a separate proxy layer. Overriding flags(), data(), and setData() on the existing model was the way to go. Qt's view renders the checkboxes automatically once Qt::ItemIsUserCheckable is set and Qt::CheckStateRole returns a value. Check state persists to ProjectLocal::selectedTMs() immediately on every toggle via saveCheckedState(), and reloads on project open via a Project::loaded connection.

One non-obvious issue I stumbled into and fixed myself was cleanupSelectedTMs(), which removes stale entries for TMs that no longer exist on disk, was being called immediately when Project::loaded fired. But DBFilesModel populates asynchronously via QFileSystemModel scanning the TM directory. The fix was deferring cleanupSelectedTMs() using QTimer::singleShot(), the same pattern used elsewhere in the codebase for async model population. loadCheckedState() itself runs immediately since it only reads from config and doesn't need the model to be populated. This was a subtle timing issue that only surfaced when testing with an actual project and multiple TM databases. In fact, cleanupSelectedTMs() itself wasn't thought of when planning.

After testing this end-to-end and verifying the .local config file was being written and read correctly, I merged this in.

Studying TMView's querying and why it can't help TMTab

Before touching TMTab's query logic, I spent time understanding how TMView (the suggestions dock widget in the editor) does its querying since my mentor suggested that it's querying might help designing something similar for TMTab's multi-TM quering.

TMView uses SelectJob which operates on TMEntry structs, it does fuzzy word-level matching, scores results, and is designed specifically for the suggestions workflow. It fires secondary DB queries only when the primary project DB scores below a threshold.

This is fundamentally different from what TMTab needs, it uses ExecQueryJob which runs SQL query against a DB and hands the cursor to QSqlQueryModel. The two systems aren't interchangeable, so the multi-DB approach for each has to be designed separately I guess. For TMView, the change is relatively small, loop selectedTMs() and fire one SelectJob per DB. For TMTab, it might turn to be little complex.

Removing the dbName combobox

With the TM list in TMManagerWin now showing checkboxes for selection, the dbName KComboBox in the search panel is redundant, users select which TMs to query via checkboxes, not a dropdown. I removed it from queryoptions.ui and cleaned up all references in tmtab.cpp, but some of them need workaround. The openFile() (RemoveFileJob) gets a TODO, to be fixed properly once multi-DB results carry their source DB name.

Debugging with GDB and Dr Konqi

My mentor reported a crash when opening the QA dock widget in the TM tab. This was a good opportunity to learn proper debugging with GDB, Dr Konqi, and reading backtraces.

After investigating, this appeared to be a preexisting bug unrelated to my changes. It's probably data-dependent and only triggers with specific content in the TM results view at the moment the QA dock repaints. It didn't reproduce on my machine. I might work on it later when I have time.

The years old chats on QtForum and StackOverflow were helpful throughout. Qt itself is so well documented!

TM Tab Redesigned

I'm looking forward to see how translators would like the TMTab's glow up when the project is completed and all the changes get merged.