Page 1 of 2

How can I display text during file copying?

Posted: Wed May 02, 2018 6:13 am
by davido
I have a program that copies some files from one directory to another.
During the copying, I wish to display information about the file just copied.

I've posted some sample code, not the same as in my program, but is simpler and has exactly the same problem.
I find that the window blanks and no text is displayed until all the files have been copied!

I tried moving the copy process into another thread but then all the text is displayed before copying is started!

Can anybody say what I am doing wrong?

Code: Select all

;// Copyfiles.pb ?
EnableExplicit

  CompilerIf #PB_Compiler_Unicode
    #XmlEncoding = #PB_UTF8
  CompilerElse 
    #XmlEncoding = #PB_Ascii
  CompilerEndIf

  #Dialog = 0
  #Xml = 0
  Global XML1$, XML2$, Event.i
  
  Global SourcePath$, TargetPath$, NewList FileList$()

  
  
  Runtime Enumeration Windows
    #WinMain
    #win2
  EndEnumeration
  Runtime Enumeration Gadgets
    #copySourceButton
    #copySourcePath
    #copyTargetButton
    #copyTargetPath
    #copyList
    #copyGo
  EndEnumeration
  Runtime Enumeration Gadgets
    
  EndEnumeration
  
  Declare ProcessFiles()
  
  Procedure ProcessFiles()
    
 If ExamineDirectory(0, SourcePath$, "*.*")  
    While NextDirectoryEntry(0)
      If DirectoryEntryType(0) = #PB_DirectoryEntry_File
        AddElement(FileList$())
        FileList$() = DirectoryEntryName(0)
      EndIf
    Wend
    FinishDirectory(0)
  EndIf
  ClearGadgetItems(#copyList)
  ForEach FileList$()
    AddGadgetItem(#copyList,-1,FileList$())
  Next
  ForEach FileList$()
    CopyFile(SourcePath$ + FileList$(),TargetPath$ + FileList$())
    SetGadgetItemText(#copyList,ListIndex(FileList$()),"Copied!",1)
  Next
  EndProcedure
  
  Runtime Procedure EventButtons()
    Select EventGadget()
      Case #copySourceButton
        SourcePath$ = PathRequester("Source Directory","")
        SetGadgetText(#copySourcePath,SourcePath$)
        
      Case #copyTargetButton
        TargetPath$ = PathRequester("Target Directory","")
        SetGadgetText(#copyTargetPath,TargetPath$)
        
      Case #copyGo
        ProcessFiles()
        
    EndSelect
  EndProcedure
  
  Runtime Procedure SetUP()
    SetGadgetItemText(#copyList,-1,"Files to Copy")
    AddGadgetColumn(#copyList,1,"Result",60)
  EndProcedure
  
  XML1$ = "<dialogs>"+
          "  <window id='#WinMain' name='Template' text='Print' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered |"+
          "  #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
          "   <vbox>"+
          "     <hbox>"+
          "       <button id='#copySourceButton' height='60' text='Source' onevent='EventButtons()' />"+
          "       <text id='#copySourcePath' width='350' />"+
          "     </hbox>"+
          "     <hbox>"+
          "       <button id='#copyTargetButton' height='60' text='Target' onevent='EventButtons()' />"+
          "       <text id='#copyTargetPath' width='350' />"+
          "     </hbox>"+
          "    <listicon id='#copyList' width='450' height='200' flags='#PB_ListIcon_GridLines' />"+
          "    <button id='#copyGo' text='Go' onevent='EventButtons()' />"+
          "   </vbox>"+
         "  </window>"+
         "</dialogs>"
  
  If CatchXML(#Xml, @XML1$, StringByteLength(XML1$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
    
    If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "Template")
      SetUp()
      Repeat
        Event = WaitWindowEvent()
      Until Event = #PB_Event_CloseWindow 
      
    Else  
      Debug "Dialog error: " + DialogError(#Dialog)
    EndIf
  Else
    Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
  EndIf

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 7:38 am
by infratec
Try this:

Code: Select all

;// Copyfiles.pb ?
EnableExplicit

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

#Dialog = 0
#Xml = 0
Global XML1$, XML2$, Event.i


Structure ThreadParameterStructure
  Thread.i
  Semaphore.i
  Exit.i
EndStructure


Global SourcePath$, TargetPath$, NewList FileList$(), ThreadParameter.ThreadParameterStructure




Runtime Enumeration Windows
  #WinMain
  #win2
EndEnumeration
Runtime Enumeration Gadgets
  #copySourceButton
  #copySourcePath
  #copyTargetButton
  #copyTargetPath
  #copyList
  #copyGo
EndEnumeration
Runtime Enumeration Gadgets
  
EndEnumeration


Enumeration #PB_EventType_FirstCustomValue
  #Event_ShowFileToCopy
  #Event_ShowFileCopied
EndEnumeration



Procedure ProcessFiles(*Parameter.ThreadParameterStructure)
  
  Protected Help$
  
  ClearGadgetItems(#copyList)
  
  If ExamineDirectory(0, SourcePath$, "*.*") 
    While NextDirectoryEntry(0)
      If DirectoryEntryType(0) = #PB_DirectoryEntry_File
        AddElement(FileList$())
        Help$ = DirectoryEntryName(0)
        FileList$() = Help$
        PostEvent(#Event_ShowFileToCopy, #WinMain, 0, 0, @Help$)
        WaitSemaphore(*Parameter\Semaphore)
      EndIf
    Wend
    FinishDirectory(0)
  EndIf
  
  ForEach FileList$()
    CopyFile(SourcePath$ + FileList$(),TargetPath$ + FileList$())
    PostEvent(#Event_ShowFileCopied, #WinMain, 0, 0, ListIndex(FileList$()))
    ;SetGadgetItemText(#copyList,ListIndex(FileList$()),"Copied!",1)
    WaitSemaphore(*Parameter\Semaphore)
    If *Parameter\Exit
      Break
    EndIf
  Next
EndProcedure


Runtime Procedure EventButtons()
  Select EventGadget()
    Case #copySourceButton
      SourcePath$ = PathRequester("Source Directory","")
      SetGadgetText(#copySourcePath,SourcePath$)
      
    Case #copyTargetButton
      TargetPath$ = PathRequester("Target Directory","")
      SetGadgetText(#copyTargetPath,TargetPath$)
      
    Case #copyGo
      ThreadParameter\Exit = #False
      ThreadParameter\Thread = CreateThread(@ProcessFiles(), @ThreadParameter)
      
  EndSelect
EndProcedure

Runtime Procedure SetUP()
  SetGadgetItemText(#copyList,-1,"Files to Copy")
  AddGadgetColumn(#copyList,1,"Result",60)
EndProcedure




ThreadParameter\Semaphore = CreateSemaphore()

XML1$ = "<dialogs>"+
        "  <window id='#WinMain' name='Template' text='Print' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered |"+
        "  #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
        "   <vbox>"+
        "     <hbox>"+
        "       <button id='#copySourceButton' height='60' text='Source' onevent='EventButtons()' />"+
        "       <text id='#copySourcePath' width='350' />"+
        "     </hbox>"+
        "     <hbox>"+
        "       <button id='#copyTargetButton' height='60' text='Target' onevent='EventButtons()' />"+
        "       <text id='#copyTargetPath' width='350' />"+
        "     </hbox>"+
        "    <listicon id='#copyList' width='450' height='200' flags='#PB_ListIcon_GridLines' />"+
        "    <button id='#copyGo' text='Go' onevent='EventButtons()' />"+
        "   </vbox>"+
        "  </window>"+
        "</dialogs>"

If CatchXML(#Xml, @XML1$, StringByteLength(XML1$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
  
  If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "Template")
    SetUp()
    Repeat
      Event = WaitWindowEvent()
      
      Select Event
        Case #Event_ShowFileToCopy
          AddGadgetItem(#copyList, -1, PeekS(EventData()))
          SignalSemaphore(ThreadParameter\Semaphore)
          
        Case #Event_ShowFileCopied
          SetGadgetItemText(#copyList, EventData(), "Copied!", 1)
          SignalSemaphore(ThreadParameter\Semaphore)
          
      EndSelect
      
    Until Event = #PB_Event_CloseWindow
    
  Else 
    Debug "Dialog error: " + DialogError(#Dialog)
  EndIf
Else
  Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
Bernd

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 7:41 am
by Marc56us
PB auto-refresh gadgets only when WindowEvent() occurs.

A tips was to add a single loop such as

Code: Select all

While WindowEvent() : Wend
in

Code: Select all

    ForEach FileList$()
        CopyFile(SourcePath$ + FileList$(),TargetPath$ + FileList$())
        SetGadgetItemText(#copyList,ListIndex(FileList$()),"Copied!",1)
        While WindowEvent() : Wend ; <--- This auto-refresh gadgets
    Next
But this does not work with Bindxxx event (and XMD dialog use it)

:|

The solution proposed by Infratec (see post above) works fine :wink:

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 7:44 am
by infratec
@Marc56us

A very bad tip.
Never, really never, use a second event loop.
You will lost events. (Like closing the window)

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 7:52 am
by Marc56us
Yeah, maybe, but I'm not sure.
I've used it for years and never had a problem before.
(and it was, it seems to me, someone important who had indicated this tip)
This loop will leave at the first iteration, so for example a timer event (1/1000s) or a mouse movement.
So much faster than what a user or hard drive can do.

But I'm willing to believe. Do you have an example that would demonstrate the possible crash for this type of unique loop?

Code: Select all

While WindowEvent() : Wend
:?:

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 7:59 am
by infratec
Doesn't matter if it works for you since years...

If an event occurs in this time it is lost. (you can not debate about this :wink: )
Depending on the event it is more or less critical.

If your code is more complex, where different threads generates events, than you will come definately to a point where you notice that something is not working as expected.
And then it is very difficult to find out why, because everything looks fine with your code.
No one thinks that an event is lost.

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 8:03 am
by infratec
Or in Yodas words
There is only one of them.
No more, no less.
And you are allways on the save side.
:mrgreen:

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 8:06 am
by Marc56us
Yes, I agree with you. I use this tip only for small simple programs and to go faster.
So far, almost none of my programs exceed 15000 lines and very few use threads, so I haven't had a problem yet.

:?: :idea: But it's true that I have one that has weird reactions sometimes, so I'll double-check if I hadn't put this Tip on.

Thanks
:wink:

Re: How can I display text during file copying?

Posted: Wed May 02, 2018 8:45 am
by Dude
Maybe my code here is of interest to you:

http://www.purebasic.fr/english/viewtop ... 76#p491376

Works great for large files. :)

Re: How can I display text during file copying?

Posted: Thu May 03, 2018 6:59 am
by Lord
Hi infratec!
infratec wrote:Doesn't matter if it works for you since years...
...
Does it matter if even Fred suggests it?
http://www.purebasic.fr/english/viewtop ... 01&start=3

Re: How can I display text during file copying?

Posted: Thu May 03, 2018 7:36 am
by walbus
I use a similar function inside QUICK_AES_256.
It works very fine, you can try.
Move as sample a lot files or folders in the text editor.

Without WindowEvent() you won't get any output.
The behavior is also not exactly the same between the three OS.
Within your copy loop, the second WindowEvent() does not disturb.
The problem with multiple WindowEvent() is that one takes something away from the other.
However, processing must always take place sequentially, first one, then the other.
The easier it is structured, the better it works.

Re: How can I display text during file copying?

Posted: Thu May 03, 2018 9:55 am
by davido
Thanks to you all for taking the trouble to help me. :D

@infratec: Usually when I am shown how to do something I think how simple it looks!
But, not in this case as I had tried copying in a thread and failed miserably. I don't think I could have done this by myself.
I really like your solution because you've made it so simple for me to add to my code. It also works on my Mac, too.

@Dude: I like this one, too, as it displays a graphic 'thermometer' similar to the display on my Mac.
It would be nice if there was a way to add the function on the Mac.

@walbus: Thanks for the tip: I'll take a look.

Re: How can I display text during file copying?

Posted: Thu May 03, 2018 10:26 am
by walbus
Hi Davido
yep, primary it is simple, but for a perfect working it is not simple

For batch file copy i make this so :

I read firstly only the paths in a list
This works very fast, also with your routine, but you can not add with your routine WindowEvent
Or you must change your code for making the complete output with one step !

Then i display the paths and files, this also is very fast,
and you can use for this step WindowEvent
But you must not, its simple a eye catcher for many different outputs

I display a progressbar,
all files and states in a editor gadget and display at the same time the file amount and a counter on a text gadget
(I have count the files bevore with the first step) :wink:

The third step is the bare file copy on a separately loop
I copy the files blockwise, do it at the same !
Make this block copy not threaded
So i have little blocks, can add simple a progressbar and WinEvent, how ever i want
This is the Way, so you get a very smooth output, without any flickering and it look absolutely cool

Unfortunatelly i can not separate this code for you from QAES
The code is combined with complicated hash creating and encryption routines

But i can say you, so it works perfectly, on all OS :wink:

Re: How can I display text during file copying?

Posted: Thu May 03, 2018 4:00 pm
by infratec
Lord wrote:Hi infratec!
infratec wrote:Doesn't matter if it works for you since years...
...
Does it matter if even Fred suggests it?
http://www.purebasic.fr/english/viewtop ... 01&start=3
Hi, hi,

this was a decade ago.
Ask him today about this.

Re: How can I display text during file copying?

Posted: Fri May 04, 2018 7:00 am
by Lord
infratec wrote:
Lord wrote:Hi infratec!
infratec wrote:Doesn't matter if it works for you since years...
...
Does it matter if even Fred suggests it?
http://www.purebasic.fr/english/viewtop ... 01&start=3
Hi, hi,

this was a decade ago.
Ask him today about this.
Hi Fred! What is your suggestion at this topic today (or tomorrow)?