Unsolved Saving and discarding QAbstractTableModel in a dialog
-
Hi, I am having trouble with having good practices for saving and discarding changes. I want to be able to open a dialog make changes to a table in a TableView and decide whether to keep the changes or not when exit the dialog.
Since the TableView modifies your existing data automatically, I had to come up with a way to prevent that. In a setup call to the dialog class, I passed in a pointer of the table model, stored it as a member variable, and made its own copy. The TableView would set its model to the copy. If "Save" is pressed, then I have the stored pointer of the table model clone the copy. If "Cancel" is pressed, then I simply do nothing and close the dialog.
This method works in general, but has become more complicated because my tables are inheriting from a base class. Therefore, it has become difficult to make a local copy because I need to know what is the derived class. This has led to creating additional classes for every type of table just to use this dialog.
Does anybody have a simpler solution to the problem of preventing a TableView from applying its changes until the user accepts them?
Thanks!
-
@Nekreg45 said in Saving and discarding QAbstractTableModel in a dialog:
Therefore, it has become difficult to make a local copy because I need to know what is the derived class. This has led to creating additional classes for every type of table just to use this dialog.
Don't try to do the copy this way. Use the inherited
data()
method: iterate through all the rows & columns calling that. -
Hi
Since its a custom model where you can control everything, could you not
store the original value in a user role on edit.Then if changes are to not be saved, loop over the indexes and restore the values
for the changed ones. ? -
You can use
RoleMaskProxyModel
from this library
Example:QDialog editDialog; // create the proxy RoleMaskProxyModel* editProxy = new RoleMaskProxyModel(&editDialog); editProxy->setSourceModel(model); // tell it to intercept all changes to EditRole editProxy->addMaskedRole(Qt::EditRole); QTableView* editView = new QTableView(&editDialog); editView->setModel(editProxy); QDialogButtonBox *dialButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel ,&editDialog); QObject::connect(dialButtons,&QDialogButtonBox::accepted,&editDialog,&QDialog::accept); QObject::connect(dialButtons,&QDialogButtonBox::rejected,&editDialog,&QDialog::reject); QVBoxLayout* dialLay = new QVBoxLayout(&editDialog); dialLay->addWidget(editView); dialLay->addWidget(dialButtons); if(editDialog.exec()){ // if the dialog is accepted save the changes back into the model for(int i=0;i<editProxy->rowCount();++i){ for(int j=0;j<editProxy->columnCount();++j){ model->setData(model->index(i,j),editProxy->index(i,j).data()); } } }
-
@mrjj Wouldn't this mean that I would have to store two sets of data on my custom model? One that is my "saved" data and the other is "modified but not saved" data?
I like the idea of being able to custom the data being retrieved vs edited, but it feels wrong to store temporary data for the lifetime of the model.
-
@VRonin Thanks. What is licensing associated with this library?
This seems to do what mrjj said, but it uses the proxy model to be a temporary inbetween while it's being used by the view. Does this class make a copy of the original model? Is that the magic?
-
@Nekreg45
Hi
well you would store only the modified ones, so might not be that many.
In any case, we will need some way of storing original values to be able to revert so
even with other solutions, we still end up with a cloned model or a cache of the value of sorts.I would try @VRonin RoleMaskProxyModel as then it will just work without altering your model code.
-
@Nekreg45 said in Saving and discarding QAbstractTableModel in a dialog:
What is licensing associated with this library?
Apache 2 (Basically MIT + you have the added protection against patent trolls)
Does this class make a copy of the original model? Is that the magic?
Nope. It has an internal storage system for data that is "masked", for the rest it just uses the data in the original model (just like
QIdentityProxyModel
).
Then you have the option of discarding the data saved in the proxy model (just destroy the proxy) or feeding it back to the original model (the two for loops at the end in my example)