Skip to content

Commit

Permalink
Merge pull request #2 from PucklaMotzer09/file_dialog_locations
Browse files Browse the repository at this point in the history
File dialog locations
  • Loading branch information
charlesdaniels committed Oct 6, 2020
2 parents f3e0660 + d5ce136 commit ac81a66
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 88 deletions.
101 changes: 46 additions & 55 deletions dialog/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"

"fyne.io/fyne"
Expand Down Expand Up @@ -84,14 +83,6 @@ func (f *fileDialog) makeUI() fyne.CanvasObject {
name := f.fileName.(*widget.Entry).Text
path, _ := storage.Child(f.dir, name)

// On windows replace '\\' with '/'
if runtime.GOOS == "windows" {
pathString := path.String()
pathString = strings.ReplaceAll(pathString, "\\\\", "/")
pathString = strings.ReplaceAll(pathString, "\\", "/")
path = storage.NewURI(pathString)
}

exists, _ := storage.Exists(path)

_, err := storage.ListerForURI(path)
Expand Down Expand Up @@ -131,12 +122,6 @@ func (f *fileDialog) makeUI() fyne.CanvasObject {
}
path := f.selected.location
// On windows replace '\\' with '/'
if runtime.GOOS == "windows" {
pathString := path.String()
pathString = strings.ReplaceAll(pathString, "\\\\", "/")
pathString = strings.ReplaceAll(pathString, "\\", "/")
path = storage.NewURI(pathString)
}
callback(storage.OpenFileFromURI(path))
}
})
Expand Down Expand Up @@ -192,49 +177,62 @@ func (f *fileDialog) makeUI() fyne.CanvasObject {
}

func (f *fileDialog) loadFavorites() ([]fyne.CanvasObject, error) {
osHome, err := os.UserHomeDir()
if err != nil {
return nil, err
}
var home fyne.ListableURI
var documents fyne.ListableURI
var downloads fyne.ListableURI
var osHome string
var err, err1 error

home, err := storage.ListerForURI(storage.NewURI("file://" + osHome))
if err != nil {
return nil, err
}
osHome, err = os.UserHomeDir()

documentsURI, err := storage.Child(home, "Documents")
if err != nil {
return nil, err
}
documents, err := storage.ListerForURI(documentsURI)
if err != nil {
return nil, err
}

downloadsURI, err := storage.Child(home, "Downloads")
if err != nil {
return nil, err
}
downloads, err := storage.ListerForURI(downloadsURI)
if err != nil {
return nil, err
if err == nil {
home, err1 = storage.ListerForURI(storage.NewURI("file://" + osHome))
if err1 == nil {
var documentsURI fyne.URI
documentsURI, err1 = storage.Child(home, "Documents")
if err1 == nil {
documents, err1 = storage.ListerForURI(documentsURI)
if err1 != nil {
err = err1
}
} else {
err = err1
}
var downloadsURI fyne.URI
downloadsURI, err1 = storage.Child(home, "Downloads")
if err1 == nil {
downloads, err1 = storage.ListerForURI(downloadsURI)
if err1 != nil {
err = err1
}
} else {
err = err1
}
} else {
err = err1
}
}

places := []fyne.CanvasObject{
var places []fyne.CanvasObject

makeFavoriteButton("Home", theme.HomeIcon(), func() {
if home != nil {
places = append(places, makeFavoriteButton("Home", theme.HomeIcon(), func() {
f.setDirectory(home)
}),
makeFavoriteButton("Documents", theme.DocumentIcon(), func() {
}))
}
if documents != nil {
places = append(places, makeFavoriteButton("Documents", theme.DocumentIcon(), func() {
f.setDirectory(documents)
}),
makeFavoriteButton("Downloads", theme.DownloadIcon(), func() {
}))
}
if downloads != nil {
places = append(places, makeFavoriteButton("Downloads", theme.DownloadIcon(), func() {
f.setDirectory(downloads)
}),
}))
}

places = append(places, f.loadPlaces()...)
return places, nil
return places, err
}

func (f *fileDialog) refreshDir(dir fyne.ListableURI) {
Expand Down Expand Up @@ -289,17 +287,10 @@ func (f *fileDialog) setDirectory(dir fyne.ListableURI) error {

f.breadcrumb.Children = nil

if dir.Scheme() != "file" {
return fmt.Errorf("scheme for directory was not file://")
}

localdir := dir.String()[len(dir.Scheme())+3:]
if runtime.GOOS == "windows" {
localdir = strings.ReplaceAll(localdir, "/", "\\")
}

buildDir := filepath.VolumeName(localdir)
for i, d := range strings.Split(localdir, string(filepath.Separator)) {
for i, d := range strings.Split(localdir, "/") {
if d == "" {
if i > 0 { // what we get if we split "/"
break
Expand Down
27 changes: 18 additions & 9 deletions dialog/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ func TestShowFileOpen(t *testing.T) {
buttons := ui.Objects[2].(*fyne.Container).Objects[0].(*widget.Box)
open := buttons.Children[1].(*widget.Button)

breadcrumb := ui.Objects[3].(*fyne.Container).Objects[0].(*widget.ScrollContainer).Content.(*widget.Box)
assert.Greater(t, len(breadcrumb.Children), 0)

wd, err := os.Getwd()
if runtime.GOOS == "windows" {
// on windows os.Getwd() returns '\'
wd = strings.ReplaceAll(wd, "\\", "/")
}
assert.Nil(t, err)
components := strings.Split(wd, "/")
if assert.Equal(t, len(components), len(breadcrumb.Children)) {
for i := range components {
assert.Equal(t, components[i], breadcrumb.Children[i].(*widget.Button).Text)
}
}

files := ui.Objects[3].(*fyne.Container).Objects[1].(*widget.ScrollContainer).Content.(*fyne.Container)
assert.Greater(t, len(files.Objects), 0)

Expand Down Expand Up @@ -210,16 +226,9 @@ func TestShowFileOpen(t *testing.T) {
assert.Nil(t, win.Canvas().Overlays().Top())
assert.Nil(t, openErr)

targetLocationString := target.location.String()
// Replace all '\\' with '/' on windows since the dialog
// will return a URI with only '/'
if runtime.GOOS == "windows" {
targetLocationString = strings.ReplaceAll(targetLocationString, "\\\\", "/")
targetLocationString = strings.ReplaceAll(targetLocationString, "\\", "/")
}
assert.Equal(t, targetLocationString, chosen.URI().String())
assert.Equal(t, target.location.String(), chosen.URI().String())

err := chosen.Close()
err = chosen.Close()
assert.Nil(t, err)
}

Expand Down
2 changes: 1 addition & 1 deletion dialog/fileitem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func TestNewFileItem_Folder(t *testing.T) {
test.Tap(item)
assert.False(t, item.isCurrent)
assert.Equal(t, (*fileDialogItem)(nil), f.selected)
assert.Equal(t, currentDir, f.dir.String()[len(f.dir.Scheme())+3:])
assert.Equal(t, storage.NewURI("file://"+currentDir).String(), f.dir.String())
}

func TestNewFileItem_ParentFolder(t *testing.T) {
Expand Down
31 changes: 13 additions & 18 deletions storage/uri.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ type uri struct {
// NewURI creates a new URI from the given string representation.
// This could be a URI from an external source or one saved from URI.String()
func NewURI(u string) fyne.URI {
// URIs are supposed to use forward slashes. On Windows, it
// should be OK to use the platform native filepath with UNIX
// or NT sytle paths, with / or \, but when we reconstruct
// the URI, we want to have / only.
if runtime.GOOS == "windows" {
// seems that sometimes we end up with
// double-backslashes
u = strings.ReplaceAll(u, "\\\\", "/")
u = strings.ReplaceAll(u, "\\", "/")
}
return &uri{raw: u}
}

Expand Down Expand Up @@ -81,8 +91,6 @@ func parentGeneric(location string) (string, error) {
components := strings.Split(location, "/")

if len(components) == 1 {
// trimmed <= 2 makes sure we handle UNIX-style paths on
// Windows correctly
return "", URIRootError
}

Expand All @@ -104,11 +112,6 @@ func Parent(u fyne.URI) (fyne.URI, error) {
s := u.String()

// trim trailing slash
if runtime.GOOS == "windows" {
if s[len(s)-1] == '\\' {
s = s[0 : len(s)-1]
}
}
if s[len(s)-1] == '/' {
s = s[0 : len(s)-1]
}
Expand All @@ -125,23 +128,15 @@ func Parent(u fyne.URI) (fyne.URI, error) {
if u.Scheme() == "file" {
// use the system native path resolution
parent = filepath.Dir(s)
if parent[len(parent)-1] != filepath.Separator {
parent += "/"
}

// only root is it's own parent
if filepath.Clean(parent) == filepath.Clean(s) {
return nil, URIRootError
}

// URIs are supposed to use forward slashes. On Windows, it
// should be OK to use the platform native filepath with UNIX
// or NT sytle paths, with / or \, but when we reconstruct
// the URI, we want to have / only.
if runtime.GOOS == "windows" {
// seems that sometimes we end up with
// double-backslashes
parent = strings.ReplaceAll(parent, "\\\\", "/")
parent = strings.ReplaceAll(parent, "\\", "/")
}

} else {
var err error
parent, err = parentGeneric(s)
Expand Down
41 changes: 36 additions & 5 deletions storage/uri_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,43 @@ func TestURI_Parent(t *testing.T) {

parent, err := storage.Parent(storage.NewURI("file:///foo/bar/baz"))
assert.Nil(t, err)
assert.Equal(t, "file:///foo/bar", parent.String())
assert.Equal(t, "file:///foo/bar/", parent.String())

parent, err = storage.Parent(storage.NewURI("file:///foo/bar/baz/"))
assert.Nil(t, err)
assert.Equal(t, "file:///foo/bar", parent.String())
assert.Equal(t, "file:///foo/bar/", parent.String())

parent, err = storage.Parent(storage.NewURI("file://C:/foo/bar/baz/"))
assert.Nil(t, err)
assert.Equal(t, "file://C:/foo/bar", parent.String())
assert.Equal(t, "file://C:/foo/bar/", parent.String())

parent, err = storage.Parent(storage.NewURI("http://foo/bar/baz/"))
assert.Nil(t, err)
assert.Equal(t, "http://foo/bar/", parent.String())

parent, err = storage.Parent(storage.NewURI("http:////foo/bar/baz/"))
assert.Nil(t, err)
assert.Equal(t, "http://foo/bar/", parent.String())

_, err = storage.Parent(storage.NewURI("http://foo"))
assert.Equal(t, storage.URIRootError, err)

_, err = storage.Parent(storage.NewURI("http:///"))
assert.Equal(t, storage.URIRootError, err)

parent, err = storage.Parent(storage.NewURI("https://///foo/bar/"))
assert.Nil(t, err)
assert.Equal(t, "https:///foo/", parent.String())

if runtime.GOOS == "windows" {
// Only the Windows version of filepath will know how to handle
// backslashes.
parent, err = storage.Parent(storage.NewURI("file://C:\\foo\\bar\\baz\\"))
uri := storage.NewURI("file://C:\\foo\\bar\\baz\\")
assert.Equal(t, "file://C:/foo/bar/baz/", uri.String())

parent, err = storage.Parent(uri)
assert.Nil(t, err)
assert.Equal(t, "file://C:/foo/bar", parent.String())
assert.Equal(t, "file://C:/foo/bar/", parent.String())
}

_, err = storage.Parent(storage.NewURI("file:///"))
Expand Down Expand Up @@ -104,4 +125,14 @@ func TestURI_Child(t *testing.T) {

p, _ = storage.Child(storage.NewURI("file:///foo/bar/"), "baz")
assert.Equal(t, "file:///foo/bar/baz", p.String())

if runtime.GOOS == "windows" {
// Only the Windows version of filepath will know how to handle
// backslashes.
uri := storage.NewURI("file://C:\\foo\\bar\\")
assert.Equal(t, "file://C:/foo/bar/", uri.String())

p, _ = storage.Child(uri, "baz")
assert.Equal(t, "file://C:/foo/bar/baz", p.String())
}
}

0 comments on commit ac81a66

Please sign in to comment.