Den ons 3 juni 2020 10:38Jonathan Purol <[email protected]> skrev: > Hello everyone, > > I've been in a bit of a tough spot recently with `QAbstractItemModel`. > I'll try to delineate my situation, then my problem, and then the > potential solutions and why I think they're all inferior to what I wish > to have. > > We have a desktop applications using QtWidgets, however instead of a > data model we obtain our data from an "external source" (this is a > little complicated in our use case, but you can think of it as a remote > server for all intents and purposes). > Now the server emits events for changes in the underlying data model. > For example there is an event for `itemAdded` with all appropriate data > points being passed to us via a web socket. > This is all fine and dandy. > > The problem arises when I try to now connect this to the model > representing all `Item` objects. > Qt requires both `beginInsertRows` and `endInsertRows` to be called when > these changes are made. Furthermore it requires the underlying data to > really only be changed in-between those calls. I.e. `rowCount` should > return something different at the time `beginInsertRows` is called than > at the time `endInsertRows` is called. So far so good. But we don't > really have that in-between point. We only get notified when the change > has already happened. > > There are a few solutions I could see here: > 1. Keep a local cache of all of the data, update it incrementally when > changes come through with this pattern: > - change events arrives > - emit "begin change" > - update internal data > - emit "end change" > > 2. Keep a local cache of all the data on a per-model basis then repeat > as can be seen above > > I dislike both of these changes, even if they do solve the issue > flawlessly. The reason for that is that it is quite a bit of overhead. > Both regarding code complexity as well as regarding memory usage and > performance. Don't get me wrong, having a cache is important, and we > will have one as well. What doesn't stick right with me is a cache that > in turn keeps track of all the data all the time. > > Now you might say "why not just have the server emit both a "before" and > a "after" change event for whatever happens. > Yeah, I would love to do that - but with Qt's current setup it just > isn't possible. > What Qt is missing is an `abortInsertRows` function to reset the model's > internal state. > There are many, many things that can go wrong in our setup, even IF the > data was successfully updated. And if we cannot tell Qt to revert the > changes in case such an error occurs we cannot possible use this approach. > The only solution I would see here would be to call > `begin/endResetModel` in case an error occurs, but that sounds like > trying to put a nail into a coffin with a wrecking ball. >
I understand your problem. I've not been in your situation, but how about - Change server to emit before and after events, plus a cancel event. - Upon receiving a before event, call beginInsertRows, - Upon receiving an after event, call endInsertRows, - Upon receiving a cancel event, call endInsertRows, then call beginRemoveRows, remove the cancelled rows, then call endRemoveRows. Could that work? I don't think the models would ever show the cancelled data, as control never returned to the event loop during the dance in the last step. Cheers, Elvis > My questions now are as follows: > Is there any chance `abort*` methods would be added in the future? > Could I perhaps add such a method myself? > Is it safe to just call `endInsertRows` when no changes were made? > Is there a simple solution I overlooked? > > Sincerely, > Jonathan Purol > > _______________________________________________ > Interest mailing list > [email protected] > https://lists.qt-project.org/listinfo/interest >
_______________________________________________ Interest mailing list [email protected] https://lists.qt-project.org/listinfo/interest
