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

QTableView on editing last row add new line



  • I am redoing a legacy system built in ms access and want to simulate the same behavior when adding records to tables. In Access when adding records to a table, access automatically adds a new blank row to the bottom of the record set. I have a custom model with an insertBlankRow function (it calls beginInsertRows() & endInsertRows()), but I need a signal to correctly time the insertion

    Option A:
    I tried sub-classing a delegate/editor and emitted a signal from createEditor(), but when I add the blank row whilst the editor is open the editor's position is not updated correctly. How can I update the editors position to take into account the newly inserted row?

    Option B:
    If I can emit a signal just before an editor is created, then I could add the blank record. How/Where would you emit a signal just before a editor on a QTableview is to be opened?

    PS: Its a PyQt5 app but please feel free to share ideas in either C++ or PyQt (or links)

    EDIT: Sorry I should have mentioned that I have opened up persistent editors/delegates for combo-boxes on certain columns and these editors' alignment are giving me trouble when inserting new rows.



  • @JonB thanks for the reply. Similar to MS Access I have a blank row at the bottom at all times, if the user edit it a new blank row appear below it.

    I got it working by:

    1. Overwriting the delegate and emitting a signal from createEditor(),
    2. then inserted the blank record,
    3. then calling scheduleDelayedItemsLayout() on the QTableView to re-allign the editors.
      (My custom model mange the amount of blank records that can be added this way)
      (Also you just need to disconnect & reconnect the signal when opening persistent editors)

    Edit: I still ran into a bunch of quirks,,, however there is a much simpler way to achieve more or less the same effect. Create 2 TableViews and use the bottom one as the "add new record" table. Link both table's QHeaderViews to make sure their columns stay in sync!

    Edit2: Be sure to see VRonin's answer below for a link to a working C++ model that does exactly what the original question asked



  • Found part of the solution: After adding the new blank row you can loop through the QTableView, remove and then re-open the persistent editors. This will re-align their positions correctly, however the operation is costly.

    I am not sure other than removing persistence altogether if there would be a better way? (Edit: If you call scheduleDelayedItemsLayout() https://doc.qt.io/qt-5/qabstractitemview.html#scheduleDelayedItemsLayout then the editors is updated correctly no need for recreating)

    Either way I still need a signal to time the insert... (Edit: Emitting a signal from the delegates createEditor() function, then calling scheduleDelayedItemsLayout does the trick, you just need to disconnect & reconnect the signal when opening persistent editors)



  • @Rhdr
    If I understand right, you need an "edit signal" before CreateEditor() is called, right?

    So since I too do not see any signal for this, look at your QTableView's editTriggers (https://doc.qt.io/qt-5/qabstractitemview.html#editTriggers-prop) and implement your own slot(s) on the event(s)/signal(s) which are going to going to take you into edit mode?

    Another possibility is QTableView::edit() slot (https://doc.qt.io/qt-5/qabstractitemview.html#edit)

    Starts editing the item corresponding to the given index if it is editable.

    Does that get called before the CreateEditor()? In which case that might be the signal you were looking for?

    Actually it's not terribly clear to me how/when you do this "extra blank row for adding a row". If you do not always have a blank row there won't be anything for the user to edit, so they must have to click a button? If you do have a blank row sitting there all the time, then the signal you are looking for when to add a new blank line is something about after the user has edited the blank line, for next time around. I leave that to you.



  • @JonB thanks for the reply. Similar to MS Access I have a blank row at the bottom at all times, if the user edit it a new blank row appear below it.

    I got it working by:

    1. Overwriting the delegate and emitting a signal from createEditor(),
    2. then inserted the blank record,
    3. then calling scheduleDelayedItemsLayout() on the QTableView to re-allign the editors.
      (My custom model mange the amount of blank records that can be added this way)
      (Also you just need to disconnect & reconnect the signal when opening persistent editors)

    Edit: I still ran into a bunch of quirks,,, however there is a much simpler way to achieve more or less the same effect. Create 2 TableViews and use the bottom one as the "add new record" table. Link both table's QHeaderViews to make sure their columns stay in sync!

    Edit2: Be sure to see VRonin's answer below for a link to a working C++ model that does exactly what the original question asked



  • You can use InsertProxyModel from https://github.com/VSRonin/QtModelUtilities/tree/dev
    Example usage: https://github.com/VSRonin/QtModelUtilities/tree/dev/examples/exem_InsertProxyModel

    Should do exactly what you want but it will probably require a bit of translation from C++ to Python

    If you are reading this in 2059 then maybe I would have found the time to complete the merge of that class in Qt: https://codereview.qt-project.org/c/qt/qtbase/+/236399



  • @vronin that looks like exactly it, thanks for the link! The translation shouldn't be a problem, most of the qt documentation is written in c++ anyway. Is there a way to mark your post as the answer instead?


Log in to reply