From 250398a55e7283ea90a2fe8e9c5fae2b4acec708 Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Mon, 28 Oct 2013 16:38:30 +0300 Subject: [PATCH] Fix template sub-menu loading code (Bug 10138) The old code recursively searched the XDG_TEMPLATES_DIR for files that can be used as templates. This patch changes it so that it only searches that directory and limits the number of items shown to the xfconf property max-template-files which is set to 16 to keep the sub-menu usable. It also only shows files which are not marked as hidden or backup to eliminate clutter. --- common/xfdesktop-common.h | 1 + src/xfdesktop-file-icon-manager.c | 289 +++++++++++++++++++++----------------- 2 files changed, 161 insertions(+), 129 deletions(-) diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h index dde3fa40..163855c 100644 --- a/common/xfdesktop-common.h +++ b/common/xfdesktop-common.h @@ -61,6 +61,7 @@ #define DESKTOP_ICONS_SHOW_TRASH "/desktop-icons/file-icons/show-trash" #define DESKTOP_ICONS_SHOW_FILESYSTEM "/desktop-icons/file-icons/show-filesystem" #define DESKTOP_ICONS_SHOW_REMOVABLE "/desktop-icons/file-icons/show-removable" +#define DESKTOP_ICONS_MAX_TEMPLATE_FILES "/desktop-icons/file-icons/max-template-files" /** * File information namespaces queried for #GFileInfo objects. diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index 63d00c4..a4432cb 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -76,8 +76,8 @@ #include #include -#define SAVE_DELAY 7000 -#define BORDER 8 +#define SAVE_DELAY 7000 +#define BORDER 8 typedef enum { @@ -90,7 +90,8 @@ typedef enum PROP_SHOW_NETWORK_VOLUME, PROP_SHOW_DEVICE_VOLUME, PROP_SHOW_UNKNOWN_VOLUME, - PROP_SHOW_THUMBNAILS + PROP_SHOW_THUMBNAILS, + PROP_MAX_TEMPLATES, } XfdesktopFileIconManagerProp; struct _XfdesktopFileIconManagerPrivate @@ -139,6 +140,8 @@ struct _XfdesktopFileIconManagerPrivate #endif XfdesktopThumbnailer *thumbnailer; + + guint max_templates; }; static void xfdesktop_file_icon_manager_set_property(GObject *object, @@ -206,6 +209,11 @@ static void xfdesktop_file_icon_manager_update_image(GtkWidget *widget, gchar *thumbfile, XfdesktopFileIconManager *fmanager); +static void +xfdesktop_file_icon_manager_set_max_templates(XfdesktopFileIconManager *manager, + gint max_templates); + + G_DEFINE_TYPE_EXTENDED(XfdesktopFileIconManager, xfdesktop_file_icon_manager, G_TYPE_OBJECT, 0, @@ -318,6 +326,12 @@ xfdesktop_file_icon_manager_class_init(XfdesktopFileIconManagerClass *klass) "show-thumbnails", TRUE, XFDESKTOP_PARAM_FLAGS)); + g_object_class_install_property(gobject_class, PROP_MAX_TEMPLATES, + g_param_spec_uint("max-templates", + "max-templates", + "max-templates", + 0, G_MAXUSHORT, 16, + XFDESKTOP_PARAM_FLAGS)); #undef XFDESKTOP_PARAM_FLAGS xfdesktop_app_info_quark = g_quark_from_static_string("xfdesktop-app-info-quark"); @@ -388,6 +402,11 @@ xfdesktop_file_icon_manager_set_property(GObject *object, g_value_get_boolean(value)); break; + case PROP_MAX_TEMPLATES: + xfdesktop_file_icon_manager_set_max_templates(fmanager, + g_value_get_uint(value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -440,7 +459,11 @@ xfdesktop_file_icon_manager_get_property(GObject *object, case PROP_SHOW_THUMBNAILS: g_value_set_boolean(value, fmanager->priv->show_thumbnails); break; - + + case PROP_MAX_TEMPLATES: + g_value_set_int(value, fmanager->priv->max_templates); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -1166,24 +1189,24 @@ static gint compare_template_files(gconstpointer a, gconstpointer b) { - GFileInfo *info_a = g_object_get_data(G_OBJECT(a), "info"); - GFileInfo *info_b = g_object_get_data(G_OBJECT(b), "info"); - GFileType type_a = g_file_info_get_file_type(info_a); - GFileType type_b = g_file_info_get_file_type(info_b); - const gchar* name_a = g_file_info_get_display_name(info_a); - const gchar* name_b = g_file_info_get_display_name(info_b); + GFileInfo *info_a = g_object_get_data(G_OBJECT(a), "info"); + GFileInfo *info_b = g_object_get_data(G_OBJECT(b), "info"); + GFileType type_a = g_file_info_get_file_type(info_a); + GFileType type_b = g_file_info_get_file_type(info_b); + const gchar* name_a = g_file_info_get_display_name(info_a); + const gchar* name_b = g_file_info_get_display_name(info_b); - if(!info_a || !info_b) - return 0; + if(!info_a || !info_b) + return 0; - if(type_a == type_b) { - return g_strcmp0(name_a, name_b); - } else { - if(type_a == G_FILE_TYPE_DIRECTORY) - return -1; - else - return 1; - } + if(type_a == type_b) { + return g_strcmp0(name_a, name_b); + } else { + if(type_a == G_FILE_TYPE_DIRECTORY) + return -1; + else + return 1; + } } static gboolean @@ -1191,94 +1214,84 @@ xfdesktop_file_icon_menu_fill_template_menu(GtkWidget *menu, GFile *template_dir, XfdesktopFileIconManager *fmanager) { - GFileEnumerator *enumerator; - GtkWidget *item, *image, *submenu; - GFileInfo *info; - GFile *file; - GIcon *icon; - GList *files = NULL, *lp; - gchar *label, *dot; - gboolean have_templates = FALSE; - - g_return_val_if_fail(G_IS_FILE(template_dir), FALSE); - - enumerator = g_file_enumerate_children(template_dir, - XFDESKTOP_FILE_INFO_NAMESPACE, - G_FILE_QUERY_INFO_NONE, - NULL, NULL); - - if(enumerator) { - while((info = g_file_enumerator_next_file(enumerator, NULL, NULL))) { - file = g_file_get_child(template_dir, g_file_info_get_name(info)); - g_object_set_data_full(G_OBJECT(file), "info", info, g_object_unref); - files = g_list_prepend(files, file); - } + GFileEnumerator *enumerator; + GtkWidget *item, *image; + GFileInfo *info; + GFile *file; + GIcon *icon; + GList *files = NULL, *lp; + gchar *label, *dot; + gboolean have_templates = FALSE; + guint items = 0; + + g_return_val_if_fail(G_IS_FILE(template_dir), FALSE); + + enumerator = g_file_enumerate_children(template_dir, + XFDESKTOP_FILE_INFO_NAMESPACE, + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + + if(enumerator) { + while((info = g_file_enumerator_next_file(enumerator, NULL, NULL))) { + file = g_file_get_child(template_dir, g_file_info_get_name(info)); + g_object_set_data_full(G_OBJECT(file), "info", info, g_object_unref); + files = g_list_prepend(files, file); + } - g_object_unref(enumerator); - } + g_object_unref(enumerator); + } - files = g_list_sort(files, compare_template_files); + files = g_list_sort(files, compare_template_files); - for(lp = files; lp != NULL; lp = lp->next) { - file = lp->data; - info = g_object_get_data(G_OBJECT(file), "info"); + for(lp = files; lp != NULL && items < fmanager->priv->max_templates; lp = lp->next) { + file = lp->data; + info = g_object_get_data(G_OBJECT(file), "info"); - if(g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) { - /* allocate a new submenu for the directory */ - submenu = gtk_menu_new(); - g_object_ref_sink(submenu); - gtk_menu_set_screen(GTK_MENU(submenu), gtk_widget_get_screen(menu)); + /* Skip directories */ + if(g_file_info_get_file_type(info) != G_FILE_TYPE_DIRECTORY) { + /* skip hidden & backup files */ + if(g_file_info_get_is_hidden(info) || g_file_info_get_is_backup(info)) { + g_object_unref(file); + continue; + } - /* fill the submenu from the folder contents */ - have_templates = xfdesktop_file_icon_menu_fill_template_menu(submenu, file, fmanager) - || have_templates; + /* generate a label by stripping off the extension */ + label = g_strdup(g_file_info_get_display_name(info)); + dot = g_utf8_strrchr(label, -1, '.'); + if(dot) + *dot = '\0'; - /* check if any items were added to the submenu */ - if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(submenu))) - { - /* create a new menu item for the submenu */ - item = gtk_image_menu_item_new_with_label (g_file_info_get_display_name(info)); - icon = g_file_info_get_icon(info); - image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - } + /* allocate a new menu item */ + item = gtk_image_menu_item_new_with_label(label); - /* cleanup */ - g_object_unref (submenu); - } else { - /* generate a label by stripping off the extension */ - label = g_strdup(g_file_info_get_display_name(info)); - dot = g_utf8_strrchr(label, -1, '.'); - if(dot) - *dot = '\0'; + /* determine the icon to display */ + icon = g_file_info_get_icon(info); + image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - /* allocate a new menu item */ - item = gtk_image_menu_item_new_with_label(label); - icon = g_file_info_get_icon(info); - image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_widget_show(item); + /* add the item to the menu */ + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); - g_object_set_data_full(G_OBJECT(item), "file", - g_object_ref(file), g_object_unref); + g_object_set_data_full(G_OBJECT(item), "file", + g_object_ref(file), g_object_unref); - g_signal_connect (G_OBJECT(item), "activate", - G_CALLBACK(xfdesktop_file_icon_template_item_activated), - fmanager); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(xfdesktop_file_icon_template_item_activated), + fmanager); - have_templates = TRUE; - } + have_templates = TRUE; + /* keep it under fmanager->priv->max_templates otherwise the menu + * could have tons of items and be unusable */ + items++; + } - g_object_unref(file); - } + g_object_unref(file); + } - g_list_free(files); + g_list_free(files); - return have_templates; + return have_templates; } #ifdef HAVE_THUNARX @@ -1454,45 +1467,49 @@ xfdesktop_file_icon_manager_populate_context_menu(XfceDesktop *desktop, gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img); gtk_widget_show(img); - /* create from template submenu */ + /* create from template submenu, 0 disables the sub-menu */ + if(fmanager->priv->max_templates > 0) { + mi = gtk_menu_item_new_with_mnemonic(_("Create From _Template")); + gtk_widget_show(mi); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); - mi = gtk_menu_item_new_with_mnemonic(_("Create From _Template")); - gtk_widget_show(mi); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); - - tmpl_menu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), tmpl_menu); - - home_dir = g_file_new_for_path(xfce_get_homedir()); - templates_dir_path = g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES); - if(templates_dir_path) { - templates_dir = g_file_new_for_path(templates_dir_path); - } + tmpl_menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), tmpl_menu); - if(templates_dir && !g_file_equal(home_dir, templates_dir)) - { - xfdesktop_file_icon_menu_fill_template_menu(tmpl_menu, - templates_dir, - fmanager); - } + /* check if XDG_TEMPLATES_DIR="$HOME" and don't show + * templates if so. */ + home_dir = g_file_new_for_path(xfce_get_homedir()); + templates_dir_path = g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES); + if(templates_dir_path) { + templates_dir = g_file_new_for_path(templates_dir_path); + } - if(templates_dir) - g_object_unref(templates_dir); - g_object_unref(home_dir); + if(templates_dir && !g_file_equal(home_dir, templates_dir)) + { + xfdesktop_file_icon_menu_fill_template_menu(tmpl_menu, + templates_dir, + fmanager); + } - img = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); - gtk_widget_show(img); - mi = gtk_image_menu_item_new_with_mnemonic(_("_Empty File")); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img); - gtk_widget_show(mi); - gtk_menu_shell_append(GTK_MENU_SHELL(tmpl_menu), mi); - g_signal_connect(G_OBJECT(mi), "activate", - G_CALLBACK(xfdesktop_file_icon_template_item_activated), - fmanager); - - mi = gtk_separator_menu_item_new(); - gtk_widget_show(mi); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); + if(templates_dir) + g_object_unref(templates_dir); + g_object_unref(home_dir); + + /* add the "Empty File" template option */ + img = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); + gtk_widget_show(img); + mi = gtk_image_menu_item_new_with_mnemonic(_("_Empty File")); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img); + gtk_widget_show(mi); + gtk_menu_shell_append(GTK_MENU_SHELL(tmpl_menu), mi); + g_signal_connect(G_OBJECT(mi), "activate", + G_CALLBACK(xfdesktop_file_icon_template_item_activated), + fmanager); + + mi = gtk_separator_menu_item_new(); + gtk_widget_show(mi); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); + } } } else { if(xfdesktop_file_utils_file_is_executable(info)) { @@ -3604,6 +3621,8 @@ xfdesktop_file_icon_manager_new(GFile *folder, G_OBJECT(fmanager), "show-unknown-volume"); xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_THUMBNAILS, G_TYPE_BOOLEAN, G_OBJECT(fmanager), "show-thumbnails"); + xfconf_g_property_bind(channel, DESKTOP_ICONS_MAX_TEMPLATE_FILES, G_TYPE_INT, + G_OBJECT(fmanager), "max-templates"); return XFDESKTOP_ICON_VIEW_MANAGER(fmanager); } @@ -3707,6 +3726,18 @@ xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manage } static void +xfdesktop_file_icon_manager_set_max_templates(XfdesktopFileIconManager *manager, + gint max_templates) +{ + g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager)); + + if(max_templates < 0 || max_templates > G_MAXUSHORT) + return; + + manager->priv->max_templates = max_templates; +} + +static void xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager, XfdesktopSpecialFileIconType type, gboolean show_special_file) -- 1.8.3.2