Add log viewer buttons and live log refresh for conversions
This commit is contained in:
parent
8b872672f3
commit
c7690f7f61
95
main.go
95
main.go
|
|
@ -146,6 +146,56 @@ func getLogsDir() string {
|
||||||
return logsDirPath
|
return logsDirPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// openLogViewer opens a simple dialog showing the log content. If live is true, it auto-refreshes.
|
||||||
|
func (s *appState) openLogViewer(title, path string, live bool) {
|
||||||
|
if strings.TrimSpace(path) == "" {
|
||||||
|
dialog.ShowInformation("No Log", "No log available.", s.window)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
dialog.ShowError(fmt.Errorf("failed to read log: %w", err), s.window)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
text := widget.NewMultiLineEntry()
|
||||||
|
text.SetText(string(data))
|
||||||
|
text.Wrapping = fyne.TextWrapWord
|
||||||
|
text.Disable()
|
||||||
|
scroll := container.NewVScroll(text)
|
||||||
|
scroll.SetMinSize(fyne.NewSize(600, 400))
|
||||||
|
|
||||||
|
stop := make(chan struct{})
|
||||||
|
if live {
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stop:
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
b, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
b = []byte(fmt.Sprintf("failed to read log: %v", err))
|
||||||
|
}
|
||||||
|
content := string(b)
|
||||||
|
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
||||||
|
text.SetText(content)
|
||||||
|
}, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
closeBtn := widget.NewButton("Close", func() {
|
||||||
|
close(stop)
|
||||||
|
})
|
||||||
|
content := container.NewBorder(nil, container.NewHBox(layout.NewSpacer(), closeBtn), nil, nil, scroll)
|
||||||
|
d := dialog.NewCustomWithoutButtons(title, content, s.window)
|
||||||
|
d.Show()
|
||||||
|
}
|
||||||
|
|
||||||
type formatOption struct {
|
type formatOption struct {
|
||||||
Label string
|
Label string
|
||||||
Ext string
|
Ext string
|
||||||
|
|
@ -250,6 +300,7 @@ type appState struct {
|
||||||
convertStatus string
|
convertStatus string
|
||||||
convertActiveIn string
|
convertActiveIn string
|
||||||
convertActiveOut string
|
convertActiveOut string
|
||||||
|
convertActiveLog string
|
||||||
convertProgress float64
|
convertProgress float64
|
||||||
convertFPS float64
|
convertFPS float64
|
||||||
convertSpeed float64
|
convertSpeed float64
|
||||||
|
|
@ -3279,11 +3330,26 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
convertBtn.Disable()
|
convertBtn.Disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewLogBtn := widget.NewButton("View Log", func() {
|
||||||
|
if state.convertActiveLog == "" {
|
||||||
|
dialog.ShowInformation("No Log", "No conversion log available.", state.window)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.openLogViewer("Conversion Log", state.convertActiveLog, state.convertBusy)
|
||||||
|
})
|
||||||
|
viewLogBtn.Importance = widget.LowImportance
|
||||||
|
if state.convertActiveLog == "" {
|
||||||
|
viewLogBtn.Disable()
|
||||||
|
}
|
||||||
if state.convertBusy {
|
if state.convertBusy {
|
||||||
// Allow queueing new jobs while current convert runs; just disable Convert Now and enable Cancel.
|
// Allow queueing new jobs while current convert runs; just disable Convert Now and enable Cancel.
|
||||||
convertBtn.Disable()
|
convertBtn.Disable()
|
||||||
cancelBtn.Enable()
|
cancelBtn.Enable()
|
||||||
addQueueBtn.Enable()
|
addQueueBtn.Enable()
|
||||||
|
if state.convertActiveLog != "" {
|
||||||
|
viewLogBtn.Enable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Also disable if queue is running
|
// Also disable if queue is running
|
||||||
if state.jobQueue != nil && state.jobQueue.IsRunning() {
|
if state.jobQueue != nil && state.jobQueue.IsRunning() {
|
||||||
|
|
@ -3323,7 +3389,7 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
|
|
||||||
leftControls := container.NewHBox(resetBtn, autoCompareCheck)
|
leftControls := container.NewHBox(resetBtn, autoCompareCheck)
|
||||||
centerStatus := container.NewHBox(activity, statusLabel)
|
centerStatus := container.NewHBox(activity, statusLabel)
|
||||||
rightControls := container.NewHBox(cancelBtn, addQueueBtn, convertBtn)
|
rightControls := container.NewHBox(cancelBtn, viewLogBtn, addQueueBtn, convertBtn)
|
||||||
actionInner := container.NewBorder(nil, nil, leftControls, rightControls, centerStatus)
|
actionInner := container.NewBorder(nil, nil, leftControls, rightControls, centerStatus)
|
||||||
actionBar := ui.TintedBar(convertColor, actionInner)
|
actionBar := ui.TintedBar(convertColor, actionInner)
|
||||||
|
|
||||||
|
|
@ -5469,6 +5535,7 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
s.convertProgress = 0
|
s.convertProgress = 0
|
||||||
s.convertActiveIn = src.Path
|
s.convertActiveIn = src.Path
|
||||||
s.convertActiveOut = outPath
|
s.convertActiveOut = outPath
|
||||||
|
s.convertActiveLog = ""
|
||||||
logFile, logPath, logErr := createConversionLog(src.Path, outPath, args)
|
logFile, logPath, logErr := createConversionLog(src.Path, outPath, args)
|
||||||
if logErr != nil {
|
if logErr != nil {
|
||||||
logging.Debug(logging.CatFFMPEG, "conversion log open failed: %v", logErr)
|
logging.Debug(logging.CatFFMPEG, "conversion log open failed: %v", logErr)
|
||||||
|
|
@ -5624,6 +5691,7 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
s.convertBusy = false
|
s.convertBusy = false
|
||||||
s.convertActiveIn = ""
|
s.convertActiveIn = ""
|
||||||
s.convertActiveOut = ""
|
s.convertActiveOut = ""
|
||||||
|
s.convertActiveLog = ""
|
||||||
s.convertProgress = 0
|
s.convertProgress = 0
|
||||||
setStatus("Cancelled")
|
setStatus("Cancelled")
|
||||||
}, false)
|
}, false)
|
||||||
|
|
@ -5667,6 +5735,7 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
s.convertBusy = false
|
s.convertBusy = false
|
||||||
s.convertActiveIn = ""
|
s.convertActiveIn = ""
|
||||||
s.convertActiveOut = ""
|
s.convertActiveOut = ""
|
||||||
|
s.convertActiveLog = ""
|
||||||
s.convertProgress = 0
|
s.convertProgress = 0
|
||||||
setStatus("Failed")
|
setStatus("Failed")
|
||||||
}, false)
|
}, false)
|
||||||
|
|
@ -5686,6 +5755,7 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
s.convertBusy = false
|
s.convertBusy = false
|
||||||
s.convertActiveIn = ""
|
s.convertActiveIn = ""
|
||||||
s.convertActiveOut = ""
|
s.convertActiveOut = ""
|
||||||
|
s.convertActiveLog = ""
|
||||||
s.convertProgress = 0
|
s.convertProgress = 0
|
||||||
setStatus("Failed")
|
setStatus("Failed")
|
||||||
}, false)
|
}, false)
|
||||||
|
|
@ -5698,6 +5768,7 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
s.convertBusy = false
|
s.convertBusy = false
|
||||||
s.convertActiveIn = ""
|
s.convertActiveIn = ""
|
||||||
s.convertActiveOut = ""
|
s.convertActiveOut = ""
|
||||||
|
s.convertActiveLog = ""
|
||||||
s.convertProgress = 100
|
s.convertProgress = 100
|
||||||
setStatus("Done")
|
setStatus("Done")
|
||||||
|
|
||||||
|
|
@ -7075,8 +7146,28 @@ func buildInspectView(state *appState) fyne.CanvasObject {
|
||||||
})
|
})
|
||||||
copyBtn.Importance = widget.LowImportance
|
copyBtn.Importance = widget.LowImportance
|
||||||
|
|
||||||
|
logPath := ""
|
||||||
|
if state.inspectFile != nil {
|
||||||
|
base := strings.TrimSuffix(filepath.Base(state.inspectFile.Path), filepath.Ext(state.inspectFile.Path))
|
||||||
|
p := filepath.Join(getLogsDir(), base+conversionLogSuffix)
|
||||||
|
if _, err := os.Stat(p); err == nil {
|
||||||
|
logPath = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewLogBtn := widget.NewButton("View Conversion Log", func() {
|
||||||
|
if logPath == "" {
|
||||||
|
dialog.ShowInformation("No Log", "No conversion log found for this file.", state.window)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.openLogViewer("Conversion Log", logPath, false)
|
||||||
|
})
|
||||||
|
viewLogBtn.Importance = widget.LowImportance
|
||||||
|
if logPath == "" {
|
||||||
|
viewLogBtn.Disable()
|
||||||
|
}
|
||||||
|
|
||||||
// Action buttons
|
// Action buttons
|
||||||
actionButtons := container.NewHBox(loadBtn, copyBtn, clearBtn)
|
actionButtons := container.NewHBox(loadBtn, copyBtn, viewLogBtn, clearBtn)
|
||||||
|
|
||||||
// Main layout: left side is video player, right side is metadata
|
// Main layout: left side is video player, right side is metadata
|
||||||
leftColumn := container.NewBorder(
|
leftColumn := container.NewBorder(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user