|
|
|
#[Copyright 2023 ITwrx.
|
|
|
|
This file is part of EZ-Bkup.
|
|
|
|
EZ-Bkup is released under the General Public License 3.0.
|
|
|
|
See COPYING or <https://www.gnu.org/licenses/> for details.]#
|
|
|
|
|
|
|
|
import owlkettle
|
|
|
|
import "../models/routine", "../shared"
|
|
|
|
|
|
|
|
viewable RoutineEditor:
|
|
|
|
## A form for editing a Routine
|
|
|
|
|
|
|
|
routine: Routine ## The routine that is being edited
|
|
|
|
|
|
|
|
# Since Routine is passed by value, we need to notify the parent widget of
|
|
|
|
# any changes to the routine. The changed callback
|
|
|
|
proc changed(routine: Routine)
|
|
|
|
|
|
|
|
method view(editor: RoutineEditorState): Widget {.locks: "unknown".} =
|
|
|
|
result = gui:
|
|
|
|
#must have top level container that everything else is inside of.
|
|
|
|
Box:
|
|
|
|
orient = OrientY
|
|
|
|
margin = 12
|
|
|
|
spacing = 12
|
|
|
|
Box {.expand: false.}:
|
|
|
|
orient = OrientX
|
|
|
|
spacing = 6
|
|
|
|
Label {.expand: false.}:
|
|
|
|
text = "<span weight=\"bold\">Name:</span>"
|
|
|
|
xAlign = 0
|
|
|
|
useMarkup = true
|
|
|
|
Entry {.expand: false.}:
|
|
|
|
text = editor.routine.name
|
|
|
|
xAlign = 0
|
|
|
|
proc changed(text: string) =
|
|
|
|
editor.routine.name = text
|
|
|
|
# Call the changed callback
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Box {.expand: false.}:
|
|
|
|
orient = OrientX
|
|
|
|
spacing = 6
|
|
|
|
Label {.expand: false.}:
|
|
|
|
text = "<span weight=\"bold\" color=\"#FFF469\">Enabled by default?</span>"
|
|
|
|
tooltip = "Should this Routine be enabled for inclusion in any Bkup run by default?"
|
|
|
|
xAlign = 0
|
|
|
|
useMarkup = true
|
|
|
|
Switch {.expand: false.}:
|
|
|
|
state = editor.routine.selByDef
|
|
|
|
proc changed(state: bool) =
|
|
|
|
editor.routine.selByDef = state
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Label {.expand: false.}:
|
|
|
|
text = "<span weight=\"bold\" color=\"#FFF469\">Sources:</span>"
|
|
|
|
tooltip = "The file(s) or folder(s) you want to backup when this Routine is run."
|
|
|
|
xAlign = 0
|
|
|
|
useMarkup = true
|
|
|
|
Box {.expand: false.}:
|
|
|
|
spacing = 6
|
|
|
|
Button {.expand: false.}:
|
|
|
|
text = "+ File"
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
proc clicked() =
|
|
|
|
let (res, state) = editor.app.open: gui:
|
|
|
|
FileChooserDialog:
|
|
|
|
title = "Add Source Files to Routine"
|
|
|
|
action = FileChooserOpen
|
|
|
|
selectMultiple = true
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Cancel"
|
|
|
|
res = DialogCancel
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Confirm"
|
|
|
|
res = DialogAccept
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
if res.kind == DialogAccept:
|
|
|
|
for filename in FileChooserDialogState(state).filenames:
|
|
|
|
if hasCommas(filename):
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Commas in Source filename/path are not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
elif filename in editor.routine.sources:
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Duplicate Routine Source filenames (" & filename & ") are not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
else:
|
|
|
|
editor.routine.sources.add(filename)
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Button {.expand: false.}:
|
|
|
|
text = "+ Folder"
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
proc clicked() =
|
|
|
|
let (res, state) = editor.app.open: gui:
|
|
|
|
FileChooserDialog:
|
|
|
|
title = "Add Source Folders to Routine"
|
|
|
|
action = FileChooserSelectFolder
|
|
|
|
selectMultiple = true
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Cancel"
|
|
|
|
res = DialogCancel
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Confirm"
|
|
|
|
res = DialogAccept
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
if res.kind == DialogAccept:
|
|
|
|
for filename in FileChooserDialogState(state).filenames:
|
|
|
|
if hasCommas(filename):
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Commas in Source filename/path are not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
elif filename in editor.routine.sources:
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Duplicate Routine Source (" & filename & ") not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
else:
|
|
|
|
editor.routine.sources.add(filename)
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Box {.expand: false.}:
|
|
|
|
orient = OrientY
|
|
|
|
margin = 6
|
|
|
|
spacing = 6
|
|
|
|
#routineSeq returns an empty seq when no sources exist.
|
|
|
|
if editor.routine.sources.len != 0:
|
|
|
|
for it, routineSource in editor.routine.sources:
|
|
|
|
Box:
|
|
|
|
orient = OrientX
|
|
|
|
spacing = 6
|
|
|
|
Label:
|
|
|
|
text = routineSource
|
|
|
|
xAlign = 0
|
|
|
|
Button {.expand: false.}:
|
|
|
|
icon = "user-trash-symbolic"
|
|
|
|
tooltip = "Delete this Source. Warning: will not ask you to confirm."
|
|
|
|
proc clicked() =
|
|
|
|
editor.routine.sources.delete(it)
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Label {.expand: false.}:
|
|
|
|
text = "<span weight=\"bold\" color=\"#FFF469\">Destinations:</span>"
|
|
|
|
tooltip = "The folder(s) or drive(s) you want to backup this Routine's Sources to."
|
|
|
|
xAlign = 0
|
|
|
|
useMarkup = true
|
|
|
|
Box {.expand: false.}:
|
|
|
|
spacing = 6
|
|
|
|
Button {.expand: false.}:
|
|
|
|
text = "+ Folder/Drive"
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
proc clicked() =
|
|
|
|
let (res, state) = editor.app.open: gui:
|
|
|
|
FileChooserDialog:
|
|
|
|
title = "Add Destination Folders to Routine"
|
|
|
|
action = FileChooserSelectFolder
|
|
|
|
selectMultiple = true
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Cancel"
|
|
|
|
res = DialogCancel
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Confirm"
|
|
|
|
res = DialogAccept
|
|
|
|
style = [ButtonSuggested]
|
|
|
|
if res.kind == DialogAccept:
|
|
|
|
for filename in FileChooserDialogState(state).filenames:
|
|
|
|
if hasCommas(filename):
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Commas in Destination filename/path are not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
elif filename in editor.routine.destinations:
|
|
|
|
discard editor.app.open: gui:
|
|
|
|
MessageDialog:
|
|
|
|
message = "Duplicate Routine Destination (" & filename & ") not supported."
|
|
|
|
style = [StyleClass("error")]
|
|
|
|
DialogButton {.addButton.}:
|
|
|
|
text = "Ok"
|
|
|
|
res = DialogAccept
|
|
|
|
else:
|
|
|
|
editor.routine.destinations.add(filename)
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
Box {.expand: false.}:
|
|
|
|
orient = OrientY
|
|
|
|
margin = 6
|
|
|
|
spacing = 6
|
|
|
|
#routineSeq returns an empty seq when no destinations exist.
|
|
|
|
if editor.routine.destinations.len != 0:
|
|
|
|
for it, routineDestination in editor.routine.destinations:
|
|
|
|
Box:
|
|
|
|
orient = OrientX
|
|
|
|
spacing = 6
|
|
|
|
Label:
|
|
|
|
text = routineDestination
|
|
|
|
xAlign = 0
|
|
|
|
Button {.expand: false.}:
|
|
|
|
icon = "user-trash-symbolic"
|
|
|
|
tooltip = "Delete this Destination. Warning: will not ask you to confirm."
|
|
|
|
proc clicked() =
|
|
|
|
editor.routine.destinations.delete(it)
|
|
|
|
if not editor.changed.isNil:
|
|
|
|
editor.changed.callback(editor.routine)
|
|
|
|
|
|
|
|
export RoutineEditor
|