diff --git a/globals/global_Variables.go b/globals/global_Variables.go index a1b489e..5aa77b2 100644 --- a/globals/global_Variables.go +++ b/globals/global_Variables.go @@ -1,6 +1,10 @@ package globals import ( + "log" + "os" + + "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" ) @@ -53,3 +57,41 @@ var ( ConfigPath string ThumbnailsPath string ) + +// Restores the window size of the last time the app has oppened. +func RestoreWindowSize() { + Window.Resize(fyne.NewSize(float32(WindowWidth), float32(WindowHeight))) +} + +// Thise are the used config files. +// ~/.config/walldo/config.json (unix). +// ~/AppData/Local/walldo/config.json (windows). +func InitApp() { + // set darkmode + os.Setenv("FYNE_THEME", "dark") + + // set configuration paths + userConfig, err := os.UserConfigDir() + if err != nil { + log.Fatal("Cannot establish users home directory: ", err.Error()) + } + + cacheDir, err := os.UserCacheDir() + if err != nil { + log.Fatal("Cannot establish users home directory: ", err.Error()) + } + + ConfigPath = userConfig + "walldo/" + ConfigFile = ConfigPath + "config.json" + ThumbnailsPath = cacheDir + "/walldo/" + + err = os.MkdirAll(ConfigPath, 0o770) + if err != nil { + panic("Cannot create config directory " + err.Error()) + } + + err = os.MkdirAll(ThumbnailsPath, 0o770) + if err != nil { + panic("Cannot create cache directory " + err.Error()) + } +} diff --git a/globals/globals_setup.go b/globals/globals_setup.go deleted file mode 100644 index 2ffe5b9..0000000 --- a/globals/globals_setup.go +++ /dev/null @@ -1,35 +0,0 @@ -package globals - -import ( - "log" - "os" - "runtime" - - "fyne.io/fyne/v2" -) - -// Thise are the used config files. -// ~/.config/walldo/config.json (unix). -// ~/AppData/Local/walldo/config.json (windows). -func SetupEnvVariables() { - os.Setenv("FYNE_THEME", "dark") - Window.Resize(fyne.NewSize(float32(WindowWidth), float32(WindowHeight))) - - home, err := os.UserHomeDir() - if err != nil { - log.Fatal("Cannot establish users home directory: ", err.Error()) - } - - switch runtime.GOOS { - case "windows": - ConfigPath = home + "/AppData/Local/walldo/" - ConfigFile = home + "/AppData/Local/walldo/config.json" - ThumbnailsPath = home + "/AppData/Local/walldo/resized_images/" - - default: - // sistemas Unix (Mac y Linux) - ConfigPath = home + "/.config/walldo/" - ConfigFile = home + "/.config/walldo/config.json" - ThumbnailsPath = home + "/.config/walldo/resized_images/" - } -} diff --git a/gui/components/dialogs/settings_Window.go b/gui/components/dialogs/settings_Window.go index 3203642..9b949a1 100644 --- a/gui/components/dialogs/settings_Window.go +++ b/gui/components/dialogs/settings_Window.go @@ -73,16 +73,16 @@ func ConfigWindow(win *fyne.Window, app fyne.App, refresh func()) { }) }) + pathsList.Resize(fyne.NewSize(float32(pathsList.Size().Width), 25)) + // Window content - cont := []*widget.FormItem{ - widget.NewFormItem("Images size", sizeSelector), - widget.NewFormItem("", pathInput), - widget.NewFormItem("", pathPickerButton), - widget.NewFormItem("", container.NewMax(pathsList)), - } + layout := container.NewGridWithRows(2, + container.NewVBox(sizeSelector, widget.NewSeparator()), + container.NewGridWithRows(2, pathsList, container.NewVBox(pathPickerButton)), + ) // Create the new dialog window (the main container) - dia := dialog.NewForm("Settings", "Confirm", "Cancel", cont, + dia := dialog.NewCustomConfirm("Settings", "Confirm", "Cancel", layout, // function to refresh the content with the new given config func(status bool) { if status { diff --git a/gui/components/images_grid.go b/gui/components/images_grid.go index 0bb9726..c1f6321 100644 --- a/gui/components/images_grid.go +++ b/gui/components/images_grid.go @@ -15,6 +15,12 @@ import ( "github.com/elias-gill/walldo-in-go/wallpaper" ) +type card struct { + imgPath string + container *fyne.Container + button *widget.Button +} + type wallpapersGrid struct { container *fyne.Container grid *fyne.Container @@ -38,19 +44,15 @@ func (c wallpapersGrid) GetGridContent() *fyne.Container { func (c *wallpapersGrid) RefreshImgGrid() { c.grid.RemoveAll() - utils.ListImagesRecursivelly() + utils.RefreshImagesList() - channel := c.generateFrames() - c.fillContainers(channel) -} + cardsChannel := c.generateFrames() -type card struct { - imgPath string - container *fyne.Container - button *widget.Button + c.fillContainers(cardsChannel) } -// fills the image grid with frame containers. +// fills the image grid with frame containers. Returns a channel with cards that +// are going to be filled latter asynchronously. func (c wallpapersGrid) generateFrames() chan card { // define the cards size size := globals.Sizes[globals.GridSize] @@ -96,7 +98,7 @@ generates the thumbnail for the card and refresh the container. create as many threads as cpus for resizing images to make thumbnails. */ func (c wallpapersGrid) fillContainers(channel chan card) { - print("\n Usando ", runtime.NumCPU()-2, " Hilos") + log.Println("\n Usando ", runtime.NumCPU()-2, " Hilos") for i := 0; i < runtime.NumCPU()-2; i++ { go func() { @@ -108,7 +110,6 @@ func (c wallpapersGrid) fillContainers(channel chan card) { image.FillMode = canvas.ImageFillContain // With the max layout we can overlap the button and the thumbnail - card.container.RemoveAll() card.container.Add(image) card.container.Add(card.button) card.container.Refresh() diff --git a/gui/main_window.go b/gui/gui.go similarity index 91% rename from gui/main_window.go rename to gui/gui.go index c6d05ce..46ef327 100644 --- a/gui/main_window.go +++ b/gui/gui.go @@ -7,11 +7,15 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/layout" + "github.com/elias-gill/walldo-in-go/globals" global "github.com/elias-gill/walldo-in-go/globals" "github.com/elias-gill/walldo-in-go/gui/components" ) func SetupGui() { + // restore previous window size + globals.RestoreWindowSize() + // title title := canvas.NewText("Select your wallpaper", color.White) title.TextStyle = fyne.TextStyle{Bold: true} diff --git a/main.go b/main.go index 6469fe3..91307b4 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,7 @@ import ( func main() { // set all global variables and run - globals.SetupEnvVariables() + globals.InitApp() gui.SetupGui() globals.Window.CenterOnScreen() globals.Window.ShowAndRun() diff --git a/utils/config_Manager.go b/utils/config_Manager.go index 4d27e73..7a169db 100644 --- a/utils/config_Manager.go +++ b/utils/config_Manager.go @@ -45,14 +45,7 @@ func parseConfigFile() Config { // Creates the config folder and the config.json if is not created yet. // This function may pannic if cannot modify/create the configuration file. func MustWriteConfig(config Config) { - // create the folders - // os.MkdirAll(global.ConfigPath, 0o777) - err := os.MkdirAll(global.ConfigPath+"resized_images", 0o777) - if err != nil { - panic("Cannot create configuration path: " + err.Error()) - } - - file, err := os.Create(global.ConfigPath + "config.json") + file, err := os.Create(global.ConfigFile) if err != nil { panic("Cannot create the configuration file: " + err.Error()) } diff --git a/utils/image_manager.go b/utils/image_manager.go index 5632044..0527ab5 100644 --- a/utils/image_manager.go +++ b/utils/image_manager.go @@ -1,20 +1,24 @@ package utils import ( + "fmt" + "hash/fnv" "log" "os" + "path" "path/filepath" + "strconv" "strings" "github.com/disintegration/imaging" "github.com/elias-gill/walldo-in-go/globals" ) -// used for GetImagesList(), so we dont need to re-search for images +// used for GetImagesList(), so we dont need to re-search for images. var imagesList []string // Resize the image to create a thumbnail. -// If a thumbnail already exists just do nothing +// If a thumbnail already exists just do nothing. func ResizeImage(image string) string { thumbPath := generateThnPath(image) @@ -23,11 +27,12 @@ func ResizeImage(image string) string { return thumbPath } - src, _ := imaging.Open(image) - if err != nil { - fmt.Println("Image not found: ", image) - return "" - } + src, err := imaging.Open(image) + if err != nil { + fmt.Println("Image not found: ", image) + return "" + } + src = imaging.Thumbnail(src, 200, 180, imaging.NearestNeighbor) imaging.Save(src, thumbPath) @@ -35,7 +40,7 @@ func ResizeImage(image string) string { } // Goes trought the configured folders recursivelly and list all the supported image files. -func ListImagesRecursivelly() { +func RefreshImagesList() { imagesList = []string{} folders := GetConfiguredPaths() @@ -56,6 +61,7 @@ func ListImagesRecursivelly() { if !info.IsDir() && hasValidExtension(file) { imagesList = append(imagesList, file) } + return nil }) if err != nil { @@ -66,20 +72,18 @@ func ListImagesRecursivelly() { // This returns the image list. The difference from ListImagesRecursivelly is that // this does not have to search again through the folders in order to improve performance for the -// fuzzy engine +// fuzzy engine. func GetImagesList() []string { return imagesList } -// Returns a new name for an image thumbnail +// Returns a new (hashed) path for an image thumbnail. func generateThnPath(image string) string { - // replace backslashes with normal slashes (for windows) - image = strings.ReplaceAll(image, `\`, `/`) - res := strings.Split(image, "/") - // generate a thumbnail name with format "parent + file" - largo := len(res) - 1 - thumbnail := res[largo] + res[largo-1] - return globals.ThumbnailsPath + thumbnail + ".jpg" + h := fnv.New32a() + name := strings.Split(path.Base(image), ".")[0] + h.Write([]byte(name)) + + return globals.ThumbnailsPath + strconv.Itoa(int(h.Sum32())) + ".jpg" } // Determine if the file has a valid extension. @@ -91,5 +95,6 @@ func hasValidExtension(file string) bool { validos := map[string]int{"jpg": 1, "jpeg": 1, "png": 1} _, res := validos[file] + return res }