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…

Recent Menu

recent-chooser: Finally, after more than one month of hacking on the RecentManager object, I’ve been able to create a reasonable “Open Recent” menu widget:

EggRecentChooserMenu
Obligatory screenshot of the new and improved recent menu

The icon code is placed in the RecentInfo object, and it’s based on the GtkFileSystemUnix code, complete with the pixbuf cache (ideally, it should be shared across GtkFileChooser implementations and GtkRecentChooser implementations).

Right now, it does not have filtering abilities other than a filter function you must feed to the RecentManager (for that, I’ll implement a RecentFilter object); also, the “Clear” item is always shown, and the tooltips aren’t attached yet.

But it’s a start, and it’s also a way lot saner than the current EggRecentViewGtk object (starting from the class name).

recent-files: bug-fixing still going on… The bug count is down to twenty items, with 6 marked as enhancement (which I keep open as a feature reminder).

Post-Triage

I’ve spent the last five hours triaging the open bugs of recent-files. Some of them were in bugzilla since 2003, and many were marked UNCOFIRMED.

First of all, I scanned the bugs with patches, and created a first batch with the most clean patches I found; then, I triaged the uncofirmed bugs. Then I closed the only report which was not a bug.

On other news: ph34r m3, f0r I h4v3 4 CVS 4cc0unt

(not for writing yet, but I assume I’ll need time for that).

I hope to commit the first batch tomorrow – now I’m completely spent.

Taking My Part

recent-files I’ve began assuming maintainership of all the bugs inside Bugzilla for the recent-files component of libegg. The listed bugs are basically issues against API unfriendlyness towards language bindings; segfaults for being too optimistic against user intervention on the storage file; UI enhancements. Many of these bugs have patches, so it should only be a job of committing those patches after some review.

As for this issue: I’m still waiting to get a CVS account for cvs.gnome.org

recent-chooser: the code is taking shape quite fast. The new API is reaching a stable form. I’m still unconvinced about the need of having the creation of the RecentItem objects exposed: we could simply offer a convenience API for adding items by their URI (plus some other metadata), and let the user get a RecentInfo object when looking up a recently used URI.

desktop-bookmarks: I’m working on a technology demonstrator; a simple bookmarks manager that allows the creation of desktop bookmarks by DnD’ing an URI from an application exporting the text/URI target.

life: Hot. Hot. Hot.

Blue skies from pain

ork: These last two months of working at $WE_TEACH_TO_TEENAGERS will kill me…

I’ve been wiping out disks (which have seen too many months without a format) since last week; Windows9x is Pain and Suffering to maintain. Unfortunately, we still have old ‘chines with only 64 megs of RAM, so installing Windows XP is completely out of question. It’s mind boggling how on earth people did not complain when they were forced to use these Toys ‘R’ Us operating system; and when I say “complain” I mean: getting to Redmond with rusty medieval tools and burn the place from the ground.

hacking: I’ve sent my desktop bookmarks parser/builder object to the gtk-devel-list guys, and I’m still waiting for a CVS account. I hope to put it into libegg, since this object is a dependency on my EggRecent stuff.

This code is similar to GKeyFile: it can load a XBEL data stream with the metadata of the desktop bookmarks specification, and offers access to each bookmark in it by using the item’s URI.

desktop bookmarks spec: I’m still reviewing the spec. I was thinking about the <group> tag: what if we changed it with a <tag>? We could have user-defined tags, which could be more useful for identifying, sorting and filtering metadata.

Back from GUADEC

Yesterday I came back from the GUADEC 2005 in Stuttgart.

It has been freakin’ awesome! The talks, the people, the organization… Simply amazing.

I enjoyed every talk I attended: the Cairo talk by Owen Taylor; the Keith Packard’s talk on improving X; Davyd Madeley’s talk on the future of panel applets; Seth Nickell’s talk on usability.

I found the keynotes by Miguel de Icaza and Mark Shuttleworth very entertaining, and aggressive; I think that the Gnome community as a whole should be much more aggressive, in terms of market acquisition, if we want to achieve the “10×10” (10% of market share within 2010) objective. As for what I’ve seen in these two days, we can make it – with a little help from our competitors, obviously.

I met Federico Mena Quintero, and we talked about implementing a bookmarks/recently used files manager in Gtk – basically, shifting my Gnome Desktop Bookmarks project down into the dependency stack. This should get rid of the recent-files stuff in libegg, and should provide the correct API for others to use (especially Nautilus). At the hackfest I put up a mockup (actually, it’s an almost complete program in Perl using my development trunk of the recent-files Perl bindings) of what should become the GtkFileChooserDialog for recently used items.

Here’s an obligatory snapshot:

Recent Items Viewer

As I sayed, it already works; you might want to download it from here; you need the latest CVS snapshot of the Gtk2::Recent module from the Gtk2-Perl’s CVS.

What I plan to do is to rewrite the entire recently used management (using the desktop bookmark specification for the items storage), create a dialog like the one above and a widget. The recently used objects would be stored by the GtkFileChooser class, so no interaction of the developer should be needed; applications might decide to implement a “Open Recently Used…” menu item which creates the GtkRecentChooserDialog dialog instead of filling a (sub)menu.

Also, an applet/viewer/nautilus extension should be available, in order to always have the recently used items on the desktop.

Stuttgart here we come

Travelling: Tomorrow, after work, I’ll be leaving for Milan where I’ll pick up my girlfriend Marta, and then we’ll be heading Stuttgart for GUADEC 2005. Yay! Since Stuttgart is 500 kilometers (for youn non-metric-system people, roughly 310 miles), we’ll be going with my car – its waaaay more economic than taking a plane or the train, and it gives us a little more flexibility on the timings; I’ll need to get back to work on Tuesday, so we’ll be leaving monday at lunch (and, since we are in route, we will go to see Ulm). Pity that I can’t leave on Wednesday, and attend the whole conference.

It’s my first GUADEC, and I think it’ll be Just Fun® to meet some of the best Gnome hackers from all around the world.

I plan to meet with some fellow italian hackers, and with some other people.

Desktop bookmarks: the work on the specification proceeds, even if not as fast as I thought at first; the spec itself changed quite a lot during the first reviewing iteration: I switched from a XML-like markup to a full XBEL-compliant specification, with custom metadata for our bookmarks. Since this would require a full XML parser, I’ve created a GObject wrapper around libxml2 just for XBEL entities; it has been quite a ride, and I’ve learned a lot in the process. I plan to release this library, since it might be useful for Gnome-based browsers like Epiphany or Galeon (which already do use XBEL for storing their bookmarks). The work on the spec and the parser library also has brought me to make changes to the Gnome library: now it’s more complete, and saner. I plan to release it just after the GUADEC (it will also have Perl bindings, so we will be the first language binding set to have it – so long for the Pythonistas in the Gnome world ;-)).

Work: my job at ${WE_TEACH_TO_TEENAGERS} is almost ended. It has been a strange year: I met some interesting people, and I’ve learned that the system administrator’s job sucks in ways that I did not know (even if I was prepared, having lurked the Scary Devil Monastery many years); nevertheless, it was fun, and I’d do it again – given a more consistent wage and more decisional power. I would also like to try a career in programming – but that has to wait at least the next year.

College: I’ve had little or no time for studying, so I’ll take my exams in September – which sucks, because in Semptember begins my last year, and I’ll have more courses, a stage and my thesis to write. I have an assignment for a C course due in July; I think I’ll take my teacher the tarball of my XBEL parser library, and pretending a 30 cum laude (basically, an A+).

Life: life has been very kind to me, this year. It all began when I met Marta – and I think that it’s not entirely unrelated.

Bookmark Spec

I’ve sent a draft for a desktop bookmark spec on fd.o, and it got reviewed – mostly by the KDE people, that got already a standard way of storing bookmarks across the desktop.

If it reaches the common approval, I’ll apply for a CVS account on freedesktop.org’s server.

Meanwhile, I’m working on the implementation of the spec on the Gnome side: I already have a model/viewer approach set, and now I’m writing a generic XBEL object using GLib. It’s quite fun, I must admit. Well, it’s fun since I’ve found an implementation of an XBEL parser using libxml2 inside Galeon.

I hope to have a Gnome platform library for the bookmarks spec ready before GUADEC arrives…

Gnome Desktop Bookmarks

On Gnome Live there’s an ongoing discussion about recent files and bookmarks in Gnome.

In the last two weeks I’ve been designing and writing a platform library for Gnome which addresses the points made on the Wiki, on Bugzilla and on the mailing lists (as I said here).

It’s called libgnome-bookmark and implements the concept of a generic “bookmark”; a bookmark is everything pointed by a URI, plus some meta-data. The library comes with two objects: GnomeBookmarkItem – which is the representation of the bookmark – and GnomeBookmarkModel – the monitor of the bookmarks storage.

You just add and get items to and from the model, similarly to the current recent-files stuff. Plus, the model has the ability to support custom filter and sort functions, in order to get what you want, the way you want it. Bookmarks also might be registered by more than one application (so that you have the ability to create per-application bookmarks) and might belong to various groups (so that you can have classes of applications using the same bookmarks).

Recent files and desktop bookmarks are handled simply by defining two groups in the specification.

In my opinion, this solves the bookmarks problem, and the recent files issues in a single move.

DBus Perl Bindings/3

It seems that my work on a D-Bus perl binding was duplicating the (excellent) work of Daniel P. Berrange.

Not that I’m complaining: I badly needed to understand how D-Bus worked, and creating a binding was the fastest way to understand the inner workings of D-Bus.

Well, all in all I learned much, and now I volunteered for giving a hand to Daniel if he needs it. This is the beauty of F/OSS.