diff options
author | Darin Adler <darin@src.gnome.org> | 2000-02-14 19:38:45 +0000 |
---|---|---|
committer | Darin Adler <darin@src.gnome.org> | 2000-02-14 19:38:45 +0000 |
commit | 291fb2d6939ab04739a86b91e7c138b0396136b9 (patch) | |
tree | 867cbc2d07e35937540dae8a9657395795c36829 /libnautilus-private | |
parent | 6db4c052ff0981ff003b46938b8141b6c03a9674 (diff) | |
download | nautilus-291fb2d6939ab04739a86b91e7c138b0396136b9.tar.gz |
Redid the icon factory to fix a few things:
* libnautilus/nautilus-icon-factory.c:
Redid the icon factory to fix a few things:
- Replaced the existing non-working count-based LRU algorithm with
one that works (uses a linked list).
- Keep resized icons in the cache.
- Hand out a single NautilusScalableIcon when multiple callers ask
for the same icon instead of a new one each time.
- Fixed one bug where pixbuf's would get an extra ref and never get
freed once they are no longer used.
* libnautilus/nautilus-metadata.h:
* src/nautilus-index-title.c (nautilus_index_title_set_up_info):
* libnautilus/nautilus-icon-factory.c
(nautilus_icon_factory_get_icon_for_file):
Added keys for the two pieces of metadata Andy just added.
* libnautilus/gnome-icon-container-private.h:
* libnautilus/gnome-icon-container.c: (scroll),
(make_icon_visible), (set_scroll_region): Fixed the code that
resizes the canvas as items are added and removed to properly
handle the case where the canvas extends into negative-coordinate
territory. This included removing the width and height that were
stored in the private structure.
* libnautilus/nautilus-directory.c: (nautilus_directory_get): Tiny
formatting tweak.
Diffstat (limited to 'libnautilus-private')
-rw-r--r-- | libnautilus-private/gnome-icon-container-private.h | 67 | ||||
-rw-r--r-- | libnautilus-private/gnome-icon-container.c | 80 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory.c | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-factory.c | 855 | ||||
-rw-r--r-- | libnautilus-private/nautilus-metadata.h | 4 |
5 files changed, 573 insertions, 435 deletions
diff --git a/libnautilus-private/gnome-icon-container-private.h b/libnautilus-private/gnome-icon-container-private.h index abb781303..3ee3f4240 100644 --- a/libnautilus-private/gnome-icon-container-private.h +++ b/libnautilus-private/gnome-icon-container-private.h @@ -30,17 +30,17 @@ #include "nautilus-icon-factory.h" #include "nautilus-icons-view-icon-item.h" -/* An Icon. */ +/* An Icon. */ typedef struct { /* Canvas item for the icon. */ NautilusIconsViewIconItem *item; - /* X/Y coordinates and size. We could use the GnomeCanvasItem - * functions, but this is a lot faster + /* X/Y coordinates and size. We could use the GnomeCanvasItem + * functions, but this is a lot faster */ double x, y; - + /* Whether this item is selected for operation. */ gboolean is_selected : 1; @@ -62,29 +62,29 @@ typedef struct { #define INITIAL_GRID_HEIGHT 64 typedef struct { - /* Size of the grid. */ + /* Size of the grid. */ guint width, height; /* This is the width that we can actually use for finding an empty - * position. + * position. */ guint visible_width; - /* Array of grid elements. */ + /* Array of grid elements. */ GList **elems; - /* Size of the allocated array. */ + /* Size of the allocated array. */ guint alloc_width, alloc_height; /* Position of the first free cell (used to speed up progressive - * updates). If negative, there is no free cell. + * updates). If negative, there is no free cell. */ int first_free_x, first_free_y; } GnomeIconContainerIconGrid; -/* Private GnomeIconContainer members. */ +/* Private GnomeIconContainer members. */ typedef struct { gboolean active; @@ -108,65 +108,62 @@ struct _GnomeIconContainerDetails { /* single-click mode setting */ gboolean single_click_mode; - /* Size of the container. */ - guint width, height; - - /* List of icons. */ + /* List of icons. */ GList *icons; guint num_icons; - /* The grid. */ + /* The grid. */ GnomeIconContainerIconGrid *grid; /* FIXME: This is *ugly*, but more efficient (both memory- and - speed-wise) than using gtk_object_{set,get}_data() for all the - icon items. */ + speed-wise) than using gtk_object_{set,get}_data() for all the + icon items. */ GHashTable *canvas_item_to_icon; - /* Current icon for keyboard navigation. */ + /* Current icon for keyboard navigation. */ GnomeIconContainerIcon *kbd_current; /* Rubberbanding status. */ GnomeIconContainerRubberbandInfo rubberband_info; /* Timeout used to make a selected icon fully visible after a short - * period of time. (The timeout is needed to make sure - * double-clicking still works.) + * period of time. (The timeout is needed to make sure + * double-clicking still works.) */ guint kbd_icon_visibility_timer_id; - /* the time the mouse button went down in milliseconds */ - guint32 button_down_time; - - /* Position of the pointer during the last click. */ + /* the time the mouse button went down in milliseconds */ + guint32 button_down_time; + + /* Position of the pointer during the last click. */ int drag_x, drag_y; - /* Button currently pressed, possibly for dragging. */ + /* Button currently pressed, possibly for dragging. */ guint drag_button; - /* Icon on which the click happened. */ + /* Icon on which the click happened. */ GnomeIconContainerIcon *drag_icon; - /* Whether we are actually performing a dragging action. */ + /* Whether we are actually performing a dragging action. */ gboolean doing_drag; - /* Idle ID. */ + /* Idle ID. */ guint idle_id; /* Timeout for selection in browser mode. */ guint linger_selection_mode_timer_id; - /* Icon to be selected at timeout in browser mode. */ + /* Icon to be selected at timeout in browser mode. */ GnomeIconContainerIcon *linger_selection_mode_icon; - /* DnD info. */ + /* DnD info. */ GnomeIconContainerDndInfo *dnd_info; - /* zoom level */ - int zoom_level; - - /* default fonts used to draw labels */ - GdkFont *label_font[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]; + /* zoom level */ + int zoom_level; + + /* default fonts used to draw labels */ + GdkFont *label_font[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]; }; /* Layout and icon size constants. diff --git a/libnautilus-private/gnome-icon-container.c b/libnautilus-private/gnome-icon-container.c index a4803b7b4..d42943a86 100644 --- a/libnautilus-private/gnome-icon-container.c +++ b/libnautilus-private/gnome-icon-container.c @@ -598,40 +598,13 @@ static void scroll (GnomeIconContainer *container, int delta_x, int delta_y) { - GnomeIconContainerDetails *details; GtkAdjustment *hadj, *vadj; - GtkAllocation *allocation; - gfloat vnew, hnew; - gfloat hmax, vmax; - - details = container->details; hadj = GTK_LAYOUT (container)->hadjustment; vadj = GTK_LAYOUT (container)->vadjustment; - allocation = >K_WIDGET (container)->allocation; - - if (container->details->width > allocation->width) - hmax = (gfloat) (container->details->width - allocation->width); - else - hmax = 0.0; - - if (container->details->height > allocation->height) - vmax = (gfloat) (container->details->height - allocation->height); - else - vmax = 0.0; - - hnew = CLAMP (hadj->value + (gfloat) delta_x, 0.0, hmax); - vnew = CLAMP (vadj->value + (gfloat) delta_y, 0.0, vmax); - - if (hnew != hadj->value) { - hadj->value = hnew; - gtk_signal_emit_by_name (GTK_OBJECT (hadj), "value_changed"); - } - if (vnew != vadj->value) { - vadj->value = vnew; - gtk_signal_emit_by_name (GTK_OBJECT (vadj), "value_changed"); - } + gtk_adjustment_set_value (hadj, hadj->value + delta_x); + gtk_adjustment_set_value (vadj, vadj->value + delta_y); } static void @@ -646,10 +619,6 @@ make_icon_visible (GnomeIconContainer *container, details = container->details; allocation = >K_WIDGET (container)->allocation; - if (details->height < allocation->height - && details->width < allocation->width) - return; - hadj = GTK_LAYOUT (container)->hadjustment; vadj = GTK_LAYOUT (container)->vadjustment; @@ -845,41 +814,36 @@ set_kbd_current (GnomeIconContainer *container, static void set_scroll_region (GnomeIconContainer *container) { - GnomeIconContainerDetails *details; - GnomeIconContainerIconGrid *grid; + double x1, y1, x2, y2; + double content_width, content_height; + double scroll_width, scroll_height; GtkAllocation *allocation; GtkAdjustment *vadj, *hadj; - double x1, y1, x2, y2; - guint scroll_width, scroll_height; - - details = container->details; - grid = details->grid; - allocation = &(GTK_WIDGET (container)->allocation); - hadj = GTK_LAYOUT (container)->hadjustment; - vadj = GTK_LAYOUT (container)->vadjustment; - /* FIXME: We can do this more efficiently. */ gnome_canvas_item_get_bounds (GNOME_CANVAS (container)->root, &x1, &y1, &x2, &y2); - details->width = x2 + GNOME_ICON_CONTAINER_CELL_SPACING (container); - details->height = y2 + GNOME_ICON_CONTAINER_CELL_SPACING (container); + content_width = x2 - x1 + GNOME_ICON_CONTAINER_CELL_SPACING (container); + content_height = y2 - y1 + GNOME_ICON_CONTAINER_CELL_SPACING (container); - scroll_width = MAX (details->width, allocation->width); - scroll_height = MAX (details->height, allocation->height); + allocation = >K_WIDGET (container)->allocation; - scroll_width--; - scroll_height--; + scroll_width = MAX (content_width, allocation->width); + scroll_height = MAX (content_height, allocation->height); + /* FIXME: Why are we subtracting one from each dimension? */ gnome_canvas_set_scroll_region (GNOME_CANVAS (container), - 0.0, 0.0, - (double) scroll_width, - (double) scroll_height); - - if (details->width <= allocation->width) - gtk_adjustment_set_value (hadj, 0.0); - if (details->height <= allocation->height) - gtk_adjustment_set_value (vadj, 0.0); + x1, y1, + x1 + scroll_width - 1, + y1 + scroll_height - 1); + + hadj = GTK_LAYOUT (container)->hadjustment; + vadj = GTK_LAYOUT (container)->vadjustment; + + if (content_width <= allocation->width) + gtk_adjustment_set_value (hadj, x1); + if (content_height <= allocation->height) + gtk_adjustment_set_value (vadj, y1); } static gboolean diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index ee1c4c3f7..15769d07c 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -249,7 +249,7 @@ nautilus_directory_get (const char *uri) } else { /* Create a new directory object instead. */ directory = NAUTILUS_DIRECTORY (nautilus_directory_new (uri)); - if(!directory) + if (directory == NULL) return NULL; g_assert (strcmp (directory->details->uri_text, uri) == 0); diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c index bf86db7bf..08045d1af 100644 --- a/libnautilus-private/nautilus-icon-factory.c +++ b/libnautilus-private/nautilus-icon-factory.c @@ -35,88 +35,125 @@ #include "nautilus-string.h" #include "nautilus-default-file-icon.h" +#include "nautilus-metadata.h" + +#define ICON_NAME_DIRECTORY "i-directory.png" +#define ICON_NAME_DIRECTORY_CLOSED "i-dirclosed.png" +#define ICON_NAME_EXECUTABLE "i-executable.png" +#define ICON_NAME_REGULAR "i-regular.png" +#define ICON_NAME_CORE "i-core.png" +#define ICON_NAME_SOCKET "i-sock.png" +#define ICON_NAME_FIFO "i-fifo.png" +#define ICON_NAME_CHARACTER_DEVICE "i-chardev.png" +#define ICON_NAME_BLOCK_DEVICE "i-blockdev.png" +#define ICON_NAME_BROKEN_SYMBOLIC_LINK "i-brokenlink.png" + +#define ICON_NAME_SYMBOLIC_LINK_OVERLAY "i-symlink.png" + +/* This used to be called ICON_CACHE_MAX_ENTRIES, but it's misleading + * to call it that, since we can have any number of entries in the + * cache if the caller keeps the pixbuf around (we only get rid of + * items from the cache after the caller unref's them). +*/ +#define ICON_CACHE_COUNT 20 -#define ICON_CACHE_MAX_ENTRIES 10 -#define ICON_CACHE_SWEEP_TIMEOUT 10 +/* This is the number of milliseconds we wait before sweeping out + * items from the cache. + */ +#define ICON_CACHE_SWEEP_TIMEOUT (10 * 1000) -/* This allows us to do smarter caching */ -static guint use_counter = 0; +/* For now, images are used themselves as thumbnails when they are + * below this threshold size. Later we might have to have a more + * complex rule about when to use an image for itself. + */ +#define SELF_THUMBNAIL_SIZE_THRESHOLD 16384 -typedef struct { - guint ref_count; - char *name; - GdkPixbuf *plain, *symlink; - guint last_use; -} IconSet; - -typedef enum { - ICON_SET_DIRECTORY, - ICON_SET_DIRECTORY_CLOSED, - ICON_SET_EXECUTABLE, - ICON_SET_REGULAR, - ICON_SET_CORE, - ICON_SET_SOCKET, - ICON_SET_FIFO, - ICON_SET_CHARACTER_DEVICE, - ICON_SET_BLOCK_DEVICE, - ICON_SET_BROKEN_SYMBOLIC_LINK, - ICON_SET_FALLBACK, - ICON_SET_SPECIAL_LAST -} SpecialIconSetType; +/* This circular doubly-linked list structure is used to keep a list + * of the most recently used items in the cache. + */ +typedef struct NautilusCircularList NautilusCircularList; +struct NautilusCircularList { + NautilusCircularList *next; + NautilusCircularList *prev; +}; +/* The icon factory. + * These are actually globals, but they're in a structure so we can + * have multiple icon factories some day if we want to. + */ typedef struct { char *theme_name; - GHashTable *name_to_image; - IconSet special_icon_sets[ICON_SET_SPECIAL_LAST]; + /* A hash table so we pass out the same scalable icon pointer + * every time someone asks for the same icon. Scalable icons + * are removed from this hash table when they are destroyed. + */ + GHashTable *scalable_icons; - GdkPixbuf *symlink_overlay; - + /* A hash table that contains a cache of actual images. + * A circular list of the most recently used images is kept + * around, and we don't let them go when we sweep the cache. + */ + GHashTable *icon_cache; + NautilusCircularList recently_used_dummy_head; + guint recently_used_count; guint sweep_timer; + + /* An overlay for symbolic link icons. This is probably going + * to go away when we switch to using little icon badges for + * various keywords. + */ + GdkPixbuf *symbolic_link_overlay; } NautilusIconFactory; +/* A scalable icon, which is basically the name and path of an icon, + * before we load the actual pixels of the icons's image. + */ struct _NautilusScalableIcon { guint ref_count; char *uri; - IconSet *icon_set; + char *name; gboolean is_symbolic_link; }; -/* forward declarations */ -static NautilusIconFactory * nautilus_get_current_icon_factory (void); -static GdkPixbuf * nautilus_icon_factory_scale (NautilusIconFactory *factory, - GdkPixbuf *standard_sized_pixbuf, - guint size_in_pixels); -static NautilusScalableIcon *scalable_icon_get (const char *uri, - IconSet *icon_set, - gboolean is_symbolic_link); - -static IconSet * -icon_set_new (const gchar *name) -{ - IconSet *new; +/* The key to a hash table that holds the scaled icons as pixbufs. + */ +typedef struct { + NautilusScalableIcon *scalable_icon; + guint size_in_pixels; - new = g_new0 (IconSet, 1); - new->name = g_strdup (name); + NautilusCircularList recently_used_node; +} NautilusIconCacheKey; - return new; -} +/* forward declarations */ -static void -icon_set_destroy (IconSet *icon_set, gboolean free_name) +static NautilusIconFactory * nautilus_get_current_icon_factory (void); +static NautilusIconFactory * nautilus_icon_factory_new (const char *theme_name); +static GdkPixbuf * nautilus_icon_factory_scale (GdkPixbuf *standard_sized_image, + guint size_in_pixels); +static NautilusScalableIcon *nautilus_scalable_icon_get (const char *uri, + const char *name, + gboolean is_symbolic_link); +static guint nautilus_scalable_icon_hash (gconstpointer p); +static gboolean nautilus_scalable_icon_equal (gconstpointer a, + gconstpointer b); +static void nautilus_icon_cache_key_destroy (NautilusIconCacheKey *key); +static guint nautilus_icon_cache_key_hash (gconstpointer p); +static gboolean nautilus_icon_cache_key_equal (gconstpointer a, + gconstpointer b); + +/* Return a pointer to the single global icon factory. */ +NautilusIconFactory * +nautilus_get_current_icon_factory (void) { - if (icon_set == NULL) - return; - - if (free_name) - g_free (icon_set->name); - if (icon_set->plain != NULL) - gdk_pixbuf_unref (icon_set->plain); - if (icon_set->symlink != NULL) - gdk_pixbuf_unref (icon_set->symlink); + static NautilusIconFactory *global_icon_factory = NULL; + if (global_icon_factory == NULL) + global_icon_factory = nautilus_icon_factory_new (NULL); + return global_icon_factory; } +/* Create the icon factory. */ static NautilusIconFactory * nautilus_icon_factory_new (const char *theme_name) { @@ -125,44 +162,47 @@ nautilus_icon_factory_new (const char *theme_name) factory = g_new0 (NautilusIconFactory, 1); factory->theme_name = g_strdup (theme_name); - factory->name_to_image = g_hash_table_new (g_str_hash, g_str_equal); - factory->special_icon_sets[ICON_SET_DIRECTORY].name = "i-directory.png"; - factory->special_icon_sets[ICON_SET_DIRECTORY_CLOSED].name = "i-dirclosed.png"; - factory->special_icon_sets[ICON_SET_EXECUTABLE].name = "i-executable.png"; - factory->special_icon_sets[ICON_SET_REGULAR].name = "i-regular.png"; - factory->special_icon_sets[ICON_SET_CORE].name = "i-core.png"; - factory->special_icon_sets[ICON_SET_SOCKET].name = "i-sock.png"; - factory->special_icon_sets[ICON_SET_FIFO].name = "i-fifo.png"; - factory->special_icon_sets[ICON_SET_CHARACTER_DEVICE].name = "i-chardev.png"; - factory->special_icon_sets[ICON_SET_BLOCK_DEVICE].name = "i-blockdev.png"; - factory->special_icon_sets[ICON_SET_BROKEN_SYMBOLIC_LINK].name = "i-brokenlink.png"; - factory->special_icon_sets[ICON_SET_FALLBACK].name = ""; - + factory->scalable_icons = g_hash_table_new (nautilus_scalable_icon_hash, + nautilus_scalable_icon_equal); + factory->icon_cache = g_hash_table_new (nautilus_icon_cache_key_hash, + nautilus_icon_cache_key_equal); + + /* Empty out the recently-used list. */ + factory->recently_used_dummy_head.next = &factory->recently_used_dummy_head; + factory->recently_used_dummy_head.prev = &factory->recently_used_dummy_head; + return factory; } +/* Destroy one image in the cache. */ static gboolean -nautilus_icon_factory_destroy_icon_sets (gpointer key, gpointer value, gpointer user_data) +nautilus_icon_factory_destroy_cached_image (gpointer key, gpointer value, gpointer user_data) { - icon_set_destroy (value, TRUE); + nautilus_icon_cache_key_destroy (key); + gdk_pixbuf_unref (value); return TRUE; } +/* Reset the cache to the default state. */ static void -nautilus_icon_factory_invalidate (NautilusIconFactory *factory) +nautilus_icon_factory_clear (void) { - int i; + NautilusIconFactory *factory; - g_hash_table_foreach_remove (factory->name_to_image, - nautilus_icon_factory_destroy_icon_sets, + factory = nautilus_get_current_icon_factory (); + + g_hash_table_foreach_remove (factory->icon_cache, + nautilus_icon_factory_destroy_cached_image, NULL); - for (i = 0; i < ICON_SET_SPECIAL_LAST; i++) - icon_set_destroy (&factory->special_icon_sets[i], FALSE); + /* Empty out the recently-used list. */ + factory->recently_used_dummy_head.next = &factory->recently_used_dummy_head; + factory->recently_used_dummy_head.prev = &factory->recently_used_dummy_head; + factory->recently_used_count = 0; - if (factory->symlink_overlay) { - gdk_pixbuf_unref (factory->symlink_overlay); - factory->symlink_overlay = NULL; + if (factory->symbolic_link_overlay != NULL) { + gdk_pixbuf_unref (factory->symbolic_link_overlay); + factory->symbolic_link_overlay = NULL; } } @@ -171,8 +211,8 @@ nautilus_icon_factory_invalidate (NautilusIconFactory *factory) static void nautilus_icon_factory_destroy (NautilusIconFactory *factory) { - nautilus_icon_factory_invalidate (factory); - g_hash_table_destroy (factory->name_to_image); + nautilus_icon_factory_clear (); + g_hash_table_destroy (factory->icon_cache); g_free (factory->theme_name); g_free (factory); @@ -181,302 +221,368 @@ nautilus_icon_factory_destroy (NautilusIconFactory *factory) #endif static gboolean -icon_set_possibly_free (gpointer key, gpointer value, gpointer user_data) +nautilus_icon_factory_possibly_free_cached_image (gpointer key, + gpointer value, + gpointer user_data) { - IconSet *is = value; + NautilusIconCacheKey *icon_key; + GdkPixbuf *image; - if (is->last_use > (use_counter - ICON_CACHE_MAX_ENTRIES)) + /* Don't free a cache entry that is in the recently used list. */ + icon_key = key; + if (icon_key->recently_used_node.next != NULL) return FALSE; - if (is->plain && is->plain->ref_count <= 1) { - gdk_pixbuf_unref (is->plain); - is->plain = NULL; - } - - if (is->symlink && is->symlink->ref_count <= 1) { - gdk_pixbuf_unref (is->symlink); - is->symlink = NULL; - } - - if (is->symlink == NULL && is->plain == NULL && is->ref_count == 0) { - g_free (is->name); - return TRUE; - } + /* Don't free a cache entry if the image is still in use. */ + image = value; + if (image->ref_count > 1) + return FALSE; - return FALSE; + /* Free the item. */ + return nautilus_icon_factory_destroy_cached_image (key, value, NULL); } +/* Sweep the cache, freeing any images that are not in use and are + * also not recently used. + */ static gboolean -nautilus_icon_factory_sweep(gpointer data) +nautilus_icon_factory_sweep (gpointer user_data) { NautilusIconFactory *factory; - factory = data; + factory = user_data; + + g_hash_table_foreach_remove (factory->icon_cache, + nautilus_icon_factory_possibly_free_cached_image, + NULL); - g_hash_table_foreach_remove (factory->name_to_image, icon_set_possibly_free, NULL); factory->sweep_timer = 0; return FALSE; } +/* Schedule a timer to do a sweep. */ static void -nautilus_icon_factory_setup_sweep(NautilusIconFactory *factory) +nautilus_icon_factory_schedule_sweep (void) { - if (factory->sweep_timer) - return; + NautilusIconFactory *factory; - if (g_hash_table_size (factory->name_to_image) < ICON_CACHE_MAX_ENTRIES) + factory = nautilus_get_current_icon_factory (); + + if (factory->sweep_timer != 0) return; - factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT * 1000, - nautilus_icon_factory_sweep, factory); + factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT, + nautilus_icon_factory_sweep, + factory); } +/* Change the theme. */ void -nautilus_icon_factory_set_theme(const char *theme_name) +nautilus_icon_factory_set_theme (const char *theme_name) { NautilusIconFactory *factory; factory = nautilus_get_current_icon_factory (); - nautilus_icon_factory_invalidate (factory); + + nautilus_icon_factory_clear (); + g_free (factory->theme_name); factory->theme_name = g_strdup (theme_name); } -static IconSet * -nautilus_icon_factory_get_icon_set_for_file (NautilusIconFactory *factory, NautilusFile *file) +/* Use the MIME type to get the icon name. */ +static const char * +nautilus_icon_factory_get_icon_name_for_regular_file (NautilusFile *file) { - IconSet *icon_set; const char *mime_type; const char *icon_name; mime_type = nautilus_file_get_mime_type (file); - icon_name = NULL; - if (mime_type) + if (mime_type != NULL) { icon_name = gnome_mime_get_value (mime_type, "icon-filename"); + if (icon_name != NULL) + return icon_name; + } - if (icon_name) { - icon_set = g_hash_table_lookup (factory->name_to_image, icon_name); - if (!icon_set) { - icon_set = icon_set_new (icon_name); - g_hash_table_insert (factory->name_to_image, icon_set->name, icon_set); - } - } else { - /* We can't get a name, so we have to do some faking to figure out what set to load */ - if (nautilus_file_is_executable (file)) - icon_set = &factory->special_icon_sets[ICON_SET_EXECUTABLE]; - else - icon_set = &factory->special_icon_sets[ICON_SET_REGULAR]; - } + /* GNOME didn't give us a file name, so we have to fall back on special icon sets. */ + if (nautilus_file_is_executable (file)) + return ICON_NAME_EXECUTABLE; + return ICON_NAME_REGULAR; +} - return icon_set; +/* Get the icon name for a file. */ +static const char * +nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file) +{ + /* Get an icon name based on the file's type. */ + switch (nautilus_file_get_type (file)) { + case GNOME_VFS_FILE_TYPE_DIRECTORY: + return ICON_NAME_DIRECTORY; + case GNOME_VFS_FILE_TYPE_FIFO: + return ICON_NAME_FIFO; + case GNOME_VFS_FILE_TYPE_SOCKET: + return ICON_NAME_SOCKET; + case GNOME_VFS_FILE_TYPE_CHARDEVICE: + return ICON_NAME_CHARACTER_DEVICE; + case GNOME_VFS_FILE_TYPE_BLOCKDEVICE: + return ICON_NAME_BLOCK_DEVICE; + case GNOME_VFS_FILE_TYPE_BROKENSYMLINK: + return ICON_NAME_BROKEN_SYMBOLIC_LINK; + case GNOME_VFS_FILE_TYPE_REGULAR: + case GNOME_VFS_FILE_TYPE_UNKNOWN: + default: + return nautilus_icon_factory_get_icon_name_for_regular_file (file); + } } +/* Given the icon name, load the pixbuf. */ static GdkPixbuf * -nautilus_icon_factory_load_file(NautilusIconFactory *factory, const char *fn) +nautilus_icon_factory_load_file (const char *name) { - char *file_name = NULL; - char cbuf[128]; + NautilusIconFactory *factory; + char *file_name; + char *partial_path; GdkPixbuf *image; - - if(*fn != '/') { - if(factory->theme_name) { - g_snprintf(cbuf, sizeof(cbuf), "nautilus/%s/%s", factory->theme_name, fn); - - file_name = gnome_pixmap_file(cbuf); + + factory = nautilus_get_current_icon_factory (); + + if (name[0] == '/') + file_name = g_strdup (name); + else { + /* Get theme version of icon. */ + file_name = NULL; + if (factory->theme_name != NULL) { + partial_path = g_strdup_printf ("nautilus/%s/%s", + factory->theme_name, name); + file_name = gnome_pixmap_file (partial_path); + g_free (partial_path); } - if(!file_name) { - g_snprintf(cbuf, sizeof(cbuf), "nautilus/%s", fn); - file_name = gnome_pixmap_file(cbuf); + /* Get non-theme version of icon. */ + if (file_name == NULL) { + partial_path = g_strdup_printf ("nautilus/%s", name); + file_name = gnome_pixmap_file (partial_path); + g_free (partial_path); } + + /* Can't find icon. Don't try to read it with a partial path. */ + if (file_name == NULL) + return NULL; } - image = gdk_pixbuf_new_from_file(file_name?file_name:fn); - g_free(file_name); - + /* Load the image. */ + image = gdk_pixbuf_new_from_file (file_name); + g_free (file_name); return image; } -/* Splats one on top of the other, putting the src pixbuf in the lower left corner of the dest pixbuf */ +/* Splats one on top of the other, putting the src image + * in the lower left corner of the dest image. + */ static void -my_gdk_pixbuf_composite(GdkPixbuf *dest, GdkPixbuf *src) +nautilus_gdk_pixbuf_composite_corner (GdkPixbuf *dest, GdkPixbuf *src) { int dx, dy, dw, dh; - dw = MIN(dest->art_pixbuf->width, src->art_pixbuf->width); - dh = MIN(dest->art_pixbuf->width, src->art_pixbuf->width); + dw = MIN (dest->art_pixbuf->width, src->art_pixbuf->width); + dh = MIN (dest->art_pixbuf->width, src->art_pixbuf->width); dx = dw - src->art_pixbuf->width; dy = dh - src->art_pixbuf->height; - gdk_pixbuf_composite(src, dest, dx, dy, dw, dh, 0, 0, 1, 1, ART_FILTER_BILINEAR, 255); + gdk_pixbuf_composite (src, dest, dx, dy, dw, dh, 0, 0, 1, 1, ART_FILTER_BILINEAR, 255); } +/* Given the icon name, load the pixbuf, falling back to the fallback + * icon if necessary. Also composite the symbolic link symbol as needed. + */ static GdkPixbuf * -nautilus_icon_factory_load_icon(NautilusIconFactory *factory, IconSet *is, gboolean is_symlink) +nautilus_icon_factory_load_icon (const char *name, gboolean is_symbolic_link) { GdkPixbuf *image; + NautilusIconFactory *factory; - if(is_symlink) - image = is->symlink; - else - image = is->plain; - - if (!image) { - if (*is->name == '\0') { - /* This is the fallback icon set */ - image = gdk_pixbuf_new_from_data ((guchar*)nautilus_default_file_icon, - ART_PIX_RGB, - nautilus_default_file_icon_has_alpha, - nautilus_default_file_icon_width, - nautilus_default_file_icon_height, - /* rowstride */ - nautilus_default_file_icon_width*4, - NULL, /* don't destroy data */ - NULL ); - } else { - /* need to load the file */ - image = nautilus_icon_factory_load_file(factory, is->name); - } - if (is_symlink) { - if (!factory->symlink_overlay) - factory->symlink_overlay = nautilus_icon_factory_load_file(factory, "i-symlink.png"); - - if(factory->symlink_overlay) - my_gdk_pixbuf_composite(image, factory->symlink_overlay); - is->symlink = image; - } else - is->plain = image; - } - - if (image) - gdk_pixbuf_ref(image); /* Returned value is owned by caller */ + /* Load the image. */ + image = nautilus_icon_factory_load_file (name); + if (image == NULL) + /* This is the fallback icon. */ + image = gdk_pixbuf_new_from_data (nautilus_default_file_icon, + ART_PIX_RGB, + nautilus_default_file_icon_has_alpha, + nautilus_default_file_icon_width, + nautilus_default_file_icon_height, + nautilus_default_file_icon_width * 4, /* stride */ + NULL, /* don't destroy data */ + NULL); + + /* Overlay the symbolic link symbol on top of the image. */ + if (is_symbolic_link) { + factory = nautilus_get_current_icon_factory (); + if (factory->symbolic_link_overlay == NULL) + factory->symbolic_link_overlay = nautilus_icon_factory_load_file + (ICON_NAME_SYMBOLIC_LINK_OVERLAY); + if (factory->symbolic_link_overlay != NULL) + nautilus_gdk_pixbuf_composite_corner + (image, factory->symbolic_link_overlay); + } return image; } +/* Get or create a scalable icon. */ static NautilusScalableIcon * -scalable_icon_new (const char *uri, - IconSet *icon_set, - gboolean is_symbolic_link) +nautilus_scalable_icon_get (const char *uri, + const char *name, + gboolean is_symbolic_link) { - NautilusScalableIcon *icon; - - g_return_val_if_fail (icon_set != NULL, NULL); - - icon = g_new (NautilusScalableIcon, 1); - icon->ref_count = 1; - icon->uri = g_strdup (uri); - icon->icon_set = icon_set; - icon->is_symbolic_link = is_symbolic_link; - - icon_set->ref_count++; + GHashTable *hash_table; + NautilusScalableIcon icon_key, *icon; + + /* Get at the hash table. */ + hash_table = nautilus_get_current_icon_factory ()->scalable_icons; + + /* Check to see if it's already in the table. */ + icon_key.uri = (char *)uri; + icon_key.name = (char *)name; + icon_key.is_symbolic_link = is_symbolic_link; + icon = g_hash_table_lookup (hash_table, &icon_key); + if (icon == NULL) { + /* Not in the table, so create it and put it in. */ + icon = g_new0 (NautilusScalableIcon, 1); + icon->uri = g_strdup (uri); + icon->name = g_strdup (name); + icon->is_symbolic_link = is_symbolic_link; + g_hash_table_insert (hash_table, icon, icon); + } + /* Grab a reference and return it. */ + nautilus_scalable_icon_ref (icon); return icon; } -static NautilusScalableIcon * -scalable_icon_get (const char *uri, - IconSet *icon_set, - gboolean is_symbolic_link) +void +nautilus_scalable_icon_ref (NautilusScalableIcon *icon) { - /* FIXME: These should come from a hash table. */ - return scalable_icon_new (uri, icon_set, is_symbolic_link); + g_return_if_fail (icon != NULL); + + icon->ref_count++; } void nautilus_scalable_icon_unref (NautilusScalableIcon *icon) { - g_return_if_fail (icon->ref_count != 0); + GHashTable *hash_table; + g_return_if_fail (icon != NULL); + g_return_if_fail (icon->ref_count != 0); + if (--icon->ref_count != 0) return; + hash_table = nautilus_get_current_icon_factory ()->scalable_icons; + g_hash_table_remove (hash_table, icon); + g_free (icon->uri); + g_free (icon->name); + g_free (icon); +} - g_assert (icon->icon_set->ref_count != 0); - icon->icon_set->ref_count--; +static guint +nautilus_scalable_icon_hash (gconstpointer p) +{ + const NautilusScalableIcon *icon; + guint hash; - g_free (icon); + icon = p; + hash = 0; + + if (icon->uri != NULL) + hash = g_str_hash (icon->uri); + + hash <<= 4; + if (icon->name != NULL) + hash ^= g_str_hash (icon->name); + + hash <<= 1; + hash |= icon->is_symbolic_link; + + return hash; +} + +static gboolean +nautilus_scalable_icon_equal (gconstpointer a, + gconstpointer b) +{ + const NautilusScalableIcon *icon_a, *icon_b; + + icon_a = a; + icon_b = b; + + return nautilus_strcmp (icon_a->uri, icon_b->uri) == 0 + && nautilus_strcmp (icon_a->name, icon_b->name) == 0 + && icon_a->is_symbolic_link == icon_b->is_symbolic_link; } NautilusScalableIcon * nautilus_icon_factory_get_icon_for_file (NautilusFile *file) { - NautilusIconFactory *factory; - IconSet *set; - char *uri, *custom_image; + char *uri; + const char *name; gboolean is_symbolic_link; NautilusScalableIcon *scalable_icon; - + if (file == NULL) return NULL; - factory = nautilus_get_current_icon_factory (); + /* If there is a custom image in the metadata, use that. + * Otherwise, consider using the image itself as a custom icon. + * The check for using the image is currently based on the file + * size, but that will change to a more sophisticated scheme later. + */ + uri = nautilus_file_get_metadata(file, NAUTILUS_CUSTOM_ICON_METADATA_KEY, NULL); + if (uri == NULL + && nautilus_has_prefix (nautilus_file_get_mime_type (file), "image/") + && nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) + uri = nautilus_file_get_uri (file); - /* Get an icon set based on the file's type. */ - switch (nautilus_file_get_type (file)) { - case GNOME_VFS_FILE_TYPE_UNKNOWN: - case GNOME_VFS_FILE_TYPE_REGULAR: - default: - set = nautilus_icon_factory_get_icon_set_for_file (factory, file); - break; - case GNOME_VFS_FILE_TYPE_DIRECTORY: - set = &factory->special_icon_sets[ICON_SET_DIRECTORY]; - break; - case GNOME_VFS_FILE_TYPE_FIFO: - set = &factory->special_icon_sets[ICON_SET_FIFO]; - break; - case GNOME_VFS_FILE_TYPE_SOCKET: - set = &factory->special_icon_sets[ICON_SET_SOCKET]; - break; - case GNOME_VFS_FILE_TYPE_CHARDEVICE: - set = &factory->special_icon_sets[ICON_SET_CHARACTER_DEVICE]; - break; - case GNOME_VFS_FILE_TYPE_BLOCKDEVICE: - set = &factory->special_icon_sets[ICON_SET_BLOCK_DEVICE]; - break; - case GNOME_VFS_FILE_TYPE_BROKENSYMLINK: - set = &factory->special_icon_sets[ICON_SET_BROKEN_SYMBOLIC_LINK]; - break; - } + /* Get the generic icon set for this file. */ + name = nautilus_icon_factory_get_icon_name_for_file (file); /* Also record whether it's a symbolic link or not. * Later, we'll probably use a separate icon badge for this, - * but for now, we'll keep it. + * outside the icon factory machinery. But for now, we'll keep it. */ is_symbolic_link = nautilus_file_is_symbolic_link (file); - /* if there is a custom image in the metadata, use that instead */ - - custom_image = nautilus_file_get_metadata(file, "image", NULL); - if (custom_image != NULL) - uri = custom_image; - /* Use the image itself as a custom icon. */ - else if (nautilus_has_prefix (nautilus_file_get_mime_type (file), "image/") - && nautilus_file_get_size (file) < 16384) - uri = nautilus_file_get_uri (file); - else - uri = NULL; - /* Create the icon or find it in the cache if it's already there. */ - scalable_icon = scalable_icon_get (uri, set, is_symbolic_link); - if (uri != NULL) - g_free (uri); - - nautilus_icon_factory_setup_sweep (factory); + scalable_icon = nautilus_scalable_icon_get (uri, name, is_symbolic_link); + g_free (uri); return scalable_icon; } -GdkPixbuf * -nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon, - guint size_in_pixels) +static GdkPixbuf * +nautilus_icon_factory_create_image_for_icon (NautilusScalableIcon *scalable_icon, + guint size_in_pixels) { NautilusIconFactory *factory; - IconSet *set; - GdkPixbuf *image; + GdkPixbuf *image, *standard_size_image; + /* First cut at handling multiple sizes. If size is other than standard, + * scale the pixbuf here. Eventually we'll read in icon files at multiple + * sizes rather than relying on scaling in every case (though we'll still + * need scaling as a fallback). + */ + if (size_in_pixels != NAUTILUS_ICON_SIZE_STANDARD) + { + standard_size_image = nautilus_icon_factory_get_pixbuf_for_icon + (scalable_icon, NAUTILUS_ICON_SIZE_STANDARD); + image = nautilus_icon_factory_scale + (standard_size_image, size_in_pixels); + gdk_pixbuf_unref (standard_size_image); + return image; + } + factory = nautilus_get_current_icon_factory (); /* FIXME: This works only with file:// images, because there's @@ -488,82 +594,152 @@ nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon, image = gdk_pixbuf_new_from_file (scalable_icon->uri + 7); /* If there was no suitable custom icon URI, then use the icon set. */ - if (image == NULL) { - set = scalable_icon->icon_set; - set->last_use = use_counter++; + if (image == NULL) image = nautilus_icon_factory_load_icon - (factory, set, scalable_icon->is_symbolic_link); - } + (scalable_icon->name, scalable_icon->is_symbolic_link); - /* If the icon set failed, then use the fallback set. */ - if (image == NULL) { - g_warning ("failed to load icon, using fallback icon set"); - set = &factory->special_icon_sets[ICON_SET_FALLBACK]; - set->last_use = use_counter++; - image = nautilus_icon_factory_load_icon - (factory, set, scalable_icon->is_symbolic_link); - } - - g_assert (image != NULL); + return image; +} - /* First cut at handling multiple sizes. If size is other than standard, - * scale the pixbuf here. Eventually we'll store icons at multiple sizes - * rather than relying on scaling in every case (though we'll still need - * scaling as a fallback). We'll also cache the scaled pixbufs. - * For now, assume that the icon found so far is of standard size. - */ - if (size_in_pixels != NAUTILUS_ICON_SIZE_STANDARD) - { - GdkPixbuf *scaled_icon; +/* Move this item to the head of the recently-used list, + * bumping the last item off that list if necessary. + */ +static void +nautilus_icon_factory_mark_recently_used (NautilusCircularList *node) +{ + NautilusIconFactory *factory; + NautilusCircularList *head, *last_node; - scaled_icon = nautilus_icon_factory_scale - (factory, image, size_in_pixels); - gdk_pixbuf_unref (image); - image = scaled_icon; - } - - nautilus_icon_factory_setup_sweep (factory); - + factory = nautilus_get_current_icon_factory (); + head = &factory->recently_used_dummy_head; + + /* Move the node to the start of the list. */ + if (node->prev != head) { + if (node->next != NULL) { + /* Remove the node from its current position in the list. */ + node->next->prev = node->prev; + node->prev->next = node->next; + } else { + /* Node was not already in the list, so add it. + * If the list is already full, remove the last node. + */ + if (factory->recently_used_count < ICON_CACHE_COUNT) + factory->recently_used_count++; + else { + /* Remove the last node. */ + last_node = head->prev; + + g_assert (last_node != head); + g_assert (last_node != node); + + head->prev = last_node->prev; + last_node->prev->next = head; + + last_node->prev = NULL; + last_node->next = NULL; + } + } + + /* Insert the node at the head of the list. */ + node->prev = head; + node->next = head->next; + node->next->prev = node; + head->next = node; + } +} + +GdkPixbuf * +nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon, + guint size_in_pixels) +{ + NautilusIconFactory *factory; + GHashTable *hash_table; + NautilusIconCacheKey lookup_key, *key; + GdkPixbuf *image; + gpointer key_in_table, value; + + factory = nautilus_get_current_icon_factory (); + hash_table = factory->icon_cache; + + /* Check to see if it's already in the table. */ + lookup_key.scalable_icon = scalable_icon; + lookup_key.size_in_pixels = size_in_pixels; + if (g_hash_table_lookup_extended (hash_table, &lookup_key, &key_in_table, &value)) { + /* Found it in the table. */ + key = key_in_table; + image = value; + } else { + /* Not in the table, so create the image and put it in. */ + image = nautilus_icon_factory_create_image_for_icon + (scalable_icon, size_in_pixels); + + /* Create the key for the table. */ + key = g_new0 (NautilusIconCacheKey, 1); + nautilus_scalable_icon_ref (scalable_icon); + key->scalable_icon = scalable_icon; + key->size_in_pixels = size_in_pixels; + + /* Add the item to the hash table. */ + g_hash_table_insert (hash_table, key, image); + } + + /* Since this item was used, keep it in the cache longer. */ + nautilus_icon_factory_mark_recently_used (&key->recently_used_node); + + /* Come back later and sweep the cache. */ + nautilus_icon_factory_schedule_sweep (); + + /* Grab a ref for the caller. */ + gdk_pixbuf_ref (image); return image; } -NautilusIconFactory * -nautilus_get_current_icon_factory (void) +static void +nautilus_icon_cache_key_destroy (NautilusIconCacheKey *key) { - static NautilusIconFactory *global_icon_factory = NULL; - if (global_icon_factory == NULL) - global_icon_factory = nautilus_icon_factory_new (NULL); - return global_icon_factory; + nautilus_scalable_icon_unref (key->scalable_icon); +} + +static guint +nautilus_icon_cache_key_hash (gconstpointer p) +{ + const NautilusIconCacheKey *key; + + key = p; + return (guint)key->scalable_icon ^ key->size_in_pixels; +} + +static gboolean +nautilus_icon_cache_key_equal (gconstpointer a, gconstpointer b) +{ + const NautilusIconCacheKey *key_a, *key_b; + + key_a = a; + key_b = b; + + return key_a->scalable_icon == key_b->scalable_icon + && key_a->size_in_pixels == key_b->size_in_pixels; } static GdkPixbuf * -nautilus_icon_factory_scale (NautilusIconFactory *factory, - GdkPixbuf *standard_sized_pixbuf, - guint size_in_pixels) +nautilus_icon_factory_scale (GdkPixbuf *standard_sized_image, + guint size_in_pixels) { - GdkPixbuf *result; int old_width, old_height, new_width, new_height; - g_return_val_if_fail (standard_sized_pixbuf != NULL, NULL); - - old_width = gdk_pixbuf_get_width (standard_sized_pixbuf); - old_height = gdk_pixbuf_get_height (standard_sized_pixbuf); + old_width = gdk_pixbuf_get_width (standard_sized_image); + old_height = gdk_pixbuf_get_height (standard_sized_image); new_width = (old_width * size_in_pixels) / NAUTILUS_ICON_SIZE_STANDARD; new_height = (old_height * size_in_pixels) / NAUTILUS_ICON_SIZE_STANDARD; - /* This creates scaled icon with ref. count of 1. */ - result = gdk_pixbuf_scale_simple (standard_sized_pixbuf, - new_width, - new_height, - ART_FILTER_BILINEAR); - - return result; + return gdk_pixbuf_scale_simple (standard_sized_image, + new_width, + new_height, + ART_FILTER_BILINEAR); } - -/* - * Return nominal icon size for given zoom level. +/* Return nominal icon size for given zoom level. * @zoom_level: zoom level for which to find matching icon size. * * Return value: icon size between NAUTILUS_ICON_SIZE_SMALLEST and @@ -572,24 +748,23 @@ nautilus_icon_factory_scale (NautilusIconFactory *factory, guint nautilus_icon_size_for_zoom_level (NautilusZoomLevel zoom_level) { - switch (zoom_level) - { - case NAUTILUS_ZOOM_LEVEL_SMALLEST: - return NAUTILUS_ICON_SIZE_SMALLEST; - case NAUTILUS_ZOOM_LEVEL_SMALLER: - return NAUTILUS_ICON_SIZE_SMALLER; - case NAUTILUS_ZOOM_LEVEL_SMALL: - return NAUTILUS_ICON_SIZE_SMALL; - case NAUTILUS_ZOOM_LEVEL_STANDARD: - return NAUTILUS_ICON_SIZE_STANDARD; - case NAUTILUS_ZOOM_LEVEL_LARGE: - return NAUTILUS_ICON_SIZE_LARGE; - case NAUTILUS_ZOOM_LEVEL_LARGER: - return NAUTILUS_ICON_SIZE_LARGER; - case NAUTILUS_ZOOM_LEVEL_LARGEST: - return NAUTILUS_ICON_SIZE_LARGEST; - default: - g_assert_not_reached(); - return NAUTILUS_ICON_SIZE_STANDARD; + switch (zoom_level) { + case NAUTILUS_ZOOM_LEVEL_SMALLEST: + return NAUTILUS_ICON_SIZE_SMALLEST; + case NAUTILUS_ZOOM_LEVEL_SMALLER: + return NAUTILUS_ICON_SIZE_SMALLER; + case NAUTILUS_ZOOM_LEVEL_SMALL: + return NAUTILUS_ICON_SIZE_SMALL; + case NAUTILUS_ZOOM_LEVEL_STANDARD: + return NAUTILUS_ICON_SIZE_STANDARD; + case NAUTILUS_ZOOM_LEVEL_LARGE: + return NAUTILUS_ICON_SIZE_LARGE; + case NAUTILUS_ZOOM_LEVEL_LARGER: + return NAUTILUS_ICON_SIZE_LARGER; + case NAUTILUS_ZOOM_LEVEL_LARGEST: + return NAUTILUS_ICON_SIZE_LARGEST; + default: + g_assert_not_reached (); + return NAUTILUS_ICON_SIZE_STANDARD; } } diff --git a/libnautilus-private/nautilus-metadata.h b/libnautilus-private/nautilus-metadata.h index 0ffe6b571..859a3fe90 100644 --- a/libnautilus-private/nautilus-metadata.h +++ b/libnautilus-private/nautilus-metadata.h @@ -29,6 +29,9 @@ * should define its key here, so we can keep track of the whole set easily. */ +#define NAUTILUS_CUSTOM_ICON_METADATA_KEY "CUSTOM_ICON" +#define NAUTILUS_NOTES_METADATA_KEY "NOTES" + #define ICON_VIEW_BACKGROUND_COLOR_METADATA_KEY "ICON_VIEW_BACKGROUND_COLOR" #define ICON_VIEW_ZOOM_LEVEL_METADATA_KEY "ICON_VIEW_ZOOM_LEVEL" #define ICON_VIEW_ICON_POSITION_METADATA_KEY "ICON_POSITION" @@ -40,5 +43,4 @@ #define INDEX_PANEL_BACKGROUND_COLOR_METADATA_KEY "INDEX_PANEL_BACKGROUND_COLOR" - #endif /* NAUTILUS_METADATA_H */ |