Recent files woes

Yesterday, on IRC, there has been some discussion about my recently used resources handling proposal – especially with regards to the storage format.

I hate discussing on IRC; I’m not fast enough a typist – and since english is not my primary language, I find it very difficult to make myself understandable. So, I decided to put here some of the rationales for changing the storage format of the recently used resources list, written down in form of Q&A.

Storage format

Q: Why did you have to change the format?
A: Because the old format, as defined by the recent-file spec has shown its limits, since it has been proposed. Also, that spec is still a draft, and it’s not used by anyone else but Gnome.

Q: What limits the recent-file spec has?
A: It lacks the meta-data needed to know which applications registered a recently used resources. It lacks descriptors for meta-data such as a human readable name for the recently used reosurce.

Q: But recently used files need not a human readable name. Why should we use it?
A: The “human readable” name and description are not mandatory. Anyway, a user might have set that meta-data on its document; we strongly encourage the existence of this metadata. It would be totally unfriendly to show the file name instead of what the user decided to use as a name for that document. Also, “Wireless adapter WX-6615 Manual” is more readable than “wx-6615.pdf”. Anyway, the XBEL DTD makes the title and desc entities non-mandatory, so we can use them only if needed.

Q: Still, a recent file is not bookmark; then, why allow things that a bookmark allows on a recently used file pointer?
A: For me, a recent file is a bookmark to a file, with a lifetime that is kept artificially short, so it makes perfectly sense to use a bookmark-definition language in order to store it. You are gladly invited to prove me wrong, by providing examples on how a pointer to a recently used resource could be described apart from using a URI, and why does XBEL fail to store and describe a pointer to a recently used resource on.

Q: We could extend the recent-file spec, then, instead of using XBEL; did you think about it?
A: Yes, in fact I did. The first proposal of the desktop-bookmark spec used an updated version of the recent-file spec, but it was shot down, and usage of XBEL was proposed.

I’ll add more entries…

Update: directly from the libegg/recentchooser/README file:

Dependencies

Q: Why did you wrote the RecentManager?
A: The code living recent-files started to bit-rot, after being unmaintained for a long time; also, we never made clear whether the RecentModel code should live in a Gnome platform library on the same level of libgnome, or on a lower position on the dependency chain. The RecentManager code should go into Gtk, so it does not depend on anything more than GLib, Gtk+ and libxml2.

Q: In which library this code should go?
A: Inside Gtk+, starting from the 2.9 development cycle (I hope).

Q: Why Gtk? Why not libgnome?
A: We are in the process of getting rid of libgnome, so Gtk makes sense.

Q: Why this shouldn’t go inside a custom library?
A: Because I don’t want to create Yet Another Library upon which Gnome should depend; also, the requirements of this library would really be Glib, Gtk+ and libxml2, so there would be nothing gained by keeping this code outside Gtk+.

Q: The old recent-files code depended on libgnomevfs. Why yours does not?
A:The recent-files code depended on libgnomevfs for the fancy stuff needed in order to retrieve the MIME type of a file, and on the conversion of the URI in order to be displayable; also, it needed libgnomevfs for the monitor on the storage file. The MIME stuff could go away, since we require the user of this code to pass the MIME type of the resource when registering it; it makes sense, because if you used libgnomevfs yourself in your code, you wouldn’t have to check the MIME type twice. Also, many of the UTF-8 and URI manipulation code it’s now available directly inside GLib. At the end of the day, the recent-files code only needed the GnomeVFSMonitor from libgnomevfs – and that could be easily replaced with a timed poll() on the file.

Q: The old recent-files code depended on libgnomeui. Why yours does not?
A: The only left-over of the libgnomeui dependency inside libegg/recent-files was the usage of gnome_icon_lookup() function in order to retrieve the icon bound to the MIME type. I removed it, and switched to the same system used by the GtkFileChooser object (we’ll also share the icon cache, so it should even be more efficient once this code goes in Gtk+).

Manager API

Q: Shouldn’t you have tried to save the RecentModel object first?
A: I tried, at first. It soon became obvious that the RecentModel code had become a collection of hacks, especially WRT visualization, trying to hide its usage of Gnome-VFS; also, the storage file format was subject to a review process, both for enhancements and for interoperability. The model code would have been subject to a mass rewrite process anyway.

Q: No, really, I liked the RecentModel API, can’t you please keep it?
A: The short answer is no. The long answer is: it’s not worth it. The RecentModel tried to retrieve for itself most of the metadata reguarding a recently used resource. While this kept the API simple (what you had to do was to feed it a URI, in most of the cases), it also had a negative impact on the performances of the RecentModel object – which, obviously, negatively impacted on the overall performance of the widgets. Even if you did not use Gnome-VFS, the RecentModel was depending on it for querying the file metadata; if you did use it, you ended up with twice the number of the queries: one did by you code, and one did by the RecentModel code; this, especially in a networked environment, had caused many performance issues that the only solution was to create a RecentItem by yourself – and that made the API as complex as the RecentManager API could be (in fact, a bit more complex, since a RecentData structure is very lightweight when compared to a RecentItem object).

Widgetry

Q: You even changed the viewer widget. Why did you scrapped the entire EggRecentViewGtk object?
A: I really hated its name.

Q: Now, be serious…
A: Okay: I hated the whole thing – starting from the name. It was a clever hack, which tried to be useful for both the “inlined recent files” and the “recent files sub-menu” concepts. But it was an hack – which, clever or not, had passed the point of being maintainable. The interface upon which was based was too simple for being useful (EggRecentView only has two methods: “set_model” and “get_model”), so it had to be refactored; the menu API was too dependent on the RecentModel code – which led to separation issues when it came to visualization; for instance, you don’t sort a ListStore: you pass a sorting function to the TreeView, so that you can have multiple views of the same data. The same should happen with the Recently Used Resources List: same data, multiple viewers. Oh, and did I mention that the name was ugly?

Q: Why the RecentChooserMenu shows up in a sub-menu? Wasn’t this removed from the HIG?
A: It was indeed removed, and I consider it a mistake made by the GUP. The rationale for its removal was, shortly: “recently used files should live on the same level of the Open menu item”; which could be fine – if it didn’t bring up issues involving latency when building the File menu; or issues involving the total utility of a list composed of just four items. I believe that the “Open Recent” menu just as appears in OS-X should be the right approach, WRT recently used resources shown in a menu. Also, this keeps the code compact (the entire RecentChooserMenu size is < 1 kLOC), and maintainable.

Q: What if I wanted an inlined recently used resources list?
A: It’s not difficult to build, using the list returned by the RecentManager; you don’t even need to implement a widget:

     ...
     menu_item = gtk_separator_menu_item_new ();
     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), menu_item);
     gtk_widget_show (menu_item);

     manager = egg_recent_manager_new ();
     egg_recent_manager_set_limit (manager, 4);
     egg_recent_manager_set_sort_type (manager, EGG_RECENT_SORT_MRU);

     items = egg_recent_manager_get_items (manager);
     for (l = items, count = 1; l != NULL; l = l->next, count++)
       {
         EggRecentInfo *info = (EggRecentInfo *) l->data;
         gchar *text, *name;

         name = egg_recent_info_get_display_name (info);
         text = g_strdup_printf ("_%d. %s", count, name);

         menu_item = gtk_menu_item_new_with_mnemonic (text);
         gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), menu_item);
         gtk_widget_show (menu_item);

         egg_recent_info_unref (info);
       }

     g_list_free (item);

     menu_item = gtk_separator_menu_item_new ();
     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), menu_item);
     gtk_widget_show (menu_item);
     ...

Less than thirty lines of code.

Q: Do you plan to create a inlined menu widget?
A: Eventually; if the HIG does not change, or if the demand is high enough. Or you could implement it. It’s Open Source, you know…

2 Replies to “Recent files woes”

  1. Can this be adapted to use GMarkup instead of libxml2? We are using gtk on embedded devices (see http://gpe.handhelds.org) and just got rid of the fairly big libxml2, so it would be a shame that gtk gets a dependency upon libxml2 just for this.

  2. XBEL is a dialect of XML, and it’s using namespaces and other nifty things in order to keep custom meta-data as much transparent as possible – so that we can add ours, and other projects theirs.

    I tried to use a revamped version of the recent-files storage format, which uses GMarkup, but that would cripple down interoperability between Gnome and the rest of the world

    Daniel Veillard said:

    Something like GMarkup makes some sense for parsing small chunks like menu descriptions which are embedded in a program. It makes no sense for user data, because the lack of specification and behaviour description, if even a formal set of the syntax accepted makes it a risk for the processing of user data. It will make it a risk for user’s bookmarks, for example XML-1.0 has some rules about attributes and CR/LF normalization that I doubt GMarkup would comply to, making a GMarkup based processing of the bookmark generate different informations than if the same subset was parsed with a conformant XML parser. Designing a FreeDesktop.org format for user data based on the limitations of GMarkup simply makes no sense to me, use GMarkup where it makes sense, but don’t try to push it as an example for anything standard related, you will just lower the credibility of FD.o which would be a shame.

Comments are closed.