Introduced `DirectoryForSaving` for managing directory paths persistently. Integrated the new setting into relevant modules, ensuring the selected directory is saved and loaded across sessions.
475 lines
14 KiB
Go
475 lines
14 KiB
Go
package view
|
|
|
|
import (
|
|
"errors"
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/canvas"
|
|
"fyne.io/fyne/v2/container"
|
|
"fyne.io/fyne/v2/storage"
|
|
"fyne.io/fyne/v2/widget"
|
|
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor/view/form_items"
|
|
encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder"
|
|
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
|
|
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel/encoder"
|
|
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
|
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
"image/color"
|
|
"path/filepath"
|
|
)
|
|
|
|
type ConversionContract interface {
|
|
GetContent() fyne.CanvasObject
|
|
AfterViewContent()
|
|
}
|
|
|
|
type Conversion struct {
|
|
app kernel.AppContract
|
|
form *form
|
|
conversionMessage *canvas.Text
|
|
fileForConversion *fileForConversion
|
|
directoryForSaving *directoryForSaving
|
|
overwriteOutputFiles *overwriteOutputFiles
|
|
selectEncoder *selectEncoder
|
|
runConvert func(setting HandleConvertSetting)
|
|
}
|
|
|
|
type HandleConvertSetting struct {
|
|
FileInput kernel.File
|
|
DirectoryForSave string
|
|
OverwriteOutputFiles bool
|
|
Format string
|
|
Encoder encoder2.EncoderContract
|
|
}
|
|
|
|
func NewConversion(app kernel.AppContract, formats encoder.ConvertorFormatsContract, runConvert func(setting HandleConvertSetting), settingDirectoryForSaving setting.DirectoryForSavingContract) *Conversion {
|
|
conversionMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
|
|
conversionMessage.TextSize = 16
|
|
conversionMessage.TextStyle = fyne.TextStyle{Bold: true}
|
|
|
|
fileForConversion := newFileForConversion(app)
|
|
directoryForSaving := newDirectoryForSaving(app, settingDirectoryForSaving)
|
|
overwriteOutputFiles := newOverwriteOutputFiles(app)
|
|
selectEncoder := newSelectEncoder(app, formats)
|
|
|
|
items := []*widget.FormItem{
|
|
{
|
|
Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "fileForConversionTitle"}),
|
|
Widget: fileForConversion.button,
|
|
},
|
|
{
|
|
Widget: container.NewHScroll(fileForConversion.message),
|
|
},
|
|
{
|
|
Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "buttonForSelectedDirTitle"}),
|
|
Widget: directoryForSaving.button,
|
|
},
|
|
{
|
|
Widget: container.NewHScroll(directoryForSaving.message),
|
|
},
|
|
{
|
|
Widget: overwriteOutputFiles.checkbox,
|
|
},
|
|
{
|
|
Widget: selectEncoder.SelectFileType,
|
|
},
|
|
{
|
|
Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "selectFormat"}),
|
|
Widget: selectEncoder.SelectFormat,
|
|
},
|
|
{
|
|
Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "selectEncoder"}),
|
|
Widget: selectEncoder.SelectEncoder,
|
|
},
|
|
}
|
|
form := newForm(app, items)
|
|
|
|
return &Conversion{
|
|
app: app,
|
|
form: form,
|
|
conversionMessage: conversionMessage,
|
|
fileForConversion: fileForConversion,
|
|
directoryForSaving: directoryForSaving,
|
|
overwriteOutputFiles: overwriteOutputFiles,
|
|
selectEncoder: selectEncoder,
|
|
runConvert: runConvert,
|
|
}
|
|
}
|
|
|
|
func (c Conversion) GetContent() fyne.CanvasObject {
|
|
c.form.form.OnSubmit = c.submit
|
|
c.fileForConversion.AddChangeCallback(c.selectFileForConversion)
|
|
c.selectEncoder.AddChangeCallback(c.changeEncoder)
|
|
if c.selectEncoder.Encoder != nil {
|
|
c.selectEncoder.SelectEncoder.SetSelectedIndex(c.selectEncoder.SelectEncoder.SelectedIndex())
|
|
}
|
|
|
|
return container.NewVBox(
|
|
c.form.form,
|
|
c.conversionMessage,
|
|
)
|
|
}
|
|
|
|
func (c Conversion) changeEncoder(encoder encoder2.EncoderContract) {
|
|
items := []*widget.FormItem{}
|
|
|
|
if form_items.Views[encoder.GetName()] != nil {
|
|
items = form_items.Views[encoder.GetName()](encoder, c.app)
|
|
}
|
|
|
|
c.form.ChangeItems(items)
|
|
}
|
|
|
|
func (c Conversion) AfterViewContent() {
|
|
c.form.form.Disable()
|
|
}
|
|
|
|
func (c Conversion) selectFileForConversion(err error) {
|
|
c.conversionMessage.Text = ""
|
|
if err != nil {
|
|
c.form.form.Disable()
|
|
return
|
|
}
|
|
|
|
c.form.form.Enable()
|
|
}
|
|
|
|
func (c Conversion) submit() {
|
|
if len(c.directoryForSaving.path) == 0 {
|
|
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "errorSelectedFolderSave",
|
|
})))
|
|
c.enableFormConversion()
|
|
return
|
|
}
|
|
if len(c.selectEncoder.SelectFormat.Selected) == 0 {
|
|
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "errorSelectedFormat",
|
|
})))
|
|
return
|
|
}
|
|
if c.selectEncoder.Encoder == nil {
|
|
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "errorSelectedEncoder",
|
|
})))
|
|
return
|
|
}
|
|
c.conversionMessage.Text = ""
|
|
|
|
c.fileForConversion.button.Disable()
|
|
c.directoryForSaving.button.Disable()
|
|
c.form.form.Disable()
|
|
|
|
setting := HandleConvertSetting{
|
|
FileInput: *c.fileForConversion.file,
|
|
DirectoryForSave: c.directoryForSaving.path,
|
|
OverwriteOutputFiles: c.overwriteOutputFiles.IsChecked(),
|
|
Format: c.selectEncoder.SelectFormat.Selected,
|
|
Encoder: c.selectEncoder.Encoder,
|
|
}
|
|
c.runConvert(setting)
|
|
c.enableFormConversion()
|
|
|
|
c.fileForConversion.message.Text = ""
|
|
c.form.form.Disable()
|
|
}
|
|
|
|
func (c Conversion) enableFormConversion() {
|
|
c.fileForConversion.button.Enable()
|
|
c.directoryForSaving.button.Enable()
|
|
c.form.form.Enable()
|
|
}
|
|
|
|
type fileForConversion struct {
|
|
button *widget.Button
|
|
message *canvas.Text
|
|
file *kernel.File
|
|
|
|
changeCallbacks map[int]func(err error)
|
|
}
|
|
|
|
func newFileForConversion(app kernel.AppContract) *fileForConversion {
|
|
fileForConversion := &fileForConversion{
|
|
file: &kernel.File{},
|
|
changeCallbacks: map[int]func(err error){},
|
|
}
|
|
|
|
buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "choose",
|
|
})
|
|
|
|
fileForConversion.message = canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
|
|
fileForConversion.message.TextSize = 16
|
|
fileForConversion.message.TextStyle = fyne.TextStyle{Bold: true}
|
|
|
|
var locationURI fyne.ListableURI
|
|
|
|
fileForConversion.button = widget.NewButton(buttonTitle, func() {
|
|
app.GetWindow().NewFileOpen(func(r fyne.URIReadCloser, err error) {
|
|
if err != nil {
|
|
fileForConversion.message.Text = err.Error()
|
|
setStringErrorStyle(fileForConversion.message)
|
|
fileForConversion.eventSelectFile(err)
|
|
return
|
|
}
|
|
if r == nil {
|
|
return
|
|
}
|
|
|
|
fileForConversion.file.Path = r.URI().Path()
|
|
fileForConversion.file.Name = r.URI().Name()
|
|
fileForConversion.file.Ext = r.URI().Extension()
|
|
|
|
fileForConversion.message.Text = r.URI().Path()
|
|
setStringSuccessStyle(fileForConversion.message)
|
|
|
|
fileForConversion.eventSelectFile(nil)
|
|
|
|
listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path()))
|
|
locationURI, err = storage.ListerForURI(listableURI)
|
|
}, locationURI)
|
|
})
|
|
|
|
return fileForConversion
|
|
}
|
|
|
|
func (c fileForConversion) AddChangeCallback(callback func(err error)) {
|
|
c.changeCallbacks[len(c.changeCallbacks)] = callback
|
|
}
|
|
|
|
func (c fileForConversion) eventSelectFile(err error) {
|
|
for _, changeCallback := range c.changeCallbacks {
|
|
changeCallback(err)
|
|
}
|
|
}
|
|
|
|
type directoryForSaving struct {
|
|
button *widget.Button
|
|
message *canvas.Text
|
|
path string
|
|
}
|
|
|
|
func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving setting.DirectoryForSavingContract) *directoryForSaving {
|
|
directoryForSaving := &directoryForSaving{
|
|
path: "",
|
|
}
|
|
|
|
directoryForSaving.message = canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
|
|
directoryForSaving.message.TextSize = 16
|
|
directoryForSaving.message.TextStyle = fyne.TextStyle{Bold: true}
|
|
|
|
buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "choose",
|
|
})
|
|
|
|
var locationURI fyne.ListableURI
|
|
|
|
location, err := getDirectoryForSaving(settingDirectoryForSaving)
|
|
if err == nil {
|
|
directoryForSaving.path = location.Path()
|
|
directoryForSaving.message.Text = location.Path()
|
|
setStringSuccessStyle(directoryForSaving.message)
|
|
}
|
|
|
|
directoryForSaving.button = widget.NewButton(buttonTitle, func() {
|
|
app.GetWindow().NewFolderOpen(func(r fyne.ListableURI, err error) {
|
|
if err != nil {
|
|
directoryForSaving.message.Text = err.Error()
|
|
setStringErrorStyle(directoryForSaving.message)
|
|
return
|
|
}
|
|
if r == nil {
|
|
return
|
|
}
|
|
|
|
directoryForSaving.path = r.Path()
|
|
|
|
directoryForSaving.message.Text = r.Path()
|
|
setStringSuccessStyle(directoryForSaving.message)
|
|
locationURI, err = storage.ListerForURI(r)
|
|
|
|
if err == nil {
|
|
_, _ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path())
|
|
}
|
|
|
|
}, locationURI)
|
|
})
|
|
|
|
return directoryForSaving
|
|
}
|
|
|
|
func getDirectoryForSaving(settingDirectoryForSaving setting.DirectoryForSavingContract) (fyne.ListableURI, error) {
|
|
path, err := settingDirectoryForSaving.GetDirectoryForSaving()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(path) > 0 {
|
|
path = "file://" + path
|
|
}
|
|
|
|
uri, err := storage.ParseURI(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return storage.ListerForURI(uri)
|
|
}
|
|
|
|
type overwriteOutputFiles struct {
|
|
checkbox *widget.Check
|
|
isChecked bool
|
|
}
|
|
|
|
func newOverwriteOutputFiles(app kernel.AppContract) *overwriteOutputFiles {
|
|
overwriteOutputFiles := &overwriteOutputFiles{
|
|
isChecked: false,
|
|
}
|
|
checkboxOverwriteOutputFilesTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "checkboxOverwriteOutputFilesTitle",
|
|
})
|
|
overwriteOutputFiles.checkbox = widget.NewCheck(checkboxOverwriteOutputFilesTitle, func(b bool) {
|
|
overwriteOutputFiles.isChecked = b
|
|
})
|
|
|
|
return overwriteOutputFiles
|
|
}
|
|
|
|
func (receiver overwriteOutputFiles) IsChecked() bool {
|
|
return receiver.isChecked
|
|
}
|
|
|
|
type selectEncoder struct {
|
|
SelectFileType *widget.RadioGroup
|
|
SelectFormat *widget.Select
|
|
SelectEncoder *widget.Select
|
|
Encoder encoder2.EncoderContract
|
|
|
|
changeCallbacks map[int]func(encoder encoder2.EncoderContract)
|
|
}
|
|
|
|
func newSelectEncoder(app kernel.AppContract, formats encoder.ConvertorFormatsContract) *selectEncoder {
|
|
selectEncoder := &selectEncoder{
|
|
changeCallbacks: map[int]func(encoder encoder2.EncoderContract){},
|
|
}
|
|
|
|
encoders := map[int]encoder2.EncoderDataContract{}
|
|
selectEncoder.SelectEncoder = widget.NewSelect([]string{}, func(s string) {
|
|
if encoders[selectEncoder.SelectEncoder.SelectedIndex()] == nil {
|
|
return
|
|
}
|
|
selectEncoderData := encoders[selectEncoder.SelectEncoder.SelectedIndex()]
|
|
selectEncoder.ChangeEncoder(selectEncoderData.NewEncoder())
|
|
})
|
|
|
|
formatSelected := ""
|
|
selectEncoder.SelectFormat = widget.NewSelect([]string{}, func(s string) {
|
|
if formatSelected == s {
|
|
return
|
|
}
|
|
formatSelected = s
|
|
format, err := formats.GetFormat(s)
|
|
if err != nil {
|
|
return
|
|
}
|
|
encoderOptions := []string{}
|
|
encoders = map[int]encoder2.EncoderDataContract{}
|
|
for _, e := range format.GetEncoders() {
|
|
encoders[len(encoders)] = e
|
|
encoderOptions = append(encoderOptions, app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoder_" + e.GetTitle()}))
|
|
}
|
|
selectEncoder.SelectEncoder.SetOptions(encoderOptions)
|
|
selectEncoder.SelectEncoder.SetSelectedIndex(0)
|
|
})
|
|
|
|
fileTypeOptions := []string{}
|
|
for _, fileType := range encoder2.GetListFileType() {
|
|
fileTypeOptions = append(fileTypeOptions, fileType.Name())
|
|
}
|
|
|
|
encoderGroupVideo := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupVideo"})
|
|
encoderGroupAudio := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupAudio"})
|
|
encoderGroupImage := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupImage"})
|
|
encoderGroup := map[string]string{
|
|
encoderGroupVideo: "video",
|
|
encoderGroupAudio: "audio",
|
|
encoderGroupImage: "image",
|
|
}
|
|
selectEncoder.SelectFileType = widget.NewRadioGroup([]string{encoderGroupVideo, encoderGroupAudio, encoderGroupImage}, func(s string) {
|
|
groupCode := encoderGroup[s]
|
|
|
|
formatOptions := []string{}
|
|
for _, f := range formats.GetFormats() {
|
|
if groupCode != f.GetFileType().Name() {
|
|
continue
|
|
}
|
|
formatOptions = append(formatOptions, f.GetTitle())
|
|
}
|
|
selectEncoder.SelectFormat.SetOptions(formatOptions)
|
|
if groupCode == encoder2.FileType(encoder2.Video).Name() {
|
|
selectEncoder.SelectFormat.SetSelected("mp4")
|
|
} else {
|
|
selectEncoder.SelectFormat.SetSelectedIndex(0)
|
|
}
|
|
})
|
|
selectEncoder.SelectFileType.Horizontal = true
|
|
selectEncoder.SelectFileType.Required = true
|
|
selectEncoder.SelectFileType.SetSelected(encoderGroupVideo)
|
|
|
|
return selectEncoder
|
|
}
|
|
|
|
func (e *selectEncoder) ChangeEncoder(encoder encoder2.EncoderContract) {
|
|
e.Encoder = encoder
|
|
e.eventSelectEncoder(e.Encoder)
|
|
}
|
|
|
|
func (e *selectEncoder) AddChangeCallback(callback func(encoder encoder2.EncoderContract)) {
|
|
e.changeCallbacks[len(e.changeCallbacks)] = callback
|
|
}
|
|
|
|
func (e *selectEncoder) eventSelectEncoder(encoder encoder2.EncoderContract) {
|
|
for _, changeCallback := range e.changeCallbacks {
|
|
changeCallback(encoder)
|
|
}
|
|
}
|
|
|
|
func setStringErrorStyle(text *canvas.Text) {
|
|
text.Color = color.RGBA{R: 255, G: 0, B: 0, A: 255}
|
|
text.Refresh()
|
|
}
|
|
|
|
func setStringSuccessStyle(text *canvas.Text) {
|
|
text.Color = color.RGBA{R: 49, G: 127, B: 114, A: 255}
|
|
text.Refresh()
|
|
}
|
|
|
|
func showConversionMessage(conversionMessage *canvas.Text, err error) {
|
|
conversionMessage.Text = err.Error()
|
|
setStringErrorStyle(conversionMessage)
|
|
}
|
|
|
|
type form struct {
|
|
form *widget.Form
|
|
items []*widget.FormItem
|
|
}
|
|
|
|
func newForm(app kernel.AppContract, items []*widget.FormItem) *form {
|
|
f := widget.NewForm()
|
|
f.SubmitText = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "converterVideoFilesSubmitTitle",
|
|
})
|
|
f.Items = items
|
|
|
|
return &form{
|
|
form: f,
|
|
items: items,
|
|
}
|
|
}
|
|
|
|
func (f form) ChangeItems(items []*widget.FormItem) {
|
|
f.form.Items = f.items
|
|
f.form.Refresh()
|
|
f.form.Items = append(f.form.Items, items...)
|
|
f.form.Refresh()
|
|
}
|