Unsolved Model/View: How to tell an edit delegate to update it's position?
-
I have a situation where the edit delegate is not positioned above the cell that is actually edited, but one row below. To the user, it looks as if she were editing the cell in row 3, whereas actually the cell in row 2 is changed.
Is there any way to tell the delegate to update it's position according to the cell being edited?
Background:
I have a rather complex setup: A table view that is connected to a custom-written AbstractItemModel, which obtains the data (already sorted and filtered) from a class running in a separate thread, all in the spirit of high performance and UI responsiveness.Because the actual sorting and filtering is running in a separate thread, changes to the sort order arrive asynchronously. That means, if I change a cell value in a column relevant for sorting, I will receive a notification that the sort order has changed through the event loop.
Much like in Excel, the user should be able to quickly enter values by typing and then pressing <Tab> (jump to next cell to the right) or <Return> (jump to cell below). And the latter is causing trouble.
When the user edits within the "sorted by" column, any change to the content may trigger sorting - asynchronously. This is easiest to show when multiple rows have the same value in the "sorted by" column. Let's say the following table is sorted by column "Name" in ascending order:
Name Source Input F_01 Input F_02 Input F_03 Output F_01 Output F_02 Output F_03
The user wants to make the names unique, and starts editing in the top row (the '|' indicating the text cursor):
Name Source Input_01| F_01 Input F_02 Input F_03 Output F_01 Output F_02 Output F_03
..then presses <Return>.
The value change is committed to the model, and in the "closeEditor" slot, the cell below is selected for editing:Name Source Input_01 F_01 Input| F_02 Input F_03 Output F_01 Output F_02 Output F_03
Now sorting kicks in:
Name Source Input F_02 Input| F_03 Input_01 F_01 Output F_01 Output F_02 Output F_03
The edit delegate remains in row 2, but actually edits the item now in row 1.
The code to select the next cell to edit is basically simple:
if((model() == nullptr)|| selectedIndexes().isEmpty()) { QTableView::closeEditor(editor, hint); return; } //Den selektierten index vor dem Basisklassenaufruf merken const QModelIndex selectedIndex = selectedIndexes().first(); //Achtung: eine const & ist hier nicht möglich QTableView::closeEditor(editor, hint); switch(hint) { case QAbstractItemDelegate::SubmitModelCache: { int row = selectedIndex.row()+1; int column = selectedIndex.column(); if(row >= model()->rowCount()) { row = 0; ++column; } const QModelIndex & newIndex = model()->index(row,column); edit(newIndex); break; } }
(removed some checks for corner cases to make it simpler)
-
- since sorting is asynchronous, can't you just queue
edit(newIndex);
so that it's executed after sorting too? - do you reimplement
QStyledItemDelegate::updateEditorGeometry
?
- since sorting is asynchronous, can't you just queue
-
@VRonin said in Model/View: How to tell an edit delegate to update it's position?:
- since sorting is asynchronous, can't you just queue
edit(newIndex);
so that it's executed after sorting too? - do you reimplement
QStyledItemDelegate::updateEditorGeometry
?
- I have tried delaying the call to edit (using a 1000 ms single shot timer), but as long as newIndex is determined before sorting, the result is exactly the same (for whatever reason). However, since the item that is actually edited is exactly the one I want, the newIndex seems to be correct.
- No, updateEditorGeometry is not reimplemented. But that would give me a handle to find out a bit more. Thanks for the hint!
- since sorting is asynchronous, can't you just queue