Commit 7af769f9 authored by Federico Mena Quintero's avatar Federico Mena Quintero Committed by Federico Mena Quintero
Browse files

Fix #132314.

2004-01-27  Federico Mena Quintero  <federico@ximian.com>

	Fix #132314.

	* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.

	* gtk/gtkfilesystem.c: Likewise.

	* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
	icon-type code.
	(gtk_file_system_unix_render_icon): Moved the icon-rendering code
	from GtkFileInfo to here.
	(gtk_file_system_unix_volume_render_icon): Implement.
parent 320166f2
2004-01-27 Federico Mena Quintero <federico@ximian.com>
Fix #132314.
* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.
* gtk/gtkfilesystem.c: Likewise.
* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
icon-type code.
(gtk_file_system_unix_render_icon): Moved the icon-rendering code
from GtkFileInfo to here.
(gtk_file_system_unix_volume_render_icon): Implement.
2004-01-28 Changwoo Ryu <cwryu@debian.org>
* modules/input/imhangul-defs.h:
......
2004-01-27 Federico Mena Quintero <federico@ximian.com>
Fix #132314.
* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.
* gtk/gtkfilesystem.c: Likewise.
* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
icon-type code.
(gtk_file_system_unix_render_icon): Moved the icon-rendering code
from GtkFileInfo to here.
(gtk_file_system_unix_volume_render_icon): Implement.
2004-01-28 Changwoo Ryu <cwryu@debian.org>
* modules/input/imhangul-defs.h:
......
2004-01-27 Federico Mena Quintero <federico@ximian.com>
Fix #132314.
* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.
* gtk/gtkfilesystem.c: Likewise.
* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
icon-type code.
(gtk_file_system_unix_render_icon): Moved the icon-rendering code
from GtkFileInfo to here.
(gtk_file_system_unix_volume_render_icon): Implement.
2004-01-28 Changwoo Ryu <cwryu@debian.org>
* modules/input/imhangul-defs.h:
......
2004-01-27 Federico Mena Quintero <federico@ximian.com>
Fix #132314.
* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.
* gtk/gtkfilesystem.c: Likewise.
* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
icon-type code.
(gtk_file_system_unix_render_icon): Moved the icon-rendering code
from GtkFileInfo to here.
(gtk_file_system_unix_volume_render_icon): Implement.
2004-01-28 Changwoo Ryu <cwryu@debian.org>
* modules/input/imhangul-defs.h:
......
2004-01-27 Federico Mena Quintero <federico@ximian.com>
Fix #132314.
* gtk/gtkfilesystem.h: Removed the #ifdef-ed out, old icon API.
* gtk/gtkfilesystem.c: Likewise.
* gtk/gtkfilesystemunix.c (filename_get_info): Removed the old
icon-type code.
(gtk_file_system_unix_render_icon): Moved the icon-rendering code
from GtkFileInfo to here.
(gtk_file_system_unix_volume_render_icon): Implement.
2004-01-28 Changwoo Ryu <cwryu@debian.org>
* modules/input/imhangul-defs.h:
......
......@@ -31,9 +31,6 @@ struct _GtkFileInfo
gchar *display_name;
gchar *display_key;
gchar *mime_type;
#if 0
GtkFileIconType icon_type : 4;
#endif
guint is_folder : 1;
guint is_hidden : 1;
};
......@@ -247,169 +244,6 @@ gtk_file_info_set_size (GtkFileInfo *info,
info->size = size;
}
#if 0
void
gtk_file_info_set_icon_type (GtkFileInfo *info,
GtkFileIconType icon_type)
{
g_return_if_fail (info != NULL);
info->icon_type = icon_type;
}
GtkFileIconType
gtk_file_info_get_icon_type (const GtkFileInfo *info)
{
g_return_val_if_fail (info != NULL, GTK_FILE_ICON_REGULAR);
return info->icon_type;
}
typedef struct _IconCacheElement IconCacheElement;
struct _IconCacheElement
{
gint size;
GdkPixbuf *pixbuf;
};
static void
icon_cache_element_free (IconCacheElement *element)
{
if (element->pixbuf)
g_object_unref (element->pixbuf);
g_free (element);
}
static void
icon_theme_changed (GtkIconTheme *icon_theme)
{
GHashTable *cache;
/* Difference from the initial creation is that we don't
* reconnect the signal
*/
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)icon_cache_element_free);
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
cache, (GDestroyNotify)g_hash_table_destroy);
}
static GdkPixbuf *
get_cached_icon (GtkWidget *widget,
const gchar *name,
gint pixel_size)
{
GtkIconTheme *icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
GHashTable *cache = g_object_get_data (G_OBJECT (icon_theme), "gtk-file-icon-cache");
IconCacheElement *element;
if (!cache)
{
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)icon_cache_element_free);
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
cache, (GDestroyNotify)g_hash_table_destroy);
g_signal_connect (icon_theme, "changed",
G_CALLBACK (icon_theme_changed), NULL);
}
element = g_hash_table_lookup (cache, name);
if (!element)
{
element = g_new0 (IconCacheElement, 1);
g_hash_table_insert (cache, g_strdup (name), element);
}
if (element->size != pixel_size)
{
if (element->pixbuf)
g_object_unref (element->pixbuf);
element->size = pixel_size;
element->pixbuf = gtk_icon_theme_load_icon (icon_theme, name,
pixel_size, 0, NULL);
}
return element->pixbuf ? g_object_ref (element->pixbuf) : NULL;
}
GdkPixbuf *
gtk_file_info_render_icon (const GtkFileInfo *info,
GtkWidget *widget,
gint pixel_size)
{
const gchar *separator;
GdkPixbuf *pixbuf;
GString *icon_name;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (widget != NULL, NULL);
g_return_val_if_fail (pixel_size > 0, NULL);
if (info->icon_type != GTK_FILE_ICON_REGULAR)
{
const char *name = NULL; /* Quiet gcc */
switch (info->icon_type)
{
case GTK_FILE_ICON_BLOCK_DEVICE:
name ="gnome-fs-blockdev";
break;
case GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK:
name = "gnome-fs-symlink";
break;
case GTK_FILE_ICON_CHARACTER_DEVICE:
name = "gnome-fs-chardev";
break;
case GTK_FILE_ICON_DIRECTORY:
name = "gnome-fs-directory";
break;
case GTK_FILE_ICON_EXECUTABLE:
name ="gnome-fs-executable";
break;
case GTK_FILE_ICON_FIFO:
name = "gnome-fs-fifo";
break;
case GTK_FILE_ICON_SOCKET:
name = "gnome-fs-socket";
break;
case GTK_FILE_ICON_REGULAR:
g_assert_not_reached ();
}
return get_cached_icon (widget, name, pixel_size);
}
if (!info->mime_type)
return NULL;
separator = strchr (info->mime_type, '/');
if (!separator)
return NULL;
icon_name = g_string_new ("gnome-mime-");
g_string_append_len (icon_name, info->mime_type, separator - info->mime_type);
g_string_append_c (icon_name, '-');
g_string_append (icon_name, separator + 1);
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
g_string_free (icon_name, TRUE);
if (pixbuf)
return pixbuf;
icon_name = g_string_new ("gnome-mime-");
g_string_append_len (icon_name, info->mime_type, separator - info->mime_type);
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
g_string_free (icon_name, TRUE);
if (pixbuf)
return pixbuf;
return get_cached_icon (widget, "gnome-fs-regular", pixel_size);
}
#endif
/*****************************************
* GtkFileSystem *
......
......@@ -55,27 +55,9 @@ typedef enum {
GTK_FILE_INFO_MIME_TYPE = 1 << 3,
GTK_FILE_INFO_MODIFICATION_TIME = 1 << 4,
GTK_FILE_INFO_SIZE = 1 << 5,
#if 0
GTK_FILE_INFO_ICON = 1 << 6,
#endif
GTK_FILE_INFO_ALL = (1 << 7) - 1
GTK_FILE_INFO_ALL = (1 << 6) - 1
} GtkFileInfoType;
#if 0
/* Icon type, supplemented by MIME type
*/
typedef enum {
GTK_FILE_ICON_REGULAR, /* Use mime type for icon */
GTK_FILE_ICON_BLOCK_DEVICE,
GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK,
GTK_FILE_ICON_CHARACTER_DEVICE,
GTK_FILE_ICON_DIRECTORY,
GTK_FILE_ICON_EXECUTABLE,
GTK_FILE_ICON_FIFO,
GTK_FILE_ICON_SOCKET
} GtkFileIconType;
#endif
/* GError enumeration for GtkFileSystem
*/
......@@ -122,14 +104,6 @@ void gtk_file_info_set_modification_time (GtkFileInfo *in
gint64 gtk_file_info_get_size (const GtkFileInfo *info);
void gtk_file_info_set_size (GtkFileInfo *info,
gint64 size);
#if 0
void gtk_file_info_set_icon_type (GtkFileInfo *info,
GtkFileIconType icon_type);
GtkFileIconType gtk_file_info_get_icon_type (const GtkFileInfo *info);
GdkPixbuf * gtk_file_info_render_icon (const GtkFileInfo *info,
GtkWidget *widget,
gint pixel_size);
#endif
/* The base GtkFileSystem interface
*/
......
......@@ -20,6 +20,7 @@
#include "gtkfilesystem.h"
#include "gtkfilesystemunix.h"
#include "gtkicontheme.h"
#include "gtkintl.h"
#define XDG_PREFIX _gtk_xdg
......@@ -47,10 +48,20 @@ struct _GtkFileSystemUnix
GObject parent_instance;
};
/* Simple stub for our returned volumes */
typedef struct {
int dummy;
} Volume;
/* Icon type, supplemented by MIME type
*/
typedef enum {
ICON_NONE,
ICON_REGULAR, /* Use mime type for icon */
ICON_BLOCK_DEVICE,
ICON_BROKEN_SYMBOLIC_LINK,
ICON_CHARACTER_DEVICE,
ICON_DIRECTORY,
ICON_EXECUTABLE,
ICON_FIFO,
ICON_SOCKET
} IconType;
#define GTK_TYPE_FILE_FOLDER_UNIX (gtk_file_folder_unix_get_type ())
#define GTK_FILE_FOLDER_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnix))
......@@ -386,6 +397,128 @@ gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system,
return g_strdup (_("Filesystem")); /* Same as Nautilus */
}
static IconType
get_icon_type (const char *filename,
GError **error)
{
struct stat statbuf;
IconType icon_type;
/* If stat fails, try to fall back to lstat to catch broken links
*/
if (stat (filename, &statbuf) != 0 &&
lstat (filename, &statbuf) != 0)
{
gchar *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
_("error getting information for '%s': %s"),
filename_utf8 ? filename_utf8 : "???",
g_strerror (errno));
g_free (filename_utf8);
return ICON_NONE;
}
if (S_ISBLK (statbuf.st_mode))
icon_type = ICON_BLOCK_DEVICE;
else if (S_ISLNK (statbuf.st_mode))
icon_type = ICON_BROKEN_SYMBOLIC_LINK; /* See above */
else if (S_ISCHR (statbuf.st_mode))
icon_type = ICON_CHARACTER_DEVICE;
else if (S_ISDIR (statbuf.st_mode))
icon_type = ICON_DIRECTORY;
else if (S_ISFIFO (statbuf.st_mode))
icon_type = ICON_FIFO;
else if (S_ISSOCK (statbuf.st_mode))
icon_type = ICON_SOCKET;
else
{
icon_type = ICON_REGULAR;
#if 0
if ((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR &&
(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
(strcmp (mime_type, XDG_MIME_TYPE_UNKNOWN) == 0 ||
strcmp (mime_type, "application/x-executable") == 0 ||
strcmp (mime_type, "application/x-shellscript") == 0))
gtk_file_info_set_icon_type (info, GTK_FILE_ICON_EXECUTABLE);
#endif
}
return icon_type;
}
typedef struct
{
gint size;
GdkPixbuf *pixbuf;
} IconCacheElement;
static void
icon_cache_element_free (IconCacheElement *element)
{
if (element->pixbuf)
g_object_unref (element->pixbuf);
g_free (element);
}
static void
icon_theme_changed (GtkIconTheme *icon_theme)
{
GHashTable *cache;
/* Difference from the initial creation is that we don't
* reconnect the signal
*/
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)icon_cache_element_free);
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
cache, (GDestroyNotify)g_hash_table_destroy);
}
static GdkPixbuf *
get_cached_icon (GtkWidget *widget,
const gchar *name,
gint pixel_size)
{
GtkIconTheme *icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
GHashTable *cache = g_object_get_data (G_OBJECT (icon_theme), "gtk-file-icon-cache");
IconCacheElement *element;
if (!cache)
{
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)icon_cache_element_free);
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
cache, (GDestroyNotify)g_hash_table_destroy);
g_signal_connect (icon_theme, "changed",
G_CALLBACK (icon_theme_changed), NULL);
}
element = g_hash_table_lookup (cache, name);
if (!element)
{
element = g_new0 (IconCacheElement, 1);
g_hash_table_insert (cache, g_strdup (name), element);
}
if (element->size != pixel_size)
{
if (element->pixbuf)
g_object_unref (element->pixbuf);
element->size = pixel_size;
element->pixbuf = gtk_icon_theme_load_icon (icon_theme, name,
pixel_size, 0, NULL);
}
return element->pixbuf ? g_object_ref (element->pixbuf) : NULL;
}
static GdkPixbuf *
gtk_file_system_unix_volume_render_icon (GtkFileSystem *file_system,
GtkFileSystemVolume *volume,
......@@ -393,7 +526,8 @@ gtk_file_system_unix_volume_render_icon (GtkFileSystem *file_system,
gint pixel_size,
GError **error)
{
return NULL; /* FIXME: We need a hard disk icon or something */
/* FIXME: set the GError if we can't load the icon */
return get_cached_icon (widget, "gnome-fs-blockdev", pixel_size);
}
static gboolean
......@@ -641,12 +775,85 @@ gtk_file_system_unix_render_icon (GtkFileSystem *file_system,
gint pixel_size,
GError **error)
{
/* FIXME: Implement this */
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_FAILED,
_("This file system does not support icons"));
return NULL;
const char *filename;
IconType icon_type;
const char *mime_type;
filename = gtk_file_path_get_string (path);
icon_type = get_icon_type (filename, error);
/* FIXME: this function should not return NULL without setting the GError; we
* should perhaps provide a "never fails" generic stock icon for when all else
* fails.
*/
if (icon_type == ICON_NONE)
return NULL;
if (icon_type != ICON_REGULAR)
{
const char *name;
switch (icon_type)
{
case ICON_BLOCK_DEVICE:
name = "gnome-fs-blockdev";
break;
case ICON_BROKEN_SYMBOLIC_LINK:
name = "gnome-fs-symlink";
break;
case ICON_CHARACTER_DEVICE:
name = "gnome-fs-chardev";
break;
case ICON_DIRECTORY:
name = "gnome-fs-directory";
break;
case ICON_EXECUTABLE:
name ="gnome-fs-executable";
break;
case ICON_FIFO:
name = "gnome-fs-fifo";
break;
case ICON_SOCKET:
name = "gnome-fs-socket";
break;
default:
g_assert_not_reached ();
return NULL;
}
return get_cached_icon (widget, name, pixel_size);
}
mime_type = xdg_mime_get_mime_type_for_file (filename);
if (mime_type)
{
const char *separator;
GString *icon_name;
GdkPixbuf *pixbuf;
separator = strchr (mime_type, '/');
if (!separator)
return NULL;
icon_name = g_string_new ("gnome-mime-");
g_string_append_len (icon_name, mime_type, separator - mime_type);
g_string_append_c (icon_name, '-');
g_string_append (icon_name, separator + 1);
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
g_string_free (icon_name, TRUE);
if (pixbuf)
return pixbuf;
icon_name = g_string_new ("gnome-mime-");
g_string_append_len (icon_name, mime_type, separator - mime_type);
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
g_string_free (icon_name, TRUE);
if (pixbuf)
return pixbuf;
}
return get_cached_icon (widget, "gnome-fs-regular", pixel_size);
}
static gboolean
......@@ -830,9 +1037,6 @@ filename_get_info (const gchar *filename,
GError **error)
{
GtkFileInfo *info;
#if 0
GtkFileIconType icon_type = GTK_FILE_ICON_REGULAR;
#endif
struct stat statbuf;
/* If stat fails, try to fall back to lstat to catch broken links
......@@ -890,42 +1094,10 @@ filename_get_info (const gchar *filename,
gtk_file_info_set_is_folder (info, S_ISDIR (statbuf.st_mode));
}
#if 0
if (types & GTK_FILE_INFO_ICON)
{
if (S_ISBLK (statbuf.st_mode))
icon_type = GTK_FILE_ICON_BLOCK_DEVICE;
else if (S_ISLNK (statbuf.st_mode))
icon_type = GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK;
else if (S_ISCHR (statbuf.st_mode))
icon_type = GTK_FILE_ICON_CHARACTER_DEVICE;
else if (S_ISDIR (statbuf.st_mode))
icon_type = GTK_FILE_ICON_DIRECTORY;
else if (S_ISFIFO (statbuf.st_mode))
icon_type = GTK_FILE_ICON_FIFO;
else if (S_ISSOCK (statbuf.st_mode))
icon_type = GTK_FILE_ICON_SOCKET;
gtk_file_info_set_icon_type (info, icon_type);
}
if ((types & GTK_FILE_INFO_MIME_TYPE) ||
((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR))
#else
if (types & GTK_FILE_INFO_MIME_TYPE)
#endif
{
const char *mime_type = xdg_mime_get_mime_type_for_file (filename);
gtk_file_info_set_mime_type (info, mime_type);
#if 0
if ((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR &&
(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
(strcmp (mime_type, XDG_MIME_TYPE_UNKNOWN) == 0 ||
strcmp (mime_type, "application/x-executable") == 0 ||
strcmp (mime_type, "application/x-shellscript") == 0))
gtk_file_info_set_icon_type (info, GTK_FILE_ICON_EXECUTABLE);
#endif
}
if (types & GTK_FILE_INFO_MODIFICATION_TIME)
......