QTreeView::visualRect and QTreeView::indexAt don't appear to work
-
Apart from @SGaist 's question - is ttv()->model() really tvm() or is there a proxy model in between?
-
@SGaist Thanks for the speedy reply.
scrollTo() will be what I will use when I've recovered the index based on what I've cached. The model may be changing quite a bit, so I'm trying to find the locale of the currently viewed set of objects, cache that information, then when the model is reset, I'll try to scroll back to the approximate location, perhaps simply bringing that item back to the top if I can, or finding data in the same range (it's a table of date-stamped rows).
Since I can't see what's currently in the viewport, I can't figure out what data to grab onto, which I would use to find on the flip side after the model update.
Does that make sense? Surely I'm making some simple mistake or have a wrong assumption. Why wouldn't these APIs "just work"?
-
@Christian-Ehrlicher Yes, ttv()->model() == tvm(). No proxy. At some point I may use a sort proxy, but I wanted to keep it simple for the time being.
-
@Jos_Rarebit said in QTreeView::visualRect and QTreeView::indexAt don't appear to work:
modelAboutToBeReset()
@Jos_Rarebit you have mentioned about handling model reset in modelAboutToBeReset() slot.
If model is getting reset, then old index may not valid for the new model. -
@nagesh I'm not intending to cache any indexes, just find what the visible indexes are. This code is being invoked in response to modelAboutToBeReset(), so the index changes haven't happened yet, anyway. In fact, if I explicitly call the function before the call which causes the model reset, it still does not work.
Anyone have any ideas?
-
Shouldn't you store some identifying data of the visible indexes before the model is changed, then look for the same data and call scrollTo with the appropriate index ?
-
@SGaist Yes. That's exactly what I intend to do. Sorry if that wasn't clear.
The issue is that there doesn't seem to be a way of determining what the visible indexes are. Hence the title of this topic. Or, rather, there is a presumed way to do this, but the API(s) to be used do)es(n't seem to work as expected. So, that's weird!Stepping into the Qt code a bit (what I wanted to avoid!) it seems that QTreeView::visualRect() has no "viewIndex" data for the items in the model. I.e., here's the spot in QTreeView::visualRect() where it appears to be punting:
// QTreeView::visualRect... Q_D(const QTreeView); if (!d->isIndexValid(index) || isIndexHidden(index)) return QRect(); d->executePostedLayout(); int vi = d->viewIndex(index); if (vi < 0) return QRect();
It returns because vi == -1.
I am wondering if my model implementation is deficient in some way. It compiles, so the basic overrides are present. It's basically a model interface of a std::list<> of some class objects, so I don't do anything with insertRows(), I just pretend to reset the model when the underlying data gets rebuilt. But I kind of wonder if the view needs some extra hints to cache some geometry about what it's displaying for this purpose. But it's displaying everything in my model perfectly well, so what could it be? If I emit signals about rows being inserted, that doesn't seem to do anything magical, but then again I'm still not implementing insertRows directly...
Hmm... I guess I'll step into that viewIndex function...
-
so I don't do anything with insertRows(), I just pretend to reset the model when the underlying data gets rebuilt.
Refer to addressbook example in Qt for dynamic model.
I think you should implement insertRows() if your model is dynamic -
@nagesh Thanks for the suggestion. Might be what I have to do. However:
I think this might be a signal-slot order issue that I'll have to work-around. Or use a different signal/slot. I have been using modelAboutToBeReset() signal, but the treeview itself also uses that, and it gets it first.
I set a breakpoint in QTreeViewPrivate::_q_modelAboutToBeReset(),
void QTreeViewPrivate::_q_modelAboutToBeReset() { viewItems.clear(); }
which is the treeview's handler, and it is getting called before my own handler.
Makes sense, given how the signals/slots are generally processed in order of creation.
-
Okay, I had absolutely believed that I had tried making the call to my savePos() function to try to diagnose whether the signal had something to do with it, yet when I disable the connect()ion altogether and call it explicitly, now these APIs want to behave like good little children and do what they're supposed to.
So, essentially I shot myself in the foot by handling this with modelAboutToBeReset(), which implicitly trashes the internal cache of visible indexes.
D'oh! Argh, etc.
Thanks for the help, folks.