Friday, September 23, 2011

How to create a Nautilus extension (aka nautilus plugin)

Nautilus is the default file manager for GNOME. You can textend the functionality of nautilus by writing extensions or plugins.  Extensions can be written in both c and python. This link explains the concepts, documents the API and even has example code snippets.This covers pretty much everything you need to know for writing a nautilus extension in C.  I have tried to add few missing or unclear items here.

1. Icons in context menu and emblem(icon overlay).

When writing a nautilus extension(or plug-gin), you can display your own icon on the context menu, or other menus. You can display you own emblem(also called icon overlay) as well.
What you have to do is to make use of the icon parameter of the corresponding API. For example the nautilus_menu_item_new function which can be used to create a context menu item has following signature in the official doccumentation.

NautilusMenuItem * nautilus_menu_item_new (const char *name,
const char *label,
const char *tip,
const char *icon);

Creates a new menu item that can be added to the toolbar or to a contextual menu.

name : the identifier for the menu item
label : the user-visible label of the menu item
tip : the tooltip of the menu item
icon : the name of the icon to display in the menu item

Returns : a newly create NautilusMenuItem

The last parameter "icon" is the one which we are looking for.
But its type is const char *. So we have to pass the name of the icon while invoking this function. But how to get the icon name?

If you dig a little deeper you will find that there is a thing called "The desktop icon system". The desktop icon system works according to the XDG Icon Theme
Specification at http://www.freedesktop.org/Standards/icon-theme-spec You can use an icon in your code once it is installed in the desktop icon system. So now the question is how to install an icon into the desktop icon theme?

There are some commands available on your desktop which starts with "xdg-" which are tools for various desktop integration operations. The set includes a command for icon management "xdg-icon-resource". You can use this command to install(or uninstall) an icon to the desktop icon system.
For example, to add a 48x48 icon file "name.png" with icon name "name" under the category "emblems" I would execute the command,

sudo xdg-icon-resource install --context emblems --size 48 name.png name

Check the man pages to learn the usage and more about this command.

Once you have added an icon to the desktop icon system you can use the icon name to refer to this icon in your code.

So for our context menu just pass this icon name as the icon parameter of the nautilus_menu_item_new function. The same way you can pass this icon name to other APIs which accepts an icon name.

NOTE:
In the latest GNOME versions, displaying of icons in the context menu is disabled by default. To enable this feature execute the below command.

$ gconftool-2 --type Boolean --set /desktop/gnome/interface/menus_have_icons true

You can check the current value of this param using,

$ gconftool-2 --get /desktop/gnome/interface/menus_have_icon



2. Context menu

The guide talks about adding a context menu item to the main context menu.
But in a similar way you can add sub menus and even create a multi level menu hierarchy. What you have to do is create menu items, create a sub menu, append menu items to sub menu, attach sub menu to a menu item in the parent menu.
Use the following APIs for that,

nautilus_menu_new
nautilus_menu_item_new
nautilus_menu_append_item
nautilus_menu_item_set_submenu

Check the official documentation for details.

3. Resources

You can check projects like RabitVCS to see an actual extension code in action.

These are some resources which describe desktop integration in general.

http://developers.sun.com/solaris/articles/integrating_gnome.html
http://library.gnome.org/admin/system-admin-guide/stable/mimetypes-9.html.en