[OK]CopyDirectory et progressBar
Publié : dim. 22/août/2010 11:44
y'a t il une façon simple de gérer la progression d'une copie de dossier avec un ProgressBarGadget() lorsqu'on utilise CopyDirectory() ?
Forums PureBasic - Français
http://forums.purebasic.com/french/
Code : Tout sélectionner
;- Procédure de calcul de la taille d'un dossier
Procedure.q GetDirectorySizeMo(path$, pattern$="")
Protected dir=ExamineDirectory(#PB_Any, path$, pattern$), size.q
If dir
While NextDirectoryEntry(dir)
If DirectoryEntryType(dir) = #PB_DirectoryEntry_File
size+DirectoryEntrySize(dir)
Continue
ElseIf Not DirectoryEntryName(dir) = "." And Not DirectoryEntryName(dir) = ".."
size+GetDirectorySizeMo(path$+DirectoryEntryName(dir)+"\", pattern$)
Continue
EndIf
Wend
FinishDirectory(dir)
EndIf
ProcedureReturn size
EndProcedure
;- Nom de dossier, pratique pour limiter l'affichage au nom uniquement
Structure Characters
c.c[0]
EndStructure
Procedure.s GetDirectoryPart(FileName.s)
Protected Directory.s, i.l
Protected *Directory.Characters
Directory = GetPathPart(FileName)
If Directory
i = Len(Directory) - 2
*Directory = @Directory
While i >= 0 And *Directory\c[i] <> '/' And *Directory\c[i] <> '\'
i - 1
Wend
i + 2
Directory = Mid(Directory, i, Len(Directory) - i)
EndIf
ProcedureReturn Directory
EndProcedure
;- Exemple:
Dossier$ = "C:\Users\username\Documents\MonDossier" ;<<< changer le chemin
;TailleFichier$ = StrF((GetDirectorySizeMo(Dossier$+"\", "*.*")/1024)/1024,3)+" Mo"
; pour utiliser le nb d'octets en valeur max de ta progressbar, décommenter ci-dessous et commenter ci-dessus
TailleFichier$ = Str((GetDirectorySizeMo(Dossier$+"\", "*.*")))+" Octets"
MessageRequester("Taille de "+GetDirectoryPart(Dossier$+ "\"),"La taille exacte de ce répertoire est de : "+Chr(10)+""+Chr(10)+TailleFichier$,#MB_ICONINFORMATION)
Code : Tout sélectionner
Enumeration
#WindowCopy
#Text_selectdir
#Btn_selectdir
#Str_selectdir
#Text_selectdest
#Btn_selectdest
#Str_selectdest
#Text_2
#Text_3
#ContainerInfos
#Text_4
#Progression
#Btn_copy
#Btn_close
EndEnumeration
Global valmax.l = 100
Global ThreadCopy,ThreadControl
;-Procédure de comptage de tous les éléments d'un répertoire, sous répertoires compris.
Global nbfiles.l, nbdir.l
Procedure.l CountDirectoryItems(Dir, dossier.s)
If Right(dossier, 1) <> "\" : dossier + "\" : EndIf
If ExamineDirectory(Dir, dossier, "*.*")
While NextDirectoryEntry(Dir)
If DirectoryEntryType(Dir) = #PB_DirectoryEntry_File
nbfiles = nbfiles + 1
name.s = DirectoryEntryName(Dir)
ElseIf DirectoryEntryType(Dir) = #PB_DirectoryEntry_Directory
name.s = DirectoryEntryName(Dir)
If name <> "." And name <> ".."
nbdir = nbdir + 1
CountDirectoryItems(Dir + 1, dossier + name)
EndIf
EndIf
Wend
FinishDirectory(Dir)
EndIf
ProcedureReturn nbfiles + nbdir ; addition des fichiers et des dossiers
;(permet d'afficher le compte séparé des fichiers et dossiers suivant préférences)
EndProcedure
;- Procédure de calcul de la taille d'un dossier
Procedure.q GetDirectorySizeMo(path$, pattern$="")
Protected dir=ExamineDirectory(#PB_Any, path$, pattern$), size.q
If dir
While NextDirectoryEntry(dir)
If DirectoryEntryType(dir) = #PB_DirectoryEntry_File
size+DirectoryEntrySize(dir)
Continue
ElseIf Not DirectoryEntryName(dir) = "." And Not DirectoryEntryName(dir) = ".."
size+GetDirectorySizeMo(path$+DirectoryEntryName(dir)+"\", pattern$)
Continue
EndIf
Wend
FinishDirectory(dir)
EndIf
ProcedureReturn size
EndProcedure
;- Nom de dossier
Structure Characters
c.c[0]
EndStructure
Procedure.s GetDirectoryPart(FileName.s)
Protected Directory.s, i.l
Protected *Directory.Characters
Directory = GetPathPart(FileName)
If Directory
i = Len(Directory) - 2
*Directory = @Directory
While i >= 0 And *Directory\c[i] <> '/' And *Directory\c[i] <> '\'
i - 1
Wend
i + 2
Directory = Mid(Directory, i, Len(Directory) - i)
EndIf
ProcedureReturn Directory
EndProcedure
Procedure ControleCopy(*Verif.l)
;Pour contrôler on compare la taille des 2 dossiers
SetGadgetText(#Text_4,"Contrôle du résultat de la copie... Patientez SVP")
Dossier1$ = GetGadgetText(#Str_selectdir)
Dossier2$ = GetGadgetText(#Str_selectdest) + GetDirectoryPart(Dossier1$)+ "\"
SizeDos1 = GetDirectorySizeMo(Dossier1$, "*.*") : SetGadgetText(#Text_2,"Taille dossier : "+StrF(SizeDos1/1024/1024,3)+" Mo")
SizeDos2 = GetDirectorySizeMo(Dossier2$, "*.*") : SetGadgetText(#Text_3,"Taille dossier : "+StrF(SizeDos2/1024/1024,3)+" Mo")
If SizeDos2 = SizeDos1 ; S'il y a correspondance, c'est bon.
KillTimer_(WindowID(#WindowCopy),2)
SetGadgetState(#Progression,0)
MessageRequester("Contrôle","La copie de [ "+GetDirectoryPart(GetGadgetText(#Str_selectdir))+" ] s'est terminée sans erreur.",#MB_ICONINFORMATION)
SetGadgetText(#Text_2,"")
SetGadgetText(#Text_3,"")
SetGadgetText(#Text_4,"")
SetGadgetText(#Str_selectdir,"")
SetGadgetText(#Str_selectdest,"")
DisableWindow(#WindowCopy,0)
Else
KillTimer_(WindowID(#WindowCopy),2)
SetGadgetState(#Progression,0)
MessageRequester("Contrôle","La copie de [ "+GetDirectoryPart(GetGadgetText(#Str_selectdir))+" ] semble avoir rencontrée des erreurs. Vérifiez votre copie.",#MB_ICONEXCLAMATION)
SetGadgetText(#Text_4,"VEUILLEZ VERIFIER VOTRE COPIE DE DOSSIER!")
SetGadgetText(#Text_2,"")
SetGadgetText(#Text_3,"")
SetGadgetText(#Str_selectdir,"")
SetGadgetText(#Str_selectdest,"")
DisableWindow(#WindowCopy,0)
EndIf
EndProcedure
Procedure ControlProgress()
If IsThread(ThreadControl) <> 0
SetGadgetState(#Progression,GetGadgetState(#Progression)+1)
If GetGadgetState(#Progression) = 100
SetGadgetState(#Progression,1)
EndIf
EndIf
EndProcedure
Procedure Progression()
;On simule le remplissage...
If IsThread(ThreadCopy) <> 0
SetGadgetState(#Progression,GetGadgetState(#Progression)+1)
If GetGadgetState(#Progression) = 100
SetGadgetState(#Progression,1)
EndIf
Else
;Jusqu'à la fin de la tache
SetGadgetState(#Progression,100)
SetGadgetText(#Text_4,"La copie du dossier est terminée.")
KillTimer_(WindowID(#WindowCopy),1)
MessageRequester("Copie","La copie de "+GetDirectoryPart(GetGadgetText(#Str_selectdir))+" est terminée.",#MB_ICONINFORMATION)
;Reset des gadgets
SetGadgetState(#Progression,0)
SetGadgetText(#Text_4,"")
SetGadgetText(#Text_2,"")
SetGadgetText(#Text_3,"")
DisableGadget(#Btn_copy,0)
DisableGadget(#Btn_selectdir,0)
DisableGadget(#Btn_selectdest,0)
;On offre le choix de vérifier ou non
Resultat = MessageRequester("Vérification","Voulez-vous effectuer une vérification de la copie?",#PB_MessageRequester_YesNo)
If Resultat = 6 ;Oui, on lance le thread de contrôle
DisableWindow(#WindowCopy,1)
SetGadgetText(#Text_4,"")
ThreadControl = CreateThread(@ControleCopy(),0)
SetTimer_(WindowID(#WindowCopy),2,250,@ControlProgress())
ElseIf Resultat = 7 ;Non...
EndIf
EndIf
EndProcedure
Procedure ThreadCopyDir(*param.l)
Dossier1$ = GetGadgetText(#Str_selectdir)
Dossier2$ = GetGadgetText(#Str_selectdest) + "\" +GetDirectoryPart(Dossier1$)
CopyDirectory(Dossier1$, Dossier2$+"\", "*.*", #PB_FileSystem_Recursive)
EndProcedure
If OpenWindow (#WindowCopy, #PB_Ignore, #PB_Ignore, 500, 350, "CopyDirectory with Progress", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;{
TextGadget(#Text_selectdir,10,10,250,15,"Sélectionnez le répertoire à copier")
ButtonGadget(#Btn_selectdir,430,10,50,20,"Select")
StringGadget(#Str_selectdir,10,35,480,20,"")
TextGadget(#Text_2,10,60,250,20,"")
SetGadgetColor(#Text_2,#PB_Gadget_FrontColor,RGB(29, 31, 226))
TextGadget(#Text_selectdest,10,100,250,15,"Sélectionnez l'emplacement où sera copié le dossier")
ButtonGadget(#Btn_selectdest,430,100,50,20,"Select")
StringGadget(#Str_selectdest,10,125,480,20,"")
TextGadget(#Text_3,10,150,250,20,"")
SetGadgetColor(#Text_3,#PB_Gadget_FrontColor,RGB(29, 31, 226))
ContainerGadget(#ContainerInfos,10,180,480,45,#PB_Container_Single)
TextGadget(#Text_4,5,7,470,30,"");Affichage des infos courantes / processus
SetGadgetColor(#Text_4,#PB_Gadget_FrontColor,RGB(29, 31, 226))
CloseGadgetList()
ProgressBarGadget(#Progression,10,230,480,20,0,valmax)
ButtonGadget(#Btn_copy,260,300,100,25,"Démarrer")
GadgetToolTip(#Btn_copy,"Démarrer la copie du répertoire")
ButtonGadget(#Btn_close,380,300,100,25,"Quitter")
GadgetToolTip(#Btn_close,"Annuler et fermer la fenêtre")
;}
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
Select EventGadget()
Case #Btn_selectdir ;{
If CheminInitial$ = ""
CheminInitial$ = "C:\"
EndIf
Chemin$ = PathRequester("Choisissez un dossier à copier", CheminInitial$)
If Chemin$
SetGadgetText(#Str_selectdir,Chemin$)
CheminInitial$ = Chemin$
SetGadgetText(#Text_2,Str(CountDirectoryItems(0, Chemin$)) + " Eléments à copier")
EndIf
;}
Case #Btn_selectdest ;{
If Destination$ = ""
Destination$ = "C:\"
EndIf
repdest$ = PathRequester("Choisissez une destination", Destination$)
If repdest$
SetGadgetText(#Str_selectdest,repdest$)
Destination$ = repdest$
EndIf
;}
Case #Btn_copy ;{
Dossier1$ = GetGadgetText(#Str_selectdir)
Dossier2$ = GetGadgetText(#Str_selectdest) + "\" +GetDirectoryPart(Dossier1$)
If Dossier1$ <> "" And GetGadgetText(#Str_selectdest) <> ""
SetTimer_(WindowID(#WindowCopy),1,250,@Progression()) ;ce timer va simuler le remplissage de la progressbar() à répétition jusqu'à la fin du Thread
SetGadgetText(#Text_4,"Copie du dossier en cours... Patientez durant le processus SVP")
ThreadCopy = CreateThread(@ThreadCopyDir(),1)
If IsThread(ThreadCopy) <> 0
DisableGadget(#Btn_copy,1); désactive les boutons et évite une erreur
DisableGadget(#Btn_selectdir,1)
DisableGadget(#Btn_selectdest,1)
Else
MessageRequester("Thread error!","Le thread n'a pu se lancer",#MB_ICONERROR)
SetGadgetText(#Text_4,"La copie a échouée!")
KillTimer_(WindowID(#WindowCopy),1)
DisableGadget(#Btn_copy,0)
DisableGadget(#Btn_selectdir,0)
DisableGadget(#Btn_selectdest,0)
EndIf
ElseIf Dossier1$ <> "" And GetGadgetText(#Str_selectdest) = ""
MessageRequester("Thread error!","Vous devez choisir un répertoire de destination!",#MB_ICONEXCLAMATION)
ElseIf Dossier1$ = "" And GetGadgetText(#Str_selectdest) <> ""
MessageRequester("Thread error!","Vous devez choisir un répertoire à copier!",#MB_ICONEXCLAMATION)
ElseIf Dossier1$ = "" And GetGadgetText(#Str_selectdest) = ""
MessageRequester("Thread error!","Vous devez choisir un répertoire à copier et sa destination!",#MB_ICONEXCLAMATION)
EndIf
;}
Case #Btn_close ; On vérifie si un process est en cours avant de fermer.
If IsThread(ThreadCopy) <> 0
Result = MessageRequester("Tâche en cours!","La copie est en cours, êtes vous sûr de vouloir annuler et quitter?",#PB_MessageRequester_YesNoCancel)
If Result = 6 ;Oui, on termine tout et on ferme
EventID = #PB_Event_CloseWindow
ElseIf Result = 7 ;Non, on continue...
Else ;Annuler
;La demande a été annulée, on continue...
EndIf
Else
EventID = #PB_Event_CloseWindow
EndIf
;Faire de même avec > Case #PB_Event_CloseWindow
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
;Par sécurité...
If IsThread(ThreadCopy) <> 0
KillThread(ThreadCopy)
KillTimer_(WindowID(#WindowCopy),1)
EndIf
If IsThread(ThreadControl) <> 0
KillThread(ThreadControl)
KillTimer_(WindowID(#WindowCopy),2)
EndIf
End
EndIf
Code : Tout sélectionner
; Ar-S / 2010 PB 4.50
; Récupération du dernier nom de dossier avec possibilité de lui faire précéder la date.
SOURCE$="c:\canoscan\" ; por l'exemple
DEST$="c:\"
rc.s=chr(10)
; Procédure de récupération du dernier nom de fichier
; j'ajoute "\" à la fin du nom pour les besoins de mon programme.
Procedure.s GetLastDirectory(DossierSource$)
DossierSource$=ReverseString(DossierSource$)
PosSlash=FindString(DossierSource$,"\",3)
DossierSource$=ReverseString(mid(DossierSource$,2,PosSlash-2))+"\"
ProcedureReturn DossierSource$
EndProcedure
GetLastDirectory(SOURCE$)
QuestionSav=MessageRequester("Résumé","Répertoire source : "+rc+SOURCE$+rc+rc+"Répertoire de destination : "+rc+DEST$+DernierRep$+rc+rc+"Souhaitez vous ajouter 'la date' en sous repertoire pour votre sauvegarde ?"+rc+"(nous vous conseillons d'utiliser cette option)"+rc+"Ce qui donnerait : "+rc+DEST$+FormatDate("%yyyy_%mm_%dd", Date())+"\"+DernierRep$,#PB_MessageRequester_YesNoCancel|#MB_ICONINFORMATION ) ;
If QuestionSav = 6 ; oui
DEST$+FormatDate("%yyyy-%mm-%dd", Date())+"\"+DernierRep$
elseif QuestionSav=7
DEST$+DernierRep$
else
GOCOPY=0
debug "annulé"
EndIf
Debug "Destination finale : "+DEST$