Skip to content

Commit addfd14

Browse files
committed
A more complete GUI that allows users to pick the OS, arch and kind.
Ignore binaries. Added cross compiling to the build.sh for windows binaries.
1 parent 966ab54 commit addfd14

File tree

6 files changed

+165
-46
lines changed

6 files changed

+165
-46
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
getgo.exe
33
getgo
44
getgo-arm
5+
getgo-gui
6+
getgo-win.exe
7+
go*.tar.gz

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,17 @@ To try the Fyne version (require installing Fyne and its dependencies):
8383

8484
```
8585
go get lazyhacker.dev/getgo
86-
go run -tags gui,fyne lazyhacker.dev/getgo --gui
86+
go run -tags gui,fyne lazyhacker.dev/getgo
8787
8888
```
8989

90+
** There is a problem with gotk3 and Go 1.16 **
91+
9092
To try the GTK3 version (requires installing the GTK3 development libraries):
9193

9294
```
9395
go get lazyhacker.dev/getgo
94-
go run -tags gui,gtk3 lazyhacker.dev/getgo --gui
96+
go run -tags gui,gtk3 lazyhacker.dev/getgo
9597
9698
```
9799

build.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ GOOS=linux GOARCH=amd64 go build -o getgo
88

99
echo "Building Linux Raspberry Pi command line binary"
1010
GOOS=linux GOARCH=arm go build -o getgo-arm
11+
12+
echo "Building Linux GUI interface"
13+
GOOS=linux GOARCH=amd64 go build -tags gui,fyne -o getgo-gui
14+
15+
echo "Building Windows GUI interface"
16+
CC=x86_64-w64-mingw32-gcc GOOS=windows CGO_ENABLED=1 go build -ldflags -H=windowsgui -tags fyne,gui -o getgo-win.exe

internal/guimain/fyne.go

Lines changed: 146 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,165 @@
33
package guimain
44

55
import (
6-
"image/color"
76
"os"
7+
"runtime"
88

99
"fyne.io/fyne/v2"
1010
"fyne.io/fyne/v2/app"
11-
"fyne.io/fyne/v2/canvas"
11+
"fyne.io/fyne/v2/container"
1212
"fyne.io/fyne/v2/dialog"
1313
"fyne.io/fyne/v2/layout"
14+
"fyne.io/fyne/v2/theme"
1415
"fyne.io/fyne/v2/widget"
15-
"golang.org/x/image/colornames"
1616

1717
"lazyhacker.dev/getgo/internal/lib"
1818
)
1919

20-
func LoadGUI(filename, checksum string) {
20+
/* GetGo describes the elements of the main UI and the data needed by the UI.*/
21+
type GetGo struct {
22+
parent fyne.Window // reference the parent window for the app.
23+
operatingSystem string // GOOS version
24+
architecture string // GOARCH (e.g. amd64, arm, etc.)
25+
kind string // archive or installer
26+
savepath string // directory to save to
27+
filename string // Go binary to download
28+
shasum string // SHA256 of the binary
29+
30+
formInput *widget.Form // Input form for OS, Arch and Kind
31+
32+
// The read-only file info. Using widget.Form as a cheat for the layout.
33+
formFileInfo *widget.Form
34+
35+
lblChecksumValue *widget.Label // Label to display the SHA256 value.
36+
lblSavePath *widget.Label // Label to show the directory to save to.
37+
lblFileName *widget.Label // Label to show the binary filename to download
38+
39+
iconDir *widget.Icon
40+
41+
btnDownload *widget.Button // button to start the download
42+
btnSaveFile *widget.Button // button to pick the save directory
43+
44+
saveDirWidget fyne.CanvasObject // container for the save button and label.
45+
}
46+
47+
/* downloadGo starts the downloading and the corresponding dialogs. */
48+
func (a *GetGo) downloadGo() {
49+
a.filename, a.shasum, _ = lib.LatestVersion(a.operatingSystem, a.architecture, a.kind)
50+
a.lblFileName.SetText(a.filename)
51+
a.lblChecksumValue.SetText(a.shasum)
52+
prog := dialog.NewProgressInfinite("Downloading", "", a.parent)
53+
prog.Show()
54+
err := lib.DownloadAndVerify(a.savepath, a.filename, a.shasum, "")
55+
prog.Hide()
56+
if err != nil {
57+
dialog.ShowError(err, a.parent)
58+
return
59+
}
60+
dialog.ShowInformation("Complete!", "File downloaded.", a.parent)
61+
62+
}
63+
64+
/*
65+
Init should be called first to initialize the UI elements and default values.
66+
It can be called again to reset the UI elements back to the defaults.
67+
*/
68+
func (a *GetGo) Init(w fyne.Window) {
69+
70+
defaultkind := "archive"
71+
72+
pwd, _ := os.Getwd()
73+
74+
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
75+
defaultkind = "installer"
76+
}
77+
78+
a.parent = w
79+
a.operatingSystem = runtime.GOOS
80+
a.architecture = runtime.GOARCH
81+
a.savepath = pwd
82+
a.kind = defaultkind
83+
a.lblChecksumValue = widget.NewLabel("")
84+
a.lblFileName = widget.NewLabel("")
85+
86+
// Select boxes for OS, arch and kind
87+
selOS := widget.NewSelect(lib.OperatingSystems,
88+
func(s string) {
89+
a.operatingSystem = s
90+
},
91+
)
92+
selArch := widget.NewSelect(lib.Architectures, func(s string) {
93+
a.architecture = s
94+
},
95+
)
96+
selKind := widget.NewSelect(
97+
[]string{"archive", "installer"},
98+
func(s string) {
99+
a.kind = s
100+
},
101+
)
102+
103+
// Add the selection dropdowns into a single form.
104+
a.formInput = widget.NewForm(
105+
widget.NewFormItem("OS", selOS),
106+
widget.NewFormItem("Arch", selArch),
107+
widget.NewFormItem("Kind", selKind),
108+
)
109+
110+
// Set the default selection.
111+
selOS.SetSelected(a.operatingSystem)
112+
selArch.SetSelected(a.architecture)
113+
selKind.SetSelected(a.kind)
114+
115+
a.btnSaveFile = widget.NewButtonWithIcon("", theme.FolderIcon(),
116+
func() {
117+
dialog.ShowFolderOpen(
118+
func(uri fyne.ListableURI, err error) {
119+
// TODO: Should look into data binding for these fields.
120+
a.savepath = uri.Path()
121+
a.lblSavePath.SetText(uri.Path())
122+
}, a.parent)
123+
124+
},
125+
)
126+
127+
// Default to the directory the app was launched.
128+
a.lblSavePath = widget.NewLabel(pwd)
129+
130+
a.formFileInfo = widget.NewForm(
131+
widget.NewFormItem("File", a.lblFileName),
132+
widget.NewFormItem("Sha256", a.lblChecksumValue),
133+
)
134+
135+
a.btnDownload = widget.NewButton("Download",
136+
func() {
137+
a.downloadGo()
138+
})
139+
140+
// Want two column side-by-side layout similar to a form but widget.Form
141+
// takes a string and not an icon for the input label.
142+
a.saveDirWidget = container.New(layout.NewHBoxLayout(),
143+
a.btnSaveFile,
144+
a.lblSavePath,
145+
)
146+
}
147+
148+
/*
149+
LoadGUI is the main entry point to start an Fyne app. It will initialize an
150+
app, create a window, set the container and start the app.
151+
*/
152+
func LoadGUI() {
21153
a := app.New()
22154
w := a.NewWindow("GetGo")
23155

24-
wd, _ := os.Getwd()
25-
dirLabel := canvas.NewText("Directory", colornames.Gray)
26-
dirValue := canvas.NewText(wd, color.White)
27-
fileLabel := canvas.NewText("Latest Stable", colornames.Gray)
28-
fileValue := canvas.NewText(filename, color.White)
29-
shaLabel := canvas.NewText("Sha256", colornames.Gray)
30-
shaValue := canvas.NewText(checksum, color.White)
31-
32-
formGrid := fyne.NewContainerWithLayout(
33-
layout.NewFormLayout(),
34-
dirLabel, dirValue,
35-
fileLabel, fileValue,
36-
shaLabel, shaValue)
37-
38-
grid := fyne.NewContainerWithLayout(
39-
layout.NewVBoxLayout(),
40-
formGrid,
41-
widget.NewButton("Download Latest",
42-
func() {
43-
prog := dialog.NewProgressInfinite("Downloading", fileValue.Text, w)
44-
prog.Show()
45-
err := lib.DownloadAndVerify(dirValue.Text, filename, checksum, "")
46-
prog.Hide()
47-
if err != nil {
48-
dialog.ShowError(err, w)
49-
return
50-
}
51-
dialog.ShowInformation("Complete!", "File downloaded.", w)
52-
},
53-
),
54-
)
55-
w.SetContent(grid)
156+
ui := GetGo{}
157+
ui.Init(w)
158+
c := container.New(layout.NewVBoxLayout(),
159+
ui.formInput,
160+
ui.saveDirWidget,
161+
ui.btnDownload,
162+
ui.formFileInfo,
163+
)
164+
165+
w.SetContent(c)
56166
w.ShowAndRun()
57167
}

internal/lib/download.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ const (
2020
GO_DOWNLOAD_URL = "https://golang.org/dl" // redirects to https://dl.google.com/go
2121
)
2222

23+
var (
24+
OperatingSystems = []string{"aix", "darwin", "dragonfly", "freebsd", "illumos", "js", "linux", "netbsd", "openbsd", "plan9", "solaris", "windows"}
25+
Architectures = []string{"386", "amd64", "arm", "arm64", "ppc64", "ppc64le", "mips", "mips64", "mips64le", "riscv64", "s390x", "wasm"}
26+
)
27+
2328
// goFilesStruct maps to the JSON format from STABLE_VERSION.
2429
type goFilesStruct struct {
2530
Version string `json:"version"`

main_gui.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,13 @@ package main // import "lazyhacker.dev/getgo"
44

55
import (
66
"flag"
7-
"log"
87

98
"lazyhacker.dev/getgo/internal/guimain"
10-
"lazyhacker.dev/getgo/internal/lib"
119
)
1210

1311
func main() {
1412

1513
flag.Parse()
1614

17-
stable, checksum, err := lib.LatestVersion("windows", "amd64", "installer")
18-
if err != nil {
19-
log.Fatalf("%v", err)
20-
}
21-
22-
guimain.LoadGUI(stable, checksum)
15+
guimain.LoadGUI()
2316
}

0 commit comments

Comments
 (0)