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:
- Overwriting the delegate and emitting a signal from createEditor(),
- then inserted the blank record,
- 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" beforeCreateEditor()
is called, right?So since I too do not see any signal for this, look at your
QTableView
'seditTriggers
(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:
- Overwriting the delegate and emitting a signal from createEditor(),
- then inserted the blank record,
- 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
Example usage: https://github.com/VSRonin/QtModelUtilities/tree/1.0.0/examples/exam_InsertProxyModelShould 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
-