4 Commits

57 changed files with 1825 additions and 2182 deletions

View File

@@ -2,5 +2,8 @@
Icon = "icon.png" Icon = "icon.png"
Name = "GUI for FFmpeg" Name = "GUI for FFmpeg"
ID = "net.kor-elf.projects.gui-for-ffmpeg" ID = "net.kor-elf.projects.gui-for-ffmpeg"
Version = "0.9.0" Version = "0.8.0"
Build = 11 Build = 4
[Migrations]
fyneDo = true

View File

@@ -25,7 +25,21 @@
* fyne-cross linux --icon icon.png --app-id "." -name "gui-for-ffmpeg" * fyne-cross linux --icon icon.png --app-id "." -name "gui-for-ffmpeg"
7. Создаться папка **fyne-cross/bin** и там будет созданна папка с тем названием под которую Вы компилировали приложения (linux-amd64 или windows-amd64). 7. Создаться папка **fyne-cross/bin** и там будет созданна папка с тем названием под которую Вы компилировали приложения (linux-amd64 или windows-amd64).
8. В папку **fyne-cross/bin/linux-amd64** или **fyne-cross/bin/windows-amd64** копируете: 8. В папку **fyne-cross/bin/linux-amd64** или **fyne-cross/bin/windows-amd64** копируете:
* icon.png
* data
* languages
* LICENSE * LICENSE
* LICENSE-3RD-PARTY.txt * LICENSE-3RD-PARTY.txt
<p><strong>Структура должна получиться такая:</strong></p> <p><strong>Структура должна получиться такая:</strong></p>
<img src="images/screenshot-folder-structure.png"> <img src="images/screenshot-folder-structure.png">
## Работа с переводами:
1. go install -v github.com/nicksnyder/go-i18n/v2/goi18n@latest
3. Создаём файл languages/translate.\*.toml
4. goi18n merge -sourceLanguage ru -outdir languages languages/active.\*.toml languages/translate.\*.toml
5. В файлах **languages/translate.\*.toml** переводим текст на нужный язык
6. goi18n merge -sourceLanguage ru -outdir languages languages/active.\*.toml languages/translate.\*.toml
___где * подставляем нужный язык___
Более подробно можно почитать тут: https://github.com/nicksnyder/go-i18n

View File

@@ -5,12 +5,10 @@ import (
) )
type RepositoryContract interface { type RepositoryContract interface {
GetPathFfmpeg() string GetPathFfmpeg() (string, error)
SavePathFfmpeg(code string) setting.Setting SavePathFfmpeg(code string) (setting.Setting, error)
GetPathFfprobe() string GetPathFfprobe() (string, error)
SavePathFfprobe(code string) setting.Setting SavePathFfprobe(code string) (setting.Setting, error)
GetPathFfplay() string
SavePathFfplay(code string) setting.Setting
} }
type Repository struct { type Repository struct {
@@ -21,26 +19,18 @@ func NewRepository(settingRepository setting.RepositoryContract) *Repository {
return &Repository{settingRepository: settingRepository} return &Repository{settingRepository: settingRepository}
} }
func (r Repository) GetPathFfmpeg() string { func (r Repository) GetPathFfmpeg() (string, error) {
return r.settingRepository.GetValue("ffmpeg") return r.settingRepository.GetValue("ffmpeg")
} }
func (r Repository) SavePathFfmpeg(path string) setting.Setting { func (r Repository) SavePathFfmpeg(path string) (setting.Setting, error) {
return r.settingRepository.CreateOrUpdate("ffmpeg", path) return r.settingRepository.CreateOrUpdate("ffmpeg", path)
} }
func (r Repository) GetPathFfprobe() string { func (r Repository) GetPathFfprobe() (string, error) {
return r.settingRepository.GetValue("ffprobe") return r.settingRepository.GetValue("ffprobe")
} }
func (r Repository) SavePathFfprobe(path string) setting.Setting { func (r Repository) SavePathFfprobe(path string) (setting.Setting, error) {
return r.settingRepository.CreateOrUpdate("ffprobe", path) return r.settingRepository.CreateOrUpdate("ffprobe", path)
} }
func (r Repository) GetPathFfplay() string {
return r.settingRepository.GetValue("ffplay")
}
func (r Repository) SavePathFfplay(path string) setting.Setting {
return r.settingRepository.CreateOrUpdate("ffplay", path)
}

View File

@@ -7,6 +7,7 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor/view" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor/view"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
"image/color" "image/color"
) )
@@ -17,8 +18,7 @@ type ViewContract interface {
SelectFFPath( SelectFFPath(
ffmpegPath string, ffmpegPath string,
ffprobePath string, ffprobePath string,
ffplayPath string, save func(ffmpegPath string, ffprobePath string) error,
save func(ffmpegPath string, ffprobePath string, ffplayPath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error, donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) )
@@ -44,7 +44,9 @@ func NewView(app kernel.AppContract) *View {
} }
func (v View) Main(formConversion view.ConversionContract) { func (v View) Main(formConversion view.ConversionContract) {
converterVideoFilesTitle := v.app.GetLocalizerService().GetMessage("converterVideoFilesTitle") converterVideoFilesTitle := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "converterVideoFilesTitle",
})
v.app.GetWindow().SetContent(widget.NewCard(converterVideoFilesTitle, "", container.NewVScroll(formConversion.GetContent()))) v.app.GetWindow().SetContent(widget.NewCard(converterVideoFilesTitle, "", container.NewVScroll(formConversion.GetContent())))
formConversion.AfterViewContent() formConversion.AfterViewContent()
} }

View File

@@ -12,6 +12,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "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/kernel/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
"github.com/nicksnyder/go-i18n/v2/i18n"
"image/color" "image/color"
"os" "os"
"path/filepath" "path/filepath"
@@ -23,44 +24,44 @@ type ConversionContract interface {
} }
type Conversion struct { type Conversion struct {
app kernel.AppContract app kernel.AppContract
form *form form *form
conversionMessage *canvas.Text conversionMessage *canvas.Text
fileForConversion *fileForConversion fileForConversion *fileForConversion
directoryForSaving *directoryForSaving directoryForSaving *directoryForSaving
overwriteOutputFiles *overwriteOutputFiles overwriteOutputFiles *overwriteOutputFiles
selectEncoder *selectEncoder selectEncoder *selectEncoder
runConvert func(setting HandleConvertSetting) runConvert func(setting HandleConvertSetting)
itemsToConvertService kernel.ItemsToConvertContract
} }
type HandleConvertSetting struct { type HandleConvertSetting struct {
FileInput kernel.File
DirectoryForSave string DirectoryForSave string
OverwriteOutputFiles bool OverwriteOutputFiles bool
Format string Format string
Encoder encoder2.EncoderContract Encoder encoder2.EncoderContract
} }
func NewConversion(app kernel.AppContract, formats encoder.ConvertorFormatsContract, runConvert func(setting HandleConvertSetting), settingDirectoryForSaving setting.DirectoryForSavingContract, itemsToConvertService kernel.ItemsToConvertContract) *Conversion { 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 := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
conversionMessage.TextSize = 16 conversionMessage.TextSize = 16
conversionMessage.TextStyle = fyne.TextStyle{Bold: true} conversionMessage.TextStyle = fyne.TextStyle{Bold: true}
fileForConversion := newFileForConversion(app, itemsToConvertService) fileForConversion := newFileForConversion(app)
directoryForSaving := newDirectoryForSaving(app, settingDirectoryForSaving) directoryForSaving := newDirectoryForSaving(app, settingDirectoryForSaving)
overwriteOutputFiles := newOverwriteOutputFiles(app) overwriteOutputFiles := newOverwriteOutputFiles(app)
selectEncoder := newSelectEncoder(app, formats) selectEncoder := newSelectEncoder(app, formats)
items := []*widget.FormItem{ items := []*widget.FormItem{
{ {
Text: app.GetLocalizerService().GetMessage("fileForConversionTitle"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "fileForConversionTitle"}),
Widget: fileForConversion.button, Widget: fileForConversion.button,
}, },
{ {
Widget: container.NewHScroll(fileForConversion.message), Widget: container.NewHScroll(fileForConversion.message),
}, },
{ {
Text: app.GetLocalizerService().GetMessage("buttonForSelectedDirTitle"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "buttonForSelectedDirTitle"}),
Widget: directoryForSaving.button, Widget: directoryForSaving.button,
}, },
{ {
@@ -73,26 +74,25 @@ func NewConversion(app kernel.AppContract, formats encoder.ConvertorFormatsContr
Widget: selectEncoder.SelectFileType, Widget: selectEncoder.SelectFileType,
}, },
{ {
Text: app.GetLocalizerService().GetMessage("selectFormat"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "selectFormat"}),
Widget: selectEncoder.SelectFormat, Widget: selectEncoder.SelectFormat,
}, },
{ {
Text: app.GetLocalizerService().GetMessage("selectEncoder"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "selectEncoder"}),
Widget: selectEncoder.SelectEncoder, Widget: selectEncoder.SelectEncoder,
}, },
} }
form := newForm(app, items) form := newForm(app, items)
return &Conversion{ return &Conversion{
app: app, app: app,
form: form, form: form,
conversionMessage: conversionMessage, conversionMessage: conversionMessage,
fileForConversion: fileForConversion, fileForConversion: fileForConversion,
directoryForSaving: directoryForSaving, directoryForSaving: directoryForSaving,
overwriteOutputFiles: overwriteOutputFiles, overwriteOutputFiles: overwriteOutputFiles,
selectEncoder: selectEncoder, selectEncoder: selectEncoder,
runConvert: runConvert, runConvert: runConvert,
itemsToConvertService: itemsToConvertService,
} }
} }
@@ -121,41 +121,37 @@ func (c Conversion) changeEncoder(encoder encoder2.EncoderContract) {
} }
func (c Conversion) AfterViewContent() { func (c Conversion) AfterViewContent() {
if len(c.itemsToConvertService.GetItems()) == 0 { c.form.form.Disable()
c.form.form.Disable()
}
} }
func (c Conversion) selectFileForConversion(err error) { func (c Conversion) selectFileForConversion(err error) {
c.conversionMessage.Text = "" c.conversionMessage.Text = ""
if len(c.itemsToConvertService.GetItems()) == 0 { if err != nil {
if err != nil { c.form.form.Disable()
c.form.form.Disable() return
return
}
} }
c.form.form.Enable() c.form.form.Enable()
} }
func (c Conversion) submit() { func (c Conversion) submit() {
if len(c.itemsToConvertService.GetItems()) == 0 {
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage("errorNoFilesAddedForConversion")))
c.enableFormConversion()
return
}
if len(c.directoryForSaving.path) == 0 { if len(c.directoryForSaving.path) == 0 {
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage("errorSelectedFolderSave"))) showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorSelectedFolderSave",
})))
c.enableFormConversion() c.enableFormConversion()
return return
} }
if len(c.selectEncoder.SelectFormat.Selected) == 0 { if len(c.selectEncoder.SelectFormat.Selected) == 0 {
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage("errorSelectedFormat"))) showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorSelectedFormat",
})))
return return
} }
if c.selectEncoder.Encoder == nil { if c.selectEncoder.Encoder == nil {
showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage("errorSelectedEncoder"))) showConversionMessage(c.conversionMessage, errors.New(c.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorSelectedEncoder",
})))
return return
} }
c.conversionMessage.Text = "" c.conversionMessage.Text = ""
@@ -164,17 +160,18 @@ func (c Conversion) submit() {
c.directoryForSaving.button.Disable() c.directoryForSaving.button.Disable()
c.form.form.Disable() c.form.form.Disable()
c.runConvert(HandleConvertSetting{ setting := HandleConvertSetting{
FileInput: *c.fileForConversion.file,
DirectoryForSave: c.directoryForSaving.path, DirectoryForSave: c.directoryForSaving.path,
OverwriteOutputFiles: c.overwriteOutputFiles.IsChecked(), OverwriteOutputFiles: c.overwriteOutputFiles.IsChecked(),
Format: c.selectEncoder.SelectFormat.Selected, Format: c.selectEncoder.SelectFormat.Selected,
Encoder: c.selectEncoder.Encoder, Encoder: c.selectEncoder.Encoder,
}) }
c.runConvert(setting)
c.enableFormConversion() c.enableFormConversion()
if len(c.itemsToConvertService.GetItems()) == 0 { c.fileForConversion.message.Text = ""
c.form.form.Disable() c.form.form.Disable()
}
} }
func (c Conversion) enableFormConversion() { func (c Conversion) enableFormConversion() {
@@ -191,45 +188,44 @@ type fileForConversion struct {
changeCallbacks map[int]func(err error) changeCallbacks map[int]func(err error)
} }
func newFileForConversion(app kernel.AppContract, itemsToConvertService kernel.ItemsToConvertContract) *fileForConversion { func newFileForConversion(app kernel.AppContract) *fileForConversion {
message := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
fileForConversion := &fileForConversion{ fileForConversion := &fileForConversion{
message: message, file: &kernel.File{},
changeCallbacks: map[int]func(err error){}, changeCallbacks: map[int]func(err error){},
} }
buttonTitle := app.GetLocalizerService().GetMessage("choose") + "\n" + buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
app.GetLocalizerService().GetMessage("or") + "\n" + MessageID: "choose",
app.GetLocalizerService().GetMessage("dragAndDropFiles") }) + "\n\r\n\r" + app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "or",
}) + "\n\r\n\r" + app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "dragAndDrop1File",
})
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 var locationURI fyne.ListableURI
fileForConversion.button = widget.NewButton(buttonTitle, func() { fileForConversion.button = widget.NewButton(buttonTitle, func() {
app.GetWindow().NewFileOpen(func(r fyne.URIReadCloser, err error) { app.GetWindow().NewFileOpen(func(r fyne.URIReadCloser, err error) {
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
if err != nil { if err != nil {
fyne.Do(func() { fileForConversion.message.Text = err.Error()
fileForConversion.message.Text = err.Error() setStringErrorStyle(fileForConversion.message)
fileForConversion.message.Refresh()
})
fileForConversion.eventSelectFile(err) fileForConversion.eventSelectFile(err)
return return
} }
if r == nil { if r == nil {
return return
} }
app.GetWindow().GetLayout().GetRightTabs().SelectAddedFilesTab()
itemsToConvertService.Add(&kernel.File{ fileForConversion.file.Path = r.URI().Path()
Path: r.URI().Path(), fileForConversion.file.Name = r.URI().Name()
Name: r.URI().Name(), fileForConversion.file.Ext = r.URI().Extension()
Ext: r.URI().Extension(),
}) fileForConversion.message.Text = r.URI().Path()
setStringSuccessStyle(fileForConversion.message)
fileForConversion.eventSelectFile(nil) fileForConversion.eventSelectFile(nil)
@@ -243,40 +239,43 @@ func newFileForConversion(app kernel.AppContract, itemsToConvertService kernel.I
return return
} }
isError := false if len(uris) > 1 {
for _, uri := range uris { fileForConversion.message.Text = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
info, err := os.Stat(uri.Path()) MessageID: "errorDragAndDrop1File",
if err != nil {
isError = true
continue
}
if info.IsDir() {
isError = true
continue
}
itemsToConvertService.Add(&kernel.File{
Path: uri.Path(),
Name: uri.Name(),
Ext: uri.Extension(),
}) })
fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(uri.Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}
app.GetWindow().GetLayout().GetRightTabs().SelectAddedFilesTab()
if isError {
fileForConversion.message.Text = app.GetLocalizerService().GetMessage("errorDragAndDropFile")
setStringErrorStyle(fileForConversion.message) setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text)) fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text))
} else { return
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
} }
uri := uris[0]
info, err := os.Stat(uri.Path())
if err != nil {
fileForConversion.message.Text = err.Error()
setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(err)
return
}
if info.IsDir() {
fileForConversion.message.Text = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorIsFolder",
})
setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text))
return
}
fileForConversion.file.Path = uri.Path()
fileForConversion.file.Name = uri.Name()
fileForConversion.file.Ext = uri.Extension()
fileForConversion.message.Text = uri.Path()
setStringSuccessStyle(fileForConversion.message)
fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(uri.Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}) })
return fileForConversion return fileForConversion
@@ -307,7 +306,9 @@ func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving set
directoryForSaving.message.TextSize = 16 directoryForSaving.message.TextSize = 16
directoryForSaving.message.TextStyle = fyne.TextStyle{Bold: true} directoryForSaving.message.TextStyle = fyne.TextStyle{Bold: true}
buttonTitle := app.GetLocalizerService().GetMessage("choose") buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "choose",
})
var locationURI fyne.ListableURI var locationURI fyne.ListableURI
@@ -336,7 +337,7 @@ func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving set
locationURI, err = storage.ListerForURI(r) locationURI, err = storage.ListerForURI(r)
if err == nil { if err == nil {
_ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path()) _, _ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path())
} }
}, locationURI) }, locationURI)
@@ -346,7 +347,10 @@ func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving set
} }
func getDirectoryForSaving(settingDirectoryForSaving setting.DirectoryForSavingContract) (fyne.ListableURI, error) { func getDirectoryForSaving(settingDirectoryForSaving setting.DirectoryForSavingContract) (fyne.ListableURI, error) {
path := settingDirectoryForSaving.GetDirectoryForSaving() path, err := settingDirectoryForSaving.GetDirectoryForSaving()
if err != nil {
return nil, err
}
if len(path) > 0 { if len(path) > 0 {
path = "file://" + path path = "file://" + path
@@ -369,7 +373,9 @@ func newOverwriteOutputFiles(app kernel.AppContract) *overwriteOutputFiles {
overwriteOutputFiles := &overwriteOutputFiles{ overwriteOutputFiles := &overwriteOutputFiles{
isChecked: false, isChecked: false,
} }
checkboxOverwriteOutputFilesTitle := app.GetLocalizerService().GetMessage("checkboxOverwriteOutputFilesTitle") checkboxOverwriteOutputFilesTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "checkboxOverwriteOutputFilesTitle",
})
overwriteOutputFiles.checkbox = widget.NewCheck(checkboxOverwriteOutputFilesTitle, func(b bool) { overwriteOutputFiles.checkbox = widget.NewCheck(checkboxOverwriteOutputFilesTitle, func(b bool) {
overwriteOutputFiles.isChecked = b overwriteOutputFiles.isChecked = b
}) })
@@ -418,7 +424,7 @@ func newSelectEncoder(app kernel.AppContract, formats encoder.ConvertorFormatsCo
encoders = map[int]encoder2.EncoderDataContract{} encoders = map[int]encoder2.EncoderDataContract{}
for _, e := range format.GetEncoders() { for _, e := range format.GetEncoders() {
encoders[len(encoders)] = e encoders[len(encoders)] = e
encoderOptions = append(encoderOptions, app.GetLocalizerService().GetMessage("encoder_"+e.GetTitle())) encoderOptions = append(encoderOptions, app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoder_" + e.GetTitle()}))
} }
selectEncoder.SelectEncoder.SetOptions(encoderOptions) selectEncoder.SelectEncoder.SetOptions(encoderOptions)
selectEncoder.SelectEncoder.SetSelectedIndex(0) selectEncoder.SelectEncoder.SetSelectedIndex(0)
@@ -429,9 +435,9 @@ func newSelectEncoder(app kernel.AppContract, formats encoder.ConvertorFormatsCo
fileTypeOptions = append(fileTypeOptions, fileType.Name()) fileTypeOptions = append(fileTypeOptions, fileType.Name())
} }
encoderGroupVideo := app.GetLocalizerService().GetMessage("encoderGroupVideo") encoderGroupVideo := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupVideo"})
encoderGroupAudio := app.GetLocalizerService().GetMessage("encoderGroupAudio") encoderGroupAudio := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupAudio"})
encoderGroupImage := app.GetLocalizerService().GetMessage("encoderGroupImage") encoderGroupImage := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "encoderGroupImage"})
encoderGroup := map[string]string{ encoderGroup := map[string]string{
encoderGroupVideo: "video", encoderGroupVideo: "video",
encoderGroupAudio: "audio", encoderGroupAudio: "audio",
@@ -498,7 +504,9 @@ type form struct {
func newForm(app kernel.AppContract, items []*widget.FormItem) *form { func newForm(app kernel.AppContract, items []*widget.FormItem) *form {
f := widget.NewForm() f := widget.NewForm()
f.SubmitText = app.GetLocalizerService().GetMessage("converterVideoFilesSubmitTitle") f.SubmitText = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "converterVideoFilesSubmitTitle",
})
f.Items = items f.Items = items
return &form{ return &form{

View File

@@ -6,6 +6,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/h264_nvenc" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/h264_nvenc"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem { func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem {
@@ -44,7 +45,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
elementSelect.SetSelected(presetDefault) elementSelect.SetSelected(presetDefault)
elementSelect.Hide() elementSelect.Hide()
checkboxTitle := app.GetLocalizerService().GetMessage("parameterCheckbox") checkboxTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "parameterCheckbox"})
elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) {
if b == true { if b == true {
parameter.SetEnable() parameter.SetEnable()
@@ -57,7 +58,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
return []*widget.FormItem{ return []*widget.FormItem{
{ {
Text: app.GetLocalizerService().GetMessage("formPreset"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "formPreset"}),
Widget: container.NewVBox(elementCheckbox, elementSelect), Widget: container.NewVBox(elementCheckbox, elementSelect),
}, },
} }

View File

@@ -6,6 +6,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/libx264" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/libx264"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem { func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem {
@@ -27,7 +28,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
presetDefault := "" presetDefault := ""
for _, name := range libx264.Presets { for _, name := range libx264.Presets {
title := app.GetLocalizerService().GetMessage("preset_" + name) title := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "preset_" + name})
presetsForSelect = append(presetsForSelect, title) presetsForSelect = append(presetsForSelect, title)
presets[title] = name presets[title] = name
if name == parameter.Get() { if name == parameter.Get() {
@@ -44,7 +45,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
elementSelect.SetSelected(presetDefault) elementSelect.SetSelected(presetDefault)
elementSelect.Hide() elementSelect.Hide()
checkboxTitle := app.GetLocalizerService().GetMessage("parameterCheckbox") checkboxTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "parameterCheckbox"})
elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) {
if b == true { if b == true {
parameter.SetEnable() parameter.SetEnable()
@@ -57,7 +58,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
return []*widget.FormItem{ return []*widget.FormItem{
{ {
Text: app.GetLocalizerService().GetMessage("formPreset"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "formPreset"}),
Widget: container.NewVBox(elementCheckbox, elementSelect), Widget: container.NewVBox(elementCheckbox, elementSelect),
}, },
} }

View File

@@ -6,6 +6,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/libx265" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder/libx265"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem { func View(encoder encoder.EncoderContract, app kernel.AppContract) []*widget.FormItem {
@@ -27,7 +28,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
presetDefault := "" presetDefault := ""
for _, name := range libx265.Presets { for _, name := range libx265.Presets {
title := app.GetLocalizerService().GetMessage("preset_" + name) title := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "preset_" + name})
presetsForSelect = append(presetsForSelect, title) presetsForSelect = append(presetsForSelect, title)
presets[title] = name presets[title] = name
if name == parameter.Get() { if name == parameter.Get() {
@@ -44,7 +45,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
elementSelect.SetSelected(presetDefault) elementSelect.SetSelected(presetDefault)
elementSelect.Hide() elementSelect.Hide()
checkboxTitle := app.GetLocalizerService().GetMessage("parameterCheckbox") checkboxTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "parameterCheckbox"})
elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) {
if b == true { if b == true {
parameter.SetEnable() parameter.SetEnable()
@@ -57,7 +58,7 @@ func presetParameter(encoder encoder.EncoderContract, app kernel.AppContract) []
return []*widget.FormItem{ return []*widget.FormItem{
{ {
Text: app.GetLocalizerService().GetMessage("formPreset"), Text: app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{MessageID: "formPreset"}),
Widget: container.NewVBox(elementCheckbox, elementSelect), Widget: container.NewVBox(elementCheckbox, elementSelect),
}, },
} }

View File

@@ -6,6 +6,7 @@ import (
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"image/color" "image/color"
"net/url" "net/url"
"path/filepath" "path/filepath"
@@ -14,8 +15,7 @@ import (
func (v View) SelectFFPath( func (v View) SelectFFPath(
currentPathFfmpeg string, currentPathFfmpeg string,
currentPathFfprobe string, currentPathFfprobe string,
currentPathFfplay string, save func(ffmpegPath string, ffprobePath string) error,
save func(ffmpegPath string, ffprobePath string, ffplayPath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error, donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) { ) {
@@ -25,7 +25,6 @@ func (v View) SelectFFPath(
ffmpegPath, buttonFFmpeg, buttonFFmpegMessage := v.getButtonSelectFile(currentPathFfmpeg) ffmpegPath, buttonFFmpeg, buttonFFmpegMessage := v.getButtonSelectFile(currentPathFfmpeg)
ffprobePath, buttonFFprobe, buttonFFprobeMessage := v.getButtonSelectFile(currentPathFfprobe) ffprobePath, buttonFFprobe, buttonFFprobeMessage := v.getButtonSelectFile(currentPathFfprobe)
ffplayPath, buttonFFplay, buttonFFplayMessage := v.getButtonSelectFile(currentPathFfplay)
link := widget.NewHyperlink("https://ffmpeg.org/download.html", &url.URL{ link := widget.NewHyperlink("https://ffmpeg.org/download.html", &url.URL{
Scheme: "https", Scheme: "https",
@@ -36,37 +35,38 @@ func (v View) SelectFFPath(
form := &widget.Form{ form := &widget.Form{
Items: []*widget.FormItem{ Items: []*widget.FormItem{
{ {
Text: v.app.GetLocalizerService().GetMessage("titleDownloadLink"), Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "titleDownloadLink",
}),
Widget: link, Widget: link,
}, },
{ {
Text: v.app.GetLocalizerService().GetMessage("pathToFfmpeg"), Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "pathToFfmpeg",
}),
Widget: buttonFFmpeg, Widget: buttonFFmpeg,
}, },
{ {
Widget: container.NewHScroll(buttonFFmpegMessage), Widget: container.NewHScroll(buttonFFmpegMessage),
}, },
{ {
Text: v.app.GetLocalizerService().GetMessage("pathToFfprobe"), Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "pathToFfprobe",
}),
Widget: buttonFFprobe, Widget: buttonFFprobe,
}, },
{ {
Widget: container.NewHScroll(buttonFFprobeMessage), Widget: container.NewHScroll(buttonFFprobeMessage),
}, },
{
Text: v.app.GetLocalizerService().GetMessage("pathToFfplay"),
Widget: buttonFFplay,
},
{
Widget: container.NewHScroll(buttonFFplayMessage),
},
{ {
Widget: errorMessage, Widget: errorMessage,
}, },
}, },
SubmitText: v.app.GetLocalizerService().GetMessage("save"), SubmitText: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "save",
}),
OnSubmit: func() { OnSubmit: func() {
err := save(*ffmpegPath, *ffprobePath, *ffplayPath) err := save(*ffmpegPath, *ffprobePath)
if err != nil { if err != nil {
errorMessage.Text = err.Error() errorMessage.Text = err.Error()
} }
@@ -74,9 +74,13 @@ func (v View) SelectFFPath(
} }
if cancel != nil { if cancel != nil {
form.OnCancel = cancel form.OnCancel = cancel
form.CancelText = v.app.GetLocalizerService().GetMessage("cancel") form.CancelText = v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "cancel",
})
} }
selectFFPathTitle := v.app.GetLocalizerService().GetMessage("selectFFPathTitle") selectFFPathTitle := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "selectFFPathTitle",
})
if v.downloadFFmpeg.blockDownloadFFmpegContainer == nil { if v.downloadFFmpeg.blockDownloadFFmpegContainer == nil {
v.downloadFFmpeg.blockDownloadFFmpegContainer = v.blockDownloadFFmpeg(donwloadFFmpeg) v.downloadFFmpeg.blockDownloadFFmpegContainer = v.blockDownloadFFmpeg(donwloadFFmpeg)
@@ -95,7 +99,9 @@ func (v View) getButtonSelectFile(path string) (filePath *string, button *widget
buttonMessage.TextSize = 16 buttonMessage.TextSize = 16
buttonMessage.TextStyle = fyne.TextStyle{Bold: true} buttonMessage.TextStyle = fyne.TextStyle{Bold: true}
buttonTitle := v.app.GetLocalizerService().GetMessage("choose") buttonTitle := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "choose",
})
var locationURI fyne.ListableURI var locationURI fyne.ListableURI
if len(path) > 0 { if len(path) > 0 {

View File

@@ -8,6 +8,7 @@ import (
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/image/colornames" "golang.org/x/image/colornames"
"image/color" "image/color"
) )
@@ -28,7 +29,9 @@ func (v View) blockDownloadFFmpeg(
var buttonDownloadFFmpeg *widget.Button var buttonDownloadFFmpeg *widget.Button
buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage("download"), func() { buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "download",
}), func() {
fyne.Do(func() { fyne.Do(func() {
buttonDownloadFFmpeg.Disable() buttonDownloadFFmpeg.Disable()
}) })
@@ -44,11 +47,15 @@ func (v View) blockDownloadFFmpeg(
}) })
downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage("downloadFFmpegFromSite") downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadFFmpegFromSite",
})
return container.NewVBox( return container.NewVBox(
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
widget.NewCard(v.app.GetLocalizerService().GetMessage("buttonDownloadFFmpeg"), "", container.NewVBox( widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "buttonDownloadFFmpeg",
}), "", container.NewVBox(
widget.NewRichTextFromMarkdown( widget.NewRichTextFromMarkdown(
downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)", downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)",
), ),

View File

@@ -8,6 +8,7 @@ import (
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/image/colornames" "golang.org/x/image/colornames"
"image/color" "image/color"
) )
@@ -28,7 +29,9 @@ func (v View) blockDownloadFFmpeg(
var buttonDownloadFFmpeg *widget.Button var buttonDownloadFFmpeg *widget.Button
buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage("download"), func() { buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "download",
}), func() {
go func() { go func() {
fyne.Do(func() { fyne.Do(func() {
@@ -44,11 +47,15 @@ func (v View) blockDownloadFFmpeg(
}() }()
}) })
downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage("downloadFFmpegFromSite") downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadFFmpegFromSite",
})
return container.NewVBox( return container.NewVBox(
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
widget.NewCard(v.app.GetLocalizerService().GetMessage("buttonDownloadFFmpeg"), "", container.NewVBox( widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "buttonDownloadFFmpeg",
}), "", container.NewVBox(
widget.NewRichTextFromMarkdown( widget.NewRichTextFromMarkdown(
downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)", downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)",
), ),

2
data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

7
db/db.go Normal file
View File

@@ -0,0 +1,7 @@
package db
import "errors"
var (
ErrRecordNotFound = errors.New("record not found")
)

View File

@@ -5,6 +5,7 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
type ViewContract interface { type ViewContract interface {
@@ -22,7 +23,9 @@ func NewView(app kernel.AppContract) *View {
} }
func (v View) PanicError(err error) { func (v View) PanicError(err error) {
messageHead := v.app.GetLocalizerService().GetMessage("error") messageHead := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "error",
})
v.app.GetWindow().SetContent(container.NewBorder( v.app.GetWindow().SetContent(container.NewBorder(
container.NewVBox( container.NewVBox(
@@ -37,3 +40,25 @@ func (v View) PanicError(err error) {
}), }),
)) ))
} }
func (v View) PanicErrorWriteDirectoryData() {
message := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorDatabase",
})
messageHead := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "error",
})
v.app.GetWindow().SetContent(container.NewBorder(
container.NewVBox(
widget.NewLabel(messageHead),
widget.NewLabel(message),
),
nil,
nil,
nil,
localizer.LanguageSelectionForm(v.app.GetLocalizerService(), func(lang kernel.Lang) {
v.PanicErrorWriteDirectoryData()
}),
))
}

7
go.mod
View File

@@ -6,13 +6,16 @@ toolchain go1.23.9
require ( require (
fyne.io/fyne/v2 v2.6.1 fyne.io/fyne/v2 v2.6.1
github.com/BurntSushi/toml v1.5.0
github.com/nicksnyder/go-i18n/v2 v2.6.0
github.com/ulikunitz/xz v0.5.12 github.com/ulikunitz/xz v0.5.12
go.etcd.io/bbolt v1.4.0
golang.org/x/image v0.27.0 golang.org/x/image v0.27.0
golang.org/x/text v0.25.0
) )
require ( require (
fyne.io/systray v1.11.0 // indirect fyne.io/systray v1.11.0 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fredbi/uri v1.1.0 // indirect github.com/fredbi/uri v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
@@ -31,7 +34,6 @@ require (
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nicksnyder/go-i18n/v2 v2.6.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.4.1 // indirect github.com/rymdport/portal v0.4.1 // indirect
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
@@ -40,6 +42,5 @@ require (
github.com/yuin/goldmark v1.7.11 // indirect github.com/yuin/goldmark v1.7.11 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

4
go.sum
View File

@@ -67,10 +67,14 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w= golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g= golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=

View File

@@ -8,6 +8,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/helper" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/helper"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
type ConvertorHandlerContract interface { type ConvertorHandlerContract interface {
@@ -15,7 +16,6 @@ type ConvertorHandlerContract interface {
FfPathSelection() FfPathSelection()
GetFfmpegVersion() (string, error) GetFfmpegVersion() (string, error)
GetFfprobeVersion() (string, error) GetFfprobeVersion() (string, error)
GetFfplayVersion() (string, error)
} }
type ConvertorHandler struct { type ConvertorHandler struct {
@@ -24,7 +24,6 @@ type ConvertorHandler struct {
errorView error2.ViewContract errorView error2.ViewContract
convertorRepository convertor.RepositoryContract convertorRepository convertor.RepositoryContract
settingDirectoryForSaving setting.DirectoryForSavingContract settingDirectoryForSaving setting.DirectoryForSavingContract
itemsToConvertService kernel.ItemsToConvertContract
} }
func NewConvertorHandler( func NewConvertorHandler(
@@ -33,7 +32,6 @@ func NewConvertorHandler(
errorView error2.ViewContract, errorView error2.ViewContract,
convertorRepository convertor.RepositoryContract, convertorRepository convertor.RepositoryContract,
settingDirectoryForSaving setting.DirectoryForSavingContract, settingDirectoryForSaving setting.DirectoryForSavingContract,
itemsToConvertService kernel.ItemsToConvertContract,
) *ConvertorHandler { ) *ConvertorHandler {
return &ConvertorHandler{ return &ConvertorHandler{
app: app, app: app,
@@ -41,7 +39,6 @@ func NewConvertorHandler(
errorView: errorView, errorView: errorView,
convertorRepository: convertorRepository, convertorRepository: convertorRepository,
settingDirectoryForSaving: settingDirectoryForSaving, settingDirectoryForSaving: settingDirectoryForSaving,
itemsToConvertService: itemsToConvertService,
} }
} }
@@ -52,18 +49,17 @@ func (h ConvertorHandler) MainConvertor() {
h.errorView.PanicError(err) h.errorView.PanicError(err)
return return
} }
conversion := view.NewConversion(h.app, formats, h.runConvert, h.settingDirectoryForSaving, h.itemsToConvertService) conversion := view.NewConversion(h.app, formats, h.runConvert, h.settingDirectoryForSaving)
h.convertorView.Main(conversion) h.convertorView.Main(conversion)
return return
} }
h.convertorView.SelectFFPath("", "", "", h.saveSettingFFPath, nil, h.downloadFFmpeg) h.convertorView.SelectFFPath("", "", h.saveSettingFFPath, nil, h.downloadFFmpeg)
} }
func (h ConvertorHandler) FfPathSelection() { func (h ConvertorHandler) FfPathSelection() {
ffmpeg := h.convertorRepository.GetPathFfmpeg() ffmpeg, _ := h.convertorRepository.GetPathFfmpeg()
ffprobe := h.convertorRepository.GetPathFfprobe() ffprobe, _ := h.convertorRepository.GetPathFfprobe()
ffplay := h.convertorRepository.GetPathFfplay() h.convertorView.SelectFFPath(ffmpeg, ffprobe, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg)
h.convertorView.SelectFFPath(ffmpeg, ffprobe, ffplay, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg)
} }
func (h ConvertorHandler) GetFfmpegVersion() (string, error) { func (h ConvertorHandler) GetFfmpegVersion() (string, error) {
@@ -74,31 +70,17 @@ func (h ConvertorHandler) GetFfprobeVersion() (string, error) {
return h.app.GetConvertorService().GetFFprobeVersion() return h.app.GetConvertorService().GetFFprobeVersion()
} }
func (h ConvertorHandler) GetFfplayVersion() (string, error) {
return h.app.GetConvertorService().GetFFplayVersion()
}
func (h ConvertorHandler) runConvert(setting view.HandleConvertSetting) { func (h ConvertorHandler) runConvert(setting view.HandleConvertSetting) {
h.app.GetWindow().GetLayout().GetRightTabs().SelectFileQueueTab() h.app.GetQueue().Add(&kernel.ConvertSetting{
VideoFileInput: setting.FileInput,
for _, item := range h.itemsToConvertService.GetItems() { VideoFileOut: kernel.File{
file := item.GetFile() Path: setting.DirectoryForSave + helper.PathSeparator() + setting.FileInput.Name + "." + setting.Format,
if file == nil { Name: setting.FileInput.Name,
continue Ext: "." + setting.Format,
} },
OverwriteOutputFiles: setting.OverwriteOutputFiles,
h.app.GetQueue().Add(&kernel.ConvertSetting{ Encoder: setting.Encoder,
VideoFileInput: *file, })
VideoFileOut: kernel.File{
Path: setting.DirectoryForSave + helper.PathSeparator() + file.Name + "." + setting.Format,
Name: file.Name,
Ext: "." + setting.Format,
},
OverwriteOutputFiles: setting.OverwriteOutputFiles,
Encoder: setting.Encoder,
})
}
h.itemsToConvertService.AfterAddingQueue()
} }
func (h ConvertorHandler) checkingFFPathUtilities() bool { func (h ConvertorHandler) checkingFFPathUtilities() bool {
@@ -116,42 +98,33 @@ func (h ConvertorHandler) checkingFFPathUtilities() bool {
if ffprobeChecking == false { if ffprobeChecking == false {
continue continue
} }
_, _ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg)
ffplayChecking, _ := h.app.GetConvertorService().ChangeFFplayPath(item.FFplay) _, _ = h.convertorRepository.SavePathFfprobe(item.FFprobe)
if ffplayChecking == false {
continue
}
_ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg)
_ = h.convertorRepository.SavePathFfprobe(item.FFprobe)
_ = h.convertorRepository.SavePathFfplay(item.FFplay)
return true return true
} }
return false return false
} }
func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string, ffplayPath string) error { func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string) error {
ffmpegChecking, _ := h.app.GetConvertorService().ChangeFFmpegPath(ffmpegPath) ffmpegChecking, _ := h.app.GetConvertorService().ChangeFFmpegPath(ffmpegPath)
if ffmpegChecking == false { if ffmpegChecking == false {
errorText := h.app.GetLocalizerService().GetMessage("errorFFmpeg") errorText := h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorFFmpeg",
})
return errors.New(errorText) return errors.New(errorText)
} }
ffprobeChecking, _ := h.app.GetConvertorService().ChangeFFprobePath(ffprobePath) ffprobeChecking, _ := h.app.GetConvertorService().ChangeFFprobePath(ffprobePath)
if ffprobeChecking == false { if ffprobeChecking == false {
errorText := h.app.GetLocalizerService().GetMessage("errorFFprobe") errorText := h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorFFprobe",
})
return errors.New(errorText) return errors.New(errorText)
} }
ffplayChecking, _ := h.app.GetConvertorService().ChangeFFplayPath(ffplayPath) _, _ = h.convertorRepository.SavePathFfmpeg(ffmpegPath)
if ffplayChecking == false { _, _ = h.convertorRepository.SavePathFfprobe(ffprobePath)
errorText := h.app.GetLocalizerService().GetMessage("errorFFplay")
return errors.New(errorText)
}
_ = h.convertorRepository.SavePathFfmpeg(ffmpegPath)
_ = h.convertorRepository.SavePathFfprobe(ffprobePath)
_ = h.convertorRepository.SavePathFfplay(ffplayPath)
h.MainConvertor() h.MainConvertor()
@@ -169,10 +142,5 @@ func (h ConvertorHandler) checkingFFPath() bool {
return false return false
} }
_, err = h.app.GetConvertorService().GetFFplayVersion()
if err != nil {
return false
}
return true return true
} }

View File

@@ -10,7 +10,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{FFmpeg: "ffmpeg/bin/ffmpeg", FFprobe: "ffmpeg/bin/ffprobe", FFplay: "ffmpeg/bin/ffplay"}, {FFmpeg: "ffmpeg", FFprobe: "ffprobe", FFplay: "ffplay"}} return []kernel.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {

View File

@@ -10,6 +10,7 @@ import (
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/ulikunitz/xz" "github.com/ulikunitz/xz"
"io" "io"
"net/http" "net/http"
@@ -18,7 +19,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{FFmpeg: "ffmpeg/bin/ffmpeg", FFprobe: "ffmpeg/bin/ffprobe", FFplay: "ffmpeg/bin/ffplay"}, {FFmpeg: "ffmpeg", FFprobe: "ffprobe", FFplay: "ffplay"}} return []kernel.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
@@ -29,7 +30,9 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
return err return err
} }
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("downloadRun") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadRun",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
@@ -38,7 +41,9 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
return err return err
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("unzipRun") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "unzipRun",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
@@ -48,21 +53,21 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
} }
_ = os.Remove("ffmpeg/ffmpeg.tar.xz") _ = os.Remove("ffmpeg/ffmpeg.tar.xz")
progressMessage.Text = h.app.GetLocalizerService().GetMessage("testFF") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "testFF",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
err = h.saveSettingFFPath( err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg", "ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffprobe")
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg",
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffprobe",
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffplay",
)
if err != nil { if err != nil {
return err return err
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("completedQueue") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "completedQueue",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
@@ -212,12 +217,6 @@ func unTarXz(fileTar string, directory string, progressBar *widget.ProgressBar)
return err return err
} }
ffplayPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffplay")
err = os.Chmod(ffplayPath, 0755)
if err != nil {
return err
}
return nil return nil
} }

View File

@@ -10,6 +10,7 @@ import (
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
"io" "io"
"net/http" "net/http"
"os" "os"
@@ -18,7 +19,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{FFmpeg: "ffmpeg\\bin\\ffmpeg.exe", FFprobe: "ffmpeg\\bin\\ffprobe.exe", FFplay: "ffmpeg\\bin\\ffplay.exe"}} return []kernel.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
@@ -29,7 +30,9 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
return err return err
} }
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("downloadRun") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadRun",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
@@ -38,7 +41,9 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
return err return err
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("unzipRun") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "unzipRun",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
@@ -48,20 +53,20 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
} }
_ = os.Remove("ffmpeg/ffmpeg.zip") _ = os.Remove("ffmpeg/ffmpeg.zip")
progressMessage.Text = h.app.GetLocalizerService().GetMessage("testFF") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "testFF",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
err = h.saveSettingFFPath( err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", "ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe")
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe",
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe",
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffplay.exe",
)
if err != nil { if err != nil {
return err return err
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage("completedQueue") progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "completedQueue",
})
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })

View File

@@ -2,31 +2,37 @@ package handler
import ( import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
) )
type MainHandler struct { type MainHandler struct {
app kernel.AppContract app kernel.AppContract
convertorHandler ConvertorHandlerContract convertorHandler ConvertorHandlerContract
menuHandler MenuHandlerContract menuHandler MenuHandlerContract
localizerRepository localizer.RepositoryContract
} }
func NewMainHandler( func NewMainHandler(
app kernel.AppContract, app kernel.AppContract,
convertorHandler ConvertorHandlerContract, convertorHandler ConvertorHandlerContract,
menuHandler MenuHandlerContract, menuHandler MenuHandlerContract,
localizerRepository localizer.RepositoryContract,
) *MainHandler { ) *MainHandler {
return &MainHandler{ return &MainHandler{
app: app, app: app,
convertorHandler: convertorHandler, convertorHandler: convertorHandler,
menuHandler: menuHandler, menuHandler: menuHandler,
localizerRepository: localizerRepository,
} }
} }
func (h MainHandler) Start() { func (h MainHandler) Start() {
if h.app.GetLocalizerService().IsStartWithLanguageSelection() { language, err := h.localizerRepository.GetCode()
if err != nil {
h.menuHandler.LanguageSelection() h.menuHandler.LanguageSelection()
return return
} }
_ = h.app.GetLocalizerService().SetCurrentLanguageByCode(language)
h.convertorHandler.MainConvertor() h.convertorHandler.MainConvertor()
} }

View File

@@ -5,7 +5,7 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme" "github.com/nicksnyder/go-i18n/v2/i18n"
) )
type MenuHandlerContract interface { type MenuHandlerContract interface {
@@ -14,29 +14,26 @@ type MenuHandlerContract interface {
} }
type MenuHandler struct { type MenuHandler struct {
app kernel.AppContract app kernel.AppContract
convertorHandler ConvertorHandlerContract convertorHandler ConvertorHandlerContract
menuView menu.ViewContract menuView menu.ViewContract
menuViewSetting menu.ViewSettingContract localizerView localizer.ViewContract
localizerView localizer.ViewContract localizerRepository localizer.RepositoryContract
themeService theme.ThemeContract
} }
func NewMenuHandler( func NewMenuHandler(
app kernel.AppContract, app kernel.AppContract,
convertorHandler ConvertorHandlerContract, convertorHandler ConvertorHandlerContract,
menuView menu.ViewContract, menuView menu.ViewContract,
menuViewSetting menu.ViewSettingContract,
localizerView localizer.ViewContract, localizerView localizer.ViewContract,
themeService theme.ThemeContract, localizerRepository localizer.RepositoryContract,
) *MenuHandler { ) *MenuHandler {
return &MenuHandler{ return &MenuHandler{
app: app, app: app,
convertorHandler: convertorHandler, convertorHandler: convertorHandler,
menuView: menuView, menuView: menuView,
menuViewSetting: menuViewSetting, localizerView: localizerView,
localizerView: localizerView, localizerRepository: localizerRepository,
themeService: themeService,
} }
} }
@@ -48,23 +45,31 @@ func (h MenuHandler) GetMainMenu() *fyne.MainMenu {
} }
func (h MenuHandler) getMenuSettings() *fyne.Menu { func (h MenuHandler) getMenuSettings() *fyne.Menu {
quit := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("exit"), nil) quit := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "exit",
}), nil)
quit.IsQuit = true quit.IsQuit = true
h.app.GetLocalizerService().AddChangeCallback("exit", func(text string) { h.app.GetLocalizerService().AddChangeCallback("exit", func(text string) {
quit.Label = text quit.Label = text
}) })
settingsSelection := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("settings"), h.settingsSelection) languageSelection := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
h.app.GetLocalizerService().AddChangeCallback("settings", func(text string) { MessageID: "changeLanguage",
settingsSelection.Label = text }), h.LanguageSelection)
h.app.GetLocalizerService().AddChangeCallback("changeLanguage", func(text string) {
languageSelection.Label = text
}) })
ffPathSelection := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("changeFFPath"), h.convertorHandler.FfPathSelection) ffPathSelection := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "changeFFPath",
}), h.convertorHandler.FfPathSelection)
h.app.GetLocalizerService().AddChangeCallback("changeFFPath", func(text string) { h.app.GetLocalizerService().AddChangeCallback("changeFFPath", func(text string) {
ffPathSelection.Label = text ffPathSelection.Label = text
}) })
settings := fyne.NewMenu(h.app.GetLocalizerService().GetMessage("settings"), settingsSelection, ffPathSelection, quit) settings := fyne.NewMenu(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "settings",
}), languageSelection, ffPathSelection, quit)
h.app.GetLocalizerService().AddChangeCallback("settings", func(text string) { h.app.GetLocalizerService().AddChangeCallback("settings", func(text string) {
settings.Label = text settings.Label = text
settings.Refresh() settings.Refresh()
@@ -74,22 +79,23 @@ func (h MenuHandler) getMenuSettings() *fyne.Menu {
} }
func (h MenuHandler) getMenuHelp() *fyne.Menu { func (h MenuHandler) getMenuHelp() *fyne.Menu {
about := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("about"), h.openAbout) about := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "about",
}), h.openAbout)
h.app.GetLocalizerService().AddChangeCallback("about", func(text string) { h.app.GetLocalizerService().AddChangeCallback("about", func(text string) {
about.Label = text about.Label = text
}) })
gratitude := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("gratitude"), h.menuView.Gratitude) gratitude := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}), h.openGratitude)
h.app.GetLocalizerService().AddChangeCallback("gratitude", func(text string) { h.app.GetLocalizerService().AddChangeCallback("gratitude", func(text string) {
gratitude.Label = text gratitude.Label = text
}) })
helpFFplay := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage("helpFFplay"), h.menuView.HelpFFplay) help := fyne.NewMenu(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
h.app.GetLocalizerService().AddChangeCallback("helpFFplay", func(text string) { MessageID: "help",
helpFFplay.Label = text }), about, gratitude)
})
help := fyne.NewMenu(h.app.GetLocalizerService().GetMessage("help"), helpFFplay, about, gratitude)
h.app.GetLocalizerService().AddChangeCallback("help", func(text string) { h.app.GetLocalizerService().AddChangeCallback("help", func(text string) {
help.Label = text help.Label = text
help.Refresh() help.Refresh()
@@ -101,43 +107,27 @@ func (h MenuHandler) getMenuHelp() *fyne.Menu {
func (h MenuHandler) openAbout() { func (h MenuHandler) openAbout() {
ffmpeg, err := h.convertorHandler.GetFfmpegVersion() ffmpeg, err := h.convertorHandler.GetFfmpegVersion()
if err != nil { if err != nil {
ffmpeg = h.app.GetLocalizerService().GetMessage("errorFFmpegVersion") ffmpeg = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorFFmpegVersion",
})
} }
ffprobe, err := h.convertorHandler.GetFfprobeVersion() ffprobe, err := h.convertorHandler.GetFfprobeVersion()
if err != nil { if err != nil {
ffprobe = h.app.GetLocalizerService().GetMessage("errorFFprobeVersion") ffprobe = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
} MessageID: "errorFFprobeVersion",
ffplay, err := h.convertorHandler.GetFfplayVersion() })
if err != nil {
ffplay = h.app.GetLocalizerService().GetMessage("errorFFplayVersion")
} }
h.menuView.About(ffmpeg, ffprobe, ffplay) h.menuView.About(ffmpeg, ffprobe)
}
func (h MenuHandler) openGratitude() {
h.menuView.Gratitude()
} }
func (h MenuHandler) LanguageSelection() { func (h MenuHandler) LanguageSelection() {
h.localizerView.LanguageSelection(func(lang kernel.Lang) { h.localizerView.LanguageSelection(func(lang kernel.Lang) {
_, _ = h.localizerRepository.Save(lang.Code)
h.convertorHandler.MainConvertor() h.convertorHandler.MainConvertor()
}) })
} }
func (h MenuHandler) settingsSelection() {
save := func(setting *menu.SettingForm) error {
err := h.app.GetLocalizerService().SetCurrentLanguage(setting.Language, true)
if err != nil {
return err
}
err = h.themeService.SetCurrentTheme(setting.ThemeInfo)
if err != nil {
return err
}
h.convertorHandler.MainConvertor()
return nil
}
cancel := func() {
h.convertorHandler.MainConvertor()
}
h.menuViewSetting.Main(save, cancel)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -1,13 +0,0 @@
package resources
import (
_ "embed"
"fyne.io/fyne/v2"
)
//go:embed icons/logo.png
var iconAppLogo []byte
func IconAppLogoResource() *fyne.StaticResource {
return fyne.NewStaticResource("icon.png", iconAppLogo)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -12,7 +12,6 @@ type AppContract interface {
GetQueue() QueueListContract GetQueue() QueueListContract
GetLocalizerService() LocalizerContract GetLocalizerService() LocalizerContract
GetConvertorService() ConvertorContract GetConvertorService() ConvertorContract
GetFFplayService() FFplayContract
AfterClosing() AfterClosing()
RunConvertor() RunConvertor()
} }
@@ -22,41 +21,27 @@ type App struct {
Window WindowContract Window WindowContract
Queue QueueListContract Queue QueueListContract
localizerService LocalizerContract localizerService LocalizerContract
convertorService ConvertorContract convertorService ConvertorContract
blockProgressbarService BlockProgressbarContract
ffplayService FFplayContract
} }
func NewApp( func NewApp(
metadata *fyne.AppMetadata, metadata *fyne.AppMetadata,
localizerService LocalizerContract,
queue QueueListContract, queue QueueListContract,
ffplayService FFplayContract, queueLayoutObject QueueLayoutObjectContract,
convertorService ConvertorContract, convertorService ConvertorContract,
) *App { ) *App {
app.SetMetadata(*metadata) app.SetMetadata(*metadata)
a := app.New() a := app.New()
localizerService, err := newLocalizer(a)
if err != nil {
panicErrorLang(a, err)
return nil
}
statusesText := GetBlockProgressbarStatusesText(localizerService)
blockProgressbarService := NewBlockProgressbar(statusesText, ffplayService)
rightTabsService := NewRightTabs(localizerService)
queueLayoutObject := NewQueueLayoutObject(queue, localizerService, ffplayService, rightTabsService, blockProgressbarService.GetContainer())
return &App{ return &App{
AppFyne: a, AppFyne: a,
Window: newWindow(a.NewWindow("GUI for FFmpeg"), NewLayout(queueLayoutObject, localizerService, rightTabsService)), Window: newWindow(a.NewWindow("GUI for FFmpeg"), NewLayout(queueLayoutObject, localizerService)),
Queue: queue, Queue: queue,
localizerService: localizerService, localizerService: localizerService,
convertorService: convertorService, convertorService: convertorService,
blockProgressbarService: blockProgressbarService,
ffplayService: ffplayService,
} }
} }
@@ -80,10 +65,6 @@ func (a App) GetConvertorService() ConvertorContract {
return a.convertorService return a.convertorService
} }
func (a App) GetFFplayService() FFplayContract {
return a.ffplayService
}
func (a App) AfterClosing() { func (a App) AfterClosing() {
for _, cmd := range a.convertorService.GetRunningProcesses() { for _, cmd := range a.convertorService.GetRunningProcesses() {
_ = cmd.Process.Kill() _ = cmd.Process.Kill()
@@ -100,33 +81,22 @@ func (a App) RunConvertor() {
} }
queue.Status = StatusType(InProgress) queue.Status = StatusType(InProgress)
a.Window.GetLayout().ChangeQueueStatus(queueId, queue) a.Window.GetLayout().ChangeQueueStatus(queueId, queue)
if a.blockProgressbarService.GetContainer().Hidden {
a.blockProgressbarService.GetContainer().Show()
}
totalDuration, err := a.convertorService.GetTotalDuration(&queue.Setting.VideoFileInput) totalDuration, err := a.convertorService.GetTotalDuration(&queue.Setting.VideoFileInput)
if err != nil { if err != nil {
totalDuration = 0 totalDuration = 0
} }
progress := a.Window.GetLayout().NewProgressbar(queueId, totalDuration)
progress := a.blockProgressbarService.GetProgressbar(
totalDuration,
queue.Setting.VideoFileInput.Path,
a.localizerService,
)
err = a.convertorService.RunConvert(*queue.Setting, progress) err = a.convertorService.RunConvert(*queue.Setting, progress)
if err != nil { if err != nil {
queue.Status = StatusType(Error) queue.Status = StatusType(Error)
queue.Error = err queue.Error = err
a.Window.GetLayout().ChangeQueueStatus(queueId, queue) a.Window.GetLayout().ChangeQueueStatus(queueId, queue)
a.blockProgressbarService.ProcessEndedWithError(err.Error())
continue continue
} }
queue.Status = StatusType(Completed) queue.Status = StatusType(Completed)
a.Window.GetLayout().ChangeQueueStatus(queueId, queue) a.Window.GetLayout().ChangeQueueStatus(queueId, queue)
a.blockProgressbarService.ProcessEndedWithSuccess(queue.Setting.VideoFileOut.Path)
} }
}() }()
} }

View File

@@ -32,10 +32,8 @@ type ConvertorContract interface {
GetTotalDuration(file *File) (float64, error) GetTotalDuration(file *File) (float64, error)
GetFFmpegVesrion() (string, error) GetFFmpegVesrion() (string, error)
GetFFprobeVersion() (string, error) GetFFprobeVersion() (string, error)
GetFFplayVersion() (string, error)
ChangeFFmpegPath(path string) (bool, error) ChangeFFmpegPath(path string) (bool, error)
ChangeFFprobePath(path string) (bool, error) ChangeFFprobePath(path string) (bool, error)
ChangeFFplayPath(path string) (bool, error)
GetRunningProcesses() map[int]*exec.Cmd GetRunningProcesses() map[int]*exec.Cmd
GetSupportFormats() (encoder.ConvertorFormatsContract, error) GetSupportFormats() (encoder.ConvertorFormatsContract, error)
} }
@@ -48,7 +46,6 @@ type ProgressContract interface {
type FFPathUtilities struct { type FFPathUtilities struct {
FFmpeg string FFmpeg string
FFprobe string FFprobe string
FFplay string
} }
type runningProcesses struct { type runningProcesses struct {
@@ -180,17 +177,6 @@ func (s Convertor) GetFFprobeVersion() (string, error) {
return text[0], nil return text[0], nil
} }
func (s Convertor) GetFFplayVersion() (string, error) {
cmd := exec.Command(s.ffPathUtilities.FFplay, "-version")
helper.PrepareBackgroundCommand(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
text := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1)
return text[0], nil
}
func (s Convertor) ChangeFFmpegPath(path string) (bool, error) { func (s Convertor) ChangeFFmpegPath(path string) (bool, error) {
cmd := exec.Command(path, "-version") cmd := exec.Command(path, "-version")
helper.PrepareBackgroundCommand(cmd) helper.PrepareBackgroundCommand(cmd)
@@ -219,20 +205,6 @@ func (s Convertor) ChangeFFprobePath(path string) (bool, error) {
return true, nil return true, nil
} }
func (s Convertor) ChangeFFplayPath(path string) (bool, error) {
cmd := exec.Command(path, "-version")
helper.PrepareBackgroundCommand(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
return false, err
}
if strings.Contains(strings.TrimSpace(string(out)), "ffplay") == false {
return false, nil
}
s.ffPathUtilities.FFplay = path
return true, nil
}
func (s Convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error) { func (s Convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error) {
formats := encoder.NewConvertorFormats() formats := encoder.NewConvertorFormats()
cmd := exec.Command(s.ffPathUtilities.FFmpeg, "-encoders") cmd := exec.Command(s.ffPathUtilities.FFmpeg, "-encoders")

View File

@@ -2,11 +2,14 @@ package kernel
import ( import (
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
func panicErrorLang(a fyne.App, err error) { func PanicErrorLang(err error, metadata *fyne.AppMetadata) {
app.SetMetadata(*metadata)
a := app.New()
window := a.NewWindow("GUI for FFmpeg") window := a.NewWindow("GUI for FFmpeg")
window.SetContent(container.NewVBox( window.SetContent(container.NewVBox(
widget.NewLabel("Произошла ошибка!"), widget.NewLabel("Произошла ошибка!"),

View File

@@ -1,28 +0,0 @@
package kernel
import (
"os/exec"
)
type FFplay struct {
ffPathUtilities *FFPathUtilities
}
type FFplaySetting struct {
PathToFile string
}
type FFplayContract interface {
Run(setting FFplaySetting) error
}
func NewFFplay(ffPathUtilities *FFPathUtilities) *FFplay {
return &FFplay{ffPathUtilities: ffPathUtilities}
}
func (ffplay FFplay) Run(setting FFplaySetting) error {
args := []string{setting.PathToFile}
cmd := exec.Command(ffplay.ffPathUtilities.FFplay, args...)
return cmd.Start()
}

View File

@@ -1,152 +0,0 @@
package kernel
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
type ItemsToConvertContract interface {
Add(file *File)
GetItems() map[int]ItemToConvertContract
AfterAddingQueue()
}
type ItemsToConvert struct {
nextId int
items map[int]ItemToConvertContract
itemsContainer *fyne.Container
ffplayService FFplayContract
isAutoRemove bool
}
func NewItemsToConvert(itemsContainer *fyne.Container, ffplayService FFplayContract, localizerService LocalizerContract) *ItemsToConvert {
containerForItems := container.NewVBox()
ItemsToConvert := &ItemsToConvert{
nextId: 0,
items: map[int]ItemToConvertContract{},
itemsContainer: containerForItems,
ffplayService: ffplayService,
isAutoRemove: true,
}
line := canvas.NewLine(theme.Color(theme.ColorNameFocus))
line.StrokeWidth = 5
checkboxAutoRemove := widget.NewCheck(
localizerService.GetMessage("autoClearAfterAddingToQueue"),
func(checked bool) {
ItemsToConvert.isAutoRemove = checked
},
)
checkboxAutoRemove.SetChecked(ItemsToConvert.isAutoRemove)
localizerService.AddChangeCallback("autoClearAfterAddingToQueue", func(text string) {
checkboxAutoRemove.Text = text
})
buttonClear := widget.NewButton(
localizerService.GetMessage("clearAll"),
func() {
ItemsToConvert.clear()
},
)
buttonClear.Importance = widget.DangerImportance
localizerService.AddChangeCallback("clearAll", func(text string) {
buttonClear.Text = text
})
itemsContainer.Add(container.NewVBox(
container.NewPadded(),
container.NewBorder(nil, nil, nil, buttonClear, container.NewHScroll(checkboxAutoRemove)),
container.NewPadded(),
line,
container.NewPadded(),
containerForItems,
))
return ItemsToConvert
}
func (items *ItemsToConvert) Add(file *File) {
nextId := items.nextId
var content *fyne.Container
var buttonPlay *widget.Button
buttonPlay = widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() {
buttonPlay.Disable()
go func() {
_ = items.ffplayService.Run(FFplaySetting{
PathToFile: file.Path,
})
fyne.Do(func() {
buttonPlay.Enable()
})
}()
})
buttonRemove := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameDelete), func() {
items.itemsContainer.Remove(content)
items.itemsContainer.Refresh()
delete(items.items, nextId)
})
buttonRemove.Importance = widget.DangerImportance
content = container.NewVBox(
container.NewBorder(
nil,
nil,
buttonPlay,
buttonRemove,
container.NewHScroll(widget.NewLabel(file.Name)),
),
container.NewHScroll(widget.NewLabel(file.Path)),
container.NewPadded(),
canvas.NewLine(theme.Color(theme.ColorNameFocus)),
container.NewPadded(),
)
items.itemsContainer.Add(content)
items.items[nextId] = NewItemToConvert(file, content)
items.nextId++
}
func (items *ItemsToConvert) GetItems() map[int]ItemToConvertContract {
return items.items
}
func (items *ItemsToConvert) AfterAddingQueue() {
if items.isAutoRemove {
items.clear()
}
}
func (items *ItemsToConvert) clear() {
items.itemsContainer.RemoveAll()
items.items = map[int]ItemToConvertContract{}
}
type ItemToConvertContract interface {
GetFile() *File
GetContent() *fyne.Container
}
type ItemToConvert struct {
file *File
content *fyne.Container
}
func NewItemToConvert(file *File, content *fyne.Container) *ItemToConvert {
return &ItemToConvert{
file: file,
content: content,
}
}
func (item ItemToConvert) GetFile() *File {
return item.file
}
func (item ItemToConvert) GetContent() *fyne.Container {
return item.content
}

View File

@@ -1,37 +1,40 @@
package kernel package kernel
import ( import (
"bufio"
"errors"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"image/color" "image/color"
"io"
"regexp"
"strconv" "strconv"
"strings" "strings"
) )
type LayoutContract interface { type LayoutContract interface {
SetContent(content fyne.CanvasObject) *fyne.Container SetContent(content fyne.CanvasObject) *fyne.Container
NewProgressbar(queueId int, totalDuration float64) ProgressContract
ChangeQueueStatus(queueId int, queue *Queue) ChangeQueueStatus(queueId int, queue *Queue)
GetRightTabs() RightTabsContract
} }
type Layout struct { type Layout struct {
layout *fyne.Container layout *fyne.Container
queueLayoutObject QueueLayoutObjectContract queueLayoutObject QueueLayoutObjectContract
localizerService LocalizerContract localizerService LocalizerContract
rightTabsService RightTabsContract
} }
func NewLayout(queueLayoutObject QueueLayoutObjectContract, localizerService LocalizerContract, rightTabsService RightTabsContract) *Layout { func NewLayout(queueLayoutObject QueueLayoutObjectContract, localizerService LocalizerContract) *Layout {
layout := container.NewAdaptiveGrid(2, widget.NewLabel(""), queueLayoutObject.GetCanvasObject()) layout := container.NewAdaptiveGrid(2, widget.NewLabel(""), container.NewVScroll(queueLayoutObject.GetCanvasObject()))
return &Layout{ return &Layout{
layout: layout, layout: layout,
queueLayoutObject: queueLayoutObject, queueLayoutObject: queueLayoutObject,
localizerService: localizerService, localizerService: localizerService,
rightTabsService: rightTabsService,
} }
} }
@@ -40,16 +43,18 @@ func (l Layout) SetContent(content fyne.CanvasObject) *fyne.Container {
return l.layout return l.layout
} }
func (l Layout) NewProgressbar(queueId int, totalDuration float64) ProgressContract {
progressbar := l.queueLayoutObject.GetProgressbar(queueId)
return NewProgress(totalDuration, progressbar, l.localizerService)
}
func (l Layout) ChangeQueueStatus(queueId int, queue *Queue) { func (l Layout) ChangeQueueStatus(queueId int, queue *Queue) {
l.queueLayoutObject.ChangeQueueStatus(queueId, queue) l.queueLayoutObject.ChangeQueueStatus(queueId, queue)
} }
func (l Layout) GetRightTabs() RightTabsContract {
return l.rightTabsService
}
type QueueLayoutObjectContract interface { type QueueLayoutObjectContract interface {
GetCanvasObject() fyne.CanvasObject GetCanvasObject() fyne.CanvasObject
GetProgressbar(queueId int) *widget.ProgressBar
ChangeQueueStatus(queueId int, queue *Queue) ChangeQueueStatus(queueId int, queue *Queue)
} }
@@ -58,25 +63,22 @@ type QueueLayoutObject struct {
queue QueueListContract queue QueueListContract
container *fyne.Container container *fyne.Container
containerItems *fyne.Container
items map[int]QueueLayoutItem items map[int]QueueLayoutItem
localizerService LocalizerContract localizerService LocalizerContract
queueStatisticsFormat *queueStatisticsFormat queueStatisticsFormat *queueStatisticsFormat
ffplayService FFplayContract
} }
type QueueLayoutItem struct { type QueueLayoutItem struct {
CanvasObject fyne.CanvasObject CanvasObject fyne.CanvasObject
BlockMessageError *container.Scroll ProgressBar *widget.ProgressBar
StatusMessage *canvas.Text StatusMessage *canvas.Text
MessageError *canvas.Text MessageError *canvas.Text
buttonPlay *widget.Button
status *StatusContract status *StatusContract
} }
func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerContract, ffplayService FFplayContract, rightTabsService RightTabsContract, blockProgressbar *fyne.Container) *QueueLayoutObject { func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerContract) *QueueLayoutObject {
title := widget.NewLabel(localizerService.GetMessage("queue")) title := widget.NewLabel(localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: "queue"}))
title.TextStyle.Bold = true title.TextStyle.Bold = true
localizerService.AddChangeCallback("queue", func(text string) { localizerService.AddChangeCallback("queue", func(text string) {
@@ -87,31 +89,15 @@ func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerCon
items := map[int]QueueLayoutItem{} items := map[int]QueueLayoutItem{}
queueStatisticsFormat := newQueueStatisticsFormat(localizerService, &items) queueStatisticsFormat := newQueueStatisticsFormat(localizerService, &items)
line := canvas.NewLine(theme.Color(theme.ColorNameFocus))
line.StrokeWidth = 5
rightTabsService.GetFileQueueContainer().Add(container.NewVBox(
container.NewPadded(),
container.NewHBox(title, queueStatisticsFormat.completed.widget, queueStatisticsFormat.error.widget),
container.NewHBox(queueStatisticsFormat.inProgress.widget, queueStatisticsFormat.waiting.widget, queueStatisticsFormat.total.widget),
container.NewPadded(),
line,
container.NewPadded(),
))
queueLayoutObject := &QueueLayoutObject{ queueLayoutObject := &QueueLayoutObject{
queue: queue, queue: queue,
container: container.NewBorder( container: container.NewVBox(
container.NewVBox( container.NewHBox(title, queueStatisticsFormat.completed.widget, queueStatisticsFormat.error.widget),
blockProgressbar, container.NewHBox(queueStatisticsFormat.inProgress.widget, queueStatisticsFormat.waiting.widget, queueStatisticsFormat.total.widget),
widget.NewSeparator(),
),
nil, nil, nil, container.NewVScroll(rightTabsService.GetTabs()),
), ),
containerItems: rightTabsService.GetFileQueueContainer(),
items: items, items: items,
localizerService: localizerService, localizerService: localizerService,
queueStatisticsFormat: queueStatisticsFormat, queueStatisticsFormat: queueStatisticsFormat,
ffplayService: ffplayService,
} }
queue.AddListener(queueLayoutObject) queue.AddListener(queueLayoutObject)
@@ -123,24 +109,24 @@ func (o QueueLayoutObject) GetCanvasObject() fyne.CanvasObject {
return o.container return o.container
} }
func (o QueueLayoutObject) GetProgressbar(queueId int) *widget.ProgressBar {
if item, ok := o.items[queueId]; ok {
return item.ProgressBar
}
return widget.NewProgressBar()
}
func (o QueueLayoutObject) Add(id int, queue *Queue) { func (o QueueLayoutObject) Add(id int, queue *Queue) {
progressBar := widget.NewProgressBar()
statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary)) statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary))
messageError := canvas.NewText("", theme.Color(theme.ColorNameError)) messageError := canvas.NewText("", theme.Color(theme.ColorNameError))
buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() {
})
buttonPlay.Hide()
blockMessageError := container.NewHScroll(messageError)
blockMessageError.Hide()
content := container.NewVBox( content := container.NewVBox(
container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)), container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)),
container.NewHBox( progressBar,
buttonPlay, container.NewHScroll(statusMessage),
statusMessage, container.NewHScroll(messageError),
),
blockMessageError,
container.NewPadded(),
canvas.NewLine(theme.Color(theme.ColorNameFocus)), canvas.NewLine(theme.Color(theme.ColorNameFocus)),
container.NewPadded(), container.NewPadded(),
) )
@@ -151,14 +137,13 @@ func (o QueueLayoutObject) Add(id int, queue *Queue) {
} }
o.items[id] = QueueLayoutItem{ o.items[id] = QueueLayoutItem{
CanvasObject: content, CanvasObject: content,
StatusMessage: statusMessage, ProgressBar: progressBar,
BlockMessageError: blockMessageError, StatusMessage: statusMessage,
MessageError: messageError, MessageError: messageError,
buttonPlay: buttonPlay, status: &queue.Status,
status: &queue.Status,
} }
o.containerItems.Add(content) o.container.Add(content)
} }
func (o QueueLayoutObject) Remove(id int) { func (o QueueLayoutObject) Remove(id int) {
@@ -181,24 +166,9 @@ func (o QueueLayoutObject) ChangeQueueStatus(queueId int, queue *Queue) {
item.MessageError.Text = queue.Error.Error() item.MessageError.Text = queue.Error.Error()
item.MessageError.Color = statusColor item.MessageError.Color = statusColor
fyne.Do(func() { fyne.Do(func() {
item.BlockMessageError.Show()
item.MessageError.Refresh() item.MessageError.Refresh()
}) })
} }
if queue.Status == StatusType(Completed) {
item.buttonPlay.Show()
item.buttonPlay.OnTapped = func() {
item.buttonPlay.Disable()
go func() {
_ = o.ffplayService.Run(FFplaySetting{
PathToFile: queue.Setting.VideoFileOut.Path,
})
fyne.Do(func() {
item.buttonPlay.Enable()
})
}()
}
}
if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true { if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true {
item.CanvasObject.Hide() item.CanvasObject.Hide()
} else if item.CanvasObject.Visible() == false { } else if item.CanvasObject.Visible() == false {
@@ -221,7 +191,102 @@ func (o QueueLayoutObject) getStatusColor(status StatusContract) color.Color {
} }
func (o QueueLayoutObject) getStatusTitle(status StatusContract) string { func (o QueueLayoutObject) getStatusTitle(status StatusContract) string {
return o.localizerService.GetMessage(status.Name() + "Queue") return o.localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: status.Name() + "Queue"})
}
type Progress struct {
totalDuration float64
progressbar *widget.ProgressBar
protocol string
localizerService LocalizerContract
}
func NewProgress(totalDuration float64, progressbar *widget.ProgressBar, localizerService LocalizerContract) Progress {
return Progress{
totalDuration: totalDuration,
progressbar: progressbar,
protocol: "pipe:",
localizerService: localizerService,
}
}
func (p Progress) GetProtocole() string {
return p.protocol
}
func (p Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
isProcessCompleted := false
var errorText string
p.progressbar.Value = 0
p.progressbar.Max = p.totalDuration
fyne.Do(func() {
p.progressbar.Refresh()
})
progress := 0.0
go func() {
scannerErr := bufio.NewReader(stdErr)
for {
line, _, err := scannerErr.ReadLine()
if err != nil {
if err == io.EOF {
break
}
continue
}
data := strings.TrimSpace(string(line))
errorText = data
}
}()
scannerOut := bufio.NewReader(stdOut)
for {
line, _, err := scannerOut.ReadLine()
if err != nil {
if err == io.EOF {
break
}
continue
}
data := strings.TrimSpace(string(line))
if strings.Contains(data, "progress=end") {
p.progressbar.Value = p.totalDuration
fyne.Do(func() {
p.progressbar.Refresh()
})
isProcessCompleted = true
break
}
re := regexp.MustCompile(`frame=(\d+)`)
a := re.FindAllStringSubmatch(data, -1)
if len(a) > 0 && len(a[len(a)-1]) > 0 {
c, err := strconv.Atoi(a[len(a)-1][len(a[len(a)-1])-1])
if err != nil {
continue
}
progress = float64(c)
}
if p.progressbar.Value != progress {
p.progressbar.Value = progress
fyne.Do(func() {
p.progressbar.Refresh()
})
}
}
if isProcessCompleted == false {
if len(errorText) == 0 {
errorText = p.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "errorConverter",
})
}
return errors.New(errorText)
}
return nil
} }
type queueStatistics struct { type queueStatistics struct {
@@ -440,7 +505,7 @@ func newQueueStatistics(messaigeID string, localizerService LocalizerContract) *
count := int64(0) count := int64(0)
title := localizerService.GetMessage(messaigeID) title := localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: messaigeID})
queueStatistics := &queueStatistics{ queueStatistics := &queueStatistics{
widget: checkbox, widget: checkbox,
title: strings.ToLower(title), title: strings.ToLower(title),

View File

@@ -1,28 +1,21 @@
package kernel package kernel
import ( import (
"embed" "github.com/BurntSushi/toml"
"encoding/json" "github.com/nicksnyder/go-i18n/v2/i18n"
"fyne.io/fyne/v2" "golang.org/x/text/cases"
"fyne.io/fyne/v2/lang"
"golang.org/x/text/language" "golang.org/x/text/language"
"golang.org/x/text/language/display"
"path/filepath"
"sort"
) )
//go:embed translations
var translations embed.FS
var supportedLanguages = map[string]Lang{
"ru": {Code: "ru", Title: "Русский"},
"kk": {Code: "kk", Title: "Қазақ Тілі"},
"en": {Code: "en", Title: "English"},
}
type LocalizerContract interface { type LocalizerContract interface {
IsStartWithLanguageSelection() bool
GetMessage(key string, data ...any) string
GetLanguages() []Lang GetLanguages() []Lang
GetCurrentLanguage() Lang GetMessage(localizeConfig *i18n.LocalizeConfig) string
SetCurrentLanguage(selectLang Lang, isSaveSetting bool) error SetCurrentLanguage(lang Lang) error
SetCurrentLanguageByCode(code string) error
GetCurrentLanguage() *CurrentLanguage
AddChangeCallback(messageID string, callback func(text string)) AddChangeCallback(messageID string, callback func(text string))
} }
@@ -31,164 +24,135 @@ type Lang struct {
Title string Title string
} }
type CurrentLanguage struct {
Lang Lang
localizer *i18n.Localizer
localizerDefault *i18n.Localizer
}
type changeCallback struct { type changeCallback struct {
messageID string messageID string
callback func(text string) callback func(text string)
} }
type Localizer struct { type Localizer struct {
setting SettingLanguageContract bundle *i18n.Bundle
currentLang Lang languages []Lang
changeCallbacks map[int]*changeCallback currentLanguage *CurrentLanguage
isStartWithLanguageSelection bool changeCallbacks map[int]*changeCallback
} }
func newLocalizer(app fyne.App) (*Localizer, error) { func NewLocalizer(directory string, languageDefault language.Tag) (*Localizer, error) {
setting := newSettingLanguage(app) bundle := i18n.NewBundle(languageDefault)
currentLanguage, isLanguageNotSupported := setting.GetLang() bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
localizer := &Localizer{ languages, err := initLanguages(directory, bundle)
setting: setting,
changeCallbacks: map[int]*changeCallback{},
isStartWithLanguageSelection: isLanguageNotSupported,
}
err := localizer.SetCurrentLanguage(currentLanguage, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return localizer, nil localizerDefault := i18n.NewLocalizer(bundle, languageDefault.String())
return &Localizer{
bundle: bundle,
languages: languages,
currentLanguage: &CurrentLanguage{
Lang: Lang{
Code: languageDefault.String(),
Title: cases.Title(languageDefault).String(display.Self.Name(languageDefault)),
},
localizer: localizerDefault,
localizerDefault: localizerDefault,
},
changeCallbacks: map[int]*changeCallback{},
}, nil
} }
func (l *Localizer) IsStartWithLanguageSelection() bool { func initLanguages(directory string, bundle *i18n.Bundle) ([]Lang, error) {
return l.isStartWithLanguageSelection var languages []Lang
}
func (l *Localizer) GetMessage(key string, data ...any) string { files, err := filepath.Glob(directory + "/active.*.toml")
return lang.L(key, data...)
}
func (l *Localizer) GetLanguages() []Lang {
return getLanguages()
}
func (l *Localizer) GetCurrentLanguage() Lang {
return l.currentLang
}
func (l *Localizer) SetCurrentLanguage(selectLang Lang, isSaveSetting bool) error {
l.currentLang = selectLang
translationsData, err := l.getTranslations(selectLang)
if err != nil { if err != nil {
return err return nil, err
}
for _, file := range files {
lang, err := bundle.LoadMessageFile(file)
if err != nil {
return nil, err
}
title := cases.Title(lang.Tag).String(display.Self.Name(lang.Tag))
languages = append(languages, Lang{Code: lang.Tag.String(), Title: title})
} }
name := lang.SystemLocale().LanguageString() sort.Sort(languagesSort(languages))
err = lang.AddTranslations(fyne.NewStaticResource(name+".json", translationsData))
return languages, nil
}
func (l Localizer) GetLanguages() []Lang {
return l.languages
}
func (l Localizer) GetMessage(localizeConfig *i18n.LocalizeConfig) string {
message, err := l.GetCurrentLanguage().localizer.Localize(localizeConfig)
if err != nil { if err != nil {
return err message, err = l.GetCurrentLanguage().localizerDefault.Localize(localizeConfig)
} if err != nil {
return err.Error()
if isSaveSetting { }
l.setting.SetLang(selectLang)
} }
return message
}
func (l Localizer) SetCurrentLanguage(lang Lang) error {
l.currentLanguage.Lang = lang
l.currentLanguage.localizer = i18n.NewLocalizer(l.bundle, lang.Code)
l.eventSetCurrentLanguage() l.eventSetCurrentLanguage()
return nil return nil
} }
func (l *Localizer) AddChangeCallback(messageID string, callback func(text string)) { func (l Localizer) SetCurrentLanguageByCode(code string) error {
lang, err := language.Parse(code)
if err != nil {
return err
}
title := cases.Title(lang).String(display.Self.Name(lang))
return l.SetCurrentLanguage(Lang{Code: lang.String(), Title: title})
}
func (l Localizer) GetCurrentLanguage() *CurrentLanguage {
return l.currentLanguage
}
func (l Localizer) AddChangeCallback(messageID string, callback func(text string)) {
l.changeCallbacks[len(l.changeCallbacks)] = &changeCallback{messageID: messageID, callback: callback} l.changeCallbacks[len(l.changeCallbacks)] = &changeCallback{messageID: messageID, callback: callback}
} }
func (l *Localizer) eventSetCurrentLanguage() { func (l Localizer) eventSetCurrentLanguage() {
for _, changeCallback := range l.changeCallbacks { for _, changeCallback := range l.changeCallbacks {
text := l.GetMessage(changeCallback.messageID) text := l.GetMessage(&i18n.LocalizeConfig{MessageID: changeCallback.messageID})
changeCallback.callback(text) changeCallback.callback(text)
} }
} }
func (l *Localizer) getTranslations(language Lang) ([]byte, error) { type languagesSort []Lang
baseJson, err := translations.ReadFile("translations/base." + language.Code + ".json")
if err != nil { func (l languagesSort) Len() int { return len(l) }
return nil, err func (l languagesSort) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
} func (l languagesSort) Less(i, j int) bool {
appJson, err := translations.ReadFile("translations/app." + language.Code + ".json") return languagePriority(l[i]) < languagePriority(l[j])
if err != nil { }
return nil, err func languagePriority(l Lang) int {
priority := 0
switch l.Code {
case "ru":
priority = -3
case "kk":
priority = -2
case "en":
priority = -1
} }
return l.mergeTranslations(baseJson, appJson) return priority
}
func (l *Localizer) mergeTranslations(baseJson []byte, appJson []byte) ([]byte, error) {
base := map[string]interface{}{}
custom := map[string]interface{}{}
err := json.Unmarshal(baseJson, &base)
if err != nil {
return nil, err
}
err = json.Unmarshal(appJson, &custom)
if err != nil {
return nil, err
}
for k, v := range custom {
base[k] = v
}
return json.Marshal(base)
}
func getLanguages() []Lang {
items := []Lang{}
for _, item := range supportedLanguages {
items = append(items, item)
}
return items
}
type SettingLanguageContract interface {
GetLang() (currentLang Lang, isLanguageNotSupported bool)
SetLang(language Lang)
}
type SettingLanguage struct {
app fyne.App
}
func newSettingLanguage(app fyne.App) *SettingLanguage {
return &SettingLanguage{
app: app,
}
}
func (s *SettingLanguage) GetLang() (currentLang Lang, isLanguageNotSupported bool) {
languageCode := s.app.Preferences().String("language")
currentLang = supportedLanguages["ru"]
if languageCode == "" {
languageTag, err := language.Parse(lang.SystemLocale().LanguageString())
if err != nil {
return currentLang, true
}
base, _ := languageTag.Base()
languageCode = base.String()
}
if findLang, ok := findSupportedLanguage(languageCode); ok {
return findLang, false
}
return currentLang, true
}
func (s *SettingLanguage) SetLang(language Lang) {
s.app.Preferences().SetString("language", language.Code)
}
func findSupportedLanguage(code string) (Lang, bool) {
lang, ok := supportedLanguages[code]
return lang, ok
} }

View File

@@ -1,245 +0,0 @@
package kernel
import (
"bufio"
"errors"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"image/color"
"io"
"regexp"
"strconv"
"strings"
)
type BlockProgressbarContract interface {
GetContainer() *fyne.Container
GetProgressbar(totalDuration float64, filePath string, localizerService LocalizerContract) Progress
ProcessEndedWithError(errorText string)
ProcessEndedWithSuccess(filePath string)
}
type BlockProgressbar struct {
container *fyne.Container
label *widget.Label
progressbar *widget.ProgressBar
errorBlock *container.Scroll
messageError *canvas.Text
statusMessage *canvas.Text
buttonPlay *widget.Button
statusesText *BlockProgressbarStatusesText
ffplayService FFplayContract
}
func NewBlockProgressbar(statusesText *BlockProgressbarStatusesText, ffplayService FFplayContract) *BlockProgressbar {
label := widget.NewLabel("")
progressbar := widget.NewProgressBar()
statusMessage := canvas.NewText("", theme.Color(theme.ColorNamePrimary))
messageError := canvas.NewText("", theme.Color(theme.ColorNameError))
buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() {
})
buttonPlay.Hide()
errorBlock := container.NewHScroll(messageError)
errorBlock.Hide()
content := container.NewVBox(
container.NewHScroll(label),
progressbar,
container.NewHScroll(container.NewHBox(
buttonPlay,
statusMessage,
)),
errorBlock,
)
content.Hide()
return &BlockProgressbar{
container: content,
label: label,
progressbar: progressbar,
errorBlock: errorBlock,
messageError: messageError,
statusMessage: statusMessage,
buttonPlay: buttonPlay,
statusesText: statusesText,
ffplayService: ffplayService,
}
}
func (block BlockProgressbar) GetContainer() *fyne.Container {
return block.container
}
func (block BlockProgressbar) GetProgressbar(totalDuration float64, filePath string, localizerService LocalizerContract) Progress {
block.label.Text = filePath
block.statusMessage.Color = theme.Color(theme.ColorNamePrimary)
block.statusMessage.Text = block.statusesText.inProgress
block.messageError.Text = ""
fyne.Do(func() {
block.buttonPlay.Hide()
if block.errorBlock.Visible() {
block.errorBlock.Hide()
}
block.statusMessage.Refresh()
block.container.Refresh()
block.errorBlock.Refresh()
})
block.progressbar.Value = 0
return NewProgress(totalDuration, block.progressbar, localizerService)
}
func (block BlockProgressbar) ProcessEndedWithError(errorText string) {
fyne.Do(func() {
block.statusMessage.Color = theme.Color(theme.ColorNameError)
block.statusMessage.Text = block.statusesText.error
block.messageError.Text = errorText
block.errorBlock.Show()
})
}
func (block BlockProgressbar) ProcessEndedWithSuccess(filePath string) {
fyne.Do(func() {
block.statusMessage.Color = color.RGBA{R: 49, G: 127, B: 114, A: 255}
block.statusMessage.Text = block.statusesText.completed
block.buttonPlay.Show()
block.buttonPlay.OnTapped = func() {
block.buttonPlay.Disable()
go func() {
_ = block.ffplayService.Run(FFplaySetting{
PathToFile: filePath,
})
fyne.Do(func() {
block.buttonPlay.Enable()
})
}()
}
})
}
type Progress struct {
totalDuration float64
progressbar *widget.ProgressBar
protocol string
localizerService LocalizerContract
}
func NewProgress(totalDuration float64, progressbar *widget.ProgressBar, localizerService LocalizerContract) Progress {
return Progress{
totalDuration: totalDuration,
progressbar: progressbar,
protocol: "pipe:",
localizerService: localizerService,
}
}
func (p Progress) GetProtocole() string {
return p.protocol
}
func (p Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
isProcessCompleted := false
var errorText string
p.progressbar.Value = 0
p.progressbar.Max = p.totalDuration
fyne.Do(func() {
p.progressbar.Refresh()
})
progress := 0.0
go func() {
scannerErr := bufio.NewReader(stdErr)
for {
line, _, err := scannerErr.ReadLine()
if err != nil {
if err == io.EOF {
break
}
continue
}
data := strings.TrimSpace(string(line))
errorText = data
}
}()
scannerOut := bufio.NewReader(stdOut)
for {
line, _, err := scannerOut.ReadLine()
if err != nil {
if err == io.EOF {
break
}
continue
}
data := strings.TrimSpace(string(line))
if strings.Contains(data, "progress=end") {
p.progressbar.Value = p.totalDuration
fyne.Do(func() {
p.progressbar.Refresh()
})
isProcessCompleted = true
break
}
re := regexp.MustCompile(`frame=(\d+)`)
a := re.FindAllStringSubmatch(data, -1)
if len(a) > 0 && len(a[len(a)-1]) > 0 {
c, err := strconv.Atoi(a[len(a)-1][len(a[len(a)-1])-1])
if err != nil {
continue
}
progress = float64(c)
}
if p.progressbar.Value != progress {
p.progressbar.Value = progress
fyne.Do(func() {
p.progressbar.Refresh()
})
}
}
if isProcessCompleted == false {
if len(errorText) == 0 {
errorText = p.localizerService.GetMessage("errorConverter")
}
return errors.New(errorText)
}
return nil
}
type BlockProgressbarStatusesText struct {
inProgress string
completed string
error string
}
func GetBlockProgressbarStatusesText(localizerService LocalizerContract) *BlockProgressbarStatusesText {
statusesText := &BlockProgressbarStatusesText{
inProgress: localizerService.GetMessage("inProgressQueue"),
completed: localizerService.GetMessage("completedQueue"),
error: localizerService.GetMessage("errorQueue"),
}
localizerService.AddChangeCallback("inProgressQueue", func(text string) {
statusesText.inProgress = text
})
localizerService.AddChangeCallback("completedQueue", func(text string) {
statusesText.completed = text
})
localizerService.AddChangeCallback("errorQueue", func(text string) {
statusesText.error = text
})
return statusesText
}

View File

@@ -1,75 +0,0 @@
package kernel
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
)
type RightTabsContract interface {
GetTabs() *container.AppTabs
GetAddedFilesContainer() *fyne.Container
GetFileQueueContainer() *fyne.Container
SelectFileQueueTab()
SelectAddedFilesTab()
}
type RightTabs struct {
tabs *container.AppTabs
addedFilesContainer *fyne.Container
addedFilesTab *container.TabItem
fileQueueContainer *fyne.Container
fileQueueTab *container.TabItem
}
func NewRightTabs(localizerService LocalizerContract) *RightTabs {
addedFilesContainer := container.NewVBox()
addedFilesTab := container.NewTabItem(localizerService.GetMessage("addedFilesTitle"), addedFilesContainer)
localizerService.AddChangeCallback("addedFilesTitle", func(text string) {
addedFilesTab.Text = text
})
fileQueueContainer := container.NewVBox()
fileQueueTab := container.NewTabItem(localizerService.GetMessage("fileQueueTitle"), fileQueueContainer)
localizerService.AddChangeCallback("fileQueueTitle", func(text string) {
fileQueueTab.Text = text
})
tabs := container.NewAppTabs(
addedFilesTab,
fileQueueTab,
)
return &RightTabs{
tabs: tabs,
addedFilesContainer: addedFilesContainer,
addedFilesTab: addedFilesTab,
fileQueueContainer: fileQueueContainer,
fileQueueTab: fileQueueTab,
}
}
func (t RightTabs) GetTabs() *container.AppTabs {
return t.tabs
}
func (t RightTabs) GetAddedFilesContainer() *fyne.Container {
return t.addedFilesContainer
}
func (t RightTabs) GetFileQueueContainer() *fyne.Container {
return t.fileQueueContainer
}
func (t RightTabs) SelectFileQueueTab() {
fyne.Do(func() {
t.tabs.Select(t.fileQueueTab)
})
}
func (t RightTabs) SelectAddedFilesTab() {
fyne.Do(func() {
t.tabs.Select(t.addedFilesTab)
})
}

View File

@@ -1,143 +0,0 @@
{
"AlsoUsedProgram": "The program also uses:",
"about": "About",
"aboutText": "A simple interface for the FFmpeg console utility. \nBut I am not the author of the FFmpeg utility itself.",
"addedFilesTitle": "Added files",
"autoClearAfterAddingToQueue": "Auto-clear after adding to queue",
"buttonDownloadFFmpeg": "Download FFmpeg automatically",
"buttonForSelectedDirTitle": "Save to folder:",
"cancel": "Cancel",
"changeFFPath": "FFmpeg, FFprobe and FFplay",
"changeLanguage": "Change language",
"checkboxOverwriteOutputFilesTitle": "Allow file to be overwritten",
"choose": "choose",
"clearAll": "Clear List",
"completedQueue": "Completed",
"converterVideoFilesSubmitTitle": "Convert",
"converterVideoFilesTitle": "Video, audio and picture converter",
"download": "Download",
"downloadFFmpegFromSite": "Will be downloaded from the site:",
"downloadRun": "Downloading...",
"dragAndDropFiles": "drag and drop files",
"encoderGroupAudio": "Audio",
"encoderGroupImage": "Images",
"encoderGroupVideo": "Video",
"encoder_apng": "APNG image",
"encoder_bmp": "BMP image",
"encoder_flv": "FLV",
"encoder_gif": "GIF image",
"encoder_h264_nvenc": "H.264 with NVIDIA support",
"encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)",
"encoder_libshine": "libshine MP3 (MPEG audio layer 3)",
"encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)",
"encoder_libvpx": "libvpx VP8 (codec vp8)",
"encoder_libvpx-vp9": "libvpx VP9 (codec vp9)",
"encoder_libwebp": "libwebp WebP image",
"encoder_libwebp_anim": "libwebp_anim WebP image",
"encoder_libx264": "H.264 libx264",
"encoder_libx265": "H.265 libx265",
"encoder_libxvid": "libxvidcore MPEG-4 part 2",
"encoder_mjpeg": "MJPEG (Motion JPEG)",
"encoder_mp2": "MP2 (MPEG audio layer 2)",
"encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)",
"encoder_mpeg1video": "MPEG-1",
"encoder_mpeg2video": "MPEG-2",
"encoder_mpeg4": "MPEG-4 part 2",
"encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3",
"encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2",
"encoder_msvideo1": "Microsoft Video-1",
"encoder_png": "PNG image",
"encoder_qtrle": "QuickTime Animation (RLE) video",
"encoder_sgi": "SGI image",
"encoder_tiff": "TIFF image",
"encoder_wmav1": "Windows Media Audio 1",
"encoder_wmav2": "Windows Media Audio 2",
"encoder_wmv1": "Windows Media Video 7",
"encoder_wmv2": "Windows Media Video 8",
"encoder_xbm": "XBM (X BitMap) image",
"error": "An error has occurred!",
"errorConverter": "Couldn't convert video",
"errorDragAndDropFile": "Not all files were added",
"errorFFmpeg": "this is not FFmpeg",
"errorFFmpegVersion": "Could not determine FFmpeg version",
"errorFFplay": "this is not FFplay",
"errorFFplayVersion": "Could not determine FFplay version",
"errorFFprobe": "this is not FFprobe",
"errorFFprobeVersion": "Failed to determine FFprobe version",
"errorNoFilesAddedForConversion": "There are no files to convert",
"errorQueue": "Error",
"errorSelectedEncoder": "Converter not selected",
"errorSelectedFolderSave": "No save folder selected!",
"errorSelectedFormat": "File extension not selected",
"exit": "Exit",
"ffmpegLGPL": "This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**.",
"ffmpegTrademark": "**FFmpeg** is a trademark of **[Fabrice Bellard](http://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project.",
"fileForConversionTitle": "File:",
"fileQueueTitle": "Queue",
"formPreset": "Preset",
"gratitude": "Gratitude",
"gratitudeText": "I sincerely thank you for your invaluable\n\r and timely assistance:",
"help": "Help",
"helpFFplay": "FFplay Player Keys",
"helpFFplayActivateFrameStepMode": "Activate frame-by-frame mode.",
"helpFFplayCycleVideoFiltersOrShowModes": "A cycle of video filters or display modes.",
"helpFFplayDecreaseVolume": "Decrease the volume.",
"helpFFplayDescription": "Description",
"helpFFplayDoubleClickLeftMouseButton": "double click\nleft mouse button",
"helpFFplayIncreaseVolume": "Increase the volume.",
"helpFFplayKeyDown": "down",
"helpFFplayKeyHoldS": "hold S",
"helpFFplayKeyLeft": "left",
"helpFFplayKeyRight": "right",
"helpFFplayKeySpace": "SPACE",
"helpFFplayKeyUp": "up",
"helpFFplayKeys": "Keys",
"helpFFplayPause": "Pause or continue playing.",
"helpFFplayQuit": "Close the player.",
"helpFFplaySeekBForward10Minutes": "Fast forward 10 minutes.",
"helpFFplaySeekBForward1Minute": "Fast forward 1 minute.",
"helpFFplaySeekBackward10Minutes": "Rewind 10 minutes.",
"helpFFplaySeekBackward10Seconds": "Rewind 10 seconds.",
"helpFFplaySeekBackward1Minute": "Rewind 1 minute.",
"helpFFplaySeekForward10Seconds": "Fast forward 10 seconds.",
"helpFFplayToggleFullScreen": "Switch to full screen or exit full screen.",
"helpFFplayToggleMute": "Mute or unmute.",
"inProgressQueue": "In Progress",
"languageSelectionFormHead": "Switch language",
"languageSelectionHead": "Choose language",
"licenseLink": "License information",
"licenseLinkOther": "Licenses from other products used in the program",
"menuSettingsLanguage": "Language",
"menuSettingsTheme": "Theme",
"or": "or",
"parameterCheckbox": "Enable option",
"pathToFfmpeg": "Path to FFmpeg:",
"pathToFfplay": "Path to FFplay:",
"pathToFfprobe": "Path to FFprobe:",
"preset_fast": "fast (slower than \"faster\", but the file will weigh less)",
"preset_faster": "faster (slower than \"veryfast\", but the file will weigh less)",
"preset_medium": "medium (slower than \"fast\", but the file will weigh less)",
"preset_placebo": "placebo (not recommended)",
"preset_slow": "slow (slower than \"medium\", but the file will weigh less)",
"preset_slower": "slower (slower than \"slow\", but the file will weigh less)",
"preset_superfast": "superfast (slower than \"ultrafast\", but the file will weigh less)",
"preset_ultrafast": "ultrafast (fast, but the file will weigh a lot)",
"preset_veryfast": "veryfast (slower than \"superfast\", but the file will weigh less)",
"preset_veryslow": "veryslow (slower than \"slower\", but the file will weigh less)",
"programmLink": "Project website",
"programmVersion": "**Program version:** {{.Version}}",
"queue": "Queue",
"save": "Save",
"selectEncoder": "Encoder:",
"selectFFPathTitle": "Specify the path to FFmpeg and FFprobe",
"selectFormat": "File extension:",
"settings": "Settings",
"testFF": "Checking FFmpeg for serviceability...",
"themesNameDark": "Dark",
"themesNameDefault": "Default",
"themesNameLight": "Light",
"titleDownloadLink": "You can download it from here",
"total": "Total",
"unzipRun": "Unpacked...",
"waitingQueue": "Waiting"
}

View File

@@ -1,143 +0,0 @@
{
"AlsoUsedProgram": "Бағдарлама сонымен қатар пайдаланады:",
"about": "Бағдарлама туралы",
"aboutText": "FFmpeg консоль утилитасы үшін қарапайым интерфейс. \nБірақ мен FFmpeg утилитасының авторы емеспін.",
"addedFilesTitle": "Қосылған файлдар",
"autoClearAfterAddingToQueue": "Кезекке қосқаннан кейін тазалаңыз",
"buttonDownloadFFmpeg": "FFmpeg автоматты түрде жүктеп алыңыз",
"buttonForSelectedDirTitle": "Қалтаға сақтаңыз:",
"cancel": "Болдырмау",
"changeFFPath": "FFmpeg, FFprobe және FFplay",
"changeLanguage": "Тілді өзгерту",
"checkboxOverwriteOutputFilesTitle": "Файлды қайта жазуға рұқсат беріңіз",
"choose": "таңдау",
"clearAll": "Тізімді өшіру",
"completedQueue": "Дайын",
"converterVideoFilesSubmitTitle": "Файлды түрлендіру",
"converterVideoFilesTitle": "Бейне, аудио және суретті түрлендіргіш",
"download": "Жүктеп алу",
"downloadFFmpegFromSite": "Сайттан жүктеледі:",
"downloadRun": "Жүктеп алынуда...",
"dragAndDropFiles": "файлдарды сүйреп апарыңыз",
"encoderGroupAudio": "Аудио",
"encoderGroupImage": "Суреттер",
"encoderGroupVideo": "Бейне",
"encoder_apng": "APNG image",
"encoder_bmp": "BMP image",
"encoder_flv": "FLV",
"encoder_gif": "GIF image",
"encoder_h264_nvenc": "NVIDIA қолдауымен H.264",
"encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)",
"encoder_libshine": "libshine MP3 (MPEG audio layer 3)",
"encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)",
"encoder_libvpx": "libvpx VP8 (codec vp8)",
"encoder_libvpx-vp9": "libvpx VP9 (codec vp9)",
"encoder_libwebp": "libwebp WebP image",
"encoder_libwebp_anim": "libwebp_anim WebP image",
"encoder_libx264": "H.264 libx264",
"encoder_libx265": "H.265 libx265",
"encoder_libxvid": "libxvidcore MPEG-4 part 2",
"encoder_mjpeg": "MJPEG (Motion JPEG)",
"encoder_mp2": "MP2 (MPEG audio layer 2)",
"encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)",
"encoder_mpeg1video": "MPEG-1",
"encoder_mpeg2video": "MPEG-2",
"encoder_mpeg4": "MPEG-4 part 2",
"encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3",
"encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2",
"encoder_msvideo1": "Microsoft Video-1",
"encoder_png": "PNG image",
"encoder_qtrle": "QuickTime Animation (RLE) video",
"encoder_sgi": "SGI image",
"encoder_tiff": "TIFF image",
"encoder_wmav1": "Windows Media Audio 1",
"encoder_wmav2": "Windows Media Audio 2",
"encoder_wmv1": "Windows Media Video 7",
"encoder_wmv2": "Windows Media Video 8",
"encoder_xbm": "XBM (X BitMap) image",
"error": "Қате орын алды!",
"errorConverter": "Бейнені түрлендіру мүмкін болмады",
"errorDragAndDropFile": "Барлық файлдар қосылмаған",
"errorFFmpeg": "бұл FFmpeg емес",
"errorFFmpegVersion": "FFmpeg нұсқасын анықтау мүмкін болмады",
"errorFFplay": "бұл FFplay емес",
"errorFFplayVersion": "FFplay нұсқасын анықтау мүмкін болмады",
"errorFFprobe": "бұл FFprobe емес",
"errorFFprobeVersion": "FFprobe нұсқасын анықтау мүмкін болмады",
"errorNoFilesAddedForConversion": "Түрлендіруге арналған файлдар жоқ",
"errorQueue": "Қате",
"errorSelectedEncoder": "Түрлендіргіш таңдалмаған",
"errorSelectedFolderSave": "Сақтау қалтасы таңдалмаған!",
"errorSelectedFormat": "Файл кеңейтімі таңдалмаған",
"exit": "Шығу",
"ffmpegLGPL": "Бұл бағдарламалық құрал **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)** астында **FFmpeg** жобасының кітапханаларын пайдаланады.",
"ffmpegTrademark": "FFmpeg — **[FFmpeg](https://ffmpeg.org/about.html)** жобасын жасаушы **[Fabrice Bellard](http://bellard.org/)** сауда белгісі.",
"fileForConversionTitle": "Файл:",
"fileQueueTitle": "Кезек",
"formPreset": "Алдын ала орнатылған",
"gratitude": "Алғыс",
"gratitudeText": "Сізге баға жетпес және уақтылы көмектескеніңіз\n\r үшін шын жүректен алғыс айтамын:",
"help": "Анықтама",
"helpFFplay": "FFplay ойнатқышының пернелері",
"helpFFplayActivateFrameStepMode": "Уақыт аралығын іске қосыңыз.",
"helpFFplayCycleVideoFiltersOrShowModes": "Бейне сүзгілерінің немесе дисплей режимдерінің циклі.",
"helpFFplayDecreaseVolume": "Дыбыс деңгейін төмендетіңіз.",
"helpFFplayDescription": "Сипаттама",
"helpFFplayDoubleClickLeftMouseButton": "тінтуірдің сол жақ\nбатырмасын екі рет басу",
"helpFFplayIncreaseVolume": "Дыбыс деңгейін арттыру.",
"helpFFplayKeyDown": "төмен",
"helpFFplayKeyHoldS": "ұстау S",
"helpFFplayKeyLeft": "сол",
"helpFFplayKeyRight": "құқық",
"helpFFplayKeySpace": "SPACE (пробел)",
"helpFFplayKeyUp": "жоғары",
"helpFFplayKeys": "Кілттер",
"helpFFplayPause": "Кідіртіңіз немесе жоғалтуды жалғастырыңыз.",
"helpFFplayQuit": "Ойнатқышты жабыңыз.",
"helpFFplaySeekBForward10Minutes": "10 минутқа алға айналдырыңыз.",
"helpFFplaySeekBForward1Minute": "1 минутқа алға айналдырыңыз.",
"helpFFplaySeekBackward10Minutes": "10 минутқа артқа айналдырыңыз.",
"helpFFplaySeekBackward10Seconds": "10 секундқа артқа айналдырыңыз.",
"helpFFplaySeekBackward1Minute": "1 минутқа артқа айналдырыңыз.",
"helpFFplaySeekForward10Seconds": "10 секунд алға айналдырыңыз.",
"helpFFplayToggleFullScreen": "Толық экранға ауысу немесе толық экраннан шығу.",
"helpFFplayToggleMute": "Дыбысты өшіріңіз немесе дыбысты қосыңыз.",
"inProgressQueue": "Орындалуда",
"languageSelectionFormHead": "Тілді ауыстыру",
"languageSelectionHead": "Тілді таңдаңыз",
"licenseLink": "Лицензия туралы ақпарат",
"licenseLinkOther": "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары",
"menuSettingsLanguage": "Тіл",
"menuSettingsTheme": "Тақырып",
"or": "немесе",
"parameterCheckbox": "Опцияны қосу",
"pathToFfmpeg": "FFmpeg жол:",
"pathToFfplay": "FFplay жол:",
"pathToFfprobe": "FFprobe жол:",
"preset_fast": "fast («faster» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_faster": "faster («veryfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_medium": "medium («fast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_placebo": "placebo (ұсынылмайды)",
"preset_slow": "slow («medium» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_slower": "slower («slow» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_superfast": "superfast («ultrafast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_ultrafast": "ultrafast (жылдам, бірақ файлдың салмағы көп болады)",
"preset_veryfast": "veryfast («superfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"preset_veryslow": "veryslow («slower» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)",
"programmLink": "Жобаның веб-сайты",
"programmVersion": "**Бағдарлама нұсқасы:** {{.Version}}",
"queue": "Кезек",
"save": "Сақтау",
"selectEncoder": "Кодировщик:",
"selectFFPathTitle": "FFmpeg және FFprobe жолын көрсетіңіз",
"selectFormat": "Файл кеңейтімі:",
"settings": "Параметрлер",
"testFF": "FFmpeg функционалдығы тексерілуде...",
"themesNameDark": "Қараңғы тақырып",
"themesNameDefault": "Әдепкі бойынша",
"themesNameLight": "Жеңіл тақырып",
"titleDownloadLink": "Сіз оны осы жерден жүктей аласыз",
"total": "Барлығы",
"unzipRun": "Орамнан шығарылуда...",
"waitingQueue": "Күту"
}

View File

@@ -1,143 +0,0 @@
{
"AlsoUsedProgram": "Также в программе используется:",
"about": "О программе",
"aboutText": "Простенький интерфейс для консольной утилиты FFmpeg. \nНо я не являюсь автором самой утилиты FFmpeg.",
"addedFilesTitle": "Добавленные файлы",
"autoClearAfterAddingToQueue": "Очищать после добавления в очередь",
"buttonDownloadFFmpeg": "Скачать автоматически FFmpeg",
"buttonForSelectedDirTitle": "Сохранить в папку:",
"cancel": "Отмена",
"changeFFPath": "FFmpeg, FFprobe и FFplay",
"changeLanguage": "Поменять язык",
"checkboxOverwriteOutputFilesTitle": "Разрешить перезаписать файл",
"choose": "выбрать",
"clearAll": "Очистить список",
"completedQueue": "Готово",
"converterVideoFilesSubmitTitle": "Конвертировать",
"converterVideoFilesTitle": "Конвертер видео, аудио и картинок",
"download": "Скачать",
"downloadFFmpegFromSite": "Будет скачано с сайта:",
"downloadRun": "Скачивается...",
"dragAndDropFiles": "перетащить файлы",
"encoderGroupAudio": "Аудио",
"encoderGroupImage": "Картинки",
"encoderGroupVideo": "Видео",
"encoder_apng": "APNG image",
"encoder_bmp": "BMP image",
"encoder_flv": "FLV",
"encoder_gif": "GIF image",
"encoder_h264_nvenc": "H.264 с поддержкой NVIDIA",
"encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)",
"encoder_libshine": "libshine MP3 (MPEG audio layer 3)",
"encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)",
"encoder_libvpx": "libvpx VP8 (codec vp8)",
"encoder_libvpx-vp9": "libvpx VP9 (codec vp9)",
"encoder_libwebp": "libwebp WebP image",
"encoder_libwebp_anim": "libwebp_anim WebP image",
"encoder_libx264": "H.264 libx264",
"encoder_libx265": "H.265 libx265",
"encoder_libxvid": "libxvidcore MPEG-4 part 2",
"encoder_mjpeg": "MJPEG (Motion JPEG)",
"encoder_mp2": "MP2 (MPEG audio layer 2)",
"encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)",
"encoder_mpeg1video": "MPEG-1",
"encoder_mpeg2video": "MPEG-2",
"encoder_mpeg4": "MPEG-4 part 2",
"encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3",
"encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2",
"encoder_msvideo1": "Microsoft Video-1",
"encoder_png": "PNG image",
"encoder_qtrle": "QuickTime Animation (RLE) video",
"encoder_sgi": "SGI image",
"encoder_tiff": "TIFF image",
"encoder_wmav1": "Windows Media Audio 1",
"encoder_wmav2": "Windows Media Audio 2",
"encoder_wmv1": "Windows Media Video 7",
"encoder_wmv2": "Windows Media Video 8",
"encoder_xbm": "XBM (X BitMap) image",
"error": "Произошла ошибка!",
"errorConverter": "не смогли отконвертировать видео",
"errorDragAndDropFile": "Не все файлы добавились",
"errorFFmpeg": "это не FFmpeg",
"errorFFmpegVersion": "Не смогли определить версию FFmpeg",
"errorFFplay": "это не FFplay",
"errorFFplayVersion": "Не смогли определить версию FFplay",
"errorFFprobe": "это не FFprobe",
"errorFFprobeVersion": "Не смогли определить версию FFprobe",
"errorNoFilesAddedForConversion": "Нет файлов для конвертации",
"errorQueue": "Ошибка",
"errorSelectedEncoder": "Конвертер не выбран",
"errorSelectedFolderSave": "Папка для сохранения не выбрана!",
"errorSelectedFormat": "Расширение файла не выбрана",
"exit": "Выход",
"ffmpegLGPL": "Это программное обеспечение использует библиотеки из проекта **FFmpeg** под **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**.",
"ffmpegTrademark": "**FFmpeg** — торговая марка **[Fabrice Bellard](http://bellard.org/)** , создателя проекта **[FFmpeg](https://ffmpeg.org/about.html)**.",
"fileForConversionTitle": "Файл:",
"fileQueueTitle": "Очередь",
"formPreset": "Предустановка",
"gratitude": "Благодарность",
"gratitudeText": "Я искренне благодарю вас за неоценимую\n\rи своевременную помощь:",
"help": "Справка",
"helpFFplay": "Клавиши проигрывателя FFplay",
"helpFFplayActivateFrameStepMode": "Активировать покадровый режим.",
"helpFFplayCycleVideoFiltersOrShowModes": "Цикл видеофильтров или режимов показа.",
"helpFFplayDecreaseVolume": "Уменьшить громкость.",
"helpFFplayDescription": "Описание",
"helpFFplayDoubleClickLeftMouseButton": "двойной щелчок\nлевой кнопкой мыши",
"helpFFplayIncreaseVolume": "Увеличить громкость.",
"helpFFplayKeyDown": "вниз",
"helpFFplayKeyHoldS": "держать S",
"helpFFplayKeyLeft": "лево",
"helpFFplayKeyRight": "право",
"helpFFplayKeySpace": "SPACE (пробел)",
"helpFFplayKeyUp": "вверх",
"helpFFplayKeys": "Клавиши",
"helpFFplayPause": "Поставить на паузу или продолжить проигрывать.",
"helpFFplayQuit": "Закрыть проигрыватель.",
"helpFFplaySeekBForward10Minutes": "Перемотать вперёд на 10 минут.",
"helpFFplaySeekBForward1Minute": "Перемотать вперёд на 1 минуту.",
"helpFFplaySeekBackward10Minutes": "Перемотать назад на 10 минут.",
"helpFFplaySeekBackward10Seconds": "Перемотать назад на 10 секунд.",
"helpFFplaySeekBackward1Minute": "Перемотать назад на 1 минуту.",
"helpFFplaySeekForward10Seconds": "Перемотать вперёд на 10 секунд.",
"helpFFplayToggleFullScreen": "Переключиться на полный экран или выйти с полного экрана.",
"helpFFplayToggleMute": "Отключить звук или включить звук.",
"inProgressQueue": "Выполняется",
"languageSelectionFormHead": "Переключить язык",
"languageSelectionHead": "Выберите язык",
"licenseLink": "Сведения о лицензии",
"licenseLinkOther": "Лицензии от других продуктов, которые используются в программе",
"menuSettingsLanguage": "Язык",
"menuSettingsTheme": "Тема",
"or": "или",
"parameterCheckbox": "Включить параметр",
"pathToFfmpeg": "Путь к FFmpeg:",
"pathToFfplay": "Путь к FFplay:",
"pathToFfprobe": "Путь к FFprobe:",
"preset_fast": "fast (медленней чем faster, но будет файл и меньше весить)",
"preset_faster": "faster (медленней чем veryfast, но будет файл и меньше весить)",
"preset_medium": "medium (медленней чем fast, но будет файл и меньше весить)",
"preset_placebo": "placebo (не рекомендуется)",
"preset_slow": "slow (медленней чем medium, но будет файл и меньше весить)",
"preset_slower": "slower (медленней чем slow, но будет файл и меньше весить)",
"preset_superfast": "superfast (медленней чем ultrafast, но будет файл и меньше весить)",
"preset_ultrafast": "ultrafast (быстро, но файл будет много весить)",
"preset_veryfast": "veryfast (медленней чем superfast, но будет файл и меньше весить)",
"preset_veryslow": "veryslow (медленней чем slower, но будет файл и меньше весить)",
"programmLink": "Сайт проекта",
"programmVersion": "**Версия программы:** {{.Version}}",
"queue": "Очередь",
"save": "Сохранить",
"selectEncoder": "Кодировщик:",
"selectFFPathTitle": "Укажите путь к FFmpeg и к FFprobe",
"selectFormat": "Расширение файла:",
"settings": "Настройки",
"testFF": "Проверка FFmpeg на работоспособность...",
"themesNameDark": "Тёмная",
"themesNameDefault": "По умолчанию",
"themesNameLight": "Светлая",
"titleDownloadLink": "Скачать можно от сюда",
"total": "Всего",
"unzipRun": "Распаковывается...",
"waitingQueue": "В очереди"
}

View File

@@ -1,45 +0,0 @@
{
"Advanced": "Advanced",
"Cancel": "Cancel",
"Confirm": "Confirm",
"Copy": "Copy",
"Create Folder": "Create Folder",
"Cut": "Cut",
"Enter filename": "Enter filename",
"Error": "Error",
"Favourites": "Favourites",
"File": "File",
"Folder": "Folder",
"New Folder": "New Folder",
"No": "No",
"OK": "OK",
"Open": "Open",
"Paste": "Paste",
"Quit": "Quit",
"Redo": "Redo",
"Save": "Save",
"Select all": "Select all",
"Show Hidden Files": "Show Hidden Files",
"Undo": "Undo",
"Yes": "Yes",
"file.name": {
"other": "Name"
},
"file.parent": {
"other": "Parent"
},
"friday": "Friday",
"friday.short": "Fri",
"monday": "Monday",
"monday.short": "Mon",
"saturday": "Saturday",
"saturday.short": "Sat",
"sunday": "Sunday",
"sunday.short": "Sun",
"thursday": "Thursday",
"thursday.short": "Thu",
"tuesday": "Tuesday",
"tuesday.short": "Tue",
"wednesday": "Wednesday",
"wednesday.short": "Wed"
}

View File

@@ -1,45 +0,0 @@
{
"Advanced": "Кеңейтілген",
"Cancel": "Бас тарту",
"Confirm": "Растау",
"Copy": "Көшіру",
"Create Folder": "Қалта жасау",
"Cut": "Кесу",
"Enter filename": "Файл атауын енгізіңіз",
"Error": "Қате",
"Favourites": "Таңдаулылар",
"File": "Файл",
"Folder": "Қалта",
"New Folder": "Жаңа қалта",
"No": "Жоқ",
"OK": "ОК",
"Open": "Ашу",
"Paste": "Кірістіру",
"Quit": "Шығу",
"Redo": "Қайталау",
"Save": "Сақтау",
"Select all": "Барлығын таңдаңыз",
"Show Hidden Files": "Жасырын файлдарды көрсету",
"Undo": "Бас тарту",
"Yes": "Иә",
"file.name": {
"other": "Аты"
},
"file.parent": {
"other": "Жоғары"
},
"friday": "Жұма",
"friday.short": "Жұ",
"monday": "Дүйсенбі",
"monday.short": "Дү",
"saturday": "Сенбі",
"saturday.short": "Сен",
"sunday": "Жексенбі",
"sunday.short": "Же",
"thursday": "Сейсенбі",
"thursday.short": "Се",
"tuesday": "Бейсенбі",
"tuesday.short": "Бе",
"wednesday": "Сәрсенбі",
"wednesday.short": "Сә"
}

View File

@@ -1,45 +0,0 @@
{
"Advanced": "Расширенные",
"Cancel": "Отмена",
"Confirm": "Подтвердить",
"Copy": "Копировать",
"Create Folder": "Создать папку",
"Cut": "Вырезать",
"Enter filename": "Введите имя файла",
"Error": "Ошибка",
"Favourites": "Избранное",
"File": "Файл",
"Folder": "Папка",
"New Folder": "Новая папка",
"No": "Нет",
"OK": "ОК",
"Open": "Открыть",
"Paste": "Вставить",
"Quit": "Выйти",
"Redo": "Повторить",
"Save": "Сохранить",
"Select all": "Выбрать всё",
"Show Hidden Files": "Показать скрытые файлы",
"Undo": "Отменить",
"Yes": "Да",
"file.name": {
"other": "Имя"
},
"file.parent": {
"other": "Вверх"
},
"friday": "Пятница",
"friday.short": "Пт",
"monday": "Понедельник",
"monday.short": "Пн",
"saturday": "Суббота",
"saturday.short": "Сб",
"sunday": "Воскресенье",
"sunday.short": "Вс",
"thursday": "Вторник",
"thursday.short": "Вт",
"tuesday": "Четверг",
"tuesday.short": "Чт",
"wednesday": "Среда",
"wednesday.short": "Ср"
}

View File

@@ -83,7 +83,5 @@ func (w Window) GetLayout() LayoutContract {
} }
func (w Window) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) { func (w Window) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) {
fyne.Do(func() { w.windowFyne.SetOnDropped(callback)
w.windowFyne.SetOnDropped(callback)
})
} }

1
languages/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
translate.*.toml

423
languages/active.en.toml Normal file
View File

@@ -0,0 +1,423 @@
[AlsoUsedProgram]
hash = "sha1-a72be72e7808bb8a0144ed7a93acb29c568b1ed4"
other = "The program also uses:"
[about]
hash = "sha1-3da0b9ef719fd707f443ac00404447f29445976f"
other = "About"
[aboutText]
hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6"
other = "A simple interface for the FFmpeg console utility. \nBut I am not the author of the FFmpeg utility itself."
[buttonDownloadFFmpeg]
hash = "sha1-c223c2e15171156192bc3146aee91e6094bb475b"
other = "Download FFmpeg automatically"
[buttonForSelectedDirTitle]
hash = "sha1-8cbe5c67bcf89e4624635a79cbea104227faedda"
other = "Save to folder:"
[cancel]
hash = "sha1-0ec753be8df955a117404fb634b01b45eb386e2a"
other = "Cancel"
[changeFFPath]
hash = "sha1-46793a2844600d0eb19fa3540fb9564ee5705491"
other = "FFmpeg and FFprobe"
[changeLanguage]
hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b"
other = "Change language"
[checkboxOverwriteOutputFilesTitle]
hash = "sha1-5860124bb781e7ef680f573fa93977e96328d4e7"
other = "Allow file to be overwritten"
[choose]
hash = "sha1-f60bb5f761024d973834b5e9d25ceebce2c85f94"
other = "choose"
[completedQueue]
hash = "sha1-398c7d4f7b0d522afb930769c0fbb1a9f4b61fbe"
other = "Completed"
[converterVideoFilesSubmitTitle]
hash = "sha1-7ac460f3c24c9952082f2db6e4d62f752598709c"
other = "Convert"
[converterVideoFilesTitle]
hash = "sha1-1ab29597cc9dfefab08e54ea5442e7ffa15f0394"
other = "Video, audio and picture converter"
[download]
hash = "sha1-fe8f79f29da457de2f6bc9531de6e536e0c426ad"
other = "Download"
[downloadFFmpegFromSite]
hash = "sha1-0889c95aa3a8659d8d903b4dab7097699c4d8aa4"
other = "Will be downloaded from the site:"
[downloadRun]
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Downloading..."
[dragAndDrop1File]
hash = "sha1-7259670822df1cc92ef5f06ed3c0e9407746975a"
other = "drag and drop 1 file"
[encoderGroupAudio]
hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba"
other = "Audio"
[encoderGroupImage]
hash = "sha1-a7e528bc7ac9538aec87d1593c38b80be95d4745"
other = "Images"
[encoderGroupVideo]
hash = "sha1-8e7b9894c7ef0f57ac0bf910f6a8aac1c8a53683"
other = "Video"
[encoder_apng]
hash = "sha1-1cbd9abfef96d5614a7e569161b41bd6ad87bbaf"
other = "APNG image"
[encoder_bmp]
hash = "sha1-e0b9c16b016961a5abdc2217e8ffd1ba7ddebc40"
other = "BMP image"
[encoder_flv]
hash = "sha1-3602bbf1cc90e48254f81975c7879b5fc0c4d602"
other = "FLV"
[encoder_gif]
hash = "sha1-d092a779172291b5215aa095390a5b11659128a4"
other = "GIF image"
[encoder_h264_nvenc]
hash = "sha1-169389f8c4a2518410159c363378ab5c978c32e5"
other = "H.264 with NVIDIA support"
[encoder_libmp3lame]
hash = "sha1-cd2c8d6f246c8bc18554b7105cb50b78d3cb2b98"
other = "libmp3lame MP3 (MPEG audio layer 3)"
[encoder_libshine]
hash = "sha1-891d56c85857e5d83ef5a1fe077c1f1540788f49"
other = "libshine MP3 (MPEG audio layer 3)"
[encoder_libtwolame]
hash = "sha1-b2f53be810b74edc3c454ac75de7ddecfee322ca"
other = "libtwolame MP2 (MPEG audio layer 2)"
[encoder_libvpx]
hash = "sha1-b85c923aecfb48de0e87e71b6a21bfc2c547c70e"
other = "libvpx VP8 (codec vp8)"
[encoder_libvpx-vp9]
hash = "sha1-3106417bd89bee87daa691e87614caf78cb934fe"
other = "libvpx VP9 (codec vp9)"
[encoder_libwebp]
hash = "sha1-1d590d47d46f7880246061fce0e0de6d743db39e"
other = "libwebp WebP image"
[encoder_libwebp_anim]
hash = "sha1-f141a9c8f23d79c13d44c30d8f34e05b363771ad"
other = "libwebp_anim WebP image"
[encoder_libx264]
hash = "sha1-6d764ac459c0bf3c819d76618418cdfbb7a749eb"
other = "H.264 libx264"
[encoder_libx265]
hash = "sha1-55544c166b1e15fd71a58096518e528109599eea"
other = "H.265 libx265"
[encoder_libxvid]
hash = "sha1-d4bed46d6cdd2bfa8fd1689801164a83ab10c3f5"
other = "libxvidcore MPEG-4 part 2"
[encoder_mjpeg]
hash = "sha1-94ba63a322b493a04da65e566781fe1cf8bb0d50"
other = "MJPEG (Motion JPEG)"
[encoder_mp2]
hash = "sha1-a9154b7203349e5d6fbfd67d1ea97715f54b2065"
other = "MP2 (MPEG audio layer 2)"
[encoder_mp2fixed]
hash = "sha1-dd2ee670d8bc8a60a96a717ebd26f16b5748cf3f"
other = "MP2 fixed point (MPEG audio layer 2)"
[encoder_mpeg1video]
hash = "sha1-30043660719a3cb19dab5c33450665a8a9cc1c01"
other = "MPEG-1"
[encoder_mpeg2video]
hash = "sha1-ccb2dcd8510cfdc9d52e5258af1863e5f2c51e77"
other = "MPEG-2"
[encoder_mpeg4]
hash = "sha1-67fe42f18421b2f6c90fcdc579f9199bfca4b182"
other = "MPEG-4 part 2"
[encoder_msmpeg4]
hash = "sha1-313ee597e4f0d9bd63a2bc6ac1618f028aef76f4"
other = "MPEG-4 part 2 Microsoft variant version 3"
[encoder_msmpeg4v2]
hash = "sha1-adc442ce88f2717693b2da3010a1937d77ee522f"
other = "MPEG-4 part 2 Microsoft variant version 2"
[encoder_msvideo1]
hash = "sha1-00f43ac0dc162bca10e0d98d6b70c0c6a902f66f"
other = "Microsoft Video-1"
[encoder_png]
hash = "sha1-6715d4b82f5d9dfe3e53e30b402ffa1a6fbf30a5"
other = "PNG image"
[encoder_qtrle]
hash = "sha1-31bf155cffaf6842ebc54084e4337ca08fdd9848"
other = "QuickTime Animation (RLE) video"
[encoder_sgi]
hash = "sha1-f4510e237f7fc3c02caa728f9e500f4b069f9c11"
other = "SGI image"
[encoder_tiff]
hash = "sha1-ed09d78c38e0b17ed695f35740c756dd7340eeac"
other = "TIFF image"
[encoder_wmav1]
hash = "sha1-cd4a4c5eeac694b6699d55d0f9b477b3b50f18c7"
other = "Windows Media Audio 1"
[encoder_wmav2]
hash = "sha1-eb2e5306cb33a702577ecfbdca0461862c66c053"
other = "Windows Media Audio 2"
[encoder_wmv1]
hash = "sha1-f9b748554c590c36a56bcba2cd317196b7bdeddb"
other = "Windows Media Video 7"
[encoder_wmv2]
hash = "sha1-5b21c87f5c6104797ead60b488b2948428f6b1b7"
other = "Windows Media Video 8"
[encoder_xbm]
hash = "sha1-2dfc35881da62e9a1379d8238cf7839b24f79566"
other = "XBM (X BitMap) image"
[error]
hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483"
other = "An error has occurred!"
[errorConverter]
hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9"
other = "Couldn't convert video"
[errorDatabase]
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "could not create file 'database' in folder 'data'"
[errorDragAndDrop1File]
hash = "sha1-a8edb5cbd622f3ce4ec07a2377e22ec5fad4491b"
other = "You can only drag and drop 1 file."
[errorFFmpeg]
hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0"
other = "this is not FFmpeg"
[errorFFmpegVersion]
hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f"
other = "Could not determine FFmpeg version"
[errorFFprobe]
hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8"
other = "this is not FFprobe"
[errorFFprobeVersion]
hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17"
other = "Failed to determine FFprobe version"
[errorIsFolder]
hash = "sha1-f937d090b6e320957514d850657cdf2f911dc6aa"
other = "You can only drag and drop a file"
[errorQueue]
hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7"
other = "Error"
[errorSelectedEncoder]
hash = "sha1-33ed1aaf4cb3c2ee9d8f8c325b9b75d16ddf9979"
other = "Converter not selected"
[errorSelectedFolderSave]
hash = "sha1-16f3ef93ee36813fdd79d8fb9bb7fc02acbb94a8"
other = "No save folder selected!"
[errorSelectedFormat]
hash = "sha1-cda92c56a1ef1aabc92bbfc405ede8ab13087e66"
other = "File extension not selected"
[exit]
hash = "sha1-c42457057d1ab7950cea00719cbe0b078891775f"
other = "Exit"
[ffmpegLGPL]
hash = "sha1-d395b16cc8f8eab98a8a970307c5b010ba22dde6"
other = "This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."
[ffmpegTrademark]
hash = "sha1-45f772b2eca5098cd6d31f2d1dc6edec1987a617"
other = "**FFmpeg** is a trademark of **[Fabrice Bellard](http://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."
[fileForConversionTitle]
hash = "sha1-96ac799e1086b31fd8f5f8d4c801829d6c853f08"
other = "File:"
[formPreset]
hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68"
other = "Preset"
[gratitude]
hash = "sha1-51968fc38e53a9a11c861126c62404674fd6096f"
other = "Gratitude"
[gratitudeText]
hash = "sha1-cb343e4d39ca31e6da6f72b9394cc915cb7d1258"
other = "I sincerely thank you for your invaluable\n\r and timely assistance:"
[help]
hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f"
other = "Help"
[inProgressQueue]
hash = "sha1-eff79c40e2100ae5fadf3a7d99336025edcca8b5"
other = "In Progress"
[languageSelectionFormHead]
hash = "sha1-0ff5fa82cf684112660128cba1711297acf11003"
other = "Switch language"
[languageSelectionHead]
hash = "sha1-daf1108fc10d3b1a908288d611f749b3cc651e4b"
other = "Choose language"
[licenseLink]
hash = "sha1-ea18ab849f0eea030d770da82c2a6b3484a7bd13"
other = "License information"
[licenseLinkOther]
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Licenses from other products used in the program"
[or]
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
other = "or"
[parameterCheckbox]
hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c"
other = "Enable option"
[pathToFfmpeg]
hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6"
other = "Path to FFmpeg:"
[pathToFfprobe]
hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024"
other = "Path to FFprobe:"
[preset_fast]
hash = "sha1-935e1ac9d3c8ba4478326c909ba66662acb0540e"
other = "fast (slower than \"faster\", but the file will weigh less)"
[preset_faster]
hash = "sha1-98620b73c896440c39ea6ec4b9b19d41301c9a7e"
other = "faster (slower than \"veryfast\", but the file will weigh less)"
[preset_medium]
hash = "sha1-f7d1c30135c22c2f07c247075c0df103bb3c3ea5"
other = "medium (slower than \"fast\", but the file will weigh less)"
[preset_placebo]
hash = "sha1-7bcff099104bb192881139e6404981bd426b3f91"
other = "placebo (not recommended)"
[preset_slow]
hash = "sha1-681bf587275a45b48af49bb2ad8f0947919530e7"
other = "slow (slower than \"medium\", but the file will weigh less)"
[preset_slower]
hash = "sha1-d1c692ee2b7643ae2c71a48bea880327a3c6b1e3"
other = "slower (slower than \"slow\", but the file will weigh less)"
[preset_superfast]
hash = "sha1-41c39959e8f1547cc9259a5b459c4ccbf368cc23"
other = "superfast (slower than \"ultrafast\", but the file will weigh less)"
[preset_ultrafast]
hash = "sha1-dfed981573ac2046832f9a9450bc9388958753fa"
other = "ultrafast (fast, but the file will weigh a lot)"
[preset_veryfast]
hash = "sha1-370b82509887d02d7a2ef9b110df4616b16123ce"
other = "veryfast (slower than \"superfast\", but the file will weigh less)"
[preset_veryslow]
hash = "sha1-d428bfa6deea9dd5c7c1f80ceba24e123ae96d0d"
other = "veryslow (slower than \"slower\", but the file will weigh less)"
[programmLink]
hash = "sha1-18f9a3fad6aacefe1b05eed23122800b391ff5ca"
other = "Project website"
[programmVersion]
hash = "sha1-fa2e4994a301bb24bc2a8fa166e5486ea95a7475"
other = "**Program version:** {{.Version}}"
[queue]
hash = "sha1-aec93b16baeaf55fed871075c9494a460e4a91b8"
other = "Queue"
[save]
hash = "sha1-4864057d626a868fa60f999bed3191d61d045ddc"
other = "Save"
[selectEncoder]
hash = "sha1-88f3670b09758a3336057520a215058d61006abd"
other = "Encoder:"
[selectFFPathTitle]
hash = "sha1-95581446a28d968ff1a027c623159a7eb08654cf"
other = "Specify the path to FFmpeg and FFprobe"
[selectFormat]
hash = "sha1-f3809b0b48886570cd4cf1d7099de6da5b6d4524"
other = "File extension:"
[settings]
hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f"
other = "Settings"
[testFF]
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "Checking FFmpeg for serviceability..."
[titleDownloadLink]
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
other = "You can download it from here"
[total]
hash = "sha1-3b5143902e0c5c84459aedf918e17604d9735b94"
other = "Total"
[unzipRun]
hash = "sha1-c554dad13026668a1f6adf3171837c5d51bbac36"
other = "Unpacked..."
[waitingQueue]
hash = "sha1-307429dd84150877080c4bbff2b340d1e7dadff2"
other = "Waiting"

423
languages/active.kk.toml Normal file
View File

@@ -0,0 +1,423 @@
[AlsoUsedProgram]
hash = "sha1-a72be72e7808bb8a0144ed7a93acb29c568b1ed4"
other = "Бағдарлама сонымен қатар пайдаланады:"
[about]
hash = "sha1-3da0b9ef719fd707f443ac00404447f29445976f"
other = "Бағдарлама туралы"
[aboutText]
hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6"
other = "FFmpeg консоль утилитасы үшін қарапайым интерфейс. \nБірақ мен FFmpeg утилитасының авторы емеспін."
[buttonDownloadFFmpeg]
hash = "sha1-c223c2e15171156192bc3146aee91e6094bb475b"
other = "FFmpeg автоматты түрде жүктеп алыңыз"
[buttonForSelectedDirTitle]
hash = "sha1-8cbe5c67bcf89e4624635a79cbea104227faedda"
other = "Қалтаға сақтаңыз:"
[cancel]
hash = "sha1-0ec753be8df955a117404fb634b01b45eb386e2a"
other = "Болдырмау"
[changeFFPath]
hash = "sha1-46793a2844600d0eb19fa3540fb9564ee5705491"
other = "FFmpeg және FFprobe"
[changeLanguage]
hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b"
other = "Тілді өзгерту"
[checkboxOverwriteOutputFilesTitle]
hash = "sha1-5860124bb781e7ef680f573fa93977e96328d4e7"
other = "Файлды қайта жазуға рұқсат беріңіз"
[choose]
hash = "sha1-f60bb5f761024d973834b5e9d25ceebce2c85f94"
other = "таңдау"
[completedQueue]
hash = "sha1-398c7d4f7b0d522afb930769c0fbb1a9f4b61fbe"
other = "Дайын"
[converterVideoFilesSubmitTitle]
hash = "sha1-7ac460f3c24c9952082f2db6e4d62f752598709c"
other = "Файлды түрлендіру"
[converterVideoFilesTitle]
hash = "sha1-1ab29597cc9dfefab08e54ea5442e7ffa15f0394"
other = "Бейне, аудио және суретті түрлендіргіш"
[download]
hash = "sha1-fe8f79f29da457de2f6bc9531de6e536e0c426ad"
other = "Жүктеп алу"
[downloadFFmpegFromSite]
hash = "sha1-0889c95aa3a8659d8d903b4dab7097699c4d8aa4"
other = "Сайттан жүктеледі:"
[downloadRun]
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Жүктеп алынуда..."
[dragAndDrop1File]
hash = "sha1-7259670822df1cc92ef5f06ed3c0e9407746975a"
other = "1 файлды сүйреңіз"
[encoderGroupAudio]
hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba"
other = "Аудио"
[encoderGroupImage]
hash = "sha1-a7e528bc7ac9538aec87d1593c38b80be95d4745"
other = "Суреттер"
[encoderGroupVideo]
hash = "sha1-8e7b9894c7ef0f57ac0bf910f6a8aac1c8a53683"
other = "Бейне"
[encoder_apng]
hash = "sha1-1cbd9abfef96d5614a7e569161b41bd6ad87bbaf"
other = "APNG image"
[encoder_bmp]
hash = "sha1-e0b9c16b016961a5abdc2217e8ffd1ba7ddebc40"
other = "BMP image"
[encoder_flv]
hash = "sha1-3602bbf1cc90e48254f81975c7879b5fc0c4d602"
other = "FLV"
[encoder_gif]
hash = "sha1-d092a779172291b5215aa095390a5b11659128a4"
other = "GIF image"
[encoder_h264_nvenc]
hash = "sha1-169389f8c4a2518410159c363378ab5c978c32e5"
other = "NVIDIA қолдауымен H.264"
[encoder_libmp3lame]
hash = "sha1-cd2c8d6f246c8bc18554b7105cb50b78d3cb2b98"
other = "libmp3lame MP3 (MPEG audio layer 3)"
[encoder_libshine]
hash = "sha1-891d56c85857e5d83ef5a1fe077c1f1540788f49"
other = "libshine MP3 (MPEG audio layer 3)"
[encoder_libtwolame]
hash = "sha1-b2f53be810b74edc3c454ac75de7ddecfee322ca"
other = "libtwolame MP2 (MPEG audio layer 2)"
[encoder_libvpx]
hash = "sha1-b85c923aecfb48de0e87e71b6a21bfc2c547c70e"
other = "libvpx VP8 (codec vp8)"
[encoder_libvpx-vp9]
hash = "sha1-3106417bd89bee87daa691e87614caf78cb934fe"
other = "libvpx VP9 (codec vp9)"
[encoder_libwebp]
hash = "sha1-1d590d47d46f7880246061fce0e0de6d743db39e"
other = "libwebp WebP image"
[encoder_libwebp_anim]
hash = "sha1-f141a9c8f23d79c13d44c30d8f34e05b363771ad"
other = "libwebp_anim WebP image"
[encoder_libx264]
hash = "sha1-6d764ac459c0bf3c819d76618418cdfbb7a749eb"
other = "H.264 libx264"
[encoder_libx265]
hash = "sha1-55544c166b1e15fd71a58096518e528109599eea"
other = "H.265 libx265"
[encoder_libxvid]
hash = "sha1-d4bed46d6cdd2bfa8fd1689801164a83ab10c3f5"
other = "libxvidcore MPEG-4 part 2"
[encoder_mjpeg]
hash = "sha1-94ba63a322b493a04da65e566781fe1cf8bb0d50"
other = "MJPEG (Motion JPEG)"
[encoder_mp2]
hash = "sha1-a9154b7203349e5d6fbfd67d1ea97715f54b2065"
other = "MP2 (MPEG audio layer 2)"
[encoder_mp2fixed]
hash = "sha1-dd2ee670d8bc8a60a96a717ebd26f16b5748cf3f"
other = "MP2 fixed point (MPEG audio layer 2)"
[encoder_mpeg1video]
hash = "sha1-30043660719a3cb19dab5c33450665a8a9cc1c01"
other = "MPEG-1"
[encoder_mpeg2video]
hash = "sha1-ccb2dcd8510cfdc9d52e5258af1863e5f2c51e77"
other = "MPEG-2"
[encoder_mpeg4]
hash = "sha1-67fe42f18421b2f6c90fcdc579f9199bfca4b182"
other = "MPEG-4 part 2"
[encoder_msmpeg4]
hash = "sha1-313ee597e4f0d9bd63a2bc6ac1618f028aef76f4"
other = "MPEG-4 part 2 Microsoft variant version 3"
[encoder_msmpeg4v2]
hash = "sha1-adc442ce88f2717693b2da3010a1937d77ee522f"
other = "MPEG-4 part 2 Microsoft variant version 2"
[encoder_msvideo1]
hash = "sha1-00f43ac0dc162bca10e0d98d6b70c0c6a902f66f"
other = "Microsoft Video-1"
[encoder_png]
hash = "sha1-6715d4b82f5d9dfe3e53e30b402ffa1a6fbf30a5"
other = "PNG image"
[encoder_qtrle]
hash = "sha1-31bf155cffaf6842ebc54084e4337ca08fdd9848"
other = "QuickTime Animation (RLE) video"
[encoder_sgi]
hash = "sha1-f4510e237f7fc3c02caa728f9e500f4b069f9c11"
other = "SGI image"
[encoder_tiff]
hash = "sha1-ed09d78c38e0b17ed695f35740c756dd7340eeac"
other = "TIFF image"
[encoder_wmav1]
hash = "sha1-cd4a4c5eeac694b6699d55d0f9b477b3b50f18c7"
other = "Windows Media Audio 1"
[encoder_wmav2]
hash = "sha1-eb2e5306cb33a702577ecfbdca0461862c66c053"
other = "Windows Media Audio 2"
[encoder_wmv1]
hash = "sha1-f9b748554c590c36a56bcba2cd317196b7bdeddb"
other = "Windows Media Video 7"
[encoder_wmv2]
hash = "sha1-5b21c87f5c6104797ead60b488b2948428f6b1b7"
other = "Windows Media Video 8"
[encoder_xbm]
hash = "sha1-2dfc35881da62e9a1379d8238cf7839b24f79566"
other = "XBM (X BitMap) image"
[error]
hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483"
other = "Қате орын алды!"
[errorConverter]
hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9"
other = "Бейнені түрлендіру мүмкін болмады"
[errorDatabase]
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "'data' қалтасында 'database' файлын жасау мүмкін болмады"
[errorDragAndDrop1File]
hash = "sha1-a8edb5cbd622f3ce4ec07a2377e22ec5fad4491b"
other = "Тек 1 файлды сүйреп апаруға болады"
[errorFFmpeg]
hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0"
other = "бұл FFmpeg емес"
[errorFFmpegVersion]
hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f"
other = "FFmpeg нұсқасын анықтау мүмкін болмады"
[errorFFprobe]
hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8"
other = "бұл FFprobe емес"
[errorFFprobeVersion]
hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17"
other = "FFprobe нұсқасын анықтау мүмкін болмады"
[errorIsFolder]
hash = "sha1-f937d090b6e320957514d850657cdf2f911dc6aa"
other = "Тек файлды сүйреп апаруға болады"
[errorQueue]
hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7"
other = "Қате"
[errorSelectedEncoder]
hash = "sha1-33ed1aaf4cb3c2ee9d8f8c325b9b75d16ddf9979"
other = "Түрлендіргіш таңдалмаған"
[errorSelectedFolderSave]
hash = "sha1-16f3ef93ee36813fdd79d8fb9bb7fc02acbb94a8"
other = "Сақтау қалтасы таңдалмаған!"
[errorSelectedFormat]
hash = "sha1-cda92c56a1ef1aabc92bbfc405ede8ab13087e66"
other = "Файл кеңейтімі таңдалмаған"
[exit]
hash = "sha1-c42457057d1ab7950cea00719cbe0b078891775f"
other = "Шығу"
[ffmpegLGPL]
hash = "sha1-d395b16cc8f8eab98a8a970307c5b010ba22dde6"
other = "Бұл бағдарламалық құрал **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)** астында **FFmpeg** жобасының кітапханаларын пайдаланады."
[ffmpegTrademark]
hash = "sha1-45f772b2eca5098cd6d31f2d1dc6edec1987a617"
other = "FFmpeg — **[FFmpeg](https://ffmpeg.org/about.html)** жобасын жасаушы **[Fabrice Bellard](http://bellard.org/)** сауда белгісі."
[fileForConversionTitle]
hash = "sha1-96ac799e1086b31fd8f5f8d4c801829d6c853f08"
other = "Файл:"
[formPreset]
hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68"
other = "Алдын ала орнатылған"
[gratitude]
hash = "sha1-51968fc38e53a9a11c861126c62404674fd6096f"
other = "Алғыс"
[gratitudeText]
hash = "sha1-cb343e4d39ca31e6da6f72b9394cc915cb7d1258"
other = "Сізге баға жетпес және уақтылы көмектескеніңіз\n\r үшін шын жүректен алғыс айтамын:"
[help]
hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f"
other = "Анықтама"
[inProgressQueue]
hash = "sha1-eff79c40e2100ae5fadf3a7d99336025edcca8b5"
other = "Орындалуда"
[languageSelectionFormHead]
hash = "sha1-0ff5fa82cf684112660128cba1711297acf11003"
other = "Тілді ауыстыру"
[languageSelectionHead]
hash = "sha1-daf1108fc10d3b1a908288d611f749b3cc651e4b"
other = "Тілді таңдаңыз"
[licenseLink]
hash = "sha1-ea18ab849f0eea030d770da82c2a6b3484a7bd13"
other = "Лицензия туралы ақпарат"
[licenseLinkOther]
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары"
[or]
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
other = "немесе"
[parameterCheckbox]
hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c"
other = "Опцияны қосу"
[pathToFfmpeg]
hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6"
other = "FFmpeg жол:"
[pathToFfprobe]
hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024"
other = "FFprobe жол:"
[preset_fast]
hash = "sha1-935e1ac9d3c8ba4478326c909ba66662acb0540e"
other = "fast («faster» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_faster]
hash = "sha1-98620b73c896440c39ea6ec4b9b19d41301c9a7e"
other = "faster («veryfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_medium]
hash = "sha1-f7d1c30135c22c2f07c247075c0df103bb3c3ea5"
other = "medium («fast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_placebo]
hash = "sha1-7bcff099104bb192881139e6404981bd426b3f91"
other = "placebo (ұсынылмайды)"
[preset_slow]
hash = "sha1-681bf587275a45b48af49bb2ad8f0947919530e7"
other = "slow («medium» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_slower]
hash = "sha1-d1c692ee2b7643ae2c71a48bea880327a3c6b1e3"
other = "slower («slow» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_superfast]
hash = "sha1-41c39959e8f1547cc9259a5b459c4ccbf368cc23"
other = "superfast («ultrafast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_ultrafast]
hash = "sha1-dfed981573ac2046832f9a9450bc9388958753fa"
other = "ultrafast (жылдам, бірақ файлдың салмағы көп болады)"
[preset_veryfast]
hash = "sha1-370b82509887d02d7a2ef9b110df4616b16123ce"
other = "veryfast («superfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[preset_veryslow]
hash = "sha1-d428bfa6deea9dd5c7c1f80ceba24e123ae96d0d"
other = "veryslow («slower» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)"
[programmLink]
hash = "sha1-18f9a3fad6aacefe1b05eed23122800b391ff5ca"
other = "Жобаның веб-сайты"
[programmVersion]
hash = "sha1-fa2e4994a301bb24bc2a8fa166e5486ea95a7475"
other = "**Бағдарлама нұсқасы:** {{.Version}}"
[queue]
hash = "sha1-aec93b16baeaf55fed871075c9494a460e4a91b8"
other = "Кезек"
[save]
hash = "sha1-4864057d626a868fa60f999bed3191d61d045ddc"
other = "Сақтау"
[selectEncoder]
hash = "sha1-88f3670b09758a3336057520a215058d61006abd"
other = "Кодировщик:"
[selectFFPathTitle]
hash = "sha1-95581446a28d968ff1a027c623159a7eb08654cf"
other = "FFmpeg және FFprobe жолын көрсетіңіз"
[selectFormat]
hash = "sha1-f3809b0b48886570cd4cf1d7099de6da5b6d4524"
other = "Файл кеңейтімі:"
[settings]
hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f"
other = "Параметрлер"
[testFF]
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "FFmpeg функционалдығы тексерілуде..."
[titleDownloadLink]
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
other = "Сіз оны осы жерден жүктей аласыз"
[total]
hash = "sha1-3b5143902e0c5c84459aedf918e17604d9735b94"
other = "Барлығы"
[unzipRun]
hash = "sha1-c554dad13026668a1f6adf3171837c5d51bbac36"
other = "Орамнан шығарылуда..."
[waitingQueue]
hash = "sha1-307429dd84150877080c4bbff2b340d1e7dadff2"
other = "Күту"

106
languages/active.ru.toml Normal file
View File

@@ -0,0 +1,106 @@
AlsoUsedProgram = "Также в программе используется:"
about = "О программе"
aboutText = "Простенький интерфейс для консольной утилиты FFmpeg. \nНо я не являюсь автором самой утилиты FFmpeg."
buttonDownloadFFmpeg = "Скачать автоматически FFmpeg"
buttonForSelectedDirTitle = "Сохранить в папку:"
cancel = "Отмена"
changeFFPath = "FFmpeg и FFprobe"
changeLanguage = "Поменять язык"
checkboxOverwriteOutputFilesTitle = "Разрешить перезаписать файл"
choose = "выбрать"
completedQueue = "Готово"
converterVideoFilesSubmitTitle = "Конвертировать"
converterVideoFilesTitle = "Конвертер видео, аудио и картинок"
download = "Скачать"
downloadFFmpegFromSite = "Будет скачано с сайта:"
downloadRun = "Скачивается..."
dragAndDrop1File = "перетащить 1 файл"
encoderGroupAudio = "Аудио"
encoderGroupImage = "Картинки"
encoderGroupVideo = "Видео"
encoder_apng = "APNG image"
encoder_bmp = "BMP image"
encoder_flv = "FLV"
encoder_gif = "GIF image"
encoder_h264_nvenc = "H.264 с поддержкой NVIDIA"
encoder_libmp3lame = "libmp3lame MP3 (MPEG audio layer 3)"
encoder_libshine = "libshine MP3 (MPEG audio layer 3)"
encoder_libtwolame = "libtwolame MP2 (MPEG audio layer 2)"
encoder_libvpx = "libvpx VP8 (codec vp8)"
encoder_libvpx-vp9 = "libvpx VP9 (codec vp9)"
encoder_libwebp = "libwebp WebP image"
encoder_libwebp_anim = "libwebp_anim WebP image"
encoder_libx264 = "H.264 libx264"
encoder_libx265 = "H.265 libx265"
encoder_libxvid = "libxvidcore MPEG-4 part 2"
encoder_mjpeg = "MJPEG (Motion JPEG)"
encoder_mp2 = "MP2 (MPEG audio layer 2)"
encoder_mp2fixed = "MP2 fixed point (MPEG audio layer 2)"
encoder_mpeg1video = "MPEG-1"
encoder_mpeg2video = "MPEG-2"
encoder_mpeg4 = "MPEG-4 part 2"
encoder_msmpeg4 = "MPEG-4 part 2 Microsoft variant version 3"
encoder_msmpeg4v2 = "MPEG-4 part 2 Microsoft variant version 2"
encoder_msvideo1 = "Microsoft Video-1"
encoder_png = "PNG image"
encoder_qtrle = "QuickTime Animation (RLE) video"
encoder_sgi = "SGI image"
encoder_tiff = "TIFF image"
encoder_wmav1 = "Windows Media Audio 1"
encoder_wmav2 = "Windows Media Audio 2"
encoder_wmv1 = "Windows Media Video 7"
encoder_wmv2 = "Windows Media Video 8"
encoder_xbm = "XBM (X BitMap) image"
error = "Произошла ошибка!"
errorConverter = "не смогли отконвертировать видео"
errorDatabase = "не смогли создать файл 'database' в папке 'data'"
errorDragAndDrop1File = "Можно перетащить только 1 файл"
errorFFmpeg = "это не FFmpeg"
errorFFmpegVersion = "Не смогли определить версию FFmpeg"
errorFFprobe = "это не FFprobe"
errorFFprobeVersion = "Не смогли определить версию FFprobe"
errorIsFolder = "Можно перетаскивать только файл"
errorQueue = "Ошибка"
errorSelectedEncoder = "Конвертер не выбран"
errorSelectedFolderSave = "Папка для сохранения не выбрана!"
errorSelectedFormat = "Расширение файла не выбрана"
exit = "Выход"
ffmpegLGPL = "Это программное обеспечение использует библиотеки из проекта **FFmpeg** под **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."
ffmpegTrademark = "**FFmpeg** — торговая марка **[Fabrice Bellard](http://bellard.org/)** , создателя проекта **[FFmpeg](https://ffmpeg.org/about.html)**."
fileForConversionTitle = "Файл:"
formPreset = "Предустановка"
gratitude = "Благодарность"
gratitudeText = "Я искренне благодарю вас за неоценимую\n\rи своевременную помощь:"
help = "Справка"
inProgressQueue = "Выполняется"
languageSelectionFormHead = "Переключить язык"
languageSelectionHead = "Выберите язык"
licenseLink = "Сведения о лицензии"
licenseLinkOther = "Лицензии от других продуктов, которые используются в программе"
or = "или"
parameterCheckbox = "Включить параметр"
pathToFfmpeg = "Путь к FFmpeg:"
pathToFfprobe = "Путь к FFprobe:"
preset_fast = "fast (медленней чем faster, но будет файл и меньше весить)"
preset_faster = "faster (медленней чем veryfast, но будет файл и меньше весить)"
preset_medium = "medium (медленней чем fast, но будет файл и меньше весить)"
preset_placebo = "placebo (не рекомендуется)"
preset_slow = "slow (медленней чем medium, но будет файл и меньше весить)"
preset_slower = "slower (медленней чем slow, но будет файл и меньше весить)"
preset_superfast = "superfast (медленней чем ultrafast, но будет файл и меньше весить)"
preset_ultrafast = "ultrafast (быстро, но файл будет много весить)"
preset_veryfast = "veryfast (медленней чем superfast, но будет файл и меньше весить)"
preset_veryslow = "veryslow (медленней чем slower, но будет файл и меньше весить)"
programmLink = "Сайт проекта"
programmVersion = "**Версия программы:** {{.Version}}"
queue = "Очередь"
save = "Сохранить"
selectEncoder = "Кодировщик:"
selectFFPathTitle = "Укажите путь к FFmpeg и к FFprobe"
selectFormat = "Расширение файла:"
settings = "Настройки"
testFF = "Проверка FFmpeg на работоспособность..."
titleDownloadLink = "Скачать можно от сюда"
total = "Всего"
unzipRun = "Распаковывается..."
waitingQueue = "В очереди"

26
localizer/repository.go Normal file
View File

@@ -0,0 +1,26 @@
package localizer
import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
)
type RepositoryContract interface {
GetCode() (string, error)
Save(code string) (setting.Setting, error)
}
type Repository struct {
settingRepository setting.RepositoryContract
}
func NewRepository(settingRepository setting.RepositoryContract) *Repository {
return &Repository{settingRepository: settingRepository}
}
func (r Repository) GetCode() (string, error) {
return r.settingRepository.GetValue("language")
}
func (r Repository) Save(code string) (setting.Setting, error) {
return r.settingRepository.CreateOrUpdate("language", code)
}

View File

@@ -4,6 +4,7 @@ import (
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
) )
type ViewContract interface { type ViewContract interface {
@@ -34,11 +35,13 @@ func (v View) LanguageSelection(funcSelected func(lang kernel.Lang)) {
block.SetText(languages[i].Title) block.SetText(languages[i].Title)
}) })
listView.OnSelected = func(id widget.ListItemID) { listView.OnSelected = func(id widget.ListItemID) {
_ = v.app.GetLocalizerService().SetCurrentLanguage(languages[id], true) _ = v.app.GetLocalizerService().SetCurrentLanguage(languages[id])
funcSelected(languages[id]) funcSelected(languages[id])
} }
messageHead := v.app.GetLocalizerService().GetMessage("languageSelectionHead") messageHead := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "languageSelectionHead",
})
v.app.GetWindow().SetContent(widget.NewCard(messageHead, "", listView)) v.app.GetWindow().SetContent(widget.NewCard(messageHead, "", listView))
} }
@@ -55,15 +58,17 @@ func LanguageSelectionForm(localizerService kernel.LocalizerContract, funcSelect
func(i widget.ListItemID, o fyne.CanvasObject) { func(i widget.ListItemID, o fyne.CanvasObject) {
block := o.(*widget.Label) block := o.(*widget.Label)
block.SetText(languages[i].Title) block.SetText(languages[i].Title)
if languages[i].Code == currentLanguage.Code { if languages[i].Code == currentLanguage.Lang.Code {
block.TextStyle = fyne.TextStyle{Bold: true} block.TextStyle = fyne.TextStyle{Bold: true}
} }
}) })
listView.OnSelected = func(id widget.ListItemID) { listView.OnSelected = func(id widget.ListItemID) {
_ = localizerService.SetCurrentLanguage(languages[id], true) _ = localizerService.SetCurrentLanguage(languages[id])
funcSelected(languages[id]) funcSelected(languages[id])
} }
messageHead := localizerService.GetMessage("languageSelectionFormHead") messageHead := localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "languageSelectionFormHead",
})
return widget.NewCard(messageHead, "", listView) return widget.NewCard(messageHead, "", listView)
} }

92
main.go
View File

@@ -1,76 +1,120 @@
package main package main
import ( import (
_ "embed" "errors"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor"
dberror "git.kor-elf.net/kor-elf/gui-for-ffmpeg/db"
error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error" error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/handler" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/handler"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/resources"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/migration"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme" "go.etcd.io/bbolt"
"golang.org/x/text/language"
"os"
"time"
) )
var application kernel.AppContract var application kernel.AppContract
var ffPathUtilities *kernel.FFPathUtilities var ffPathUtilities *kernel.FFPathUtilities
func init() { func init() {
iconResource, _ := fyne.LoadResourceFromPath("icon.png")
appMetadata := &fyne.AppMetadata{ appMetadata := &fyne.AppMetadata{
ID: "net.kor-elf.projects.gui-for-ffmpeg", ID: "net.kor-elf.projects.gui-for-ffmpeg",
Name: "GUI for FFmpeg", Name: "GUI for FFmpeg",
Version: "0.9.0", Version: "0.8.0",
Icon: resources.IconAppLogoResource(), Icon: iconResource,
} }
ffPathUtilities = &kernel.FFPathUtilities{FFmpeg: "", FFprobe: "", FFplay: ""} localizerService, err := kernel.NewLocalizer("languages", language.Russian)
if err != nil {
kernel.PanicErrorLang(err, appMetadata)
}
ffPathUtilities = &kernel.FFPathUtilities{FFmpeg: "", FFprobe: ""}
convertorService := kernel.NewService(ffPathUtilities) convertorService := kernel.NewService(ffPathUtilities)
ffplayService := kernel.NewFFplay(ffPathUtilities)
queue := kernel.NewQueueList() queue := kernel.NewQueueList()
application = kernel.NewApp( application = kernel.NewApp(
appMetadata, appMetadata,
localizerService,
queue, queue,
ffplayService, kernel.NewQueueLayoutObject(queue, localizerService),
convertorService, convertorService,
) )
} }
func main() { func main() {
errorView := error2.NewView(application) errorView := error2.NewView(application)
if canCreateFile("data/database.db") != true {
errorView.PanicErrorWriteDirectoryData()
application.GetWindow().ShowAndRun()
return
}
settingRepository := setting.NewRepository(application.GetAppFyne()) db, err := bbolt.Open("data/database.db", 0600, &bbolt.Options{Timeout: 3 * time.Second})
if err != nil {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
defer db.Close()
err = migration.Run(db)
if err != nil {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
settingRepository := setting.NewRepository(db)
settingDirectoryForSaving := setting.NewSettingDirectoryForSaving(settingRepository) settingDirectoryForSaving := setting.NewSettingDirectoryForSaving(settingRepository)
convertorRepository := convertor.NewRepository(settingRepository) convertorRepository := convertor.NewRepository(settingRepository)
ffPathUtilities.FFmpeg = convertorRepository.GetPathFfmpeg() pathFFmpeg, err := convertorRepository.GetPathFfmpeg()
ffPathUtilities.FFprobe = convertorRepository.GetPathFfprobe() if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
ffPathUtilities.FFplay = convertorRepository.GetPathFfplay() errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFmpeg = pathFFmpeg
pathFFprobe, err := convertorRepository.GetPathFfprobe()
if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFprobe = pathFFprobe
application.RunConvertor() application.RunConvertor()
defer application.AfterClosing() defer application.AfterClosing()
localizerView := localizer.NewView(application) localizerView := localizer.NewView(application)
convertorView := convertor.NewView(application) convertorView := convertor.NewView(application)
itemsToConvertService := kernel.NewItemsToConvert( convertorHandler := handler.NewConvertorHandler(application, convertorView, errorView, convertorRepository, settingDirectoryForSaving)
application.GetWindow().GetLayout().GetRightTabs().GetAddedFilesContainer(),
application.GetFFplayService(),
application.GetLocalizerService(),
)
convertorHandler := handler.NewConvertorHandler(application, convertorView, errorView, convertorRepository, settingDirectoryForSaving, itemsToConvertService)
themeRepository := theme.NewRepository(settingRepository)
themeService := theme.NewTheme(application, themeRepository)
localizerRepository := localizer.NewRepository(settingRepository)
menuView := menu.NewView(application) menuView := menu.NewView(application)
menuSettingView := menu.NewViewSetting(application, themeService) mainMenu := handler.NewMenuHandler(application, convertorHandler, menuView, localizerView, localizerRepository)
mainMenu := handler.NewMenuHandler(application, convertorHandler, menuView, menuSettingView, localizerView, themeService)
mainHandler := handler.NewMainHandler(application, convertorHandler, mainMenu) mainHandler := handler.NewMainHandler(application, convertorHandler, mainMenu, localizerRepository)
mainHandler.Start() mainHandler.Start()
application.GetWindow().SetMainMenu(mainMenu.GetMainMenu()) application.GetWindow().SetMainMenu(mainMenu.GetMainMenu())
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
} }
func canCreateFile(path string) bool {
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return false
}
_ = file.Close()
return true
}

View File

@@ -4,18 +4,16 @@ import (
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/resources"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/image/colornames" "golang.org/x/image/colornames"
"net/url" "net/url"
) )
type ViewContract interface { type ViewContract interface {
About(ffmpegVersion string, ffprobeVersion string, ffplayVersion string) About(ffmpegVersion string, ffprobeVersion string)
Gratitude() Gratitude()
HelpFFplay()
} }
type View struct { type View struct {
@@ -29,15 +27,19 @@ func NewView(app kernel.AppContract) *View {
} }
func (v View) Gratitude() { func (v View) Gratitude() {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage("gratitude")) view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}))
view.Resize(fyne.Size{Width: 500, Height: 400}) view.Resize(fyne.Size{Width: 500, Height: 400})
view.SetFixedSize(true) view.SetFixedSize(true)
image := canvas.NewImageFromResource(resources.IconAppLogoResource()) image := canvas.NewImageFromFile("icon.png")
image.SetMinSize(fyne.Size{Width: 100, Height: 100}) image.SetMinSize(fyne.Size{Width: 100, Height: 100})
image.FillMode = canvas.ImageFillContain image.FillMode = canvas.ImageFillContain
gratitude := canvas.NewText(v.app.GetLocalizerService().GetMessage("gratitude"), colornames.Darkgreen) gratitude := canvas.NewText(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}), colornames.Darkgreen)
gratitude.TextStyle = fyne.TextStyle{Bold: true} gratitude.TextStyle = fyne.TextStyle{Bold: true}
gratitude.TextSize = 20 gratitude.TextSize = 20
@@ -45,19 +47,23 @@ func (v View) Gratitude() {
container.NewScroll(container.NewVBox( container.NewScroll(container.NewVBox(
container.NewBorder(nil, nil, container.NewVBox(image), nil, container.NewVBox( container.NewBorder(nil, nil, container.NewVBox(image), nil, container.NewVBox(
gratitude, gratitude,
widget.NewLabel(v.app.GetLocalizerService().GetMessage("gratitudeText")), widget.NewLabel(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitudeText",
})),
widget.NewLabel("Екатерина"), widget.NewLabel("Екатерина"),
widget.NewLabel("Евгений"), widget.NewLabel("Евгений"),
)), ),
)), ))),
) )
view.CenterOnScreen() view.CenterOnScreen()
view.Show() view.Show()
} }
func (v View) About(ffmpegVersion string, ffprobeVersion string, ffplayVersion string) { func (v View) About(ffmpegVersion string, ffprobeVersion string) {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage("about")) view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "about",
}))
view.Resize(fyne.Size{Width: 793, Height: 550}) view.Resize(fyne.Size{Width: 793, Height: 550})
view.SetFixedSize(true) view.SetFixedSize(true)
@@ -65,51 +71,54 @@ func (v View) About(ffmpegVersion string, ffprobeVersion string, ffplayVersion s
programmName.TextStyle = fyne.TextStyle{Bold: true} programmName.TextStyle = fyne.TextStyle{Bold: true}
programmName.TextSize = 20 programmName.TextSize = 20
programmLink := widget.NewHyperlink( programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
v.app.GetLocalizerService().GetMessage("programmLink"), MessageID: "programmLink",
&url.URL{ }), &url.URL{
Scheme: "https", Scheme: "https",
Host: "gui-for-ffmpeg.projects.kor-elf.net", Host: "gui-for-ffmpeg.projects.kor-elf.net",
Path: "/", Path: "/",
}, })
)
licenseLink := widget.NewHyperlink( licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
v.app.GetLocalizerService().GetMessage("licenseLink"), MessageID: "licenseLink",
&url.URL{ }), &url.URL{
Scheme: "https", Scheme: "https",
Host: "git.kor-elf.net", Host: "git.kor-elf.net",
Path: "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE", Path: "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE",
}, })
)
licenseLinkOther := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage( licenseLinkOther := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
"licenseLinkOther"), MessageID: "licenseLinkOther",
&url.URL{ }), &url.URL{
Scheme: "https", Scheme: "https",
Host: "git.kor-elf.net", Host: "git.kor-elf.net",
Path: "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE-3RD-PARTY.txt", Path: "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE-3RD-PARTY.txt",
}, })
)
programmVersion := widget.NewRichTextFromMarkdown( programmVersion := widget.NewRichTextFromMarkdown(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
v.app.GetLocalizerService().GetMessage( MessageID: "programmVersion",
"programmVersion", TemplateData: map[string]string{
map[string]any{"Version": v.app.GetAppFyne().Metadata().Version}, "Version": v.app.GetAppFyne().Metadata().Version,
), },
) }))
aboutText := widget.NewRichText( aboutText := widget.NewRichText(
&widget.TextSegment{ &widget.TextSegment{
Text: v.app.GetLocalizerService().GetMessage("aboutText"), Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "aboutText",
}),
}, },
) )
image := canvas.NewImageFromResource(resources.IconAppLogoResource()) image := canvas.NewImageFromFile("icon.png")
image.SetMinSize(fyne.Size{Width: 100, Height: 100}) image.SetMinSize(fyne.Size{Width: 100, Height: 100})
image.FillMode = canvas.ImageFillContain image.FillMode = canvas.ImageFillContain
ffmpegTrademark := widget.NewRichTextFromMarkdown(v.app.GetLocalizerService().GetMessage("ffmpegTrademark")) ffmpegTrademark := widget.NewRichTextFromMarkdown(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
ffmpegLGPL := widget.NewRichTextFromMarkdown(v.app.GetLocalizerService().GetMessage("ffmpegLGPL")) MessageID: "ffmpegTrademark",
}))
ffmpegLGPL := widget.NewRichTextFromMarkdown(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "ffmpegLGPL",
}))
view.SetContent( view.SetContent(
container.NewScroll(container.NewVBox( container.NewScroll(container.NewVBox(
@@ -125,111 +134,15 @@ func (v View) About(ffmpegVersion string, ffprobeVersion string, ffplayVersion s
)), )),
v.getAboutFfmpeg(ffmpegVersion), v.getAboutFfmpeg(ffmpegVersion),
v.getAboutFfprobe(ffprobeVersion), v.getAboutFfprobe(ffprobeVersion),
v.getAboutFfplay(ffplayVersion), widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
widget.NewCard(v.app.GetLocalizerService().GetMessage("AlsoUsedProgram"), "", v.getOther()), MessageID: "AlsoUsedProgram",
}), "", v.getOther()),
)), )),
) )
view.CenterOnScreen() view.CenterOnScreen()
view.Show() view.Show()
} }
func (v View) HelpFFplay() {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage("helpFFplay"))
view.Resize(fyne.Size{Width: 800, Height: 550})
view.SetFixedSize(true)
data := [][]string{
[]string{
v.app.GetLocalizerService().GetMessage("helpFFplayKeys"),
v.app.GetLocalizerService().GetMessage("helpFFplayDescription"),
},
[]string{
"Q, ESC",
v.app.GetLocalizerService().GetMessage("helpFFplayQuit"),
},
[]string{
"F, " + v.app.GetLocalizerService().GetMessage("helpFFplayDoubleClickLeftMouseButton"),
v.app.GetLocalizerService().GetMessage("helpFFplayToggleFullScreen"),
},
[]string{
"P, " +
v.app.GetLocalizerService().GetMessage("helpFFplayKeySpace"),
v.app.GetLocalizerService().GetMessage("helpFFplayPause"),
},
[]string{
"M",
v.app.GetLocalizerService().GetMessage("helpFFplayToggleMute"),
},
[]string{
"9, /",
v.app.GetLocalizerService().GetMessage("helpFFplayDecreaseVolume"),
},
[]string{
"0, *",
v.app.GetLocalizerService().GetMessage("helpFFplayIncreaseVolume"),
},
[]string{
v.app.GetLocalizerService().GetMessage("helpFFplayKeyLeft"),
v.app.GetLocalizerService().GetMessage("helpFFplaySeekBackward10Seconds"),
},
[]string{
v.app.GetLocalizerService().GetMessage("helpFFplayKeyRight"),
v.app.GetLocalizerService().GetMessage("helpFFplaySeekForward10Seconds"),
},
[]string{
v.app.GetLocalizerService().GetMessage("helpFFplayKeyDown"),
v.app.GetLocalizerService().GetMessage("helpFFplaySeekBackward1Minute"),
},
[]string{
v.app.GetLocalizerService().GetMessage("helpFFplayKeyUp"),
v.app.GetLocalizerService().GetMessage("helpFFplaySeekBForward1Minute"),
},
[]string{
"Page Down",
v.app.GetLocalizerService().GetMessage("helpFFplaySeekBackward10Minutes"),
},
[]string{
"Page Up",
v.app.GetLocalizerService().GetMessage("helpFFplaySeekBForward10Minutes"),
},
[]string{
"S, " + v.app.GetLocalizerService().GetMessage("helpFFplayKeyHoldS"),
v.app.GetLocalizerService().GetMessage("helpFFplayActivateFrameStepMode"),
},
[]string{
"W",
v.app.GetLocalizerService().GetMessage("helpFFplayCycleVideoFiltersOrShowModes"),
},
}
list := widget.NewTable(
func() (int, int) {
return len(data), len(data[0])
},
func() fyne.CanvasObject {
return widget.NewLabel("")
},
func(i widget.TableCellID, o fyne.CanvasObject) {
if i.Row == 0 {
o.(*widget.Label).TextStyle.Bold = true
o.(*widget.Label).SizeName = theme.SizeNameSubHeadingText
}
if i.Col == 0 {
o.(*widget.Label).TextStyle.Bold = true
}
o.(*widget.Label).SetText(data[i.Row][i.Col])
})
list.SetRowHeight(0, 40)
list.SetColumnWidth(0, 200)
list.SetColumnWidth(1, 585)
list.SetRowHeight(2, 55)
view.SetContent(
container.NewScroll(list),
)
view.CenterOnScreen()
view.Show()
}
func (v View) getCopyright() *widget.RichText { func (v View) getCopyright() *widget.RichText {
return widget.NewRichTextFromMarkdown("Copyright (c) 2024 **[Leonid Nikitin (kor-elf)](https://git.kor-elf.net/kor-elf/)**.") return widget.NewRichTextFromMarkdown("Copyright (c) 2024 **[Leonid Nikitin (kor-elf)](https://git.kor-elf.net/kor-elf/)**.")
} }
@@ -239,13 +152,17 @@ func (v View) getAboutFfmpeg(version string) *fyne.Container {
programmName.TextStyle = fyne.TextStyle{Bold: true} programmName.TextStyle = fyne.TextStyle{Bold: true}
programmName.TextSize = 20 programmName.TextSize = 20
programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("programmLink"), &url.URL{ programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "programmLink",
}), &url.URL{
Scheme: "https", Scheme: "https",
Host: "ffmpeg.org", Host: "ffmpeg.org",
Path: "", Path: "",
}) })
licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("licenseLink"), &url.URL{ licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "licenseLink",
}), &url.URL{
Scheme: "https", Scheme: "https",
Host: "ffmpeg.org", Host: "ffmpeg.org",
Path: "legal.html", Path: "legal.html",
@@ -265,39 +182,17 @@ func (v View) getAboutFfprobe(version string) *fyne.Container {
programmName.TextStyle = fyne.TextStyle{Bold: true} programmName.TextStyle = fyne.TextStyle{Bold: true}
programmName.TextSize = 20 programmName.TextSize = 20
programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("programmLink"), &url.URL{ programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "programmLink",
}), &url.URL{
Scheme: "https", Scheme: "https",
Host: "ffmpeg.org", Host: "ffmpeg.org",
Path: "ffprobe.html", Path: "ffprobe.html",
}) })
licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("licenseLink"), &url.URL{ licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
Scheme: "https", MessageID: "licenseLink",
Host: "ffmpeg.org", }), &url.URL{
Path: "legal.html",
})
return container.NewVBox(
programmName,
widget.NewLabel(version),
widget.NewRichTextFromMarkdown("**FFmpeg** is a trademark of **[Fabrice Bellard](http://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."),
widget.NewRichTextFromMarkdown("This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."),
container.NewHBox(programmLink, licenseLink),
)
}
func (v View) getAboutFfplay(version string) *fyne.Container {
programmName := canvas.NewText(" FFplay", colornames.Darkgreen)
programmName.TextStyle = fyne.TextStyle{Bold: true}
programmName.TextSize = 20
programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("programmLink"), &url.URL{
Scheme: "https",
Host: "ffmpeg.org",
Path: "ffplay.html",
})
licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage("licenseLink"), &url.URL{
Scheme: "https", Scheme: "https",
Host: "ffmpeg.org", Host: "ffmpeg.org",
Path: "legal.html", Path: "legal.html",

View File

@@ -1,101 +0,0 @@
package menu
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme"
"image/color"
)
type ViewSettingContract interface {
Main(
save func(*SettingForm) error,
cancel func(),
)
}
type SettingForm struct {
Language kernel.Lang
ThemeInfo theme.ThemeInfoContract
}
type ViewSetting struct {
app kernel.AppContract
themeService theme.ThemeContract
}
func NewViewSetting(app kernel.AppContract, themeService theme.ThemeContract) *ViewSetting {
return &ViewSetting{
app: app,
themeService: themeService,
}
}
func (v ViewSetting) Main(save func(*SettingForm) error, cancel func()) {
errorMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
errorMessage.TextSize = 16
errorMessage.TextStyle = fyne.TextStyle{Bold: true}
viewSettingForm := &SettingForm{
Language: v.app.GetLocalizerService().GetCurrentLanguage(),
ThemeInfo: v.themeService.GetCurrentThemeInfo(),
}
languageItems := []string{}
langByTitle := map[string]kernel.Lang{}
for _, language := range v.app.GetLocalizerService().GetLanguages() {
languageItems = append(languageItems, language.Title)
langByTitle[language.Title] = language
}
selectLanguage := widget.NewSelect(languageItems, func(s string) {
if lang, ok := langByTitle[s]; ok {
viewSettingForm.Language = lang
}
})
selectLanguage.Selected = v.app.GetLocalizerService().GetCurrentLanguage().Title
themeItems := []string{}
themeByTitle := map[string]theme.ThemeInfoContract{}
for _, themeInfo := range v.themeService.List() {
themeItems = append(themeItems, themeInfo.GetTitle())
themeByTitle[themeInfo.GetTitle()] = themeInfo
}
selectTheme := widget.NewSelect(themeItems, func(s string) {
if themeInfo, ok := themeByTitle[s]; ok {
viewSettingForm.ThemeInfo = themeInfo
}
})
selectTheme.Selected = v.themeService.GetCurrentThemeInfo().GetTitle()
form := &widget.Form{
Items: []*widget.FormItem{
{
Text: v.app.GetLocalizerService().GetMessage("menuSettingsLanguage"),
Widget: selectLanguage,
},
{
Text: v.app.GetLocalizerService().GetMessage("menuSettingsTheme"),
Widget: selectTheme,
},
{
Widget: errorMessage,
},
},
SubmitText: v.app.GetLocalizerService().GetMessage("save"),
OnSubmit: func() {
err := save(viewSettingForm)
if err != nil {
errorMessage.Text = err.Error()
}
},
}
if cancel != nil {
form.OnCancel = cancel
form.CancelText = v.app.GetLocalizerService().GetMessage("cancel")
}
messageHead := v.app.GetLocalizerService().GetMessage("settings")
v.app.GetWindow().SetContent(widget.NewCard(messageHead, "", form))
}

12
migration/migration.go Normal file
View File

@@ -0,0 +1,12 @@
package migration
import (
"go.etcd.io/bbolt"
)
func Run(db *bbolt.DB) error {
return db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists([]byte("settings"))
return err
})
}

View File

@@ -1,8 +1,8 @@
package setting package setting
type DirectoryForSavingContract interface { type DirectoryForSavingContract interface {
GetDirectoryForSaving() string GetDirectoryForSaving() (string, error)
SaveDirectoryForSaving(path string) Setting SaveDirectoryForSaving(path string) (Setting, error)
} }
type DirectoryForSaving struct { type DirectoryForSaving struct {
@@ -13,10 +13,10 @@ func NewSettingDirectoryForSaving(settingRepository RepositoryContract) *Directo
return &DirectoryForSaving{settingRepository: settingRepository} return &DirectoryForSaving{settingRepository: settingRepository}
} }
func (setting DirectoryForSaving) GetDirectoryForSaving() string { func (setting DirectoryForSaving) GetDirectoryForSaving() (string, error) {
return setting.settingRepository.GetValue("directoryForSaving") return setting.settingRepository.GetValue("directoryForSaving")
} }
func (setting DirectoryForSaving) SaveDirectoryForSaving(path string) Setting { func (setting DirectoryForSaving) SaveDirectoryForSaving(path string) (Setting, error) {
return setting.settingRepository.CreateOrUpdate("directoryForSaving", path) return setting.settingRepository.CreateOrUpdate("directoryForSaving", path)
} }

View File

@@ -1,6 +1,6 @@
package setting package setting
type Setting struct { type Setting struct {
Code string Code string `json:"code"`
Value string Value string `json:"value"`
} }

View File

@@ -1,39 +1,82 @@
package setting package setting
import ( import (
"fyne.io/fyne/v2" "encoding/json"
"errors"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/db"
"go.etcd.io/bbolt"
) )
type RepositoryContract interface { type RepositoryContract interface {
Create(setting Setting) Setting Create(setting Setting) (Setting, error)
CreateOrUpdate(code string, value string) Setting CreateOrUpdate(code string, value string) (Setting, error)
GetValue(code string) string GetValue(code string) (value string, err error)
} }
type Repository struct { type Repository struct {
app fyne.App db *bbolt.DB
} }
func NewRepository(app fyne.App) *Repository { func NewRepository(db *bbolt.DB) *Repository {
return &Repository{ return &Repository{db}
app: app, }
func (r Repository) GetValue(code string) (value string, err error) {
var setting Setting
err = r.db.View(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("settings"))
if b == nil {
return errors.New("bucket 'settings' not found")
}
val := b.Get([]byte(code))
if val == nil {
return db.ErrRecordNotFound
}
return json.Unmarshal(val, &setting)
})
if err != nil {
return "", err
} }
return setting.Value, nil
} }
func (r Repository) GetValue(code string) string { func (r Repository) Create(setting Setting) (Setting, error) {
return r.app.Preferences().String(code) err := r.db.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("settings"))
if b == nil {
return errors.New("bucket 'settings' not found")
}
data, err := json.Marshal(setting)
if err != nil {
return err
}
return b.Put([]byte(setting.Code), data)
})
return setting, err
} }
func (r Repository) Create(setting Setting) Setting { func (r Repository) CreateOrUpdate(code string, value string) (Setting, error) {
r.app.Preferences().SetString(setting.Code, setting.Value)
return setting
}
func (r Repository) CreateOrUpdate(code string, value string) Setting {
var setting Setting var setting Setting
setting.Code = code setting.Code = code
setting.Value = value setting.Value = value
r.app.Preferences().SetString(code, value) err := r.db.Update(func(tx *bbolt.Tx) error {
return setting b := tx.Bucket([]byte("settings"))
if b == nil {
return errors.New("bucket 'settings' not found")
}
data, err := json.Marshal(setting)
if err != nil {
return err
}
return b.Put([]byte(code), data)
})
return setting, err
} }

View File

@@ -1,28 +0,0 @@
package theme
import "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
type RepositoryContract interface {
GetCode() string
Save(code string) setting.Setting
}
type Repository struct {
settingRepository setting.RepositoryContract
}
func NewRepository(settingRepository setting.RepositoryContract) *Repository {
return &Repository{settingRepository: settingRepository}
}
func (r Repository) GetCode() string {
name := r.settingRepository.GetValue("theme")
if len(name) == 0 {
return "default"
}
return name
}
func (r Repository) Save(code string) setting.Setting {
return r.settingRepository.CreateOrUpdate("theme", code)
}

View File

@@ -1,148 +0,0 @@
package theme
import (
"fyne.io/fyne/v2"
fyneTheme "fyne.io/fyne/v2/theme"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"image/color"
)
type ThemeContract interface {
List() map[string]ThemeInfoContract
GetCurrentThemeInfo() ThemeInfoContract
SetCurrentTheme(themeInfo ThemeInfoContract) error
}
type theme struct {
app kernel.AppContract
repository RepositoryContract
list map[string]ThemeInfoContract
}
func NewTheme(app kernel.AppContract, repository RepositoryContract) ThemeContract {
theme := &theme{
app: app,
repository: repository,
list: getThemes(app.GetLocalizerService()),
}
theme.init()
return theme
}
func (t theme) init() {
themeInfo := t.GetCurrentThemeInfo()
if themeInfo.GetName() == "default" {
t.app.GetAppFyne().Settings().SetTheme(fyneTheme.DefaultTheme())
return
}
t.app.GetAppFyne().Settings().SetTheme(&forcedVariant{theme: fyneTheme.DefaultTheme(), variant: themeInfo.GetVariant()})
}
func (t theme) GetCurrentThemeInfo() ThemeInfoContract {
themes := t.List()
if themeInfo, ok := themes[t.repository.GetCode()]; ok {
return themeInfo
}
return themes["default"]
}
func (t theme) List() map[string]ThemeInfoContract {
return t.list
}
func (t theme) SetCurrentTheme(themeInfo ThemeInfoContract) error {
_ = t.repository.Save(themeInfo.GetName())
if themeInfo.GetName() == "default" {
t.app.GetAppFyne().Settings().SetTheme(fyneTheme.DefaultTheme())
return nil
}
t.app.GetAppFyne().Settings().SetTheme(&forcedVariant{theme: fyneTheme.DefaultTheme(), variant: themeInfo.GetVariant()})
return nil
}
type ThemeInfoContract interface {
GetName() string
GetTitle() string
GetVariant() fyne.ThemeVariant
}
type themeInfo struct {
name string
title string
variant fyne.ThemeVariant
}
func (inf themeInfo) GetName() string {
return inf.name
}
func (inf themeInfo) GetTitle() string {
return inf.title
}
func (inf themeInfo) GetVariant() fyne.ThemeVariant {
return inf.variant
}
func getThemes(localizer kernel.LocalizerContract) map[string]ThemeInfoContract {
themesNameDefault := &themeInfo{
name: "default",
title: localizer.GetMessage("themesNameDefault"),
}
themesNameLight := &themeInfo{
name: "light",
title: localizer.GetMessage("themesNameLight"),
variant: fyneTheme.VariantLight,
}
themesNameDark := &themeInfo{
name: "dark",
title: localizer.GetMessage("themesNameDark"),
variant: fyneTheme.VariantDark,
}
list := map[string]ThemeInfoContract{
"default": themesNameDefault,
"light": themesNameLight,
"dark": themesNameDark,
}
localizer.AddChangeCallback("themesNameDefault", func(text string) {
themesNameDefault.title = text
})
localizer.AddChangeCallback("themesNameLight", func(text string) {
themesNameLight.title = text
})
localizer.AddChangeCallback("themesNameDark", func(text string) {
themesNameDark.title = text
})
return list
}
type forcedVariant struct {
theme fyne.Theme
variant fyne.ThemeVariant
}
func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color {
return f.theme.Color(name, f.variant)
}
func (f *forcedVariant) Font(style fyne.TextStyle) fyne.Resource {
return fyneTheme.DefaultTheme().Font(style)
}
func (f *forcedVariant) Icon(name fyne.ThemeIconName) fyne.Resource {
return fyneTheme.DefaultTheme().Icon(name)
}
func (f *forcedVariant) Size(name fyne.ThemeSizeName) float32 {
return fyneTheme.DefaultTheme().Size(name)
}