AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Faster way to add rows to a Listview or an alternative?

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Toony Tom
Guest





PostPosted: Sat Dec 12, 2009 12:30 pm    Post subject: Faster way to add rows to a Listview or an alternative? Reply with quote

I'm attempting to build a program to save a list of files on all my dvds and have that list searchable. My problem is that loading more than 30,000 rows into a listview control takes a bit of time. Searching this many rows with a "find as you type" routine becomes really clumsy as well.

Now 30,000 may seem like too much, but I can load winamp, and in less than 10 seconds it's listview is populated with about 17,000 tracks."Everything" is also lightning quick with searching and scanning the hard drive: http://www.voidtools.com/ It actually inspired me to try and code my disc searcher.

Just to give an idea of the time involved, here's a quick simple example:
Code:
Gui,Font,Bold
Gui, Add, Text,x0 y5 w200 h20 vtext,
Gui,Font,
Gui, Add, ListView, x0 y+ h300 w300 +grid  +0x100 +0x40 ,Name|Size|Path|
Gui,Show
Loop,3
   LV_ModifyCol(a_index,"AutoHdr")

Loop,50000
  {
    types=avi,mp3,txt,psd
   index:=a_index
    Loop,Parse,types,CSV
      {
       LV_Add("",index "." a_loopfield,"0 kb",a_workingdir "\temp\")
      }
  GuiControl,,text,Loading....%index%
   }
Loop,3
   LV_ModifyCol(a_index,"AutoHdr")
   GuiControl,,text,Done! with %index% rows
return


Maybe using a listview in the first place to display this many results is a bad idea, but it looked good because it's "the" control to use when displaying files. If anyone has a better solution I'm all ears Razz
Back to top
UncleScrooge



Joined: 14 Apr 2009
Posts: 75
Location: Italy

PostPosted: Sat Dec 12, 2009 1:43 pm    Post subject: Reply with quote

maybe not faster but neater imo
Code:
Gui,Font,Bold
Gui, Add, Text,x0 y5 w200 h20 vtext,
Gui,Font,
Gui, Add, ListView, % "x0 y+ h". (A_ScreenHeight // 2) . " w" (A_ScreenWidth // 1.5) "+grid +0x100 +0x40", Name|Extension|Size (KB)|Full Path
Gui, Add, Button, % "xp yp+" . (A_ScreenHeight // 2) . " gChangeRoot", Change Root
Gui,Show, AutoSize
LV_ModifyCol(1, (A_ScreenWidth // 1.5) // 5)
LV_ModifyCol(2, (A_ScreenWidth // 1.5) // 14)
LV_ModifyCol(3, (A_ScreenWidth // 1.5) // 14)
FilesPattern := ".mpg,.mp3,.wav"         ; you name it...
BeginFrom := "c:\"                                ; you choose where to begin
BuildLV()
Return

ChangeRoot:
   FileSelectFolder, BeginFrom, % "*" . BeginFrom
   If ErrorLevel
      Return
   BeginFrom .= "\"
   LV_Delete()
   BuildLV()
Return
GuiClose:
ExitApp

BuildLV()
{
   global
   Loop Parse, FilesPattern, `,
   {
      If (A_LoopField = "")
        Continue
      Loop % BeginFrom . "*" . A_LoopField, 0, 1
      {
        LV_Add("",A_LoopFileName, A_LoopFileExt, A_LoopFileSizeKB, A_LoopFileLongPath)
        GuiControl,,text, % "Loading.... " . LV_GetCount()
      }
   }
   GuiControl,,text, % "Done! with " . LV_GetCount() . " rows."
   Return
}

no counters, but let the Loop scan for wanted files.
The above example actually scans the whole C: HDD, you might want to narrow that range...
EDIT: I've added a Button by means of which you can select the range of your media files search. Needless to say: change the FilesPattern variable contents to scan other type of files (or you could add another control to let the user (yourself...?) make the choice.
_________________
Intel Centrino @ 2.8GHz
4 GB RAM
WIN XP SP3


Last edited by UncleScrooge on Sat Dec 12, 2009 5:07 pm; edited 2 times in total
Back to top
View user's profile Send private message AIM Address
hd0202



Joined: 13 Aug 2006
Posts: 265
Location: Germany

PostPosted: Sat Dec 12, 2009 4:16 pm    Post subject: Re: Faster way to add rows to a Listview or an alternative? Reply with quote

Add
Code:
GuiControl, -Redraw, ListView
before your loop and
Code:
GuiControl, +Redraw, ListView
after your loop

Hubert
Back to top
View user's profile Send private message
UncleScrooge



Joined: 14 Apr 2009
Posts: 75
Location: Italy

PostPosted: Sat Dec 12, 2009 4:59 pm    Post subject: Re: Faster way to add rows to a Listview or an alternative? Reply with quote

hd0202 wrote:
Add
Code:
GuiControl, -Redraw, ListView
before your loop and
Code:
GuiControl, +Redraw, ListView
after your loop

Hubert

not quite so...
moreover you loose the "feeling" of the filling up List view: staring at a blank ListView for 64 secs is worth looking at the partial filling already done (where you can scroll, select, etc.) for 67 secs, that is 3 secs over a minute (5% improvement in performace)?
Code:
---------------------------
temptest.ahk
---------------------------
66875 mSecs. With +/- Redraw option OFF Over 23428 red Items.
---------------------------
OK   
---------------------------

---------------------------
temptest.ahk
---------------------------
64265 mSecs. With +/- Redraw option ON Over 23428 red Items.
---------------------------
OK   

test it yourself (you should include a substantial number of file though, add some more extensions in the"FilesPattern" variable...):
Code:
ChkBoxString := "+/- Listview Redraw option is "
Gui,Font,Bold
Gui, Add, Text,x0 y5 w200 h20 vtext,
Gui,Font,
Gui, Add, ListView, % "x0 y+ h". (A_ScreenHeight // 2) . " w" (A_ScreenWidth // 1.5) "+grid +0x100 +0x40 vMyListView", Name|Extension|Size (KB)|Full Path
Gui, Add, Button, % "xp yp+" . (A_ScreenHeight // 2) . " gChangeRoot", Change Root
Gui, add, Checkbox, xp+200 yp vMyCheckBox gMyCheckBox, %ChkBoxString%ON
Gui,Show, AutoSize
LV_ModifyCol(1, (A_ScreenWidth // 1.5) // 5)
LV_ModifyCol(2, (A_ScreenWidth // 1.5) // 14)
LV_ModifyCol(3, (A_ScreenWidth // 1.5) // 14)
FilesPattern := ".mpg,.mp3,.wav"         ; you name it...
BeginFrom := "c:\"                                ; you choose where to begin
BuildLV()
Return

ChangeRoot:
   FileSelectFolder, BeginFrom, % "*" . BeginFrom
   If ErrorLevel
      Return
   BeginFrom .= "\"
   LV_Delete()
   BuildLV()
Return
GuiClose:
ExitApp

BuildLV()
{
   global
   start := A_TickCount
   If MyCheckBox
      GuiControl, -Redraw, MyListView
   Loop Parse, FilesPattern, `,
   {
      If (A_LoopField = "")
         Continue
      Loop % BeginFrom . "*" . A_LoopField, 0, 1
      {
        LV_Add("",A_LoopFileName, A_LoopFileExt, A_LoopFileSizeKB, A_LoopFileLongPath)
        GuiControl,,text, % "Loading.... " . LV_GetCount()
      }
   }
   If MyCheckBox
      GuiControl, +Redraw, MyListView
   GuiControl,,text, % "Done! with " . LV_GetCount() . " rows."
   MyCheckBox ? msg := " mSecs. With +/- Redraw option ON" : msg := " mSecs. With +/- Redraw option OFF"
   MsgBox % A_TickCount - start . msg . " Over " . LV_GetCount() . " red Items."
   Return
}
MyCheckBox:
    Gui, Submit, NoHide
    GuiControl,, MyCheckBox, % MyCheckBox ? ChkBoxString . "ON" : ChkBoxString . "OFF"
    Return

_________________
Intel Centrino @ 2.8GHz
4 GB RAM
WIN XP SP3
Back to top
View user's profile Send private message AIM Address
Toony Tom
Guest





PostPosted: Sun Dec 13, 2009 2:20 am    Post subject: Reply with quote

That's a good point actually UncleScrooge. Don't want to bore the user by making him stare at a blank control Laughing I remembered RaGrid today and began playing with it.

Loading the RaGrid control up with 50,000 rows took:
33,828ms or about 34 seconds!!!!

by contrast loading the listview control took:
411,563ms or about 7 minutes!!!!

RaGrid:
http://www.autohotkey.com/forum/topic19253.html

Here's the modified example code I used for RaGrid:
Code:
#SingleInstance, force
  start := A_TickCount
   w := 1000, h := 500, header := 30

   Gui, +LastFound +Resize
   hwnd := WinExist()

   Gui, Add, Button,x0      gOnBtn, Insert
   Gui, Add, Button,x+0 yp   gOnBtn, Delete
   Gui, Add, Button,x+0 yp   gOnBtn, Move Up
   Gui, Add, Button,x+0 yp   gOnBtn, Move Down

   Gui, Add, Button,x+20 yp gOnBtn, Colorize Row
   Gui, Add, Button,x+0 yp   gOnBtn, Set Colors
   Gui, Add, Button,x+20 yp gOnBtn, Read Cell
   Gui, Add, Button,x+5 yp gOnBtn, Convert Cell
   Gui, Add, Button,x+5 yp gOnBtn, Sort Column

   Gui, Add, Button,x+40 yp gOnBtn, Reload
   Gui, Add, StatusBar, ,Loading data
   Gui, Show, h%h% w%w%

   hIL := ImageList_Create(16, 16, 0x21, 255, 10)
   Loop 255 
      ImageList_AddIcon(hIL, LoadIcon("shell32.dll", A_Index, 16))
   
   hGrd := RG_Add(hwnd, 0, header, w, h-header-30, "GRIDFRAME VGRIDLINES NOSEL", "OnRa" ), Attach(hGrd, "w h")
   ;RG_SetFont(hGrd, "s8, Courier New")
   RG_SetHdrHeight(hGrd, 20), RG_SetRowHeight(hGrd, 26)   

   loop, 1
   {
      RG_AddColumn(hGrd, "txt=EditText",  "w=100", "hdral=1",   "txtal=1", "type=EditText")
      RG_AddColumn(hGrd, "txt=EditLong",  "w=100", "hdral=1", "txtal=1", "type=EditLong", "format=# ### ####")
      RG_AddColumn(hGrd, "txt=Combo",      "w=90",  "hdral=1", "txtal=1", "type=ComboBox", "items=combo 1|combo 2|combo 3|combo 4|combo 5|combo 6|combo 7|combo 8|combo 9|combo 10|combo 11|combo 12")
      RG_AddColumn(hGrd, "txt=Check",      "w=70",  "hdral=1", "txtal=1", "type=CheckBox")
      RG_AddColumn(hGrd, "txt=Button",   "w=100", "hdral=1", "txtal=1", "type=Button")
      RG_AddColumn(hGrd, "txt=EButton",   "w=100", "hdral=1", "txtal=1", "type=EditButton")
      RG_AddColumn(hGrd, "txt=Image",      "w=100", "hdral=1", "txtal=1", "type=Image", "il=" hIL)
      RG_AddColumn(hGrd, "txt=Hotkey",   "w=100", "hdral=1", "txtal=1", "type=Hotkey")
      RG_AddColumn(hGrd, "txt=Date",      "w=100", "hdral=1", "txtal=1", "type=Date", "format=yy'-'MM'-'dd")
      RG_AddColumn(hGrd, "txt=Time",      "w=100", "hdral=1", "txtal=1", "type=Time", "format=HH':'mm")
      RG_AddColumn(hGrd, "txt=User",      "w=100", "hdral=1", "txtal=1", "type=User", "data=1234")
   }

   loop, 50000
      RG_AddRow(hGrd, 0, "Text" A_Index ,A_Index, mod(A_Index, 12), mod(A_Index, 2), "btn" A_Index, "",mod(A_Index, 255))
      ;, RG_AddRow(hGrd, 0 " " 10, "Text" A_Index ,A_Index, mod(A_Index, 12), mod(A_Index, 2), "btn" A_Index, "", mod(A_Index, 255))

   SB_SetText("Loading finished`n`nRows " RG_GetRowCount(hGrd) " Cols " RG_GetColCount(hGrd))
   MsgBox % A_TickCount - start "ms for 50,000 items"
return



OnBtn:
   if A_GuiControl = Insert
      RG_AddRow(hGrd, RG_GetCurrentRow(hGrd))

#Include RaGrid.ahk
#include inc\Attach.ahk
#include inc\Il.ahk


Now, I just hope I can learn to use RaGrid correctly Razz
Back to top
entropic



Joined: 21 Dec 2008
Posts: 181

PostPosted: Sun Dec 13, 2009 3:16 am    Post subject: Reply with quote

This loads a listview with 50k rows in about 1.5 seconds on my machine and 500,000 rows in 14 seconds.
Code:

SetBatchLines, -1
Gui, Font, Bold
Gui, Add , Text    ,x0  y5 h020 w200 vtext,
Gui, Font,
Gui, Add , ListView, x0 y+ h300 w300 +grid +0x100 +0x40 vMyListView Count50000 ,Name|Size|Path|
GuiControl, -Redraw, MyListView
Gui, Show

Loop,3
   LV_ModifyCol(a_index,"AutoHdr")

StartTime := A_TickCount

Loop, 50000
{
  LV_Add("", A_Index,"0 kb",a_workingdir "\temp\")
}   

GuiControl, +Redraw, MyListView
Loop,3
   LV_ModifyCol(a_index,"AutoHdr")
 
Msgbox, % "Total Time: " A_TickCount - StartTime . "ms"

SetBatchLines, 10ms
return


Edit:

Everything by Void Tools is so quick because it builds the file list from the Master File Table, for changes it uses the USN Journal. I think it probably also loads the ListView as you scroll rather than loading everything at once, as you scroll you can see it loading the icons.


Last edited by entropic on Sun Dec 13, 2009 3:39 am; edited 2 times in total
Back to top
View user's profile Send private message
Toony Tom
Guest





PostPosted: Sun Dec 13, 2009 3:23 am    Post subject: Reply with quote

Shocked It loads in 17 seconds for me. I'm curious what kind of setup you have. I'm running windows xp pro SP3 (32 bit) on an AMD quad core 2.4ghz with 4gb of ram.
Back to top
entropic



Joined: 21 Dec 2008
Posts: 181

PostPosted: Sun Dec 13, 2009 3:32 am    Post subject: Reply with quote

I'm on a dual core Pentium 4 3.0ghz with 3gb ram, WinXp Sp3 (32bit). I'm not sure why mine is faster.
Back to top
View user's profile Send private message
Toony Tom
Guest





PostPosted: Sun Dec 13, 2009 7:14 am    Post subject: Reply with quote

Laughing Well now, I do believe I figured out part of the problem. I had a lot of applications running, mainly my browser with it's many cpu gobbling tabs and ram hogging pages. I killed everything and found that loading 50 thousand rows took 2 seconds compared with 17 from before. Also 500 thousand rows took 22 seconds compared with 3 to 4 minutes with your code before. Rolling Eyes Live and learn and viva la listview!
Back to top
MakeMyPCBetter



Joined: 19 Dec 2008
Posts: 27

PostPosted: Wed Jan 27, 2010 9:54 pm    Post subject: Speed up Load times in List View Reply with quote

This Sped my process up alot
I used to use a Parsing loop.

Code:
Loop, read, %Data_Base_File_Name%
{
   DataBase_Record_Count = %A_Index%
   
   ;Add Feilds into List View
   StringSplit, Record_Array, A_LoopReadLine, `,
   LV_Add("",Record_Array1,Record_Array2,Record_Array3,Record_Array4)
}
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group