Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 868ae8f700 | |||
| 226e9d6210 | |||
| 56748f043e | |||
| 3d3239fe0a | |||
| 6e643b68ac | |||
| 539f33d25e | |||
| 4d3cb9f486 | |||
| a55c82483a | |||
| 9e9bb82025 | |||
| ea91d3cd80 | |||
| 2a0d53db09 | |||
| a0213d1886 | |||
| 695ce815d9 | |||
| 01556c1eb0 | |||
| d7410bb88f | |||
| bc63e6d10f | |||
| 0403825c3d | |||
| 0f1bb3fabd | |||
| 78c6842fab | |||
| dc1edbad3a | |||
| 6dd00c5f8f | |||
| e68337886f | |||
| 3b639f53fd | |||
| 3199ad88fd | |||
| a221d18d33 |
@@ -2,10 +2,10 @@
|
||||
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
||||
|
||||
# How to use
|
||||
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 (.sh script files have priority), but if one isn't found it launches the first executable in general.
|
||||
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 it finds. .sh script files have priority over other executable files.
|
||||
|
||||
# Apps:
|
||||
Both of the below places provide linux executables that don't need libs installed on the host system:
|
||||
The below place provides linux executables that don't need libs installed on the host system:
|
||||
[AppImage](https://bintray.com/probono/AppImages)
|
||||
|
||||
# PortableApps.com Compatibility
|
||||
@@ -13,25 +13,23 @@ LinuxPA works will with the PortableApps.com launcher, as it looks for apps in t
|
||||
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
|
||||
|
||||
# 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). You can create and edit the common.sh from settings
|
||||
|
||||
# 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 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=`
|
||||
Because apps aren't natively formated in the PortableApps.com format, LinuxPA will look in the root directory for a AppInfo.ini (for basic info such as category and name) and appicon.png. If they aren't found, it looks where the appicon_\*.png and AppInfo.ini is in PortableApps format. You can set what the AppInfo.ini and appicon.png are from LinuxPA.
|
||||
|
||||
# AppImage Support
|
||||
[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 later on.
|
||||
Right now AppImages are simply supported via the native linux executable support, and you can download AppImages. (Woo)
|
||||
|
||||
# USB mount
|
||||
Unfortunately Linux, by default, doesn't support running executables off of FAT formated flash drives, requiring you to mount your drive with special mount arguments or format in a linux friendly format (such as EXT4). I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
||||
|
||||
# Screenshots
|
||||
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
||||
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshots are with the adapta gtk theme
|
||||
|
||||
# TODO (Might be in order)
|
||||
1. MAKE IT BETTER
|
||||
1. Add settings menu
|
||||
1. Add updater for .AppImage files
|
||||
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. Portable wine (Should be able to get a working version from PlayOnLinux, but I need to add a check to see if filesystem is EXT as Wine doesn't like filesystems w/o permission control)
|
||||
1. MAKE IT BETTER
|
||||
1. Manual update check
|
||||
1. Better appimage support in general
|
||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/nelsam/gxui"
|
||||
"github.com/nelsam/gxui/math"
|
||||
"github.com/gotk3/gotk3/gdk"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
type app struct {
|
||||
@@ -15,94 +17,54 @@ type app struct {
|
||||
appimg []string
|
||||
lin []string
|
||||
ex []string
|
||||
icon gxui.Texture
|
||||
icon *gdk.Pixbuf
|
||||
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]+"\"")
|
||||
func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter {
|
||||
it := store.Append(nil)
|
||||
store.SetValue(it, 0, a.icon)
|
||||
if portableHide {
|
||||
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
|
||||
} else {
|
||||
store.SetValue(it, 1, a.name)
|
||||
}
|
||||
if len(a.ex) > 1 {
|
||||
if wine {
|
||||
for _, v := range a.ex {
|
||||
i := store.Append(it)
|
||||
store.SetValue(i, 1, v)
|
||||
}
|
||||
} 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]+"\"")
|
||||
for _, v := range a.lin {
|
||||
i := store.Append(it)
|
||||
store.SetValue(i, 1, v)
|
||||
}
|
||||
}
|
||||
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()
|
||||
return it
|
||||
}
|
||||
|
||||
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 {
|
||||
func (a *app) launch() {
|
||||
if len(a.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 !contains(a.lin, a.ex[0]) {
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||
}
|
||||
} else {
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[0]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[0]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[0]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. 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
|
||||
@@ -110,10 +72,14 @@ func (a *appNode) launch() {
|
||||
cmd.Start()
|
||||
} else {
|
||||
var cmd *exec.Cmd
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[0]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[0]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[0]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||
}
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@@ -122,39 +88,51 @@ func (a *appNode) launch() {
|
||||
} 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]+"\"")
|
||||
if len(a.lin) == 0 {
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||
}
|
||||
} else {
|
||||
var ind int
|
||||
for i, v := range a.ap.lin {
|
||||
for i, v := range a.lin {
|
||||
if strings.HasSuffix(v, ".sh") {
|
||||
ind = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[ind]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||
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.ap.lin) != 0 {
|
||||
if len(a.lin) != 0 {
|
||||
var ind int
|
||||
for i, v := range a.ap.lin {
|
||||
for i, v := range a.lin {
|
||||
if strings.HasSuffix(v, ".sh") {
|
||||
ind = i
|
||||
break
|
||||
}
|
||||
}
|
||||
var cmd *exec.Cmd
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[ind]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||
}
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@@ -164,109 +142,172 @@ func (a *appNode) launch() {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *appNode) Count() int {
|
||||
func (a *app) launchSub(sub 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
|
||||
var cmd *exec.Cmd
|
||||
if !contains(a.lin, a.ex[sub]) {
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
|
||||
} else {
|
||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
|
||||
}
|
||||
} else {
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[sub]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. 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()
|
||||
} else {
|
||||
for i, v := range a.ap.lin {
|
||||
if v == item {
|
||||
return i
|
||||
}
|
||||
var cmd *exec.Cmd
|
||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[sub]), ".appimage") {
|
||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".home", 0777)
|
||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".config", 0777)
|
||||
}
|
||||
if comEnbld {
|
||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. 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()
|
||||
}
|
||||
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()
|
||||
func (a *app) edit(parent *gtk.Window, reload func()) {
|
||||
tmp := *a
|
||||
parent.SetSensitive(false)
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
win.Connect("destroy", func() {
|
||||
master = make(map[string][]app)
|
||||
linmaster = make(map[string][]app)
|
||||
cats = make([]string, 0)
|
||||
lin = make([]string, 0)
|
||||
setup()
|
||||
reload()
|
||||
parent.SetSensitive(true)
|
||||
})
|
||||
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
|
||||
win.SetDefaultSize(400, 135)
|
||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
topLvl.SetMarginStart(10)
|
||||
topLvl.SetMarginEnd(10)
|
||||
topLvl.SetMarginTop(10)
|
||||
topLvl.SetMarginBottom(10)
|
||||
top, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||
img, _ := gtk.ImageNewFromPixbuf(a.icon)
|
||||
imgBut, _ := gtk.ButtonNew()
|
||||
imgBut.SetImage(img)
|
||||
imgBut.SetSizeRequest(100, 100)
|
||||
imgBut.Connect("clicked", func() {
|
||||
fil, _ := gtk.FileChooserDialogNewWith1Button("Select Icon", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_ACCEPT)
|
||||
filter, _ := gtk.FileFilterNew()
|
||||
filter.AddPixbufFormats()
|
||||
filter.SetName("Supported Pictures")
|
||||
fil.AddFilter(filter)
|
||||
but, _ := fil.AddButton("Cancel", gtk.RESPONSE_CANCEL)
|
||||
but.Connect("clicked", func() {
|
||||
fil.Close()
|
||||
})
|
||||
resp := fil.Run()
|
||||
if resp == int(gtk.RESPONSE_ACCEPT) {
|
||||
filename := fil.GetFilename()
|
||||
_, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
pix, _ := gdk.PixbufNewFromFileAtSize(filename, 32, 32)
|
||||
tmp.icon = pix
|
||||
img.SetFromPixbuf(pix)
|
||||
fil.Close()
|
||||
}
|
||||
} else {
|
||||
for i, v := range linmaster[a.cat] {
|
||||
if v.name == item {
|
||||
return i
|
||||
}
|
||||
}
|
||||
})
|
||||
topRt, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
nameLbl, _ := gtk.LabelNew("Name:")
|
||||
nameLbl.SetHAlign(gtk.ALIGN_START)
|
||||
txtgtbl, _ := gtk.TextTagTableNew()
|
||||
txtBuf, _ := gtk.TextBufferNew(txtgtbl)
|
||||
nameTxt, _ := gtk.TextViewNewWithBuffer(txtBuf)
|
||||
nameTxt.SetAcceptsTab(false)
|
||||
nameTxt.SetWrapMode(gtk.WRAP_CHAR)
|
||||
nameTxt.SetPixelsBelowLines(5)
|
||||
nameTxt.SetHExpand(true)
|
||||
nameTxt.SetVExpand(false)
|
||||
nameTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
||||
txtBuf.SetText(tmp.name)
|
||||
vScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
hScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
nameScr, _ := gtk.ScrolledWindowNew(hScrollName, vScrollName)
|
||||
nameScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
||||
nameScr.SetSizeRequest(300, 25)
|
||||
nameScr.SetVExpand(false)
|
||||
nameScr.Add(nameTxt)
|
||||
catLbl, _ := gtk.LabelNew("Category:")
|
||||
catLbl.SetHAlign(gtk.ALIGN_START)
|
||||
catTbl, _ := gtk.TextTagTableNew()
|
||||
catBuf, _ := gtk.TextBufferNew(catTbl)
|
||||
catTxt, _ := gtk.TextViewNewWithBuffer(catBuf)
|
||||
catBuf.SetText(tmp.cat)
|
||||
catTxt.SetAcceptsTab(false)
|
||||
catTxt.SetWrapMode(gtk.WRAP_CHAR)
|
||||
catTxt.SetPixelsBelowLines(5)
|
||||
catTxt.SetHExpand(true)
|
||||
catTxt.SetVExpand(false)
|
||||
catTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
||||
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
catScr, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
||||
catScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
||||
catScr.SetSizeRequest(300, 25)
|
||||
catScr.SetVExpand(false)
|
||||
catScr.Add(catTxt)
|
||||
topRt.Add(nameLbl)
|
||||
topRt.Add(nameScr)
|
||||
topRt.Add(catLbl)
|
||||
topRt.Add(catScr)
|
||||
top.Add(imgBut)
|
||||
top.Add(topRt)
|
||||
bot, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||
sv, _ := gtk.ButtonNewWithLabel("Save")
|
||||
sv.Connect("clicked", func() {
|
||||
tmp.name, _ = txtBuf.GetText(txtBuf.GetStartIter(), txtBuf.GetEndIter(), true)
|
||||
tmp.cat, _ = catBuf.GetText(catBuf.GetStartIter(), catBuf.GetEndIter(), true)
|
||||
tmp.makeIni()
|
||||
os.Remove(a.dir + "/appicon.png")
|
||||
tmp.icon.SavePNG(a.dir+"/appicon.png", 0)
|
||||
win.Close()
|
||||
})
|
||||
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||
cnl.Connect("clicked", func() {
|
||||
win.Close()
|
||||
})
|
||||
bot.PackEnd(sv, false, false, 0)
|
||||
bot.PackEnd(cnl, false, false, 0)
|
||||
topLvl.Add(top)
|
||||
topLvl.Add(bot)
|
||||
win.Add(topLvl)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
}
|
||||
|
||||
func (a *app) makeIni() {
|
||||
os.Remove(a.dir + "/appinfo.ini")
|
||||
fil, err := os.Create(a.dir + "/appinfo.ini")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return -1
|
||||
ini := "[General]\n"
|
||||
ini += "Category=" + a.cat + "\n"
|
||||
ini += "Name=" + a.name + "\n"
|
||||
wrt := bufio.NewWriter(fil)
|
||||
wrt.WriteString(ini)
|
||||
wrt.Flush()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package appimg
|
||||
|
||||
import "reflect"
|
||||
|
||||
func convert(in string) (out []tag) {
|
||||
for i := 0; i < len(in); i++ {
|
||||
v := in[i]
|
||||
if v == '<' {
|
||||
for j := i; j < len(in); j++ {
|
||||
val := in[j]
|
||||
if val == '>' {
|
||||
var tmp tag
|
||||
tmp.process(in[i+1 : j+1])
|
||||
if !tmp.end && tmp.typ == "a" {
|
||||
tmp.index[0] = i
|
||||
tmp.index[1] = j
|
||||
nd := fndend(tmp, in[j+1:])
|
||||
if !reflect.DeepEqual(nd, tag{}) {
|
||||
tmp.Meat = in[j+1 : nd.index[0]]
|
||||
out = append(out, tmp)
|
||||
str := in[tmp.index[1]:nd.index[0]]
|
||||
in = in[:i] + str + in[nd.index[1]+1:]
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fndend(fnt tag, area string) tag {
|
||||
var count int
|
||||
for i, v := range area {
|
||||
if v == '<' {
|
||||
for j, val := range area[i:] {
|
||||
if val == '>' {
|
||||
var tmp tag
|
||||
tmp.process(area[i+1 : i+j+1])
|
||||
if tmp.typ == fnt.typ {
|
||||
if tmp.end {
|
||||
if count == 0 {
|
||||
tmp.index[0] = fnt.index[1] + 1 + i
|
||||
tmp.index[1] = fnt.index[1] + j + i + 1
|
||||
return tmp
|
||||
}
|
||||
count--
|
||||
break
|
||||
} else {
|
||||
count++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag{}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package appimg
|
||||
|
||||
import "strings"
|
||||
|
||||
type tag struct {
|
||||
typ string
|
||||
end bool
|
||||
params map[string]string
|
||||
index [2]int
|
||||
Meat string
|
||||
}
|
||||
|
||||
func (t *tag) value(param string) string {
|
||||
return t.params[param]
|
||||
}
|
||||
|
||||
func (t *tag) setValue(param, value string) {
|
||||
if t.params == nil {
|
||||
t.params = make(map[string]string)
|
||||
}
|
||||
t.params[strings.TrimSpace(strings.ToLower(param))] = strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
func (t *tag) process(bbtag string) {
|
||||
if strings.HasPrefix(bbtag, "/") {
|
||||
t.end = true
|
||||
t.typ = strings.ToLower(strings.TrimPrefix(bbtag[:len(bbtag)-1], "/"))
|
||||
return
|
||||
}
|
||||
for i, v := range bbtag {
|
||||
if v == '=' || v == ' ' || v == '>' {
|
||||
t.typ = strings.ToLower(bbtag[:i])
|
||||
switch v {
|
||||
case '=':
|
||||
if qt := bbtag[i+1]; qt == '\'' || qt == '"' {
|
||||
for j := i + 2; j < len(bbtag); j++ {
|
||||
if bbtag[j] == qt {
|
||||
t.setValue("starting", bbtag[i+2:j])
|
||||
bbtag = bbtag[j+1:]
|
||||
break
|
||||
} else if bbtag[j] == '>' {
|
||||
t.setValue("starting", bbtag[i+2:j])
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for j := i + 1; j < len(bbtag); j++ {
|
||||
if bbtag[j] == '>' {
|
||||
t.setValue("starting", bbtag[i+1:j])
|
||||
return
|
||||
} else if bbtag[j] == ' ' {
|
||||
t.setValue("starting", bbtag[i+1:j])
|
||||
bbtag = bbtag[j+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case '>':
|
||||
return
|
||||
case ' ':
|
||||
bbtag = bbtag[i:]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
t.processFurther(bbtag)
|
||||
}
|
||||
|
||||
func (t *tag) processFurther(further string) {
|
||||
further = strings.TrimSpace(further)
|
||||
for i := 0; i < len(further); i++ {
|
||||
switch further[i] {
|
||||
case ' ':
|
||||
t.setValue(strings.ToLower(further[:i]), further[:i])
|
||||
further = strings.TrimSpace(further[i:])
|
||||
i = -1
|
||||
case '=':
|
||||
if qt := further[i+1]; qt == '\'' || qt == '"' {
|
||||
outloopqt:
|
||||
for j := i + 2; j < len(further); j++ {
|
||||
switch further[j] {
|
||||
case '>':
|
||||
t.setValue(strings.ToLower(further[:i]), further[i+2:j])
|
||||
return
|
||||
case qt:
|
||||
t.setValue(strings.ToLower(further[:i]), further[i+2:j])
|
||||
further = strings.TrimSpace(further[j+1:])
|
||||
i = -1
|
||||
break outloopqt
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outloop:
|
||||
for j := i + 1; j < len(further); j++ {
|
||||
switch further[j] {
|
||||
case '>':
|
||||
t.setValue(strings.ToLower(further[:i]), further[i+1:j])
|
||||
return
|
||||
case ' ':
|
||||
t.setValue(strings.ToLower(further[:i]), further[i+1:j])
|
||||
further = strings.TrimSpace(further[j:])
|
||||
i = -1
|
||||
break outloop
|
||||
}
|
||||
}
|
||||
}
|
||||
case '>':
|
||||
if i != 0 {
|
||||
t.setValue(strings.ToLower(further[:i]), further[:i])
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package appimg
|
||||
|
||||
type appimg struct {
|
||||
full string
|
||||
name string
|
||||
version string
|
||||
}
|
||||
|
||||
func newApp(name string) appimg {
|
||||
var out appimg
|
||||
out.full = name
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package appimg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
func downloadApp(parent *gtk.Window, ap appimg) {
|
||||
parent.SetSensitive(false)
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
win.SetTransientFor(parent)
|
||||
win.Connect("destroy", func() {
|
||||
parent.SetSensitive(true)
|
||||
})
|
||||
spn, _ := gtk.SpinnerNew()
|
||||
spn.Start()
|
||||
lbl, _ := gtk.LabelNew("Downloading " + ap.full + "...")
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
box.SetMarginStart(10)
|
||||
box.SetMarginEnd(10)
|
||||
box.SetMarginTop(10)
|
||||
box.SetMarginBottom(10)
|
||||
box.Add(spn)
|
||||
box.Add(lbl)
|
||||
win.Add(box)
|
||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
go func(win *gtk.Window, ap appimg) {
|
||||
defer win.Close()
|
||||
check := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
},
|
||||
}
|
||||
resp, err := check.Get(urlBase + ap.full)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
name := strings.Split(ap.full, "-")[0]
|
||||
var foldName string
|
||||
if _, err = os.Open("PortableApps/" + name + "Portable"); err == nil {
|
||||
foldName = "PortableApps/" + name + "Portable"
|
||||
} else if _, err = os.Open("PortableApps/" + name); err == nil {
|
||||
foldName = "PortableApps/" + name
|
||||
} else {
|
||||
os.Mkdir("PortableApps/"+name+"Portable", 0777)
|
||||
foldName = "PortableApps/" + name + "Portable"
|
||||
}
|
||||
os.Remove(foldName + "/" + ap.full)
|
||||
fil, err := os.Create(foldName + "/" + ap.full)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
io.Copy(fil, resp.Body)
|
||||
fil.Chmod(0777)
|
||||
}(win, ap)
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
//Package appimg is for downloading new AppImages for LinuxPA
|
||||
package appimg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const (
|
||||
urlBase = "https://dl.bintray.com/probono/AppImages/"
|
||||
)
|
||||
|
||||
//ShowUI shows the list of possible AppImages to be downloaded in a gtk.Window
|
||||
func ShowUI(newestVersionOnly bool, clsFunc func()) {
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
win.Connect("destroy", func() {
|
||||
clsFunc()
|
||||
})
|
||||
apps := make([]appimg, 0)
|
||||
win.SetSizeRequest(400, 400)
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
appList, _ := gtk.ListBoxNew()
|
||||
apch := make(chan appimg)
|
||||
appList.SetHExpand(true)
|
||||
appList.SetVExpand(true)
|
||||
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
lst, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
||||
lst.SetSizeRequest(170, 500)
|
||||
lst.Add(appList)
|
||||
box.Add(lst)
|
||||
win.Add(box)
|
||||
appList.Connect("row-activated", func() {
|
||||
if appList.GetSelectedRow().GetIndex() >= 0 {
|
||||
downloadApp(win, apps[appList.GetSelectedRow().GetIndex()])
|
||||
}
|
||||
})
|
||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
getList(win, apch)
|
||||
go func(win *gtk.Window, apch chan appimg, list *gtk.ListBox) {
|
||||
if newestVersionOnly {
|
||||
imgs := make([]appimg, 0)
|
||||
a := make(map[string][]appimg)
|
||||
names := make([]string, 0)
|
||||
for i := range apch {
|
||||
imgs = append(imgs, i)
|
||||
}
|
||||
for i, v := range imgs {
|
||||
sp := strings.Split(v.full, "-")
|
||||
if len(sp) >= 2 {
|
||||
vers := sp[1]
|
||||
removeLetters(vers)
|
||||
imgs[i].version = vers
|
||||
imgs[i].name = sp[0]
|
||||
if _, ok := a[imgs[i].name]; !ok {
|
||||
names = append(names, imgs[i].name)
|
||||
}
|
||||
a[imgs[i].name] = append(a[imgs[i].name], imgs[i])
|
||||
}
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, name := range names {
|
||||
glib.IdleAdd(func(name string, list *gtk.ListBox, i appimg) {
|
||||
lbl, _ := gtk.LabelNew(name)
|
||||
list.Add(lbl)
|
||||
apps = append(apps, i)
|
||||
lbl.Show()
|
||||
}, name, list, a[name][compareVersions(a[name])])
|
||||
}
|
||||
} else {
|
||||
for i := range apch {
|
||||
glib.IdleAdd(func(list *gtk.ListBox, i appimg) {
|
||||
lbl, _ := gtk.LabelNew(i.full)
|
||||
list.Add(lbl)
|
||||
apps = append(apps, i)
|
||||
lbl.Show()
|
||||
}, list, i)
|
||||
}
|
||||
}
|
||||
}(win, apch, appList)
|
||||
}
|
||||
|
||||
func getList(parent *gtk.Window, apch chan appimg) {
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_POPUP)
|
||||
win.SetTransientFor(parent)
|
||||
win.SetDestroyWithParent(true)
|
||||
win.Connect("destroy", func() {
|
||||
parent.SetSensitive(true)
|
||||
})
|
||||
parent.SetSensitive(false)
|
||||
spin, _ := gtk.SpinnerNew()
|
||||
spin.Start()
|
||||
txt, _ := gtk.LabelNew("Getting List...")
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
box.SetMarginBottom(10)
|
||||
box.SetMarginEnd(10)
|
||||
box.SetMarginStart(10)
|
||||
box.SetMarginTop(10)
|
||||
box.Add(spin)
|
||||
box.Add(txt)
|
||||
win.Add(box)
|
||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
go func(win *gtk.Window, apch chan appimg) {
|
||||
check := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
},
|
||||
}
|
||||
resp, err := check.Get(urlBase)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
close(apch)
|
||||
win.Close()
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
btys, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
close(apch)
|
||||
win.Close()
|
||||
return
|
||||
}
|
||||
tgs := convert(string(btys))
|
||||
for _, v := range tgs {
|
||||
if strings.HasSuffix(strings.ToLower(v.Meat), ".appimage") {
|
||||
apch <- newApp(v.Meat)
|
||||
}
|
||||
}
|
||||
close(apch)
|
||||
win.Close()
|
||||
}(win, apch)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package appimg
|
||||
|
||||
import "strings"
|
||||
|
||||
func removeLetters(vers string) string {
|
||||
vers = strings.ToLower(vers)
|
||||
letters := []string{"abcdefghijklmnopqrstuvwxyz"}
|
||||
for _, v := range letters {
|
||||
vers = strings.Replace(vers, v, "", -1)
|
||||
}
|
||||
return vers
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package appimg
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func compareVersions(imgs []appimg) int {
|
||||
for i := range imgs {
|
||||
imgs[i].version = removeLetters(imgs[i].version)
|
||||
}
|
||||
highest := 0
|
||||
higharr := strings.Split(imgs[0].version, ".")
|
||||
for i := 0; i < len(imgs); i++ {
|
||||
if i != highest {
|
||||
varr := strings.Split(imgs[i].version, ".")
|
||||
if len(higharr) < len(varr) {
|
||||
for j := 0; j < len(higharr); j++ {
|
||||
h, _ := strconv.Atoi(higharr[j])
|
||||
c, _ := strconv.Atoi(varr[j])
|
||||
if h > c {
|
||||
break
|
||||
} else if c > h {
|
||||
highest = i
|
||||
higharr = varr
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return highest
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1,75 +1,108 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"flag"
|
||||
"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"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const (
|
||||
version = "1.1.0.0"
|
||||
defIni = "[basic]\ntheme=dk"
|
||||
version = "2.1.2.1"
|
||||
)
|
||||
|
||||
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
|
||||
master map[string][]app
|
||||
linmaster map[string][]app
|
||||
cats []string
|
||||
lin []string
|
||||
wine bool
|
||||
comEnbld bool
|
||||
wineAvail bool
|
||||
portableHide bool
|
||||
versionNewest = true
|
||||
paDirs = true
|
||||
)
|
||||
|
||||
func main() {
|
||||
updated := false
|
||||
forced := flag.Bool("force-update", false, "Force the update dialog to be shown")
|
||||
flag.Parse()
|
||||
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)
|
||||
master = make(map[string][]app)
|
||||
linmaster = make(map[string][]app)
|
||||
uiStart(*forced)
|
||||
}
|
||||
|
||||
func uiStart(forced bool) {
|
||||
gtk.Init(nil)
|
||||
setup()
|
||||
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
if err != nil {
|
||||
fmt.Println("Window not created", 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)
|
||||
win.SetTitle("LinuxPA")
|
||||
win.Connect("destroy", func() {
|
||||
savePrefs()
|
||||
gtk.MainQuit()
|
||||
})
|
||||
win.SetDefaultSize(500, 500)
|
||||
win.SetPosition(gtk.WIN_POS_CENTER)
|
||||
ui(win)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
update(win, forced)
|
||||
gtk.Main()
|
||||
}
|
||||
|
||||
func savePrefs() {
|
||||
os.Remove("PortableApps/LinuxPACom/Prefs.gob")
|
||||
fil, err := os.Create("PortableApps/LinuxPACom/Prefs.gob")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
enc := gob.NewEncoder(fil)
|
||||
err = enc.Encode(wine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = enc.Encode(portableHide)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = enc.Encode(versionNewest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = enc.Encode(paDirs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func appMain(dri gxui.Driver) {
|
||||
dr = dri
|
||||
setup()
|
||||
if darkTheme {
|
||||
th = dark.CreateTheme(dr)
|
||||
} else {
|
||||
th = light.CreateTheme(dr)
|
||||
func loadPrefs() {
|
||||
fil, err := os.Open("PortableApps/LinuxPACom/Prefs.gob")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dec := gob.NewDecoder(fil)
|
||||
err = dec.Decode(&wine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dec.Decode(&portableHide)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dec.Decode(&versionNewest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dec.Decode(&paDirs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
th = dark.CreateTheme(dr)
|
||||
ui()
|
||||
}
|
||||
|
||||
func contains(arr []string, str string) bool {
|
||||
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const (
|
||||
commonHelp = "The common.sh is run before every app is launched and allows you to set variables such as $HOME. For directories, ALWAYS start the directory with $PWD which points to the directory where LinuxPA is. To allow for greater customization and isolation, you can use the $FILENAME variable which is the filename of the executable you're using and the $APPNAME variable which is the name of the app being lanched."
|
||||
)
|
||||
|
||||
func settingsUI(parent *gtk.Window, onExit func()) {
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
win.SetTransientFor(parent)
|
||||
parent.SetSensitive(false)
|
||||
win.SetDefaultSize(600, 300)
|
||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
win.Connect("destroy", func() {
|
||||
parent.SetSensitive(true)
|
||||
onExit()
|
||||
})
|
||||
comTagTbl, _ := gtk.TextTagTableNew()
|
||||
comBuf, _ := gtk.TextBufferNew(comTagTbl)
|
||||
ntbk, _ := gtk.NotebookNew()
|
||||
gnrl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
gnrl.SetMarginStart(10)
|
||||
gnrl.SetMarginEnd(10)
|
||||
gnrl.SetMarginTop(10)
|
||||
gnrl.SetMarginBottom(10)
|
||||
dlWine, _ := gtk.ButtonNewWithLabel("Download Wine")
|
||||
wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)")
|
||||
wineLbl, _ := gtk.LabelNew("PortableApps/LinuxPACom/Wine present")
|
||||
dlWine.Connect("clicked", func() {
|
||||
cb := make(chan bool)
|
||||
downloadWine(win, cb)
|
||||
go func() {
|
||||
v := <-cb
|
||||
if v {
|
||||
setupTxt(comBuf)
|
||||
wineLbl.Show()
|
||||
}
|
||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
||||
if _, errd := exec.LookPath("wine"); errd == nil {
|
||||
wineAvail = true
|
||||
}
|
||||
} else if err == nil {
|
||||
wineAvail = true
|
||||
}
|
||||
glib.IdleAdd(func() {
|
||||
if !wineAvail {
|
||||
wineCheck.SetSensitive(false)
|
||||
wineCheck.SetTooltipText("Download wine to run windows apps")
|
||||
} else {
|
||||
wineCheck.SetSensitive(true)
|
||||
wineCheck.SetTooltipText("")
|
||||
}
|
||||
})
|
||||
}()
|
||||
})
|
||||
if !comEnbld {
|
||||
dlWine.SetSensitive(false)
|
||||
dlWine.SetTooltipText("common.sh needed")
|
||||
}
|
||||
pthdCheck, _ := gtk.CheckButtonNewWithLabel("Hide \"Portable\" from app name")
|
||||
pthdCheck.Connect("toggled", func() {
|
||||
portableHide = pthdCheck.GetActive()
|
||||
master = make(map[string][]app)
|
||||
linmaster = make(map[string][]app)
|
||||
cats = make([]string, 0)
|
||||
lin = make([]string, 0)
|
||||
setup()
|
||||
})
|
||||
pthdCheck.SetActive(portableHide)
|
||||
if !wineAvail {
|
||||
wineCheck.SetSensitive(false)
|
||||
wineCheck.SetTooltipText("Download wine to run windows apps")
|
||||
}
|
||||
wineCheck.SetActive(wine)
|
||||
wineCheck.Connect("toggled", func() {
|
||||
wine = wineCheck.GetActive()
|
||||
})
|
||||
versCheck, _ := gtk.CheckButtonNewWithLabel("Only show newest app version in downloads (A bit iffy ATM)")
|
||||
versCheck.SetActive(versionNewest)
|
||||
versCheck.Connect("toggled", func() {
|
||||
versionNewest = versCheck.GetActive()
|
||||
})
|
||||
paDirsCheck, _ := gtk.CheckButtonNewWithLabel("Create .home and .config directories for AppImages")
|
||||
paDirsCheck.SetActive(paDirs)
|
||||
paDirsCheck.Connect("toggled", func() {
|
||||
paDirs = paDirsCheck.GetActive()
|
||||
})
|
||||
gnrl.Add(wineLbl)
|
||||
gnrl.Add(dlWine)
|
||||
gnrl.Add(pthdCheck)
|
||||
gnrl.Add(wineCheck)
|
||||
gnrl.Add(versCheck)
|
||||
gnrl.Add(paDirsCheck)
|
||||
ntbk.AppendPage(gnrl, getLabel("General"))
|
||||
com, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
com.SetMarginStart(10)
|
||||
com.SetMarginEnd(10)
|
||||
com.SetMarginTop(10)
|
||||
com.SetMarginBottom(10)
|
||||
comEdit, _ := gtk.TextViewNewWithBuffer(comBuf)
|
||||
comEdit.SetVExpand(true)
|
||||
comEdit.SetHExpand(true)
|
||||
vScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
hScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||
comScrl, _ := gtk.ScrolledWindowNew(hScroll, vScroll)
|
||||
comScrl.Add(comEdit)
|
||||
svBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||
sv, _ := gtk.ButtonNewWithLabel("Save")
|
||||
sv.Connect("clicked", func() {
|
||||
beg, end := comBuf.GetBounds()
|
||||
txt, _ := comBuf.GetText(beg, end, true)
|
||||
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte(txt), 0777)
|
||||
})
|
||||
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||
cnl.Connect("clicked", func() {
|
||||
setupTxt(comBuf)
|
||||
})
|
||||
info, _ := gtk.ButtonNewWithLabel("Info")
|
||||
info.Connect("clicked", func() {
|
||||
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
infoBox.SetTransientFor(parent)
|
||||
infoBox.SetDefaultSize(300, 80)
|
||||
infoBox.SetName("common.sh info")
|
||||
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
infolbl, _ := gtk.LabelNew(commonHelp)
|
||||
infolbl.SetLineWrap(true)
|
||||
infolbl.SetSizeRequest(200, 50)
|
||||
box.Add(infolbl)
|
||||
infoBox.Add(box)
|
||||
infoBox.ShowAll()
|
||||
infoBox.Show()
|
||||
})
|
||||
svBox.Add(sv)
|
||||
svBox.Add(cnl)
|
||||
svBox.Add(info)
|
||||
com.Add(comScrl)
|
||||
com.Add(svBox)
|
||||
ntbk.AppendPage(com, getLabel("common.sh"))
|
||||
win.Add(ntbk)
|
||||
win.ShowAll()
|
||||
if !comEnbld {
|
||||
comScrl.Hide()
|
||||
svBox.Hide()
|
||||
mkCom, _ := gtk.ButtonNewWithLabel("Create common.sh")
|
||||
mkCom.Connect("clicked", func() {
|
||||
err := ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte("export HOME=$PWD/PortableApps/LinuxPACom/Home"), 0777)
|
||||
if err == nil {
|
||||
mkCom.Hide()
|
||||
comScrl.Show()
|
||||
svBox.Show()
|
||||
setupTxt(comBuf)
|
||||
comEnbld = true
|
||||
dlWine.SetSensitive(true)
|
||||
dlWine.SetTooltipText("")
|
||||
}
|
||||
})
|
||||
in, _ := gtk.ButtonNewWithLabel("Info")
|
||||
in.Connect("clicked", func() {
|
||||
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
infoBox.SetTransientFor(parent)
|
||||
infoBox.SetDefaultSize(300, 80)
|
||||
infoBox.SetName("common.sh info")
|
||||
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
infolbl, _ := gtk.LabelNew(commonHelp)
|
||||
infolbl.SetLineWrap(true)
|
||||
infolbl.SetSizeRequest(200, 50)
|
||||
box.Add(infolbl)
|
||||
infoBox.Add(box)
|
||||
infoBox.ShowAll()
|
||||
infoBox.Show()
|
||||
})
|
||||
mkCom.Show()
|
||||
com.Add(mkCom)
|
||||
com.Add(in)
|
||||
} else {
|
||||
setupTxt(comBuf)
|
||||
}
|
||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); err != nil && os.IsNotExist(err) {
|
||||
wineLbl.Hide()
|
||||
}
|
||||
win.Show()
|
||||
}
|
||||
|
||||
func setupTxt(buf *gtk.TextBuffer) {
|
||||
fil, _ := os.Open("PortableApps/LinuxPACom/common.sh")
|
||||
btys, _ := ioutil.ReadAll(fil)
|
||||
buf.SetText(string(btys))
|
||||
}
|
||||
|
||||
func getLabel(name string) *gtk.Label {
|
||||
lbl, _ := gtk.LabelNew(name)
|
||||
return lbl
|
||||
}
|
||||
@@ -2,21 +2,29 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
_ "image/png"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/nelsam/gxui"
|
||||
"github.com/gotk3/gotk3/gdk"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const ()
|
||||
|
||||
func setup() {
|
||||
loadPrefs()
|
||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
||||
if _, errd := exec.LookPath("wine"); errd == nil {
|
||||
wineAvail = true
|
||||
}
|
||||
} else if err == nil {
|
||||
wineAvail = true
|
||||
}
|
||||
if !wineAvail {
|
||||
wine = false
|
||||
}
|
||||
PortableAppsFold, err := os.Open("PortableApps")
|
||||
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
||||
os.Mkdir("PortableApps", 0777)
|
||||
@@ -28,34 +36,10 @@ func setup() {
|
||||
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 {
|
||||
@@ -98,6 +82,9 @@ func processApp(fold string) (out app) {
|
||||
if out.cat == "" {
|
||||
out.cat = "Other"
|
||||
}
|
||||
if portableHide {
|
||||
out.name = strings.TrimSuffix(out.name, "Portable")
|
||||
}
|
||||
out.icon = getIcon(fold)
|
||||
folder, _ := os.Open(fold)
|
||||
fis, _ := folder.Readdirnames(-1)
|
||||
@@ -138,6 +125,8 @@ func getCat(ini *os.File) string {
|
||||
if strings.HasPrefix(string(line), "Category=") {
|
||||
ret = strings.TrimPrefix(string(line), "Category=")
|
||||
break
|
||||
} else if strings.HasPrefix(string(line), "category=") {
|
||||
ret = strings.TrimPrefix(string(line), "category=")
|
||||
}
|
||||
}
|
||||
rdr.Reset(ini)
|
||||
@@ -151,15 +140,20 @@ func getName(ini *os.File) string {
|
||||
if strings.HasPrefix(string(line), "Name=") {
|
||||
ret = strings.TrimPrefix(string(line), "Name=")
|
||||
break
|
||||
} else 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 {
|
||||
func getIcon(fold string) *gdk.Pixbuf {
|
||||
var pic string
|
||||
if _, err := os.Open(fold + "/appicon.png"); err == nil {
|
||||
pic = fold + "/appicon.png"
|
||||
} else if folder, err := os.Open(fold + "/App/AppInfo"); err == nil {
|
||||
fis, _ := folder.Readdir(-1)
|
||||
var pics []string
|
||||
for _, v := range fis {
|
||||
@@ -175,24 +169,22 @@ 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 {
|
||||
return nil
|
||||
img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON)
|
||||
buf := img.GetPixbuf()
|
||||
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 {
|
||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
||||
return fi
|
||||
}
|
||||
tmp, err := os.Open(fold + "/App/AppInfo")
|
||||
if err == nil {
|
||||
fis, _ := tmp.Readdirnames(-1)
|
||||
@@ -203,8 +195,5 @@ func findInfo(fold string) *os.File {
|
||||
}
|
||||
}
|
||||
}
|
||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
||||
return fi
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,66 +1,188 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/nelsam/gxui"
|
||||
"github.com/CalebQ42/LinuxPA/appimg"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
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")
|
||||
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.SetTooltipText("Settings")
|
||||
dnl, _ := gtk.ButtonNewFromIconName("emblem-downloads", gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
dnl.SetTooltipText("Download Apps")
|
||||
header.PackStart(settings)
|
||||
header.PackEnd(dnl)
|
||||
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)
|
||||
appsList.SetHeadersVisible(false)
|
||||
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)
|
||||
catScrl.SetSizeRequest(170, 500)
|
||||
appScrl, _ := gtk.ScrolledWindowNew(hScrollApp, vScrollApp)
|
||||
appScrl.Add(appsList)
|
||||
appScrl.SetSizeRequest(300, 500)
|
||||
lrBox.Add(catScrl)
|
||||
lrBox.Add(appScrl)
|
||||
botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2)
|
||||
botBox.SetMarginStart(10)
|
||||
botBox.SetMarginEnd(10)
|
||||
botBox.SetMarginTop(10)
|
||||
botBox.SetMarginBottom(10)
|
||||
edit, _ := gtk.ButtonNewWithLabel("Edit App..")
|
||||
edit.Connect("clicked", func() {
|
||||
selec, _ := appsList.GetSelection()
|
||||
_, it, ok := selec.GetSelected()
|
||||
if ok {
|
||||
pth, _ := store.GetPath(it)
|
||||
ind := pth.GetIndices()
|
||||
if wine {
|
||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.edit(win, func() {
|
||||
store.Clear()
|
||||
for i := range ls {
|
||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||
}
|
||||
ls = getCatRows()
|
||||
for i, v := range ls {
|
||||
catList.Insert(v, i)
|
||||
}
|
||||
catList.ShowAll()
|
||||
})
|
||||
} else {
|
||||
catListAdap.SetStrings(lin)
|
||||
wineBut.SetText("Show Windows Apps")
|
||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.edit(win, func() {
|
||||
store.Clear()
|
||||
for i := range ls {
|
||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||
}
|
||||
ls = getCatRows()
|
||||
for i, v := range ls {
|
||||
catList.Insert(v, i)
|
||||
}
|
||||
catList.ShowAll()
|
||||
})
|
||||
}
|
||||
})
|
||||
_, 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)
|
||||
})
|
||||
botBox.PackEnd(edit, false, false, 0)
|
||||
topLvl.Add(lrBox)
|
||||
topLvl.PackEnd(botBox, false, true, 0)
|
||||
win.Add(topLvl)
|
||||
for _, v := range ls {
|
||||
catList.Add(v)
|
||||
}
|
||||
top.AddChild(butBox)
|
||||
top.AddChild(splBox)
|
||||
win.AddChild(top)
|
||||
win.OnClose(dr.Terminate)
|
||||
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 {
|
||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.launch()
|
||||
} else {
|
||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.launch()
|
||||
}
|
||||
} else if len(ind) == 2 {
|
||||
if wine {
|
||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.launchSub(ind[1])
|
||||
} else {
|
||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||
appLnch.launchSub(ind[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
dnl.Connect("clicked", func() {
|
||||
appimg.ShowUI(versionNewest, func() {
|
||||
master = make(map[string][]app)
|
||||
linmaster = make(map[string][]app)
|
||||
cats = make([]string, 0)
|
||||
lin = make([]string, 0)
|
||||
setup()
|
||||
store.Clear()
|
||||
for i := range ls {
|
||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||
}
|
||||
ls = getCatRows()
|
||||
for i, v := range ls {
|
||||
catList.Insert(v, i)
|
||||
}
|
||||
catList.ShowAll()
|
||||
})
|
||||
})
|
||||
settings.Connect("clicked", func() {
|
||||
settingsUI(win, func() {
|
||||
store.Clear()
|
||||
for i := range ls {
|
||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||
}
|
||||
ls = getCatRows()
|
||||
for i, v := range ls {
|
||||
catList.Insert(v, i)
|
||||
}
|
||||
catList.ShowAll()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func getCatRows() (out []*gtk.Label) {
|
||||
if wine {
|
||||
for _, v := range cats {
|
||||
txt, _ := gtk.LabelNew(v)
|
||||
out = append(out, txt)
|
||||
}
|
||||
} else {
|
||||
for _, v := range lin {
|
||||
txt, _ := gtk.LabelNew(v)
|
||||
out = append(out, txt)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,16 +2,22 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const (
|
||||
versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1"
|
||||
downloadURL = "https://github.com/CalebQ42/LinuxPA/releases/download/vXXX/LinuxPA"
|
||||
versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1"
|
||||
downloadURL = "https://github.com/CalebQ42/LinuxPA/releases/download/vXXX/LinuxPA"
|
||||
changelogURL = "https://www.dropbox.com/s/nmbk318er5kej5h/Changelog?dl=1"
|
||||
)
|
||||
|
||||
//Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
|
||||
@@ -51,6 +57,38 @@ func getVersionFileInfo() string {
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func changelogDL() (bool, error) {
|
||||
changelogFile, err := os.Create("PortableApps/LinuxPACom/Changelog")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
changelogFile.Chmod(0777)
|
||||
check := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
},
|
||||
}
|
||||
response, err := check.Get(changelogURL)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, err = io.Copy(changelogFile, response.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func getChangelog() string {
|
||||
fil, err := os.Open("PortableApps/LinuxPACom/Changelog")
|
||||
if err != nil {
|
||||
return "Error!"
|
||||
}
|
||||
out, _ := ioutil.ReadAll(fil)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func checkForUpdate(new string) (bool, error) {
|
||||
curSlice := strings.Split(version, ".")
|
||||
newSlice := strings.Split(new, ".")
|
||||
@@ -69,6 +107,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
|
||||
@@ -104,3 +144,102 @@ func downloadUpdate(newVersion string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func update(win *gtk.Window, forced bool) {
|
||||
stat, err := versionDL()
|
||||
if stat {
|
||||
res := getVersionFileInfo()
|
||||
if res != "Error!" {
|
||||
stat, err = checkForUpdate(res)
|
||||
if stat || forced {
|
||||
stat, err = changelogDL()
|
||||
if stat {
|
||||
updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
updateWin.SetTransientFor(win)
|
||||
updateWin.SetPosition(gtk.WIN_POS_CENTER)
|
||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
lbl, _ := gtk.LabelNew("There's a new update! Here's the changelog:")
|
||||
tagTbl, _ := gtk.TextTagTableNew()
|
||||
buf, _ := gtk.TextBufferNew(tagTbl)
|
||||
tv, _ := gtk.TextViewNewWithBuffer(buf)
|
||||
tv.SetEditable(false)
|
||||
buf.SetText(getChangelog())
|
||||
butBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||
upBut, _ := gtk.ButtonNewWithLabel("Update")
|
||||
upBut.Connect("clicked", func() {
|
||||
updateWin.Close()
|
||||
actuallyUpdate(win, forced)
|
||||
})
|
||||
cnlBut, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||
cnlBut.Connect("clicked", func() {
|
||||
updateWin.Close()
|
||||
})
|
||||
butBox.Add(upBut)
|
||||
butBox.Add(cnlBut)
|
||||
topLvl.Add(lbl)
|
||||
topLvl.Add(tv)
|
||||
topLvl.Add(butBox)
|
||||
topLvl.SetMarginBottom(10)
|
||||
topLvl.SetMarginEnd(10)
|
||||
topLvl.SetMarginStart(10)
|
||||
topLvl.SetMarginTop(10)
|
||||
updateWin.Add(topLvl)
|
||||
updateWin.ShowAll()
|
||||
updateWin.Show()
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Failed Version File Info")
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func actuallyUpdate(win *gtk.Window, forced bool) {
|
||||
updateWin, _ := gtk.WindowNew(gtk.WINDOW_POPUP)
|
||||
updateWin.SetTransientFor(win)
|
||||
updateWin.SetSizeRequest(150, 50)
|
||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
spin, _ := gtk.SpinnerNew()
|
||||
spin.Start()
|
||||
lbl, _ := gtk.LabelNew("Updating")
|
||||
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) {
|
||||
defer updateWin.Close()
|
||||
stat, err := versionDL()
|
||||
if stat {
|
||||
res := getVersionFileInfo()
|
||||
if res != "Error!" {
|
||||
stat, err = checkForUpdate(res)
|
||||
if stat || forced {
|
||||
downloadUpdate(res)
|
||||
win.Close()
|
||||
cmd := exec.Command("./LinuxPA")
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Start()
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Failed Version File Info")
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}(win, updateWin)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"github.com/mholt/archiver"
|
||||
)
|
||||
|
||||
@@ -12,31 +16,86 @@ const (
|
||||
wineURL = "https://www.playonlinux.com/wine/binaries/linux-amd64/PlayOnLinux-wine-2.5-linux-amd64.pol"
|
||||
)
|
||||
|
||||
func downloadWine() (bool, error) {
|
||||
wineTar, err := os.Create("PortableApps/LinuxPACom/wine2.5.tar.bz2")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
wineTar.Chmod(0777)
|
||||
defer wineTar.Close()
|
||||
check := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
},
|
||||
}
|
||||
resp, err := check.Get(wineURL)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
_, err = io.Copy(wineTar, resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = archiver.TarBz2.Open("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
func downloadWine(parent *gtk.Window, cb chan bool) {
|
||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||
win.SetTransientFor(parent)
|
||||
win.SetDestroyWithParent(true)
|
||||
win.Connect("destroy", func() {
|
||||
parent.SetSensitive(true)
|
||||
})
|
||||
parent.SetSensitive(false)
|
||||
spin, _ := gtk.SpinnerNew()
|
||||
spin.Start()
|
||||
txt, _ := gtk.LabelNew("Downloading Wine")
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||
box.SetMarginBottom(10)
|
||||
box.SetMarginEnd(10)
|
||||
box.SetMarginStart(10)
|
||||
box.SetMarginTop(10)
|
||||
box.Add(spin)
|
||||
box.Add(txt)
|
||||
win.Add(box)
|
||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
win.ShowAll()
|
||||
win.Show()
|
||||
go func(win *gtk.Window, txt *gtk.Label) {
|
||||
defer win.Close()
|
||||
wineTar, err := os.Create("PortableApps/LinuxPACom/wine2.5.tar.bz2")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
defer wineTar.Close()
|
||||
check := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
},
|
||||
}
|
||||
resp, err := check.Get(wineURL)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
os.RemoveAll("PortableApps/LinuxPACom/Wine")
|
||||
defer resp.Body.Close()
|
||||
_, err = io.Copy(wineTar, resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
txt.SetText("Extracting Wine")
|
||||
err = archiver.TarBz2.Open("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
fil, err := os.Open("PortableApps/LinuxPACom/common.sh")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
tmp, err := ioutil.ReadAll(fil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
if !strings.Contains(string(tmp), "export PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH") {
|
||||
tmp = append(tmp, []byte("\nexport PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH")...)
|
||||
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", tmp, 0777)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
cb <- false
|
||||
return
|
||||
}
|
||||
}
|
||||
cb <- true
|
||||
return
|
||||
}(win, txt)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user