diff --git a/src/icon.c b/src/icon.c index 164a618..1dbf0f2 100644 --- a/src/icon.c +++ b/src/icon.c @@ -8,6 +8,7 @@ #include "log.h" #include "notification.h" #include "settings.h" +#include "utils.h" static bool is_readable_file(const char *filename) { @@ -57,17 +58,21 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) return icon_surface; } -static GdkPixbuf *get_pixbuf_from_file(const char *filename) +GdkPixbuf *get_pixbuf_from_file(const char *filename) { GdkPixbuf *pixbuf = NULL; - if (is_readable_file(filename)) { + char *path = string_to_path(g_strdup(filename)); + + if (is_readable_file(path)) { GError *error = NULL; - pixbuf = gdk_pixbuf_new_from_file(filename, &error); + pixbuf = gdk_pixbuf_new_from_file(path, &error); if (!pixbuf) { LOG_W("%s", error->message); g_error_free(error); } } + + g_free(path); return pixbuf; } @@ -89,10 +94,8 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname) /* absolute path? */ if (iconname[0] == '/' || iconname[0] == '~') { pixbuf = get_pixbuf_from_file(iconname); - } - + } else { /* search in icon_path */ - if (!pixbuf) { char *start = settings.icon_path, *end, *current_folder, *maybe_icon_path; do { diff --git a/src/icon.h b/src/icon.h index c314465..2b3d92a 100644 --- a/src/icon.h +++ b/src/icon.h @@ -8,6 +8,14 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); +/** Retrieve an icon by its full filepath. + * + * @param filename A string representing a readable file path + * + * @return an instance of `GdkPixbuf` or `NULL` if file does not exist + */ +GdkPixbuf *get_pixbuf_from_file(const char *filename); + /** Retrieve an icon by its name sent via the notification bus * * @param iconname A string describing a `file://` URL, an arbitary filename diff --git a/test/icon.c b/test/icon.c index 5695a82..180a324 100644 --- a/test/icon.c +++ b/test/icon.c @@ -5,7 +5,7 @@ #include #include -#define ICONPREFIX "./data/icons/path" +#define ICONPREFIX "/data/icons/path" /* As there are no hints to test if the loaded GdkPixbuf is * read from a PNG or an SVG file, the sample icons in the @@ -14,6 +14,49 @@ #define IS_ICON_PNG(pb) 4 == gdk_pixbuf_get_width(pb) #define IS_ICON_SVG(pb) 16 == gdk_pixbuf_get_width(pb) +TEST test_get_pixbuf_from_file_tilde(void) +{ + char *cwd = g_get_current_dir(); + const char *home = g_get_home_dir(); + const char *iconpath = ICONPREFIX; + + if (0 != strncmp(home, cwd, strlen(home))) { + g_free(cwd); + SKIPm("Current directory is not a subdirectory from user's home." + " Cannot test iconpath tilde expansion.\n"); + } + + gchar *path = g_build_filename(cwd, iconpath, "valid", "icon1.svg", NULL); + path = string_replace_at(path, 0, strlen(home), "~"); + + GdkPixbuf *pixbuf = get_pixbuf_from_file(path); + g_clear_pointer(&path, g_free); + g_clear_pointer(&cwd, g_free); + + ASSERT(pixbuf); + ASSERTm("The wrong pixbuf is loaded in the icon file.", IS_ICON_SVG(pixbuf)); + g_clear_pointer(&pixbuf, g_object_unref); + PASS(); +} + +TEST test_get_pixbuf_from_file_absolute(void) +{ + char *cwd = g_get_current_dir(); + const char *iconpath = ICONPREFIX; + + gchar *path = g_build_filename(cwd, iconpath, "valid", "icon1.svg", NULL); + + GdkPixbuf *pixbuf = get_pixbuf_from_file(path); + g_clear_pointer(&path, g_free); + g_clear_pointer(&cwd, g_free); + + ASSERT(pixbuf); + ASSERTm("The wrong pixbuf is loaded in the icon file.", IS_ICON_SVG(pixbuf)); + g_clear_pointer(&pixbuf, g_object_unref); + + PASS(); +} + TEST test_get_pixbuf_from_icon_invalid(void) { GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid"); @@ -82,10 +125,12 @@ TEST test_get_pixbuf_from_icon_fileuri(void) SUITE(suite_icon) { settings.icon_path = - ICONPREFIX "/invalid" - ":" ICONPREFIX "/valid" - ":" ICONPREFIX "/both"; + "." ICONPREFIX "/invalid" + ":." ICONPREFIX "/valid" + ":." ICONPREFIX "/both"; + RUN_TEST(test_get_pixbuf_from_file_tilde); + RUN_TEST(test_get_pixbuf_from_file_absolute); RUN_TEST(test_get_pixbuf_from_icon_invalid); RUN_TEST(test_get_pixbuf_from_icon_both); RUN_TEST(test_get_pixbuf_from_icon_onlysvg);