Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be64aa083f | |||
| 3111705cae | |||
| 868ae8f700 | |||
| 226e9d6210 | |||
| 56748f043e | |||
| 3d3239fe0a | |||
| 6e643b68ac | |||
| 539f33d25e | |||
| 4d3cb9f486 |
@@ -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,27 @@ 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 integrations (Specifically updating, getting information from the appimage, and better appimage downloading)
|
||||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
1. Automagic appimage updating (It will of course ask you beforehand)
|
||||||
|
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. Sandboxing support
|
||||||
|
1. Check if all apps are closed when it closes and ask if you want to force stop the apps
|
||||||
|
|||||||
@@ -25,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)
|
||||||
store.SetValue(it, 1, a.name)
|
if portableHide {
|
||||||
|
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
|
||||||
|
} else {
|
||||||
|
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 {
|
||||||
@@ -48,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -64,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -78,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -90,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -109,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -127,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -143,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]+"\"")
|
||||||
}
|
}
|
||||||
@@ -179,11 +207,15 @@ func (a *app) edit(parent *gtk.Window, reload func()) {
|
|||||||
imgBut.SetImage(img)
|
imgBut.SetImage(img)
|
||||||
imgBut.SetSizeRequest(100, 100)
|
imgBut.SetSizeRequest(100, 100)
|
||||||
imgBut.Connect("clicked", func() {
|
imgBut.Connect("clicked", func() {
|
||||||
fil, _ := gtk.FileChooserDialogNewWith2Buttons("Select Icon", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Cancel", gtk.RESPONSE_CANCEL, "Open", gtk.RESPONSE_ACCEPT)
|
fil, _ := gtk.FileChooserDialogNewWith1Button("Select Icon", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_ACCEPT)
|
||||||
filter, _ := gtk.FileFilterNew()
|
filter, _ := gtk.FileFilterNew()
|
||||||
filter.AddPixbufFormats()
|
filter.AddPixbufFormats()
|
||||||
filter.SetName("Supported Pictures")
|
filter.SetName("Supported Pictures")
|
||||||
fil.AddFilter(filter)
|
fil.AddFilter(filter)
|
||||||
|
but, _ := fil.AddButton("Cancel", gtk.RESPONSE_CANCEL)
|
||||||
|
but.Connect("clicked", func() {
|
||||||
|
fil.Close()
|
||||||
|
})
|
||||||
resp := fil.Run()
|
resp := fil.Run()
|
||||||
if resp == int(gtk.RESPONSE_ACCEPT) {
|
if resp == int(gtk.RESPONSE_ACCEPT) {
|
||||||
filename := fil.GetFilename()
|
filename := fil.GetFilename()
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
+1
-1
@@ -53,7 +53,7 @@ func downloadApp(parent *gtk.Window, ap appimg) {
|
|||||||
foldName = "PortableApps/" + name
|
foldName = "PortableApps/" + name
|
||||||
} else {
|
} else {
|
||||||
os.Mkdir("PortableApps/"+name+"Portable", 0777)
|
os.Mkdir("PortableApps/"+name+"Portable", 0777)
|
||||||
foldName = "PortableApps/" + name
|
foldName = "PortableApps/" + name + "Portable"
|
||||||
}
|
}
|
||||||
os.Remove(foldName + "/" + ap.full)
|
os.Remove(foldName + "/" + ap.full)
|
||||||
fil, err := os.Create(foldName + "/" + ap.full)
|
fil, err := os.Create(foldName + "/" + ap.full)
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
"github.com/nelsam/gxui/drivers/gl"
|
|
||||||
"github.com/nelsam/gxui/themes/dark"
|
|
||||||
"github.com/nelsam/gxui/themes/light"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
version = "1.1.0.0"
|
|
||||||
defIni = "[basic]\ntheme=dk"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
dr gxui.Driver
|
|
||||||
th gxui.Theme
|
|
||||||
master map[string][]app
|
|
||||||
linmaster map[string][]app
|
|
||||||
cats []string
|
|
||||||
lin []string
|
|
||||||
wine bool
|
|
||||||
comEnbld bool
|
|
||||||
darkTheme = true
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
updated := false
|
|
||||||
os.MkdirAll("PortableApps/LinuxPACom", 0777)
|
|
||||||
stat, err := versionDL()
|
|
||||||
if stat {
|
|
||||||
res := getVersionFileInfo()
|
|
||||||
if res != "Error!" {
|
|
||||||
stat, err = checkForUpdate(res)
|
|
||||||
if stat {
|
|
||||||
downloadUpdate(res)
|
|
||||||
updated = true
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed Version File Info")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
cmd := exec.Command("./LinuxPA")
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
master = make(map[string][]app)
|
|
||||||
linmaster = make(map[string][]app)
|
|
||||||
gl.StartDriver(appMain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func appMain(dri gxui.Driver) {
|
|
||||||
dr = dri
|
|
||||||
setup()
|
|
||||||
if darkTheme {
|
|
||||||
th = dark.CreateTheme(dr)
|
|
||||||
} else {
|
|
||||||
th = light.CreateTheme(dr)
|
|
||||||
}
|
|
||||||
th = dark.CreateTheme(dr)
|
|
||||||
ui()
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains(arr []string, str string) bool {
|
|
||||||
for _, v := range arr {
|
|
||||||
if v == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
_ "image/png"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setup() {
|
|
||||||
PortableAppsFold, err := os.Open("PortableApps")
|
|
||||||
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
|
||||||
os.Mkdir("PortableApps", 0777)
|
|
||||||
PortableAppsFold, err = os.Open("PortableApps")
|
|
||||||
if err != nil {
|
|
||||||
panic("Can't find PortableApps folder and can't create one!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err = os.Open("PortableApps/LinuxPACom"); err != nil {
|
|
||||||
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
|
||||||
}
|
|
||||||
fmt.Println(err)
|
|
||||||
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
|
|
||||||
if err == nil {
|
|
||||||
comEnbld = true
|
|
||||||
}
|
|
||||||
fi, err := os.Open("PortableApps/LinuxPACom/Info.ini")
|
|
||||||
if err != nil {
|
|
||||||
fi, err = os.Create("PortableApps/LinuxPACom/Info.ini")
|
|
||||||
if err == nil {
|
|
||||||
wrt := bufio.NewWriter(fi)
|
|
||||||
wrt.WriteString(defIni)
|
|
||||||
wrt.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
rdr := bufio.NewReader(fi)
|
|
||||||
for err != nil {
|
|
||||||
ln, _, error := rdr.ReadLine()
|
|
||||||
err = error
|
|
||||||
str := string(ln)
|
|
||||||
if strings.HasPrefix(str, "theme=") {
|
|
||||||
str = strings.TrimPrefix(str, "theme=")
|
|
||||||
if str == "lt" {
|
|
||||||
darkTheme = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
|
|
||||||
sort.Strings(PAFolds)
|
|
||||||
for _, v := range PAFolds {
|
|
||||||
fold, _ := os.Open("PortableApps/" + v)
|
|
||||||
if stat, _ := fold.Stat(); stat.IsDir() && stat.Name() != "PortableApps.com" && stat.Name() != "LinuxPACom" {
|
|
||||||
ap := processApp("PortableApps/" + v)
|
|
||||||
if !reflect.DeepEqual(ap, app{}) {
|
|
||||||
if _, ok := master[ap.cat]; !ok {
|
|
||||||
cats = append(cats, ap.cat)
|
|
||||||
sort.Strings(cats)
|
|
||||||
}
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
if _, ok := linmaster[ap.cat]; !ok {
|
|
||||||
lin = append(lin, ap.cat)
|
|
||||||
sort.Strings(lin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master[ap.cat] = append(master[ap.cat], ap)
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
linmaster[ap.cat] = append(linmaster[ap.cat], ap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func processApp(fold string) (out app) {
|
|
||||||
wd, _ := os.Getwd()
|
|
||||||
out.dir = wd + "/" + fold
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
if out.ini != nil {
|
|
||||||
out.name = getName(out.ini)
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
out.cat = getCat(out.ini)
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
}
|
|
||||||
if out.name == "" {
|
|
||||||
out.name = strings.TrimPrefix(fold, "PortableApps/")
|
|
||||||
}
|
|
||||||
if out.cat == "" {
|
|
||||||
out.cat = "Other"
|
|
||||||
}
|
|
||||||
out.icon = getIcon(fold)
|
|
||||||
folder, _ := os.Open(fold)
|
|
||||||
fis, _ := folder.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
tmp, _ := os.Open(fold + "/" + v)
|
|
||||||
if stat, _ := tmp.Stat(); stat.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(strings.ToLower(v), ".appimage") {
|
|
||||||
out.appimg = append(out.appimg, v)
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
} else if strings.HasSuffix(strings.ToLower(v), ".exe") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
} else {
|
|
||||||
btys := make([]byte, 4)
|
|
||||||
rdr := bufio.NewReader(tmp)
|
|
||||||
rdr.Read(btys)
|
|
||||||
if (strings.Contains(strings.ToLower(string(btys)), "elf") && !strings.HasSuffix(strings.ToLower(v), ".so") && !strings.Contains(v, ".so.")) || strings.HasPrefix(strings.ToLower(string(btys)), "#!") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(out.ex) == 0 {
|
|
||||||
return app{}
|
|
||||||
}
|
|
||||||
if len(out.lin) == 0 {
|
|
||||||
out.name += " (Wine)"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCat(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Category=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Category=")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func getName(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Name=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Name=")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIcon(fold string) gxui.Texture {
|
|
||||||
var pic *os.File
|
|
||||||
if folder, err := os.Open(fold + "/App/AppInfo"); err == nil {
|
|
||||||
fis, _ := folder.Readdir(-1)
|
|
||||||
var pics []string
|
|
||||||
for _, v := range fis {
|
|
||||||
if !v.IsDir() && strings.HasSuffix(strings.ToLower(v.Name()), ".png") && strings.HasPrefix(strings.ToLower(v.Name()), "appicon_") {
|
|
||||||
pics = append(pics, v.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(pics)
|
|
||||||
if len(pics) > 1 {
|
|
||||||
var ind int
|
|
||||||
if !contains(pics, "appicon_32.png") {
|
|
||||||
ind = len(pics) - 1
|
|
||||||
} else {
|
|
||||||
ind = sort.SearchStrings(pics, "appicon_32.png")
|
|
||||||
}
|
|
||||||
pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind])
|
|
||||||
}
|
|
||||||
} else if fi, err := os.Open(fold + "/appicon.png"); err == nil {
|
|
||||||
pic = fi
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
img, _, err := image.Decode(pic)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rgba := image.NewRGBA(img.Bounds())
|
|
||||||
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
|
|
||||||
ret := dr.CreateTexture(rgba, 1)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func findInfo(fold string) *os.File {
|
|
||||||
tmp, err := os.Open(fold + "/App/AppInfo")
|
|
||||||
if err == nil {
|
|
||||||
fis, _ := tmp.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
if strings.ToLower(v) == "appinfo.ini" {
|
|
||||||
tmp, _ := os.Open(fold + "/App/AppInfo/" + v)
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
|
||||||
return fi
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
"github.com/nelsam/gxui/math"
|
|
||||||
)
|
|
||||||
|
|
||||||
//StrList TODO
|
|
||||||
type StrList struct {
|
|
||||||
gxui.AdapterBase
|
|
||||||
strs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
//AddString TODO
|
|
||||||
func (s *StrList) AddString(add string) {
|
|
||||||
s.strs = append(s.strs, add)
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove TODO
|
|
||||||
func (s *StrList) Remove(index int) {
|
|
||||||
s.strs = append(s.strs[:index], s.strs[index+1:]...)
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//SetStrings TODO
|
|
||||||
func (s *StrList) SetStrings(strs []string) {
|
|
||||||
s.strs = strs
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Count TODO
|
|
||||||
func (s *StrList) Count() int {
|
|
||||||
return len(s.strs)
|
|
||||||
}
|
|
||||||
|
|
||||||
//ItemAt TODO
|
|
||||||
func (s *StrList) ItemAt(index int) gxui.AdapterItem {
|
|
||||||
return s.strs[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
//ItemIndex TODO
|
|
||||||
func (s *StrList) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
for i, v := range s.strs {
|
|
||||||
if v == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create TODO
|
|
||||||
func (s *StrList) Create(th gxui.Theme, index int) gxui.Control {
|
|
||||||
box := th.CreateLinearLayout()
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
lbl := th.CreateLabel()
|
|
||||||
lbl.SetText(s.strs[index])
|
|
||||||
box.AddChild(lbl)
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
//Size TODO
|
|
||||||
func (s *StrList) Size(gxui.Theme) math.Size {
|
|
||||||
return math.Size{W: math.MaxSize.W, H: 20}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ui() {
|
|
||||||
catListAdap := &StrList{}
|
|
||||||
appListAdap := &catAdap{}
|
|
||||||
catListAdap.SetStrings(lin)
|
|
||||||
win := th.CreateWindow(500, 500, "LinuxPA")
|
|
||||||
top := th.CreateLinearLayout()
|
|
||||||
top.SetDirection(gxui.BottomToTop)
|
|
||||||
splBox := th.CreateLinearLayout()
|
|
||||||
spl := th.CreateSplitterLayout()
|
|
||||||
spl.SetOrientation(gxui.Horizontal)
|
|
||||||
catList := th.CreateList()
|
|
||||||
catList.SetAdapter(catListAdap)
|
|
||||||
catList.OnSelectionChanged(func(it gxui.AdapterItem) {
|
|
||||||
appListAdap.setCat(it.(string))
|
|
||||||
})
|
|
||||||
appList := th.CreateTree()
|
|
||||||
appList.SetAdapter(appListAdap)
|
|
||||||
spl.AddChild(catList)
|
|
||||||
spl.AddChild(appList)
|
|
||||||
splBox.AddChild(spl)
|
|
||||||
butBox := th.CreateLinearLayout()
|
|
||||||
butBox.SetDirection(gxui.LeftToRight)
|
|
||||||
if _, err := exec.LookPath("wine"); err == nil {
|
|
||||||
wineBut := th.CreateButton()
|
|
||||||
wineBut.SetType(gxui.ToggleButton)
|
|
||||||
wineBut.SetChecked(wine)
|
|
||||||
wineBut.SetText("Show Windows Apps")
|
|
||||||
wineBut.OnClick(func(gxui.MouseEvent) {
|
|
||||||
wine = wineBut.IsChecked()
|
|
||||||
appListAdap.refresh()
|
|
||||||
if wineBut.IsChecked() {
|
|
||||||
catListAdap.SetStrings(cats)
|
|
||||||
wineBut.SetText("Hide Windows Apps")
|
|
||||||
} else {
|
|
||||||
catListAdap.SetStrings(lin)
|
|
||||||
wineBut.SetText("Show Windows Apps")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
_, err := os.Open("Start.exe")
|
|
||||||
if err == nil {
|
|
||||||
pa := th.CreateButton()
|
|
||||||
pa.SetText("Open PortableApps Launcher")
|
|
||||||
pa.OnClick(func(gxui.MouseEvent) {
|
|
||||||
cmd := exec.Command("wine", "Start.exe")
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
})
|
|
||||||
butBox.AddChild(pa)
|
|
||||||
}
|
|
||||||
butBox.AddChild(wineBut)
|
|
||||||
}
|
|
||||||
top.AddChild(butBox)
|
|
||||||
top.AddChild(splBox)
|
|
||||||
win.AddChild(top)
|
|
||||||
win.OnClose(dr.Terminate)
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@@ -9,8 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "2.1.1.0"
|
version = "2.1.4.0"
|
||||||
defIni = ""
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -22,17 +22,21 @@ var (
|
|||||||
comEnbld bool
|
comEnbld bool
|
||||||
wineAvail bool
|
wineAvail bool
|
||||||
portableHide bool
|
portableHide bool
|
||||||
|
betaUpdate bool
|
||||||
versionNewest = true
|
versionNewest = true
|
||||||
|
paDirs = true
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
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,7 +53,7 @@ func uiStart() {
|
|||||||
ui(win)
|
ui(win)
|
||||||
win.ShowAll()
|
win.ShowAll()
|
||||||
win.Show()
|
win.Show()
|
||||||
update(win)
|
update(win, forced)
|
||||||
gtk.Main()
|
gtk.Main()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +76,14 @@ func savePrefs() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
err = enc.Encode(paDirs)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = enc.Encode(betaUpdate)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPrefs() {
|
func loadPrefs() {
|
||||||
@@ -92,6 +104,14 @@ func loadPrefs() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
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 {
|
||||||
|
|||||||
+46
@@ -9,6 +9,10 @@ import (
|
|||||||
"github.com/gotk3/gotk3/gtk"
|
"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()) {
|
func settingsUI(parent *gtk.Window, onExit func()) {
|
||||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
win.SetTransientFor(parent)
|
win.SetTransientFor(parent)
|
||||||
@@ -84,11 +88,19 @@ func settingsUI(parent *gtk.Window, onExit func()) {
|
|||||||
versCheck.Connect("toggled", func() {
|
versCheck.Connect("toggled", func() {
|
||||||
versionNewest = versCheck.GetActive()
|
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(wineLbl)
|
||||||
gnrl.Add(dlWine)
|
gnrl.Add(dlWine)
|
||||||
gnrl.Add(pthdCheck)
|
gnrl.Add(pthdCheck)
|
||||||
gnrl.Add(wineCheck)
|
gnrl.Add(wineCheck)
|
||||||
gnrl.Add(versCheck)
|
gnrl.Add(versCheck)
|
||||||
|
gnrl.Add(paDirsCheck)
|
||||||
|
gnrl.Add(betaCheck)
|
||||||
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)
|
||||||
@@ -113,8 +125,25 @@ func settingsUI(parent *gtk.Window, onExit func()) {
|
|||||||
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(comScrl)
|
||||||
com.Add(svBox)
|
com.Add(svBox)
|
||||||
ntbk.AppendPage(com, getLabel("common.sh"))
|
ntbk.AppendPage(com, getLabel("common.sh"))
|
||||||
@@ -136,8 +165,25 @@ func settingsUI(parent *gtk.Window, onExit func()) {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -14,8 +15,10 @@ 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"
|
||||||
|
changelogBetaURL = "https://www.dropbox.com/s/m8mo2o3nsvfqbfx/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
|
||||||
@@ -45,17 +48,61 @@ func versionDL() (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVersionFileInfo() string {
|
func getVersionFileInfo() (stable string, beta string) {
|
||||||
fil, err := os.Open("PortableApps/LinuxPACom/Version")
|
fil, err := os.Open("PortableApps/LinuxPACom/Version")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "Error!"
|
return "Error!", ""
|
||||||
}
|
}
|
||||||
rdr := bufio.NewReader(fil)
|
rdr := bufio.NewReader(fil)
|
||||||
out, _, _ := rdr.ReadLine()
|
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)
|
return string(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkForUpdate(new string) (bool, error) {
|
func checkForUpdate(stable, beta string) (bool, error) {
|
||||||
|
new := stable
|
||||||
|
if betaUpdate {
|
||||||
|
new = beta
|
||||||
|
}
|
||||||
curSlice := strings.Split(version, ".")
|
curSlice := strings.Split(version, ".")
|
||||||
newSlice := strings.Split(new, ".")
|
newSlice := strings.Split(new, ".")
|
||||||
curNums := make([]int, 4)
|
curNums := make([]int, 4)
|
||||||
@@ -111,13 +158,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 {
|
||||||
|
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, _ := 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)
|
||||||
@@ -132,12 +235,15 @@ func update(win *gtk.Window) {
|
|||||||
defer updateWin.Close()
|
defer updateWin.Close()
|
||||||
stat, err := versionDL()
|
stat, err := versionDL()
|
||||||
if stat {
|
if stat {
|
||||||
res := getVersionFileInfo()
|
stable, beta := getVersionFileInfo()
|
||||||
if res != "Error!" {
|
if stable != "Error!" {
|
||||||
stat, err = checkForUpdate(res)
|
stat, err = checkForUpdate(stable, beta)
|
||||||
if stat {
|
if stat || forced {
|
||||||
lbl.SetText("Updating!")
|
if betaUpdate {
|
||||||
downloadUpdate(res)
|
downloadUpdate(beta)
|
||||||
|
} else {
|
||||||
|
downloadUpdate(stable)
|
||||||
|
}
|
||||||
win.Close()
|
win.Close()
|
||||||
cmd := exec.Command("./LinuxPA")
|
cmd := exec.Command("./LinuxPA")
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
|
|||||||
Reference in New Issue
Block a user