Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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?


  • @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!

Log in to reply