/* * xfdesktop - xfce4's desktop manager * * Copyright(c) 2006 Brian Tarricone, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #include #include #include #include #include #ifdef HAVE_THUNARX #include #endif #include "xfdesktop-dbus-bindings-filemanager.h" #include "xfdesktop-file-icon.h" #include "xfdesktop-file-utils.h" ThunarVfsInteractiveJobResponse xfdesktop_file_utils_interactive_job_ask(GtkWindow *parent, const gchar *message, ThunarVfsInteractiveJobResponse choices) { GtkWidget *dlg, *btn; gint resp; dlg = xfce_message_dialog_new(parent, _("Question"), GTK_STOCK_DIALOG_QUESTION, NULL, message, NULL); if(choices & THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_CANCEL) { btn = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_widget_show(btn); gtk_dialog_add_action_widget(GTK_DIALOG(dlg), btn, THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_CANCEL); } if(choices & THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_NO) { btn = gtk_button_new_from_stock(GTK_STOCK_NO); gtk_widget_show(btn); gtk_dialog_add_action_widget(GTK_DIALOG(dlg), btn, THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_NO); } if(choices & THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES_ALL) { btn = gtk_button_new_with_mnemonic(_("Yes to _all")); gtk_widget_show(btn); gtk_dialog_add_action_widget(GTK_DIALOG(dlg), btn, THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES_ALL); } if(choices & THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES) { btn = gtk_button_new_from_stock(GTK_STOCK_YES); gtk_widget_show(btn); gtk_dialog_add_action_widget(GTK_DIALOG(dlg), btn, THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES); } resp = gtk_dialog_run(GTK_DIALOG(dlg)); gtk_widget_destroy(dlg); return (ThunarVfsInteractiveJobResponse)resp; } void xfdesktop_file_utils_handle_fileop_error(GtkWindow *parent, const ThunarVfsInfo *src_info, const ThunarVfsInfo *dest_info, XfdesktopFileUtilsFileop fileop, GError *error) { if(error) { gchar *primary_fmt, *primary; switch(fileop) { case XFDESKTOP_FILE_UTILS_FILEOP_MOVE: primary_fmt = _("There was an error moving \"%s\" to \"%s\":"); break; case XFDESKTOP_FILE_UTILS_FILEOP_COPY: primary_fmt = _("There was an error copying \"%s\" to \"%s\":"); break; case XFDESKTOP_FILE_UTILS_FILEOP_LINK: primary_fmt = _("There was an error linking \"%s\" to \"%s\":"); break; default: return; } primary = g_strdup_printf(primary_fmt, src_info->display_name, dest_info->display_name); xfce_message_dialog(parent, _("File Error"), GTK_STOCK_DIALOG_ERROR, primary, error->message, GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL); g_free(primary); } } gchar * xfdesktop_file_utils_get_file_kind(const ThunarVfsInfo *info, gboolean *is_link) { gchar *str = NULL; if(!strcmp(thunar_vfs_mime_info_get_name(info->mime_info), "inode/symlink")) { str = g_strdup(_("broken link")); if(is_link) *is_link = TRUE; } else if(info->flags & THUNAR_VFS_FILE_FLAGS_SYMLINK) { str = g_strdup_printf(_("link to %s"), thunar_vfs_mime_info_get_comment(info->mime_info)); if(is_link) *is_link = TRUE; } else { str = g_strdup(thunar_vfs_mime_info_get_comment(info->mime_info)); if(is_link) *is_link = FALSE; } return str; } GList * xfdesktop_file_utils_file_icon_list_to_path_list(GList *icon_list) { GList *path_list = NULL, *l; XfdesktopFileIcon *icon; const ThunarVfsInfo *info; for(l = icon_list; l; l = l->next) { icon = XFDESKTOP_FILE_ICON(l->data); info = xfdesktop_file_icon_peek_info(icon); if(info) { path_list = g_list_prepend(path_list, thunar_vfs_path_ref(info->path)); } } return g_list_reverse(path_list); } static GdkPixbuf *xfdesktop_fallback_icon = NULL; static gint xfdesktop_fallback_icon_size = -1; GdkPixbuf * xfdesktop_file_utils_get_fallback_icon(gint size) { g_return_val_if_fail(size > 0, NULL); if(size != xfdesktop_fallback_icon_size && xfdesktop_fallback_icon) { g_object_unref(G_OBJECT(xfdesktop_fallback_icon)); xfdesktop_fallback_icon = NULL; } if(!xfdesktop_fallback_icon) { xfdesktop_fallback_icon = gdk_pixbuf_new_from_file_at_size(DATADIR "/pixmaps/xfdesktop/xfdesktop-fallback-icon.png", size, size, NULL); } if(G_UNLIKELY(!xfdesktop_fallback_icon)) { GtkWidget *dummy = gtk_invisible_new(); gtk_widget_realize(dummy); /* this is kinda crappy, but hopefully should never happen */ xfdesktop_fallback_icon = gtk_widget_render_icon(dummy, GTK_STOCK_MISSING_IMAGE, (GtkIconSize)-1, NULL); if(gdk_pixbuf_get_width(xfdesktop_fallback_icon) != size || gdk_pixbuf_get_height(xfdesktop_fallback_icon) != size) { GdkPixbuf *tmp = gdk_pixbuf_scale_simple(xfdesktop_fallback_icon, size, size, GDK_INTERP_BILINEAR); g_object_unref(G_OBJECT(xfdesktop_fallback_icon)); xfdesktop_fallback_icon = tmp; } } xfdesktop_fallback_icon_size = size; return g_object_ref(G_OBJECT(xfdesktop_fallback_icon)); } GdkPixbuf * xfdesktop_file_utils_get_file_icon(const gchar *custom_icon_name, ThunarVfsInfo *info, gint size, const GdkPixbuf *emblem, guint opacity) { GdkPixbuf *pix_theme = NULL, *pix = NULL; const gchar *icon_name; if(custom_icon_name) pix_theme = xfce_themed_icon_load(custom_icon_name, size); if(!pix_theme && info) { icon_name = thunar_vfs_info_get_custom_icon(info); if(icon_name) pix_theme = xfce_themed_icon_load(icon_name, size); } if(!pix_theme && info && info->mime_info) { icon_name = thunar_vfs_mime_info_lookup_icon_name(info->mime_info, gtk_icon_theme_get_default()); DBG("got mime info icon name: %s", icon_name); if(icon_name) pix_theme = xfce_themed_icon_load(icon_name, size); } if(G_LIKELY(pix_theme)) { /* we can't edit thsese icons */ pix = gdk_pixbuf_copy(pix_theme); g_object_unref(G_OBJECT(pix_theme)); pix_theme = NULL; } /* fallback */ if(G_UNLIKELY(!pix)) pix = xfdesktop_file_utils_get_fallback_icon(size); /* sanity check */ g_return_val_if_fail(pix, NULL); if(emblem) { gint emblem_pix_size = gdk_pixbuf_get_width(emblem); gint dest_size = size - emblem_pix_size; /* if we're using the fallback icon, we don't want to draw an emblem on * it, since other icons might use it without the emblem */ if(G_UNLIKELY(pix == xfdesktop_fallback_icon)) { GdkPixbuf *tmp = gdk_pixbuf_copy(pix); g_object_unref(G_OBJECT(pix)); pix = tmp; } if(dest_size < 0) g_critical("xfdesktop_file_utils_get_file_icon(): (dest_size > 0) failed"); else { DBG("calling gdk_pixbuf_composite(%p, %p, %d, %d, %d, %d, %.1f, %.1f, %.1f, %.1f, %d, %d)", emblem, pix, dest_size, dest_size, emblem_pix_size, emblem_pix_size, (gdouble)dest_size, (gdouble)dest_size, 1.0, 1.0, GDK_INTERP_BILINEAR, 255); gdk_pixbuf_composite(emblem, pix, dest_size, dest_size, emblem_pix_size, emblem_pix_size, dest_size, dest_size, 1.0, 1.0, GDK_INTERP_BILINEAR, 255); } } #ifdef HAVE_LIBEXO if(opacity != 100) { GdkPixbuf *tmp = exo_gdk_pixbuf_lucent(pix, opacity); g_object_unref(G_OBJECT(pix)); pix = tmp; } #endif return pix; } void xfdesktop_file_utils_set_window_cursor(GtkWindow *window, GdkCursorType cursor_type) { GdkCursor *cursor; if(!window || !GTK_WIDGET(window)->window) return; cursor = gdk_cursor_new(cursor_type); if(G_LIKELY(cursor)) { gdk_window_set_cursor(GTK_WIDGET(window)->window, cursor); gdk_cursor_unref(cursor); } } gboolean xfdesktop_file_utils_launch_fallback(const ThunarVfsInfo *info, GdkScreen *screen, GtkWindow *parent) { gboolean ret = FALSE; gchar *file_manager_app; g_return_val_if_fail(info, FALSE); file_manager_app = g_find_program_in_path(FILE_MANAGER_FALLBACK); if(file_manager_app) { gchar *commandline, *uri, *display_name; if(!screen && parent) screen = gtk_widget_get_screen(GTK_WIDGET(parent)); else if(!screen) screen = gdk_display_get_default_screen(gdk_display_get_default()); display_name = gdk_screen_make_display_name(screen); uri = thunar_vfs_path_dup_uri(info->path); commandline = g_strconcat("env DISPLAY=\"", display_name, "\" \"", file_manager_app, "\" \"", uri, "\"", NULL); DBG("executing:\n%s\n", commandline); ret = xfce_exec(commandline, FALSE, TRUE, NULL); g_free(commandline); g_free(file_manager_app); g_free(uri); g_free(display_name); } if(!ret) { gchar *primary = g_markup_printf_escaped(_("Unable to launch \"%s\":"), info->display_name); xfce_message_dialog(GTK_WINDOW(parent), _("Launch Error"), GTK_STOCK_DIALOG_ERROR, primary, _("This feature requires a file manager service present (such as that supplied by Thunar)."), GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL); g_free(primary); } return ret; } typedef struct { const ThunarVfsInfo *info; GdkScreen *screen; GtkWindow *parent; } XfdesktopDisplayFolderData; static void xfdesktop_file_utils_display_folder_cb(DBusGProxy *proxy, GError *error, gpointer user_data) { XfdesktopDisplayFolderData *dfdata = user_data; g_return_if_fail(user_data); xfdesktop_file_utils_set_window_cursor(dfdata->parent, GDK_LEFT_PTR); if(error) { xfdesktop_file_utils_launch_fallback(dfdata->info, dfdata->screen, dfdata->parent); } g_free(user_data); } void xfdesktop_file_utils_open_folder(const ThunarVfsInfo *info, GdkScreen *screen, GtkWindow *parent) { DBusGProxy *fileman_proxy; g_return_if_fail(info && (screen || parent)); if(!screen) screen = gtk_widget_get_screen(GTK_WIDGET(parent)); fileman_proxy = xfdesktop_file_utils_peek_filemanager_proxy(); if(fileman_proxy) { XfdesktopDisplayFolderData *dfdata = g_new(XfdesktopDisplayFolderData, 1); gchar *uri = thunar_vfs_path_dup_uri(info->path); gchar *display_name = gdk_screen_make_display_name(screen); dfdata->info = info; dfdata->screen = screen; dfdata->parent = parent; if(!org_xfce_FileManager_display_folder_async(fileman_proxy, uri, display_name, xfdesktop_file_utils_display_folder_cb, dfdata)) { xfdesktop_file_utils_launch_fallback(info, screen, parent); g_free(dfdata); } else xfdesktop_file_utils_set_window_cursor(parent, GDK_WATCH); g_free(uri); g_free(display_name); } else xfdesktop_file_utils_launch_fallback(info, screen, parent); } static gint dbus_ref_cnt = 0; static DBusGConnection *dbus_gconn = NULL; static DBusGProxy *dbus_trash_proxy = NULL; static DBusGProxy *dbus_filemanager_proxy = NULL; gboolean xfdesktop_file_utils_dbus_init(void) { gboolean ret = TRUE; if(dbus_ref_cnt++) return TRUE; if(!dbus_gconn) { dbus_gconn = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); if(G_LIKELY(dbus_gconn)) { /* dbus's default is brain-dead */ DBusConnection *dconn = dbus_g_connection_get_connection(dbus_gconn); dbus_connection_set_exit_on_disconnect(dconn, FALSE); } } if(G_LIKELY(dbus_gconn)) { dbus_trash_proxy = dbus_g_proxy_new_for_name(dbus_gconn, "org.xfce.FileManager", "/org/xfce/FileManager", "org.xfce.Trash"); dbus_g_proxy_add_signal(dbus_trash_proxy, "TrashChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_filemanager_proxy = dbus_g_proxy_new_for_name(dbus_gconn, "org.xfce.FileManager", "/org/xfce/FileManager", "org.xfce.FileManager"); } else { ret = FALSE; dbus_ref_cnt = 0; } return ret; } DBusGProxy * xfdesktop_file_utils_peek_trash_proxy(void) { return dbus_trash_proxy; } DBusGProxy * xfdesktop_file_utils_peek_filemanager_proxy(void) { return dbus_filemanager_proxy; } void xfdesktop_file_utils_dbus_cleanup(void) { if(dbus_ref_cnt == 0 || --dbus_ref_cnt > 0) return; if(dbus_trash_proxy) g_object_unref(G_OBJECT(dbus_trash_proxy)); if(dbus_filemanager_proxy) g_object_unref(G_OBJECT(dbus_filemanager_proxy)); /* we aren't going to unref dbus_gconn because dbus appears to have a * memleak in dbus_connection_setup_with_g_main(). really; the comments * in dbus-gmain.c admit this. */ } #ifdef HAVE_THUNARX /* thunar extension interface stuff: ThunarxFileInfo implementation */ gchar * xfdesktop_thunarx_file_info_get_name(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); if(info) return g_strdup(thunar_vfs_path_get_name(info->path)); else return NULL; } gchar * xfdesktop_thunarx_file_info_get_uri(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); gchar buf[PATH_MAX]; if(!info) return NULL; g_return_val_if_fail(thunar_vfs_path_to_uri(info->path, buf, PATH_MAX, NULL) > 0, NULL); return g_strdup(buf); } gchar * xfdesktop_thunarx_file_info_get_parent_uri(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); ThunarVfsPath *parent; gchar buf[PATH_MAX]; if(!info) return NULL; parent = thunar_vfs_path_get_parent(info->path); if(G_UNLIKELY(!parent)) return NULL; g_return_val_if_fail(thunar_vfs_path_to_uri(parent, buf, PATH_MAX, NULL) > 0, NULL); return g_strdup(buf); } gchar * xfdesktop_thunarx_file_info_get_uri_scheme_file(ThunarxFileInfo *file_info) { return g_strdup("file"); } gchar * xfdesktop_thunarx_file_info_get_mime_type(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); if(!info || !info->mime_info) return NULL; return g_strdup(thunar_vfs_mime_info_get_name(info->mime_info)); } gboolean xfdesktop_thunarx_file_info_has_mime_type(ThunarxFileInfo *file_info, const gchar *mime_type) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); ThunarVfsMimeDatabase *mime_db; GList *mime_infos, *l; ThunarVfsMimeInfo *minfo; gboolean has_type = FALSE; if(!info || !info->mime_info) return FALSE; mime_db = thunar_vfs_mime_database_get_default(); mime_infos = thunar_vfs_mime_database_get_infos_for_info(mime_db, info->mime_info); for(l = mime_infos; l; l = l->next) { minfo = (ThunarVfsMimeInfo *)l->data; if(!g_ascii_strcasecmp(mime_type, thunar_vfs_mime_info_get_name(minfo))) { has_type = TRUE; break; } } thunar_vfs_mime_info_list_free(mime_infos); g_object_unref(G_OBJECT(mime_db)); return has_type; } gboolean xfdesktop_thunarx_file_info_is_directory(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); return (info && info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY); } ThunarVfsInfo * xfdesktop_thunarx_file_info_get_vfs_info(ThunarxFileInfo *file_info) { XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(file_info); const ThunarVfsInfo *info = xfdesktop_file_icon_peek_info(icon); return info ? thunar_vfs_info_copy(info) : NULL; } #endif /* HAVE_THUNARX */