Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f8de0bed2 | |||
| 67ca030bb2 | |||
| da46399ded | |||
| e5d0b6a9a2 | |||
| f4ca2115d4 | |||
| 0cc7f8f445 | |||
| 767e894acd | |||
| 06e2afef1d |
@@ -1,21 +1,21 @@
|
|||||||
# LinuxPA
|
# LinuxPA
|
||||||
LinuxPA is a try to bring a PortableApps.com type launcher to Linux.
|
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
||||||
|
|
||||||
# App Detection
|
# App Detection
|
||||||
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.
|
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.
|
||||||
|
|
||||||
# PortableApps.com Compatability
|
# 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.
|
||||||
|
|
||||||
# common.sh
|
# common.sh
|
||||||
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
||||||
|
|
||||||
# Simple App Setup
|
# Simple App Setup
|
||||||
Because apps aren't natively formated in the PortableApps.com format, if LinuxPA doesn't find the AppInfo.ini or appicon_\*.png in the App/AppInfo folder of the app it looks for them in the root direcory of the app (except it looks, nor for appicon_\*.png, but appicon.png)
|
Because apps aren't natively formated in the PortableApps.com format, if LinuxPA doesn't find the AppInfo.ini or appicon_\*.png in the App/AppInfo folder of the app it looks for them in the root directory of the app (except it looks, nor for appicon_\*.png, but appicon.png). If an AppInfo.ini file isn't found then the name of the app is grabbed from the folder name and it's category is set to other. It specifically looks for the lines starting with `Name=` and `Category=`
|
||||||
|
|
||||||
# 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 downloading 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.
|
||||||
|
|
||||||
# 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`
|
||||||
@@ -25,8 +25,8 @@ Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
|||||||
|
|
||||||
# TODO (Might be in order)
|
# TODO (Might be in order)
|
||||||
1. MAKE IT BETTER
|
1. MAKE IT BETTER
|
||||||
1. Launching of .exe files via wine (wine will have to be installed on the host system, unless there is some portable wine (I may have found one))
|
|
||||||
1. Add settings menu
|
1. Add settings menu
|
||||||
1. Add updater for .AppImage files
|
1. Add updater for .AppImage files
|
||||||
1. Download .AppImage files (maybe)
|
1. Download .AppImage files (maybe)
|
||||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
||||||
|
1. Portable wine???
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
appMaster map[string][]prtap
|
appMaster map[string][]prtap
|
||||||
cats []string
|
cats []string
|
||||||
|
wineOnly []string
|
||||||
|
linOnly []string
|
||||||
conf *os.File
|
conf *os.File
|
||||||
common string
|
common string
|
||||||
commEnbl bool
|
commEnbl bool
|
||||||
@@ -24,6 +26,7 @@ type prtap struct {
|
|||||||
cat string
|
cat string
|
||||||
ex string
|
ex string
|
||||||
desc string
|
desc string
|
||||||
|
wine bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -43,7 +46,7 @@ func main() {
|
|||||||
appstmp, _ := pa.Readdir(-1)
|
appstmp, _ := pa.Readdir(-1)
|
||||||
var folds []string
|
var folds []string
|
||||||
for _, v := range appstmp {
|
for _, v := range appstmp {
|
||||||
if v.IsDir() && v.Name() != "LinuxPACom" {
|
if v.IsDir() && v.Name() != "LinuxPACom" && v.Name() != "PortableApps.com" {
|
||||||
folds = append(folds, v.Name())
|
folds = append(folds, v.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,11 +56,30 @@ func main() {
|
|||||||
pat := processApp(fi)
|
pat := processApp(fi)
|
||||||
if (pat != prtap{}) {
|
if (pat != prtap{}) {
|
||||||
if _, ok := appMaster[pat.cat]; !ok {
|
if _, ok := appMaster[pat.cat]; !ok {
|
||||||
cats = append(cats, pat.cat)
|
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)
|
appMaster[pat.cat] = append(appMaster[pat.cat], pat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sort.Strings(linOnly)
|
||||||
|
sort.Strings(wineOnly)
|
||||||
|
sort.Strings(cats)
|
||||||
gl.StartDriver(uiMain)
|
gl.StartDriver(uiMain)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,13 +94,13 @@ func processApp(fi *os.File) (out prtap) {
|
|||||||
fil, _ = os.Open(fi.Name() + "/appinfo.ini")
|
fil, _ = os.Open(fi.Name() + "/appinfo.ini")
|
||||||
out.cat = getCat(fil)
|
out.cat = getCat(fil)
|
||||||
} else {
|
} else {
|
||||||
out.cat = "other"
|
out.cat = "Other"
|
||||||
}
|
}
|
||||||
if out.name == "" {
|
if out.name == "" {
|
||||||
out.name = path.Base(fi.Name())
|
out.name = path.Base(fi.Name())
|
||||||
}
|
}
|
||||||
if out.cat == "" {
|
if out.cat == "" {
|
||||||
out.cat = "other"
|
out.cat = "Other"
|
||||||
}
|
}
|
||||||
//executable detection
|
//executable detection
|
||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
@@ -116,6 +138,18 @@ func processApp(fi *os.File) (out prtap) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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{}
|
return prtap{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-7
@@ -15,16 +15,43 @@ import (
|
|||||||
|
|
||||||
type prtapAdap struct {
|
type prtapAdap struct {
|
||||||
gxui.AdapterBase
|
gxui.AdapterBase
|
||||||
apps []prtap
|
wine bool
|
||||||
|
master []prtap
|
||||||
|
cur []prtap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prtapAdap) SetApps(apps []prtap) {
|
func (p *prtapAdap) SetApps(apps []prtap) {
|
||||||
p.apps = apps
|
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)
|
p.DataChanged(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prtapAdap) Count() int {
|
func (p *prtapAdap) Count() int {
|
||||||
return len(p.apps)
|
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 {
|
func (p *prtapAdap) Create(th gxui.Theme, index int) gxui.Control {
|
||||||
@@ -32,7 +59,7 @@ func (p *prtapAdap) Create(th gxui.Theme, index int) gxui.Control {
|
|||||||
box.SetPadding(math.CreateSpacing(2))
|
box.SetPadding(math.CreateSpacing(2))
|
||||||
box.SetDirection(gxui.LeftToRight)
|
box.SetDirection(gxui.LeftToRight)
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
box.SetVerticalAlignment(gxui.AlignMiddle)
|
||||||
dir := path.Dir(p.apps[index].ex)
|
dir := path.Dir(p.cur[index].ex)
|
||||||
if fold, err := os.Open(dir + "/App/AppInfo"); err == nil {
|
if fold, err := os.Open(dir + "/App/AppInfo"); err == nil {
|
||||||
var pics []string
|
var pics []string
|
||||||
fi, _ := fold.Readdirnames(-1)
|
fi, _ := fold.Readdirnames(-1)
|
||||||
@@ -76,13 +103,13 @@ func (p *prtapAdap) Create(th gxui.Theme, index int) gxui.Control {
|
|||||||
box.AddChild(icon)
|
box.AddChild(icon)
|
||||||
}
|
}
|
||||||
lbl := th.CreateLabel()
|
lbl := th.CreateLabel()
|
||||||
lbl.SetText(p.apps[index].name)
|
lbl.SetText(p.cur[index].name)
|
||||||
box.AddChild(lbl)
|
box.AddChild(lbl)
|
||||||
return box
|
return box
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prtapAdap) ItemAt(index int) gxui.AdapterItem {
|
func (p *prtapAdap) ItemAt(index int) gxui.AdapterItem {
|
||||||
return p.apps[index]
|
return p.cur[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prtapAdap) ItemIndex(item gxui.AdapterItem) int {
|
func (p *prtapAdap) ItemIndex(item gxui.AdapterItem) int {
|
||||||
@@ -90,7 +117,7 @@ func (p *prtapAdap) ItemIndex(item gxui.AdapterItem) int {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
for i, v := range p.apps {
|
for i, v := range p.cur {
|
||||||
if v == it {
|
if v == it {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@@ -16,8 +17,9 @@ var (
|
|||||||
func uiMain(dri gxui.Driver) {
|
func uiMain(dri gxui.Driver) {
|
||||||
dr = dri
|
dr = dri
|
||||||
catAdap := &StrList{}
|
catAdap := &StrList{}
|
||||||
catAdap.SetStrings(cats)
|
catAdap.SetStrings(linOnly)
|
||||||
appAdap := &prtapAdap{}
|
appAdap := &prtapAdap{}
|
||||||
|
appAdap.Wine(false)
|
||||||
th := dark.CreateTheme(dr)
|
th := dark.CreateTheme(dr)
|
||||||
win := th.CreateWindow(500, 500, "LinuxPA")
|
win := th.CreateWindow(500, 500, "LinuxPA")
|
||||||
top := th.CreateLinearLayout()
|
top := th.CreateLinearLayout()
|
||||||
@@ -44,16 +46,40 @@ func uiMain(dri gxui.Driver) {
|
|||||||
app := applist.Selected().(prtap)
|
app := applist.Selected().(prtap)
|
||||||
dir, fi := path.Split(app.ex)
|
dir, fi := path.Split(app.ex)
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
if commEnbl {
|
if app.wine {
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". "+common+" || exit 1;cd \""+dir+"\"; \"./"+fi+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+dir+"\"; wine \""+fi+"\"")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+dir+"\"; \"./"+fi+"\"")
|
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.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Start()
|
cmd.Start()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if _, err := exec.LookPath("wine"); err == nil {
|
||||||
|
fmt.Println("Wine found!")
|
||||||
|
wine := th.CreateButton()
|
||||||
|
wine.SetType(gxui.ToggleButton)
|
||||||
|
wine.OnClick(func(gxui.MouseEvent) {
|
||||||
|
if wine.IsChecked() {
|
||||||
|
catAdap.SetStrings(cats)
|
||||||
|
appAdap.Wine(true)
|
||||||
|
} else {
|
||||||
|
catAdap.SetStrings(linOnly)
|
||||||
|
appAdap.Wine(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
wine.SetText("Show Windows Apps")
|
||||||
|
wine.SetChecked(appAdap.wine)
|
||||||
|
but.AddChild(wine)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Wine not found!")
|
||||||
|
}
|
||||||
but.AddChild(launch)
|
but.AddChild(launch)
|
||||||
top.AddChild(but)
|
top.AddChild(but)
|
||||||
top.AddChild(spl)
|
top.AddChild(spl)
|
||||||
|
|||||||
Reference in New Issue
Block a user