15 Commits

Author SHA1 Message Date
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
Caleb Gardner d2e91baa6b Possibly full AppImage support 2020-11-06 04:54:22 -06:00
Caleb Gardner a0f22e480b Now using a new version of GoAppImage which should actually work.
Minor updates due to new library versions
Added go.mod to use Go's versioning system.
2020-11-06 03:44:34 -06:00
Belac Darkstorm 57f921c2cb Merge pull request #12 from probonopd/patch-1
https://appimage.github.io/
2019-01-18 18:37:35 -06:00
probonopd 55f897db46 https://appimage.github.io/ 2019-01-18 16:47:12 +00:00
Belac Darkstorm 3d9583281e AppImage's are now processed better
AppImage's desktop files are now extracted so name, category, and icon can be obtained
Made all icons be scaled so you don't get icons that are too big or small
2018-06-16 03:08:31 -05:00
Caleb ec4d66f6b2 Some refinement
Moved more complex appimage stuff to seperate package (github.com/CalebQ42/GoAppImage)
Moved settings to a seperate file for organization
Some work to allow asyncronouse app loading (Since goappimage is super slow)
Comments to show what's going to be there in the future.
2018-06-14 02:30:59 -05:00
Caleb c442ef5688 Removed debug code 2018-06-07 21:02:37 -05:00
Caleb 78d3723bf4 Finished work on AppImage desktop file extraction 2018-06-07 13:58:47 -05:00
18 changed files with 293 additions and 638 deletions
+3 -2
View File
@@ -6,7 +6,7 @@ Just double click on an app to launch it! If there are multiple executables, you
# 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:
[AppImage](https://bintray.com/probono/AppImages) [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.
@@ -20,7 +20,7 @@ Because apps aren't natively formated in the PortableApps.com format, LinuxPA wi
# 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, and you can download AppImages. (Woo) 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`
@@ -30,6 +30,7 @@ Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshot
# TODO (Might be in order) # TODO (Might be in order)
1. MAKE IT BETTER   1. MAKE IT BETTER  
1. Try to `chmod +x` executables if they don't have the permission
1. Manual update check   1. Manual update check  
1. Better AppImage integrations (Specifically updating, getting information from the appimage, and better appimage downloading) 1. Better AppImage integrations (Specifically updating, getting information from the appimage, and better appimage downloading)
1. Automagic appimage updating (It will of course ask you beforehand) 1. Automagic appimage updating (It will of course ask you beforehand)
+3 -2
View File
@@ -25,7 +25,8 @@ 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) scaled, _ := a.icon.ScaleSimple(32, 32, gdk.INTERP_HYPER)
store.SetValue(it, 0, scaled)
if portableHide { if portableHide {
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable")) store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
} else { } else {
@@ -218,7 +219,7 @@ func (a *app) edit(parent *gtk.Window, reload func()) {
fil.Close() fil.Close()
}) })
resp := fil.Run() resp := fil.Run()
if resp == int(gtk.RESPONSE_ACCEPT) { if resp == gtk.RESPONSE_ACCEPT {
filename := fil.GetFilename() filename := fil.GetFilename()
_, err := os.Open(filename) _, err := os.Open(filename)
if err != nil { if err != nil {
-78
View File
@@ -1,78 +0,0 @@
package appimg
// Thanks to probono for the majority of this C code: https://discourse.appimage.org/t/accessing-appimage-desktop-file/173/4?u=calebq42
/*
#cgo CFLAGS: -I/usr/lib
#cgo LDFLAGS: -L/usr/lib/libappimage.so -lappimage
#cgo pkg-config: glib-2.0
#include <appimage/appimage.h>
#include <stdlib.h>
#include <glib.h>
#include <strings.h>
bool extract_desktop(char* appimageLoc,char* extractLoc){
char** files = appimage_list_files(appimageLoc);
g_autofree gchar *desktop_file = NULL;
gchar *extracted_desktop_file = extractLoc;
int i = 0;
for (; files[i] != NULL ; i++) {
// g_debug("AppImage file: %s", files[i]);
if (g_str_has_suffix (files[i],".desktop")) {
desktop_file = files[i];
g_debug("AppImage desktop file: %s", desktop_file);
break;
}
}
if(desktop_file == NULL) {
g_debug("AppImage desktop file not found");
appimage_string_list_free(files);
return FALSE;
}
appimage_extract_file_following_symlinks(appimageLoc, desktop_file,extracted_desktop_file);
appimage_string_list_free(files);
return TRUE;
}
bool extract_file(char* appimageLoc,char* filename,char* extractLoc){
char** files = appimage_list_files(appimageLoc);
g_autofree gchar *found_file = NULL;
gchar *extracted_file = extractLoc;
int i = 0;
for (; files[i] != NULL ; i++) {
g_debug("AppImage file: %s", files[i]);
if (strcmp(files[i],filename)==0) {
found_file = files[i];
g_debug("FileFound: %s", found_file);
}
}
if(found_file == NULL) {
g_debug("filenotfound");
appimage_string_list_free(files);
return FALSE;
}
appimage_extract_file_following_symlinks(appimageLoc, found_file,extracted_file);
appimage_string_list_free(files);
return TRUE;
}
*/
import "C"
import (
"errors"
"os"
"unsafe"
)
func GetDesktopFile(loc string) (*os.File, error) {
os.Remove("/tmp/my.desktop")
var locTmp *C.char = C.CString(loc)
defer C.free(unsafe.Pointer(locTmp))
var extractLoc *C.char = C.CString("/tmp/my.desktop")
defer C.free(unsafe.Pointer(extractLoc))
var out C.bool = C.extract_desktop(locTmp, extractLoc)
if out == false {
return nil, errors.New("Desktop File Not Found!")
}
return os.Open("/tmp/my.desktop")
}
-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
}
+13
View File
@@ -0,0 +1,13 @@
module github.com/CalebQ42/LinuxPA
go 1.15
require (
github.com/CalebQ42/GoAppImage v0.4.0
github.com/gotk3/gotk3 v0.5.0
github.com/mholt/archiver/v3 v3.5.0
github.com/pkg/browser v0.0.0-20201112035734-206646e67786
)
//For testing local changes to my library
// replace github.com/CalebQ42/GoAppImage => ../GoAppImage
+71
View File
@@ -0,0 +1,71 @@
github.com/CalebQ42/GoAppImage v0.4.0 h1:aF+Y/vyo/RGhoyZEW1CMY6WyRWrZZO4ydsRFAtIGnaY=
github.com/CalebQ42/GoAppImage v0.4.0/go.mod h1:qHudJKAn/dlkNWNnH4h1YKXp29EZ7Bppsn7sNP2HuvU=
github.com/adrg/xdg v0.2.2 h1:A7ZHKRz5KGOLJX/bg7IPzStryhvCzAE1wX+KWawPiAo=
github.com/adrg/xdg v0.2.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
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/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.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/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/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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
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/browser v0.0.0-20201112035734-206646e67786 h1:4Gk0Dsp90g2YwfsxDOjvkEIgKGh+2R9FlvormRycveA=
github.com/pkg/browser v0.0.0-20201112035734-206646e67786/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/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/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=
+7 -70
View File
@@ -1,7 +1,6 @@
package main package main
import ( import (
"encoding/gob"
"flag" "flag"
"fmt" "fmt"
"os" "os"
@@ -10,21 +9,16 @@ import (
) )
const ( const (
version = "2.1.4.0" version = "2.1.5.2"
) )
var ( var (
master map[string][]app master map[string][]app
linmaster map[string][]app linmaster map[string][]app
cats []string cats []string
lin []string lin []string
wine bool comEnbld bool
comEnbld bool populated bool
wineAvail bool
portableHide bool
betaUpdate bool
versionNewest = true
paDirs = true
) )
func main() { func main() {
@@ -57,63 +51,6 @@ func uiStart(forced bool) {
gtk.Main() gtk.Main()
} }
func savePrefs() {
os.Remove("PortableApps/LinuxPACom/Prefs.gob")
fil, err := os.Create("PortableApps/LinuxPACom/Prefs.gob")
if err != nil {
return
}
enc := gob.NewEncoder(fil)
err = enc.Encode(wine)
if err != nil {
return
}
err = enc.Encode(portableHide)
if err != nil {
return
}
err = enc.Encode(versionNewest)
if err != nil {
return
}
err = enc.Encode(paDirs)
if err != nil {
return
}
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
}
}
func contains(arr []string, str string) bool { func contains(arr []string, str string) bool {
for _, v := range arr { for _, v := range arr {
if v == str { if v == str {
+72
View File
@@ -0,0 +1,72 @@
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
}
}
+112 -18
View File
@@ -9,6 +9,7 @@ import (
"sort" "sort"
"strings" "strings"
goappimage "github.com/CalebQ42/GoAppImage"
"github.com/gotk3/gotk3/gdk" "github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
) )
@@ -64,35 +65,21 @@ func setup() {
} }
} }
} }
populated = true
} }
func processApp(fold string) (out app) { func processApp(fold string) (out app) {
wd, _ := os.Getwd() wd, _ := os.Getwd()
out.dir = wd + "/" + fold out.dir = wd + "/" + fold
out.ini = findInfo(fold)
if out.ini != nil {
out.name = getName(out.ini)
out.ini = findInfo(fold)
out.cat = getCat(out.ini)
out.ini = findInfo(fold)
}
if out.name == "" {
out.name = strings.TrimPrefix(fold, "PortableApps/")
}
if out.cat == "" {
out.cat = "Other"
}
if portableHide {
out.name = strings.TrimSuffix(out.name, "Portable")
}
out.icon = getIcon(fold)
folder, _ := os.Open(fold) folder, _ := os.Open(fold)
fis, _ := folder.Readdirnames(-1) fis, _ := folder.Readdirnames(-1)
for _, v := range fis { for _, v := range fis {
tmp, _ := os.Open(fold + "/" + v) tmp, _ := os.Open(fold + "/" + v)
if stat, _ := tmp.Stat(); stat.IsDir() { stat, _ := tmp.Stat()
if stat.IsDir() {
continue continue
} }
//TODO: check permission to see if it has exec permission
if strings.HasSuffix(strings.ToLower(v), ".appimage") { if strings.HasSuffix(strings.ToLower(v), ".appimage") {
out.appimg = append(out.appimg, v) out.appimg = append(out.appimg, v)
out.ex = append(out.ex, v) out.ex = append(out.ex, v)
@@ -116,6 +103,88 @@ func processApp(fold string) (out app) {
out.name += " (Wine)" out.name += " (Wine)"
out.wine = true 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")
}
out.name = strings.TrimSpace(out.name)
return return
} }
@@ -134,6 +203,31 @@ func getCat(ini *os.File) string {
return ret 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 { func getName(ini *os.File) string {
rdr := bufio.NewReader(ini) rdr := bufio.NewReader(ini)
var ret string var ret string
+3 -17
View File
@@ -1,9 +1,9 @@
package main package main
import ( import (
"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"
"github.com/pkg/browser"
) )
func ui(win *gtk.Window) { func ui(win *gtk.Window) {
@@ -140,22 +140,8 @@ func ui(win *gtk.Window) {
} }
}) })
dnl.Connect("clicked", func() { dnl.Connect("clicked", func() {
appimg.ShowUI(versionNewest, func() { //TODO: detect if a webbrowser app is available and use that instead
master = make(map[string][]app) browser.OpenURL("https://appimage.github.io/apps/")
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() { settings.Connect("clicked", func() {
settingsUI(win, func() { settingsUI(win, func() {
+4 -2
View File
@@ -17,8 +17,8 @@ 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" changelogURL = "https://www.dropbox.com/s/rk8ec9p14imkh03/Changelog?dl=1"
changelogBetaURL = "https://www.dropbox.com/s/m8mo2o3nsvfqbfx/ChangelogBeta?dl=1" changelogBetaURL = "https://www.dropbox.com/s/h2u34g5s8qr8sef/ChangelogBeta?dl=1"
) )
//Thanks to https://www.socketloop.com/tutorials/golang-download-file-example //Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
@@ -170,11 +170,13 @@ func update(win *gtk.Window, forced bool) {
updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
updateWin.SetTransientFor(win) updateWin.SetTransientFor(win)
updateWin.SetPosition(gtk.WIN_POS_CENTER) updateWin.SetPosition(gtk.WIN_POS_CENTER)
updateWin.SetDefaultSize(600, 300)
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
lbl, _ := gtk.LabelNew("There's a new update! Here's the changelog:") lbl, _ := gtk.LabelNew("There's a new update! Here's the changelog:")
tagTbl, _ := gtk.TextTagTableNew() tagTbl, _ := gtk.TextTagTableNew()
buf, _ := gtk.TextBufferNew(tagTbl) buf, _ := gtk.TextBufferNew(tagTbl)
tv, _ := gtk.TextViewNewWithBuffer(buf) tv, _ := gtk.TextViewNewWithBuffer(buf)
tv.SetWrapMode(gtk.WRAP_WORD)
tv.SetEditable(false) tv.SetEditable(false)
buf.SetText(getChangelog()) buf.SetText(getChangelog())
butBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5) butBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
+4 -4
View File
@@ -9,11 +9,11 @@ import (
"strings" "strings"
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
"github.com/mholt/archiver" "github.com/mholt/archiver/v3"
) )
const ( const (
wineURL = "https://www.playonlinux.com/wine/binaries/linux-amd64/PlayOnLinux-wine-2.5-linux-amd64.pol" 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) { func downloadWine(parent *gtk.Window, cb chan bool) {
@@ -40,7 +40,7 @@ func downloadWine(parent *gtk.Window, cb chan bool) {
win.Show() win.Show()
go func(win *gtk.Window, txt *gtk.Label) { go func(win *gtk.Window, txt *gtk.Label) {
defer win.Close() defer win.Close()
wineTar, err := os.Create("PortableApps/LinuxPACom/wine2.5.tar.bz2") wineTar, err := os.Create("PortableApps/LinuxPACom/wine5.20.tar.bz2")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
cb <- false cb <- false
@@ -68,7 +68,7 @@ func downloadWine(parent *gtk.Window, cb chan bool) {
return return
} }
txt.SetText("Extracting Wine") txt.SetText("Extracting Wine")
err = archiver.TarBz2.Open("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine") err = archiver.DefaultTarBz2.Unarchive("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
cb <- false cb <- false