## Migrating from EggRecent to GtkRecentChooser

### Emmanuele

`<ebassi`gmail.com`>`

Since version 2.10, GTK+ provides a way of handling the recently used documents. It is similar to the code that has lived inside the libegg library and has been incorporated by many applications. The GTK+ version aims to completely replace that code, and offers many distinctive features that improve the registration and visualization of the recently used documents, such as:

- Better performances while reading and writing the list of recently used files

- More meta-data available for each recent document, like the applications that have registered a document inside the list, the last time and the number of times the same application did register a document inside the list, an optional user readable name and description of the document

- Improved the ability to sort and filter the documents, also using custom sorting and filtering functions

- New widgets for displaying the list, and better integration with current GtkFileChooser and GtkUIManager widgets

## Managing the Recently Used Documents

GtkRecentManager is used to manage the Recently Used Documents. To create a new GtkRecentManager, you simply call `gtk_recent_manager_new()`. Like the EggRecentModel inside EggRecent, the GtkRecentManager loads the list of the recent documents and notifies you of changes inside the list.

Usually, instead of creating a new GtkRecentManager each time you need it, you'll want to use the `gtk_recent_manager_get_default()` function.

To add a document to the list, you can use `gtk_recent_manager_add_item()`, like:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    GtkRecentManager *manager;

    	manager = gtk_recent_manager_new ();

    	if (!gtk_recent_manager_add_item (manager, document_uri))
    	  {
    	    /* warn about the error */
    	  }

    	g_object_unref (manager);

The `gtk_recent_manager_add_item()` function will try and guess some of the meta-data associated to a URI. If you know some of meta-data about the document yourself, set the desired fields of a GtkRecentData structure and pass it to the `gtk_recent_manager_add_full()` function instead:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    GtkRecentManager *manager;
    GtkRecentData *recent_data;

    	manager = gtk_recent_manager_new ();

    	recent_data = g_new0 (GtkRecentData, 1);
    	/* the user visible name of the document (maybe its title); should
    	 * be preferred when displaying the item into the list
    	 */
    recent_data->display_name = document_name;

    	/* the MIME type is mandatory */
    	recent_data->mime_type = document_mime_type;

    	/* the name of the application that is registering the document
    	 * (also mandatory); usually, the same name you used with
    	 * the g_set_application_name () function.
    	 */
    	recent_data-&app_name = APP_NAME;

    	/* the command to open a file; the %u string will be automagically
    	 * expanded to the document's URI when getting the application's
    	 * command line from the GtkRecentInfo object with
    	 * gtk_recent_info_get_application_info ()
    	 */
    	recent_data-&app_exec = g_strjoin (" ", g_get_prgname (), "--open-file", "%u", NULL);

    	if (!gtk_recent_manager_add_full (manager, document_uri, recent_data))
    	  {
    	    /* warn about the error */
    	  }

    	g_free (recent_data->app_exec);
    	g_free (recent_data);
    	g_object_unref (manager);

Getting the list of items is also similar to EggRecentModel; the GtkRecentInfo data is allocated at look up time in order not to waste memory keeping it around, so you must remember to free the data inside the list and then the list itself when you are done using it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    GtkRecentManager *manager;
    GList *recent_items, *l;

    	manager = gtk_recent_manager_get_default();

    	recent_items = gtk_recent_manager_get_items (manager);
    	for (l = recent_items; l != NULL; l = l->next)
    	  {
    	    GtkRecentInfo *recent_info = l->data;

    	    do_something_with_the_item (recent_info);
    	  }

    	/* free everything and the list */
    	g_list_foreach (recent_items, (GFunc) gtk_recent_info_unref, NULL);
    	g_list_free (recent_items);

You can also look up a single item:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    GtkRecentInfo *recent_info;
    	GError *error = NULL;

    	recent_info = gtk_recent_manager_lookup_item (manager, document_uri, &error);
    	if (error)
    	  {
    	    display_error (error);

    	    g_error_free (error);
    	  }
    	else
    	  {
    	    do_something_with_the_item (recent_info);

    	    gtk_recent_info_unref (recent_info);
    	  }

The GtkRecentInfo is a reference counted boxed type, and it holds all the meta-data of a recently used document, like its display name, its description, the list of each application that has registered the document or the list of groups to which the document belong.