PDA

View Full Version : Buffer form modifications before commiting them to the model



gchauvie
9th September 2016, 10:07
Hello,

I want to edit some object in a form that have an ok and a cancel button. I have a QObject with property exposed to the QML (name, surname, ...) and this QObject has a reference to a Person object.
What I have at first is something like that :


Q_PROPERTY (QString name READ getName WRITE setName NOTIFY nameChanged)

QString PersonViewModel::getName () const
{
return person->getName();
}

void PersonViewModel::setName (QString i_value)
{
person->set_name(i_value);
emit nameChanged(i_value);
}



The issue is that I want to be able to rollback all the modifications made on the form if I click on the cancel button and I want to call the person->setName() only after the user clicks on the ok button.
I thought of overriding the setProperty method to store all the modification in a map and return the value stored in the map like that


QString PersonViewModel::getName () const
{
if(map.contains("name")
{
return map.value("name");
}
else
{
return person->getName();
}
}

void PersonViewModel::setName (QString i_value)
{
map.insert("name", i_value);
}

void PersonViewModel::commitChanges()
{
if(map.contains("name")
{
person->set_name(map.value("name");
emit nameChanged(i_value);
}
map.clear();
}


Is it ok or is there a more desirable way of doing it with QT ?

Thanks.

anda_skoa
9th September 2016, 10:47
You can go with the map, or with member variables for each property or by using two Person objects.

Btw, your setters should check if there is actually any change before emitting the notification signal.

And your commitChanges() method doesn't need to emit them at all because as far as the QML side is concerned there is no value change (the getter will return the same value, just from the Person object instead of the map).

Cheers,
_

wysota
9th September 2016, 12:28
Alternatively the form can operate on a temporary object (e.g. a JavaScript object) and commit the changes to the real object only after the form is confirmed with the ok button.

d_stranz
9th September 2016, 18:17
I usually use the method of two objects. The constructor for the form takes a reference to a const object instance as an argument (or I provide a setter method with the same argument). This is copied into a second object instance owned by the form. All of the get and set operations used by the form are done using the form's instance. When the user clicks OK, the caller can retrieve the form's copy of the object through a getter method.

Using this scheme, the form doesn't need to emit any signals and the form is in control over what happens to its copy of the object. When the caller receives the Accepted result from clicking the OK button (if the form is in a dialog), the caller knows that all of the requirements for a successful edit have been satisfied (otherwise the OK button wouldn't have been enabled).