Replace gtk_widget_render_icon with gtk_icon_theme_load_icon
authorArkadiy Illarionov <qarkai@gmail.com>
Sat, 30 Sep 2023 11:51:32 +0000 (14:51 +0300)
committerColin Clark <colin.clark@cclark.uk>
Sun, 1 Oct 2023 09:11:25 +0000 (10:11 +0100)
* Use icon size in pixels in gtk_icon_theme_load_icon
* Deduplicate folder icons creation
* Copy pixbuf returned by gtk_icon_theme_load_icon to avoid GTK+ keeping the old icon theme loaded
* Move static functions to anonymous namespace
* Replace some icon name string literals with GQ_ICON macros

src/logwindow.cc
src/main.h
src/ui-misc.cc
src/ui-misc.h
src/utilops.cc
src/view-dir.cc

index 47d86cf..e49faa6 100644 (file)
@@ -498,7 +498,7 @@ static LogWindow *log_window_create(LayoutWindow *lw)
        g_signal_connect(logwin->search_entry_box, "activate", G_CALLBACK(search_activate_event), logwin);
 
        theme = gtk_icon_theme_get_default();
-       pixbuf = gtk_icon_theme_load_icon(theme, "pan-up-symbolic", 20, GTK_ICON_LOOKUP_GENERIC_FALLBACK, nullptr);
+       pixbuf = gtk_icon_theme_load_icon(theme, GQ_ICON_PAN_UP, 20, GTK_ICON_LOOKUP_GENERIC_FALLBACK, nullptr);
        image = gtk_image_new_from_pixbuf(pixbuf);
        backwards_button = gtk_button_new();
        gtk_button_set_image(GTK_BUTTON(backwards_button), GTK_WIDGET(image));
@@ -508,7 +508,7 @@ static LogWindow *log_window_create(LayoutWindow *lw)
        g_signal_connect(backwards_button, "button_release_event", G_CALLBACK(backwards_keypress_event_cb), logwin);
        g_object_unref(pixbuf);
 
-       pixbuf = gtk_icon_theme_load_icon(theme, "pan-down-symbolic", 20, GTK_ICON_LOOKUP_GENERIC_FALLBACK, nullptr);
+       pixbuf = gtk_icon_theme_load_icon(theme, GQ_ICON_PAN_DOWN, 20, GTK_ICON_LOOKUP_GENERIC_FALLBACK, nullptr);
        image = gtk_image_new_from_pixbuf(pixbuf);
        forwards_button = gtk_button_new();
        gtk_button_set_image(GTK_BUTTON(forwards_button), GTK_WIDGET(image));
index 3f582ab..eef718a 100644 (file)
 #define GQ_ICON_ADD "list-add"
 #define GQ_ICON_REMOVE "list-remove"
 #define GQ_ICON_UNDO "edit-undo"
+#define GQ_ICON_REDO "edit-redo"
 #define GQ_ICON_OPEN "document-open"
 #define GQ_ICON_SAVE "document-save"
 #define GQ_ICON_SAVE_AS "document-save-as"
index b9b61be..6c84f47 100644 (file)
@@ -1626,4 +1626,15 @@ gboolean defined_mouse_buttons(GtkWidget *, GdkEventButton *event, gpointer data
        return ret;
 }
 
+GdkPixbuf *gq_gtk_icon_theme_load_icon_copy(GtkIconTheme *icon_theme, const gchar *icon_name, gint size, GtkIconLookupFlags flags)
+{
+       GError *error = nullptr;
+       GdkPixbuf *icon = gtk_icon_theme_load_icon(icon_theme, icon_name, size, flags, &error);
+       if (error) return nullptr;
+
+       GdkPixbuf *pixbuf = gdk_pixbuf_copy(icon);
+       g_object_unref(icon);
+       return pixbuf;
+}
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index f8613bb..a5b1ca9 100644 (file)
@@ -238,5 +238,8 @@ GList* get_action_items();
 void action_items_free(GList *list);
 
 gboolean defined_mouse_buttons(GtkWidget *widget, GdkEventButton *event, gpointer data);
+
+// Copy pixbuf returned by gtk_icon_theme_load_icon() to avoid GTK+ keeping the old icon theme loaded
+GdkPixbuf *gq_gtk_icon_theme_load_icon_copy(GtkIconTheme *icon_theme, const gchar *icon_name, gint size, GtkIconLookupFlags flags);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index d5e100d..f7bb316 100644 (file)
 #include "ui-fileops.h"
 #include "ui-misc.h"
 
+namespace
+{
+
+struct PixmapErrors
+{
+       GdkPixbuf *error;
+       GdkPixbuf *warning;
+       GdkPixbuf *apply;
+};
+
+GdkPixbuf *file_util_get_error_icon(FileData *fd, GList *list, GtkWidget *widget)
+{
+       static PixmapErrors pe = [widget]() -> PixmapErrors
+       {
+               GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
+
+               gint size;
+               if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &size, &size))
+                       {
+                       size = 16;
+                       }
+
+               GdkPixbuf *pb_error = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_DIALOG_ERROR, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+               GdkPixbuf *pb_warning = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_DIALOG_WARNING, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+               GdkPixbuf *pb_apply = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_APPLY, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+               return {pb_error, pb_warning, pb_apply};
+       }();
+
+       gint error = file_data_sc_verify_ci(fd, list);
+
+       if (error & CHANGE_ERROR_MASK)
+               {
+               return pe.error;
+               }
+
+       if (error)
+               {
+               return pe.warning;
+               }
+
+       return pe.apply;
+}
+
+}
+
 #define DIALOG_WIDTH 750
 
 enum ClipboardDestination {
@@ -45,8 +90,6 @@ enum ClipboardDestination {
        CLIPBOARD_UTF8_STRING   = 3
 };
 
-static GdkPixbuf *file_util_get_error_icon(FileData *fd, GList *list, GtkWidget *widget);
-
 static GtkTargetEntry target_types[] =
 {
        {const_cast<gchar *>("text/plain"), 0, CLIPBOARD_TEXT_PLAIN},
@@ -986,42 +1029,6 @@ void file_util_perform_ci(UtilityData *ud)
                }
 }
 
-static GdkPixbuf *file_util_get_error_icon(FileData *fd, GList *list, GtkWidget *widget)
-{
-       static GdkPixbuf *pb_warning;
-       static GdkPixbuf *pb_error;
-       static GdkPixbuf *pb_apply;
-       gint error;
-
-       if (!pb_warning)
-               {
-               pb_warning = gtk_widget_render_icon(widget, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU, nullptr);
-               }
-
-       if (!pb_error)
-               {
-               pb_error = gtk_widget_render_icon(widget, GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_MENU, nullptr);
-               }
-
-       if (!pb_apply)
-               {
-               pb_apply = gtk_widget_render_icon(widget, GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU, nullptr);
-               }
-
-       error = file_data_sc_verify_ci(fd, list);
-
-       if (!error) return pb_apply;
-
-       if (error & CHANGE_ERROR_MASK)
-               {
-               return pb_error;
-               }
-       else
-               {
-               return pb_warning;
-               }
-}
-
 static void file_util_check_resume_cb(GenericDialog *, gpointer data)
 {
        auto ud = static_cast<UtilityData *>(data);
index 2f7bd66..2668d85 100644 (file)
 #include "view-dir-list.h"
 #include "view-dir-tree.h"
 
-/* Folders icons to be used in tree or list directory view */
-static PixmapFolders *folder_icons_new(GtkWidget *widget)
+namespace
 {
-       auto pf = g_new0(PixmapFolders, 1);
-       GError *error = nullptr;
-       GdkPixbuf *icon;
-       gint scale;
-
-       GtkIconSize size = GTK_ICON_SIZE_MENU;
-
-/** @FIXME Emblems should be attached to icons via e.g.: \n
- * GIcon *.... \n
- * icon = g_themed_icon_new("folder"); \n
- * emblem_icon = g_themed_icon_new("emblem_symbolic_link"); \n
- * emblem = g_emblem_new(emblem_icon); \n
- * emblemed = g_emblemed_icon_new(icon, emblem); \n
- * gtk_icon_info_load_icon(icon_info, NULL) \n
+
+/** @FIXME Emblems should be attached to icons via e.g.:
+ * GIcon *....
+ * icon = g_themed_icon_new("folder");
+ * emblem_icon = g_themed_icon_new("emblem_symbolic_link");
+ * emblem = g_emblem_new(emblem_icon);
+ * emblemed = g_emblemed_icon_new(icon, emblem);
+ * gtk_icon_info_load_icon(icon_info, NULL)
  * But there does not seem to be a way to get GtkIconInfo from a GIcon
  */
-
-       /* Attempt to use stock gtk icons */
-       pf->close  = gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr);
-       pf->open   = gtk_widget_render_icon(widget, GTK_STOCK_OPEN, size, nullptr);
-       pf->parent = gtk_widget_render_icon(widget, GTK_STOCK_GO_UP, size, nullptr);
-
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), GQ_ICON_UNREADABLE))
-               {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), GQ_ICON_UNREADABLE, size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
-
-                       pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_STOP, size, nullptr));
-                       }
-               else
-                       {
-                       pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->deny, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
-
-                       }
-               g_object_unref(icon);
-               }
-       else
+GdkPixbuf *create_folder_icon_with_emblem(GtkIconTheme *icon_theme, const gchar *emblem, const gchar *fallback_icon, gint size)
+{
+       if (!gtk_icon_theme_has_icon(icon_theme, emblem))
                {
-               pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_STOP, size, nullptr));
+               return gq_gtk_icon_theme_load_icon_copy(icon_theme, fallback_icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
                }
 
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), GQ_ICON_LINK))
+       GError *error = nullptr;
+       GdkPixbuf *icon = gtk_icon_theme_load_icon(icon_theme, emblem, size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
+       GdkPixbuf *pixbuf;
+       if (error)
                {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), GQ_ICON_LINK, size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
-
-                       pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_REDO, size, nullptr));
-                       }
-               else
-                       {
-                       pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->link, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
-                       }
-               g_object_unref(icon);
+               log_printf("Error: %s\n", error->message);
+               g_error_free(error);
+               pixbuf = gq_gtk_icon_theme_load_icon_copy(icon_theme, fallback_icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
                }
        else
                {
-               pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_REDO, size, nullptr));
+               GdkPixbuf *directory_pixbuf = gtk_icon_theme_load_icon(icon_theme, GQ_ICON_DIRECTORY, size, GTK_ICON_LOOKUP_USE_BUILTIN, nullptr);
+               pixbuf = gdk_pixbuf_copy(directory_pixbuf);
+               g_object_unref(directory_pixbuf);
+               
+               gint scale = gdk_pixbuf_get_width(icon) / 2;
+               gdk_pixbuf_composite(icon, pixbuf, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
                }
+       g_object_unref(icon);
 
-       pf->read_only = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
+       return pixbuf;
+}
+
+/* Folders icons to be used in tree or list directory view */
+PixmapFolders *folder_icons_new()
+{
+       auto pf = g_new0(PixmapFolders, 1);
+       GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
 
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), GQ_ICON_READONLY))
+       gint size;
+       if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &size, &size))
                {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), GQ_ICON_READONLY, size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
+               size = 16;
+               }
 
-                       pf->read_only = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       }
-               else
-                       {
-                       gint scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->read_only, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
+       pf->close  = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_DIRECTORY, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+       pf->open   = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_OPEN, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+       pf->parent = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_GO_UP, size, GTK_ICON_LOOKUP_USE_BUILTIN);
 
-                       }
-               g_object_unref(icon);
-               }
+       pf->deny = create_folder_icon_with_emblem(icon_theme, GQ_ICON_UNREADABLE, GQ_ICON_STOP, size);
+       pf->link = create_folder_icon_with_emblem(icon_theme, GQ_ICON_LINK, GQ_ICON_REDO, size);
+       pf->read_only = create_folder_icon_with_emblem(icon_theme, GQ_ICON_READONLY, GQ_ICON_DIRECTORY, size);
 
        return pf;
 }
 
-static void folder_icons_free(PixmapFolders *pf)
+void folder_icons_free(PixmapFolders *pf)
 {
        if (!pf) return;
 
@@ -147,7 +116,7 @@ static void folder_icons_free(PixmapFolders *pf)
        g_free(pf);
 }
 
-
+}
 
 static void vd_notify_cb(FileData *fd, NotifyType type, gpointer data);
 
@@ -189,7 +158,7 @@ ViewDir *vd_new(LayoutWindow *lw)
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
 
        vd->layout = lw;
-       vd->pf = folder_icons_new(vd->widget);
+       vd->pf = folder_icons_new();
 
        switch (lw->options.dir_view_type)
                {