Jump to content
Sign in to follow this  
tarretarretarre

Questions about creating a file tree structure with TreeView

Recommended Posts

tarretarretarre

So I am trying to create a file tree structure Using _FileListToArrayRec with GuiCtrlCreateTreeView. But i have some problems with levels of directorys. In my mind there is nothing wrong with my logic, but obviously it is, since i dont get the output i want :P 

 

Here is a printscreen of the outcome, the array is sorted so it feels like it should be pretty easy, but its not :(

 

Here is the working code

#include <File.au3>
#include <Array.au3>
#include <GUITreeview.au3>
#include <WINapiSHELLEX.au3>

Local $hGI = GUICreate("test", 500,500)
Local $hTreeView = GUICtrlCreateTreeView(0,0,500,500)

GUISetState()

Local $arr = _GuictrlTreeview__FileListToArrayRec($hTreeView,"C:\Autoit\REMOVE", "*.au3||BackUp;.git*;___TrashCan")

_ArrayDisplay($arr)

Func _GuictrlTreeview__FileListToArrayRec($hTreeView, $sPath, $sFilter)
    if StringRight($sPath,1) == "\" Then $sPath = StringLeft($sPath, StringLen($sPath) - 1)
    if not FileExists($sPath) Then Return SetError(1,0,0)
    Local $aFileList = _FileListToArrayRec($sPath, $sFilter, $FLTAR_FILESFOLDERS, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH)
    if @error Then Return SetError(1,0,0)

    Local $aParents[1] = [0]

    Local $sLastParentDirectory = False
    Local $hLastParentTreeItem = False
    Local $hLastParentChildItem = False

    ; Set default icons (late rreplaced with file associated icon
    $hImageList = _GUIImageList_Create(16, 16, 5, 1)
    _GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)

    ; Begin tree update
    _GUICtrlTreeView_BeginUpdate($hTreeView)

    For $i = 1 To $aFileList[0]
        Local $sCurFullFilePath = $aFileList[$i]
        Local $sCurFileName = _Misc_GetFileName($aFileList[$i], False)

        ;Get da icon
        Local $hIcon = _WinAPI_ShellExtractAssociatedIcon($sCurFullFilePath, 1)
        Local $hIcon_Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)

        ;If directory
        If FileGetAttrib($sCurFullFilePath) == "D" Then

            ; Check if sub has file to add
            If StringLeft($sCurFullFilePath, StringLen($sLastParentDirectory)) == $sLastParentDirectory Then

                $hLastParentChildItem = _GUICtrlTreeView_AddChild($hTreeView, $hLastParentTreeItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
                ;Loop will end here
                ContinueLoop
            EndIf

            ;Create new parent folder & Update parents
            $sLastParentDirectory = $sCurFullFilePath
            $hLastParentTreeItem = _GUICtrlTreeView_Add($hTreeView, 0, StringFormat("%s", $sCurFileName), $hIcon_Index, $hIcon_Index)

        Else

            If Not $hLastParentChildItem Then
                ;ConsoleWrite($hLastParentTreeItem&" "&$sCurFileName&@CRLF)
                _GUICtrlTreeView_AddChild($hTreeView, $hLastParentTreeItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
            Else
                _GUICtrlTreeView_AddChild($hTreeView, $hLastParentChildItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
            EndIf

        EndIf


    Next

    ; End update
    _GUICtrlTreeView_EndUpdate($hTreeView)

    Return $aFileList

EndFunc



Func _Misc_GetFileName($sFilePath, $KeepExtension = True)
    ; Gets the filename
    Local $StringSPlit = StringSplit($sFilePath, "\")

    If Not $KeepExtension Then Return StringRegExpReplace($StringSPlit[$StringSPlit[0]], "\.(.*?)[a-zA-Z1234567890_-]{1,}+", "")
    Return $StringSPlit[$StringSPlit[0]]
EndFunc   ;==>_Misc_GetFileName

 

Any tips ?

 

Thanks in advance

Share this post


Link to post
Share on other sites
LarsJ
kylomas
44 minutes ago, LarsJ said:

tarretarretarre, Here here here is all what you need need need. Post 3.

Damn near dumped my coffee on the kb when i read this...thanks for the laugh of the day LarsJ...

Kylomas

By the way, thanks for the example code.  I have a "Hatfield and McCoy's" kind of relationship with treeview controls...

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
tarretarretarre

I solved it..... In the ghetto

 

I got what i was aiming for. I will share if anyone else wanna look@it.

 

Its really slow and uses 2 recurisve functions to: Sort files (windows style, folders first)

http://i.imgur.com/3N6lC5K.png 
 

#include <GuiTreeView.au3>
#include <WINapiSHELLEX.au3>
#include <array.au3>


$hGui = GUICreate("Demo1", 600, 400)
$hTreeView = _GUICtrlTreeView_Create($hGui, 10, 10, 580, 380)
GUISetState()

Local $test = _GuictrlTreeview__FileListToArrayRec($hTreeView, @ScriptDir, ".au3", "BackUp;.git")

_ArrayDisplay($test)


; Retrives a full array of directorys., here we use filters

Func _GuictrlTreeview__FileListToArrayRec($hTreeView, $sRoot, $sAcceptedFiles = ".", $sExcludedFolders = "")
    Local $aReturn[1];All files stored here in 1D array
    Local $AcceptedFiles = StringSplit($sAcceptedFiles, ";")
    Local $ExcludedFolders = StringSplit($sExcludedFolders, ";")
    $FileListToArray = _FileListToSortedArray($sRoot, $AcceptedFiles, $ExcludedFolders)

    ; Dummy icon control.
    Local $hImageList = _GUIImageList_Create(16, 16, 5, 1)
    _GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)

    _GUICtrlTreeView_BeginUpdate($hTreeView)
    _SortedArrayToTreeView($aReturn, $FileListToArray, 0, $hImageList)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    Return $aReturn
EndFunc   ;==>_GuictrlTreeview__FileListToArrayRec




Do
Until GUIGetMsg() = -3

Func _SortedArrayToTreeView(ByRef $aReturn, ByRef $sSourceFolder, $hItem, $hImageList)
    Local $sCurFileName = "unkown :P", $aFileList, $newItem, $hIcon, $aCurFileList, $hIcon_Index


    For $i = 2 To $sSourceFolder[0]; Last arg of array push lets us start from 2 instead so we can save 2 for stuff
        ; Current "file array"
        $aFileList = $sSourceFolder[$i]

        ; Get Type
        If IsArray($aFileList) Then
            $aCurFileList = $aFileList[1]
            _Array_Push($aReturn, $aCurFileList)
        Else
            $aCurFileList = $aFileList
            _Array_Push($aReturn, $aCurFileList)
        EndIf

        ; Get short name
        $sCurFileName = _________GetFileName($aCurFileList)

        ; Get icon of file
        $hIcon = _WinAPI_ShellExtractAssociatedIcon($aCurFileList, 1)
        $hIcon_Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
        _WinAPI_DestroyIcon($hIcon)


        ; Check if "Folder"
        If IsArray($aFileList) Then
            ;Ghetto get the folder name

            $newItem = _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
            _SortedArrayToTreeView($aReturn, $aFileList, $newItem, $hImageList)

        Else
            ;(THIS WILL IGNORE EMPTY DIRECTORYS) SEARCH FOR THIS
            If Not $sCurFileName Then

            Else; Regular file
                _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
            EndIf
        EndIf


    Next


EndFunc   ;==>_SortedArrayToTreeView


;// Fuck yeah...
Func _FileListToSortedArray($sSourceFolder, $AcceptedFiles, $ExcludedFolders)
    Local $newTree[1]

    Local $sFile, $sCurFullFilePath, $DeniedFolder, $DeniedFile

    ; Force a trailing \
    If StringRight($sSourceFolder, 1) <> "\" Then $sSourceFolder &= "\"

    ; Add basedir to array
    _Array_Push($newTree, $sSourceFolder)

    ; Start the search
    Local $hSearch = FileFindFirstFile($sSourceFolder & "*.*")
    ; If no files found then return
    If $hSearch = -1 Then Return ; This is where we break the recursive loop <<<<<<<<<<<<<<<<<<<<<<<<<<

    ; Now run through the contents of the folder
    While 1
        ; reset
        $DeniedFolder = False
        $DeniedFile = False
        ; Get next match
        $sFile = FileFindNextFile($hSearch)
        $sCurFullFilePath = $sSourceFolder & $sFile

        If @error Then ExitLoop ; This is where we break the recursive loop <<<<<<<<<<<<<<<<<<<<<<<<<<

        ; Check if a folder
        If @extended Then
            ; If so then call the function recursively

            ;Check if exluced folder
            For $i = 1 To $ExcludedFolders[0]
                If StringInStr($sFile, $ExcludedFolders[$i]) Then $DeniedFolder = True
            Next

            If $DeniedFolder Then ContinueLoop

            ;Fix empty dirs (THIS WILL IGNORE EMPTY DIRECTORYS) SEARCH FOR THIS
            Local $try = _FileListToSortedArray($sCurFullFilePath, $AcceptedFiles, $ExcludedFolders)
            If IsArray($try) Then
                _Array_Push($newTree, $try)
            EndIf

        Else
            ; If a file than write path and name
            For $i = 1 To $AcceptedFiles[0]
                If Not StringInStr($sFile, $AcceptedFiles[$i]) Then $DeniedFile = True
            Next
            If $DeniedFile Then ContinueLoop
            _Array_Push($newTree, $sCurFullFilePath)
        EndIf
    WEnd

    ;Sort this nigga
    _ArraySort($newTree, 0, 2)
    Return $newTree

EndFunc   ;==>_FileListToSortedArray

Func _Array_Push(ByRef $a, $v)
    If Not IsArray($a) Then
        ConsoleWrite("! _Array_Push used with non array" & @CRLF)
        Return False
    EndIf

    ReDim $a[$a[0] + 2]
    $a[$a[0] + 1] = $v
    $a[0] += 1
    Return $a[0]
EndFunc   ;==>_Array_Push


Func _________GetFileName($sFilePath)
    If Not StringInStr($sFilePath, "\") Then Return False; $sFilePath (THIS WILL IGNORE EMPTY DIRECTORYS) SEARCH FOR THIS
    Local $StringSplit = StringSplit($sFilePath, "\")
    If StringRegExp($StringSplit[$StringSplit[0]], "\.(.*?)[a-zA-Z1234567890_-]{1,}+") Then Return $StringSplit[$StringSplit[0]]
    Return $StringSplit[$StringSplit[0] - 1]
EndFunc   ;==>_Misc_GetFileName

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • Sven-Seyfert
      By Sven-Seyfert
       
      Hi Community,

      I have a problem with the usage of _GUICtrlTreeView_AddChild and setting different item text colors (and different background colors), separately for the TreeView levels.

      I use the UDF GUITreeViewEx.au3 of 'Melba23' and I renamed the functions to increase my understanding about the content. I already talked to him about his UDF to respect his rights and intellectual property. I read many forum threads, I tried many ways to get it, but it's seems to be impossible in the way that I use the UDF.

      Question:
      How can I set different item text colors, separately for the TreeView levels?
      How can I set different item background colors, separately for the TreeView levels?

      I found out that _GUICtrlTreeView_AddChild don't let my set this properties directly. But after loading the TreeView content I can't change the items (children) too. Only the font weight to bold I could set with _GUICtrlTreeView_SetBold but I want to do this in a generic way directly at the creation (loading) of the TreeView.

      Of course I tried the different functions to set text color or bkgColor, but it didn't work - maybe I do it wrong.
      I really hope you can help me, give me a hint and understand what I want to do.
      [Solved] final solution made by @LarsJ (see below)

      Thanks for your help - I'm grateful!
      Sven

      CODE
      BEFORE
      AFTER
      ExecutionPlan.zip
    • gillesg
      By gillesg
      Hello,
      I am struggling in merging GUITreeViewEx, Shelltristate and enhancing to handle a third state that means : some items under are selected.
      I have difficulties handling expand order and key Space (especially when node is collapsed).
      Here the zip with UDF and and example.
       
      The problem I might need some advice to handle : 
      1- When load Treeview, have a correct settings of the checkbox for a tristate tree
      2 - Handle keyboard used for walking in tree
           Chicken is checked and  Steak is unchecked
          When walking with arrow to Meat, it gets unchecked
      3 - When node is collapsed and checked thru keyboard (space)
         the middle state is possible which should not
      Here is joined an animated gif showing the 3 problems
       
      Thanks for your advices
       
       
       
       
       
       
       
       
       
       
       

      GUITreeview3Ex.zip
    • gillesg
      By gillesg
      Hello,
      I just bumped into this problem with _GUICtrlTreeView_Sort.
      Just used doc example and comment out the child creation
      #include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> Example() Func Example() Local $aidItem[10], $iX = 9, $iY = 29, $idTreeView Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS) GUICreate("TreeView Sort", 400, 300) $idTreeView = GUICtrlCreateTreeView(2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE) GUISetState(@SW_SHOW) _GUICtrlTreeView_BeginUpdate($idTreeView) For $x = 0 To 3 $aidItem[$x] = GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Item", $iX), $idTreeView) $iX -= 1 For $y = 1 To 3 ; GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Child", $iY), $aidItem[$x]) $iY -= 1 Next Next _GUICtrlTreeView_Expand($idTreeView) _GUICtrlTreeView_EndUpdate($idTreeView) MsgBox($MB_SYSTEMMODAL, "Information", "Sort") _GUICtrlTreeView_Sort($idTreeView) _GUICtrlTreeView_SelectItem($idTreeView, $aidItem[9]) ; Boucle jusqu'à ce que l'utilisateur quitte. Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>Example The tree is not sorted.
       
      There is a similar problem with deeper tree
      Also based on the example
      #include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> Example() Func Example() Local $aidItem[10], $bidItem[10], $iX = 9, $iY = 29, $idTreeView Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS) GUICreate("TreeView Sort", 400, 300) $idTreeView = GUICtrlCreateTreeView(2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE) GUISetState(@SW_SHOW) _GUICtrlTreeView_BeginUpdate($idTreeView) $index=0 For $x = 0 To 3 $aidItem[$x] = GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Item", $iX), $idTreeView) $iX -= 1 For $y = 1 To 2 $BidItem[$y]= GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Child", $iY), $aidItem[$x]) $iY -= 1 For $z= 1 To 2 GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Child", $iY), $BidItem[$y]) $iY -= 1 Next Next Next _GUICtrlTreeView_Expand($idTreeView) _GUICtrlTreeView_EndUpdate($idTreeView) MsgBox($MB_SYSTEMMODAL, "Information", "Sort") _GUICtrlTreeView_Sort($idTreeView) _GUICtrlTreeView_SelectItem($idTreeView, $aidItem[9]) ; Boucle jusqu'à ce que l'utilisateur quitte. Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>Example The tree is now 2 level deep and it is not properly sorted.
       
      Any advices ?
       
      Regards
    • corgano
      By corgano
      I can't explain easily what i want to do, so i made a picture:

      What i want to do is to specify a treeview item, and then be able to move it right to be a child of the previous item, or left to do the opposite (make a child into a sibling). I also want to move and child items of the target with it, like in the bottom half of the above image depicts. However I didn't see any functions in the help file to move items around. All i want is a button that when pressed, makes the selected item and any of selected item's children move one layer to the right / left. Does anyone know how?

      Edit: something along the lines of _GUICtrlTreeView_Level but SET level
    • Tjalve
      By Tjalve
      Hi everyone. Im creating a GUI for an application. Im usinga  treeview item and i want to add some information to the side of the treeview based on what cilditem you are pressing. For the moment i have a "get info" button that works. But that means that you have to select your child in the treeview, and then press a button to gte the info. I want the info to be visable as soon as you select it.
      With uther controls you can just add it to the loop but it doesnt seem to work with tyhe UDF version of the treeview control. Is there anything I can do?
      #include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> ;~ Create GUI dim $guilabel[7] local $currentlevel = 1 Local $hGui = GUICreate( "Grejs", 1000, 500, 600, 300, BitOR( $GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX ) ) Local $iBorderWidth = 4, $aPos = WinGetClientSize( $hGui ) $idTV = _GUICtrlTreeView_Create($hGui, $iBorderWidth, $iBorderWidth, $aPos[0]-2*$iBorderWidth-400, $aPos[1]-2*$iBorderWidth-30 ) $root_level = _GUICtrlTreeView_Add($idTV,0,"Root") $item1 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child1") $item2 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child2") $item3 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child3") ;~ Start Gui GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idTV MsgBox(0,"","") EndSwitch WEnd GUIDelete($hGui) Exit In this example, i want the msgbox to appear whenevr i select something in the treeview. It ios not my full code, but its an example of the problam i have. Help is much appritiated
      /G
×