/* the file where we store the recently used items */
#define GTK_RECENTLY_USED_FILE ".recently-used.xbel"
-/* a poll per second should be enough */
-#define POLL_DELTA 1000
+/* a poll approximately every five seconds */
+#define POLL_DELTA 5
/* return all items by default */
#define DEFAULT_LIMIT -1
/* keep in sync with xdgmime */
#define GTK_RECENT_DEFAULT_MIME "application/octet-stream"
+typedef struct
+{
+ GSourceFunc func;
+ gpointer data;
+ GDestroyNotify notify;
+} ThreadsDispatch;
+
typedef struct
{
gchar *name;
{
gchar *filename;
- guint is_screen_singleton : 1;
guint is_dirty : 1;
guint write_in_progress : 1;
guint read_in_progress : 1;
gint limit;
gint size;
- GdkScreen *screen;
-
GBookmarkFile *recent_items;
time_t last_mtime;
PROP_SIZE
};
+static void gtk_recent_manager_dispose (GObject *object);
static void gtk_recent_manager_finalize (GObject *object);
static void gtk_recent_manager_set_property (GObject *object,
static guint signal_changed = 0;
-G_DEFINE_TYPE (GtkRecentManager, gtk_recent_manager, G_TYPE_OBJECT);
+static GtkRecentManager *recent_manager_singleton = NULL;
-void
-filename_warning (const char *format, const char *filename, const char *message)
+G_DEFINE_TYPE (GtkRecentManager, gtk_recent_manager, G_TYPE_OBJECT)
+
+static void
+filename_warning (const gchar *format,
+ const gchar *filename,
+ const gchar *message)
{
- char *utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ gchar *utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
g_warning (format, utf8 ? utf8 : "(invalid filename)", message);
g_free (utf8);
}
+/* Test of haystack has the needle prefix, comparing case
+ * insensitive. haystack may be UTF-8, but needle must
+ * contain only lowercase ascii. */
+static gboolean
+has_case_prefix (const gchar *haystack,
+ const gchar *needle)
+{
+ const gchar *h, *n;
+
+ /* Eat one character at a time. */
+ h = haystack;
+ n = needle;
+
+ while (*n && *h && *n == g_ascii_tolower (*h))
+ {
+ n++;
+ h++;
+ }
+
+ return *n == '\0';
+}
+
GQuark
gtk_recent_manager_error_quark (void)
{
return g_quark_from_static_string ("gtk-recent-manager-error-quark");
}
+static gboolean
+threads_dispatch (gpointer data)
+{
+ ThreadsDispatch *dispatch = data;
+ gboolean res = FALSE;
+
+ GDK_THREADS_ENTER ();
+
+ if (!g_source_is_destroyed (g_main_current_source ()))
+ res = dispatch->func (dispatch->data);
+
+ GDK_THREADS_LEAVE ();
+
+ return res;
+}
+
+static void
+threads_free (gpointer data)
+{
+ ThreadsDispatch *dispatch = data;
+
+ if (dispatch->notify)
+ dispatch->notify (dispatch->data);
+
+ g_slice_free (ThreadsDispatch, dispatch);
+}
static void
gtk_recent_manager_class_init (GtkRecentManagerClass *klass)
gobject_class->set_property = gtk_recent_manager_set_property;
gobject_class->get_property = gtk_recent_manager_get_property;
+ gobject_class->dispose = gtk_recent_manager_dispose;
gobject_class->finalize = gtk_recent_manager_finalize;
/**
gtk_recent_manager_init (GtkRecentManager *manager)
{
GtkRecentManagerPrivate *priv;
+ ThreadsDispatch *dispatch;
priv = g_type_instance_get_private ((GTypeInstance *) manager,
GTK_TYPE_RECENT_MANAGER);
manager->priv = priv;
- priv->filename = g_build_filename (g_get_home_dir (),
- GTK_RECENTLY_USED_FILE,
- NULL);
-
priv->limit = DEFAULT_LIMIT;
priv->size = 0;
- priv->is_screen_singleton = FALSE;
priv->is_dirty = FALSE;
priv->write_in_progress = FALSE;
priv->read_in_progress = FALSE;
- priv->screen = NULL;
+ priv->filename = g_build_filename (g_get_home_dir (),
+ GTK_RECENTLY_USED_FILE,
+ NULL);
+
+ dispatch = g_slice_new (ThreadsDispatch);
+ dispatch->func = gtk_recent_manager_poll_timeout;
+ dispatch->data = manager;
+ dispatch->notify = NULL;
+ priv->poll_timeout = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT + 30,
+ POLL_DELTA,
+ threads_dispatch,
+ dispatch,
+ threads_free);
build_recent_items_list (manager);
}
}
static void
-gtk_recent_manager_finalize (GObject *object)
+gtk_recent_manager_dispose (GObject *object)
{
GtkRecentManager *manager = GTK_RECENT_MANAGER (object);
GtkRecentManagerPrivate *priv = manager->priv;
- /* remove the poll timeout */
if (priv->poll_timeout)
- g_source_remove (priv->poll_timeout);
-
- if (priv->filename)
- g_free (priv->filename);
+ {
+ g_source_remove (priv->poll_timeout);
+ priv->poll_timeout = 0;
+ }
+
+ G_OBJECT_CLASS (gtk_recent_manager_parent_class)->dispose (object);
+}
+
+static void
+gtk_recent_manager_finalize (GObject *object)
+{
+ GtkRecentManager *manager = GTK_RECENT_MANAGER (object);
+ GtkRecentManagerPrivate *priv = manager->priv;
+
+ g_free (priv->filename);
if (priv->recent_items)
g_bookmark_file_free (priv->recent_items);
-
- /* chain up parent's finalize method */
+
G_OBJECT_CLASS (gtk_recent_manager_parent_class)->finalize (object);
}
}
write_error = NULL;
- g_bookmark_file_to_file (priv->recent_items,
- priv->filename,
- &write_error);
+ g_bookmark_file_to_file (priv->recent_items, priv->filename, &write_error);
if (write_error)
{
filename_warning ("Attempting to store changes into `%s', "
g_error_free (write_error);
}
+ priv->write_in_progress = FALSE;
+
/* we have sync'ed our list with the storage file, so we
* update the file mtime in order to skip the timed check
* and spare us from a re-read.
priv->filename,
g_strerror (errno));
- priv->write_in_progress = FALSE;
-
g_object_thaw_notify (G_OBJECT (manager));
return;
return TRUE;
}
- /* the file didn't change from the last poll(), so we bail out */
+ /* the file didn't change from the last poll, so we bail out */
if (stat_buf.st_mtime == priv->last_mtime)
return TRUE;
const gchar *filename)
{
GtkRecentManagerPrivate *priv;
+ ThreadsDispatch *dispatch;
g_assert (GTK_IS_RECENT_MANAGER (manager));
priv = manager->priv;
}
priv->filename = g_strdup (filename);
- priv->poll_timeout = g_timeout_add (POLL_DELTA,
- gtk_recent_manager_poll_timeout,
- manager);
+
+ dispatch = g_slice_new (ThreadsDispatch);
+ dispatch->func = gtk_recent_manager_poll_timeout;
+ dispatch->data = manager;
+ dispatch->notify = NULL;
+ priv->poll_timeout = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT + 30,
+ POLL_DELTA,
+ threads_dispatch,
+ dispatch,
+ threads_free);
/* mark us clean, so that we can re-read the list
* of recently used resources
* monitors the recently used resources list, and emits the "changed" signal
* each time something inside the list changes.
*
- * #GtkRecentManager objects are expansive: be sure to create them only when
- * needed. You should use the gtk_recent_manager_new_for_screen() or the
- * gtk_recent_manager_get_default() functions instead.
+ * #GtkRecentManager objects are expensive: be sure to create them only when
+ * needed. You should use gtk_recent_manager_get_default() instead.
*
* Return value: A newly created #GtkRecentManager object.
*
/**
* gtk_recent_manager_get_default:
*
- * Gets the recent manager for the default screen. See
- * gtk_recent_manager_get_for_screen().
+ * Gets a unique instance of #GtkRecentManager, that you can share
+ * in your application without caring about memory management. The
+ * returned instance will be freed when you application terminates.
*
- * Return value: A unique #GtkRecentManager associated with the
- * default screen. This recent manager is associated to the
- * screen and can be used as long as the screen is open.
- * Do no ref or unref it.
+ * Return value: A unique #GtkRecentManager. Do not ref or unref it.
*
* Since: 2.10
*/
GtkRecentManager *
gtk_recent_manager_get_default (void)
{
- return gtk_recent_manager_get_for_screen (gdk_screen_get_default ());
+ if (G_UNLIKELY (!recent_manager_singleton))
+ recent_manager_singleton = gtk_recent_manager_new ();
+
+ return recent_manager_singleton;
}
/**
* and can be used as long as the screen is open. Do not ref or
* unref it.
*
+ * Deprecated: 2.12: This function has been deprecated and should
+ * not be used in newly written code. Calling this function is
+ * equivalent to calling gtk_recent_manager_get_default().
+ *
* Since: 2.10
*/
GtkRecentManager *
gtk_recent_manager_get_for_screen (GdkScreen *screen)
{
- GtkRecentManager *manager;
-
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
- g_return_val_if_fail (!screen->closed, NULL);
-
- manager = g_object_get_data (G_OBJECT (screen), "gtk-recent-manager-default");
- if (!manager)
- {
- GtkRecentManagerPrivate *priv;
-
- manager = gtk_recent_manager_new ();
- gtk_recent_manager_set_screen (manager, screen);
-
- priv = manager->priv;
- priv->is_screen_singleton = TRUE;
-
- g_object_set_data (G_OBJECT (screen), I_("gtk-recent-manager-default"), manager);
- }
-
- return manager;
-}
-
-static void
-display_closed (GdkDisplay *display,
- gboolean is_error,
- GtkRecentManager *manager)
-{
- GtkRecentManagerPrivate *priv = manager->priv;
- GdkScreen *screen = priv->screen;
- gboolean was_screen_singleton = priv->is_screen_singleton;
-
- if (was_screen_singleton)
- {
- g_object_set_data (G_OBJECT (screen), I_("gtk-recent-manager-default"), NULL);
- priv->is_screen_singleton = FALSE;
- }
-
- gtk_recent_manager_set_screen (manager, NULL);
-
- if (was_screen_singleton)
- g_object_unref (manager);
-}
-
-static void
-unset_screen (GtkRecentManager *manager)
-{
- GtkRecentManagerPrivate *priv = manager->priv;
- GdkDisplay *display;
-
- if (priv->screen)
- {
- display = gdk_screen_get_display (priv->screen);
-
- g_signal_handlers_disconnect_by_func (display,
- (gpointer) display_closed,
- manager);
-
- priv->screen = NULL;
- }
+ return gtk_recent_manager_get_default ();
}
/**
* storage.
*
* Since: 2.10
+ *
+ * Deprecated: 2.12: This function has been deprecated and should
+ * not be used in newly written code. Calling this function has
+ * no effect.
*/
void
gtk_recent_manager_set_screen (GtkRecentManager *manager,
GdkScreen *screen)
{
- GtkRecentManagerPrivate *priv;
- GdkDisplay *display;
-
- g_return_if_fail (GTK_IS_RECENT_MANAGER (manager));
- g_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen));
-
- priv = manager->priv;
-
- unset_screen (manager);
- if (screen)
- {
- display = gdk_screen_get_display (screen);
-
- priv->screen = screen;
-
- g_signal_connect (display, "closed",
- G_CALLBACK (display_closed), manager);
- }
}
/**
* gtk_recent_manager_add_item:
* @manager: a #GtkRecentManager
* @uri: a valid URI
- * @error: return location for a #GError, or %NULL
*
* Adds a new resource, pointed by @uri, into the recently used
* resources list.
*
- * This function automatically retrieving some of the needed
+ * This function automatically retrieves some of the needed
* metadata and setting other metadata to common default values; it
* then feeds the data to gtk_recent_manager_add_full().
*
- * See gtk_recent_manager_add_full() if you want to explicitely
+ * See gtk_recent_manager_add_full() if you want to explicitly
* define the metadata for the resource pointed by @uri.
*
* Return value: %TRUE if the new item was successfully added
*/
gboolean
gtk_recent_manager_add_item (GtkRecentManager *manager,
- const gchar *uri,
- GError **error)
+ const gchar *uri)
{
- GtkRecentData *recent_data;
- GError *add_error;
+ GtkRecentData recent_data;
gboolean retval;
g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
- recent_data = g_slice_new (GtkRecentData);
-
- recent_data->display_name = NULL;
- recent_data->description = NULL;
-
+ recent_data.display_name = NULL;
+ recent_data.description = NULL;
+ recent_data.mime_type = NULL;
+
#ifdef G_OS_UNIX
- if (g_str_has_prefix (uri, "file://"))
+ if (has_case_prefix (uri, "file:/"))
{
gchar *filename;
const gchar *mime_type;
filename = g_filename_from_uri (uri, NULL, NULL);
- mime_type = xdg_mime_get_mime_type_for_file (filename, NULL);
- if (!mime_type)
- recent_data->mime_type = g_strdup (GTK_RECENT_DEFAULT_MIME);
- else
- recent_data->mime_type = g_strdup (mime_type);
+ if (filename)
+ {
+ mime_type = xdg_mime_get_mime_type_for_file (filename, NULL);
+ if (mime_type)
+ recent_data.mime_type = g_strdup (mime_type);
- g_free (filename);
+ g_free (filename);
+ }
+
+ if (!recent_data.mime_type)
+ recent_data.mime_type = g_strdup (GTK_RECENT_DEFAULT_MIME);
}
else
#endif
- recent_data->mime_type = g_strdup (GTK_RECENT_DEFAULT_MIME);
-
- recent_data->app_name = g_strdup (g_get_application_name ());
- recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
+ recent_data.mime_type = g_strdup (GTK_RECENT_DEFAULT_MIME);
- recent_data->groups = NULL;
+ recent_data.app_name = g_strdup (g_get_application_name ());
+ recent_data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
+ recent_data.groups = NULL;
+ recent_data.is_private = FALSE;
- recent_data->is_private = FALSE;
+ retval = gtk_recent_manager_add_full (manager, uri, &recent_data);
- add_error = NULL;
- retval = gtk_recent_manager_add_full (manager, uri, recent_data, &add_error);
-
- g_free (recent_data->mime_type);
- g_free (recent_data->app_name);
- g_free (recent_data->app_exec);
+ g_free (recent_data.mime_type);
+ g_free (recent_data.app_name);
+ g_free (recent_data.app_exec);
- g_slice_free (GtkRecentData, recent_data);
-
- if (!retval)
- {
- g_propagate_error (error, add_error);
-
- return FALSE;
- }
-
return retval;
}
* @manager: a #GtkRecentManager
* @uri: a valid URI
* @recent_data: metadata of the resource
- * @error: return location for a #GError, or %NULL
*
* Adds a new resource, pointed by @uri, into the recently used
* resources list, using the metadata specified inside the #GtkRecentData
gboolean
gtk_recent_manager_add_full (GtkRecentManager *manager,
const gchar *uri,
- const GtkRecentData *data,
- GError **error)
+ const GtkRecentData *data)
{
GtkRecentManagerPrivate *priv;
if ((data->display_name) &&
(!g_utf8_validate (data->display_name, -1, NULL)))
{
- g_set_error (error, GTK_RECENT_MANAGER_ERROR,
- GTK_RECENT_MANAGER_ERROR_INVALID_ENCODING,
- _("The display name of the recently used resource "
- "must be a valid UTF-8 encoded string."));
+ g_warning ("Attempting to add `%s' to the list of recently used "
+ "resources, but the display name is not a valid UTF-8 "
+ "encoded string",
+ uri);
return FALSE;
}
if ((data->description) &&
(!g_utf8_validate (data->description, -1, NULL)))
{
- g_set_error (error, GTK_RECENT_MANAGER_ERROR,
- GTK_RECENT_MANAGER_ERROR_INVALID_ENCODING,
- _("The description of the recently used resource "
- "must by a valid UTF-8 encoded string."));
+ g_warning ("Attempting to add `%s' to the list of recently used "
+ "resources, but the description is not a valid UTF-8 "
+ "encoded string",
+ uri);
return FALSE;
}
if (!data->mime_type)
{
- g_set_error (error, GTK_RECENT_MANAGER_ERROR,
- GTK_RECENT_MANAGER_ERROR_INVALID_MIME,
- _("You must specify the MIME type of the "
- "resource pointed by `%s'"),
- uri);
+ g_warning ("Attempting to add `%s' to the list of recently used "
+ "resources, but not MIME type was defined",
+ uri);
return FALSE;
}
if (!data->app_name)
{
- g_set_error (error, GTK_RECENT_MANAGER_ERROR,
- GTK_RECENT_MANAGER_ERROR_NOT_REGISTERED,
- _("You must specify the name of the application "
- "that is registering the recently used resource "
- "pointed by `%s'"),
- uri);
+ g_warning ("Attempting to add `%s' to the list of recently used "
+ "resources, but no name of the application that is "
+ "registering it was defined",
+ uri);
return FALSE;
}
if (!data->app_exec)
{
- g_set_error (error, GTK_RECENT_MANAGER_ERROR,
- GTK_RECENT_MANAGER_ERROR_BAD_EXEC_STRING,
- _("You must specify a command line to "
- "be used when launching the resource "
- "pointed by `%s'"),
- uri);
+ g_warning ("Attempting to add `%s' to the list of recently used "
+ "resources, but no command line for the application "
+ "that is registering it was defined",
+ uri);
return FALSE;
}
return g_bookmark_file_has_item (priv->recent_items, uri);
}
-static gboolean
+static void
build_recent_info (GBookmarkFile *bookmarks,
GtkRecentInfo *info)
{
app_info->count = count;
app_info->stamp = stamp;
- info->applications = g_slist_append (info->applications,
- app_info);
+ info->applications = g_slist_prepend (info->applications, app_info);
g_hash_table_replace (info->apps_lookup, app_info->name, app_info);
}
g_strfreev (apps);
-
- return TRUE;
}
/**
* about the resource pointed by @uri, or %NULL if the URI was
* not registered in the recently used resources list. Free with
* gtk_recent_info_unref().
- **/
+ *
+ * Since: 2.10
+ */
GtkRecentInfo *
gtk_recent_manager_lookup_item (GtkRecentManager *manager,
const gchar *uri,
{
GtkRecentManagerPrivate *priv;
GtkRecentInfo *info = NULL;
- gboolean res;
g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), NULL);
g_return_val_if_fail (uri != NULL, NULL);
/* fill the RecentInfo structure with the data retrieved by our
* parser object from the storage file
*/
- res = build_recent_info (priv->recent_items, info);
- if (!res)
- {
- gtk_recent_info_free (info);
-
- return NULL;
- }
-
- return gtk_recent_info_ref (info);
+ build_recent_info (priv->recent_items, info);
+
+ return info;
}
/**
priv = manager->priv;
if (!priv->recent_items)
return NULL;
+
+ if (priv->limit == 0)
+ return NULL;
uris = g_bookmark_file_get_uris (priv->recent_items, &uris_len);
for (i = 0; i < uris_len; i++)
{
GtkRecentInfo *info;
- gboolean res;
+
+ if (priv->limit != -1 && i == priv->limit)
+ break;
info = gtk_recent_info_new (uris[i]);
- res = build_recent_info (priv->recent_items, info);
- if (!res)
- {
- g_warning ("Unable to create a RecentInfo object for "
- "item with URI `%s'",
- uris[i]);
- gtk_recent_info_free (info);
-
- continue;
- }
+ build_recent_info (priv->recent_items, info);
retval = g_list_prepend (retval, info);
}
g_strfreev (uris);
-
- /* clamp the list, if a limit is present */
- if ((priv->limit != -1) &&
- (g_list_length (retval) > priv->limit))
- {
- GList *clamp, *l;
-
- clamp = g_list_nth (retval, priv->limit - 1);
-
- if (!clamp)
- return retval;
-
- l = clamp->next;
- clamp->next = NULL;
-
- g_list_foreach (l, (GFunc) gtk_recent_info_free, NULL);
- g_list_free (l);
- }
return retval;
}
static GType info_type = 0;
if (!info_type)
- info_type = g_boxed_type_register_static ("GtkRecentInfo",
+ info_type = g_boxed_type_register_static (I_("GtkRecentInfo"),
(GBoxedCopyFunc) gtk_recent_info_ref,
(GBoxedFreeFunc) gtk_recent_info_unref);
return info_type;
if (!app_info)
return;
- if (app_info->name)
- g_free (app_info->name);
+ g_free (app_info->name);
- if (app_info->exec)
- g_free (app_info->exec);
+ g_free (app_info->exec);
g_free (app_info);
}
* @app_name: the name of the application that has registered this item
* @app_exec: return location for the string containing the command line
* @count: return location for the number of times this item was registered
- * @time: return location for the timestamp this item was last registered
+ * @time_: return location for the timestamp this item was last registered
* for this application
*
* Gets the data regarding the application that has registered the resource
const gchar *app_name,
gchar **app_exec,
guint *count,
- time_t *time)
+ time_t *time_)
{
RecentAppInfo *ai;
if (count)
*count = ai->count;
- if (time)
- *time = ai->stamp;
+ if (time_)
+ *time_ = ai->stamp;
return TRUE;
}
return g_strdup (name);
}
-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-recent-icon-cache",
- cache, (GDestroyNotify)g_hash_table_destroy);
-}
-
-/* TODO: use the GtkFileChooser's icon cache instead of our own to reduce
- * the memory footprint
- */
-static GdkPixbuf *
-get_cached_icon (const gchar *name,
- gint pixel_size)
-{
- GtkIconTheme *icon_theme;
- GHashTable *cache;
- IconCacheElement *element;
-
- icon_theme = gtk_icon_theme_get_default ();
- cache = g_object_get_data (G_OBJECT (icon_theme), "gtk-recent-icon-cache");
-
- 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-recent-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 *
get_icon_for_mime_type (const char *mime_type,
gint pixel_size)
{
+ GtkIconTheme *icon_theme;
const char *separator;
GString *icon_name;
GdkPixbuf *pixbuf;
separator = strchr (mime_type, '/');
if (!separator)
- return NULL; /* maybe we should return a GError with "invalid MIME-type" */
+ return NULL;
+
+ icon_theme = gtk_icon_theme_get_default ();
+
+ /* try with the three icon name variants for MIME types */
+
+ /* canonicalize MIME type: foo/x-bar -> foo-x-bar */
+ icon_name = g_string_new (NULL);
+ 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 = gtk_icon_theme_load_icon (icon_theme, icon_name->str,
+ pixel_size,
+ 0,
+ NULL);
+ g_string_free (icon_name, TRUE);
+ if (pixbuf)
+ return pixbuf;
+ /* canonicalize MIME type, and prepend "gnome-mime-" */
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 (icon_name->str, pixel_size);
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name->str,
+ pixel_size,
+ 0,
+ NULL);
g_string_free (icon_name, TRUE);
if (pixbuf)
return pixbuf;
+ /* try the MIME family icon */
icon_name = g_string_new ("gnome-mime-");
g_string_append_len (icon_name, mime_type, separator - mime_type);
- pixbuf = get_cached_icon (icon_name->str, pixel_size);
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name->str,
+ pixel_size,
+ 0,
+ NULL);
g_string_free (icon_name, TRUE);
return pixbuf;
*
* Retrieves the icon of size @size associated to the resource MIME type.
*
- * Return value: a #GdkPixbuf containing the icon, or %NULL.
+ * Return value: a #GdkPixbuf containing the icon, or %NULL. Use
+ * g_object_unref() when finished using the icon.
*
* Since: 2.10
*/
if (info->mime_type)
retval = get_icon_for_mime_type (info->mime_type, size);
- /* this should never fail */
+ /* this function should never fail */
if (!retval)
- retval = get_icon_fallback (GTK_STOCK_FILE, size);
+ {
+ if (info->mime_type &&
+ strcmp (info->mime_type, "x-directory/normal") == 0)
+ retval = get_icon_fallback (GTK_STOCK_DIRECTORY, size);
+ else
+ retval = get_icon_fallback (GTK_STOCK_FILE, size);
+ }
return retval;
}
{
g_return_val_if_fail (info != NULL, FALSE);
- return g_str_has_prefix (info->uri, "file://");
+ return has_case_prefix (info->uri, "file:/");
}
/**
gchar *name = NULL;
gboolean validated = FALSE;
- if (g_str_has_prefix (uri, "file://"))
+ if (has_case_prefix (uri, "file:/"))
{
gchar *local_file;
local_file = g_filename_from_uri (uri, NULL, NULL);
- if (local_file != NULL)
+ if (local_file)
{
name = g_filename_display_basename (local_file);
validated = TRUE;
g_free (local_file);
}
- else
+
+ if (!name)
{
gchar *method;
gchar *local_file;
rest = get_method_string (uri, &method);
local_file = g_filename_display_basename (rest);
- name = g_strdup_printf ("%s: %s", method, local_file);
+ name = g_strconcat (method, ": ", local_file, NULL);
g_free (local_file);
g_free (method);
* gtk_recent_info_get_uri_display:
* @info: a #GtkRecentInfo
*
- * Gets a displayable version of the resource's URI.
+ * Gets a displayable version of the resource's URI. If the resource
+ * is local, it returns a local path; if the resource is not local,
+ * it returns the UTF-8 encoded content of gtk_recent_info_get_uri().
*
- * Return value: a UTF-8 string containing the resource's URI or %NULL
+ * Return value: a newly allocated UTF-8 string containing the
+ * resource's URI or %NULL. Use g_free() when done using it.
*
* Since: 2.10
*/
gchar *
gtk_recent_info_get_uri_display (GtkRecentInfo *info)
{
- gchar *filename, *filename_utf8;
+ gchar *retval;
g_return_val_if_fail (info != NULL, NULL);
-
- filename = g_filename_from_uri (info->uri, NULL, NULL);
- if (!filename)
- return NULL;
+
+ retval = NULL;
+ if (gtk_recent_info_is_local (info))
+ {
+ gchar *filename;
+
+ filename = g_filename_from_uri (info->uri, NULL, NULL);
+ if (!filename)
+ return NULL;
- filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
- g_free (filename);
+ retval = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ g_free (filename);
+ }
+ else
+ {
+ retval = make_valid_utf8 (info->uri);
+ }
- return filename_utf8;
+ return retval;
}
/**
return FALSE;
}
+/*
+ * _gtk_recent_manager_sync:
+ *
+ * Private function for synchronising the recent manager singleton.
+ */
+void
+_gtk_recent_manager_sync (void)
+{
+ if (recent_manager_singleton)
+ {
+ /* force a dump of the contents of the recent manager singleton */
+ recent_manager_singleton->priv->is_dirty = TRUE;
+ gtk_recent_manager_real_changed (recent_manager_singleton);
+ }
+}
+
#define __GTK_RECENT_MANAGER_C__
#include "gtkaliasdef.c"