From 4a516cbed81ab7600ad9b622ecd47b0dfe8fad4b Mon Sep 17 00:00:00 2001 From: KemoNine Date: Sun, 30 Aug 2020 19:46:17 -0400 Subject: [PATCH] Further implementation of UI --- cmd/ui/ui.go | 187 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 173 insertions(+), 14 deletions(-) diff --git a/cmd/ui/ui.go b/cmd/ui/ui.go index f80fd42..38c6a0c 100644 --- a/cmd/ui/ui.go +++ b/cmd/ui/ui.go @@ -1,18 +1,23 @@ package main import ( + "fmt" "io" "log" + "math" + "net" "os/exec" + "strings" "time" "github.com/eiannone/keyboard" - "github.com/gdamore/tcell" + "github.com/guillermo/go.procmeminfo" "github.com/rivo/tview" ) const ( + CMD_FINDMNT = "/usr/bin/findmnt" CMD_FIM = "/usr/local/bin/pf-fim.sh" SLIDESHOW_INTERVAL = 300 * time.Second ) @@ -99,24 +104,178 @@ func main() { }() // Run fim - if err := fim.Run(); err != nil { - // Unwrap the error a bit so we can find out if a signal killed fim or something else - // An exit code of -1 means the program didn't exit in time or was terminated by a signal (per the docs) - if exitError, ok := err.(*exec.ExitError); ok && exitError.ExitCode() != -1 { - log.Fatalf("Error running fim : %s", err) - } - } + // if err := fim.Run(); err != nil { + // // Unwrap the error a bit so we can find out if a signal killed fim or something else + // // An exit code of -1 means the program didn't exit in time or was terminated by a signal (per the docs) + // if exitError, ok := err.(*exec.ExitError); ok && exitError.ExitCode() != -1 { + // log.Fatalf("Error running fim : %s", err) + // } + // } // Stop fim slideshow advancing go routine close(stop_ticker) + // Memory info for status panel + meminfo := &procmeminfo.MemInfo{} + err = meminfo.Update() + if err != nil { + log.Printf("Error getting memory info : %s", err) + } + + // Network interfaces for status panel + ifaces, err := net.Interfaces() + if err != nil { + log.Printf("Error getting netork interfaces : %s", err) + return + } + + // Disk use + findmntOut, _ := exec.Command(CMD_FINDMNT, "-n", "-l", + "-o", "TARGET,USE%", + "-t", "ext4,exfat,vfat,btrfs,zfs,xfs").Output() + filesystems := strings.Split(strings.Trim(string(findmntOut), "\n"), "\n") + // Run config UI when slideshow stops app := tview.NewApplication() - frame := tview.NewFrame(tview.NewBox().SetBackgroundColor(tcell.ColorBlack)). - SetBorders(2, 2, 2, 2, 4, 4). - AddText("PiFrame", true, tview.AlignCenter, tcell.ColorWhite). - AddText("Configuration Utility", true, tview.AlignCenter, tcell.ColorRed) - if err := app.SetRoot(frame, true).EnableMouse(true).Run(); err != nil { - log.Fatalf("Error running UI : %s", err) + + // Header + headerTitle := tview.NewTextView(). + SetText("PiFrame"). + SetTextAlign(tview.AlignCenter). + SetTextColor(tcell.ColorAqua) + + headerSubTitle := tview.NewTextView(). + SetText("Management Utility"). + SetTextAlign(tview.AlignCenter). + SetTextColor(tcell.ColorSilver) + header := tview.NewFlex(). + SetDirection(tview.FlexRow) + header.AddItem(headerTitle, 0, 1, false). + AddItem(headerSubTitle, 0, 1, false) + + // Footer fields (Left Column) + exitButton := tview.NewButton("Exit"). + SetSelectedFunc(func() { + app.Stop() + }) + exitButton.SetLabelColor(tcell.ColorBlack). + SetBorder(true). + SetBorderColor(tcell.ColorBlack). + SetBackgroundColor(tcell.ColorGreen). + SetRect(0, 0, 22, 3) + + rebootButton := tview.NewButton("Reboot"). + SetSelectedFunc(func() { + app.Stop() + }) + rebootButton.SetLabelColor(tcell.ColorBlack). + SetBorder(true). + SetBorderColor(tcell.ColorBlack). + SetBackgroundColor(tcell.ColorYellow). + SetRect(0, 0, 22, 3) + + powerOffButton := tview.NewButton("Power Off"). + SetSelectedFunc(func() { + app.Stop() + }) + powerOffButton.SetLabelColor(tcell.ColorBlack). + SetBorder(true). + SetBorderColor(tcell.ColorBlack). + SetBackgroundColor(tcell.ColorRed). + SetRect(0, 0, 22, 3) + + // Footer + footer := tview.NewFlex() + footer.AddItem(exitButton, 0, 1, false). + AddItem(rebootButton, 0, 1, false). + AddItem(powerOffButton, 0, 1, false) + + // Setup menu + menu := tview.NewFlex(). + SetDirection(tview.FlexRow) + menu.SetTitle("Menu"). + SetBorder(true). + SetTitleColor(tcell.ColorAqua) + + // Setup main panel (Center column) + main := tview.NewFlex(). + SetDirection(tview.FlexRow) + main.SetTitle(""). + SetBorder(true) + + // Side bar fields + sideBarMemoryTitle := tview.NewTextView(). + SetText("Memory Use (Mb)"). + SetTextColor(tcell.ColorYellow) + divisor := math.Pow(1024.0, 2.0) + sideBarMemoryStats := tview.NewTextView(). + SetText(fmt.Sprintf(" %.1f / %.1f", + float64(meminfo.Used())/divisor, + float64(meminfo.Total())/divisor)) + sideBarSwapTitle := tview.NewTextView(). + SetText("Swap Use"). + SetTextColor(tcell.ColorYellow) + sideBarSwapStats := tview.NewTextView(). + SetText(fmt.Sprintf(" %d%%", meminfo.Swap())) + sideBarFilesystemTitle := tview.NewTextView(). + SetText("Disk Use"). + SetTextColor(tcell.ColorYellow) + var sideBarFilesystems []*tview.TextView + for _, i := range filesystems { + filesystemAsTextView := tview.NewTextView(). + SetText(fmt.Sprintf(" %s", i)) + sideBarFilesystems = append(sideBarFilesystems, filesystemAsTextView) + } + sideBarIPAddressesTitle := tview.NewTextView(). + SetText("IP Addresses"). + SetTextColor(tcell.ColorYellow) + var sideBarIPAddresses []*tview.TextView + for _, i := range ifaces { + addrs, err := i.Addrs() + if err != nil { + log.Printf("Error getting interface addresses : %s", err) + continue + } + for _, a := range addrs { + ipAsTextView := tview.NewTextView(). + SetText(fmt.Sprintf(" %v : %s", i.Name, a.String())) + sideBarIPAddresses = append(sideBarIPAddresses, ipAsTextView) + } + } + + // Setup side bar (Right column) + sideBar := tview.NewFlex(). + SetDirection(tview.FlexRow) + sideBar.SetTitle("System Info"). + SetBorder(true). + SetTitleColor(tcell.ColorAqua) + sideBar.AddItem(sideBarMemoryTitle, 1, 1, false) + sideBar.AddItem(sideBarMemoryStats, 1, 1, false) + sideBar.AddItem(sideBarSwapTitle, 1, 1, false) + sideBar.AddItem(sideBarSwapStats, 1, 1, false) + sideBar.AddItem(sideBarFilesystemTitle, 1, 1, false) + for _, filesystemAsTextView := range sideBarFilesystems { + sideBar.AddItem(filesystemAsTextView, 1, 1, false) + } + sideBar.AddItem(sideBarIPAddressesTitle, 1, 1, false) + for _, ipAsTextView := range sideBarIPAddresses { + sideBar.AddItem(ipAsTextView, 1, 1, false) + } + + // Main UI + grid := tview.NewGrid(). + SetRows(2, 0, 4). + SetColumns(25, 50, 50). + SetBorders(true). + AddItem(header, 0, 0, 1, 3, 0, 0, false). + AddItem(footer, 2, 0, 1, 3, 0, 0, false) + + grid.AddItem(menu, 1, 0, 1, 1, 0, 100, true). + AddItem(main, 1, 1, 1, 1, 0, 100, false). + AddItem(sideBar, 1, 2, 1, 1, 0, 100, false) + + // Show UI and panic if there are any errors + if err := app.SetRoot(grid, true).EnableMouse(false).Run(); err != nil { + panic(err) } }