11 Commits

Author SHA1 Message Date
Belac Darkstorm 868ae8f700 Update README.md 2018-01-01 16:21:45 -06:00
Caleb Gardner 226e9d6210 Changed $PANAME to $FILENAME
Added $APPNAME
Fixed a couple bugs
2017-08-10 19:05:54 -05:00
Belac Darkstorm 56748f043e Added stuff for appimages.
Shows changelog before updating.
2017-08-09 03:36:35 -05:00
Belac Darkstorm 3d3239fe0a Updated README 2017-08-08 12:39:41 -05:00
Belac Darkstorm 6e643b68ac Update README.md 2017-08-08 07:02:09 -05:00
Belac Darkstorm 539f33d25e Updated README 2017-04-18 09:21:30 -05:00
Belac Darkstorm 4d3cb9f486 updated 2017-04-14 04:07:55 -05:00
Belac Darkstorm a55c82483a Better download list parsing 2017-04-14 03:36:50 -05:00
Belac Darkstorm 9e9bb82025 Moved "Show windows apps" to settings
Added "Hide Portable from app names"
2017-04-14 01:56:36 -05:00
Belac Darkstorm ea91d3cd80 Bumping version number 2017-04-11 00:18:23 -05:00
Belac Darkstorm 2a0d53db09 Edit and some bugs 2017-04-11 00:18:00 -05:00
16 changed files with 604 additions and 107 deletions
+10 -10
View File
@@ -2,10 +2,10 @@
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 (.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: # 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) [AppImage](https://bintray.com/probono/AppImages)
# PortableApps.com Compatibility # PortableApps.com Compatibility
@@ -13,23 +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). 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). 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, 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 Support
[AppImage Website](http://appimage.org) [AppImage Website](http://appimage.org)
Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic updating support later on. Right now AppImages are simply supported via the native linux executable support, and you can download AppImages. (Woo)
# 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) 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. MAKE IT BETTER  
1. Add updater for .AppImage files 1. Manual update check  
1. Download .AppImage files (maybe) 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. Check if all apps are closed when it closes and ask if you want to force stop the apps
+169 -9
View File
@@ -1,6 +1,8 @@
package main package main
import ( import (
"bufio"
"fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
@@ -23,7 +25,11 @@ type app struct {
func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter { func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter {
it := store.Append(nil) it := store.Append(nil)
store.SetValue(it, 0, a.icon) store.SetValue(it, 0, a.icon)
if portableHide {
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
} else {
store.SetValue(it, 1, a.name) store.SetValue(it, 1, a.name)
}
if len(a.ex) > 1 { if len(a.ex) > 1 {
if wine { if wine {
for _, v := range a.ex { for _, v := range a.ex {
@@ -46,13 +52,17 @@ func (a *app) launch() {
var cmd *exec.Cmd var cmd *exec.Cmd
if !contains(a.lin, a.ex[0]) { if !contains(a.lin, a.ex[0]) {
if comEnbld { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
} }
} else { } 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
} }
@@ -62,8 +72,12 @@ func (a *app) launch() {
cmd.Start() cmd.Start()
} else { } else {
var cmd *exec.Cmd 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
} }
@@ -76,7 +90,7 @@ func (a *app) launch() {
var cmd *exec.Cmd var cmd *exec.Cmd
if len(a.lin) == 0 { if len(a.lin) == 0 {
if comEnbld { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
} }
@@ -88,8 +102,12 @@ func (a *app) launch() {
break 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
} }
@@ -107,8 +125,12 @@ func (a *app) launch() {
} }
} }
var cmd *exec.Cmd 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
} }
@@ -125,13 +147,17 @@ func (a *app) launchSub(sub int) {
var cmd *exec.Cmd var cmd *exec.Cmd
if !contains(a.lin, a.ex[sub]) { if !contains(a.lin, a.ex[sub]) {
if comEnbld { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"") 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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
} }
} else { } 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") 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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
} }
@@ -141,8 +167,12 @@ func (a *app) launchSub(sub int) {
cmd.Start() cmd.Start()
} else { } else {
var cmd *exec.Cmd 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 { if comEnbld {
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") 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 { } else {
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"") cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
} }
@@ -151,3 +181,133 @@ func (a *app) launchSub(sub int) {
cmd.Start() 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 == 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()
}
})
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
}
ini := "[General]\n"
ini += "Category=" + a.cat + "\n"
ini += "Name=" + a.name + "\n"
wrt := bufio.NewWriter(fil)
wrt.WriteString(ini)
wrt.Flush()
}
+3 -1
View File
@@ -1,11 +1,13 @@
package appimg package appimg
type appimg struct { type appimg struct {
full string
name string name string
version string
} }
func newApp(name string) appimg { func newApp(name string) appimg {
var out appimg var out appimg
out.name = name out.full = name
return out return out
} }
+8 -7
View File
@@ -19,7 +19,7 @@ func downloadApp(parent *gtk.Window, ap appimg) {
}) })
spn, _ := gtk.SpinnerNew() spn, _ := gtk.SpinnerNew()
spn.Start() spn.Start()
lbl, _ := gtk.LabelNew("Downloading " + ap.name + "...") lbl, _ := gtk.LabelNew("Downloading " + ap.full + "...")
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
box.SetMarginStart(10) box.SetMarginStart(10)
box.SetMarginEnd(10) box.SetMarginEnd(10)
@@ -39,28 +39,29 @@ func downloadApp(parent *gtk.Window, ap appimg) {
return nil return nil
}, },
} }
resp, err := check.Get(urlBase + ap.name) resp, err := check.Get(urlBase + ap.full)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
defer resp.Body.Close() defer resp.Body.Close()
name := strings.Split(ap.name, "-")[0] name := strings.Split(ap.full, "-")[0]
var foldName string var foldName string
if _, err = os.Open("PortableApps/" + name + "Portable"); err == nil { if _, err = os.Open("PortableApps/" + name + "Portable"); err == nil {
foldName = "PortableApps/" + name + "Portable" foldName = "PortableApps/" + name + "Portable"
} else if _, err = os.Open("PortableApps/" + name); err == nil { } else if _, err = os.Open("PortableApps/" + name); err == nil {
foldName = "PortableApps/" + name foldName = "PortableApps/" + name
} else { } else {
os.Mkdir("PortableApps/"+name, 0777) os.Mkdir("PortableApps/"+name+"Portable", 0777)
foldName = "PortableApps/" + name foldName = "PortableApps/" + name + "Portable"
} }
fil, err := os.Create(foldName + "/" + ap.name) os.Remove(foldName + "/" + ap.full)
fil, err := os.Create(foldName + "/" + ap.full)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
io.Copy(fil, resp.Body) io.Copy(fil, resp.Body)
_ = fil.Chmod(0777) fil.Chmod(0777)
}(win, ap) }(win, ap)
} }
+34 -2
View File
@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"sort"
"strings" "strings"
"github.com/gotk3/gotk3/glib" "github.com/gotk3/gotk3/glib"
@@ -16,7 +17,7 @@ const (
) )
//ShowUI shows the list of possible AppImages to be downloaded in a gtk.Window //ShowUI shows the list of possible AppImages to be downloaded in a gtk.Window
func ShowUI(clsFunc func()) { func ShowUI(newestVersionOnly bool, clsFunc func()) {
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
win.Connect("destroy", func() { win.Connect("destroy", func() {
clsFunc() clsFunc()
@@ -45,14 +46,45 @@ func ShowUI(clsFunc func()) {
win.Show() win.Show()
getList(win, apch) getList(win, apch)
go func(win *gtk.Window, apch chan appimg, list *gtk.ListBox) { 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 { for i := range apch {
glib.IdleAdd(func(list *gtk.ListBox, i appimg) { glib.IdleAdd(func(list *gtk.ListBox, i appimg) {
lbl, _ := gtk.LabelNew(i.name) lbl, _ := gtk.LabelNew(i.full)
list.Add(lbl) list.Add(lbl)
apps = append(apps, i) apps = append(apps, i)
lbl.Show() lbl.Show()
}, list, i) }, list, i)
} }
}
}(win, apch, appList) }(win, apch, appList)
} }
+12
View File
@@ -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
}
+33
View File
@@ -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
}
View File
+44 -13
View File
@@ -2,16 +2,15 @@ package main
import ( import (
"encoding/gob" "encoding/gob"
"flag"
"fmt" "fmt"
"os" "os"
"runtime"
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
) )
const ( const (
version = "2.0.1.0" version = "2.1.2.1"
defIni = ""
) )
var ( var (
@@ -22,17 +21,21 @@ var (
wine bool wine bool
comEnbld bool comEnbld bool
wineAvail bool wineAvail bool
portableHide bool
versionNewest = true
paDirs = true
) )
func main() { func main() {
runtime.GOMAXPROCS(4) forced := flag.Bool("force-update", false, "Force the update dialog to be shown")
flag.Parse()
os.MkdirAll("PortableApps/LinuxPACom", 0777) os.MkdirAll("PortableApps/LinuxPACom", 0777)
master = make(map[string][]app) master = make(map[string][]app)
linmaster = make(map[string][]app) linmaster = make(map[string][]app)
uiStart() uiStart(*forced)
} }
func uiStart() { func uiStart(forced bool) {
gtk.Init(nil) gtk.Init(nil)
setup() setup()
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
@@ -49,20 +52,33 @@ func uiStart() {
ui(win) ui(win)
win.ShowAll() win.ShowAll()
win.Show() win.Show()
update(win) update(win, forced)
gtk.Main() gtk.Main()
} }
func savePrefs() { func savePrefs() {
fil, err := os.Open("PortableApps/LinuxPACom/Prefs.gob") os.Remove("PortableApps/LinuxPACom/Prefs.gob")
if os.IsNotExist(err) { fil, err := os.Create("PortableApps/LinuxPACom/Prefs.gob")
fil, err = os.Create("PortableApps/LinuxPACom/Prefs.gob")
}
if err != nil { if err != nil {
return return
} }
enc := gob.NewEncoder(fil) enc := gob.NewEncoder(fil)
enc.Encode(wine) 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 loadPrefs() { func loadPrefs() {
@@ -71,7 +87,22 @@ func loadPrefs() {
return return
} }
dec := gob.NewDecoder(fil) dec := gob.NewDecoder(fil)
dec.Decode(&wine) 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
}
} }
func contains(arr []string, str string) bool { func contains(arr []string, str string) bool {
+99 -4
View File
@@ -3,14 +3,26 @@ package main
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
) )
func settingsUI() { 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, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
win.SetTransientFor(parent)
parent.SetSensitive(false)
win.SetDefaultSize(600, 300) win.SetDefaultSize(600, 300)
win.SetPosition(gtk.WIN_POS_CENTER) win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
win.Connect("destroy", func() {
parent.SetSensitive(true)
onExit()
})
comTagTbl, _ := gtk.TextTagTableNew() comTagTbl, _ := gtk.TextTagTableNew()
comBuf, _ := gtk.TextBufferNew(comTagTbl) comBuf, _ := gtk.TextBufferNew(comTagTbl)
ntbk, _ := gtk.NotebookNew() ntbk, _ := gtk.NotebookNew()
@@ -20,8 +32,8 @@ func settingsUI() {
gnrl.SetMarginTop(10) gnrl.SetMarginTop(10)
gnrl.SetMarginBottom(10) gnrl.SetMarginBottom(10)
dlWine, _ := gtk.ButtonNewWithLabel("Download Wine") dlWine, _ := gtk.ButtonNewWithLabel("Download Wine")
wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)")
wineLbl, _ := gtk.LabelNew("PortableApps/LinuxPACom/Wine present") wineLbl, _ := gtk.LabelNew("PortableApps/LinuxPACom/Wine present")
gnrl.Add(wineLbl)
dlWine.Connect("clicked", func() { dlWine.Connect("clicked", func() {
cb := make(chan bool) cb := make(chan bool)
downloadWine(win, cb) downloadWine(win, cb)
@@ -31,13 +43,62 @@ func settingsUI() {
setupTxt(comBuf) setupTxt(comBuf)
wineLbl.Show() 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 { if !comEnbld {
dlWine.SetSensitive(false) dlWine.SetSensitive(false)
dlWine.SetTooltipText("common.sh needed") 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(dlWine)
gnrl.Add(pthdCheck)
gnrl.Add(wineCheck)
gnrl.Add(versCheck)
gnrl.Add(paDirsCheck)
ntbk.AppendPage(gnrl, getLabel("General")) ntbk.AppendPage(gnrl, getLabel("General"))
com, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) com, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
com.SetMarginStart(10) com.SetMarginStart(10)
@@ -51,7 +112,6 @@ func settingsUI() {
hScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0) hScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
comScrl, _ := gtk.ScrolledWindowNew(hScroll, vScroll) comScrl, _ := gtk.ScrolledWindowNew(hScroll, vScroll)
comScrl.Add(comEdit) comScrl.Add(comEdit)
com.Add(comScrl)
svBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5) svBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
sv, _ := gtk.ButtonNewWithLabel("Save") sv, _ := gtk.ButtonNewWithLabel("Save")
sv.Connect("clicked", func() { sv.Connect("clicked", func() {
@@ -63,8 +123,26 @@ func settingsUI() {
cnl.Connect("clicked", func() { cnl.Connect("clicked", func() {
setupTxt(comBuf) 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(sv)
svBox.Add(cnl) svBox.Add(cnl)
svBox.Add(info)
com.Add(comScrl)
com.Add(svBox) com.Add(svBox)
ntbk.AppendPage(com, getLabel("common.sh")) ntbk.AppendPage(com, getLabel("common.sh"))
win.Add(ntbk) win.Add(ntbk)
@@ -85,8 +163,25 @@ func settingsUI() {
dlWine.SetTooltipText("") 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() mkCom.Show()
com.Add(mkCom) com.Add(mkCom)
com.Add(in)
} else { } else {
setupTxt(comBuf) setupTxt(comBuf)
} }
+9 -6
View File
@@ -82,6 +82,9 @@ func processApp(fold string) (out app) {
if out.cat == "" { if out.cat == "" {
out.cat = "Other" out.cat = "Other"
} }
if portableHide {
out.name = strings.TrimSuffix(out.name, "Portable")
}
out.icon = getIcon(fold) out.icon = getIcon(fold)
folder, _ := os.Open(fold) folder, _ := os.Open(fold)
fis, _ := folder.Readdirnames(-1) fis, _ := folder.Readdirnames(-1)
@@ -148,7 +151,9 @@ func getName(ini *os.File) string {
func getIcon(fold string) *gdk.Pixbuf { func getIcon(fold string) *gdk.Pixbuf {
var pic string var pic string
if folder, err := os.Open(fold + "/App/AppInfo"); err == nil { 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) fis, _ := folder.Readdir(-1)
var pics []string var pics []string
for _, v := range fis { for _, v := range fis {
@@ -166,8 +171,6 @@ func getIcon(fold string) *gdk.Pixbuf {
} }
pic = fold + "/App/AppInfo/" + pics[ind] pic = fold + "/App/AppInfo/" + pics[ind]
} }
} else if _, err := os.Open(fold + "/appicon.png"); err == nil {
pic = fold + "/appicon.png"
} else { } else {
img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON) img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON)
buf := img.GetPixbuf() buf := img.GetPixbuf()
@@ -179,6 +182,9 @@ func getIcon(fold string) *gdk.Pixbuf {
} }
func findInfo(fold string) *os.File { 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") tmp, err := os.Open(fold + "/App/AppInfo")
if err == nil { if err == nil {
fis, _ := tmp.Readdirnames(-1) fis, _ := tmp.Readdirnames(-1)
@@ -189,8 +195,5 @@ func findInfo(fold string) *os.File {
} }
} }
} }
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
return fi
}
return nil return nil
} }
+68 -29
View File
@@ -1,8 +1,6 @@
package main package main
import ( import (
"fmt"
"github.com/CalebQ42/LinuxPA/appimg" "github.com/CalebQ42/LinuxPA/appimg"
"github.com/gotk3/gotk3/glib" "github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
@@ -16,9 +14,6 @@ func ui(win *gtk.Window) {
header.SetTitle("LinuxPA") header.SetTitle("LinuxPA")
header.SetSubtitle("PortableApps.com type launcher") header.SetSubtitle("PortableApps.com type launcher")
settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR) settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR)
settings.Connect("clicked", func() {
settingsUI()
})
settings.SetTooltipText("Settings") settings.SetTooltipText("Settings")
dnl, _ := gtk.ButtonNewFromIconName("emblem-downloads", gtk.ICON_SIZE_SMALL_TOOLBAR) dnl, _ := gtk.ButtonNewFromIconName("emblem-downloads", gtk.ICON_SIZE_SMALL_TOOLBAR)
dnl.SetTooltipText("Download Apps") dnl.SetTooltipText("Download Apps")
@@ -55,25 +50,47 @@ func ui(win *gtk.Window) {
lrBox.Add(catScrl) lrBox.Add(catScrl)
lrBox.Add(appScrl) lrBox.Add(appScrl)
botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2) botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2)
wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)") botBox.SetMarginStart(10)
if !wineAvail { botBox.SetMarginEnd(10)
wineCheck.SetSensitive(false) botBox.SetMarginTop(10)
wineCheck.SetTooltipText("Download wine to run windows apps") botBox.SetMarginBottom(10)
} edit, _ := gtk.ButtonNewWithLabel("Edit App..")
wineCheck.SetActive(wine) edit.Connect("clicked", func() {
wineCheck.Connect("toggled", func() { selec, _ := appsList.GetSelection()
wine = wineCheck.GetActive() _, 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 { for i := range ls {
fmt.Println(len(ls) - i)
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1)) catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
} }
ls = getCatRows() ls = getCatRows()
for _, v := range ls { for i, v := range ls {
catList.Add(v) catList.Insert(v, i)
} }
catList.ShowAll() catList.ShowAll()
}) })
botBox.Add(wineCheck) } 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.Add(lrBox)
topLvl.PackEnd(botBox, false, true, 0) topLvl.PackEnd(botBox, false, true, 0)
win.Add(topLvl) win.Add(topLvl)
@@ -105,30 +122,52 @@ func ui(win *gtk.Window) {
ind := pth.GetIndices() ind := pth.GetIndices()
if len(ind) == 1 { if len(ind) == 1 {
if wine { if wine {
app := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]] appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
app.launch() appLnch.launch()
} else { } else {
app := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]] appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
app.launch() appLnch.launch()
} }
} else if len(ind) == 2 { } else if len(ind) == 2 {
if wine { if wine {
app := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]] appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
app.launchSub(ind[1]) appLnch.launchSub(ind[1])
} else { } else {
app := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]] appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
app.launchSub(ind[1]) appLnch.launchSub(ind[1])
} }
} }
} }
}) })
dnl.Connect("clicked", func() { dnl.Connect("clicked", func() {
appimg.ShowUI(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() store.Clear()
ls = getCatRows() for i := range ls {
for _, v := range ls { catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
catList.Add(v)
} }
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()
}) })
}) })
} }
+93 -4
View File
@@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@@ -16,6 +17,7 @@ import (
const ( const (
versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1" versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1"
downloadURL = "https://github.com/CalebQ42/LinuxPA/releases/download/vXXX/LinuxPA" 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 //Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
@@ -55,6 +57,38 @@ func getVersionFileInfo() string {
return string(out) 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) { func checkForUpdate(new string) (bool, error) {
curSlice := strings.Split(version, ".") curSlice := strings.Split(version, ".")
newSlice := strings.Split(new, ".") newSlice := strings.Split(new, ".")
@@ -111,13 +145,69 @@ func downloadUpdate(newVersion string) (bool, error) {
return true, nil return true, nil
} }
func update(win *gtk.Window) { 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, _ := gtk.WindowNew(gtk.WINDOW_POPUP)
updateWin.SetTransientFor(win) updateWin.SetTransientFor(win)
updateWin.SetSizeRequest(150, 50)
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
spin, _ := gtk.SpinnerNew() spin, _ := gtk.SpinnerNew()
spin.Start() spin.Start()
lbl, _ := gtk.LabelNew("Checking for updates") lbl, _ := gtk.LabelNew("Updating")
topLvl.Add(spin) topLvl.Add(spin)
topLvl.Add(lbl) topLvl.Add(lbl)
topLvl.SetMarginBottom(10) topLvl.SetMarginBottom(10)
@@ -135,8 +225,7 @@ func update(win *gtk.Window) {
res := getVersionFileInfo() res := getVersionFileInfo()
if res != "Error!" { if res != "Error!" {
stat, err = checkForUpdate(res) stat, err = checkForUpdate(res)
if stat { if stat || forced {
lbl.SetText("Updating!")
downloadUpdate(res) downloadUpdate(res)
win.Close() win.Close()
cmd := exec.Command("./LinuxPA") cmd := exec.Command("./LinuxPA")