PDA

View Full Version : How to inform a Model/TableView that some data changed?



Petruza
19th June 2010, 16:20
I have a QTableView and a Table Model, how do I inform the view that some data changed? or do I have to inform the model instead?
Is there a method to call? or should it be handled with slots/signals?

MorrisLiang
19th June 2010, 18:04
Check the QAbstractItemModel docs.

#1 You can just emit layoutAboutToBeChanged() and layoutChanged().The view will then update itself thoroughly.
#2 If you are inserting/removing/moving items.Check the protected function.
example:


void MyModel::removeOneRow(int index)
{
beginRemoveRows(xx);
...//Do the remove action here.
endRemoveRows(xx);
}

After calling this function,the view will also update itself.
#3 If you want to update a range of item.Check the dataChanged(xxx) signal.

waynew
20th June 2010, 17:30
Depends on the model and view design.
For example, if you change data in a database directly, that the model depends on, then all you would have to do is model->select() to refresh it. The view will get a signal from the model and show the changes.
When a user edits data directly in the view, and hits enter, the model should be updated.

Petruza
20th June 2010, 18:45
No, I'm not inserting or deleting rows or columns, just changing individual cell's values.
It's not a database model either.
It's a custom model subclassed from QAbstractTableModel, the underlying data structure is a simple char[] array, with its dimensions not changing, and the Table View just displays their contents.
So, should I fire signal dataChanged() from the model or from the view?

squidge
20th June 2010, 18:52
How will the view know what has changed? Only the class (model) that has the data will know that, so you fire it from there. The view will receive the signal and update accordingly.

Petruza
20th June 2010, 18:53
I wasn't clear enough, what I meant is if I had to call the view's signal dataChanged() or the model's signal dataChanged()

Petruza
20th June 2010, 20:01
Ok I'll try to explain better:

I have a char array that's the underlying data structure.
I've subclassed QAbstractTableModel to act as the model.
I've added a Table view like this:

http://img692.imageshack.us/img692/3484/tableviewpng.png

I have a timer that increments the underlying data, in its [0,0] position.
Right now, when I select a cell, or interact in some way with the table, then the cell's value is updated, because the table view somehow calls the model's data() method.
What I want to achieve is on each timer event, twice per second, the view updates the cell's values on the screen.
So please tell me what object should be the sender, and what signal of it, and what object should be the receiver, and what slot of it.
Or if I can achieve this with just a method call, instead of signals.

Edit:
I tried emitting layoutChanged() from the model, which works ok.
But I'm setting a timer with 0 msec timout and all I get is the signal emitted no more than 30 times per second, I need something faster.

Can't I just inform the view to update exactly the cell I know has changed?
I tried with the signal QAbstractItemModel::dataChanged, but I can't emit it from a QAbstractTableModel subclass, although it should inherit QAbstractItemModel's members, so what, aren't signals inherited?

waynew
20th June 2010, 20:30
What about this?
void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight ) [signal]

This signal is emitted whenever the data in an existing item changes.

If the items are of the same parent, the affected ones are those between topLeft and bottomRight inclusive
Then connect the signal to a slot where you view->show to refresh it?

How are you setting the model to the data? Seems like all you should have to do is re-run that code on the timer and the model/view signal slot will do what you want without further code.

squidge
20th June 2010, 20:55
I wasn't clear enough, what I meant is if I had to call the view's signal dataChanged() or the model's signal dataChanged()The model doesn't have any idea about the view, or the number of views (there could be multiple views depending on the same model), so the only one you can call is the models.

waynew
20th June 2010, 21:29
Hey Mole - doesn't seem right to me that the model doesn't know about the view.
What about: view->setModel(model)
and from the M/V architecture doc: "Signals from the model inform the view about changes to the data held by the data source."
What did you mean? Maybe only the view now knows about the model, but then what about that line in the doc?

ORBAT
21st June 2010, 16:34
Hey Mole - doesn't seem right to me that the model doesn't know about the view.
What about: view->setModel(model)
and from the M/V architecture doc: "Signals from the model inform the view about changes to the data held by the data source."
What did you mean? Maybe only the view now knows about the model, but then what about that line in the doc?


I think you might just be misinterpreting the documents. The way I see it (and the way MVC is supposed to work) is that models simply inform any listeners of changes. The way this is done in Qt is that models emit signals (like void rowsInserted( const QModelIndex & parent, int start, int end) or void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight) ) and views simply connect to those. At no point is the model aware that something is connected to it, nor does it need to know.

Models are supposed to be just that, models of some underlying data structure. The whole point of MVC is keeping the model, view and controller separate from each other.

Adly
23rd July 2010, 11:44
Well, I tried something and it worked fine. Each time I update my database, I set my tableview one more time


model->setTable("Contacts");
model->select();
ui->tableView->setModel(model);

saa7_go
24th July 2010, 08:12
Can't I just inform the view to update exactly the cell I know has changed?
I tried with the signal QAbstractItemModel::dataChanged, but I can't emit it from a QAbstractTableModel subclass, although it should inherit QAbstractItemModel's members, so what, aren't signals inherited?

You should emit QAbstractItemModel::dataChanged() (http://doc.trolltech.com/4.6/qabstractitemmodel.html#dataChanged) signal inside QAbstractItemModel::setData() (http://doc.trolltech.com/4.6/qabstractitemmodel.html#setData) function.

So, how do you implement QAbstractItemModel::setData() (http://doc.trolltech.com/4.6/qabstractitemmodel.html#setData) function in your custom model?

For more informations about model subclassing, you can look at Model Subclassing Reference (http://doc.trolltech.com/4.6/model-view-model-subclassing.html).