I am using a Treeview class to display the directory structure of all mounted volumes on a Mac, to include all subfolders/files. However, I can only get as far and getting the first sub-level of the volume to display. I understand that I have to use recursion to get this done, but I just can’t figure this one out. Below is the code I have to get the first sub-level, but I have commented out my attempt to do the recursion to get the rest of the levels to show, because it doesn’t work. Any help would be greatly appreciated!
[code]dim mItemCount, thisItem as Integer
dim currentItem as FolderItem
dim child, grandchild As String
mItemCount = folder.count //counts the item in the folder
for thisItem = 1 to mItemCount
child = “C”+str(thisItem)
currentItem = folder.Item(thisItem) // get the next item in the folder
If currentItem.Visible Then
Listbox1.Add(parent, child, currentItem.Name, True ) // recursive call
else
'if currentItem.Directory Then
'For i As Integer = 1 To currentItem.Count
'grandchild = “GC”+str(i)
'add_recursive(Listbox1, grandchild, currentItem)
'next
'end if
end if
next[/code]
You need to have different methods for getting all files and displaying them in the listbox. And I love recursion, too.
Here is my method for getting all files in a folder (I don’t know why the name is for getting mails). The code is using the MBS plugin because this is way faster:
[code]Private Sub GetListOfMails(StartFolderitem as FolderItem)
if StartFolderitem = nil then return
dim theFileList as new FileListMBS(StartFolderitem)
dim FileCount as Integer = theFileList.Count - 1
for currentFile as Integer = 0 to FileCount
if theFileList.Visible(currentFile) then
if theFileList.Directory(currentFile) then
ListOfMails.Append theFileList.TrueItem(currentFile)
GetListOfMails theFileList.TrueItem(currentFile) '<--- recursion here
else
ListOfMails.Append theFileList.TrueItem(currentFile)
end if
end if
next
End Sub[/code]
I was asking just yesterday how to put this into a thread because this can take seconds for a large folder.
However: adding this to a Xojo listbox will be slow. Consider a different approach with getting and displaying only the data when a folder is opened. But try this as second step.
Beatrix: Sorry, but this is not working for me. I have a feeling that because I am trying to do this recursion using a Treeview class for the Hierarchical listbox, normal methods aren’t going to work. I don’t know what to do. I did not think that doing a Hierarchical Listbox for a Volume browser would be so difficult, yeeesh! I need to get some sleep and try to work on this more tomorrow.
Now, if someone expands the 2017Docs folder, you get the rowtag, and work through the Child records of THAT, using 2017Docs as the ‘base’ folder this time, instead of ‘work documents’
Adding folders and files to the 2017Docs row in the treeview
Arguably, if you want to do the whole lot, you can loop through the treeview rows
If any are not expanded, expand them.
and repeat until no unexpanded rows are found
while somethingexpanded
for x as integer = 0 to thetree.listcount-1
if <this row is not expanded>
//expand it
somethingexpanded = true
end if
next
wend
what was wrong with the code I gave you to work with a few days ago…
NOTE : IT HAS NOT BEEN TESTED… so it is for illustration purposes only
Public Sub LoadVolumes(tv as treeview)
Dim v As FolderItem
Dim i As Integer
Dim parent As String
Dim trunk As String
tv.AutoUpdate=False // delay tree update
//
// add the base of the tree (the trunk)
trunk="Volumes"
tv.Add("",trunk, "Devices")
//
// step thru each mounted volume
//
For i=0 To VolumeCount-1
v=Volume(i)
parent="V"+Str(i)
tv.Add(trunk,parent,v.Name,True)
add_recursive(tv,parent,v) //<-- add all the files of this volume
Next i
tv.AutoUpdate=True // now redraw the whole tree
End Sub
Private Sub add_recursive(tv as treeview,parent as string, folder as folderitem)
Dim g As Integer
Dim f As FolderItem
Dim child As String
For g = 1 To folder.Count
f=folder.TrueItem(g)
If f.Visible Then
child="C"+Str(g)
tv.Add(parent, child , f.Name, True) // This adds a new folder to the list
If f.Directory = True Then add_recursive(tv,child,f) // <- recursive call to add the children of this "Child" (ie. "grandchildren" of "parent")
End If
Next g
End Sub
a) Try to understand what the code I posted is trying to do.
b) If you use the MBS plugin have a look at the example “Disk Browser”. This does exactly what you want to do.
c) Instead of saying “the code doesn’t work” show us what you tried.
Jeff: The While somethingexpanded doesn’t work because the calls to the listbox work with a Treeview class, which doesn’t have the standard listbox calls.
Dave: I will pm you.
Beatrix: I have purchased a Treeview class that presents an amazing UI, which is what I need for the people I am creating this application for. I did show an example of the code that I tried at the beginning of the thread. I have tried multiple iterations of the commented out code without success.
For the record… the Treeview he refers to is one that I wrote… and the untested solution above was offered with the syntax of that treeview in mind.
And Roger… IF you are in fact trying to read the ENTIRE file contents of your system in one go, it will
a) take a LONG time
b) most likely fail due to memory constraints
neither are a flaw in TreeView… but rather the fact the data exceeds ability (by a number of magnitudes)
Dave’s Treeview control is pretty good, but you will fall foul of performance or memory issues
I question whether it makes sense fully recursing all the folders on all the volumes you find.
Just my trash folder currently holds 16000 items.
The memory isn’t really a problem. I’m testing at the moment with a folder that contains 200k files. Unfortunately, getting the folderitems is rather slow.
@Roger Martin: your code doesn’t contain even a hint of recursion or iteration. Even if you don’t use the MBS plugin the example shows how to do a file browser. I’m sure there are others around.
Wayne: we went through this process for a basic hierarchical listbox. I have moved on to using a special Treeview class and working on implementing that now.
Still wondering why the code I posted has not been considered… or if it has what seems to be “not right”, especailly since it was tailored for the exact treeview you are using.
Again… memory/performance are going to be a problem no matter what if you are trying to read the directory entry for every file in your system…
Dave: I tried the exact code you posted. I have even tried multiple iterations of the code. The problem seems to be that the recursion halts after going down one level and does not recurse all the directories, sub-directories on any mounted volume. If you pm me and provide me your email address, I will send you the test project I have been working on so you can see what is happening and maybe that will shed some light on this issue.
The code actually works… the problem it is attempting to recurse both Alias and Bundles
Alias is easy to reject, but I can’t find Cocoa code to id a Bundle (all I have is deprecated Carbon methods)
EDIT… the error Roger is experiencing is due to an anomoly in the Treeview code itself… an internal recursion is getting “lost”
EDIT #2 : TreeView anomoly located… new code will be sent to Roger later today