Merge pull request #14 from nwg-piotr/files

xdg-open support + customization + 1 bug fixed
This commit is contained in:
Piotr Miller
2021-08-21 00:49:24 +02:00
committed by GitHub
5 changed files with 105 additions and 21 deletions

View File

@@ -85,6 +85,37 @@ Usage of nwg-drawer:
Edit `~/.config/nwg-panel/drawer.css` to your taste. Edit `~/.config/nwg-panel/drawer.css` to your taste.
## Files
When the search phrase is at least 3 characters long, your XDG user directories are being searched.
![screenshot-03.png](https://scrot.cloud/images/2021/05/30/screenshot-03.png)
Use the **left mouse button** to open a file with the `xdg-open` command. As configuring file associations for it is
PITA, you may override them, by creating the `~/.config/nwg-panel/preferred-apps.json` file with your own definitions.
### Sample file content
```json
{
"\\.pdf$": "atril",
"\\.svg$": "inkscape",
"\\.(jpg|png|tiff|gif)$": "feh",
"\\.(mp3|ogg|flac|wav|wma)$": "audacious",
"\\.(avi|mp4|mkv|mov|wav)$": "mpv",
"\\.(doc|docx|xls|xlsx)$": "libreoffice"
}
```
Use the **right mouse button** to open the file with your file manager (see `-fm` argument). The result depends on the
file manager you use.
- thunar will open the file location
- pcmanfm will open the file with its associated program
- caja won't open anything, except for directories
I've noy yet tried other file managers.
## Credits ## Credits
This program uses some great libraries: This program uses some great libraries:

Binary file not shown.

23
main.go
View File

@@ -19,7 +19,7 @@ import (
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
) )
const version = "0.1.5" const version = "0.1.7"
var ( var (
appDirs []string appDirs []string
@@ -28,6 +28,7 @@ var (
pinned []string pinned []string
src glib.SourceHandle src glib.SourceHandle
id2entry map[string]desktopEntry id2entry map[string]desktopEntry
preferredApps map[string]interface{}
) )
var categoryNames = [...]string{ var categoryNames = [...]string{
@@ -188,6 +189,17 @@ func main() {
status = parseDesktopFiles(desktopFiles) status = parseDesktopFiles(desktopFiles)
// For opening files we use xdg-open. As its configuration is PITA, we may override some associations
// in the ~/.config/nwg-panel/preferred-apps.json file.
paFile := filepath.Join(configDirectory, "preferred-apps.json")
preferredApps, err = loadPreferredApps(paFile)
if err != nil {
println(fmt.Sprintf("Custom associations file %s not found or invalid", paFile))
} else {
println(fmt.Sprintf("Found %v associations in %s", len(preferredApps), paFile))
fmt.Println(preferredApps)
}
// USER INTERFACE // USER INTERFACE
gtk.Init(nil) gtk.Init(nil)
@@ -243,15 +255,6 @@ func main() {
gtk.MainQuit() gtk.MainQuit()
}) })
win.Connect("button-release-event", func(sw *gtk.Window, e *gdk.Event) bool {
btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 || btnEvent.Button() == 3 {
gtk.MainQuit()
return true
}
return false
})
win.Connect("key-press-event", func(window *gtk.Window, event *gdk.Event) bool { win.Connect("key-press-event", func(window *gtk.Window, event *gdk.Event) bool {
key := &gdk.EventKey{Event: event} key := &gdk.EventKey{Event: event}
switch key.KeyVal() { switch key.KeyVal() {

View File

@@ -2,6 +2,8 @@ package main
import ( import (
"context" "context"
"encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@@ -10,6 +12,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp"
"sort" "sort"
"strings" "strings"
"time" "time"
@@ -243,6 +246,25 @@ func getAppDirs() []string {
return dirs return dirs
} }
func loadPreferredApps(path string) (map[string]interface{}, error) {
jsonFile, err := os.Open(path)
if err != nil {
return nil, err
}
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var result map[string]interface{}
json.Unmarshal([]byte(byteValue), &result)
if len(result) == 0 {
return nil, errors.New("json invalid or empty")
}
return result, nil
}
func listFiles(dir string) ([]fs.FileInfo, error) { func listFiles(dir string) ([]fs.FileInfo, error) {
files, err := ioutil.ReadDir(dir) files, err := ioutil.ReadDir(dir)
if err == nil { if err == nil {
@@ -622,14 +644,25 @@ func launch(command string, terminal bool) {
}) })
} }
func open(filePath string) { func open(filePath string, xdgOpen bool) {
cmd := exec.Command(*fileManager, filePath) var cmd *exec.Cmd
if xdgOpen {
cmd = exec.Command("xdg-open", filePath)
// Look for possible custom file association
for key, element := range preferredApps {
r, err := regexp.Compile(key)
if err == nil && r.MatchString(filePath) {
cmd = exec.Command(fmt.Sprintf("%v", element), filePath)
break
}
}
} else {
cmd = exec.Command(*fileManager, filePath)
}
fmt.Printf("Executing: %s", cmd)
cmd.Start() cmd.Start()
glib.TimeoutAdd(uint(150), func() bool {
gtk.MainQuit() gtk.MainQuit()
return false
})
} }
// Returns map output name -> gdk.Monitor // Returns map output name -> gdk.Monitor

View File

@@ -387,7 +387,8 @@ func searchUserDir(dir string) {
} }
fileSearchResultFlowBox.Hide() fileSearchResultFlowBox.Hide()
statusLabel.SetText(fmt.Sprintf("%v results", fileSearchResultFlowBox.GetChildren().Length())) statusLabel.SetText(fmt.Sprintf("%v results | LMB: xdg-open | RMB: file manager",
fileSearchResultFlowBox.GetChildren().Length()))
num := uint(fileSearchResultFlowBox.GetChildren().Length() / *fsColumns) num := uint(fileSearchResultFlowBox.GetChildren().Length() / *fsColumns)
fileSearchResultFlowBox.SetMinChildrenPerLine(num + 1) fileSearchResultFlowBox.SetMinChildrenPerLine(num + 1)
fileSearchResultFlowBox.SetMaxChildrenPerLine(num + 1) fileSearchResultFlowBox.SetMaxChildrenPerLine(num + 1)
@@ -414,8 +415,16 @@ func setUpUserDirButton(iconName, displayName, entryName string, userDirsMap map
} }
button.SetLabel(displayName) button.SetLabel(displayName)
button.Connect("clicked", func() { button.Connect("button-release-event", func(btn *gtk.Button, e *gdk.Event) bool {
launch(fmt.Sprintf("%s %s", *fileManager, userDirsMap[entryName]), false) btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 {
open(userDirsMap[entryName], true)
return true
} else if btnEvent.Button() == 3 {
open(userDirsMap[entryName], false)
return true
}
return false
}) })
box.PackStart(button, false, true, 0) box.PackStart(button, false, true, 0)
@@ -443,8 +452,16 @@ func setUpUserFileSearchResultButton(fileName, filePath string) *gtk.Box {
button.SetTooltipText(tooltipText) button.SetTooltipText(tooltipText)
} }
button.Connect("clicked", func() { button.Connect("button-release-event", func(btn *gtk.Button, e *gdk.Event) bool {
open(filePath) btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 {
open(filePath, true)
return true
} else if btnEvent.Button() == 3 {
open(filePath, false)
return true
}
return false
}) })
box.PackStart(button, false, true, 0) box.PackStart(button, false, true, 0)