Allow for multiple executables. Double click to launch instead of the launch button

This commit is contained in:
Belac Darkstorm
2016-09-22 00:11:32 -05:00
parent 2f8de0bed2
commit 7cf45c9ac8
7 changed files with 480 additions and 373 deletions
+3 -3
View File
@@ -1,8 +1,8 @@
# LinuxPA # LinuxPA
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux. LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
# App Detection # How to use
LinuxPA looks in all folders in the PortableApps folder for, first, a script file (starts with the shebang (`#!`)) and, secondly, a native linux executable (starts with ELF). It will only add the first one it finds. Just double click on an app to launch it! If there are multiple executables, you can either select the specific executable, or if you just double click the app it'll launch the first linux executable, but if one isn't found it launches the first executable in general.
# PortableApps.com Compatibility # PortableApps.com Compatibility
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format. LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
@@ -15,7 +15,7 @@ Because apps aren't natively formated in the PortableApps.com format, if LinuxPA
# AppImage Support # AppImage Support
[AppImage Website](http://appimage.org) [AppImage Website](http://appimage.org)
Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic updating support. Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic updating support later on.
# USB mount # USB mount
Unfortunately Linux, by default, doesn't support running executables off of flash drives, requiring you to mount your drive with special mount arguments, I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000` Unfortunately Linux, by default, doesn't support running executables off of flash drives, requiring you to mount your drive with special mount arguments, I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
+259
View File
@@ -0,0 +1,259 @@
package main
import (
"os"
"os/exec"
"sort"
"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 ind := sort.SearchStrings(a.ap.lin, a.ap.ex[a.exInd]); ind == len(a.ap.lin) {
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 ind := sort.SearchStrings(a.ap.lin, a.ap.ex[0]); ind == len(a.ap.lin) {
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 {
if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
} else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
}
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
} else {
if len(a.ap.lin) != 0 {
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[0]+"\"")
} else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
}
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
}
+17 -170
View File
@@ -1,184 +1,31 @@
package main package main
import ( import (
"bufio" "github.com/nelsam/gxui"
"os"
"path"
"reflect"
"sort"
"strings"
"github.com/nelsam/gxui/drivers/gl" "github.com/nelsam/gxui/drivers/gl"
"github.com/nelsam/gxui/themes/dark"
) )
var ( var (
appMaster map[string][]prtap dr gxui.Driver
th gxui.Theme
master map[string][]app
linmaster map[string][]app
cats []string cats []string
wineOnly []string lin []string
linOnly []string wine bool
conf *os.File comEnbld bool
common string
commEnbl bool
) )
type prtap struct {
name string
cat string
ex string
desc string
wine bool
}
func main() { func main() {
commEnbl = true master = make(map[string][]app)
appMaster = make(map[string][]prtap) linmaster = make(map[string][]app)
os.Mkdir("PortableApps", 0777) gl.StartDriver(appMain)
os.Mkdir("PortableApps/LinuxPACom", 0777)
common = "PortableApps/LinuxPACom/common.sh"
_, err := os.Open(common)
if os.IsNotExist(err) {
commEnbl = false
}
pa, err := os.Open("PortableApps")
if err != nil {
panic(err)
}
appstmp, _ := pa.Readdir(-1)
var folds []string
for _, v := range appstmp {
if v.IsDir() && v.Name() != "LinuxPACom" && v.Name() != "PortableApps.com" {
folds = append(folds, v.Name())
}
}
sort.Strings(folds)
for _, v := range folds {
fi, _ := os.Open("PortableApps/" + v)
pat := processApp(fi)
if (pat != prtap{}) {
if _, ok := appMaster[pat.cat]; !ok {
if pat.wine {
wineOnly = append(wineOnly, pat.cat)
cats = append(cats, pat.cat)
} else {
linOnly = append(linOnly, pat.cat)
cats = append(cats, pat.cat)
}
} else {
if !pat.wine {
for i, v := range wineOnly {
if pat.cat == v {
wineOnly = append(wineOnly[:i], wineOnly[i+1:]...)
linOnly = append(linOnly, pat.cat)
break
}
}
}
}
appMaster[pat.cat] = append(appMaster[pat.cat], pat)
}
}
sort.Strings(linOnly)
sort.Strings(wineOnly)
sort.Strings(cats)
gl.StartDriver(uiMain)
} }
func processApp(fi *os.File) (out prtap) { func appMain(dri gxui.Driver) {
fis, _ := fi.Readdir(-1) dr = dri
if fil, err := os.Open(fi.Name() + "/App/AppInfo/appinfo.ini"); err == nil { th = dark.CreateTheme(dr)
out.name = getName(fil) setup()
fil, _ = os.Open(fi.Name() + "/App/AppInfo/appinfo.ini") ui()
out.cat = getCat(fil)
} else if fil, err := os.Open(fi.Name() + "/appinfo.ini"); err == nil {
out.name = getName(fil)
fil, _ = os.Open(fi.Name() + "/appinfo.ini")
out.cat = getCat(fil)
} else {
out.cat = "Other"
}
if out.name == "" {
out.name = path.Base(fi.Name())
}
if out.cat == "" {
out.cat = "Other"
}
//executable detection
wd, _ := os.Getwd()
var rdr *bufio.Reader
for _, v := range fis {
fil, err := os.Open(wd + "/" + fi.Name() + "/" + v.Name())
if err == nil {
stat, _ := fil.Stat()
if !stat.IsDir() {
rdr = bufio.NewReader(fil)
shebang := []byte{'#', '!'}
two := make([]byte, 2)
rdr.Read(two)
if reflect.DeepEqual(shebang, two) {
out.ex = wd + "/" + fi.Name() + "/" + v.Name()
rdr.Reset(fil)
return
}
}
}
}
for _, v := range fis {
fil, err := os.Open(wd + "/" + fi.Name() + "/" + v.Name())
if err == nil {
stat, _ := fil.Stat()
if !stat.IsDir() {
rdr = bufio.NewReader(fil)
thr := make([]byte, 4)
rdr.Read(thr)
if strings.Contains(string(thr), "ELF") {
out.ex = wd + "/" + fi.Name() + "/" + v.Name()
rdr.Reset(fil)
return
}
}
}
}
for _, v := range fis {
fil, err := os.Open(wd + "/" + fi.Name() + "/" + v.Name())
if err == nil {
stat, _ := fil.Stat()
if !stat.IsDir() && strings.HasSuffix(stat.Name(), "exe") {
out.wine = true
out.ex = wd + "/" + fi.Name() + "/" + v.Name()
out.name += " (Wine)"
return
}
}
}
return prtap{}
}
func getCat(fi *os.File) (out string) {
rdr := bufio.NewReader(fi)
var err error
var ln []byte
for err == nil {
ln, _, err = rdr.ReadLine()
str := string(ln)
if strings.HasPrefix(str, "Category=") {
out = strings.TrimPrefix(str, "Category=")
return
}
}
return
}
func getName(fi *os.File) (out string) {
rdr := bufio.NewReader(fi)
var err error
var ln []byte
for err == nil {
ln, _, err = rdr.ReadLine()
str := string(ln)
if strings.HasPrefix(str, "Name=") {
out = strings.TrimPrefix(str, "Name=")
return
}
}
return
} }
-130
View File
@@ -1,130 +0,0 @@
package main
import (
"image"
"image/draw"
_ "image/png"
"os"
"path"
"sort"
"strings"
"github.com/nelsam/gxui"
"github.com/nelsam/gxui/math"
)
type prtapAdap struct {
gxui.AdapterBase
wine bool
master []prtap
cur []prtap
}
func (p *prtapAdap) SetApps(apps []prtap) {
p.master = apps
if p.wine {
p.cur = p.master
} else {
p.cur = make([]prtap, 0)
for _, v := range p.master {
if !v.wine {
p.cur = append(p.cur, v)
}
}
}
p.DataChanged(false)
}
func (p *prtapAdap) Count() int {
return len(p.cur)
}
func (p *prtapAdap) Wine(show bool) {
p.wine = show
if show {
p.cur = p.master
} else {
p.cur = make([]prtap, 0)
for _, v := range p.master {
if !v.wine {
p.cur = append(p.cur, v)
}
}
}
p.DataChanged(false)
}
func (p *prtapAdap) Create(th gxui.Theme, index int) gxui.Control {
box := th.CreateLinearLayout()
box.SetPadding(math.CreateSpacing(2))
box.SetDirection(gxui.LeftToRight)
box.SetVerticalAlignment(gxui.AlignMiddle)
dir := path.Dir(p.cur[index].ex)
if fold, err := os.Open(dir + "/App/AppInfo"); err == nil {
var pics []string
fi, _ := fold.Readdirnames(-1)
for _, v := range fi {
if strings.HasPrefix(v, "appicon_") && strings.HasSuffix(v, ".png") {
pics = append(pics, v)
}
}
if len(pics) > 0 {
ind := sort.SearchStrings(pics, "appicon_128.png")
if ind == len(pics) {
ind = len(pics) - 1
}
imgfi, _ := os.Open(dir + "/App/AppInfo/" + pics[ind])
img, _, err := image.Decode(imgfi)
if err == nil {
rgba := image.NewRGBA(img.Bounds())
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
tex := dr.CreateTexture(rgba, 1)
icon := th.CreateImage()
icon.SetExplicitSize(math.Size{H: 32, W: 32})
icon.SetTexture(tex)
box.AddChild(icon)
}
}
} else if fi, err := os.Open(dir + "/appicon.png"); err == nil {
img, _, err := image.Decode(fi)
if err == nil {
rgba := image.NewRGBA(img.Bounds())
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
tex := dr.CreateTexture(rgba, 1)
icon := th.CreateImage()
icon.SetExplicitSize(math.Size{H: 32, W: 32})
icon.SetTexture(tex)
box.AddChild(icon)
}
} else {
//Creating empty Image so that names line up
icon := th.CreateImage()
icon.SetExplicitSize(math.Size{H: 32, W: 32})
box.AddChild(icon)
}
lbl := th.CreateLabel()
lbl.SetText(p.cur[index].name)
box.AddChild(lbl)
return box
}
func (p *prtapAdap) ItemAt(index int) gxui.AdapterItem {
return p.cur[index]
}
func (p *prtapAdap) ItemIndex(item gxui.AdapterItem) int {
it, ok := item.(prtap)
if !ok {
return -1
}
for i, v := range p.cur {
if v == it {
return i
}
}
return -1
}
func (p *prtapAdap) Size(gxui.Theme) math.Size {
return math.Size{W: math.MaxSize.W, H: 36}
}
+168
View File
@@ -0,0 +1,168 @@
package main
import (
"bufio"
"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() {
panic("PortableApps folder not found!!")
}
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
sort.Strings(PAFolds)
for _, v := range PAFolds {
fold, _ := os.Open("PortableApps/" + v)
if stat, _ := fold.Stat(); stat.IsDir() {
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 {
lin = append(lin, ap.cat)
sort.Strings(lin)
}
} else {
if len(ap.lin) != 0 {
ind := sort.SearchStrings(lin, ap.cat)
if ind == len(lin) {
lin = append(lin, ap.cat)
sort.Strings(lin)
}
}
}
if len(ap.lin) != 0 {
linmaster[ap.cat] = append(linmaster[ap.cat], ap)
}
master[ap.cat] = append(master[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.HasPrefix(strings.ToLower(string(btys)), "ELF") || 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 {
ind := sort.SearchStrings(pics, "appicon_32.png")
if ind == len(pics) {
ind--
}
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 {
if fi, err := os.Open(fold + "/App/AppInfo/appinfo.ini"); err == nil {
return fi
} else if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
return fi
}
return nil
}
Executable → Regular
View File
+33 -70
View File
@@ -1,90 +1,53 @@
package main package main
import ( import (
"fmt"
"os"
"os/exec" "os/exec"
"path"
"github.com/nelsam/gxui" "github.com/nelsam/gxui"
"github.com/nelsam/gxui/themes/dark"
) )
var ( func ui() {
dr gxui.Driver catListAdap := &StrList{}
) appListAdap := &catAdap{}
catListAdap.SetStrings(lin)
func uiMain(dri gxui.Driver) { win := th.CreateWindow(600, 500, "LinuxPA")
dr = dri
catAdap := &StrList{}
catAdap.SetStrings(linOnly)
appAdap := &prtapAdap{}
appAdap.Wine(false)
th := dark.CreateTheme(dr)
win := th.CreateWindow(500, 500, "LinuxPA")
top := th.CreateLinearLayout() top := th.CreateLinearLayout()
top.SetDirection(gxui.BottomToTop) top.SetDirection(gxui.BottomToTop)
top.SetHorizontalAlignment(gxui.AlignRight) splBox := th.CreateLinearLayout()
spl := th.CreateSplitterLayout() spl := th.CreateSplitterLayout()
spl.SetOrientation(gxui.Horizontal) spl.SetOrientation(gxui.Horizontal)
catlist := th.CreateList() catList := th.CreateList()
catlist.SetAdapter(catAdap) catList.SetAdapter(catListAdap)
catlist.OnItemClicked(func(_ gxui.MouseEvent, it gxui.AdapterItem) { catList.OnSelectionChanged(func(it gxui.AdapterItem) {
str := it.(string) appListAdap.setCat(it.(string))
appAdap.SetApps(appMaster[str])
})
applist := th.CreateList()
applist.SetAdapter(appAdap)
spl.AddChild(catlist)
spl.AddChild(applist)
but := th.CreateLinearLayout()
but.SetDirection(gxui.RightToLeft)
launch := th.CreateButton()
launch.SetText("Launch!")
launch.OnClick(func(gxui.MouseEvent) {
if appAdap.ItemIndex(applist.Selected()) != -1 {
app := applist.Selected().(prtap)
dir, fi := path.Split(app.ex)
var cmd *exec.Cmd
if app.wine {
cmd = exec.Command("/bin/sh", "-c", "cd \""+dir+"\"; wine \""+fi+"\"")
} else {
if commEnbl {
cmd = exec.Command("/bin/sh", "-c", ". "+common+" || exit 1;cd \""+dir+"\"; \"./"+fi+"\"")
} else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+dir+"\"; \"./"+fi+"\"")
}
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
}
}) })
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 { if _, err := exec.LookPath("wine"); err == nil {
fmt.Println("Wine found!") wineBut := th.CreateButton()
wine := th.CreateButton() wineBut.SetType(gxui.ToggleButton)
wine.SetType(gxui.ToggleButton) wineBut.SetChecked(wine)
wine.OnClick(func(gxui.MouseEvent) { wineBut.SetText("Show Windows Apps")
if wine.IsChecked() { wineBut.OnClick(func(gxui.MouseEvent) {
catAdap.SetStrings(cats) wine = wineBut.IsChecked()
appAdap.Wine(true) appListAdap.refresh()
if wineBut.IsChecked() {
catListAdap.SetStrings(cats)
wineBut.SetText("Hide Windows Apps")
} else { } else {
catAdap.SetStrings(linOnly) catListAdap.SetStrings(lin)
appAdap.Wine(false) wineBut.SetText("Show Windows Apps")
} }
}) })
wine.SetText("Show Windows Apps") butBox.AddChild(wineBut)
wine.SetChecked(appAdap.wine)
but.AddChild(wine)
} else {
fmt.Println("Wine not found!")
} }
but.AddChild(launch) top.AddChild(butBox)
top.AddChild(but) top.AddChild(splBox)
top.AddChild(spl)
win.AddChild(top) win.AddChild(top)
win.OnClose(func() { win.OnClose(dr.Terminate)
dr.Terminate()
})
} }