On 05/11/12 20:25, Adam Light wrote: > I have tried emitting SourceModel::dataChanged() when a node goes from > not having children to having children, but that does not cause the view > to update correctly. Emitting layoutAboutToBeChanged()/layoutChanged() > *does* cause the view to be updated correctly, but often I get crashes > when layoutChanged() is called (possibly related > to https://bugreports.qt-project.org/browse/QTBUG-19261).
Hi Adam, I'd strongly encourage to check your model using ModelTest [1]. The trouble with Qt models is that any error you make will usually result in subtle errors or segfaults at a later time. The dataChanged() signal itself only informs the attached views/proxies that the *contents* of an index (or an index range at one level) has changed, but it says nothing about existence of children of the affected indexes. That's what rowsInserted() and friends is for. > What is my model supposed to do when a node in the model now has > (unloaded) children to alert views using the model of the change? I > can't use beginInsertRows() because the child rows are not yet actually > inserted into the model. Emitting dataChanged() doesn't seem to have the > desired effect. Lazy loading can still work, even in this scenario. You're right that there seems to be a slight asymmetry in the MVC API when dynamically updating the model; unlike the hasChildren() method, there's nothing like childrenArrived() signal and you really have to emulate that by calling beginInsertRows etc. However, these items that you somehow have to manufacture can easily be created by your model without actually fetching their real data; that can be deferred to the time the model gets aksed for them (through data() or any other relevant function in your scenario). In my use case (an IMAP e-mail client), user opening a mailbox results in being asked for hasChildren() (or rowCount()) being called for an index which correspond to a mailbox. The mailbox is not opened yet, so my code returns 0 and queues a netowrk operation for finding out what is in that mailbox. Some time later, when the mailbox is resynchronized so that I know how many messages are in there, my model calls the beginInsertRows()/endInsertRows() combination, but no actual message data is downloaded yet. The QTreeView now knows how many rows of e-mails to show, and begins asking for their data by calling my Model's data() method on each of these indexes (actually just those of them which are visible thanks to the view's uniformRowHeights). This means that when users opens a mailbox with 50k messages, but only 20 of them are visible on screen, I get requests for (some columns) x 20 of index data. That's the time when my model begins downloading stuff from network. Now, there are obviously use cases when it's too expensive to even compute the amount of child indexes below some parent. In that case, I'd probably return true from the hasChildren() method when the status of children is not known. The Qt's views will call rowCount() when the view gets expanded and the child items shall become visible. I'd probably request your expensive operation from that rowCount() method and return 0; when the computation finishes and your result is ready, you shall call the beginInsertRows() etc. One last comment -- you've mentioned that your code observes the internal state of the application and presents the data to other layers. You shall be *very* careful in there; when you merely observe a state, you shall make sure that you always return consistent data, which might easily become a hard problem (one of my favorite examples is model calling rowsInserted, which results in view calling rowCount() on me, which leads to model checking an on-disk cache which populates its in-memory tree structures, resulting in yet more rowsInserted signals -- but those cannot be emitted, simply because the view is already processing that event and doing it recursively *will* fail and corrupt memory -- that's just pure fun). So I'd strongly suggest to double-check that whatever you report about the state of your data remains consistent at all times. Delayed updates have served me well here. Cheers, Jan [1] http://qt-project.org/wiki/Model_Test -- Trojita, a fast e-mail client -- http://trojita.flaska.net/
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest