415 lines
11 KiB
Go

package view
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg"
encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view/convertor/encoders"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/window"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils"
"image/color"
"os"
"path/filepath"
)
type ConvertSetting struct {
DirectoryForSave string
OverwriteOutputFiles bool
Format string
Encoder encoder2.EncoderContract
}
func Convertor(
window window.WindowContract,
addFileForConversion func(file ffmpeg.File),
directoryForSavingPath string,
directoryForSaving func(path string),
formats encoder.ConvertorFormatsContract,
addToConversion func(convertSetting ConvertSetting) error,
) fyne.CanvasObject {
conversionMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
conversionMessage.TextSize = 16
conversionMessage.TextStyle = fyne.TextStyle{Bold: true}
form := newFormConvertor(
window,
addFileForConversion,
directoryForSavingPath,
directoryForSaving,
formats,
addToConversion,
conversionMessage,
)
converterVideoFilesTitle := lang.L("converterVideoFilesTitle")
return widget.NewCard(converterVideoFilesTitle, "", container.NewVScroll(form.getForm()))
}
type formConvertor struct {
form *widget.Form
items []*widget.FormItem
conversionMessage *canvas.Text
window window.WindowContract
addFileForConversion func(file ffmpeg.File)
directoryForSaving func(path string)
}
func newFormConvertor(
window window.WindowContract,
addFileForConversion func(file ffmpeg.File),
directoryForSavingPath string,
directoryForSaving func(path string),
formats encoder.ConvertorFormatsContract,
addToConversion func(convertSetting ConvertSetting) error,
conversionMessage *canvas.Text,
) *formConvertor {
f := widget.NewForm()
f.SubmitText = lang.L("converterVideoFilesSubmitTitle")
formConvertor := &formConvertor{
form: f,
window: window,
addFileForConversion: addFileForConversion,
directoryForSaving: directoryForSaving,
conversionMessage: conversionMessage,
}
fileForConversion := formConvertor.newFileForConversion()
directoryForSavingButton := formConvertor.newDirectoryForSaving(directoryForSavingPath)
isOverwriteOutputFiles := false
checkboxOverwriteOutputFiles := widget.NewCheck(lang.L("checkboxOverwriteOutputFilesTitle"), func(b bool) {
isOverwriteOutputFiles = b
})
checkboxOverwriteOutputFiles.SetChecked(isOverwriteOutputFiles)
selectEncoder := formConvertor.newSelectEncoder(formats)
items := []*widget.FormItem{
{
Text: lang.L("fileForConversionTitle"),
Widget: fileForConversion.button,
},
{
Widget: container.NewHScroll(fileForConversion.message),
},
{
Text: lang.L("buttonForSelectedDirTitle"),
Widget: directoryForSavingButton.button,
},
{
Widget: container.NewHScroll(directoryForSavingButton.message),
},
{
Widget: checkboxOverwriteOutputFiles,
},
{
Widget: selectEncoder.SelectFileType,
},
{
Text: lang.L("selectFormat"),
Widget: selectEncoder.SelectFormat,
},
{
Text: lang.L("selectEncoder"),
Widget: selectEncoder.SelectEncoder,
},
}
formConvertor.form.Items = items
formConvertor.items = items
formConvertor.changeEncoder(selectEncoder.Encoder)
selectEncoder.ChangeEncoder = formConvertor.changeEncoder
formConvertor.form.OnSubmit = func() {
formConvertor.conversionMessage.Text = ""
if len(directoryForSavingButton.path) == 0 {
formConvertor.conversionMessage.Text = lang.L("errorSelectedFolderSave")
return
}
if len(selectEncoder.SelectFormat.Selected) == 0 {
formConvertor.conversionMessage.Text = lang.L("errorSelectedFormat")
return
}
if selectEncoder.Encoder == nil {
formConvertor.conversionMessage.Text = lang.L("errorSelectedEncoder")
return
}
fileForConversion.button.Disable()
directoryForSavingButton.button.Disable()
formConvertor.form.Disable()
fyne.Do(func() {
err := addToConversion(ConvertSetting{
DirectoryForSave: directoryForSavingButton.path,
OverwriteOutputFiles: isOverwriteOutputFiles,
Format: selectEncoder.SelectFormat.Selected,
Encoder: selectEncoder.Encoder,
})
if err != nil {
formConvertor.conversionMessage.Text = err.Error()
}
fileForConversion.button.Enable()
directoryForSavingButton.button.Enable()
formConvertor.form.Enable()
})
}
return formConvertor
}
func (f *formConvertor) getForm() fyne.CanvasObject {
return container.NewVBox(
f.form,
container.NewHScroll(f.conversionMessage),
)
}
type fileForConversion struct {
button *widget.Button
message *canvas.Text
file *ffmpeg.File
}
func (f *formConvertor) newFileForConversion() *fileForConversion {
message := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
fileForConversion := &fileForConversion{
message: message,
}
buttonTitle := lang.L("choose") + "\n" +
lang.L("or") + "\n" +
lang.L("dragAndDropFiles")
var locationURI fyne.ListableURI
fileForConversion.button = widget.NewButton(buttonTitle, func() {
f.window.NewFileOpen(func(r fyne.URIReadCloser, err error) {
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
if err != nil {
fyne.Do(func() {
fileForConversion.message.Text = err.Error()
fileForConversion.message.Refresh()
})
return
}
if r == nil {
return
}
f.addFileForConversion(ffmpeg.File{
Path: r.URI().Path(),
Name: r.URI().Name(),
Ext: r.URI().Extension(),
})
listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}, locationURI)
})
f.window.SetOnDropped(func(position fyne.Position, uris []fyne.URI) {
if len(uris) == 0 {
return
}
isError := false
for _, uri := range uris {
info, err := os.Stat(uri.Path())
if err != nil {
isError = true
continue
}
if info.IsDir() {
isError = true
continue
}
f.addFileForConversion(ffmpeg.File{
Path: uri.Path(),
Name: uri.Name(),
Ext: uri.Extension(),
})
listableURI := storage.NewFileURI(filepath.Dir(uri.Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}
if isError {
fileForConversion.message.Text = lang.L("errorDragAndDropFile")
utils.SetStringErrorStyle(fileForConversion.message)
} else {
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
}
})
return fileForConversion
}
type directoryForSaving struct {
button *widget.Button
message *canvas.Text
path string
}
func (f *formConvertor) newDirectoryForSaving(directoryForSavingPath string) *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 := lang.L("choose")
locationURI, err := utils.PathToListableURI(directoryForSavingPath)
if err == nil {
directoryForSaving.path = locationURI.Path()
directoryForSaving.message.Text = locationURI.Path()
utils.SetStringSuccessStyle(directoryForSaving.message)
}
directoryForSaving.button = widget.NewButton(buttonTitle, func() {
f.window.NewFolderOpen(func(r fyne.ListableURI, err error) {
if err != nil {
directoryForSaving.message.Text = err.Error()
utils.SetStringErrorStyle(directoryForSaving.message)
return
}
if r == nil {
return
}
directoryForSaving.path = r.Path()
directoryForSaving.message.Text = r.Path()
utils.SetStringSuccessStyle(directoryForSaving.message)
locationURI, err = storage.ListerForURI(r)
if err == nil {
f.directoryForSaving(locationURI.Path())
}
}, locationURI)
})
return directoryForSaving
}
type selectEncoder struct {
SelectFileType *widget.RadioGroup
SelectFormat *widget.Select
SelectEncoder *widget.Select
Encoder encoder2.EncoderContract
ChangeEncoder func(encoder encoder2.EncoderContract)
}
func (f *formConvertor) newSelectEncoder(formats encoder.ConvertorFormatsContract) *selectEncoder {
selectEncoder := &selectEncoder{}
encoderMap := map[int]encoder2.EncoderDataContract{}
selectEncoder.SelectEncoder = widget.NewSelect([]string{}, func(s string) {
if encoderMap[selectEncoder.SelectEncoder.SelectedIndex()] == nil {
return
}
selectEncoderData := encoderMap[selectEncoder.SelectEncoder.SelectedIndex()]
selectEncoder.Encoder = selectEncoderData.NewEncoder()
if selectEncoder.ChangeEncoder != nil {
selectEncoder.ChangeEncoder(selectEncoder.Encoder)
}
})
formatSelected := ""
selectEncoder.SelectFormat = widget.NewSelect([]string{}, func(s string) {
if formatSelected == s {
return
}
formatSelected = s
format, err := formats.GetFormat(s)
if err != nil {
return
}
var encoderOptions []string
encoderMap = map[int]encoder2.EncoderDataContract{}
for _, e := range format.GetEncoders() {
encoderMap[len(encoderMap)] = e
encoderOptions = append(encoderOptions, lang.L("encoder_"+e.GetTitle()))
}
selectEncoder.SelectEncoder.SetOptions(encoderOptions)
selectEncoder.SelectEncoder.SetSelectedIndex(0)
})
var fileTypeOptions []string
for _, fileType := range encoder2.GetListFileType() {
fileTypeOptions = append(fileTypeOptions, fileType.Name())
}
encoderGroupVideo := lang.L("encoderGroupVideo")
encoderGroupAudio := lang.L("encoderGroupAudio")
encoderGroupImage := lang.L("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]
var 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 (f *formConvertor) changeEncoder(encoder encoder2.EncoderContract) {
var items []*widget.FormItem
if encoders.Views[encoder.GetName()] != nil {
items = encoders.Views[encoder.GetName()](encoder)
}
f.changeItems(items)
}
func (f *formConvertor) changeItems(items []*widget.FormItem) {
fyne.Do(func() {
f.form.Items = f.items
f.form.Refresh()
f.form.Items = append(f.form.Items, items...)
f.form.Refresh()
})
}