View in color | License | Download script | History | Other scripts by: luce80 |
30-Apr 11:01 UTC
[0.073] 31.098k
[0.073] 31.098k
archiver.rREBOL [
title: "Archiver"
file: %archiver.r
author: "Marco Antoniazzi"
Rights: "Copyright (C) 2016 Marco Antoniazzi. All Rights Reserved"
email: [luce80 AT libero DOT it]
date: 20-04-2016
version: 0.8.2
Purpose: "Backup files"
help: {
INSTRUCTIONS:
Fill the fields and press "Do".
A new temporary folder with a tree with all the specified folders and files will be created,
all the specified folders and files will be copied there and then that folder will be compressed
thus preserving all file structures. Finally the temporary folder will be deleted.
}
comment: "27-Mar-2016 GUI automatically generated by VID_build. Author: Marco Antoniazzi"
History: [
0.0.1 [27-03-2016 "Started"]
0.8.0 [28-03-2016 "Finished"]
0.8.1 [11-04-2016 "Added sorting, improved scroller, improved selecting, added now exit, fixed closing help-win"]
0.8.2 [20-04-2016 "fixed name of simple-vid-resizing.r"]
]
library: [
level: 'intermediate
platform: ['win 'linux]
type: 'tool
domain: 'files
tested-under: [View 2.7.8.3.1 Atronix-View 3.0.0.3.3]
support: none
license: 'BSD
see-also: none
]
thumbnail: http://i68.tinypic.com/2j3nzwp.png
]
;**** please set correct path to vid1r3.r3 and sdk sources (or use empty string to use default path to sdk) ****
if all [system/version > 2.9.0 not value? 'mimic-do-event] [do/args %../../r3/local/vid1r3.r3 %../../sdk-2706031/rebol-sdk-276/source]
err?: func [blk /local arg1 arg2 arg3 message err][;11-Feb-2007 Guest2
if not error? err: try blk [return :err]
err: disarm err
set [arg1 arg2 arg3] reduce [err/arg1 err/arg2 err/arg3]
message: get err/id
if block? message [bind message 'arg1]
alert rejoin ["ERROR: " form reduce message ". THE PROGRAM WILL TERMINATE."]
none
]
either debug:
false
;true
[
err?: :do
][
prin: print: func [val] [to-error form get/any 'val]
svv/error: func [msg spot] [to-error [msg]] ; patch VID error function to keep it silent
]
err? [
svv/vid-face/color: white - 30 ; background color of all windows and faces
; modules
load-script-thru: func ["Load a script from www.rebol.org thru the cache"
name [file!]
/flash "Flash a message to the user"
/warn "Alert user if script not found"
/from path [file!] "Optional path where to search for the script"
/local cache-name modul
][
if not value? 'view-root [view-root: either system/version/4 = 3 [%/C/Users/Public/Documents] [%/tmp]]
cache-name: view-root/:name
modul: any [
attempt [read cache-name] ; try the cache
attempt [read name] ; try current dir
attempt [read rejoin [undirize path "/" name]] ; try optional dir
attempt [ ; try downloading it from www.rebol.org
modul: rejoin [http://www.rebol.org/download-a-script.r?script-name= name]
read either flash [request-download/to modul cache-name cache-name][modul]
]
]
if modul [clear back back tail modul: load modul] ; remove example code
if all [not modul warn] [alert rejoin ["Script <" name "> not found."]]
modul
]
parent-dir: func [file [file!]] [
if equal? length? file 1 [return %/]
file: head remove back tail dirize file ; undirize
head clear find/tail/last file %/
]
on-linux?: system/version/4 = 4
if not value? 'file-req-ctx [; already loaded?
attempt [
do load-script-thru/flash %file-requester.r
if on-linux? [request-file: :request_file]
request-dir: :request_dir
]
]
if not value? 'resizer-ctx [; already loaded?
attempt [do load-script-thru/flash %simple-vid-resizing.r]
]
; misc
enquote: func [string [string!]] [rejoin [{"} string {"}]]
do-dir: func [
"For all files in a directory and subdirectories, recursively call a function or do a block as: func [file] block"
[catch]
dir [file! url!]
action [function! block!]
/deep count [integer!] "limit to the given level of depth"
/local files
][
count: any [count 1000000]
if count < 0 [exit]
if block? :action [action: func [file] action]
action dir
if all [
dir? dir
dir: dirize dir
attempt [files: load dir]
] [
foreach file files [do-dir/deep dir/:file :action count - 1]
]
]
build_tree: func [/local temp src dest files name info] [
make-dir temp: to-rebol-file trim get-face field-temp
view/new center-face/with info: center-face layout [text-info: text "" bold 800x50] main-window
files: text-list-files/data
forall files [
src: to-rebol-file first files
dest: parse next src "/"
; remove file part to avoid creating a wrong dir
if not dir? src [remove back tail dest]
name: copy ""
forall dest [
name: rejoin [name %/ first dest]
make-dir rejoin [temp %/ next name]
]
either dir? src [
; rebuild same tree structure as src
do-dir src [
set-face text-info reform ["Coping: " file]
name: rejoin [temp file]
either dir? file [
make-dir rejoin [temp file]
][
write/binary/direct name read/binary/direct file
]
]
][
name: rejoin [temp src]
set-face text-info reform ["Coping: " name]
write/binary/direct name read/binary/direct src
]
]
unview/only info
temp
]
; file, cfg, undo, exit
change_title: func [window /modified] [
clear find/tail window/text "- "
if modified [saved?: no append window/text "*"]
append window/text to-string last split-path any [job-name %Untitled]
window/changes: [text] show window
;set-win-title window/text
]
choose_file: func [ext [string!] /local file-name] [
until [
file-name: request-file/keep/only/filter ext
if none? file-name [return none]
exists? file-name
]
to-local-file file-name
]
open_file: func [/local file-name cfg ] [
if all [not none? job-name not request/confirm/offset "Replace current configuration?" main-window/offset + 100x100] [exit]
until [
file-name: request-file/title/keep/only/filter "Load a configuration file" "Load" "*.ren"
if none? file-name [exit]
exists? file-name
]
if none? cfg: attempt [load file-name] [exit]
if (select cfg 'info) <> "Archiver prefs file" [
alert "Wrong configuration file"
exit
]
load_cfg cfg
job-name: file-name
named: yes
change_title main-window
saved?: yes
]
save_file: func [/as /local file-name filt ext response cfg] [
attempt [change-dir first split-path job-name]
if not named [as: true]
if as [
filt: "*.ren"
ext: %.ren
file-name: request-file/title/keep/only/save/filter "Save a configuration file" "Save" filt
if none? file-name [return false]
if none? suffix? file-name [append file-name ext]
if not-equal? suffix? file-name ext [append file-name ext]
response: true
if exists? file-name [response: request/offset rejoin [{File "} last split-path file-name {" already exists, overwrite it?}] main-window/offset + 100x100]
if response <> true [return false]
job-name: file-name
named: yes
]
;flash/with join "Saving to: " job-name main-window
;probe
cfg: make_cfg
append cfg compose [
win-pos (main-window/offset)
win-size (main-window/size)
]
either not none? attempt [write job-name mold/only cfg] [
;wait 1.3
change_title main-window
saved?: yes
][
alert "Configuration NOT saved"
saved?: no
]
saved?
]
load_cfg: func [cfg [block!] /local files root-face][
replace/all cfg/general 'true true
replace/all cfg/general 'false false
foreach [style value] [
field-archive archive
field-archiver archiver
field-command command
field-temp temp
] [attempt [set-face get style select cfg/general value]]
update_archiver
saved?: yes
root-face: find-window main-window
root-face/offset: cfg/win-pos
root-face/size: cfg/win-size
show root-face
files: attempt [cfg/files]
if any [none? files empty? files] [exit]
clear text-list-files/data
text-list-files/data: files
append clear text-list-files/picked first text-list-files/data
show text-list-files/update
]
make_cfg: func [/local cfg] [
cfg: compose/deep [
; comment
info "Archiver prefs file"
version 0.0.1
general [
archive (get-face field-archive)
archiver (get-face field-archiver)
command (trim get-face field-command)
temp (trim get-face field-temp)
]
files [
]
]
new-line/all text-list-files/data
cfg/files: text-list-files/data
cfg
]
ask_close: func [] [
either not saved? [
switch request/offset ["Exit without saving?" "Yes" "Save" "No"] main-window/offset + 100x100 reduce [
yes [quit]
no [if save_file [quit]]
]
][
either get-face tog-exit [
quit
][
if request/confirm/offset "Exit now?" main-window/offset + 100x100 [quit]
]
]
]
; do
do_command: func [/local temp fl result out] [
temp: build_tree
fl: flash/with "Archiving..." main-window
;probe
result: either system/version < 2.9.0 [call/wait/output get-face info-command out: copy ""][call/wait get-face info-command]
delete-dir temp
unview/only fl
inform/offset layout [
space 2x2
below
text bold (either result <> 0 ["An error occured"]["Output"])
across
info-out: info 580x300 as-is out wrap edge [size: 1x1]
pad -20
scroller info-out/size/y * 0x1 + 16x0 with [append init [redrag 150 / 300]] [scroll-para info-out face]
key (escape) (0x0 - sp) [hide-popup]
] main-window/offset + 40x40
]
; gui
gui-edge: [color: 15.15.15 image: none effect: 'ibevel size: 1x1]
set_file_field: func [face [object!] ext type /local previous file-name response] [
previous: get-face face
file-name: switch type [
new [request-file/keep/only/save/filter ext]
file [choose_file ext]
dir [
file-name: request-file/keep/only/save/title/filter "Create a folder" "OK" ext
response: true
if all [not none? file-name exists? file-name] [response: request/offset rejoin [{File "} last split-path file-name {" already exists, overwrite it?}] main-window/offset + 100x100]
if response <> true [file-name: none]
file-name
]
]
set-face face to-local-file any [file-name previous]
saved?: not found? file-name
update_archiver
]
add_files: func [/dir /local files file] [
either dir [
files: any [request-dir/keep []]
files: append clear [] files %/
][
files: any [request-file/keep/title "Select files" "OK" []]
]
forall files [
file: to-local-file first files
if not find text-list-files/data file [
unless empty? text-list-files/data [
if empty? text-list-files/picked [append text-list-files/picked first text-list-files/data] ; security check
]
append text-list-files/data file
saved?: no
]
]
append clear text-list-files/picked file
show text-list-files/update
file
]
remove_selected: func [/local picked] [
if empty? text-list-files/data [exit]
picked: find text-list-files/data first text-list-files/picked
clear text-list-files/picked
either tail? next picked [ ; is last line?
append text-list-files/picked first back picked
][
append text-list-files/picked first next picked
]
remove picked
saved?: no
show text-list-files/update
]
save_list: func [/to file-name [file!] /local response files files-string] [
if empty? text-list-files/data [exit]
if not file-name [
file-name: request-file/only/save
if not file-name [exit]
if exists? file-name [response: request rejoin [{File "} last split-path file-name {" already exists, overwrite it?}]]
if response <> true [exit]
]
files-string: copy {}
files: text-list-files/data
forall files [
append files-string rejoin [{"} first files {"} newline]
]
write file-name files-string
]
update_archiver: func [/local command] [
command: reform [
enquote trim get-face field-archiver
trim get-face field-command
enquote trim get-face field-archive
enquote trim get-face field-temp
]
set-face info-command command
]
sort_list: func [/reverse] [
either reverse [
sort/reverse text-list-files/data
][
sort text-list-files/data
]
show text-list-files/update
]
move_selected: func [/up /local picked selecting] [
if empty? text-list-files/data [exit]
picked: text-list-files/picked
if none? first picked [change picked first text-list-files/data]
if none? selecting: find text-list-files/data first picked [exit]
change picked either up [
any [first back selecting first text-list-files/data]
][
any [attempt [first next selecting] last text-list-files/data]
]
show text-list-files/update
]
main-layout: [
do [sp: 4x4] origin sp space sp
Across
style btn btn 90x24
style field field edge gui-edge
style text text 150x24 para [origin: 0x3]
btn "Load..." [open_file]
btn "Save" [save_file]
pad (-1x0 * sp)
btn "as..." 36 [save_file/as]
pad 100x0 - 36x0
btn "?" 20 sky keycode [f1] move-x [
ssh: System/script/header
if not value? 'help-win [; avoid opening win more then once
help-win: view/new layout [ below space sp style text text 500 center
text bold ssh/Title
text rejoin ["Version: " ssh/Version either ssh/Version <> pick tail ssh/history -2 [rejoin [" (" pick tail ssh/history -2 ")"]][""] " , " ssh/Date ". Copyright (C) " now/year " " ssh/Author]
text bold "USE AT YOUR OWN RISK"
text "END USER LICENCE AGREEMENT" blue underline [browse http://creativecommons.org/licenses/by-nd/3.0/legalcode]
across
info-help: info 580x300 as-is trim/auto ssh/Help wrap edge [size: 1x1]
pad -20x0
scroller info-help/size/y * 0x1 + 16x0 with [append init [redrag 250 / 300]] [scroll-para info-help face]
key (escape) (0x0 - sp) [unview/only help-win unset 'help-win]
]
help-win/feel: make help-win/feel [
super-detect: :detect
detect: func [face event][
super-detect face event
if event/type = 'close [unview/only face unset 'help-win]
event
]
]
]
]
tog-exit: tog "Now" 36x24 off move-x
pad (-1x0 * sp)
btn "Exit..." move-x [ask_close]
return
text "Archive:" 60
field-archive: field "test.zip" 330 resize-x [update_archiver]
btn "..." 40 move-x [set_file_field field-archive "*.zip" 'new]
return
text "Archiver:" 60
field-archiver: field "7z.exe" 330 resize-x [update_archiver]
btn "..." 40 move-x [set_file_field field-archiver "*.*" 'file]
return
text "Archiver commands and options:" 190
field-command: field "a -tzip" 200 resize-x [update_archiver saved?: no]
return
text "Temporary directory:" 190
field-temp: field "backup" 200 resize-x [update_archiver saved?: no]
btn "..." 40 move-x [set_file_field field-temp "*.*" 'dir]
return
text bold "Command:"
return
info-command: info "7z.exe a -tzip test.zip temp\" 394 resize-x
btn "Do" 40 green move-x [do_command]
return
text bold "Directories and files:"
return
text-list-files: text-list 437x200 resize-xy with [
;-- The update function. This should be called by user code when the
; list has been changed. It will recompute scroll bar variables.
; Return the list face so user can write: SHOW alist/update
update: func [/local item tot-rows visible-rows] [
tot-rows: length? data visible-rows: lc
sld/redrag visible-rows / max 1 tot-rows
sld/page: sld/ratio / 1.5
if item: find data picked/1 [
either visible-rows >= tot-rows [
sld/step: 0.0
sld/data: 0.0
sn: 0
][
sld/step: 1 / (tot-rows - visible-rows)
sld/data: (index? item) / tot-rows ; simple but it works
if sld/data < sld/step [sld/data: 0]
sn: to-integer sld/data / sld/step
]
]
self
]
;-- Resize function. Change all sub-faces to new size.
resize: func [new /x /y /local tmp][
either any [x y] [
if x [size/x: new]
if y [size/y: new]
][
size: any [new size]
]
pane/size: sz: size
sld/offset/x: first sub-area/size: size - 16x0
sld/resize/y size/y
iter/size/x: first sub-area/size - sub-area/edge/size
lc: to-integer sz/y / iter/size/y
sld/redrag lc / max 1 length? data
sld/page: sld/ratio / 1.5
self
]
]
return
style btn btn 217
btn "Add dir..." [add_files/dir] resize [0 1 .5 0] ; must put resize block after first block for compatibility reasons since below I could remove word 'resize
btn "Add file..." [add_files] resize [.5 1 .5 0]
return
btn "Sort A-Z" [sort_list] resize [0 1 .5 0]
btn "Sort Z-A" [sort_list/reverse] resize [.5 1 .5 0]
return
btn "Delete selected" [remove_selected] resize [0 1 .5 0]
btn "Save files list..." [save_list] resize [.5 1 .5 0]
key (escape) (0x0 - sp) [ask_close]
key keycode [down] (0x0 - sp) [move_selected]
key keycode [up] (0x0 - sp) [move_selected/up]
key #"^~" (0x0 - sp) [remove_selected]
]
; keep working if resizer not found
if not value? 'resizer-ctx [remove-each word main-layout [any [word = 'move-x word = 'resize word = 'resize-x word = 'resize-y word = 'resize-xy]]]
main-window: layout main-layout
main-window/user-data: reduce ['size main-window/size]
update_archiver
insert-event-func func [face event /local siz] [
if event/face = main-window [
switch event/type [
close [
if event/face = main-window [
ask_close
return none
]
if all [value? 'help-win event/face = help-win] [unset 'help-win]
event
]
scroll-line [either event/offset/y < 0 [scroll-drag/page/back text-list-files/sld] [scroll-drag/page text-list-files/sld]]
]
]
event
]
; main
job-name: none
named: no
saved?: yes
main-title: join copy System/script/header/title " - Untitled"
min-size: main-window/size
view/title/options main-window main-title reduce ['resize 'min-size min-size + system/view/title-size + 8x10 + system/view/resize-border]
do-events
] ; err? |