PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » Графический вывод содержимого папки


Графический вывод содержимого папки

Сообщений 1 страница 20 из 20

1

Скачать - архив готовой программы

Есть известная утилита Scanner

мои попытки

Код:
EnableExplicit

Declare FileSearch(sPath.s, Mask$ = "*", depth=130)

Global path$


If OpenWindow(0, 0, 0, 500, 550, "Круг", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
	
	StringGadget(2 , 5 , 5 , 410 , 30 , GetUserDirectory(#PB_Directory_Downloads))
	ButtonGadget (1, 415, 5, 90, 20, "рис")
	CanvasGadget(0, 0, 50, 500, 500)
	
	
	
	Repeat
    Select WaitWindowEvent()
    	Case #PB_Event_Gadget
        Select EventGadget()
        	Case 1
            path$ = GetGadgetText(2)
            If FileSize(path$) = -2
            	FileSearch(path$, "*", 0)
            EndIf
        EndSelect
    	Case #PB_Event_CloseWindow
        CloseWindow(0)
        End
    EndSelect
	ForEver
EndIf

Procedure FileSearch(sPath.s, Mask$ = "*", depth=130)
	Protected SizeTotal, grad.d, StrtF.d, endF.d
	Protected NewList Files.s()
	Protected NewList SizeF.q()
	
	Protected sName.s, c = 0
	Protected Dim aExaDir(depth)
	Protected Dim aSePath.s(depth)
	
	If  Right(sPath, 1) <> #PS$
    sPath + #PS$
	EndIf
	
	aSePath(c) = sPath
	aExaDir(c) = ExamineDirectory(#PB_Any, sPath, Mask$)
	If Not aExaDir(c)
    ProcedureReturn
	EndIf
	
	Repeat
    While NextDirectoryEntry(aExaDir(c))
    	sName=DirectoryEntryName(aExaDir(c))
    	If sName = "." Or sName = ".."
        Continue
    	EndIf
    	If DirectoryEntryType(aExaDir(c)) = #PB_DirectoryEntry_Directory
        If c >= depth
        	Continue
        EndIf
        sPath = aSePath(c)
        c + 1
        aSePath(c) = sPath + sName + #PS$
        aExaDir(c) = ExamineDirectory(#PB_Any, aSePath(c), Mask$)
        If Not aExaDir(c)
        	c - 1
        EndIf
    	Else
        If AddElement(Files())
        	Files() = aSePath(c) + sName
        	If AddElement(SizeF())
            SizeF() = FileSize(Files())
        	EndIf
        EndIf
    	EndIf
    Wend
    FinishDirectory(aExaDir(c))
    c - 1
	Until c < 0
	
	; 	Debug "Depth = " + Str(depth)
	; 	Debug "Count = " + Str(ListSize(Files()))
	SizeTotal = 0
	ForEach SizeF()
    SizeTotal + SizeF()
	Next
	grad = SizeTotal/360
	; 	Debug SizeTotal
	; 	Debug grad
	
	If StartVectorDrawing(CanvasVectorOutput(0))
    
    endF = 0
    ForEach SizeF()
    	StrtF = endF
    	endF + SizeF()/grad
    	MovePathCursor(250, 250)
    	AddPathCircle(250, 250, 245, StrtF, endF, #PB_Path_Connected)
    	;     	ClosePath()
    	VectorSourceColor(RGBA(Random(99, 50), Random(99, 50), Random(99, 50), 255))
    	FillPath()
    	
    	VectorSourceColor(RGBA(255, 255, 255, 255))
    	MovePathCursor(190 * Cos(Radian((StrtF+endF)/2))+250, 190 * Sin(Radian((StrtF+endF)/2))+250)
    	DrawVectorText(Str(SizeF()/1024))
    Next
    
    StopVectorDrawing()
	EndIf
	
	ClearList(Files())
EndProcedure

Отредактировано AZJIO (03.05.2021 14:38:51)

0

2

If  Right(sPath, 1) <> #PS$
это что за зверь?

0

3

Версия 5.70 LTS
- Добавлено: константы #PS, #NPS, #PS$ и #NPS$ (Символ разделителя пути в зависимости от ОС)

0

4

Не информативно и примитивно.
http://s01.geekpic.net/di-7FMSOA.png
Программа Sequoia,  2002 года, выводит каждый файлик своим размером прямоугольника, и так любой диск или папку + название каждого файла при наведении мыши. Может каждый тип файла своим цветом.
Как она это делает, в смысле так точно распределяет прямоугольники в зависимости от папок и их размеров мне не ведомо и это реально круто!

0

5

ВиниПур
Я пользовался разными, в том числе и этой (эту пробовал не понравилось), в Linux есть baobab, filelight, в Krusader есть функционал "Сервис->Статистика использования диска". Для Windows есть ещё платная. Я уже ранее пробовал на AutoIt3, поэтому это в каком то смысле быстрая переделка. Но я пытался понять алгоритм. Как я понимаю нижний уровень рисуется поверх, так как рисование сектора подразумевает линии радиуса к центру, иначе надо делать типа маску обрезания, возможно надо делать в отдельной области а потом копировать поверх. И самое интересное практически во всех программах эти нарисованные секторы являются интерактивными. Как вариант могу предположить, что для каждого элемента свой цвет хоть на единицу да отличается, и некая функция при нахождении курсора над канвасом возвращает цвет пиксела в виде числа, который связан с элементом-файлов/папкой и меняется подсказка.
Опять же чтобы над сектором папки нарисовать файлы надо создавать базу данных аналогичный файловой системе, где папки задаются некоторым узлом в виде числа, тогда ему можно приписать размер содержимого папки и рисовать папку некоторым сектором, а внутри этого угла вычислять размеры вложенных. С виду кажется ничего сложного, а вот как это сделать алгоритмически голова сломается.

0

6

AZJIO написал(а):

Опять же чтобы над сектором папки нарисовать файлы надо создавать базу данных аналогичный файловой системе, где папки задаются некоторым узлом в виде числа, тогда ему можно приписать размер содержимого папки

Нужно просканировать диск и найти все папки и файлы и сохранить их размер.

Код:
Structure Files
  Name.s ; Имя файла
  Size.q ; Размер файла
EndStructure

Structure Tree
  DirName.s            ; Имя папки.
  DirSize.q
  List Files.Files()   ; Список файлов текущей папки.
  List Dirs.Tree()     ; Список вложенных папок текущей папки.
EndStructure


Procedure.q ScanDir(*s.Tree, AllDir.s) ; Сохранение структуры указаной папки
  Protected Size.q=0
  
  If *s=0
    ProcedureReturn 0
  EndIf
  
  id = ExamineDirectory(#PB_Any, AllDir, "*.*")
  If id
    
    While NextDirectoryEntry(id)
      
      If DirectoryEntryType(id) = #PB_DirectoryEntry_Directory ; Папка
        
        Dir.s = DirectoryEntryName(id)
        If Dir<>"." And Dir<>".."
          
          If AddElement(*s\Dirs())
            *s\Dirs()\DirName = Dir
            Size + ScanDir(*s\Dirs(), AllDir+Dir+#PS$) ; Рекурсивный вызов процедуры
          EndIf
          
        EndIf
          
      Else ; Файл
        
        If AddElement(*s\Files())
          *s\Files()\Name = DirectoryEntryName(id)
          *s\Files()\Size = DirectoryEntrySize(id)
          Size + *s\Files()\Size
        EndIf
        
      EndIf
      
    Wend
    
    *s\DirSize = Size
    FinishDirectory(id)
  EndIf
  
  ProcedureReturn Size
EndProcedure


Procedure View(*s.Tree, Pos) ; Отображение содержимого папки.
  
  AddGadgetItem(0, -1, *s\DirName+"  ("+*s\DirSize+") байт", 0, Pos)
  
  Pos+1
  
  ForEach *s\Dirs() ; Отображение всех подпапок текущей папки.
    View(*s\Dirs(), Pos) ; Рекурсивный вызов процедуры
  Next
  
  ForEach *s\Files() ; Отображение списка файлов текущей папки.
    AddGadgetItem(0, -1, *s\Files()\Name+"  ("+*s\Files()\Size+") байт", 0, Pos)
  Next
EndProcedure


s.Tree ; Создание экземпляра структуры.

s\DirName = PathRequester("Папка для сканирования", "")
If s\DirName
  OpenWindow(0, 0, 0, 400, 400, "", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  TreeGadget(0, 0, 0, 400, 400)
  ScanDir(s, s\DirName)
  View(s, 0)
  Repeat
     Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf

+1

7

Пётр
Интересный код в плане изучения, прям гениально. Теоретически строить графику в процессе поиска не получится, так как надо считать размеры папок после сложения размеров файлов, но хотя можно строить верхние ряды файлов, а потом внутренние слои папок. А если уже просчитано дерево, то конечно можно с корня строить. Интересно попытаться сделать аналогичный код без рекурсии.

0

8

AZJIO написал(а):

Интересно попытаться сделать аналогичный код без рекурсии.

Код будет более запутанным.

0

9

Пётр

скачать готовое

Хочу после строки "*s\DirSize = Size" вставить сортировку списка структур

Код:
SortStructuredList(*s\Dirs(), #PB_Sort_Descending, OffsetOf(Tree\DirSize) , TypeOf(Tree\DirSize))
SortStructuredList(*s\Files(), #PB_Sort_Descending, OffsetOf(Files\Size) , TypeOf(Files\Size))

ну и потом файлов, если получится, но пока не работает. Вроде получилось.

Есть старая утилита "Folder Size 3.2"
https://b.radikal.ru/b11/2104/75/cd53ab70d034.jpg

она практически аналог этому коду, надо только добавить сортировку, указать размер перед именем (ну по крайней мере я так настраивал)

Код:
AddGadgetItem(0, -1, "("+*s\DirSize+")" + #TAB$ + *s\DirName, 0, Pos)
...
AddGadgetItem(0, -1, "("+*s\Files()\Size+")" + #TAB$ + *s\Files()\Name, 0, Pos)

и добавить иконку папки. Добавить принятие параметров ком-строки, т.е. путь и готовая программа, в которую можно отправлять папку и она выведет вот такую удобную статистику, сам пользовался часто, типа не визуальный аналог но достаточной удобный.

Кстати, в телефоне для андроид есть прога "Карта SD", где файлы и папки представлены в виде квадратов, по крайней мере это красиво и удобно.

Отредактировано AZJIO (04.04.2021 14:31:38)

0

10

Есть ещё подобная для Винды
https://www.jam-software.com/sites/default/files/treesize_free/online_manual/EN/TreeSizeFree-Treemap-Chart-3D.png

0

11

В общем всю голову сломал уже.

XIncludeFile "FileList.pb" - сюда переместил 2 структуры и функцию ScanDir
добавил If level > 10 чтобы смотреть прорисовку уровней от 0
для теста надо  брать папку с небольшой структурой файлов и папок, так как с большой ничего не происходит
ClipPath() - функция вызывается, но не дойдя до прорисовки файлов вызывается рекурсия и новый ClipPath(), отсюда сомнения может ли предыдущий вызов или их комбинация создавать проблему. Функциями AddPathEllipse() рисую 2 круга, чтобы рисовать внутри кольца образованного 2-мя кругами.
уровень 1 должен нарисовать 1 полное кольцо, но вместо этого 2 сектора

Код:
EnableExplicit

XIncludeFile "FileList.pb"

Global SizeTotal.q
Global grad.d
Global center = 250

; Global path$

Procedure View(*s.Tree, Radius, Strt0.d, level) ; Отображение содержимого папки.
	Protected StrtF.d, endF.d, PosT
	If level > 10 ; проверяем прорисовку по уровням
    ProcedureReturn
	EndIf
; 	Static end0.d
	PosT = Radius-10
	
	
	AddPathEllipse(center, center, Radius-20, Radius-20)
	AddPathEllipse(center, center, 250, 250)
	ClipPath() ; отсекающий вектор
	
	StrtF = Strt0
	endF = Strt0
	endF + *s\DirSize/grad
	MovePathCursor(center, center)
; 	Debug Radius
	AddPathCircle(center, center, Radius, StrtF, endF, #PB_Path_Connected)
	;     	ClosePath()
; 	VectorSourceColor(RGBA(Random(99, 50), Random(99, 50), Random(99, 50), 255))
	VectorSourceColor(RGBA(Random(66, 30), Random(66, 30), Random(66, 30), 255))
	FillPath()
    	
	VectorSourceColor(RGBA(255, 255, 255, 255))
	MovePathCursor(PosT * Cos(Radian((StrtF+endF)/2))+center, PosT * Sin(Radian((StrtF+endF)/2))+center)
	DrawVectorText(Str(*s\DirSize/1024))
; 	end0 = endF
	
	
; 	AddGadgetItem(#TreeFileFolder, -1, "("+*s\DirSize+")" + #TAB$ + *s\DirName, ImageID(#FOLDER))

	Radius + 20
	ForEach *s\Dirs() ; Отображение всех подпапок текущей папки.
    View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
;     Strt0 + View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
	Next
	Radius - 20
	
	
; 	Debug Radius
	ForEach *s\Files() ; Отображение списка файлов текущей папки.
	
    StrtF = endF
    endF + *s\Files()\Size/grad
    MovePathCursor(center, center)
    AddPathCircle(center, center, Radius, StrtF, endF, #PB_Path_Connected)
    ;     	ClosePath()
;     VectorSourceColor(RGBA(Random(99, 50), Random(99, 50), Random(99, 50), 255))
    VectorSourceColor(RGBA(Random(155, 122), Random(155, 122), Random(155, 122), 255))
    FillPath()
    	
    VectorSourceColor(RGBA(255, 255, 255, 255))
    MovePathCursor(PosT * Cos(Radian((StrtF+endF)/2))+center, PosT * Sin(Radian((StrtF+endF)/2))+center)
    DrawVectorText(Str(*s\Files()\Size/1024))
	Next
	
; 	ProcedureReturn *s\DirSize

EndProcedure





Define s.Tree ; Создание экземпляра структуры.
Define Param$, tmp$, Pos

Param$ = ProgramParameter()
If FileSize(Param$) = -2
	If Right(Param$, 1) <> #PS$
    Param$ + #PS$
	EndIf
	s\DirName = Param$
Else
	s\DirName = PathRequester("Папка для сканирования", "")
EndIf




If s\DirName

	If OpenWindow(0, 0, 0, 500, 550, "Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
    
    StringGadget(2 , 5 , 5 , 410 , 30 , GetUserDirectory(#PB_Directory_Downloads))
    ButtonGadget (1, 415, 5, 90, 20, "pic")
    CanvasGadget(0, 0, 50, 500, 500)
    
    ScanDir(s, s\DirName)
    SizeTotal = s\DirSize
    grad = SizeTotal/360
    
    If StartVectorDrawing(CanvasVectorOutput(0))
    	View(s, 30, 0, 0)
    	
    	StopVectorDrawing()
    EndIf
    	
    
    Repeat
    	Select WaitWindowEvent()
        Case #PB_Event_Gadget
        	Select EventGadget()
            Case 1
;             	s\DirName = GetGadgetText(2)
;             	If FileSize(s\DirName) = -2
;                 ScanDir(s, s\DirName)
;             	EndIf
        	EndSelect
        Case #PB_Event_CloseWindow
        	CloseWindow(0)
        	End
    	EndSelect
    ForEver
	EndIf
	
EndIf

ГОТОВЫЙ
ещё вариант для теста. Уже рабочий. Если сделать один вызов рисования как в предыдущем примере (вся функция View внутри StartVectorDrawing), то не прорисовываются некоторые папки.

Код:
EnableExplicit


; Global SizeTotal.q
Global grad.d
Global center = 250
Global widthSec = 15
Global c, n, w, h

Structure Files
	Name.s ; Имя файла
	Size.q ; Размер файла
EndStructure

Structure Tree
	DirName.s            ; Имя папки.
	DirSize.q
	List Files.Files()   ; Список файлов текущей папки.
	List Dirs.Tree()	 ; Список вложенных папок текущей папки.
EndStructure


Procedure.q ScanDir(*s.Tree, AllDir.s) ; Сохранение структуры указаной папки
	Protected Size.q=0, id, Dir.s
	
	If *s=0
    ProcedureReturn 0
	EndIf
	
	id = ExamineDirectory(#PB_Any, AllDir, "*.*")
	If id
    
    While NextDirectoryEntry(id)
    	
    	If DirectoryEntryType(id) = #PB_DirectoryEntry_Directory ; Папка
        
        Dir = DirectoryEntryName(id)
        If Dir<>"." And Dir<>".."
        	
        	If AddElement(*s\Dirs())
            c+1
            If c > n
            	n = c
;             	Debug n
            EndIf
            *s\Dirs()\DirName = Dir
            Size + ScanDir(*s\Dirs(), AllDir+Dir+#PS$) ; Рекурсивный вызов процедуры
        	EndIf
        	c-1
        	
        EndIf
        
    	Else ; Файл
        
        If AddElement(*s\Files())
        	*s\Files()\Name = DirectoryEntryName(id)
        	*s\Files()\Size = DirectoryEntrySize(id)
        	Size + *s\Files()\Size
        EndIf
        
    	EndIf
    	
    Wend
    
    *s\DirSize = Size
    ;     тут сортировка
    SortStructuredList(*s\Dirs(), #PB_Sort_Descending, OffsetOf(Tree\DirSize) , TypeOf(Tree\DirSize))
    SortStructuredList(*s\Files(), #PB_Sort_Descending, OffsetOf(Files\Size) , TypeOf(Files\Size))
    FinishDirectory(id)
	EndIf
	
	ProcedureReturn Size
EndProcedure


; Global path$

Procedure.q View(*s.Tree, Radius, Strt0.d, level) ; Отображение содержимого папки.
	Protected StrtF.d, endF.d, PosT
	If level > 40 ; проверяем прорисовку по уровням
    ProcedureReturn
	EndIf
; 	Static end0.d
	PosT = Radius-10
	If StartVectorDrawing(CanvasVectorOutput(0))
	
; 	MessageRequester("",  *s\DirName)
	AddPathEllipse(center, center, Radius-widthSec, Radius-widthSec)
	AddPathEllipse(center, center, 250, 250)
	ClipPath() ; отсекающий вектор
	
	StrtF = Strt0
	endF = Strt0
	endF + *s\DirSize/grad
	If StrtF = endF
    StopVectorDrawing()
    ProcedureReturn 0
	EndIf
	MovePathCursor(center, center)
	; 	Debug Radius
; 	Debug *s\DirName
	AddPathCircle(center, center, Radius, StrtF, endF, #PB_Path_Connected)
	;     	ClosePath()
; 	VectorSourceColor(RGBA(Random(99, 50), Random(99, 50), Random(99, 50), 255))
	VectorSourceColor(RGBA(Random(99, 40), Random(99, 40), Random(99, 40), 255))
	FillPath()
    	
; 	VectorSourceColor(RGBA(255, 255, 255, 255))
; 	MovePathCursor(PosT * Cos(Radian((StrtF+endF)/2))+center, PosT * Sin(Radian((StrtF+endF)/2))+center)
; 	DrawVectorText(Str(*s\DirSize/1024))
; 	end0 = endF
	
	
; 	AddGadgetItem(#TreeFileFolder, -1, "("+*s\DirSize+")" + #TAB$ + *s\DirName, ImageID(#FOLDER))

	StopVectorDrawing()
	EndIf
	Radius + widthSec
	ForEach *s\Dirs() ; Отображение всех подпапок текущей папки.
;     SaveVectorState()
;     View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
    Strt0 + View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
;     RestoreVectorState()
	Next
; 	Radius - widthSec
	
	If StartVectorDrawing(CanvasVectorOutput(0))
	
	AddPathEllipse(center, center, Radius-widthSec, Radius-widthSec)
	AddPathEllipse(center, center, 250, 250)
	ClipPath() ; отсекающий вектор
	
	; 	Debug Radius
	endF = Strt0
	ForEach *s\Files() ; Отображение списка файлов текущей папки.
;     MessageRequester("",  *s\Files()\Name)
    StrtF = endF
    endF + *s\Files()\Size/grad
    If StrtF = endF
    	Continue
    EndIf
    MovePathCursor(center, center)
    AddPathCircle(center, center, Radius, StrtF, endF, #PB_Path_Connected)
    ;     	ClosePath()
;     VectorSourceColor(RGBA(Random(99, 50), Random(99, 50), Random(99, 50), 255))
    VectorSourceColor(RGBA(Random(155, 122), Random(155, 122), Random(155, 122), 255))
    FillPath()
    	
;     VectorSourceColor(RGBA(255, 255, 255, 255))
;     MovePathCursor(PosT * Cos(Radian((StrtF+endF)/2))+center, PosT * Sin(Radian((StrtF+endF)/2))+center)
;     DrawVectorText(Str(*s\Files()\Size/1024))
	Next
	StopVectorDrawing()
	EndIf
	
	ProcedureReturn *s\DirSize/grad

EndProcedure





Define s.Tree ; Создание экземпляра структуры.
Define Param$, tmp$, Pos

Param$ = ProgramParameter()
If FileSize(Param$) = -2
	If Right(Param$, 1) <> #PS$
    Param$ + #PS$
	EndIf
	s\DirName = Param$
Else
 	Param$ = PathRequester("Папка для сканирования", "")
; 	s\DirName = "/home/user/My_root/Install_arch/Find_GUI_AUR/pkg/test/"
	If Param$ And Right(Param$, 1) <> #PS$
    Param$ + #PS$
	EndIf
	s\DirName = Param$
EndIf


#Window_Main = 0

If s\DirName
;  | #PB_Window_ScreenCentered
	If OpenWindow(#Window_Main, 0, 0, 500, 550, "Circle", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
    
    StringGadget(2 , 5 , 5 , 410 , 30 , GetUserDirectory(#PB_Directory_Downloads))
    ButtonGadget (1, 415, 5, 90, 20, "pic")
    CanvasGadget(0, 0, 50, 500, 500)
    
    c=0
    n=0
    ScanDir(s, s\DirName)
    grad =  s\DirSize/360
    
    widthSec = 250/(n+1)
;     If widthSec>30
;     	widthSec=30
;     EndIf
;     Debug widthSec
;     If StartVectorDrawing(CanvasVectorOutput(0))
    	View(s, widthSec, 0, 0)
    	
;     	StopVectorDrawing()
;     EndIf
;     MessageRequester("",  "готово")
    	
    
    Repeat
    	Select WaitWindowEvent()
;         Case #PB_Event_SizeWindow
;         	w = WindowWidth(#Window_Main)
;         	h = WindowHeight(#Window_Main) - 50
;         	ResizeGadget(0, #PB_Ignore, #PB_Ignore, w, h)
;         	If StartVectorDrawing(CanvasVectorOutput(0))
;             ScaleCoordinates(w/500.0, h/500.0)
;             StopVectorDrawing()
;         	EndIf
        Case #PB_Event_Gadget
        	Select EventGadget()
            Case 1
;             	s\DirName = GetGadgetText(2)
;             	If FileSize(s\DirName) = -2
;                 ScanDir(s, s\DirName)
;             	EndIf
        	EndSelect
        Case #PB_Event_CloseWindow
        	CloseWindow(#Window_Main)
        	End
    	EndSelect
    ForEver
	EndIf
	
EndIf

Отредактировано AZJIO (05.04.2021 15:15:08)

0

12

AZJIO написал(а):

ClipPath() - функция вызывается, но не дойдя до прорисовки файлов вызывается рекурсия и новый ClipPath()

Код:
  ForEach *s\Dirs() ; Отображение всех подпапок текущей папки.
    SaveVectorState()
    View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
    ;     Strt0 + View(*s\Dirs(), Radius, Strt0, level + 1) ; Рекурсивный вызов процедуры
    RestoreVectorState()
  Next

0

13

Пётр
я только что обновил, проблема закралась в ProcedureReturn *s\DirSize/grad, ранее было без /grad

Обновил (в моём предыдущем посте), проблема была если папка пуста или файл 0 байт, то нарисовать такой сектор вызывает ошибку. Сделал игнор.

Отредактировано AZJIO (05.04.2021 13:47:50)

0

14

Пётр
Имеет ли смысл в структуру добавить указатель родителя? Такой бы способ дал возможность получить полный путь к файлу/папке. Например построено дерево файловой структуры. Было бы удобно с помощью контекстного меню получить путь и соответственно иметь пункты "Удалить файл/папку", "Открыть файл/папку". В AutoIt3 есть возможность получить пункт родителя и путь от корня, поискал аналоги в PureBasic, не нашёл. Но можно было бы используя SetGadgetItemData привязать к пункту указатель на родителя и таким образом получить весь путь. У корневого был бы указатель 0, что означает прекратить получение родителя.

Уже сделал, ссылка в первом посте. Тестировал только в Windows. Обнаружил что номера пунктов дерева по мере добавления идёт отсчёт от нуля до количества добавленных не зависимо от уровня или родителя и можно было бы в качестве SetGadgetItemData использовать номера родителя, но тогда придётся каждый раз отрезать текст слева (размер файла/папки), поэтому использовал указатели структуры.

Отредактировано AZJIO (03.05.2021 14:43:38)

0

15

AZJIO написал(а):

Имеет ли смысл в структуру добавить указатель родителя?

Если нужно то почему бы и нет.

0

16

Пётр
Есть ещё идейка: сделать построение списка по мере раскрытия пунктов. Кликнул "+" алгоритм строит текущую ветвь. Думаю если строить всю файловую систему диска в просмотрщике сразу, то займёт много времени, тем более иногда раскрыто будет пару ветвей. Одну ветвь построить даже не будет заметно, если только это не System32.

0

17

http://www.uderzo.it/main_products/space_sniffer/

0

18

Думаю попробовать создать базу данных файлов. Реляционная (иеархическая) база данных с нормерами таблиц в виде ссылок, давно хотел попробовать. Ранее где-то видел что люди структуры сохраняли, было бы конечно проще создать типа дамп памяти, а потом его просто загрузить в память (но эта функция наверно доступна только для компа на котором создавался дамп). Идея интересна тем что можно было бы сохранить дерево какого нибудь диска/флешки в базу данных, а потом поискать в них файл не подключая диск/флешку к компу, а просмотреть копию файловой системы. Даже прогу ранее использовал "CD Collection".

Набросал без теста со старых наработок:

Код:
Procedure SaveSQL(*s.Tree, Pos) ; сохранить баазу файлов.
	Protected Item, tmp$, kod$
	tmp$ = SaveFileRequester("Выберите имя файла", "Files.sqlite", "*.sqlite|*.sqlite", 0)
	If tmp$ And OpenDatabase(#Database, tmp$, "", "")
    ;     если не добавили таблицу то выпрыгиваем
    If Not DatabaseUpdate(#Database, "CREATE TABLE IF NOT EXISTS '" + Str(Pos) + "' (" + TypeID$ + " int, '" + SizeID$ + "' int, '" + NameID$ + "' Text, '" + DateID$ + "' Text);")
    	ProcedureReturn
    EndIf
    
    ; 	    добавляем текущую папку
    DatabaseUpdate(#Database, "INSERT INTO '" + Str(Pos) + "' (" + TypeID$ + "," + SizeID$ + "," + NameID$ + "," + DateID$ + ") values ('" + Pos + "','" + Str(*s\Files()\Size) + "','" + *s\Files()\Name + "','" + Str(*s\DirParent) + "');")
    
    Pos+1
    
    ForEach *s\Dirs() ; Отображение всех подпапок текущей папки.
    	View(*s\Dirs(), Pos) ; Рекурсивный вызов процедуры
    Next
    
    kod$ = "BEGIN TRANSACTION;"
    ForEach *s\Files() ; Отображение списка файлов текущей папки.
               ; Не нужно многократно вызывать  _SQLite_Exec для каждого импорта, достаточно все команды импорта объединить в один запрос, разделяя символом ";"
               ; Этот нативный способ является самым быстрым
    	kod$ + "INSERT INTO '" + Str(Pos) + "' (" + TypeID$ + "," + SizeID$ + "," + NameID$ + "," + DateID$ + ") values ('" + Pos + "','" + Str(*s\Files()\Size) + "','" + *s\Files()\Name + "','" + Str(*s\DirParent) + "');"
    Next
    kod$ + "COMMIT;"
    DatabaseUpdate(#Database, kod$)
	EndIf
EndProcedure

может надо SetDatabaseLong использовать?

Установил пакет "DB Browser for SQLite", проверил транзакции с "BEGIN TRANSACTION;", работает

Код:
EnableExplicit

UseSQLiteDatabase()

Define Filename$, sNameTable$, ID1$, ID2$, ID3$, kod$, i

; файл должен существовать (пустой)
Filename$ = "/home/user/files.sqlite"


; файл размер дата

#Database = 0
sNameTable$ = "table_name"
ID1$ = "файл"
ID2$ = "размер"
ID3$ = "дата"

If OpenDatabase(#Database, Filename$, "", "") ; если база данных успешно открыта, то
	If DatabaseUpdate(#Database, "CREATE TABLE IF NOT EXISTS '" + sNameTable$ + "' (" + ID1$ + " Text, '" + ID2$ + "' int, '" + ID3$ + "' Text);")
    Debug "Таблица создана"
	EndIf
	
	kod$ = "BEGIN TRANSACTION;"
	For i=0 To 200
    kod$ + "Insert into '" + sNameTable$ + "' (" + ID1$ + "," + ID2$ + "," + ID3$ + ") values ('" + Str(i) + "','" + Str(Random(10000)) + "','" + Str(Random(10000)) + "');"
	Next
	kod$ + "COMMIT;"
	DatabaseUpdate(#Database, kod$)
EndIf

; закрывается база автоматически при выходе
CloseDatabase(#Database)

Отредактировано AZJIO (15.05.2021 18:53:59)

0

19

Пётр
Есть ли возможность очистить структуры? Они создаются как бы структура структур. Надо в обратном порядке удалить очищая память, так как предполагается не разовый показ, а сканирование других каталогов. В справке есть варианты только удаление структур созданных с AllocateMemory или AllocateStructure, что говорит о том что память заранее известна в размере. При чём в примерах для AllocateMemory используется элементы строк, а в AllocateStructure есть список но тип - числа. То есть во втором случае размер структуры известен, так как список чисел имеет размер по числу элементов и размер типа числа. В первом случае память выделена видимо с учётом длинны строки, то есть автор выделяет память под известные размеры полей и под возможную длину строки, причём как я понимаю ClearStructure() очищает саму структуру (ссылки на поля и т.д.), а FreeMemory() освобождает место где располагалась структура (и строка структуры). Для AllocateStructure() используется FreeStructure() только потому что размер полей известен и это не строки, поэтому и удаляется одной функцией структура и освобождение места с возвратом винде. В примере выше создается структура ни одним из указанных способов.

Из этого как я понимаю выделяется память только под указатель строки, но не под саму строку.

Код:
AllocateMemory(SizeOf(Test)) 

значит ли это, что функция ClearStructure() будет очищать списки строк, а FreeMemory() только очищает указатели, то есть память выделенную под указатели на список?

Отредактировано AZJIO (05.05.2022 21:48:57)

0

20

AZJIO написал(а):

Есть ли возможность очистить структуры?

ResetStructure очищает структуру.
ClearStructure очищает структуру и деинициализирует ее содержимое (строки, массивы списки и т. д.). Чтобы в дальнейшем использовать нужно инициализировать вызовом InitializeStructure.
То есть очистить можно функцией ResetStructure или парой функций ClearStructure и InitializeStructure.

AZJIO написал(а):

При чём в примерах для AllocateMemory используется элементы строк

Наверняка в этих примерах есть инициализация структуры - вызов InitializeStructure?

AZJIO написал(а):

Для AllocateStructure() используется FreeStructure() только потому что размер полей известен и это не строки

AllocateStructure не только выделяет память но и инициализирует структуру. То есть подобно AllocateMemory и InitializeStructure.
FreeStructure освобождает всю память структуры включая динамическое содержимое. То есть эквивалентно ClearStructure и FreeMemory.

AZJIO написал(а):

Из этого как я понимаю выделяется память только под указатель строки, но не под саму строку.

Верно. AllocateMemory выделяет только память под структуру. Чтобы использовать динамическое содержимое нужно вызвать InitializeStructure.

AZJIO написал(а):

значит ли это, что функция ClearStructure() будет очищать списки строк, а FreeMemory() только очищает указатели, то есть память выделенную под указатели на список?

Да. ClearStructure деинициализирует динамическое содержимое освобождая память.

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Графический вывод содержимого папки