Friday, March 20, 2015

Kvetch blog

Do I come across very negative? I don't want to be the grumpy old fart. But really, other people ought to pick up their game a bit, you know?

Take Apple's Numbers. I used Numbers to make a little old spreadsheet composed of some numbers from running my Qt table sort test. I wanted to confirm my suspicion that it was displaying a slow-down that was exponential in N. So I took some numbers and I put them in the table and then I selected the two columns of data:

100 0.336
200 0.356
400 1.366
800 1.614
1600 5.596
3200 7.129
4800 17.389
6400 29.368
7200 38.460
8000 48.738
8800 19.603
9400 22.177
10000 24.371
15000 50.324

And selected Insert > Chart > 2D Line. It seems falling-off-a-log obvious to me that I want the first column to be the X-values and the 2nd column the Y. Go out 100 on the X-axis, go up 0.366, that's point one. Go to 200, up to 0.356, point two. No?

Well, no, not according to Numbers, nor to Open Office when I tried that. In both cases the default chart treats each column as an independent data series to be plotted on the Y-axis against the integers 1-13 on the X. And I spent a gorram half hour trying to figure out how to tell the stupid software to do what I wanted. At the end of which I didn't have a chart, and felt a lot like a grumpy old fart.

Well, take a look at that data. It's neither linear nor a simple exponential. There's a big spike around 8000 rows, then 8800 is nearly equal to 4800, and a new rise starts. This probably tells something very interesting about the internals of QSortFilterProxyModel.

I spent a couple of hours figuring out how to get a look at the Qt source code, and when I found it, reading qsortfilterproxymodel.cpp. I didn't come away any wiser, really. I see where it does the actual sorting. It calls something named as std::stable_sort but I wasn't able to figure out where std was defined. Anyway it is presumably not something silly like an insertion sort.

What I did learn was that QSFPM implements everything an abstract item model does. It's a proxy for all the features a model might provide like showing and hiding columns and rows, and implementing row insertion and deletion and so on. So it is quite complicated and has to be very generalized. It was a faint hope that I'd be able to see any problem with it—you know, like a comment /* TODO this sort blows up over 1000 rows */ or something like that—and of course I didn't see any such thing.

I have figured out how, in concept, to integrate filtering with my sorting scheme. The magic function of the real database model, get_column_vector( col, order ) will take a third parameter. It can be a None, indicating "all rows", or a compiled regex to be applied against the third column. So the sort vector returned will not always have as many rows as the database offers. This seems to be alright with the Qt table view. I verified that it is calling the rowcount() method very frequently. So when the sort() routine emits the layoutChanged signal, the view will call rowcount() which will return, not a fixed global count, but len(self.sort_vector). It should all work out nicely.

There, "nicely". I'm not a grumpy old fart all the time.

No comments: