Good Intentions/2

April 17, 2008 on 10:30 pm | In Hacking, GNOME, C, developer, gtk, clutter, crack, json-glib, glib | 8 Comments

gtk+: I’ve been working again on the RecentManager and in trunk you’ll see some new stuff, namely:

  • use GIO to determine the MIME type of a URI, on every platform supported
  • use the file monitoring API to avoid polling the storage file
  • add a GtkSettings property for clamping the recently used resources list to a 30 days limit

more stuff I’d like to add is:

  • small parser changes to GBookmarkFile, to reflect changes in the spec
  • bulk addition, for applications storing multiple items when quitting
  • new API needed to follow the usability review in bug 349541
  • moving the RecentItem icon code to GIO, and add API to extract the thumbnail

twitter: I’ve been using Twitter a lot in the past two weeks; it’s nice, it makes it easier to copy and paste a quote or a thought, and the 160 characters limit is an interesting challenge. As it’s been ages since I last wrote an application1, I decided to start writing a Twitter reader/writer — using GTK+, Clutter and Tidy; without much thinking, I opened gvim and started writing code in C2 — so, the obvious thing that happened was that I ended up writing a library yet again in order to use Twitter’s web API. luckily for me, libsoup has now a really nice API to work with; all you need is GET and POST to their RESTful API, retrieve the result, parse it through JSON-GLib, hide everything inside a new GObject and you have a wrapper around a web service. the application, you say? oh, I was sure I forgot something. well, it’s coming along — it just needs some work still.

  1. lately all I’ve been doing was writing libraries []
  2. hey, that’s what I do for a living, it’s hard to switch off; plus, I could reuse some of the platform libraries []

Berlin/5

March 15, 2008 on 1:35 am | In Hacking, GNOME, C, gtk, conference, hackfest, berlin | 2 Comments

last post of the Berlin Hackfest series, written on the last minutes of day 5

today was “wrap up” day. we got together in the room used for the presentations and summed up all our work during the various sessions of the week. it turned out that the amount of work, even though not reflected by the wiki page, was really enormous; the introspection guys worked a lot and now that they have received a lot of input, they are going to rework things and kick ass even more. apparently, Behdad decided that I would tackle the GL integration inside GDK — which, of course, I’d really like to do; the GL integration, and a GDK wrapper for the GLX_texture_from_pixmap (and the equivalent call for the other platforms) would obviously be the primary way to integrate Cairo 2D high quality drawing and GL 3D and hardware acceleration in a simple way. and this is a step forward the implementation of a scene graph inside GTK+.

in the meantime, I’m — as Ryan would put it — deeply recursing. it all started on tuesday, when I decided to start hacking on a real application with Vala using all the bits and pieces a modern GTK+ application requires: GtkUIManager, about dialogs, command-line switches. the application was supposedly going to read the new GTest framework reports, and allow comparing of multiple runs in a fast way. this, in turn, led to some bugs filed against Vala GTK+ bindings. working around these issues, I also found out that the libxml-2.0 bindings in Vala — which I need to parse the GTest report XML — require a lot of pointers usage and are, in general, quite sub-obtimal, due to the very C oriented API. while investigating on a substitute, I found out XmlReader — the cursor-based XML traversal API that .Net and other high-level languages implement1. Thus, today at a coffe shop2 I started hacking very quickly on a rough implementation of a XmlReader GObject class which, as of at this moment works quite nicely:

  XmlReader *reader = xml_reader_new ();
  GError *error = NULL;

  if (xml_reader_load_from_file (reader, “book.xml”, &error))
    g_error (“Unable to parse book.xml: %s, error->message);

  xml_reader_read_start_element (reader, “book-info”);

  xml_reader_read_start_element (reader, “author”);
  author = g_strdup (xml_reader_get_element_value (reader));
  xml_reader_read_end_element (reader);

  xml_reader_read_start_element (reader, “title”);
  title = g_strdup (xml_reader_get_element_value (reader));
  xml_reader_read_end_element (reader);

  xml_reader_read_end_element (reader);

  g_print (“The author of %s is %s\n, title, author);

  g_free (title);
  g_free (author);
  g_object_unref (reader);

and you’re done. at this moment, I’m cleaning it up and adding the gtk-doc API reference to the build3. I’m probably going to add the generic read() method, so that:

  while (xml_reader_read (reader))
    {
    …
    }

will work as expected. it’s, as usual, code replication — but I’m going to need it anyway, so it’s good code replication.

  1. Even libxml-2.0 implements it, even though it suffers from the same issues of its DOM API, and it’s still not GObject-based []
  2. Behdad is right: a coffee shop without any Internet connectivity makes wonders with your productivity levels []
  3. When I write new libraries, I usually stub out the API and document it at the same time; now I started to add the GTest units before I even implement the API []

Stinging Velvet

October 16, 2007 on 8:21 pm | In Hacking, GNOME, C, announce, clutter | 6 Comments

Clutter - If release 0.4 rocked hard, release 0.6 of Clutter will blow your mind away. Just to list some features landed in the past couple of weeks after ClutterScript got in:

  • new event handling, borrowing from the W3C DOM event - that is, two event phases: capture, which traverses the scene from the stage to the actor that received the event, and bubble which traverses the scene from the actor to the stage. You can block the event chain in any point of both phases by simply returning TRUE in the signal handlers (like GTK+); kudos to mallum and Pippin
  • improved text scaling, at least for downscaling at ~50%; kudos to Pippin
  • build and test on win32 using the SDL backend, complete with VS2005 build files; kudos to tf
  • time-based timelines, so you can define a ClutterTimeline by giving its length in milliseconds; and without even breaking the API.

Still, there’s plenty more coming - so keep looking at trunk.

JSON-GLib - The code base has been consolidated a lot while working on ClutterScript, so I feel confident about making a release of the out-of-tree repository. The release is bagged, tagged and signed as json-glib-0.2.1 in the git repository1. You can grab the tarball here. Work on seamless GObject-JSON (de)serialization will continue in the master branch towards a 0.4.0 release. Update@2007-10-16T23:30+0100: obviously, as soon as I got back home and checked the repository I found two bugs in the generator code; hence, brown paper bag release 0.2.1. Tarball, documentation and tag updated.

  1. As usual, at http://folks.o-hand.com/~ebassi/git/json-glib.git []

Porcelain

October 8, 2007 on 11:19 pm | In Hacking, GNOME, C, developer, clutter, git | 7 Comments

Today I committed to Clutter trunk ClutterScript, the initial support for defining the scenegraph using external files. You can think of it as the GtkBuilder equivalent for Clutter.

During the 0.3 development cycle we considered using XML and JSON, and opted for the latter because while XML is quite easy for applications to write, JSON is more geared towards human to read1. Also, JSON syntax is really parser-friendly, with only three barewords and six symbols.

Another nice thing about JSON is that many high-level languages already have some JSON module, so manipulating data streams would be quite easy for, let’s say, Perl or Python before feeding those streams to Clutter.

Defining a simple scene with JSON and ClutterScript is quite easy:

{
  “id” : “main-stage”,
  “type” : “ClutterStage”,
  “fullscreen” : true,
  “children” : [
    {
      “id” : “red-button”,
      “type” : “ClutterRectangle”,
      “x” : 100,
      “y” : 100,
      “width” : 100,
      “height” : 100
      “color” : “#ff0000ff”
    },
    {
      “id” : “green-button”,
      “type” : “ClutterRectangle”,
      “x” : 300,
      “y” : 100,
      “width” : 100,
      “height” : 100
      “color” : “#00ff00ff”
    },
    {
      “id” : “blue-button”,
      “type” : “ClutterRectangle”,
      “x” : 600,
      “y” : 100,
      “width” : 100,
      “height” : 100
      “color” : “#0000ffff”
    }
  ]
}

This will draw a red, a green and a blue square, 100×100 pixels of size, inside a full screen stage.
You can then retrieve the "main-stage" object (as well as any other object using its id) and connect signals and manipulate them with the usual Clutter API.

At the moment ClutterScript is not 100% complete - I still need to add support for defining behaviours (mostly a matter of defining an object syntax); complex properties parsing; merging (and, possibly, unmerging) of “snippets” of objects. Plus, obviously, more sanity checks in the scene building code.

To parse JSON there are a few C libraries, but I opted for writing a GObject-based one - which, in one of my usual moments of lack of originality, I called JSON-GLib. Clutter uses an in-tree copy because I might need API changes to make Clutter parsing code easier, but the library is already auto-tooled, tested and 100% documented (it is missing GObject deserialization, but that will have to wait). JSON-GLib is released under the terms of the LGPL and it’s available in my personal git repository, which you can clone with the usual:

  git clone http://folks.o-hand.com/~ebassi/git/json-glib.git

Update@2007-10-09T15:07+0100: Just landed in trunk: defining behaviours (not every type, complex types like the path-based ones are still to be implemented), merging tests and more sanity checks. Defining a rotate behaviour boils down to:

{
  “id”          : “rotate-behaviour”,
  “type”        : “ClutterBehaviourRotate”,
  “angle-begin” : 0.0,
  “angle-end”   : 360.0,
  “axis”        : “z-axis”,
  “direction”   : “cw”,
  “alpha”       : {
    “timeline” : { “loop” : true, “num-frames” : 300, “fps” : 60 },
    “function” : “sine”
  }
}

Really soon now: all behaviours, complex properties and more.

  1. obviously nothing prevents adding an XML parser, and use both []

Flying Teapot

August 9, 2007 on 11:23 am | In Hacking, C, announce, developer, clutter | No Comments

Clutter 0.4.0 was, finally, released two days ago. Not only the core and add-on libraries but also the language bindings are available for this new stable release cycle.

We already started working on trunk for the 0.5/0.6 development cycle, which should hopefully lead up to another stable release in six months; there already is a nice list of features we are working on, but I’d like to see more requests, more patches ( ;-) ) and people working on even more language bindings.

Take it or leave it

July 11, 2007 on 5:33 pm | In Hacking, GNOME, C, announce | No Comments

After the comments on my latest blog post, I got back at Unique and did some rearrangements in the code base. Now the backends are all compiled in (obviously, depending on whether you have the dependencies to compile them) and the backend to be used can be defined at runtime. The default backend is chosen at compile time and can be overridden by setting the UNIQUE_BACKEND environment variable. Obviously, if you launch an instance with UNIQUE_BACKEND=dbus and another one with UNIQUE_BACKEND=bacon you will have two instances running - but that’s only to be expected.

I’ve also updated the API to something I can probably call “semi-frozen” (small API additions notwithstanding); the constructor changed to always accept a startup notification id (it will try to be clever and find it for you if you pass NULL, though) and allows you to define custom commands with a single call.

As usual, you can clone the Git repository from here:

  git clone http://www.gnome.org/~ebassi/git/unique.git

or grab the tarball for 0.9.20.9.3 from here.

I’ll keep working on making a 1.0.0 release at GUADEC (probably it’ll happen right at GUADEC), API/ABI stable and with the Xlibs backend. Then I’ll resume working on the GtkApplication class, which will have the Unique features but will (hopefully) be integrated in GTK+.

Update@2007-07-12T12:54+0100: New release, with full API reference documentation, a couple of stupid bugs squashed and workspace support.

Strange news from another star

July 9, 2007 on 11:21 am | In Hacking, GNOME, C, announce | 14 Comments

I’ve been promising a release of GtkUnique for a while now, but work and other stuff got in the way of the namespace change-slash-rewrite. Yesterday I finally got around finishing the porting of the Unix domain sockets backend (or “bacon”) so I cooked up a preliminary release with the D-Bus and Bacon backends working. You can find the tarball here or, if you’re feeling in hacking mood, you can check out the git repository from here:

  git clone http://www.gnome.org/~ebassi/git/unique.git

the unique-0.9.1 is the tag for this release. I’ll work on finishing the port of the Xlibs backend and target a stable 1.0.0 release for GUADEC.

The API of Unique changed a bit since the last GtkUnique release, and I think it’ll change a bit more in order to be usable with the smallest impact possible. Now you can register custom commands and there’s convenience API for sending strings and URI lists; the command registration and construction API might change to something similar to the GtkDialog API - and I might switch to a more signal based approach (construct the message payload inside a signal handler) before 1.0. I also might add a –replace command line switch that gets slurped and does The Right Thing for you.

The biggest change is happening under the hood, though; with this release, the UniqueApp instance will request the specified name as soon as it is created, so you’ll be guaranteed to either be the first running instance or be able to send messages to the currently running instance at the same moment that the UniqueApp constructor returns. Hence, no more race conditions between the constructor and the “is running” request. Finally, the “window watching” functions have been removed - even though I might add a “watch window” function to handle the startup notification sequence for you (now that we have the API to do that in GTK+ 2.11).

This release also means that the code in SVN under the gtkunique module is to be considered deprecated. I’m going to ask the svnmaster to move it into the attic, as the delta is too big for a simple check-in. As soon as 1.0.0 is out I’ll also ask the release-team for “blessing” Unique as a dependency, so if you want your module to depend on it you’ll be able to safely do it. Again, sorry for taking this long to finish up this work.

Update@2007-07-09T15:16+0100: I’ve just rolled a 0.9.1 to fix some build issues and add licensing terms. Thanks to Christian Persch for the heads up.

Time is Running Out

June 19, 2007 on 1:59 pm | In Hacking, GNOME, C, gtk | 6 Comments

Today I committed a couple of fixes to GtkRecentManager and I thought it was worth mentioning them on pgo.

Up until now, GtkRecentManager instances were available either via the gtk_recent_manager_new() constructor - which left the memory management duties to the developer - or via the gtk_recent_manager_get_default() which tried to do the right thing, by returning a singleton instance to be shared inside an application. The master plan was having the singleton attached to the GdkScreen to take advantage of the lifetime management of the screen done by GTK+ and cleanly dispose the recent manager when the screen was closed. This approach would have worked well, except for two tiny details:

  1. if you change screen, gtk_recent_manager_get_default() will return a different instance
  2. GdkScreen are never closed unless you do that explicitly.

So much for the master plan.

Thanks to Morten Welinder, who did some very appreciated detective work on it, it was decided to switch to a more common approach, with a static variable and a private synchronisation function that gets called when the main loop level reaches zero. What does this mean, for the application developer? First of all, two deprecations: both gtk_recent_manager_get_for_screen() and gtk_recent_manager_set_screen() are deprecated as of GTK+ 2.12 and should never be used again (the first evaluates to gtk_recent_manager_get_default() and the second to a NOP, if you ever decide to compile with GTK_DISABLE_DEPRECATED turned off); second of all, no more juggling around with the screen changes: multiple calls of gtk_recent_manager_get_default() will always return the same instance of the GtkRecentManager object - which you should never unref. Obviously, if you were creating your own recent manager instance with the gtk_recent_manager_new() constructor, none of this matters and you’ll have to handle the manager lifetime by yourself.

Another change I committed was the switch to the g_timeout_add_seconds() for the polling of the recent files storage file. Since the timeout was set to every N seconds I decided that the lifespan of my laptop’s battery was more important than having a millisecond precision on a stat() call. In other news, laptop owners around the world rejoice as one. Since every signal under GTK+ is emitted under the assumption that the emitter is inside the GDK master lock, the newly added gdk_threads_add_*() functions weren’t fit for my cunning plan of using the approximate timeout source; for this reason, I added a g_timeout_add_seconds_full() inside GLib and the equivalent code directly inside GtkRecentManager.

Company Calls Epilogue

May 4, 2007 on 5:45 pm | In Hacking, GNOME, C, recent-files, gtk | 9 Comments

Today I gave the final touches to a patch based upon the patch for search capabilities in the GtkFileChooser embeddable widget, adding the “Recently Used” shortcut:

File Chooser Support for Recently Used Files

there are still a few missing bits (the icon for the shortcut is one of them) but it’s already working remarkably well. I’ll work toward implementing what’s left in the next few days, while I also fix some of the warts of the search support.

Company Calls

May 3, 2007 on 10:20 am | In Hacking, GNOME, C, gtk | 20 Comments

Search support for the GtkFileChooser (#344785) landed in GTK+ trunk. It’s a patch written by Federico and updated by Matthias Clasen (I merely kept it in sync with trunk). The patch adds a private search engine abstraction object and three implementations, using libbeagle, libtracker and a simple file-tree-walking search. There’s no hard dependency on Beagle or Tracker: the libraries are opened using g_module_open() if they are found installed on your system, otherwise it’ll all fall back to the simple search backend (it’s the same solution used by Nautilus for its search support).

The file chooser now has a “Search” shortcut:

GtkFileChooser Search Support/1

If you double click it, you’ll get a search pane:

GtkFileChooser Search Support/2

Where you can search for “foo” and get the matching results:

GtkFileChooser Search Support/3

Next stop: fix all the missing bits (#435343) and add a “Recently Used” shortcut showing the list of recently used files (bug #435342).

By the way: libbeagle has an incredibly nice API, whereas libtracker doesn’t. Please, Tracker developers: instead patching projects or writing a GTK+ widgets library which only new projects can use, focus on writing a nice, GObject-based API for all the existing projects out there. Pretty please, with the sugar on top.

Of Angels And Angles

March 8, 2007 on 6:46 pm | In Hacking, GNOME, C, open-source, developer, gtk | 6 Comments

GtkApplication class: I’ve updated the application class page on the wiki. Now, it has an updated layout of the API (which is what I’m currently working on) and the design requirements it should fulfil. While writing it I had some sort of epiphany about the whole library consolidation effort and its perception among the platform developers. Project Ridley as it stands is a double-edged sword: on one hand we’d like to have more functionalities moved from external libraries to GLib and GTK+; on the other hand, the size of the platform libraries maintainer teams is not growing at the same rate. If we are to move widgets, features and whatnot to GTK+ we must be sure not only that someone is actively working on them after inclusion, but also that someone is willing to work on the rest of the codebase, in order to review the patches leading to the inclusion of new functionalities. So, waiting for Project Ridley to come to the rescue is not going to cut it anymore: if you are proposing to move some functionality from a library to GLib or GTK+ be prepared to work on the whole code and not only on your pet feature.

GtkUnique: since a “single instance application class” doesn’t really make any sense without an “application class” to make it inherit from, I’m punting the GtkUnique inclusion in GTK+ until the application class lands in first - and that makes it part of the post-2.12 masterplan; hence, I’m going to remove the gtk namespace from gtkunique and releasing it as a standalone library for the time being. I’ll commit the namespace switch before this weekend: it’ll switch from GtkUnique to Unique; everything else will stay the same. Remember to check it out from GNOME SVN server:

  svn co http://svn.gnome.org/svn/gtkunique/trunk

GConfig: as I mentioned in the last blog post, I’m working on the next iteration of GConf. Aside from ongoing design and API churning, I’ve also submitted a talk proposal for the next GUADEC about how to tackle the whole ‘GConf issue’. GConf is part of the core GNOME platform, and it has been so since 2000; it’s almost seven years old, and now it begins to show its age. Since 2001, Havoc has been asking the community to implement the same set of (five) features; no one has answered his call yet. Maybe the community is to be blamed for this; maybe we need to rethink part of the GConf design to allow someone other than ‘the usual suspects’ to fix GConf shortcomings and add new features. For instance: the backend API is a really nasty piece of code and it’s not easy to drop a new backend into an existing GConf installation; probably, that’s also why, after all these years, we still have only the XML and had to wait a long time for the evo-ldap backends. I’m going to put a page on the wiki with what kind of API I’m thinking about.

talks: aside from the GConf talk, I’ve also proposed a talk/tutorial about the Perl bindings for GTK+. I’ll also do two talks about Perl, GObject and GTK+ at this year’s Nordic Perl Workshop which will be held at the end of April in Copenhagen.

Live Wire

March 2, 2007 on 2:09 pm | In Hacking, GNOME, C, project-ridley, developer, fosdem, gtk | 3 Comments

Back from FOSDEM 2007, after a little detour in Helsinki.

I’ve opened a bug for the places support in GtkFileChooser: #413076. Attached to it you’ll find a patch; it should be taken with a grain of salt: it’s still a work in progress, but implements the main features and shows how the new API should work. In short, if your application need to use some predefined, user visible folder and you want to provide a link inside the file chooser, you need to create your bookmark file, drop it somewhere and call:

gtk_file_chooser_add_shortcuts_from_file (file_chooser
                                          “/path/to/bookmarks.xbel”,
                                          NULL);

We’d need an intltool able to recognise the title (and eventually description) markup elements of the bookmark files and merge them into the translation pool, so that you can have the places already localised (the machinery is already in place in the patch). I’ll keep working on it, and finish up the implementation of the automagic places that applications can install in a common place and have it appear in every file chooser, based on the group or application name used in the bookmark.

I’m also working again on the Application class (the wiki page is really out of date with the current iteration I have been workin on - I’ll update it as soon as possible); now that the session management code has landed in libegg I will add hooks into the application class to have it do The Right ThingĀ®. Other than an application class, GTK+ really needs a desktop abstraction - a simple API to know whether we are connected to a network, or to control the screensaver, or to launch the default browser/mailer/editor/whatever. For that to work properly we should really have a working configuration system like GConf moved below GTK+. I did some prototype API for a configuration engine, mostly stealing^Wtaking inspiration from alexl work on GVFS (which already has a nice and clean API); will probably have something usable soon.

Like Eating Glass

February 22, 2007 on 5:52 pm | In GNOME, C, open-source, developer, gtk | 7 Comments

Desktop-devel-list (d-d-l) is an interesting place. You follow discussions that usually tend to fork off, moving through tangential arguments; but, in the end, some stuff keeps turning up. Lately, for instance, every thread seems to end up on discussing about Tracker.

Let’s take the discussion about having a GNOME “media center version”; you could think that such a discussion will end up laying out some ideas about a media center. Wrong: we ended up discussing about special folders - an argument that has already been discussed to the death. Obviously, if you read d-d-l all day you can’t really expect having time to actually work on the features (or the crack) proposed on the list. So, for a change, I decided to do stuff after saying what could be done. I decided to take an idea that has been floating around for ages and implement it.

This is a simple FileChooserDialog, but the places list have been generated using a bookmark file (read using GBookmarkFile) in $HOME/.local/share/places/gtk-bookmarks.xbel instead of $HOME/.gtk-bookmarks:

FileChooser using bookmark file
It’s completely identical to the FileChooser in trunk, really, but the places on the left are parsed using this.

The code, obviously, merges the places saved using the old format.

This, instead, is a trivial Perl application that can read all the places; it can also edit them, add new places and remove old ones:

GTK+ shortcuts editor

The fun part about switching the file chooser to the bookmark files is that it’s public API, so everyone can read, change and write these locations. We can add new locations to an application like we add Glade files, and let the file chooser populate itself by loading a file; so, instead of using:

  gtk_file_chooser_add_shortcut_folder (file_chooser, some_location);

we could use:

  gtk_file_chooser_add_shortcuts (file_chooser, PKGDATADIR "/shortcuts.xbel");

But wait, the keen reader familiar with the issue will interrupt, the whole point of this mess is localising the name the user sees in the interface. Indeed, that’s why the bookmarks have a title and a description; through intltool we can extract those two and put them into the po file for the translators to work on - exactly like we do for the Glade files. Before displaying the bookmark will pass the string through gettext, which will return the localised alias using the application’s domain - or we could add domain argument to the gtk_file_chooser_add_shortcuts() function above.

The file chooser can also load shortcuts automatically, using the application name to filter out what’s interesting.

Is this the most correct solution for this problem? I don’t really know, even though using bookmarks and applications make more sense than using dot-desktop files and MIME types (come on? MIME types? Like I should bind a directory to specific types of content and not to the applications that are most likely to use them - and what are “MIME types” anyway?). At least, however, this is a start and there’s some code to comment on.

The patches are roughly done, but the real treat would be to split the places section of the file chooser widget into its own widget and let other applications, like nautilus, use it directly without having to cut and past tons of code out of GTK+.

Little Earthquakes

November 2, 2006 on 11:05 pm | In Hacking, GNOME, C, announce, open-source | 8 Comments

After two weeks without working on it, this evening I finally returned to GtkUnique and finished the bacon-like backend. Now, beside using D-Bus and Xlibs, you can use Un*x sockets as an IPC method to send a command to a running instance of an application which is using GtkUnique.

Next items in the TODO are:

  • Add more documentation on the protocol used in the three backends;
  • Fix the Perl bindings;
  • Finish and publish the Python bindings;

In the meantime, you can grab GtkUnique 0.5.0 here or pull it from the bazaar repository.

Boogie Woogie Bugle Boy

August 1, 2006 on 11:50 pm | In Hacking, C, recent-files, developer, gtk | 2 Comments

Lately there has been some activity in projects moving from EggRecent to GtkRecent. Obviously, this led to questions and bugs opened about the API.

One of the questions is: if I had a EggRecentModel singleton what should I use now?. Since EggRecent needed a EggRecentModel around for the entire lifetime of the recently used files list, you had to keep at least a singleton around; you also had to pass it to the objects (not widgets) displaying the list, because each istance of the objects would modify the list itself. GtkRecentManager does not need that, since the widgets usually use their own internal instance of the manager and they don’t change the list in any way. So you can create a new GtkRecentManager and keep it around as a singleton (remember to call g_object_unref() on it when finished, otherwise you’ll leak it):

GtkRecentManager *manager_singleton = gtk_recent_manager_new ();

and then pass it to the widgets:

GtkWidget *dialog =
  gtk_recent_chooser_dialog_new_with_manager (“Recent Documents”
                                              parent,
                                              manager_singleton,
                                              GTK_STOCK_CLOSE,  GTK_RESPONSE_CLOSE,
                                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                              NULL);

Nevertheless, you should really use gtk_recent_manager_get_default() which will do the right thing, and pass you a per-process instance and you won’t have to care about its memory management (no g_object_unref() when quitting). Also, using gtk_recent_manager_get_default() means that you don’t have to use the _with_manager variant of the widgets constructor, as they will use the per-process GtkRecentManager by default. Using your own GtkRecentManager makes sense only if you want to use the “filename” constructor-only property to specify your own storage file (and you should do that only if you know what you are doing):

GtkRecentManager *manager = gtk_recent_manager_get_default ();

  ...

GtkWidget *dialog =
  gtk_recent_chooser_dialog_new (“Recent Documents”
                                 parent,
                                 GTK_STOCK_CLOSE,  GTK_RESPONSE_CLOSE,
                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                 NULL);

Another question is the dreaded I want an inline list of recent files in the File menu; I’ll redirect you to the bug report linked for the rationales about why I think the inline list sucks, and should be removed from the UIs of GNOME applications in favour of the sub-menu. Anyhow, for those Unbelievers still using this Windows-cloned relic of the past, here’s a simple function for adding an inline list to an existing GtkUIManager instance; it’s part of a example of integration between GtkRecent and the UI manager I sent to the gtk-devel mailing list before GUADEC.

static void
add_inline_recent_items (guint         merge_id,
                         GtkUIManager *ui_manager)
{
  GtkActionGroup *action_group;
  GtkRecentManager *manager;
  GList *items, *l;
  guint i;

  action_group = gtk_action_group_new (“recent-info”);
  gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);

  manager = gtk_recent_manager_get_default ();

  /* we don’t care about sorting and filtering, but it can
   * be done using g_list_sort_with_data() and clamping the
   * resulting list to the desired length
   */
  gtk_recent_manager_set_limit (manager, 4);
  items = gtk_recent_manager_get_items (manager);

  /* no items: attach an insensitive place holder */
  if (!items)
    {
      GtkAction *action;

      action = g_object_new (GTK_TYPE_ACTION,
      			     “name”, “recent-info-empty”,
			     “label”, “No recently used files”,
			     “sensitive”, FALSE,
			     NULL);
      gtk_action_group_add_action (action_group, action);
      g_object_unref (action);

      gtk_ui_manager_add_ui (ui_manager, merge_id,
  			     “/MenuBar/FileMenu/RecentFiles”,
			     “recent-info-empty”,
			     “recent-info-empty”,
			     GTK_UI_MANAGER_MENUITEM,
			     FALSE);

      return;
    }

  for (i = 0, l = items;
       l != NULL;
       i += 1, l = l->next)
    {
      GtkRecentInfo *info = l->data;
      gchar *name = g_strdup_printf (“recent-info-%d-%lu”,
      				     i,
				     (gulong) time (NULL));
      gchar *action_name = g_strdup (name);
      GtkAction *action;

      action = g_object_new (GTK_TYPE_ACTION,
      			     “name”, action_name,
			     “label”, gtk_recent_info_get_display_name (info),
			     “stock_id”, NULL,
			     NULL);
      g_object_set_data_full (G_OBJECT (action), “gtk-recent-info”,
                              gtk_recent_info_ref (info),
			      (GDestroyNotify) gtk_recent_info_unref);
      g_signal_connect (action, “activate”,
                        G_CALLBACK (recent_activate_cb), NULL);
      gtk_action_group_add_action (action_group, action);
      g_object_unref (action);

      /* all you need is a UI definition with a “placeholder” element called
       * “RecentFiles” under a “menu” element called “FileMenu”.
       */
      gtk_ui_manager_add_ui (ui_manager, merge_id,
  			     “/MenuBar/FileMenu/RecentFiles”,
			     name,
			     action_name,
			     GTK_UI_MANAGER_MENUITEM,
			     FALSE);

      g_print (“* adding action `%s’n”, action_name);

      g_free (action_name);
      g_free (name);
    }

  /* unref the info objects so that they will be destroyed when
   * the actions to which they are bound are destroyed with the
   * UIManager instance
   */
  g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
  g_list_free (items);
}

This code should give you an idea on how to implement your own version. Making the menu reloading the inline list means removing the UI definitions using the merge_id integer and calling this function again inside a callback attached to the “changed” signal of a GtkRecentManager instance, and it is left as an exercise for the reader. ;-)

GtkRecent and GtkUIManager

I’m really sorry that the UIManager integration did not happen in time for 2.10; it means that some applications will have to implement it by themselves until GTK+ 2.12 is out with a common implementation. In the meantime, continue asking me or opening bugs in Bugzilla.

Update@2006-08-02T09:51+0100: the complete code now has the “reload-when-list-change” feature. Remember: you may cut and paste this code for a basic support of recent files inside an inline menu; there are at least another couple of ways to implement the same level of support, and mostly it depends on how you handle your own documents. I’d like for GTK+ or libgnome or GLib to have a “document” class abstracting most of this and other stuff, like Cocoa on OSX has the NSDocument class.

Update@2006-08-02T16:05+0100: another update - I’ve fixed a couple of leaks (a GtkAction is a GObject and not a GtkObject) and added the sorting function for the inlined list.

Ride on a White Horse

July 24, 2006 on 5:12 pm | In Hacking, C | 6 Comments

Filed under the category: “useful programming tips for problems that bit my ass”

The wise men from old said: Thou shalt not check if a directory or file existeth before creating it.

Well, or something like that.

I often see code that looks like this:

if (!g_file_test (some_directory, G_FILE_TEST_EXISTS))
  {
    if (g_mkdir (some_directory, 0700) != 0)
      {
        g_warning (”Unable to create `%s’”, some_directory);
        return;
      }
  }
else
  do_something_with_some_directory (some_directory);

or, worse, code that looks like this:

if (!g_file_test (some_file, G_FILE_TEST_EXISTS))
  {
    symlink (some_other_file, some_file);
  }

Despite a BFW on the g_file_test() API reference page.

These code snippes are wrong, because they contains an implicit race: what if the directory/file you are checking suddenly disappears (or is created)? Also, blindly invoking functions like g_mkdir() or symlink without checking the returned value (”hey, I just checked so how can it fail?”) is looking for troubles; finally: when a system call fails, you should always report the error message the OS sets: too many things can go wrong, and if you can get a meaningful message then you’ll be able to debug faster.

The solution for these problems is: shoot first, then ask the questions. Or, in other words, execute the function inside the if block and act according to the results. For this to happen, you’ll often need to rely on errno.h and g_strerror():

#include <errno.h>if (g_mkdir (some_directory, 0700) == -1)
  {
    if (errno != EEXIST)
      {
        g_warning (”Unable to create `%s’: %s”,
                   some_directory,
                   g_strerror (errno));
        return;
      }
  }

do_something_with_some_directory (some_directory);

and:

#include <errno.h>if (symlink (some_other_file, some_file) == -1)
  {
    if (errno != EEXIST)
      {
        g_warning (”Unable to create a link from`%s’ to `%s’: %s”,
                   some_other_file,
                   some_file,
                   g_strerror (errno));
        return;
      }
  }

At the end of the if block we are guaranteed that the file or the directory does indeed exist either because we successfully created it or because the system call failed and errno was set to EEXIST; inside the if, instead, we can deal with failures, using various error trapping branches based on the value of errno (just remember to store it if you’re going to use it multiple times).

Tides that I tried to swim against

July 12, 2006 on 2:14 pm | In Hacking, Perl, C, recent-files, gtk, ohand, clutter | No Comments

gtk-recent: For those who missed the mail on gtk-devel-list, language-bindings and desktop-devel:

Unfortunately, when importing the GtkRecent API in GTK+ I made a mistake and these two functions have been erroneously left inside the GtkRecentChooser interface API:


  gtk_recent_chooser_set_show_numbers()
  gtk_recent_chooser_get_show_numbers()

These two functions try to set the “show-numbers” property, which is installed only by GtkRecentChooserMenu and it’s not one of the properties defined by the GtkRecentChooser interface. Using these functions on a GtkRecentChooserMenu (or any other custom GtkRecentChooser implementation which defines a boolean “show-numbers” property) will yield the expected results, while using them on a GtkRecentChooser implementation that does not support the “show-numbers” property will result in a warning.

Since we are in a stable release we can’t mark those functions as deprecated, and we cannot remove them without breaking the API. You are advised not to use these functions: use the GtkRecentChooserMenu functions instead:


  gtk_recent_chooser_menu_set_show_numbers()
  gtk_recent_chooser_menu_get_show_numbers()

Language binding authors should not bind those functions, but bind the GtkRecentChooserMenu functions instead.

These functions will be marked as deprecated as soon as GTK+ will branch off for the 2.11/2.12 cycle, so you’ll have to bear with this inconsistency for a short period of time.

language-bindings/1: By the way, gtk2-perl now supports the GtkRecent code in HEAD, thanks to the hard work of Torsten kaffee Schoenfeld who fixed most of my first iteration binding code and wrote the tests for it.

language-bindings/2: I also finished the Perl bindings for Clutter, as well as the Python ones. As I changed Clutter to behave like GTK, with the ClutterActor objects being created with a “floating” reference count, you’ll have to update Clutter to HEAD if you want to test the bindings. Beware that Clutter’s API is still a bit fuzzy at the moment. Of course, if you find bugs in the library or in the bindings, be sure to report them.

Now Listening: Last-exit, Neighbour radio

You got me all wrong

May 8, 2006 on 11:23 pm | In Hacking, C, gtk | 2 Comments

This is actually a mail I sent on gtk-devel-list. Obligatory disclaimer: this is not a proposal for getting gnome-vfs inside GLib, or for making GTK depend on gnome-vfs or for replacing gnome-vfs entirely; please, read on before commenting.

A while ago, on IRC, Christian Persch made the request that the monitoring of the storage file used by the GtkRecentManager could be overridden by libgnome, so that every application using the GnomeProgram API would automagically have notifications of file changes using gnome-vfs, instead of the default implementation which stat()s the file once in a while.

This spawned a more interesting discussion about how to implement a simple file monitoring API inside GLib; my approach and Christian’s were equivalent, and resolved in a new object with a vtable to be overridden per-process. Matthias, instead, suggested using a GSource, and having the file monitor to play nice with the main loop. Thus GFileMonitor was born.

Continue reading You got me all wrong…

Lazy loading

March 30, 2006 on 7:11 pm | In Hacking, GNOME, C | 9 Comments

Little post about a useful design pattern in GLib and GTK, written down after a question on the #gtk+ channel

While I’m not Philip and I won’t go as far as talking about this in public, I wrote down a simple design pattern for lazy loading stuff from a list into a GtkTreeView without blocking your interface or using threads.

Lazy loading using the main loop.

Roadmap

January 28, 2006 on 5:50 pm | In Hacking, GNOME, C, gnome-utils | No Comments

With the incoming release of Gnome 2.13.90, we are approaching the 2.14 version of Gnome. Now, features are frozen, and soon even changing the UI will require at least two approvals (one from the GUP and one from the release team); so, while we still have a full month for fixing bugs, I think it’s time for some little thinking and planning ahead about the next release cycle of gnome-utils.

The biggest job for the 2.15/2.16 cycle will be the cleaning up of the System Log Viewer. The code-base is a bit messy, but thanks to the great work of Vincent we’ve avoided the Design by Accretion Syndrome; still, even a white space consistency patch would be in order: some lines have a (horrid) three-space indentation, while some other have a tab indentation. So, I’d move everything to a tab-based indentation. The other “cosmetic” clean up is the removal of the dead and/or obsolete calls, the usage of a naming scheme for the classes and functions, and a switch to typed objects (e.g. boxed types and GObject-based types). I’ve already begun some attempt at cleaning up the code base, but this will most likely require to land in a new branch as soon as we release gnome-utils 2.14.

The other job is the implementation of a couple of transport methods for Dictionary, namely the HTTP-based transport, which should allow the connection to a web-based dictionary service; the file-based transport, which should allow the querying of locally available dictionaries; the StarDict transport, similar to the file-based one, but including a C parser for the StarDict format. Regarding this format, I’ve had a look at the C++ library and I seriously think that before releasing some software under an open source licence, a serious check on the code style should be in order; I don’t like C++, I think it’s inherently inefficient and messy, but something like this:

sd-lib-cpp
whitespace horror in lib.cpp

should really be closed source software - in order to avoid programmers throwing themselves out of the window after having had a look at it.

One more job would be the re-working of the gfloppy utility, with the addition of the ability to format every removable media (floppies, USB sticks, CD/DVD RW, etc). This will require some updates inside HAL - namely, the volume formatting and partitioning support. I think that, while floppies are becoming more and more rare these days, gfloppy might be reborn into something very useful again.

Finally, the last job for the 2.15/2.16 cycle should be the update of the Screenshot utility. First of all, I’d like to close bug #325708, but the whole bug list should be triaged and updated.

Obviously, I can’t promise that everything will be ready in time for 2.16. As always, patches that will make this happen faster are welcome.

Next Page »

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^