From a221d18d337165840cb1661a9f2c48b28b886224 Mon Sep 17 00:00:00 2001 From: Belac Darkstorm Date: Tue, 4 Apr 2017 07:54:04 -0500 Subject: [PATCH 1/2] Starting UI remake work --- app.go => gxui/app.go | 0 gxui/main.go | 82 ++++++++++++++ gxui/setup.go | 208 ++++++++++++++++++++++++++++++++++ strList.go => gxui/strList.go | 0 gxui/ui.go | 66 +++++++++++ main.go | 46 +++++--- setup.go | 2 - ui.go | 65 +---------- update.go | 2 + 9 files changed, 390 insertions(+), 81 deletions(-) rename app.go => gxui/app.go (100%) create mode 100644 gxui/main.go create mode 100644 gxui/setup.go rename strList.go => gxui/strList.go (100%) create mode 100644 gxui/ui.go diff --git a/app.go b/gxui/app.go similarity index 100% rename from app.go rename to gxui/app.go diff --git a/gxui/main.go b/gxui/main.go new file mode 100644 index 0000000..14cdb34 --- /dev/null +++ b/gxui/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + + "github.com/nelsam/gxui" + "github.com/nelsam/gxui/drivers/gl" + "github.com/nelsam/gxui/themes/dark" + "github.com/nelsam/gxui/themes/light" +) + +const ( + version = "1.1.0.0" + defIni = "[basic]\ntheme=dk" +) + +var ( + dr gxui.Driver + th gxui.Theme + master map[string][]app + linmaster map[string][]app + cats []string + lin []string + wine bool + comEnbld bool + darkTheme = true +) + +func main() { + updated := false + os.MkdirAll("PortableApps/LinuxPACom", 0777) + stat, err := versionDL() + if stat { + res := getVersionFileInfo() + if res != "Error!" { + stat, err = checkForUpdate(res) + if stat { + downloadUpdate(res) + updated = true + } else { + fmt.Println(err) + } + } else { + fmt.Println("Failed Version File Info") + } + } else { + fmt.Println(err) + } + if updated { + cmd := exec.Command("./LinuxPA") + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Start() + } else { + master = make(map[string][]app) + linmaster = make(map[string][]app) + gl.StartDriver(appMain) + } +} + +func appMain(dri gxui.Driver) { + dr = dri + setup() + if darkTheme { + th = dark.CreateTheme(dr) + } else { + th = light.CreateTheme(dr) + } + th = dark.CreateTheme(dr) + ui() +} + +func contains(arr []string, str string) bool { + for _, v := range arr { + if v == str { + return true + } + } + return false +} diff --git a/gxui/setup.go b/gxui/setup.go new file mode 100644 index 0000000..0874dd2 --- /dev/null +++ b/gxui/setup.go @@ -0,0 +1,208 @@ +package main + +import ( + "bufio" + "fmt" + "image" + "image/draw" + _ "image/png" + "os" + "reflect" + "sort" + "strings" + + "github.com/nelsam/gxui" +) + +func setup() { + PortableAppsFold, err := os.Open("PortableApps") + if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() { + os.Mkdir("PortableApps", 0777) + PortableAppsFold, err = os.Open("PortableApps") + if err != nil { + panic("Can't find PortableApps folder and can't create one!") + } + } + if _, err = os.Open("PortableApps/LinuxPACom"); err != nil { + os.Mkdir("PortableApps/LinuxPACom", 0777) + } + fmt.Println(err) + _, err = os.Open("PortableApps/LinuxPACom/common.sh") + if err == nil { + comEnbld = true + } + fi, err := os.Open("PortableApps/LinuxPACom/Info.ini") + if err != nil { + fi, err = os.Create("PortableApps/LinuxPACom/Info.ini") + if err == nil { + wrt := bufio.NewWriter(fi) + wrt.WriteString(defIni) + wrt.Flush() + } + } + if err == nil { + rdr := bufio.NewReader(fi) + for err != nil { + ln, _, error := rdr.ReadLine() + err = error + str := string(ln) + if strings.HasPrefix(str, "theme=") { + str = strings.TrimPrefix(str, "theme=") + if str == "lt" { + darkTheme = false + } + } + } + } + PAFolds, _ := PortableAppsFold.Readdirnames(-1) + sort.Strings(PAFolds) + for _, v := range PAFolds { + fold, _ := os.Open("PortableApps/" + v) + if stat, _ := fold.Stat(); stat.IsDir() && stat.Name() != "PortableApps.com" && stat.Name() != "LinuxPACom" { + ap := processApp("PortableApps/" + v) + if !reflect.DeepEqual(ap, app{}) { + if _, ok := master[ap.cat]; !ok { + cats = append(cats, ap.cat) + sort.Strings(cats) + } + if len(ap.lin) != 0 { + if _, ok := linmaster[ap.cat]; !ok { + lin = append(lin, ap.cat) + sort.Strings(lin) + } + } + master[ap.cat] = append(master[ap.cat], ap) + if len(ap.lin) != 0 { + linmaster[ap.cat] = append(linmaster[ap.cat], ap) + } + } + } + } +} + +func processApp(fold string) (out app) { + wd, _ := os.Getwd() + out.dir = wd + "/" + fold + out.ini = findInfo(fold) + if out.ini != nil { + out.name = getName(out.ini) + out.ini = findInfo(fold) + out.cat = getCat(out.ini) + out.ini = findInfo(fold) + } + if out.name == "" { + out.name = strings.TrimPrefix(fold, "PortableApps/") + } + if out.cat == "" { + out.cat = "Other" + } + out.icon = getIcon(fold) + folder, _ := os.Open(fold) + fis, _ := folder.Readdirnames(-1) + for _, v := range fis { + tmp, _ := os.Open(fold + "/" + v) + if stat, _ := tmp.Stat(); stat.IsDir() { + continue + } + if strings.HasSuffix(strings.ToLower(v), ".appimage") { + out.appimg = append(out.appimg, v) + out.ex = append(out.ex, v) + out.lin = append(out.lin, v) + } else if strings.HasSuffix(strings.ToLower(v), ".exe") { + out.ex = append(out.ex, v) + } else { + btys := make([]byte, 4) + rdr := bufio.NewReader(tmp) + rdr.Read(btys) + if (strings.Contains(strings.ToLower(string(btys)), "elf") && !strings.HasSuffix(strings.ToLower(v), ".so") && !strings.Contains(v, ".so.")) || strings.HasPrefix(strings.ToLower(string(btys)), "#!") { + out.ex = append(out.ex, v) + out.lin = append(out.lin, v) + } + } + } + if len(out.ex) == 0 { + return app{} + } + if len(out.lin) == 0 { + out.name += " (Wine)" + } + return +} + +func getCat(ini *os.File) string { + rdr := bufio.NewReader(ini) + var ret string + for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() { + if strings.HasPrefix(string(line), "Category=") { + ret = strings.TrimPrefix(string(line), "Category=") + break + } + } + rdr.Reset(ini) + return ret +} + +func getName(ini *os.File) string { + rdr := bufio.NewReader(ini) + var ret string + for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() { + if strings.HasPrefix(string(line), "Name=") { + ret = strings.TrimPrefix(string(line), "Name=") + break + } + } + rdr.Reset(ini) + return ret +} + +func getIcon(fold string) gxui.Texture { + var pic *os.File + if folder, err := os.Open(fold + "/App/AppInfo"); err == nil { + fis, _ := folder.Readdir(-1) + var pics []string + for _, v := range fis { + if !v.IsDir() && strings.HasSuffix(strings.ToLower(v.Name()), ".png") && strings.HasPrefix(strings.ToLower(v.Name()), "appicon_") { + pics = append(pics, v.Name()) + } + } + sort.Strings(pics) + if len(pics) > 1 { + var ind int + if !contains(pics, "appicon_32.png") { + ind = len(pics) - 1 + } else { + ind = sort.SearchStrings(pics, "appicon_32.png") + } + pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind]) + } + } else if fi, err := os.Open(fold + "/appicon.png"); err == nil { + pic = fi + } else { + return nil + } + img, _, err := image.Decode(pic) + if err != nil { + return nil + } + rgba := image.NewRGBA(img.Bounds()) + draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src) + ret := dr.CreateTexture(rgba, 1) + return ret +} + +func findInfo(fold string) *os.File { + tmp, err := os.Open(fold + "/App/AppInfo") + if err == nil { + fis, _ := tmp.Readdirnames(-1) + for _, v := range fis { + if strings.ToLower(v) == "appinfo.ini" { + tmp, _ := os.Open(fold + "/App/AppInfo/" + v) + return tmp + } + } + } + if fi, err := os.Open(fold + "/appinfo.ini"); err == nil { + return fi + } + return nil +} diff --git a/strList.go b/gxui/strList.go similarity index 100% rename from strList.go rename to gxui/strList.go diff --git a/gxui/ui.go b/gxui/ui.go new file mode 100644 index 0000000..8c83a87 --- /dev/null +++ b/gxui/ui.go @@ -0,0 +1,66 @@ +package main + +import ( + "os" + "os/exec" + + "github.com/nelsam/gxui" +) + +func ui() { + catListAdap := &StrList{} + appListAdap := &catAdap{} + catListAdap.SetStrings(lin) + win := th.CreateWindow(500, 500, "LinuxPA") + top := th.CreateLinearLayout() + top.SetDirection(gxui.BottomToTop) + splBox := th.CreateLinearLayout() + spl := th.CreateSplitterLayout() + spl.SetOrientation(gxui.Horizontal) + catList := th.CreateList() + catList.SetAdapter(catListAdap) + catList.OnSelectionChanged(func(it gxui.AdapterItem) { + appListAdap.setCat(it.(string)) + }) + appList := th.CreateTree() + appList.SetAdapter(appListAdap) + spl.AddChild(catList) + spl.AddChild(appList) + splBox.AddChild(spl) + butBox := th.CreateLinearLayout() + butBox.SetDirection(gxui.LeftToRight) + if _, err := exec.LookPath("wine"); err == nil { + wineBut := th.CreateButton() + wineBut.SetType(gxui.ToggleButton) + wineBut.SetChecked(wine) + wineBut.SetText("Show Windows Apps") + wineBut.OnClick(func(gxui.MouseEvent) { + wine = wineBut.IsChecked() + appListAdap.refresh() + if wineBut.IsChecked() { + catListAdap.SetStrings(cats) + wineBut.SetText("Hide Windows Apps") + } else { + catListAdap.SetStrings(lin) + wineBut.SetText("Show Windows Apps") + } + }) + _, err := os.Open("Start.exe") + if err == nil { + pa := th.CreateButton() + pa.SetText("Open PortableApps Launcher") + pa.OnClick(func(gxui.MouseEvent) { + cmd := exec.Command("wine", "Start.exe") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + }) + butBox.AddChild(pa) + } + butBox.AddChild(wineBut) + } + top.AddChild(butBox) + top.AddChild(splBox) + win.AddChild(top) + win.OnClose(dr.Terminate) +} diff --git a/main.go b/main.go index 14cdb34..68aed07 100644 --- a/main.go +++ b/main.go @@ -5,15 +5,12 @@ import ( "os" "os/exec" + "github.com/gotk3/gotk3/gtk" "github.com/nelsam/gxui" - "github.com/nelsam/gxui/drivers/gl" - "github.com/nelsam/gxui/themes/dark" - "github.com/nelsam/gxui/themes/light" ) const ( - version = "1.1.0.0" - defIni = "[basic]\ntheme=dk" + version = "2.0.0.0" ) var ( @@ -54,24 +51,39 @@ func main() { cmd.Stdout = os.Stdout cmd.Start() } else { - master = make(map[string][]app) - linmaster = make(map[string][]app) - gl.StartDriver(appMain) + // master = make(map[string][]app) + // linmaster = make(map[string][]app) + uiStart() } } -func appMain(dri gxui.Driver) { - dr = dri - setup() - if darkTheme { - th = dark.CreateTheme(dr) - } else { - th = light.CreateTheme(dr) +func uiStart() { + gtk.Init(nil) + win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) + if err != nil { + fmt.Println("Window not created", err) } - th = dark.CreateTheme(dr) - ui() + win.SetTitle("LinuxPA") + win.Connect("destroy", func() { + gtk.MainQuit() + }) + win.SetDefaultSize(500, 500) + ui(win) + gtk.Main() } +// func appMain(dri gxui.Driver) { +// dr = dri +// setup() +// if darkTheme { +// th = dark.CreateTheme(dr) +// } else { +// th = light.CreateTheme(dr) +// } +// th = dark.CreateTheme(dr) +// ui() +// } + func contains(arr []string, str string) bool { for _, v := range arr { if v == str { diff --git a/setup.go b/setup.go index 8290ad2..0874dd2 100644 --- a/setup.go +++ b/setup.go @@ -14,8 +14,6 @@ import ( "github.com/nelsam/gxui" ) -const () - func setup() { PortableAppsFold, err := os.Open("PortableApps") if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() { diff --git a/ui.go b/ui.go index 8c83a87..cfb33db 100644 --- a/ui.go +++ b/ui.go @@ -1,66 +1,7 @@ -package main +package ui -import ( - "os" - "os/exec" +import "github.com/gotk3/gotk3/gtk" - "github.com/nelsam/gxui" -) +func ui(win *gtk.Window) { -func ui() { - catListAdap := &StrList{} - appListAdap := &catAdap{} - catListAdap.SetStrings(lin) - win := th.CreateWindow(500, 500, "LinuxPA") - top := th.CreateLinearLayout() - top.SetDirection(gxui.BottomToTop) - splBox := th.CreateLinearLayout() - spl := th.CreateSplitterLayout() - spl.SetOrientation(gxui.Horizontal) - catList := th.CreateList() - catList.SetAdapter(catListAdap) - catList.OnSelectionChanged(func(it gxui.AdapterItem) { - appListAdap.setCat(it.(string)) - }) - appList := th.CreateTree() - appList.SetAdapter(appListAdap) - spl.AddChild(catList) - spl.AddChild(appList) - splBox.AddChild(spl) - butBox := th.CreateLinearLayout() - butBox.SetDirection(gxui.LeftToRight) - if _, err := exec.LookPath("wine"); err == nil { - wineBut := th.CreateButton() - wineBut.SetType(gxui.ToggleButton) - wineBut.SetChecked(wine) - wineBut.SetText("Show Windows Apps") - wineBut.OnClick(func(gxui.MouseEvent) { - wine = wineBut.IsChecked() - appListAdap.refresh() - if wineBut.IsChecked() { - catListAdap.SetStrings(cats) - wineBut.SetText("Hide Windows Apps") - } else { - catListAdap.SetStrings(lin) - wineBut.SetText("Show Windows Apps") - } - }) - _, err := os.Open("Start.exe") - if err == nil { - pa := th.CreateButton() - pa.SetText("Open PortableApps Launcher") - pa.OnClick(func(gxui.MouseEvent) { - cmd := exec.Command("wine", "Start.exe") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - }) - butBox.AddChild(pa) - } - butBox.AddChild(wineBut) - } - top.AddChild(butBox) - top.AddChild(splBox) - win.AddChild(top) - win.OnClose(dr.Terminate) } diff --git a/update.go b/update.go index ed57ce4..f1c5d60 100644 --- a/update.go +++ b/update.go @@ -69,6 +69,8 @@ func checkForUpdate(new string) (bool, error) { } if newNums[i] > curNums[i] { return true, nil + } else if curNums[i] > newNums[i] { + return false, nil } } return false, nil From 3199ad88fdc65ff2a4b0c5f1f2ebf08afa250c57 Mon Sep 17 00:00:00 2001 From: Belac Darkstorm Date: Tue, 4 Apr 2017 18:35:28 -0500 Subject: [PATCH 2/2] Finishing up gui --- app.go | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gxui/app.go | 272 ---------------------------------------------- main.go | 55 ++-------- setup.go | 30 +++-- ui.go | 126 ++++++++++++++++++++- update.go | 51 +++++++++ 6 files changed, 506 insertions(+), 336 deletions(-) create mode 100644 app.go delete mode 100644 gxui/app.go diff --git a/app.go b/app.go new file mode 100644 index 0000000..22bd5ee --- /dev/null +++ b/app.go @@ -0,0 +1,308 @@ +package main + +import ( + "os" + "os/exec" + "strings" + + "github.com/gotk3/gotk3/gdk" + "github.com/gotk3/gotk3/gtk" +) + +type app struct { + name string + cat string + appimg []string + lin []string + ex []string + icon *gdk.Pixbuf + dir string + ini *os.File +} + +func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter { + it := store.Append(nil) + store.SetValue(it, 0, a.icon) + store.SetValue(it, 1, a.name) + if len(a.ex) > 1 { + for _, v := range a.ex { + i := store.Append(it) + store.SetValue(i, 1, v) + } + } + return it +} + +func (a *app) launch() { + if len(a.ex) == 1 { + if wine { + var cmd *exec.Cmd + if !contains(a.lin, a.ex[0]) { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"") + } else { + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") + } + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + } else { + var cmd *exec.Cmd + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + } + } else { + if wine { + var cmd *exec.Cmd + if len(a.lin) == 0 { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"") + } else { + var ind int + for i, v := range a.lin { + if strings.HasSuffix(v, ".sh") { + ind = i + break + } + } + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") + } + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + } else { + if len(a.lin) != 0 { + var ind int + for i, v := range a.lin { + if strings.HasSuffix(v, ".sh") { + ind = i + break + } + } + var cmd *exec.Cmd + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + } + } + } +} + +func (a *app) launchSub(sub int) { + if wine { + var cmd *exec.Cmd + if !contains(a.lin, a.ex[sub]) { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"") + } else { + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") + } + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() + } + var cmd *exec.Cmd + if comEnbld { + cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") + } else { + cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Start() +} + +// type appExNode struct { +// ap app +// exInd int +// } +// +// func (a *appExNode) launch() { +// if wine { +// var cmd *exec.Cmd +// if !contains(a.ap.lin, a.ap.ex[a.exInd]) { +// cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[a.exInd]+"\"") +// } else { +// if comEnbld { +// cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") +// } else { +// cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") +// } +// } +// cmd.Stdout = os.Stdout +// cmd.Stderr = os.Stderr +// cmd.Start() +// } +// var cmd *exec.Cmd +// if comEnbld { +// cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") +// } else { +// cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") +// } +// cmd.Stdout = os.Stdout +// cmd.Stderr = os.Stderr +// cmd.Start() +// } + +// func (a *appExNode) Count() int { +// return 0 +// } +// +// func (a *appExNode) NodeAt(int) gxui.TreeNode { +// return nil +// } +// +// func (a *appExNode) ItemIndex(gxui.AdapterItem) int { +// return -1 +// } +// +// func (a *appExNode) Item() gxui.AdapterItem { +// if wine { +// return a.ap.ex[a.exInd] +// } +// return a.ap.lin[a.exInd] +// } +// +// func (a *appExNode) Create(the gxui.Theme) gxui.Control { +// box := the.CreateLinearLayout() +// box.SetDirection(gxui.LeftToRight) +// box.SetVerticalAlignment(gxui.AlignMiddle) +// img := the.CreateImage() +// img.SetTexture(a.ap.icon) +// img.SetExplicitSize(math.Size{H: 32, W: 32}) +// lbl := the.CreateLabel() +// lbl.SetText(a.ap.ex[a.exInd]) +// box.AddChild(img) +// box.AddChild(lbl) +// box.OnDoubleClick(func(gxui.MouseEvent) { +// a.launch() +// }) +// return box +// } + +// func (a *appNode) Count() int { +// if wine { +// if len(a.ex) > 1 { +// return len(a.ap.ex) +// } +// return 0 +// } +// if len(a.ap.lin) > 1 { +// return len(a.ap.lin) +// } +// return 0 +// } +// +// func (a *appNode) NodeAt(i int) gxui.TreeNode { +// return &appExNode{ap: a.ap, exInd: i} +// } +// +// func (a *appNode) ItemIndex(item gxui.AdapterItem) int { +// if wine { +// for i, v := range a.ap.ex { +// if v == item { +// return i +// } +// } +// } else { +// for i, v := range a.ap.lin { +// if v == item { +// return i +// } +// } +// } +// return -1 +// } +// +// func (a *appNode) Item() gxui.AdapterItem { +// return a.ap.name +// } +// +// func (a *appNode) Create(the gxui.Theme) gxui.Control { +// box := the.CreateLinearLayout() +// box.SetDirection(gxui.LeftToRight) +// box.SetPadding(math.CreateSpacing(2)) +// box.SetVerticalAlignment(gxui.AlignMiddle) +// img := the.CreateImage() +// if a.ap.icon != nil { +// img.SetTexture(a.ap.icon) +// } +// img.SetExplicitSize(math.Size{H: 32, W: 32}) +// lbl := the.CreateLabel() +// lbl.SetText(a.ap.name) +// box.AddChild(img) +// box.AddChild(lbl) +// box.OnDoubleClick(func(gxui.MouseEvent) { +// a.launch() +// }) +// return box +// } + +// type catAdap struct { +// gxui.AdapterBase +// cat string +// } +// +// func (a *catAdap) setCat(cat string) { +// a.cat = cat +// a.DataChanged(false) +// } +// +// func (a *catAdap) refresh() { +// a.DataChanged(false) +// } +// +// func (a *catAdap) Count() int { +// if wine { +// return len(master[a.cat]) +// } +// return len(linmaster[a.cat]) +// } +// +// func (a *catAdap) NodeAt(i int) gxui.TreeNode { +// if wine { +// return &appNode{ap: master[a.cat][i]} +// } +// return &appNode{ap: linmaster[a.cat][i]} +// } +// +// func (a *catAdap) Size(gxui.Theme) math.Size { +// return math.Size{H: 34, W: math.MaxSize.W} +// } +// +// func (a *catAdap) ItemIndex(item gxui.AdapterItem) int { +// if wine { +// for i, v := range master[a.cat] { +// if v.name == item { +// return i +// } +// } +// } else { +// for i, v := range linmaster[a.cat] { +// if v.name == item { +// return i +// } +// } +// } +// return -1 +// } diff --git a/gxui/app.go b/gxui/app.go deleted file mode 100644 index 5d84e64..0000000 --- a/gxui/app.go +++ /dev/null @@ -1,272 +0,0 @@ -package main - -import ( - "os" - "os/exec" - "strings" - - "github.com/nelsam/gxui" - "github.com/nelsam/gxui/math" -) - -type app struct { - name string - cat string - appimg []string - lin []string - ex []string - icon gxui.Texture - dir string - ini *os.File -} - -type appExNode struct { - ap app - exInd int -} - -func (a *appExNode) launch() { - if wine { - var cmd *exec.Cmd - if !contains(a.ap.lin, a.ap.ex[a.exInd]) { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[a.exInd]+"\"") - } else { - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") - } - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - } - var cmd *exec.Cmd - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"") - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() -} - -func (a *appExNode) Count() int { - return 0 -} - -func (a *appExNode) NodeAt(int) gxui.TreeNode { - return nil -} - -func (a *appExNode) ItemIndex(gxui.AdapterItem) int { - return -1 -} - -func (a *appExNode) Item() gxui.AdapterItem { - if wine { - return a.ap.ex[a.exInd] - } - return a.ap.lin[a.exInd] -} - -func (a *appExNode) Create(the gxui.Theme) gxui.Control { - box := the.CreateLinearLayout() - box.SetDirection(gxui.LeftToRight) - box.SetVerticalAlignment(gxui.AlignMiddle) - img := the.CreateImage() - img.SetTexture(a.ap.icon) - img.SetExplicitSize(math.Size{H: 32, W: 32}) - lbl := the.CreateLabel() - lbl.SetText(a.ap.ex[a.exInd]) - box.AddChild(img) - box.AddChild(lbl) - box.OnDoubleClick(func(gxui.MouseEvent) { - a.launch() - }) - return box -} - -type appNode struct { - ap app -} - -func (a *appNode) launch() { - if len(a.ap.ex) == 1 { - if wine { - var cmd *exec.Cmd - if !contains(a.ap.lin, a.ap.ex[0]) { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"") - } else { - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"") - } - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - } else { - var cmd *exec.Cmd - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"") - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - } - } else { - if wine { - var cmd *exec.Cmd - if len(a.ap.lin) == 0 { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"") - } else { - var ind int - for i, v := range a.ap.lin { - if strings.HasSuffix(v, ".sh") { - ind = i - break - } - } - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"") - } - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - } else { - if len(a.ap.lin) != 0 { - var ind int - for i, v := range a.ap.lin { - if strings.HasSuffix(v, ".sh") { - ind = i - break - } - } - var cmd *exec.Cmd - if comEnbld { - cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"") - } else { - cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"") - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Start() - } - } - } -} - -func (a *appNode) Count() int { - if wine { - if len(a.ap.ex) > 1 { - return len(a.ap.ex) - } - return 0 - } - if len(a.ap.lin) > 1 { - return len(a.ap.lin) - } - return 0 -} - -func (a *appNode) NodeAt(i int) gxui.TreeNode { - return &appExNode{ap: a.ap, exInd: i} -} - -func (a *appNode) ItemIndex(item gxui.AdapterItem) int { - if wine { - for i, v := range a.ap.ex { - if v == item { - return i - } - } - } else { - for i, v := range a.ap.lin { - if v == item { - return i - } - } - } - return -1 -} - -func (a *appNode) Item() gxui.AdapterItem { - return a.ap.name -} - -func (a *appNode) Create(the gxui.Theme) gxui.Control { - box := the.CreateLinearLayout() - box.SetDirection(gxui.LeftToRight) - box.SetPadding(math.CreateSpacing(2)) - box.SetVerticalAlignment(gxui.AlignMiddle) - img := the.CreateImage() - if a.ap.icon != nil { - img.SetTexture(a.ap.icon) - } - img.SetExplicitSize(math.Size{H: 32, W: 32}) - lbl := the.CreateLabel() - lbl.SetText(a.ap.name) - box.AddChild(img) - box.AddChild(lbl) - box.OnDoubleClick(func(gxui.MouseEvent) { - a.launch() - }) - return box -} - -type catAdap struct { - gxui.AdapterBase - cat string -} - -func (a *catAdap) setCat(cat string) { - a.cat = cat - a.DataChanged(false) -} - -func (a *catAdap) refresh() { - a.DataChanged(false) -} - -func (a *catAdap) Count() int { - if wine { - return len(master[a.cat]) - } - return len(linmaster[a.cat]) -} - -func (a *catAdap) NodeAt(i int) gxui.TreeNode { - if wine { - return &appNode{ap: master[a.cat][i]} - } - return &appNode{ap: linmaster[a.cat][i]} -} - -func (a *catAdap) Size(gxui.Theme) math.Size { - return math.Size{H: 34, W: math.MaxSize.W} -} - -func (a *catAdap) ItemIndex(item gxui.AdapterItem) int { - if wine { - for i, v := range master[a.cat] { - if v.name == item { - return i - } - } - } else { - for i, v := range linmaster[a.cat] { - if v.name == item { - return i - } - } - } - return -1 -} diff --git a/main.go b/main.go index 68aed07..ff3fb7f 100644 --- a/main.go +++ b/main.go @@ -3,19 +3,16 @@ package main import ( "fmt" "os" - "os/exec" "github.com/gotk3/gotk3/gtk" - "github.com/nelsam/gxui" ) const ( - version = "2.0.0.0" + version = "2.0.0.1" + defIni = "" ) var ( - dr gxui.Driver - th gxui.Theme master map[string][]app linmaster map[string][]app cats []string @@ -26,39 +23,15 @@ var ( ) func main() { - updated := false os.MkdirAll("PortableApps/LinuxPACom", 0777) - stat, err := versionDL() - if stat { - res := getVersionFileInfo() - if res != "Error!" { - stat, err = checkForUpdate(res) - if stat { - downloadUpdate(res) - updated = true - } else { - fmt.Println(err) - } - } else { - fmt.Println("Failed Version File Info") - } - } else { - fmt.Println(err) - } - if updated { - cmd := exec.Command("./LinuxPA") - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Start() - } else { - // master = make(map[string][]app) - // linmaster = make(map[string][]app) - uiStart() - } + master = make(map[string][]app) + linmaster = make(map[string][]app) + uiStart() } func uiStart() { gtk.Init(nil) + setup() win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) if err != nil { fmt.Println("Window not created", err) @@ -68,22 +41,14 @@ func uiStart() { gtk.MainQuit() }) win.SetDefaultSize(500, 500) + win.SetPosition(gtk.WIN_POS_CENTER) ui(win) + win.ShowAll() + win.Show() + update(win) gtk.Main() } -// func appMain(dri gxui.Driver) { -// dr = dri -// setup() -// if darkTheme { -// th = dark.CreateTheme(dr) -// } else { -// th = light.CreateTheme(dr) -// } -// th = dark.CreateTheme(dr) -// ui() -// } - func contains(arr []string, str string) bool { for _, v := range arr { if v == str { diff --git a/setup.go b/setup.go index 0874dd2..6428162 100644 --- a/setup.go +++ b/setup.go @@ -3,15 +3,14 @@ package main import ( "bufio" "fmt" - "image" - "image/draw" _ "image/png" "os" "reflect" "sort" "strings" - "github.com/nelsam/gxui" + "github.com/gotk3/gotk3/gdk" + "github.com/gotk3/gotk3/gtk" ) func setup() { @@ -155,8 +154,8 @@ func getName(ini *os.File) string { return ret } -func getIcon(fold string) gxui.Texture { - var pic *os.File +func getIcon(fold string) *gdk.Pixbuf { + var pic string if folder, err := os.Open(fold + "/App/AppInfo"); err == nil { fis, _ := folder.Readdir(-1) var pics []string @@ -173,21 +172,18 @@ func getIcon(fold string) gxui.Texture { } else { ind = sort.SearchStrings(pics, "appicon_32.png") } - pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind]) + pic = fold + "/App/AppInfo/" + pics[ind] } - } else if fi, err := os.Open(fold + "/appicon.png"); err == nil { - pic = fi + } else if _, err := os.Open(fold + "/appicon.png"); err == nil { + pic = fold + "/appicon.png" } else { - return nil + img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON) + buf, _ := img.GetPixbuf().ScaleSimple(32, 32, gdk.INTERP_BILINEAR) + return buf } - img, _, err := image.Decode(pic) - if err != nil { - return nil - } - rgba := image.NewRGBA(img.Bounds()) - draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src) - ret := dr.CreateTexture(rgba, 1) - return ret + img, _ := gtk.ImageNewFromFile(pic) + buf, _ := img.GetPixbuf().ScaleSimple(32, 32, gdk.INTERP_BILINEAR) + return buf } func findInfo(fold string) *os.File { diff --git a/ui.go b/ui.go index cfb33db..22fc40c 100644 --- a/ui.go +++ b/ui.go @@ -1,7 +1,129 @@ -package ui +package main -import "github.com/gotk3/gotk3/gtk" +import ( + "fmt" + + "github.com/gotk3/gotk3/glib" + "github.com/gotk3/gotk3/gtk" +) func ui(win *gtk.Window) { + ls := getCatRows() + var treeApps []*gtk.TreeIter + header, _ := gtk.HeaderBarNew() + header.SetShowCloseButton(true) + header.SetTitle("LinuxPA") + header.SetSubtitle("PortableApps.com type launcher") + settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR) + settings.Connect("clicked", func() { + //Open Settings window! + }) + settings.SetTooltipText("Settings (Coming Soon!)") + header.PackStart(settings) + win.SetTitlebar(header) + topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) + lrBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5) + catList, _ := gtk.ListBoxNew() + catList.SetActivateOnSingleClick(true) + store, _ := gtk.TreeStoreNew(glib.TYPE_OBJECT, glib.TYPE_STRING) + appsList, _ := gtk.TreeViewNewWithModel(store) + render, _ := gtk.CellRendererPixbufNew() + pixColumn, _ := gtk.TreeViewColumnNewWithAttribute("", render, "pixbuf", 0) + txtRender, _ := gtk.CellRendererTextNew() + txtColumn, _ := gtk.TreeViewColumnNewWithAttribute("", txtRender, "text", 1) + appsList.AppendColumn(pixColumn) + appsList.AppendColumn(txtColumn) + catList.SetHExpand(true) + catList.SetVExpand(true) + appsList.SetHExpand(true) + appsList.SetVExpand(true) + vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0) + hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0) + vScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0) + hScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0) + catScrl, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat) + catScrl.Add(catList) + appScrl, _ := gtk.ScrolledWindowNew(hScrollApp, vScrollApp) + appScrl.Add(appsList) + lrBox.Add(catScrl) + lrBox.Add(appScrl) + botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2) + wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)") + wineCheck.Connect("toggled", func() { + wine = wineCheck.GetActive() + for i := range ls { + catList.Remove(catList.GetRowAtIndex(i)) + } + ls = getCatRows() + for _, v := range ls { + catList.Add(v) + } + catList.ShowAll() + }) + botBox.Add(wineCheck) + topLvl.Add(lrBox) + topLvl.PackEnd(botBox, false, true, 0) + win.Add(topLvl) + for _, v := range ls { + catList.Prepend(v) + } + catList.Connect("row-selected", func() { + store.Clear() + if catList.GetSelectedRow().GetIndex() >= 0 { + treeApps = make([]*gtk.TreeIter, 0) + if wine { + apps := master[cats[catList.GetSelectedRow().GetIndex()]] + for _, v := range apps { + treeApps = append(treeApps, v.getTreeIter(store)) + } + } else { + apps := linmaster[lin[catList.GetSelectedRow().GetIndex()]] + for _, v := range apps { + treeApps = append(treeApps, v.getTreeIter(store)) + } + } + } + }) + appsList.Connect("row-activated", func() { + selec, _ := appsList.GetSelection() + _, it, ok := selec.GetSelected() + if ok { + pth, _ := store.GetPath(it) + ind := pth.GetIndices() + if len(ind) == 1 { + if wine { + app := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]] + app.launch() + } else { + app := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]] + app.launch() + } + } else if len(ind) == 2 { + if wine { + app := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]] + app.launchSub(ind[1]) + } else { + app := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]] + app.launchSub(ind[1]) + } + } + } + }) +} +func getCatRows() (out []*gtk.Label) { + if wine { + for _, v := range cats { + txt, _ := gtk.LabelNew(v) + out = append(out, txt) + fmt.Println(v) + } + } else { + for _, v := range lin { + txt, _ := gtk.LabelNew(v) + out = append(out, txt) + fmt.Println(v) + } + } + return } diff --git a/update.go b/update.go index f1c5d60..35a46ea 100644 --- a/update.go +++ b/update.go @@ -2,11 +2,15 @@ package main import ( "bufio" + "fmt" "io" "net/http" "os" + "os/exec" "strconv" "strings" + + "github.com/gotk3/gotk3/gtk" ) const ( @@ -106,3 +110,50 @@ func downloadUpdate(newVersion string) (bool, error) { } return true, nil } + +func update(win *gtk.Window) { + updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) + updateWin.SetTransientFor(win) + topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) + spin, _ := gtk.SpinnerNew() + spin.Start() + lbl, _ := gtk.LabelNew("Checking for updates") + topLvl.Add(spin) + topLvl.Add(lbl) + topLvl.SetMarginBottom(10) + topLvl.SetMarginEnd(10) + topLvl.SetMarginStart(10) + topLvl.SetMarginTop(10) + updateWin.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT) + updateWin.Add(topLvl) + updateWin.ShowAll() + updateWin.Show() + go func(win, updateWin *gtk.Window) { + stat, err := versionDL() + if stat { + res := getVersionFileInfo() + if res != "Error!" { + stat, err = checkForUpdate(res) + if stat { + lbl.SetText("Updating!") + downloadUpdate(res) + updateWin.Close() + win.Close() + cmd := exec.Command("./LinuxPA") + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Start() + } else { + fmt.Println(err) + updateWin.Close() + } + } else { + fmt.Println("Failed Version File Info") + updateWin.Close() + } + } else { + fmt.Println(err) + updateWin.Close() + } + }(win, updateWin) +}