Learn from mistakes

Ever made a mistake because you thought you knew how to use the APIs but they didn't work quite the way you assumed? Or that there was an API that would've made your job much easier had you known it existed? Or the food you had for lunch wasn't good and made you all confused while coding?

Well here's your chance to share those experiences so that the next person trying to do things wouldn't have to repeat the same mistakes, all over again.

Double-check the signal handler signatures

static void widget_button_press_event_cb (GtkWidget *widget, MyData *data)
{
   ...
}

MyData *data = my_data_new(...);

g_signal_connect (widget, "button-press-event", G_CALLBACK(widget_button_press_event_cb), data);

Looks innocent enough? Well, the problem is that the correct signature for button-press-event signal handler would have been:

  static gboolean widget_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, AppData *data)

Failing to return correct return value in such handler can unintentionally make the widget ignore the signal and with, for example, GtkButton effectively disable the button completely.

Of course missing one (or more) function argument is very likely to cause a crash.

String length, in bytes or characters?

Consider the following piece of code:

  glong length = g_utf8_strlen (str, -1);

  if (str[length-1] == '/')
    str[length-1] = '\0';

The intent is clearly to remove trailing slash and the savvy developer is also aware of UTF-8 character encoding and related issues. Too bad bytes and characters got mixed up in the process; str is an array of bytes but g_utf8_strlen() returns the length in characters. Thus the array index is incorrect, though it will work correctly if the string contains only ASCII.

The previous should've been written using strlen() which returns the length in bytes:

  glong length = strlen (str);

  if (str[length-1] == '/')
    str[length-1] = '\0';

Assuming the path separator is /

One possible use of the code in the previous example is to extract the directory component of a file name. This will work fine on Unix-like systems. However, large sections of the GNOME infrastructure can be used on other operating systems with different path separators (e.g. ':' or '\'). To make your life easier glib provides a series of operating-system independent functions for handling file names. In the previous example the appropriate function would be g_path_get_dirname. The full list is:

g_build_filename and g_build_filenamev

Construct a path to a file from directory names and the file name.

g_path_is_absolute

Determine if the path is fully-specified from the root of the filesystem.

g_path_skip_root

Get rid of the root of the path.

g_path_get_basename

Get the final part of a file name. i.e. the actual file.

g_path_get_dirname

Get the directory part of a file name.

The miscellaneous section of the glib documentation has many useful and portable functions.

Implementing "Edit/Select All" for treeviews

Imagine you have a GtkTreeView and you want to implement "Edit/Select All" functionality. One way to do it would be to use gtk_tree_model_foreach() and select all items in the callback. Or if you check the API documentation again you could see gtk_tree_selection_select_all() which would do it more easily and efficiently.

Bloopers (last edited 2013-07-26 15:16:18 by SébastienWilmet)