The libgnome library is the non-toolkit specific utility library for GNOME applications, and includes things like configuration file reading, .desktop file handling, special GLib like utility routines, getting the standard file locations for GNOME, handling mime types, handling meta-data on files, sound, "triggers", and other useful things one could want to use. Also say that you are writing an application in say motif, but you want your app to be more GNOME friendly. Then you could use this library to make your application work well with other GNOME programs.
The gnome-config routines provide an easy way to store configuration info in files. To see a full list of the routines, look in the libgnome/gnome-config.h header file.
The routines all working with a path. The path is a Unix like path, but the root is set to the ~/.gnome/ directory. So /some/config/path/file/sectionA/keyB, refers to the file ~/.gnome/some/config/path/file, and inside the file using section sectionA and key keyB.
To read configuration information gnome_config_get_* functions are used. the * is replaced by the type of the data, it can be int, float, string, bool and vector. The int functions work with gint, float functions work with gdouble, string functions work with gchar *, bool functions work with gboolean and vector work with an argc like array of strings (gint and gchar **). For the gnome_config_get_* functions, the default to be returned if the file section or key are not found can be appended to the path after an equals sign. If you need to know if the default was used, you can append _with_default to the function name and add a parameter which is a gboolean *, though which the function returns whether it used the default or if it actually found a real value. Example follows:
int counter; char *text; gboolean def; ... counter = gnome_config_get_int_with_default("/example/section/counter=1", &def); if(def) g_print("Default used for counter!\\n"); text = gnome_config_get_string("/example/section/text=TEXT"); ... g_free(text); |
To write configuration info to files, the gnome_config_set_* functions are used. The use is very similar to above to the gnome_config_get_* functions. The types used are exactly the same. Except with the "set" functions, you pass the data you want to store after the path, and there is no default inside the path. If the directory in the path doesn't exist it will get created when the functions are written to disk. After you set all your data, you need to call gnome_config_sync to actually write your data to file. The library will not write the data to file immediately for efficiency reasons. Example follows:
char *text; int counter; ... /*after we have set text and counter to some values we can write them to our config location*/ gnome_config_set_int("/example/section/counter",counter); gnome_config_set_string("/example/section/text",text); gnome_config_sync(); |
If you want to store sensitive data, that other users should not read, use the gnome_config_private_* functions, which have exactly the same behavior as the above functions, with the exception of gnome_config_sync (and a few others) which doesn't have a private equivalent since it works for both. The difference is that these functions write to a directory called ~/.gnome_private on which 0700 permissions are enforced. This is not extremely secure, but because of the highly brain-dead US export restrictions, we can't really use encryption.
If you wish to use gnome-config for reading and writing of arbitrary files on the file-system (as long as those files are in the gnome-config format), you can just prepend '=' to the beginning of the path and another '=' to the end of the file name. Example follows:
char buf[256]; ... /*write some bogus data to a temporary file*/ g_snprintf(buf,256,"=%s=/section/key",tmpnam(tmpnam)); gnome_config_set_int(buf,999); gnome_config_sync(); |
Sometime, especially if you have a long path, would be much easier to say have the config automatically prefix the path with a given string. This is what gnome_config_push_prefix and gnome_config_pop_prefix are for. You pass the string you want to prefix to gnome_config_push_prefix and call gnome_config_pop_prefix when you are done. Note that these functions are common between private and normal config functions. Example:
gnome_config_push_prefix("/file/section/"); gnome_config_set_int("key1",1); gnome_config_set_int("key2",2); gnome_config_set_int("key3",-88); gnome_config_pop_prefix(); |
If you need to remove a file in your configuration file, you will use gnome_config_clean_file. This function will schedule that file to be deleted on the next gnome_config_sync. You can do a gnome_config_clean_file and then use the file and then do gnome_config_sync, and it will have the expected behavior.
If you have written to a file or read from a file and want gnome-config to drop it from memory, use gnome_config_drop_file. This is used if you want to forget changes done to that file, or to simply conserve memory, since gnome-config will otherwise keep a copy of the data in memory for faster access.
The .desktop files are the files that contain information about programs. The files are in the gnome-config format and are internally read using gnome-config. Your app definitely needs one of these files installed in the system menu paths if it wants to be added to the menu.
You can use gnome_desktop_entry_* functions to manipulate these files. These functions work with a structure called GnomeDesktopEntry and you should look at the libgnome/gnome-dentry.h header file for the format of this structure.
The basic functions that you use to manipulate these files are gnome_desktop_entry_load which returns a newly allocated GnomeDesktopEntry structure, gnome_desktop_entry_launch which takes the GnomeDesktopEntry structure as an argument and launches the program it describes and gnome_desktop_entry_free which frees the allocated memory with the structure.
An example .desktop file for your app might look like:
[Desktop Entry] Name=Clock Name[cz]=Hodiny Comment=Digital Clock Comment[cz]=Digitalni Hodiny Exec=digital-clock Icon=clock.png Terminal=0 Type=Application |
There is a standard way to find files that belong to gnome installation, you shouldn't really be using your own logic to find them and you should use these functions to get filenames for icons, sounds or other data. The functions are:
char *gnome_libdir_file (const char *filename); char *gnome_datadir_file (const char *filename); char *gnome_sound_file (const char *filename); char *gnome_pixmap_file (const char *filename); char *gnome_config_file (const char *filename); char *gnome_unconditional_libdir_file (const char *filename); char *gnome_unconditional_datadir_file (const char *filename); char *gnome_unconditional_sound_file (const char *filename); char *gnome_unconditional_pixmap_file (const char *filename); char *gnome_unconditional_config_file (const char *filename); |
char *name; ... name = gnome_pixmap_file("gnome-help.png"); if(!name) { g_warning("gnome-help.png doesn't exist!"); } else { /*here we use the file*/ ... g_free(name); } |
Also of interest are the functions (actually macros) gnome_util_home_file and gnome_util_user_home. gnome_util_home_file takes one argument (string) and returns a newly allocated string with the home directory and .gnome prepended to the file. So for example if you pass it say someconfigfile, it would return /home/jirka/.gnome/someconfigfile. Similar is the gnome_util_user_home, it takes one argument and returns the file with just the home directory added. So if you pass it .dotfile, it would return /home/jirka/.dotfile.
There are also a number of GLib like named functions to make your life easier, of note would be g_file_exists which takes a filename and returns TRUE if it exists or FALSE if it doesn't, or g_concat_dir_and_file which takes a directory name and a file name, and takes care of the '/' issue, this is useful when working with strings where you don't want to check for the '/', you just want to append a directory to some file, or another directory. Note that you should g_free the string you get as usual. For more utility functions, look into libgnome/gnome-util.h, it is well commented.
Sometimes it's useful to know the mime-type of a file. You can do this by using the gnome_mime_type_or_default function, which takes two arguments, the filename and a default mime-type string which it will return if it can't figure out the mime type from the filename. This call doesn't actually look into the file, it tries to guess the type by looking at the filename itself. Also the string it returns is a pointer to it's internal database and you should not free it as that would likely result in a segfault later on. You can also use gnome_mime_type which will return NULL if it can't guess the mime-type.
It is also possible to work with URI lists, such as the ones used sometimes in Drag and Drop. Usually from an URI list you want to extract a list of filenames that you just received. For that you use the gnome_uri_list_extract_filenames function, which takes the URI list as a string argument, and returns a GList * of newly allocated strings. Once you are done with the files, you should free the strings and the list. You can use the utility routine gnome_uri_list_free_strings to do this for you.
In the following example I write a drag and drop handler that takes the files and finds out their mime information, then you could just write code that can do things based on the mime type of the files.
/*this is the handler for the drag_data_receive signal, assuming our widget only accepts the "text/uri-list" mime type of data, drag and drop is a more complicated topic and you should read up on GTK+ documentation for better treatment*/ static void dnd_drop_internal (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time) { GList *files, *li; /*here we extract the filenames from the URI-list we received*/ files = gnome_uri_list_extract_filenames(selection_data->data); /*here we loop though the files and get their mime-type*/ for(li = files; li!=NULL ; li = g_list_next(li)) { char *mimetype; char *filename = li->data; /*guess the mime type of the file*/ mimetype = gnome_mime_type(filename); /*if we can't guess it, just loop to the next filename*/ if(!mimetype) continue; /*here comes code that can actually do something based on the mime-type of the file we received*/ ... } /*free the list of files we got*/ gnome_uri_list_free_strings (files); } |
Sometimes it is useful to store some information along with a filename, this can be done easily with the gnome-metadata. It is a set of functions to manage this data. Since Unix doesn't natively support meta-data, you have to help it yourself. For example if your app copies, renames or deletes files, use the following functions.
int gnome_metadata_rename (const char *from, const char *to); int gnome_metadata_copy (const char *from, const char *to); int gnome_metadata_delete (const char *file); |
Now if you actually want to use the meta-data to store information about files, you will most likely use the functions gnome_metadata_set, gnome_metadata_remove and gnome_metadata_get. Again these functions return an integer, which is 0 in case there was no error, or they use the same error codes as the previous functions.
The functions work with a a key string for which they store a piece of data. The data is represented by a size integer and a character pointer. gnome_metadata_set takes the filename as the first argument, the name or key of the data as the second argument, the size as the third and the pointer to the actual data as the forth argument. This function just sets that data for that file and key. gnome_metadata_remove will clear a particular data item on a file, so it takes a file and then the key name as the second argument. gnome_metadata_get takes the filename as the first argument and the key name as the second, then it returns data size though an integer pointer you pass though the third argument and the actual data though a pointer to a pointer you pass as the fourth argument. The data returned is newly allocated and should be freed after use. Small example follows (in real life you should also check the return of the functions for errors):
int size; char *data; ... /*set some bogus data on a file*/ gnome_metadata_set("/some/file/name","bogus",5,"BLAH"); ... /*retrieve the data back*/ gnome_metadata_get("/some/file/name","bogus",&size,&data); |