14 Commits

Author SHA1 Message Date
Caleb Gardner 50105c242a EVEN MORE TESTING 2025-01-11 14:29:50 -06:00
Caleb Gardner 6e8d97f29b MORE MESSING AROUND 2025-01-11 13:16:58 -06:00
Caleb Gardner c8e0f08aae Started messing around with Raylib
Mainly just messing around
2025-01-11 06:35:32 -06:00
Caleb Gardner 916f9cc79b Update deps 2024-09-27 06:57:28 -05:00
Caleb Gardner e4e5adaf13 go mod tidy 2022-09-09 06:17:26 -05:00
Caleb Gardner 7a2ebd533e Update deps 2022-09-09 05:46:35 -05:00
Caleb Gardner 2f0ca5418c Updated readme and go version 2021-09-18 06:22:06 -05:00
Caleb Gardner ce9d4aed23 Fixed update download dialog 2020-11-28 03:52:10 -06:00
Caleb Gardner 712a5ab33d Removed stuff I don't need, now that I don't have a download UI 2020-11-28 03:33:50 -06:00
Caleb Gardner 6723f933b4 Forgot to up version number 2020-11-28 03:26:27 -06:00
Caleb Gardner 016fc35745 Download button now brings you to app image hub web page 2020-11-28 03:20:21 -06:00
Caleb Gardner ba5e3510ec some stuff for the future 2020-11-09 15:59:50 -06:00
Caleb Gardner 7e2d7ee14b Updated README 2020-11-09 15:30:14 -06:00
Caleb Gardner b20de4f1d6 Updated go.mod 2020-11-07 01:01:58 -06:00
23 changed files with 394 additions and 2096 deletions
+1
View File
@@ -0,0 +1 @@
testing/
+30 -18
View File
@@ -1,39 +1,51 @@
# 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.
# How to use ## 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 it finds. .sh script files have priority over other executable files. 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: ## Apps
The below place provides 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:
[https://appimage.github.io/](https://appimage.github.io/) [https://appimage.github.io/](https://appimage.github.io/)
# 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.
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998). My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
# 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). You can create and edit the common.sh from settings
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
# Simple App Setup
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. 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 Support
[AppImage Website](http://appimage.org)
Right now AppImages are simply supported via the native linux executable support, and you can download AppImages. (Woo) [AppImage Website](http://appimage.org)
I'm looking into improving AppImage support. As of 2.1.5.0 IF `unsquashfs` is in $PATH then some advanced AppImage support is available and it will automagically get the name and possibly the icon of it. I'm looking into better support, but it might be a while.
## USB mount
# 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` 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 ## Screenshots
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshots are with the adapta gtk theme Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshots are with the adapta gtk theme
# TODO (Might be in order) ## TODO (Might be in order)
1. MAKE IT BETTER  
1. Manual update check   1. MAKE IT BETTER
1. Better AppImage integrations (Specifically updating, getting information from the appimage, and better appimage downloading) 1. Integrate [goappimage](https://github.com/probonod/go-appimage) library for better AppImage integration.
1. Automagic appimage updating (It will of course ask you beforehand) 1. Try to `chmod +x` executables if they don't have the permission
1. Manual update check
1. Better AppImage integrations (Specifically updating and better appimage downloading)
1. Get information (such as name and icon) directly from an appimage 1. Get information (such as name and icon) directly from an appimage
1. Better appimage downloading (probably based around [AppImageHub](https://appimage.github.io/apps/)) 1. Better appimage downloading (probably based around [AppImageHub](https://appimage.github.io/apps/))
1. Sandboxing support 1. Sandboxing support
1. Check if all apps are closed when it closes and ask if you want to force stop the apps 1. Might be possible by packaging as an AppImage and providing Firejail, or simply just downloading it (like with Wine)
1. Check if all apps are closed when it closes and ask if you want to force stop the apps
-319
View File
@@ -1,319 +0,0 @@
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"strings"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
type app struct {
name string
cat string
appimg []string
lin []string
ex []string
icon *gdk.Pixbuf
dir string
ini *os.File
wine bool
}
func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter {
it := store.Append(nil)
scaled, _ := a.icon.ScaleSimple(32, 32, gdk.INTERP_HYPER)
store.SetValue(it, 0, scaled)
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 {
for _, v := range a.lin {
i := store.Append(it)
store.SetValue(i, 1, v)
}
}
}
return it
}
func (a *app) launch() {
if len(a.ex) == 1 {
if wine {
var cmd *exec.Cmd
if !contains(a.lin, a.ex[0]) {
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 {
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
cmd.Stderr = os.Stderr
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", "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
cmd.Stderr = os.Stderr
cmd.Start()
}
} else {
if wine {
var cmd *exec.Cmd
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.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", "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.dir+"\"; \"./"+a.lin[ind]+"\"")
}
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
} else {
if len(a.lin) != 0 {
var ind int
for i, v := range a.lin {
if strings.HasSuffix(v, ".sh") {
ind = i
break
}
}
var cmd *exec.Cmd
if 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", "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.dir+"\"; \"./"+a.lin[ind]+"\"")
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
}
}
}
}
func (a *app) launchSub(sub int) {
if wine {
var cmd *exec.Cmd
if !contains(a.lin, a.ex[sub]) {
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 {
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()
}
}
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)
})
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 == 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()
}
})
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)
nameShow := tmp.name
if tmp.wine {
nameShow = strings.TrimSuffix(nameShow, " (Wine)")
}
txtBuf.SetText(nameShow)
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
}
ini := "[General]\n"
ini += "Category=" + a.cat + "\n"
ini += "Name=" + a.name + "\n"
wrt := bufio.NewWriter(fil)
wrt.WriteString(ini)
wrt.Flush()
}
-60
View File
@@ -1,60 +0,0 @@
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
View File
@@ -1,115 +0,0 @@
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
}
}
}
-13
View File
@@ -1,13 +0,0 @@
package appimg
type appimg struct {
full string
name string
version string
}
func newApp(name string) appimg {
var out appimg
out.full = name
return out
}
-67
View File
@@ -1,67 +0,0 @@
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)
}
-144
View File
@@ -1,144 +0,0 @@
//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)
}
-12
View File
@@ -1,12 +0,0 @@
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
}
-33
View File
@@ -1,33 +0,0 @@
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
}
+6 -4
View File
@@ -1,9 +1,11 @@
module github.com/CalebQ42/LinuxPA module github.com/CalebQ42/LinuxPA
go 1.15 go 1.23.1
require github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b
require ( require (
github.com/CalebQ42/GoAppImage v0.1.1 github.com/ebitengine/purego v0.8.2 // indirect
github.com/gotk3/gotk3 v0.5.0 golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
github.com/mholt/archiver/v3 v3.5.0 golang.org/x/sys v0.29.0 // indirect
) )
+8 -135
View File
@@ -1,135 +1,8 @@
github.com/adrg/xdg v0.2.2 h1:A7ZHKRz5KGOLJX/bg7IPzStryhvCzAE1wX+KWawPiAo= github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
github.com/adrg/xdg v0.2.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b h1:JJfspevP3YOXcSKVABizYOv++yMpTJIdPUtoDzF/RWw=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
github.com/alokmenghrajani/gpgeez v0.0.0-20161206084504-1a06f1c582f9 h1:Zio/mdDEpJDG1yeH9y2Kcb9ATWXkE7WIBkO+IMqRbbM= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
github.com/alokmenghrajani/gpgeez v0.0.0-20161206084504-1a06f1c582f9/go.mod h1:u65XFfs2+s//7QVkp5Q1NEZl4zVep2BtubxiSXJERN8= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gotk3/gotk3 v0.5.0 h1:GOkq4cFgAfeK6YAukLi64bz8zPayZKeCSSRr4mcFReQ=
github.com/gotk3/gotk3 v0.5.0/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE=
github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pierrec/lz4/v4 v4.0.3 h1:vNQKSVZNYUEAvRY9FaUXAF1XPbSOHJtDTiP41kzDz2E=
github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4=
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+260
View File
@@ -0,0 +1,260 @@
package ui
import (
"image/color"
"time"
rl "github.com/gen2brain/raylib-go/raylib"
)
// A rectangle with borders.
// Default only has black borders.
type Rect struct {
x int32
y int32
h int32
w int32
radius int32
reload bool
shown bool
rendering bool
borderWidth int32
borderColor color.RGBA
fillColor color.RGBA
curTweens map[string]*Tween
tex rl.RenderTexture2D
}
func NewRect(x, y, height, width int32) *Rect {
r := &Rect{
x: x,
y: y,
h: height,
w: width,
radius: 0,
borderWidth: 2,
borderColor: rl.Black,
fillColor: rl.Blank,
reload: true,
curTweens: make(map[string]*Tween),
}
r.tex = rl.LoadRenderTexture(width, height)
rl.SetTextureFilter(r.tex.Texture, rl.FilterAnisotropic8x|rl.FilterBilinear)
return r
}
func (r *Rect) Copy() *Rect {
return &Rect{
x: r.x,
y: r.y,
h: r.h,
w: r.w,
radius: r.radius,
borderWidth: r.borderWidth,
borderColor: r.borderColor,
fillColor: r.fillColor,
}
}
func (r *Rect) addTween(key string, old, new int32) {
r.curTweens[key] = NewTween(old, new, 1000*time.Millisecond)
}
func (r *Rect) SetPosition(x, y int32) {
if !r.shown {
r.x, r.y = x, y
return
}
if r.x != x {
r.addTween("x", r.x, x)
}
if r.y != y {
r.addTween("y", r.y, y)
}
}
func (r *Rect) SetSize(h, w int32) {
if !r.shown {
r.h, r.w = h, w
return
}
if r.h != h {
r.addTween("h", r.h, h)
r.reload = true
}
if r.w != w {
r.addTween("w", r.w, w)
r.reload = true
}
}
func (r *Rect) SetBorderRadius(radius int32) {
if !r.shown {
r.radius = radius
return
}
if r.radius != radius {
r.addTween("radius", r.radius, radius)
r.reload = true
}
}
func (r *Rect) SetBorderWidth(w int32) {
if !r.shown {
r.borderWidth = w
return
}
if r.borderWidth != w {
r.addTween("borderWidth", r.borderWidth, w)
r.reload = true
}
}
func (r *Rect) SetBorderColor(c color.RGBA) {
if r.borderColor != c {
r.reload = true
}
r.borderColor = c
}
func (r *Rect) SetFillColor(c color.RGBA) {
if r.fillColor != c {
r.reload = true
}
r.fillColor = c
}
func (r *Rect) Draw() {
r.shown = true
if !r.reload && len(r.curTweens) == 0 {
rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(r.x), float32(r.y)), 0, 1, rl.White)
return
}
var curRect *Rect
updateTex := false
if len(r.curTweens) != 0 {
curRect = r.Copy()
tween, ok := r.curTweens["x"]
if ok {
curRect.x = tween.CurVal()
if tween.Ended() {
r.x = curRect.x
delete(r.curTweens, "x")
}
}
tween, ok = r.curTweens["y"]
if ok {
curRect.y = tween.CurVal()
if tween.Ended() {
r.y = curRect.y
delete(r.curTweens, "y")
}
}
tween, ok = r.curTweens["h"]
if ok {
curRect.h = tween.CurVal()
if curRect.h != r.h {
updateTex = true
}
if tween.Ended() {
r.h = curRect.h
delete(r.curTweens, "h")
}
}
tween, ok = r.curTweens["w"]
if ok {
curRect.w = tween.CurVal()
if curRect.w != r.w {
updateTex = true
}
if tween.Ended() {
r.w = curRect.w
delete(r.curTweens, "w")
}
}
tween, ok = r.curTweens["radius"]
if ok {
curRect.radius = tween.CurVal()
if curRect.radius != r.radius {
updateTex = true
}
if tween.Ended() {
r.radius = curRect.radius
delete(r.curTweens, "radius")
}
}
tween, ok = r.curTweens["borderWidth"]
if ok {
curRect.borderWidth = tween.CurVal()
if curRect.borderWidth != r.borderWidth {
updateTex = true
}
if tween.Ended() {
r.borderWidth = curRect.borderWidth
delete(r.curTweens, "borderWidth")
}
}
} else {
curRect = r
}
if r.reload || updateTex {
// rl.UnloadTexture(r.tex)
// r.tex = rl.LoadTextureFromImage(curRect.buildImage())
// rl.UpdateTexture(r.tex, rl.LoadImageColors(curRect.buildImage()))
rl.BeginTextureMode(r.tex)
curRect.drawTexture()
rl.EndTextureMode()
}
rl.DrawTexturePro(r.tex.Texture, rl.NewRectangle(0, 0, float32(curRect.w), float32(curRect.h)), rl.NewRectangle(float32(curRect.x), float32(curRect.y), float32(curRect.w), float32(curRect.h)), rl.NewVector2(0, 0), 0, rl.White)
// rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(curRect.x), float32(curRect.y)), 0, 1, rl.White)
r.reload = false
}
func (r Rect) drawTexture() {
rl.ClearBackground(rl.Blank)
// Filled areas
if r.fillColor != rl.Blank {
rl.DrawRectangle(r.radius, 0, (r.w - (2 * r.radius)), r.h, r.fillColor)
if r.radius > 0 {
rl.DrawRectangle((r.w - r.radius), r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
rl.DrawRectangle(0, r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
}
}
if r.borderColor != rl.Blank {
// Horizontal lines
rl.DrawRectangle(r.radius, 0, (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
rl.DrawRectangle(r.radius, (r.h)-(r.borderWidth), (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
// Vertical lines
rl.DrawRectangle(0, r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
rl.DrawRectangle((r.w)-(r.borderWidth), r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
}
if r.radius > 0 {
r.placeCorners()
}
}
func (r Rect) placeCorners() {
//bl
if r.borderWidth > 0 {
rl.DrawRing(rl.NewVector2(float32(r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 180, 270, 20, r.borderColor)
}
rl.DrawCircleSector(rl.NewVector2(float32(r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), 180, 270, 20, r.fillColor)
//tl
if r.borderWidth > 0 {
rl.DrawRing(rl.NewVector2(float32(r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 90, 180, 20, r.borderColor)
}
rl.DrawCircleSector(rl.NewVector2(float32(r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), 90, 180, 20, r.fillColor)
//tr
if r.borderWidth > 0 {
rl.DrawRing(rl.NewVector2(float32(r.w-r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 0, 90, 20, r.borderColor)
}
rl.DrawCircleSector(rl.NewVector2(float32(r.w-r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), 0, 90, 20, r.fillColor)
//br
if r.borderWidth > 0 {
rl.DrawRing(rl.NewVector2(float32(r.w-r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 270, 360, 20, r.borderColor)
}
rl.DrawCircleSector(rl.NewVector2(float32(r.w-r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), 270, 360, 20, r.fillColor)
}
+48
View File
@@ -0,0 +1,48 @@
package ui
import (
"time"
rl "github.com/gen2brain/raylib-go/raylib"
)
type Window struct{}
func Test() {
rl.SetConfigFlags(rl.FlagWindowResizable | rl.FlagWindowHighdpi | rl.FlagVsyncHint | rl.FlagMsaa4xHint)
rl.InitWindow(800, 450, "raylib [core] example - basic window")
defer rl.CloseWindow()
rl.SetTargetFPS(60)
noto := rl.LoadFont("./noto-sans.ttf")
txtImg := rl.ImageTextEx(noto, "Hello World!", 50, 0, rl.Black)
txt := rl.LoadTextureFromImage(txtImg)
tmpRect := NewRect(10, 10, 250, 500)
tmpRect.SetBorderRadius(25)
go func() {
for {
time.Sleep(5 * time.Second)
// tmpRect.SetBorderRadius(0)
// tmpRect.SetPosition(100, 100)
tmpRect.SetSize(400, 700)
time.Sleep(5 * time.Second)
// tmpRect.SetBorderRadius(25)
// tmpRect.SetPosition(10, 10)
tmpRect.SetSize(250, 500)
}
}()
// tmpRect.SetFillColor(rl.Green)
for !rl.WindowShouldClose() {
rl.BeginDrawing()
rl.DrawFPS(0, 0)
rl.ClearBackground(rl.DarkGray)
// rl.DrawText("Congrats! You created your first window!", 190, 100, 20, rl.LightGray)
// // rl.DrawTextEx(noto, "Congrats! You created your first window!", rl.NewVector2(190, 200), 48, 0, rl.Black)
tmpRect.Draw()
rl.DrawTexture(txt, 50, 50, rl.Black)
rl.EndDrawing()
}
}
+39
View File
@@ -0,0 +1,39 @@
package ui
import (
"math"
"time"
)
type Tween struct {
startVal int32
startTime time.Time
dif int32
dur time.Duration
}
func NewTween(startVal, endVal int32, duration time.Duration) *Tween {
return &Tween{
startVal: startVal,
dif: endVal - startVal,
dur: duration,
startTime: time.Now().Round(time.Millisecond),
}
}
func (t *Tween) CurVal() int32 {
since := time.Now().Round(time.Millisecond).Sub(t.startTime)
if since <= 0 {
return t.startVal
}
if since >= t.dur {
return t.startVal + t.dif
}
m := float32(since.Milliseconds()) / float32(t.dur.Milliseconds())
m = -1 * float32(math.Log10(-.9*float64(m)+1))
return t.startVal + int32(math.Round(float64(float32(t.dif)*m)))
}
func (t *Tween) Ended() bool {
return time.Now().Round(time.Millisecond).Sub(t.startTime) >= t.dur
}
+2 -56
View File
@@ -1,61 +1,7 @@
package main package main
import ( import "github.com/CalebQ42/LinuxPA/internal/ui"
"flag"
"fmt"
"os"
"github.com/gotk3/gotk3/gtk"
)
const (
version = "2.1.5.0"
)
var (
master map[string][]app
linmaster map[string][]app
cats []string
lin []string
comEnbld bool
populated bool
)
func main() { func main() {
forced := flag.Bool("force-update", false, "Force the update dialog to be shown") ui.Test()
flag.Parse()
os.MkdirAll("PortableApps/LinuxPACom", 0777)
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)
}
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 contains(arr []string, str string) bool {
for _, v := range arr {
if v == str {
return true
}
}
return false
} }
BIN
View File
Binary file not shown.
-72
View File
@@ -1,72 +0,0 @@
package main
import (
"encoding/gob"
"os"
)
var (
wine bool
wineAvail bool
portableHide bool
betaUpdate bool
versionNewest = true
paDirs = true
)
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
}
err = enc.Encode(betaUpdate)
if err != nil {
return
}
}
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
}
err = dec.Decode(&betaUpdate)
if err != nil {
return
}
}
-206
View File
@@ -1,206 +0,0 @@
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() {
savePrefs()
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()
})
betaCheck, _ := gtk.CheckButtonNewWithLabel("Update to beta releases")
gnrl.Add(wineLbl)
gnrl.Add(dlWine)
gnrl.Add(pthdCheck)
gnrl.Add(wineCheck)
gnrl.Add(versCheck)
gnrl.Add(paDirsCheck)
gnrl.Add(betaCheck)
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
}
-291
View File
@@ -1,291 +0,0 @@
package main
import (
"bufio"
_ "image/png"
"os"
"os/exec"
"reflect"
"sort"
"strings"
goappimage "github.com/CalebQ42/GoAppImage"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
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)
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)
}
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
if err == nil {
comEnbld = true
}
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)
}
}
}
}
populated = true
}
func processApp(fold string) (out app) {
wd, _ := os.Getwd()
out.dir = wd + "/" + 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)"
out.wine = true
}
out.icon = getIcon(fold)
out.ini = findInfo(fold)
if out.ini != nil {
out.name = getName(out.ini)
out.cat = getCat(out.ini)
}
if len(out.appimg) > 0 && out.name == "" && out.cat == "" && out.icon == nil {
os.Mkdir(out.dir+"/.appimageconfig", 0777)
ai := goappimage.NewAppImage(out.dir + "/" + out.appimg[0])
fil, err := os.Open(out.dir + "/.appimageconfig/the.md5")
if os.IsNotExist(err) {
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
appdirs, _ := appimageconfig.Readdirnames(-1)
for _, dirs := range appdirs {
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
break
}
}
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
name, cat, icon := extractDesktopInfo(desk)
if out.name == "" {
out.name = name
}
if out.cat == "" {
out.cat = cat
}
if out.icon == nil {
it, _ := gtk.IconThemeGetDefault()
out.icon, err = it.LoadIcon(icon, 64, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
}
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
wrtr := bufio.NewWriter(fil)
wrtr.WriteString(ai.Md5)
wrtr.Flush()
} else {
rdr := bufio.NewReader(fil)
filMd, _, _ := rdr.ReadLine()
oldMd := string(filMd)
if oldMd != ai.Md5 {
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
appdirs, _ := appimageconfig.Readdirnames(-1)
for _, dirs := range appdirs {
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
break
}
}
os.Remove(out.dir + "/.appimageconfig/the.md5")
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
wrtr := bufio.NewWriter(fil)
wrtr.WriteString(ai.Md5)
wrtr.Flush()
}
}
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
name, cat, icon := extractDesktopInfo(desk)
if out.name == "" {
out.name = name
}
if out.cat == "" {
out.cat = cat
}
if out.icon == nil {
it, _ := gtk.IconThemeGetDefault()
out.icon, err = it.LoadIcon(icon, 32, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
}
}
if out.name == "" {
out.name = strings.TrimPrefix(fold, "PortableApps/")
}
if out.cat == "" {
out.cat = "Other"
}
if portableHide {
out.name = strings.TrimSuffix(out.name, "Portable")
}
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
} else if strings.HasPrefix(string(line), "category=") {
ret = strings.TrimPrefix(string(line), "category=")
}
}
rdr.Reset(ini)
return ret
}
func extractDesktopInfo(desk *os.File) (name, category, iconName string) {
rdr := bufio.NewReader(desk)
var nameGot, catGot, iconGot bool
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
ln := string(line)
if !nameGot && strings.HasPrefix(ln, "Name=") {
name = strings.TrimPrefix(ln, "Name=")
nameGot = true
} else if !catGot && strings.HasPrefix(ln, "Categories=") {
cats := strings.Split(strings.TrimPrefix(ln, "Categories="), ";")
if len(cats) > 0 {
category = cats[0]
}
catGot = true
} else if !iconGot && strings.HasPrefix(ln, "Icon=") {
iconName = strings.TrimPrefix(ln, "Icon=")
iconGot = true
}
if nameGot && catGot && iconGot {
break
}
}
return
}
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
} else if strings.HasPrefix(string(line), "name=") {
ret = strings.TrimPrefix(string(line), "name=")
break
}
}
rdr.Reset(ini)
return ret
}
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 {
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 = fold + "/App/AppInfo/" + pics[ind]
}
} else {
img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON)
buf := img.GetPixbuf()
return buf
}
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)
for _, v := range fis {
if strings.ToLower(v) == "appinfo.ini" {
tmp, _ := os.Open(fold + "/App/AppInfo/" + v)
return tmp
}
}
}
return nil
}
-188
View File
@@ -1,188 +0,0 @@
package main
import (
"github.com/CalebQ42/LinuxPA/appimg"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
func ui(win *gtk.Window) {
ls := getCatRows()
var treeApps []*gtk.TreeIter
header, _ := gtk.HeaderBarNew()
header.SetShowCloseButton(true)
header.SetTitle("LinuxPA")
header.SetSubtitle("PortableApps.com type launcher")
settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR)
settings.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 {
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()
})
}
}
})
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)
}
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
}
-262
View File
@@ -1,262 +0,0 @@
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"
changelogURL = "https://www.dropbox.com/s/nmbk318er5kej5h/Changelog?dl=1"
changelogBetaURL = "https://www.dropbox.com/s/m8mo2o3nsvfqbfx/ChangelogBeta?dl=1"
)
//Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
//For some of the code
//Returns if success
func versionDL() (bool, error) {
versionFile, err := os.Create("PortableApps/LinuxPACom/Version")
if err != nil {
return false, err
}
versionFile.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(versionURL)
if err != nil {
return false, err
}
_, err = io.Copy(versionFile, response.Body)
if err != nil {
return false, err
}
return true, nil
}
func getVersionFileInfo() (stable string, beta string) {
fil, err := os.Open("PortableApps/LinuxPACom/Version")
if err != nil {
return "Error!", ""
}
rdr := bufio.NewReader(fil)
out, _, _ := rdr.ReadLine()
stable = string(out)
out, _, _ = rdr.ReadLine()
beta = string(out)
return
}
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
},
}
var response *http.Response
if betaUpdate {
response, err = check.Get(changelogBetaURL)
} else {
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(stable, beta string) (bool, error) {
new := stable
if betaUpdate {
new = beta
}
curSlice := strings.Split(version, ".")
newSlice := strings.Split(new, ".")
curNums := make([]int, 4)
newNums := make([]int, 4)
for i, v := range curSlice {
num, err := strconv.Atoi(v)
if err == nil {
curNums[i] = num
}
num, err = strconv.Atoi(newSlice[i])
if err == nil {
newNums[i] = num
} else {
return false, err
}
if newNums[i] > curNums[i] {
return true, nil
} else if curNums[i] > newNums[i] {
return false, nil
}
}
return false, nil
}
func downloadUpdate(newVersion string) (bool, error) {
url := strings.Replace(downloadURL, "XXX", newVersion, -1)
err := os.Rename("LinuxPA", ".LinuxPA.old")
if err != nil {
return false, err
}
fil, err := os.Create("LinuxPA")
fil.Chmod(0777)
defer fil.Close()
if err != nil {
os.Rename(".LinuxPA.old", "LinuxPA")
return false, err
}
check := http.Client{
CheckRedirect: func(r *http.Request, via []*http.Request) error {
r.URL.Opaque = r.URL.Path
return nil
},
}
re, err := check.Get(url)
if err != nil {
return false, err
}
defer re.Body.Close()
_, err = io.Copy(fil, re.Body)
if err != nil {
return false, err
}
return true, nil
}
func update(win *gtk.Window, forced bool) {
stat, err := versionDL()
if stat {
stable, beta := getVersionFileInfo()
if stable != "Error!" {
stat, err = checkForUpdate(stable, beta)
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 {
stable, beta := getVersionFileInfo()
if stable != "Error!" {
stat, err = checkForUpdate(stable, beta)
if stat || forced {
if betaUpdate {
downloadUpdate(beta)
} else {
downloadUpdate(stable)
}
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)
}
-101
View File
@@ -1,101 +0,0 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/gotk3/gotk3/gtk"
"github.com/mholt/archiver/v3"
)
const (
wineURL = "https://www.playonlinux.com/wine/binaries/phoenicis/staging-linux-amd64/PlayOnLinux-wine-5.20-staging-linux-amd64.tar.gz"
)
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/wine5.20.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.DefaultTarBz2.Unarchive("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)
}