Recent

Author Topic: TListView and OwnerData  (Read 1078 times)

dbannon

  • Hero Member
  • *****
  • Posts: 2778
    • tomboy-ng, a rewrite of the classic Tomboy
TListView and OwnerData
« on: May 24, 2022, 06:58:03 am »
Hi Folks, I am having a very silly problem and hope someone can suggest a reason.

I find that, in my app, the method that the ListView in OwnerData mode uses to get the necessary data (ie the OnData event, eg ListView1Data() ) is being called for the full dataset, not just the visible data.  So I made a small demo but it works as expected, that is, the OnData event is only called for the data that is visible.

Trying to work out what was different, I ended up adding a new ListView to may app, changing only the ViewStyle to vsReport, OwnerData to True and setting  ListView1.Items.Count := 5000. In my app, this calls ListView1Data() 5000 times, in my demo, exactly the same code, its called 10 or so times.

This is all I have changed in both my demo and my app -
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.FormCreate(Sender: TObject);
  2. begin
  3.     ....
  4.     ListView1.ViewStyle:= vsReport;
  5.     ListView1.OwnerData := True;
  6.     ListView1.Items.Count := 5000;
  7. end;
  8.  
  9. procedure TMainForm.ListView1Data(Sender: TObject; Item: TListItem);
  10. begin
  11.     Item.Caption := inttostr(Item.Index);
  12.     debugln('TMainForm.ListView1Data - ' + inttostr(Item.Index));
  13. end;    

But in the small demo, I see 10 or so calls, in the App, I see 5000.  It has to be something to do with the project but the above code is the ONLY explicit interaction with the app. I have tried changing the memory manager and enabling threading in the demo ('cos thats how my app is). "Clean up and Build", debugging on and off, different optimization. I work with Lazarus 2.2rc2 but its exactly the same with Main.

Can anyone suggest a reason ?  I assume it has to do with my project, its a reasonably big build ....

Davo
Lazarus 2, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

Thaddy

  • Hero Member
  • *****
  • Posts: 14157
  • Probably until I exterminate Putin.
Re: TListView and OwnerData
« Reply #1 on: May 24, 2022, 09:18:58 am »
OwnerData is only available/accessible if the listview item is visible. This is normal behavior and is because of speed.
If you need to process many items, it is better to store  the data that you now store in the listviewitem itself in some other container like a map/dictionary and use a VirtualListview for display. Otherwise the listview will become impossibly slow!
« Last Edit: May 24, 2022, 09:21:30 am by Thaddy »
Specialize a type, not a var.

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: TListView and OwnerData
« Reply #2 on: May 24, 2022, 11:41:25 am »
Does your virtual listview in the app have Multiselect=true? In this case, Laz 2.2 contains a bug that querying which node is the Selected one requires to iterate over all nodes. It has been a long story until this has been fixed without side effects, but if your test with main was done with an "old" version you might still have this issue on-board. Please update to current main, and test again.


dbannon

  • Hero Member
  • *****
  • Posts: 2778
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TListView and OwnerData
« Reply #3 on: May 24, 2022, 01:51:35 pm »
WP - no, multiselect is false.  My TListView settings are the default execpt for the three I mentioned, the three things that must be set to work in Owner Data mode.

Thaddy - as I mentioned, its in OwnerData mode. I don't poke any info into Items except the count.  My OnData event mimicks getting the data from "some other container".

Importantly, the all the TListView settings are exactly the same between the two instances I am looking at. But very different results.

Thanks.

Davo

Lazarus 2, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: TListView and OwnerData
« Reply #4 on: May 24, 2022, 02:07:50 pm »
Are the moments comparable at which you count the calls to OnData? When your app is a "big build" it is hard to keep control over what is changing...

dbannon

  • Hero Member
  • *****
  • Posts: 2778
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TListView and OwnerData
« Reply #5 on: May 25, 2022, 02:29:33 am »
Are the moments comparable at which you count the calls to OnData? When your app is a "big build" it is hard to keep control over what is changing...

Yes, thats why I reduced it down to just a "Item.Caption := inttostr(Item.Index);" - exactly the same in both instances. In both cases, there is no other interaction between the TListView and the rest of the application (except of course the "behind the scene initialisation and parent stuff"). You can grep the source code of my big app and find no other mention of ListView1.

I have to assume that I am doing something silly elsewhere and its triggering this problem but I just don't know where to start looking! Its project wide, if I put that new ListView on a different form, its behaves the same. Its all very strange.

I guess I'll have to start digging through the code.  (going to be a slow process, we'll be traveling soon and spare time and network access will be rare)

Davo

Lazarus 2, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

dbannon

  • Hero Member
  • *****
  • Posts: 2778
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TListView and OwnerData
« Reply #6 on: May 27, 2022, 12:42:01 pm »
No, I am sorry, I missed a very very obvious difference between the two projects that showed different TListView behavior, the one working correctly is using QT5, the one working very badely is using GTK2.

Sigh ....

So, TListView, in OwnerData mode, with GTK2 always scans across the entire dataset at first showing, I believe.

Attached is a demo of the problem, has GTK2 and a Qt5 mode, run it and you will see a number, bottom left, its how many calls are made from the OnData event, its should be only those necessary for the visible data, on GTK2, its the entire set.

Anyone see whats wrong with my code ?

Davo

Lazarus 2, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

 

TinyPortal © 2005-2018