Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 916f9cc79b | |||
| e4e5adaf13 | |||
| 7a2ebd533e | |||
| 2f0ca5418c | |||
| ce9d4aed23 | |||
| 712a5ab33d | |||
| 6723f933b4 | |||
| 016fc35745 | |||
| ba5e3510ec | |||
| 7e2d7ee14b | |||
| b20de4f1d6 | |||
| d2e91baa6b | |||
| a0f22e480b | |||
| 57f921c2cb | |||
| 55f897db46 | |||
| 3d9583281e | |||
| ec4d66f6b2 | |||
| c442ef5688 | |||
| 78d3723bf4 | |||
| 828b9f4cda | |||
| be64aa083f | |||
| 3111705cae | |||
| 868ae8f700 | |||
| 226e9d6210 | |||
| 56748f043e | |||
| 3d3239fe0a | |||
| 6e643b68ac | |||
| 539f33d25e | |||
| 4d3cb9f486 | |||
| a55c82483a | |||
| 9e9bb82025 | |||
| ea91d3cd80 | |||
| 2a0d53db09 | |||
| a0213d1886 | |||
| 695ce815d9 | |||
| 01556c1eb0 | |||
| d7410bb88f | |||
| bc63e6d10f | |||
| 0403825c3d | |||
| 0f1bb3fabd | |||
| 78c6842fab | |||
| dc1edbad3a | |||
| 6dd00c5f8f | |||
| e68337886f | |||
| 3b639f53fd | |||
| 3199ad88fd | |||
| a221d18d33 | |||
| a9eeb3bb1c | |||
| 844a282fd7 |
@@ -1,37 +1,51 @@
|
|||||||
# LinuxPA
|
# LinuxPA
|
||||||
|
|
||||||
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
||||||
|
|
||||||
# How to use
|
## How to use
|
||||||
Just double click on an app to launch it! If there are multiple executables, you can either select the specific executable, or if you just double click the app it'll launch the first linux executable (.sh script files have priority), but if one isn't found it launches the first executable in general.
|
|
||||||
|
|
||||||
# Apps:
|
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.
|
||||||
Both of the below places provide linux executables that don't need libs installed on the host system:
|
|
||||||
[AppImage](https://bintray.com/probono/AppImages)
|
## Apps
|
||||||
|
|
||||||
|
The below place provides linux executables that don't need libs installed on the host system:
|
||||||
|
[https://appimage.github.io/](https://appimage.github.io/)
|
||||||
|
|
||||||
|
## PortableApps.com Compatibility
|
||||||
|
|
||||||
# PortableApps.com Compatibility
|
|
||||||
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
||||||
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
|
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
|
||||||
|
|
||||||
# common.sh
|
## common.sh
|
||||||
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
|
||||||
|
|
||||||
# Simple App Setup
|
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.
|
||||||
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=`
|
|
||||||
|
|
||||||
# AppImage Support
|
## Simple App Setup
|
||||||
[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.
|
Because apps aren't natively formated in the PortableApps.com format, LinuxPA will look in the root directory for a AppInfo.ini (for basic info such as category and name) and appicon.png. If they aren't found, it looks where the appicon_\*.png and AppInfo.ini is in PortableApps format. You can set what the AppInfo.ini and appicon.png are from LinuxPA.
|
||||||
|
|
||||||
|
## AppImage Support
|
||||||
|
|
||||||
|
[AppImage Website](http://appimage.org)
|
||||||
|
I'm looking into improving AppImage support. As of 2.1.5.0 IF `unsquashfs` is in $PATH then some advanced AppImage support is available and it will automagically get the name and possibly the icon of it. I'm looking into better support, but it might be a while.
|
||||||
|
|
||||||
|
## USB mount
|
||||||
|
|
||||||
# USB mount
|
|
||||||
Unfortunately Linux, by default, doesn't support running executables off of FAT formated flash drives, requiring you to mount your drive with special mount arguments or format in a linux friendly format (such as EXT4). I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
Unfortunately Linux, by default, doesn't support running executables off of FAT formated flash drives, requiring you to mount your drive with special mount arguments or format in a linux friendly format (such as EXT4). I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
||||||
|
|
||||||
# Screenshots
|
## Screenshots
|
||||||
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
|
||||||
|
|
||||||
# TODO (Might be in order)
|
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshots are with the adapta gtk theme
|
||||||
1. MAKE IT BETTER
|
|
||||||
1. Add settings menu
|
## TODO (Might be in order)
|
||||||
1. Add updater for .AppImage files
|
|
||||||
1. Download .AppImage files (maybe)
|
1. MAKE IT BETTER
|
||||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
1. Integrate [goappimage](https://github.com/probonod/go-appimage) library for better AppImage integration.
|
||||||
1. Portable wine (Should be able to get a working version from PlayOnLinux, but I need to add a check to see if filesystem is EXT as Wine doesn't like filesystems w/o permission control)
|
1. Try to `chmod +x` executables if they don't have the permission
|
||||||
|
1. Manual update check
|
||||||
|
1. Better AppImage integrations (Specifically updating and better appimage downloading)
|
||||||
|
1. Get information (such as name and icon) directly from an appimage
|
||||||
|
1. Better appimage downloading (probably based around [AppImageHub](https://appimage.github.io/apps/))
|
||||||
|
1. Sandboxing support
|
||||||
|
1. Might be possible by packaging as an AppImage and providing Firejail, or simply just downloading it (like with Wine)
|
||||||
|
1. Check if all apps are closed when it closes and ask if you want to force stop the apps
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
"github.com/gotk3/gotk3/gdk"
|
||||||
"github.com/nelsam/gxui/math"
|
"github.com/gotk3/gotk3/gtk"
|
||||||
)
|
)
|
||||||
|
|
||||||
type app struct {
|
type app struct {
|
||||||
@@ -15,94 +17,56 @@ type app struct {
|
|||||||
appimg []string
|
appimg []string
|
||||||
lin []string
|
lin []string
|
||||||
ex []string
|
ex []string
|
||||||
icon gxui.Texture
|
icon *gdk.Pixbuf
|
||||||
dir string
|
dir string
|
||||||
ini *os.File
|
ini *os.File
|
||||||
|
wine bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type appExNode struct {
|
func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter {
|
||||||
ap app
|
it := store.Append(nil)
|
||||||
exInd int
|
scaled, _ := a.icon.ScaleSimple(32, 32, gdk.INTERP_HYPER)
|
||||||
}
|
store.SetValue(it, 0, scaled)
|
||||||
|
if portableHide {
|
||||||
func (a *appExNode) launch() {
|
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
|
||||||
if wine {
|
} else {
|
||||||
var cmd *exec.Cmd
|
store.SetValue(it, 1, a.name)
|
||||||
if !contains(a.ap.lin, a.ap.ex[a.exInd]) {
|
}
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[a.exInd]+"\"")
|
if len(a.ex) > 1 {
|
||||||
|
if wine {
|
||||||
|
for _, v := range a.ex {
|
||||||
|
i := store.Append(it)
|
||||||
|
store.SetValue(i, 1, v)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if comEnbld {
|
for _, v := range a.lin {
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
i := store.Append(it)
|
||||||
} else {
|
store.SetValue(i, 1, v)
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
}
|
||||||
var cmd *exec.Cmd
|
return it
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appExNode) Count() int {
|
func (a *app) launch() {
|
||||||
return 0
|
if len(a.ex) == 1 {
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) NodeAt(int) gxui.TreeNode {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) ItemIndex(gxui.AdapterItem) int {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) Item() gxui.AdapterItem {
|
|
||||||
if wine {
|
|
||||||
return a.ap.ex[a.exInd]
|
|
||||||
}
|
|
||||||
return a.ap.lin[a.exInd]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) Create(the gxui.Theme) gxui.Control {
|
|
||||||
box := the.CreateLinearLayout()
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
|
||||||
img := the.CreateImage()
|
|
||||||
img.SetTexture(a.ap.icon)
|
|
||||||
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
lbl := the.CreateLabel()
|
|
||||||
lbl.SetText(a.ap.ex[a.exInd])
|
|
||||||
box.AddChild(img)
|
|
||||||
box.AddChild(lbl)
|
|
||||||
box.OnDoubleClick(func(gxui.MouseEvent) {
|
|
||||||
a.launch()
|
|
||||||
})
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
type appNode struct {
|
|
||||||
ap app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) launch() {
|
|
||||||
if len(a.ap.ex) == 1 {
|
|
||||||
if wine {
|
if wine {
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
if !contains(a.ap.lin, a.ap.ex[0]) {
|
if !contains(a.lin, a.ex[0]) {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
if comEnbld {
|
if comEnbld {
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[0]), ".appimage") {
|
||||||
|
os.Mkdir(a.dir+"/"+a.ex[0]+".home", 0777)
|
||||||
|
os.Mkdir(a.dir+"/"+a.ex[0]+".config", 0777)
|
||||||
|
}
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
@@ -110,10 +74,14 @@ func (a *appNode) 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.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@@ -122,39 +90,51 @@ func (a *appNode) launch() {
|
|||||||
} else {
|
} else {
|
||||||
if wine {
|
if wine {
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
if len(a.ap.lin) == 0 {
|
if len(a.lin) == 0 {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var ind int
|
var ind int
|
||||||
for i, v := range a.ap.lin {
|
for i, v := range a.lin {
|
||||||
if strings.HasSuffix(v, ".sh") {
|
if strings.HasSuffix(v, ".sh") {
|
||||||
ind = i
|
ind = i
|
||||||
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.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Start()
|
cmd.Start()
|
||||||
} else {
|
} else {
|
||||||
if len(a.ap.lin) != 0 {
|
if len(a.lin) != 0 {
|
||||||
var ind int
|
var ind int
|
||||||
for i, v := range a.ap.lin {
|
for i, v := range a.lin {
|
||||||
if strings.HasSuffix(v, ".sh") {
|
if strings.HasSuffix(v, ".sh") {
|
||||||
ind = i
|
ind = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@@ -164,109 +144,176 @@ func (a *appNode) launch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appNode) Count() int {
|
func (a *app) launchSub(sub int) {
|
||||||
if wine {
|
if wine {
|
||||||
if len(a.ap.ex) > 1 {
|
var cmd *exec.Cmd
|
||||||
return len(a.ap.ex)
|
if !contains(a.lin, a.ex[sub]) {
|
||||||
}
|
if comEnbld {
|
||||||
return 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[sub]+"\"")
|
||||||
}
|
} else {
|
||||||
if len(a.ap.lin) > 1 {
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
|
||||||
return len(a.ap.lin)
|
}
|
||||||
}
|
} else {
|
||||||
return 0
|
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)
|
||||||
func (a *appNode) NodeAt(i int) gxui.TreeNode {
|
}
|
||||||
return &appExNode{ap: a.ap, exInd: i}
|
if comEnbld {
|
||||||
}
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
||||||
|
} else {
|
||||||
func (a *appNode) ItemIndex(item gxui.AdapterItem) int {
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
||||||
if wine {
|
|
||||||
for i, v := range a.ap.ex {
|
|
||||||
if v == item {
|
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
} else {
|
} else {
|
||||||
for i, v := range a.ap.lin {
|
var cmd *exec.Cmd
|
||||||
if v == item {
|
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[sub]), ".appimage") {
|
||||||
return i
|
os.Mkdir(a.dir+"/"+a.ex[sub]+".home", 0777)
|
||||||
}
|
os.Mkdir(a.dir+"/"+a.ex[sub]+".config", 0777)
|
||||||
}
|
}
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
}
|
}
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appNode) Item() gxui.AdapterItem {
|
func (a *app) edit(parent *gtk.Window, reload func()) {
|
||||||
return a.ap.name
|
tmp := *a
|
||||||
}
|
parent.SetSensitive(false)
|
||||||
|
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
func (a *appNode) Create(the gxui.Theme) gxui.Control {
|
win.Connect("destroy", func() {
|
||||||
box := the.CreateLinearLayout()
|
master = make(map[string][]app)
|
||||||
box.SetDirection(gxui.LeftToRight)
|
linmaster = make(map[string][]app)
|
||||||
box.SetPadding(math.CreateSpacing(2))
|
cats = make([]string, 0)
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
lin = make([]string, 0)
|
||||||
img := the.CreateImage()
|
setup()
|
||||||
if a.ap.icon != nil {
|
reload()
|
||||||
img.SetTexture(a.ap.icon)
|
parent.SetSensitive(true)
|
||||||
}
|
|
||||||
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
lbl := the.CreateLabel()
|
|
||||||
lbl.SetText(a.ap.name)
|
|
||||||
box.AddChild(img)
|
|
||||||
box.AddChild(lbl)
|
|
||||||
box.OnDoubleClick(func(gxui.MouseEvent) {
|
|
||||||
a.launch()
|
|
||||||
})
|
})
|
||||||
return box
|
win.SetDefaultSize(400, 135)
|
||||||
}
|
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
topLvl.SetMarginStart(10)
|
||||||
type catAdap struct {
|
topLvl.SetMarginEnd(10)
|
||||||
gxui.AdapterBase
|
topLvl.SetMarginTop(10)
|
||||||
cat string
|
topLvl.SetMarginBottom(10)
|
||||||
}
|
top, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||||
|
img, _ := gtk.ImageNewFromPixbuf(a.icon)
|
||||||
func (a *catAdap) setCat(cat string) {
|
imgBut, _ := gtk.ButtonNew()
|
||||||
a.cat = cat
|
imgBut.SetImage(img)
|
||||||
a.DataChanged(false)
|
imgBut.SetSizeRequest(100, 100)
|
||||||
}
|
imgBut.Connect("clicked", func() {
|
||||||
|
fil, _ := gtk.FileChooserDialogNewWith1Button("Select Icon", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_ACCEPT)
|
||||||
func (a *catAdap) refresh() {
|
filter, _ := gtk.FileFilterNew()
|
||||||
a.DataChanged(false)
|
filter.AddPixbufFormats()
|
||||||
}
|
filter.SetName("Supported Pictures")
|
||||||
|
fil.AddFilter(filter)
|
||||||
func (a *catAdap) Count() int {
|
but, _ := fil.AddButton("Cancel", gtk.RESPONSE_CANCEL)
|
||||||
if wine {
|
but.Connect("clicked", func() {
|
||||||
return len(master[a.cat])
|
fil.Close()
|
||||||
}
|
})
|
||||||
return len(linmaster[a.cat])
|
resp := fil.Run()
|
||||||
}
|
if resp == gtk.RESPONSE_ACCEPT {
|
||||||
|
filename := fil.GetFilename()
|
||||||
func (a *catAdap) NodeAt(i int) gxui.TreeNode {
|
_, err := os.Open(filename)
|
||||||
if wine {
|
if err != nil {
|
||||||
return &appNode{ap: master[a.cat][i]}
|
fmt.Println(err)
|
||||||
}
|
return
|
||||||
return &appNode{ap: linmaster[a.cat][i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) Size(gxui.Theme) math.Size {
|
|
||||||
return math.Size{H: 34, W: math.MaxSize.W}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
if wine {
|
|
||||||
for i, v := range master[a.cat] {
|
|
||||||
if v.name == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i, v := range linmaster[a.cat] {
|
|
||||||
if v.name == item {
|
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
|
pix, _ := gdk.PixbufNewFromFileAtSize(filename, 32, 32)
|
||||||
|
tmp.icon = pix
|
||||||
|
img.SetFromPixbuf(pix)
|
||||||
|
fil.Close()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
topRt, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
nameLbl, _ := gtk.LabelNew("Name:")
|
||||||
|
nameLbl.SetHAlign(gtk.ALIGN_START)
|
||||||
|
txtgtbl, _ := gtk.TextTagTableNew()
|
||||||
|
txtBuf, _ := gtk.TextBufferNew(txtgtbl)
|
||||||
|
nameTxt, _ := gtk.TextViewNewWithBuffer(txtBuf)
|
||||||
|
nameTxt.SetAcceptsTab(false)
|
||||||
|
nameTxt.SetWrapMode(gtk.WRAP_CHAR)
|
||||||
|
nameTxt.SetPixelsBelowLines(5)
|
||||||
|
nameTxt.SetHExpand(true)
|
||||||
|
nameTxt.SetVExpand(false)
|
||||||
|
nameTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
||||||
|
nameShow := tmp.name
|
||||||
|
if tmp.wine {
|
||||||
|
nameShow = strings.TrimSuffix(nameShow, " (Wine)")
|
||||||
}
|
}
|
||||||
return -1
|
txtBuf.SetText(nameShow)
|
||||||
|
vScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
hScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
nameScr, _ := gtk.ScrolledWindowNew(hScrollName, vScrollName)
|
||||||
|
nameScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
||||||
|
nameScr.SetSizeRequest(300, 25)
|
||||||
|
nameScr.SetVExpand(false)
|
||||||
|
nameScr.Add(nameTxt)
|
||||||
|
catLbl, _ := gtk.LabelNew("Category:")
|
||||||
|
catLbl.SetHAlign(gtk.ALIGN_START)
|
||||||
|
catTbl, _ := gtk.TextTagTableNew()
|
||||||
|
catBuf, _ := gtk.TextBufferNew(catTbl)
|
||||||
|
catTxt, _ := gtk.TextViewNewWithBuffer(catBuf)
|
||||||
|
catBuf.SetText(tmp.cat)
|
||||||
|
catTxt.SetAcceptsTab(false)
|
||||||
|
catTxt.SetWrapMode(gtk.WRAP_CHAR)
|
||||||
|
catTxt.SetPixelsBelowLines(5)
|
||||||
|
catTxt.SetHExpand(true)
|
||||||
|
catTxt.SetVExpand(false)
|
||||||
|
catTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
||||||
|
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
catScr, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
||||||
|
catScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
||||||
|
catScr.SetSizeRequest(300, 25)
|
||||||
|
catScr.SetVExpand(false)
|
||||||
|
catScr.Add(catTxt)
|
||||||
|
topRt.Add(nameLbl)
|
||||||
|
topRt.Add(nameScr)
|
||||||
|
topRt.Add(catLbl)
|
||||||
|
topRt.Add(catScr)
|
||||||
|
top.Add(imgBut)
|
||||||
|
top.Add(topRt)
|
||||||
|
bot, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||||
|
sv, _ := gtk.ButtonNewWithLabel("Save")
|
||||||
|
sv.Connect("clicked", func() {
|
||||||
|
tmp.name, _ = txtBuf.GetText(txtBuf.GetStartIter(), txtBuf.GetEndIter(), true)
|
||||||
|
tmp.cat, _ = catBuf.GetText(catBuf.GetStartIter(), catBuf.GetEndIter(), true)
|
||||||
|
tmp.makeIni()
|
||||||
|
os.Remove(a.dir + "/appicon.png")
|
||||||
|
tmp.icon.SavePNG(a.dir+"/appicon.png", 0)
|
||||||
|
win.Close()
|
||||||
|
})
|
||||||
|
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||||
|
cnl.Connect("clicked", func() {
|
||||||
|
win.Close()
|
||||||
|
})
|
||||||
|
bot.PackEnd(sv, false, false, 0)
|
||||||
|
bot.PackEnd(cnl, false, false, 0)
|
||||||
|
topLvl.Add(top)
|
||||||
|
topLvl.Add(bot)
|
||||||
|
win.Add(topLvl)
|
||||||
|
win.ShowAll()
|
||||||
|
win.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *app) makeIni() {
|
||||||
|
os.Remove(a.dir + "/appinfo.ini")
|
||||||
|
fil, err := os.Create(a.dir + "/appinfo.ini")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ini := "[General]\n"
|
||||||
|
ini += "Category=" + a.cat + "\n"
|
||||||
|
ini += "Name=" + a.name + "\n"
|
||||||
|
wrt := bufio.NewWriter(fil)
|
||||||
|
wrt.WriteString(ini)
|
||||||
|
wrt.Flush()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
module github.com/CalebQ42/LinuxPA
|
||||||
|
|
||||||
|
go 1.23.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/CalebQ42/GoAppImage v0.5.0
|
||||||
|
github.com/gotk3/gotk3 v0.6.4
|
||||||
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/adrg/xdg v0.5.0 // indirect
|
||||||
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
|
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.10 // indirect
|
||||||
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
|
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||||
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
|
go.lsp.dev/uri v0.3.0 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
github.com/CalebQ42/GoAppImage v0.5.0 h1:znoKNXtliH754tS9sYwyOIg/0wFDjFN5Twc7PAh1rSM=
|
||||||
|
github.com/CalebQ42/GoAppImage v0.5.0/go.mod h1:qHudJKAn/dlkNWNnH4h1YKXp29EZ7Bppsn7sNP2HuvU=
|
||||||
|
github.com/adrg/xdg v0.2.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
||||||
|
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
|
||||||
|
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
|
||||||
|
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
|
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.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||||
|
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||||
|
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||||
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gotk3/gotk3 v0.6.4 h1:5ur/PRr86PwCG8eSj98D1eXvhrNNK6GILS2zq779dCg=
|
||||||
|
github.com/gotk3/gotk3 v0.6.4/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
||||||
|
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.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
|
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
|
||||||
|
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
|
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||||
|
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||||
|
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
|
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||||
|
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
|
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/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
|
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
|
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||||
|
github.com/ulikunitz/xz v0.5.12/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/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
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/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -1,76 +1,54 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
"github.com/gotk3/gotk3/gtk"
|
||||||
"github.com/nelsam/gxui/drivers/gl"
|
|
||||||
"github.com/nelsam/gxui/themes/dark"
|
|
||||||
"github.com/nelsam/gxui/themes/light"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "1.1.0.0"
|
version = "2.2.0.0"
|
||||||
defIni = "[basic]\ntheme=dk"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dr gxui.Driver
|
|
||||||
th gxui.Theme
|
|
||||||
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
|
||||||
darkTheme = true
|
populated bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
updated := false
|
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)
|
||||||
stat := versionDL()
|
master = make(map[string][]app)
|
||||||
if stat {
|
linmaster = make(map[string][]app)
|
||||||
res := getVersionFileInfo()
|
uiStart(*forced)
|
||||||
if res != "Error!" {
|
|
||||||
stat = checkForUpdate(res)
|
|
||||||
if stat {
|
|
||||||
downloadUpdate(res)
|
|
||||||
updated = true
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed DL")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed Version File Info")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed Version DL")
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
cmd := exec.Command("./LinuxPA")
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Start()
|
|
||||||
fmt.Println("updated!")
|
|
||||||
} else {
|
|
||||||
master = make(map[string][]app)
|
|
||||||
linmaster = make(map[string][]app)
|
|
||||||
gl.StartDriver(appMain)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func appMain(dri gxui.Driver) {
|
func uiStart(forced bool) {
|
||||||
dr = dri
|
gtk.Init(nil)
|
||||||
setup()
|
setup()
|
||||||
if darkTheme {
|
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
th = dark.CreateTheme(dr)
|
if err != nil {
|
||||||
} else {
|
fmt.Println("Window not created", err)
|
||||||
th = light.CreateTheme(dr)
|
|
||||||
}
|
}
|
||||||
th = dark.CreateTheme(dr)
|
win.SetTitle("LinuxPA")
|
||||||
ui()
|
win.Connect("destroy", func() {
|
||||||
|
savePrefs()
|
||||||
|
gtk.MainQuit()
|
||||||
|
})
|
||||||
|
win.SetDefaultSize(500, 500)
|
||||||
|
win.SetPosition(gtk.WIN_POS_CENTER)
|
||||||
|
ui(win)
|
||||||
|
win.ShowAll()
|
||||||
|
win.Show()
|
||||||
|
update(win, forced)
|
||||||
|
gtk.Main()
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(arr []string, str string) bool {
|
func contains(arr []string, str string) bool {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+206
@@ -0,0 +1,206 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/glib"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
commonHelp = "The common.sh is run before every app is launched and allows you to set variables such as $HOME. For directories, ALWAYS start the directory with $PWD which points to the directory where LinuxPA is. To allow for greater customization and isolation, you can use the $FILENAME variable which is the filename of the executable you're using and the $APPNAME variable which is the name of the app being lanched."
|
||||||
|
)
|
||||||
|
|
||||||
|
func settingsUI(parent *gtk.Window, onExit func()) {
|
||||||
|
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
win.SetTransientFor(parent)
|
||||||
|
parent.SetSensitive(false)
|
||||||
|
win.SetDefaultSize(600, 300)
|
||||||
|
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
win.Connect("destroy", func() {
|
||||||
|
savePrefs()
|
||||||
|
parent.SetSensitive(true)
|
||||||
|
onExit()
|
||||||
|
})
|
||||||
|
comTagTbl, _ := gtk.TextTagTableNew()
|
||||||
|
comBuf, _ := gtk.TextBufferNew(comTagTbl)
|
||||||
|
ntbk, _ := gtk.NotebookNew()
|
||||||
|
gnrl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
gnrl.SetMarginStart(10)
|
||||||
|
gnrl.SetMarginEnd(10)
|
||||||
|
gnrl.SetMarginTop(10)
|
||||||
|
gnrl.SetMarginBottom(10)
|
||||||
|
dlWine, _ := gtk.ButtonNewWithLabel("Download Wine")
|
||||||
|
wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)")
|
||||||
|
wineLbl, _ := gtk.LabelNew("PortableApps/LinuxPACom/Wine present")
|
||||||
|
dlWine.Connect("clicked", func() {
|
||||||
|
cb := make(chan bool)
|
||||||
|
downloadWine(win, cb)
|
||||||
|
go func() {
|
||||||
|
v := <-cb
|
||||||
|
if v {
|
||||||
|
setupTxt(comBuf)
|
||||||
|
wineLbl.Show()
|
||||||
|
}
|
||||||
|
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
||||||
|
if _, errd := exec.LookPath("wine"); errd == nil {
|
||||||
|
wineAvail = true
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
wineAvail = true
|
||||||
|
}
|
||||||
|
glib.IdleAdd(func() {
|
||||||
|
if !wineAvail {
|
||||||
|
wineCheck.SetSensitive(false)
|
||||||
|
wineCheck.SetTooltipText("Download wine to run windows apps")
|
||||||
|
} else {
|
||||||
|
wineCheck.SetSensitive(true)
|
||||||
|
wineCheck.SetTooltipText("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
if !comEnbld {
|
||||||
|
dlWine.SetSensitive(false)
|
||||||
|
dlWine.SetTooltipText("common.sh needed")
|
||||||
|
}
|
||||||
|
pthdCheck, _ := gtk.CheckButtonNewWithLabel("Hide \"Portable\" from app name")
|
||||||
|
pthdCheck.Connect("toggled", func() {
|
||||||
|
portableHide = pthdCheck.GetActive()
|
||||||
|
master = make(map[string][]app)
|
||||||
|
linmaster = make(map[string][]app)
|
||||||
|
cats = make([]string, 0)
|
||||||
|
lin = make([]string, 0)
|
||||||
|
setup()
|
||||||
|
})
|
||||||
|
pthdCheck.SetActive(portableHide)
|
||||||
|
if !wineAvail {
|
||||||
|
wineCheck.SetSensitive(false)
|
||||||
|
wineCheck.SetTooltipText("Download wine to run windows apps")
|
||||||
|
}
|
||||||
|
wineCheck.SetActive(wine)
|
||||||
|
wineCheck.Connect("toggled", func() {
|
||||||
|
wine = wineCheck.GetActive()
|
||||||
|
})
|
||||||
|
versCheck, _ := gtk.CheckButtonNewWithLabel("Only show newest app version in downloads (A bit iffy ATM)")
|
||||||
|
versCheck.SetActive(versionNewest)
|
||||||
|
versCheck.Connect("toggled", func() {
|
||||||
|
versionNewest = versCheck.GetActive()
|
||||||
|
})
|
||||||
|
paDirsCheck, _ := gtk.CheckButtonNewWithLabel("Create .home and .config directories for AppImages")
|
||||||
|
paDirsCheck.SetActive(paDirs)
|
||||||
|
paDirsCheck.Connect("toggled", func() {
|
||||||
|
paDirs = paDirsCheck.GetActive()
|
||||||
|
})
|
||||||
|
betaCheck, _ := gtk.CheckButtonNewWithLabel("Update to beta releases")
|
||||||
|
gnrl.Add(wineLbl)
|
||||||
|
gnrl.Add(dlWine)
|
||||||
|
gnrl.Add(pthdCheck)
|
||||||
|
gnrl.Add(wineCheck)
|
||||||
|
gnrl.Add(versCheck)
|
||||||
|
gnrl.Add(paDirsCheck)
|
||||||
|
gnrl.Add(betaCheck)
|
||||||
|
ntbk.AppendPage(gnrl, getLabel("General"))
|
||||||
|
com, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
com.SetMarginStart(10)
|
||||||
|
com.SetMarginEnd(10)
|
||||||
|
com.SetMarginTop(10)
|
||||||
|
com.SetMarginBottom(10)
|
||||||
|
comEdit, _ := gtk.TextViewNewWithBuffer(comBuf)
|
||||||
|
comEdit.SetVExpand(true)
|
||||||
|
comEdit.SetHExpand(true)
|
||||||
|
vScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
hScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
comScrl, _ := gtk.ScrolledWindowNew(hScroll, vScroll)
|
||||||
|
comScrl.Add(comEdit)
|
||||||
|
svBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||||
|
sv, _ := gtk.ButtonNewWithLabel("Save")
|
||||||
|
sv.Connect("clicked", func() {
|
||||||
|
beg, end := comBuf.GetBounds()
|
||||||
|
txt, _ := comBuf.GetText(beg, end, true)
|
||||||
|
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte(txt), 0777)
|
||||||
|
})
|
||||||
|
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||||
|
cnl.Connect("clicked", func() {
|
||||||
|
setupTxt(comBuf)
|
||||||
|
})
|
||||||
|
info, _ := gtk.ButtonNewWithLabel("Info")
|
||||||
|
info.Connect("clicked", func() {
|
||||||
|
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
infoBox.SetTransientFor(parent)
|
||||||
|
infoBox.SetDefaultSize(300, 80)
|
||||||
|
infoBox.SetName("common.sh info")
|
||||||
|
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
infolbl, _ := gtk.LabelNew(commonHelp)
|
||||||
|
infolbl.SetLineWrap(true)
|
||||||
|
infolbl.SetSizeRequest(200, 50)
|
||||||
|
box.Add(infolbl)
|
||||||
|
infoBox.Add(box)
|
||||||
|
infoBox.ShowAll()
|
||||||
|
infoBox.Show()
|
||||||
|
})
|
||||||
|
svBox.Add(sv)
|
||||||
|
svBox.Add(cnl)
|
||||||
|
svBox.Add(info)
|
||||||
|
com.Add(comScrl)
|
||||||
|
com.Add(svBox)
|
||||||
|
ntbk.AppendPage(com, getLabel("common.sh"))
|
||||||
|
win.Add(ntbk)
|
||||||
|
win.ShowAll()
|
||||||
|
if !comEnbld {
|
||||||
|
comScrl.Hide()
|
||||||
|
svBox.Hide()
|
||||||
|
mkCom, _ := gtk.ButtonNewWithLabel("Create common.sh")
|
||||||
|
mkCom.Connect("clicked", func() {
|
||||||
|
err := ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte("export HOME=$PWD/PortableApps/LinuxPACom/Home"), 0777)
|
||||||
|
if err == nil {
|
||||||
|
mkCom.Hide()
|
||||||
|
comScrl.Show()
|
||||||
|
svBox.Show()
|
||||||
|
setupTxt(comBuf)
|
||||||
|
comEnbld = true
|
||||||
|
dlWine.SetSensitive(true)
|
||||||
|
dlWine.SetTooltipText("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
in, _ := gtk.ButtonNewWithLabel("Info")
|
||||||
|
in.Connect("clicked", func() {
|
||||||
|
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
infoBox.SetTransientFor(parent)
|
||||||
|
infoBox.SetDefaultSize(300, 80)
|
||||||
|
infoBox.SetName("common.sh info")
|
||||||
|
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
infolbl, _ := gtk.LabelNew(commonHelp)
|
||||||
|
infolbl.SetLineWrap(true)
|
||||||
|
infolbl.SetSizeRequest(200, 50)
|
||||||
|
box.Add(infolbl)
|
||||||
|
infoBox.Add(box)
|
||||||
|
infoBox.ShowAll()
|
||||||
|
infoBox.Show()
|
||||||
|
})
|
||||||
|
mkCom.Show()
|
||||||
|
com.Add(mkCom)
|
||||||
|
com.Add(in)
|
||||||
|
} else {
|
||||||
|
setupTxt(comBuf)
|
||||||
|
}
|
||||||
|
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); err != nil && os.IsNotExist(err) {
|
||||||
|
wineLbl.Hide()
|
||||||
|
}
|
||||||
|
win.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTxt(buf *gtk.TextBuffer) {
|
||||||
|
fil, _ := os.Open("PortableApps/LinuxPACom/common.sh")
|
||||||
|
btys, _ := ioutil.ReadAll(fil)
|
||||||
|
buf.SetText(string(btys))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLabel(name string) *gtk.Label {
|
||||||
|
lbl, _ := gtk.LabelNew(name)
|
||||||
|
return lbl
|
||||||
|
}
|
||||||
@@ -2,21 +2,30 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
_ "image/png"
|
_ "image/png"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
goappimage "github.com/CalebQ42/GoAppImage"
|
||||||
|
"github.com/gotk3/gotk3/gdk"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ()
|
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
|
loadPrefs()
|
||||||
|
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
||||||
|
if _, errd := exec.LookPath("wine"); errd == nil {
|
||||||
|
wineAvail = true
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
wineAvail = true
|
||||||
|
}
|
||||||
|
if !wineAvail {
|
||||||
|
wine = false
|
||||||
|
}
|
||||||
PortableAppsFold, err := os.Open("PortableApps")
|
PortableAppsFold, err := os.Open("PortableApps")
|
||||||
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
||||||
os.Mkdir("PortableApps", 0777)
|
os.Mkdir("PortableApps", 0777)
|
||||||
@@ -28,34 +37,10 @@ func setup() {
|
|||||||
if _, err = os.Open("PortableApps/LinuxPACom"); err != nil {
|
if _, err = os.Open("PortableApps/LinuxPACom"); err != nil {
|
||||||
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
||||||
}
|
}
|
||||||
fmt.Println(err)
|
|
||||||
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
|
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
comEnbld = true
|
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)
|
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
|
||||||
sort.Strings(PAFolds)
|
sort.Strings(PAFolds)
|
||||||
for _, v := range PAFolds {
|
for _, v := range PAFolds {
|
||||||
@@ -80,32 +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"
|
|
||||||
}
|
|
||||||
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)
|
||||||
@@ -127,7 +101,90 @@ func processApp(fold string) (out app) {
|
|||||||
}
|
}
|
||||||
if len(out.lin) == 0 {
|
if len(out.lin) == 0 {
|
||||||
out.name += " (Wine)"
|
out.name += " (Wine)"
|
||||||
|
out.wine = true
|
||||||
}
|
}
|
||||||
|
out.icon = getIcon(fold)
|
||||||
|
out.ini = findInfo(fold)
|
||||||
|
if out.ini != nil {
|
||||||
|
out.name = getName(out.ini)
|
||||||
|
out.cat = getCat(out.ini)
|
||||||
|
}
|
||||||
|
if len(out.appimg) > 0 && out.name == "" && out.cat == "" && out.icon == nil {
|
||||||
|
os.Mkdir(out.dir+"/.appimageconfig", 0777)
|
||||||
|
ai := goappimage.NewAppImage(out.dir + "/" + out.appimg[0])
|
||||||
|
fil, err := os.Open(out.dir + "/.appimageconfig/the.md5")
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
|
||||||
|
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
|
||||||
|
appdirs, _ := appimageconfig.Readdirnames(-1)
|
||||||
|
for _, dirs := range appdirs {
|
||||||
|
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
|
||||||
|
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
|
||||||
|
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
|
||||||
|
name, cat, icon := extractDesktopInfo(desk)
|
||||||
|
if out.name == "" {
|
||||||
|
out.name = name
|
||||||
|
}
|
||||||
|
if out.cat == "" {
|
||||||
|
out.cat = cat
|
||||||
|
}
|
||||||
|
if out.icon == nil {
|
||||||
|
it, _ := gtk.IconThemeGetDefault()
|
||||||
|
out.icon, err = it.LoadIcon(icon, 64, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
|
||||||
|
}
|
||||||
|
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
|
||||||
|
wrtr := bufio.NewWriter(fil)
|
||||||
|
wrtr.WriteString(ai.Md5)
|
||||||
|
wrtr.Flush()
|
||||||
|
} else {
|
||||||
|
rdr := bufio.NewReader(fil)
|
||||||
|
filMd, _, _ := rdr.ReadLine()
|
||||||
|
oldMd := string(filMd)
|
||||||
|
if oldMd != ai.Md5 {
|
||||||
|
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
|
||||||
|
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
|
||||||
|
appdirs, _ := appimageconfig.Readdirnames(-1)
|
||||||
|
for _, dirs := range appdirs {
|
||||||
|
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
|
||||||
|
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
|
||||||
|
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Remove(out.dir + "/.appimageconfig/the.md5")
|
||||||
|
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
|
||||||
|
wrtr := bufio.NewWriter(fil)
|
||||||
|
wrtr.WriteString(ai.Md5)
|
||||||
|
wrtr.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
|
||||||
|
name, cat, icon := extractDesktopInfo(desk)
|
||||||
|
if out.name == "" {
|
||||||
|
out.name = name
|
||||||
|
}
|
||||||
|
if out.cat == "" {
|
||||||
|
out.cat = cat
|
||||||
|
}
|
||||||
|
if out.icon == nil {
|
||||||
|
it, _ := gtk.IconThemeGetDefault()
|
||||||
|
out.icon, err = it.LoadIcon(icon, 32, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if out.name == "" {
|
||||||
|
out.name = strings.TrimPrefix(fold, "PortableApps/")
|
||||||
|
}
|
||||||
|
if out.cat == "" {
|
||||||
|
out.cat = "Other"
|
||||||
|
}
|
||||||
|
if portableHide {
|
||||||
|
out.name = strings.TrimSuffix(out.name, "Portable")
|
||||||
|
}
|
||||||
|
out.name = strings.TrimSpace(out.name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,12 +195,39 @@ func getCat(ini *os.File) string {
|
|||||||
if strings.HasPrefix(string(line), "Category=") {
|
if strings.HasPrefix(string(line), "Category=") {
|
||||||
ret = strings.TrimPrefix(string(line), "Category=")
|
ret = strings.TrimPrefix(string(line), "Category=")
|
||||||
break
|
break
|
||||||
|
} else if strings.HasPrefix(string(line), "category=") {
|
||||||
|
ret = strings.TrimPrefix(string(line), "category=")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rdr.Reset(ini)
|
rdr.Reset(ini)
|
||||||
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
|
||||||
@@ -151,15 +235,20 @@ func getName(ini *os.File) string {
|
|||||||
if strings.HasPrefix(string(line), "Name=") {
|
if strings.HasPrefix(string(line), "Name=") {
|
||||||
ret = strings.TrimPrefix(string(line), "Name=")
|
ret = strings.TrimPrefix(string(line), "Name=")
|
||||||
break
|
break
|
||||||
|
} else if strings.HasPrefix(string(line), "name=") {
|
||||||
|
ret = strings.TrimPrefix(string(line), "name=")
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rdr.Reset(ini)
|
rdr.Reset(ini)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIcon(fold string) gxui.Texture {
|
func getIcon(fold string) *gdk.Pixbuf {
|
||||||
var pic *os.File
|
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 {
|
||||||
@@ -175,24 +264,22 @@ func getIcon(fold string) gxui.Texture {
|
|||||||
} else {
|
} else {
|
||||||
ind = sort.SearchStrings(pics, "appicon_32.png")
|
ind = sort.SearchStrings(pics, "appicon_32.png")
|
||||||
}
|
}
|
||||||
pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind])
|
pic = fold + "/App/AppInfo/" + pics[ind]
|
||||||
}
|
}
|
||||||
} else if fi, err := os.Open(fold + "/appicon.png"); err == nil {
|
|
||||||
pic = fi
|
|
||||||
} else {
|
} else {
|
||||||
return nil
|
img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON)
|
||||||
|
buf := img.GetPixbuf()
|
||||||
|
return buf
|
||||||
}
|
}
|
||||||
img, _, err := image.Decode(pic)
|
img, _ := gtk.ImageNewFromFile(pic)
|
||||||
if err != nil {
|
buf, _ := img.GetPixbuf().ScaleSimple(32, 32, gdk.INTERP_BILINEAR)
|
||||||
return nil
|
return buf
|
||||||
}
|
|
||||||
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 {
|
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)
|
||||||
@@ -203,8 +290,5 @@ func findInfo(fold string) *os.File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
|
||||||
return fi
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
-65
@@ -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 +1,174 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"github.com/gotk3/gotk3/glib"
|
||||||
"os/exec"
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
"github.com/pkg/browser"
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ui() {
|
func ui(win *gtk.Window) {
|
||||||
catListAdap := &StrList{}
|
ls := getCatRows()
|
||||||
appListAdap := &catAdap{}
|
var treeApps []*gtk.TreeIter
|
||||||
catListAdap.SetStrings(lin)
|
header, _ := gtk.HeaderBarNew()
|
||||||
win := th.CreateWindow(500, 500, "LinuxPA")
|
header.SetShowCloseButton(true)
|
||||||
top := th.CreateLinearLayout()
|
header.SetTitle("LinuxPA")
|
||||||
top.SetDirection(gxui.BottomToTop)
|
header.SetSubtitle("PortableApps.com type launcher")
|
||||||
splBox := th.CreateLinearLayout()
|
settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||||
spl := th.CreateSplitterLayout()
|
settings.SetTooltipText("Settings")
|
||||||
spl.SetOrientation(gxui.Horizontal)
|
dnl, _ := gtk.ButtonNewFromIconName("emblem-downloads", gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||||
catList := th.CreateList()
|
dnl.SetTooltipText("Download Apps")
|
||||||
catList.SetAdapter(catListAdap)
|
header.PackStart(settings)
|
||||||
catList.OnSelectionChanged(func(it gxui.AdapterItem) {
|
header.PackEnd(dnl)
|
||||||
appListAdap.setCat(it.(string))
|
win.SetTitlebar(header)
|
||||||
})
|
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
||||||
appList := th.CreateTree()
|
lrBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||||
appList.SetAdapter(appListAdap)
|
catList, _ := gtk.ListBoxNew()
|
||||||
spl.AddChild(catList)
|
catList.SetActivateOnSingleClick(true)
|
||||||
spl.AddChild(appList)
|
store, _ := gtk.TreeStoreNew(glib.TYPE_OBJECT, glib.TYPE_STRING)
|
||||||
splBox.AddChild(spl)
|
appsList, _ := gtk.TreeViewNewWithModel(store)
|
||||||
butBox := th.CreateLinearLayout()
|
render, _ := gtk.CellRendererPixbufNew()
|
||||||
butBox.SetDirection(gxui.LeftToRight)
|
pixColumn, _ := gtk.TreeViewColumnNewWithAttribute("", render, "pixbuf", 0)
|
||||||
if _, err := exec.LookPath("wine"); err == nil {
|
txtRender, _ := gtk.CellRendererTextNew()
|
||||||
wineBut := th.CreateButton()
|
txtColumn, _ := gtk.TreeViewColumnNewWithAttribute("", txtRender, "text", 1)
|
||||||
wineBut.SetType(gxui.ToggleButton)
|
appsList.AppendColumn(pixColumn)
|
||||||
wineBut.SetChecked(wine)
|
appsList.AppendColumn(txtColumn)
|
||||||
wineBut.SetText("Show Windows Apps")
|
appsList.SetHeadersVisible(false)
|
||||||
wineBut.OnClick(func(gxui.MouseEvent) {
|
catList.SetHExpand(true)
|
||||||
wine = wineBut.IsChecked()
|
catList.SetVExpand(true)
|
||||||
appListAdap.refresh()
|
appsList.SetHExpand(true)
|
||||||
if wineBut.IsChecked() {
|
appsList.SetVExpand(true)
|
||||||
catListAdap.SetStrings(cats)
|
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
wineBut.SetText("Hide Windows Apps")
|
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
vScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
hScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
||||||
|
catScrl, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
||||||
|
catScrl.Add(catList)
|
||||||
|
catScrl.SetSizeRequest(170, 500)
|
||||||
|
appScrl, _ := gtk.ScrolledWindowNew(hScrollApp, vScrollApp)
|
||||||
|
appScrl.Add(appsList)
|
||||||
|
appScrl.SetSizeRequest(300, 500)
|
||||||
|
lrBox.Add(catScrl)
|
||||||
|
lrBox.Add(appScrl)
|
||||||
|
botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2)
|
||||||
|
botBox.SetMarginStart(10)
|
||||||
|
botBox.SetMarginEnd(10)
|
||||||
|
botBox.SetMarginTop(10)
|
||||||
|
botBox.SetMarginBottom(10)
|
||||||
|
edit, _ := gtk.ButtonNewWithLabel("Edit App..")
|
||||||
|
edit.Connect("clicked", func() {
|
||||||
|
selec, _ := appsList.GetSelection()
|
||||||
|
_, it, ok := selec.GetSelected()
|
||||||
|
if ok {
|
||||||
|
pth, _ := store.GetPath(it)
|
||||||
|
ind := pth.GetIndices()
|
||||||
|
if wine {
|
||||||
|
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
|
appLnch.edit(win, func() {
|
||||||
|
store.Clear()
|
||||||
|
for i := range ls {
|
||||||
|
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||||
|
}
|
||||||
|
ls = getCatRows()
|
||||||
|
for i, v := range ls {
|
||||||
|
catList.Insert(v, i)
|
||||||
|
}
|
||||||
|
catList.ShowAll()
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
catListAdap.SetStrings(lin)
|
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
wineBut.SetText("Show Windows Apps")
|
appLnch.edit(win, func() {
|
||||||
|
store.Clear()
|
||||||
|
for i := range ls {
|
||||||
|
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||||
|
}
|
||||||
|
ls = getCatRows()
|
||||||
|
for i, v := range ls {
|
||||||
|
catList.Insert(v, i)
|
||||||
|
}
|
||||||
|
catList.ShowAll()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
_, err := os.Open("Start.exe")
|
|
||||||
if err == nil {
|
|
||||||
pa := th.CreateButton()
|
|
||||||
pa.SetText("Open PortableApps Launcher")
|
|
||||||
pa.OnClick(func(gxui.MouseEvent) {
|
|
||||||
cmd := exec.Command("wine", "Start.exe")
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
})
|
|
||||||
butBox.AddChild(pa)
|
|
||||||
}
|
}
|
||||||
butBox.AddChild(wineBut)
|
})
|
||||||
|
botBox.PackEnd(edit, false, false, 0)
|
||||||
|
topLvl.Add(lrBox)
|
||||||
|
topLvl.PackEnd(botBox, false, true, 0)
|
||||||
|
win.Add(topLvl)
|
||||||
|
for _, v := range ls {
|
||||||
|
catList.Add(v)
|
||||||
}
|
}
|
||||||
top.AddChild(butBox)
|
catList.Connect("row-selected", func() {
|
||||||
top.AddChild(splBox)
|
store.Clear()
|
||||||
win.AddChild(top)
|
if catList.GetSelectedRow().GetIndex() >= 0 {
|
||||||
win.OnClose(dr.Terminate)
|
treeApps = make([]*gtk.TreeIter, 0)
|
||||||
|
if wine {
|
||||||
|
apps := master[cats[catList.GetSelectedRow().GetIndex()]]
|
||||||
|
for _, v := range apps {
|
||||||
|
treeApps = append(treeApps, v.getTreeIter(store))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
apps := linmaster[lin[catList.GetSelectedRow().GetIndex()]]
|
||||||
|
for _, v := range apps {
|
||||||
|
treeApps = append(treeApps, v.getTreeIter(store))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
appsList.Connect("row-activated", func() {
|
||||||
|
selec, _ := appsList.GetSelection()
|
||||||
|
_, it, ok := selec.GetSelected()
|
||||||
|
if ok {
|
||||||
|
pth, _ := store.GetPath(it)
|
||||||
|
ind := pth.GetIndices()
|
||||||
|
if len(ind) == 1 {
|
||||||
|
if wine {
|
||||||
|
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
|
appLnch.launch()
|
||||||
|
} else {
|
||||||
|
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
|
appLnch.launch()
|
||||||
|
}
|
||||||
|
} else if len(ind) == 2 {
|
||||||
|
if wine {
|
||||||
|
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
|
appLnch.launchSub(ind[1])
|
||||||
|
} else {
|
||||||
|
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
||||||
|
appLnch.launchSub(ind[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dnl.Connect("clicked", func() {
|
||||||
|
//TODO: detect if a webbrowser app is available and use that instead
|
||||||
|
browser.OpenURL("https://appimage.github.io/apps/")
|
||||||
|
})
|
||||||
|
settings.Connect("clicked", func() {
|
||||||
|
settingsUI(win, func() {
|
||||||
|
store.Clear()
|
||||||
|
for i := range ls {
|
||||||
|
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
||||||
|
}
|
||||||
|
ls = getCatRows()
|
||||||
|
for i, v := range ls {
|
||||||
|
catList.Insert(v, i)
|
||||||
|
}
|
||||||
|
catList.ShowAll()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCatRows() (out []*gtk.Label) {
|
||||||
|
if wine {
|
||||||
|
for _, v := range cats {
|
||||||
|
txt, _ := gtk.LabelNew(v)
|
||||||
|
out = append(out, txt)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, v := range lin {
|
||||||
|
txt, _ := gtk.LabelNew(v)
|
||||||
|
out = append(out, txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,55 +4,105 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
)
|
)
|
||||||
|
|
||||||
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/rk8ec9p14imkh03/Changelog?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
|
||||||
//For some of the code
|
//For some of the code
|
||||||
|
|
||||||
//Returns if success
|
//Returns if success
|
||||||
func versionDL() bool {
|
func versionDL() (bool, error) {
|
||||||
versionFile, err := os.Create("PortableApps/LinuxPACom/Version")
|
versionFile, err := os.Create("PortableApps/LinuxPACom/Version")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
versionFile.Chmod(0777)
|
versionFile.Chmod(0777)
|
||||||
check := http.Client{
|
check := http.Client{
|
||||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
||||||
r.URL.Opaque = r.URL.Path
|
r.URL.Opaque = r.URL.Path
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
response, err := check.Get(versionURL)
|
response, err := check.Get(versionURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
_, err = io.Copy(versionFile, response.Body)
|
_, err = io.Copy(versionFile, response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
return true
|
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, _ []*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 {
|
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)
|
||||||
@@ -65,42 +115,150 @@ func checkForUpdate(new string) bool {
|
|||||||
num, err = strconv.Atoi(newSlice[i])
|
num, err = strconv.Atoi(newSlice[i])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newNums[i] = num
|
newNums[i] = num
|
||||||
|
} else {
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
if newNums[i] > curNums[i] {
|
if newNums[i] > curNums[i] {
|
||||||
return true
|
return true, nil
|
||||||
|
} else if curNums[i] > newNums[i] {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadUpdate(newVersion string) bool {
|
func downloadUpdate(newVersion string) (bool, error) {
|
||||||
url := strings.Replace(downloadURL, "XXX", newVersion, -1)
|
url := strings.Replace(downloadURL, "XXX", newVersion, -1)
|
||||||
err := os.Rename("LinuxPA", ".LinuxPA.old")
|
err := os.Rename("LinuxPA", ".LinuxPA.old")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
return false, err
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
fil, err := os.Create("LinuxPA")
|
fil, err := os.Create("LinuxPA")
|
||||||
fil.Chmod(0777)
|
fil.Chmod(0777)
|
||||||
defer fil.Close()
|
defer fil.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Rename(".LinuxPA.old", "LinuxPA")
|
os.Rename(".LinuxPA.old", "LinuxPA")
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
check := http.Client{
|
check := http.Client{
|
||||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
||||||
r.URL.Opaque = r.URL.Path
|
r.URL.Opaque = r.URL.Path
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
re, err := check.Get(url)
|
re, err := check.Get(url)
|
||||||
defer re.Body.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
|
defer re.Body.Close()
|
||||||
_, err = io.Copy(fil, re.Body)
|
_, err = io.Copy(fil, re.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
return true
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(win *gtk.Window, forced bool) {
|
||||||
|
stat, err := versionDL()
|
||||||
|
if stat {
|
||||||
|
stable, beta := getVersionFileInfo()
|
||||||
|
if stable != "Error!" {
|
||||||
|
stat, err = checkForUpdate(stable, beta)
|
||||||
|
if stat || forced {
|
||||||
|
stat, err = changelogDL()
|
||||||
|
if stat {
|
||||||
|
updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
updateWin.SetTransientFor(win)
|
||||||
|
updateWin.SetPosition(gtk.WIN_POS_CENTER)
|
||||||
|
updateWin.SetDefaultSize(600, 300)
|
||||||
|
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.SetWrapMode(gtk.WRAP_WORD)
|
||||||
|
tv.SetEditable(false)
|
||||||
|
buf.SetText(getChangelog())
|
||||||
|
butBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
||||||
|
upBut, _ := gtk.ButtonNewWithLabel("Update")
|
||||||
|
upBut.Connect("clicked", func() {
|
||||||
|
updateWin.Close()
|
||||||
|
actuallyUpdate(win, forced)
|
||||||
|
})
|
||||||
|
cnlBut, _ := gtk.ButtonNewWithLabel("Cancel")
|
||||||
|
cnlBut.Connect("clicked", func() {
|
||||||
|
updateWin.Close()
|
||||||
|
})
|
||||||
|
butBox.Add(upBut)
|
||||||
|
butBox.Add(cnlBut)
|
||||||
|
topLvl.Add(lbl)
|
||||||
|
topLvl.Add(tv)
|
||||||
|
topLvl.Add(butBox)
|
||||||
|
topLvl.SetMarginBottom(10)
|
||||||
|
topLvl.SetMarginEnd(10)
|
||||||
|
topLvl.SetMarginStart(10)
|
||||||
|
topLvl.SetMarginTop(10)
|
||||||
|
updateWin.Add(topLvl)
|
||||||
|
updateWin.ShowAll()
|
||||||
|
updateWin.Show()
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Failed Version File Info")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func actuallyUpdate(win *gtk.Window, forced bool) {
|
||||||
|
updateWin, _ := gtk.WindowNew(gtk.WINDOW_POPUP)
|
||||||
|
updateWin.SetTransientFor(win)
|
||||||
|
updateWin.SetSizeRequest(150, 50)
|
||||||
|
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
spin, _ := gtk.SpinnerNew()
|
||||||
|
spin.Start()
|
||||||
|
lbl, _ := gtk.LabelNew("Updating")
|
||||||
|
topLvl.Add(spin)
|
||||||
|
topLvl.Add(lbl)
|
||||||
|
topLvl.SetMarginBottom(10)
|
||||||
|
topLvl.SetMarginEnd(10)
|
||||||
|
topLvl.SetMarginStart(10)
|
||||||
|
topLvl.SetMarginTop(10)
|
||||||
|
updateWin.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
updateWin.Add(topLvl)
|
||||||
|
updateWin.ShowAll()
|
||||||
|
updateWin.Show()
|
||||||
|
go func(win, updateWin *gtk.Window) {
|
||||||
|
defer updateWin.Close()
|
||||||
|
stat, err := versionDL()
|
||||||
|
if stat {
|
||||||
|
stable, beta := getVersionFileInfo()
|
||||||
|
if stable != "Error!" {
|
||||||
|
stat, err = checkForUpdate(stable, beta)
|
||||||
|
if stat || forced {
|
||||||
|
if betaUpdate {
|
||||||
|
downloadUpdate(beta)
|
||||||
|
} else {
|
||||||
|
downloadUpdate(stable)
|
||||||
|
}
|
||||||
|
win.Close()
|
||||||
|
cmd := exec.Command("./LinuxPA")
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Start()
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Failed Version File Info")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}(win, updateWin)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
"github.com/mholt/archiver/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
wineURL = "https://www.playonlinux.com/wine/binaries/phoenicis/staging-linux-amd64/PlayOnLinux-wine-5.20-staging-linux-amd64.tar.gz"
|
||||||
|
)
|
||||||
|
|
||||||
|
func downloadWine(parent *gtk.Window, cb chan bool) {
|
||||||
|
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
win.SetTransientFor(parent)
|
||||||
|
win.SetDestroyWithParent(true)
|
||||||
|
win.Connect("destroy", func() {
|
||||||
|
parent.SetSensitive(true)
|
||||||
|
})
|
||||||
|
parent.SetSensitive(false)
|
||||||
|
spin, _ := gtk.SpinnerNew()
|
||||||
|
spin.Start()
|
||||||
|
txt, _ := gtk.LabelNew("Downloading Wine")
|
||||||
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
||||||
|
box.SetMarginBottom(10)
|
||||||
|
box.SetMarginEnd(10)
|
||||||
|
box.SetMarginStart(10)
|
||||||
|
box.SetMarginTop(10)
|
||||||
|
box.Add(spin)
|
||||||
|
box.Add(txt)
|
||||||
|
win.Add(box)
|
||||||
|
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
win.ShowAll()
|
||||||
|
win.Show()
|
||||||
|
go func(win *gtk.Window, txt *gtk.Label) {
|
||||||
|
defer win.Close()
|
||||||
|
wineTar, err := os.Create("PortableApps/LinuxPACom/wine5.20.tar.bz2")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer wineTar.Close()
|
||||||
|
check := http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
||||||
|
r.URL.Opaque = r.URL.Path
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
resp, err := check.Get(wineURL)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
os.RemoveAll("PortableApps/LinuxPACom/Wine")
|
||||||
|
defer resp.Body.Close()
|
||||||
|
_, err = io.Copy(wineTar, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
txt.SetText("Extracting Wine")
|
||||||
|
err = archiver.DefaultTarBz2.Unarchive("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fil, err := os.Open("PortableApps/LinuxPACom/common.sh")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmp, err := ioutil.ReadAll(fil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(tmp), "export PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH") {
|
||||||
|
tmp = append(tmp, []byte("\nexport PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH")...)
|
||||||
|
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", tmp, 0777)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
cb <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb <- true
|
||||||
|
return
|
||||||
|
}(win, txt)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user