From c44dbabda18edcd2af251cab23cfd766044f4949 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 16 Dec 2020 11:53:48 +0100 Subject: [PATCH] LibGUI: Generate nicer icons for symlinked files Instead of symlinks showing up with the "filetype-symlink" icon, we now generate a new icon by taking the target file's icon and slapping a small arrow emblem on top of it. This looks rather nice. :^) --- Base/res/icons/symlink-emblem-small.png | Bin 0 -> 114 bytes Base/res/icons/symlink-emblem.png | Bin 0 -> 122 bytes Libraries/LibGUI/FileIconProvider.cpp | 40 ++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 Base/res/icons/symlink-emblem-small.png create mode 100644 Base/res/icons/symlink-emblem.png diff --git a/Base/res/icons/symlink-emblem-small.png b/Base/res/icons/symlink-emblem-small.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3babc19569dcd98730d9fc39b4d5f5dca326c4 GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4EInNuLnJP@_B(Ph7;qfE zwCR8SP1!aDrFHJo%%TE1mJEW%$}btePB^I^o?x_7+Um*5H51Hj8|sYpE0>CMM5^xD R!@$76;OXk;vd$@?2>?9+Ad~43W6pd%=;5L4m{N z;`)mJ+P9UsCI+Qz_6Ld_kUYY0CtF)d`dQ)`&5JzsZ*Q5}CA#d4)E4>p!|nBfyB4)S anE1a)@u@}4p3K0&z~JfX=d#Wzp$P#0rYC{` literal 0 HcmV?d00001 diff --git a/Libraries/LibGUI/FileIconProvider.cpp b/Libraries/LibGUI/FileIconProvider.cpp index 1f79a594c1..d49a173992 100644 --- a/Libraries/LibGUI/FileIconProvider.cpp +++ b/Libraries/LibGUI/FileIconProvider.cpp @@ -24,11 +24,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include +#include #include #include #include +#include #include #include @@ -45,6 +48,8 @@ static Icon s_symlink_icon; static Icon s_socket_icon; static Icon s_executable_icon; static Icon s_filetype_image_icon; +static RefPtr s_symlink_emblem; +static RefPtr s_symlink_emblem_small; static HashMap s_filetype_icons; static HashMap> s_filetype_patterns; @@ -57,6 +62,9 @@ static void initialize_if_needed() auto config = Core::ConfigFile::open("/etc/FileIconProvider.ini"); + s_symlink_emblem = Gfx::Bitmap::load_from_file("/res/icons/symlink-emblem.png"); + s_symlink_emblem_small = Gfx::Bitmap::load_from_file("/res/icons/symlink-emblem-small.png"); + s_hard_disk_icon = Icon::default_icon("hard-disk"); s_directory_icon = Icon::default_icon("filetype-folder"); s_directory_open_icon = Icon::default_icon("filetype-folder-open"); @@ -127,8 +135,36 @@ Icon FileIconProvider::icon_for_path(const String& path, mode_t mode) return s_inaccessible_directory_icon; return s_directory_icon; } - if (S_ISLNK(mode)) - return s_symlink_icon; + if (S_ISLNK(mode)) { + auto raw_symlink_target = Core::File::read_link(path); + if (raw_symlink_target.is_null()) + return s_symlink_icon; + + String target_path; + if (raw_symlink_target.starts_with('/')) { + target_path = raw_symlink_target; + } else { + target_path = Core::File::real_path_for(String::formatted("{}/{}", LexicalPath(path).dirname(), raw_symlink_target)); + } + auto target_icon = icon_for_path(target_path); + + Icon generated_icon; + for (auto size : target_icon.sizes()) { + auto& emblem = size < 32 ? *s_symlink_emblem_small : *s_symlink_emblem; + auto original_bitmap = target_icon.bitmap_for_size(size); + ASSERT(original_bitmap); + auto generated_bitmap = original_bitmap->clone(); + if (!generated_bitmap) { + dbgln("Failed to clone {}x{} icon for symlink variant", size, size); + return s_symlink_icon; + } + GUI::Painter painter(*generated_bitmap); + painter.blit({ size - emblem.width(), size - emblem.height() }, emblem, emblem.rect()); + + generated_icon.set_bitmap_for_size(size, move(generated_bitmap)); + } + return generated_icon; + } if (S_ISSOCK(mode)) return s_socket_icon; if (mode & (S_IXUSR | S_IXGRP | S_IXOTH))