Dictionary Applet/10

The merge of the new-dictionary branch into gnome-utils HEAD is fast approaching: I’ve set the deadline to the end of the week – in time to write off the last bits of the preferences dialog:

gdict-pref-dialog
the sources tab of the preferences dialog

Right now, you can’t add or activate a new dictionary source, unless you write the .desktop file and drop it into $HOME/.gnome2/gnome-dictionary, and then change the /apps/gnome-dictionary/source key inside GConf – but I plan to have this nailed down in the next couple of days (the UI for both display and edit has already been designed using Glade).

gdict-pref-dialog
the printing tab of the preferences dialog

The font selection thingy for the printed output is, instead, already working.

Known regressions: the text highlighting is still missing, and I don’t know if it’s going to make it not only before the merge deadline, but also before UI freeze.

[]
[]
[]

Dictionary Applet/9

I’ve added printing support – after a bit of struggle with GnomePrint:

The output format is stolen^Winspired by Gedit, and the font is hardcoded as Serif, 12; I’ve already added a GConf key to the shipped schema – GConf integration, as well as preferences are still in a state of flux. Now that the printing is mostly nailed down, I’ll resume work on the UI side, by adding a status bar and the preferences dialog. Also, work on the applet will begin as soon as these issues are solved; the applet should be, in fact, very easy to code.

Note: It seems that a critical warning is issued each time a print dialog is destroyed and then recreated – like some signals handlers that aren’t correctely disconnected; I’ll have a look at it, but it seems a bug of libgnomeprint as far as I can tell. Update 20051212@02:53: it is now bug #323836 of libgnomeprintui

Also, judging from the memory consumption, I’m afraid of some leakage inside libgdict (mostly). I’ll have a run with Valgrind, and see what’s going on under the hood. Update 20051210@16:33: it seems that I was fooled by the system monitor memory usage graph, as I found two simple leaks (due to me being a sloppy coder), accountable of just 6kB lost – and just once per process, since one was inside the singleton init, and the other inside the GdictSourceLoader directory walking. Both are now fixed inside my development trunk. I’m positive that, if the trend continues, the new code might land inside HEAD the next two weeks – given that the preferences dialog and the dictionary source creation code are pretty much done, and that the applet will be easy to code. Once we reach feature freeze time (in January), I’ll devote myself in writing a good user’s manual. Some might think that the next release will be a regression, but believe me: the trade-off of a few features for code readability, maintainability and overall performance is well worth it; features will be re-implemented in no time.

[]
[]
[]

Maintainership/2

I’ve just committed my development trunk of Dictionary on the CVS, as usual to new-dictionary branch.

Features

  • a navigation menu, with shortcuts for first/previous/next/last definitions
  • a Ctrl+Shift+G shortcut for search backwards
  • a “Save a Copy” menu item, used to save the content of the query to a text file;

It also features a stub for the user’s manual and some clean-ups for the build system.

What’s next?

I’m working on the printing system and the preferences dialog.

I’ve decided to remove the font preference, in order to make it the same of the desktop; I don’t want yet another font chooser. The only place where it makes sense to have another font is when printing – and for that we might just have a key in GConf.

Also, the text highlighting is going to be scaled down: since we are going to use multiple dictionary sources, over multiple languages, we really don’t know a priori some things, like how the enumerations will look like. The only text modifiers I’m going to keep will be [...] attributions (which will be rendered using italics); \...\ phonetics (which will be rendered in a styled color, default: gray); {...} links (which will be rendered in a styled color, default: blue).

[]
[]
[]

Maintainership

Vincent kindly asked me to join the maintainer team of gnome-utils, and I more than gladly accepted.

In order to celebrate the event, here’s the latest screenshot of my development trunk for Dictionary:

gnome dictionary new
the new Dictionary

As you can see, the current state is not far from the actual, stable, Dictionary:

gnome dictionary old
the old Dictionary

What’s missing:

  • the text parsing
  • the menu callbacks
  • the preferences dialog
  • the user’s manual
  • print support

The feature equivalence could require a bit more time than foreseen – especially the printing part and the manual – but I plan to have everything in place befor Christmas: think of it as my gift.

I plan to commit the new-dictionary to HEAD as soon as I have finished the menu callbacks and the preferences dialog.

[]
[]

Documentation

In the last thirty minutes I’ve ported gnome-utils to the new, spiffy gnome-doc-utils system.

I hope that this could hit HEAD in the next few days (pending Vincent‘s approval)- the sheer amount of stuff deleted and/or changed is really high. This would allow better translations of the documentation of the tools inside gnome-utils.

Leaking/2

After some six hours, a chinese dinner, two large glasses of earl grey tea, and a coffee, I’m finally able to declare that, according to Valgrind, both the libegg/recent-files and libegg/recentchooser code are leak-free.

Okay, take this with a grain of salt, as I’m not that good with Valgrind, and some of the logic of my widgets might lead to leaks; as far as my mallocs are concerned, my code is leak-free

[]
[]
[]

Leaking

Yesterday, while I was at university waiting for a seminar about network security, I was on -it, and pbor asked me to look at a leak in EggRecentModel. I began wading through the code, but I didn’t found the leakage in time before having to leave.

In the evening, after I got back home, Marta went to her church choir practice, and I looked at recent-files/egg-recent-model.c using Valgrind (and practicing with it, since I’m not that good with this tool); using the function chain reported by valgrind, I noticed that the leak was inside the logic used by egg_recent_model_filter. This function scans the list of EggRecentItem objects built from the on-disk storage and filter out using the three pre-defined filter functions (while my RecentManager object supports only custom filtering function, and the RecentChooser implementations might filter the recently used resources list using a more complex RecentFilter object). The problem is that it used the infamous GList scan using while():

  while (list) {
    SomeData *obj = l->data;

    do something with the object

    list = list->next;
  }

This code is perfectly valid: it walks the list by exhausting it; that is: the list pointer reaches the end of the list once it reaches the end of the while. Valid code does not mean right code, though. Suppose you want to move the items of a list inside another list. By using the code above, you would have:

  GList *newlist;

  /* init the target list */
  newlist = NULL;
  while (list) {
    SomeData *obj = l->data;

    if (some_condition)
      newlist = g_list_append (newlist, obj);

    list = list->next;
  }

This code is also perfectly valid for filtering a list. Suppose, now, that you want to destroy the original list and return the filtered copy; you’ll have to free the GList using g_list_free() at the end of the while cycle:

  GList *newlist;

  /* init the target list */
  newlist = NULL;
  while (list) {
    SomeData *obj = l->data;

    if (some_condition)
      newlist = g_list_append (newlist, obj);

    list = list->next;
  }

  g_list_free (list);

  return newlist;

But we said above that the list is walked by exhausting it; hence, the list pointer is now NULL (the exit condition checked by the while cycle). Thus you are leaking the old list; to avoid this leakage, you must walk the list keeping a pointer to the list start. In order to do so, the right thing to do is to use an iterator pointer, and a for() cycle to keep the cycle compact and avoid messing up with the list = list->next assignments on every cycle break condition:

  GList *newlist, *l;

  for (l = list, newlist = NULL; l; l = l->next) {
    SomeData *obj = l->data;

    if (some_condition)
      newlist = g_list_append (newlist, obj);
  }

  g_list_free (list);
  return newlist;

This code does not leak the old list, but it leaks the data that was not moved to the new list; if the function to free the data is called some_list_free, the code above becomes:

  GList *newlist, *l;

  for (l = list, newlist = NULL; l; l = l->next) {
    SomeData *obj = l->data;

    if (some_condition)
      newlist = g_list_append (newlist, obj);
    else
      some_data_free (obj);
  }

  g_list_free (list);
  return newlist;

As a performance sidenote: if the list is long, you might consider using g_list_prepend, since it’s a constant time operation, while g_list_append walks the list; just remember to return the reversed new list:

  GList *newlist, *l;

  for (l = list, newlist = NULL; l; l = l->next) {
    SomeData *obj = l->data;

    if (some_condition)
      newlist = g_list_prepend (newlist, obj);
    else
      some_data_free (obj);
  }

  g_list_free (list);
  return g_list_reverse (newlist);

I had noticed the leak around 10:30pm and began fixing it, but I had to pick up Marta and both returned home at 11:30pm, when we went straight to bed and fell asleep almost immediately. This morning, I found bug #323002 awaiting, with a fix for the first part of the leak (thanks to Paolo). Now, libegg/recent-files HEAD has the leak fully plugged. Subsequent runs of valgrind showed no mor leaks related to the recent-files.

Now, I’m going to check my libegg/recentchooser and my libegg/bookmarkfile code for leaks.

[]
[]
[]

Dictionary Applet/8

I’ve finally been able to begin working on the new GNOME Dictionary widgets. While GdictEntry still has issues – related to the speed of word look up and the entry completion – and has already hit CVS, in the last two days I’ve been hacking on the definition display widget, or GdictDefbox (I’ve retained the name from the old code).

The new Defbox code is a little bit more simple – things like links are not implemented (yet, even though I found them questionable), and the output is not quite as good looking as the old one; here’s the obligatory screenshot:

gdict-defbox

the new GdictDefbox

Aside from code cleanliness and the new multiple back-end system, what differences there are with the old Defbox? First of all, this is a composite widget and not just a TextView-derived widget; this allows neat things like the next feature, that is the embedded search pane:

gdict-defbox

the embedded search pane

It should Just Work®: Ctrl+F to view it, Ctrl+G for the next match, Esc to close it. Say goodbye to silly find dialogs.

gdict-defbox

the embedded search pane at work

The new GdictDefbox also allows jumping from one definition to another, by tracking them internally.

With GdictDefbox nailed down, a simple Dictionary application and applet might already be created; I plan to improve the definition box’s output and put it on par with the current one (plus enabling theming of the colors/sizes using GtkStyle) before actually coding the new Dictionary – but keep checking out the new-dictionary branch of gnome-utils in the next week or so.

Update 20051129@13:49: the spiffy new GdictDefbox is CVS as of some minutes. Go and try it using the gnome-dictionary/libgdict/test-defbox.c test case.

[]
[]
[]

Long-standing

I’ve just committed some code that should hopefully fix bug #172587 of the old recent-files code.

The bug was hard to track down – and for it I do own a beer to Sebastien Bacher: it appears that older versions of OpenOffice creeped unescaped & into the dot-recently-used file we use to store the recent documents. The parser code inside EggRecentModel has always been a little too fragile (a mistake I tried to avoid since the beginning of my BookmarkFile parser code, by feeding it invalid XML/XBEL streams and trying to get errors instead of crashers), and thus gnome-panel had the tendency to crash until the dot-recently-used file was deleted or corrected.

I hope to close #172587 for good before marking the whole code as deprecated: it’s personal, now.