The libgnome library is the non-toolkit specific
utility library for GNOME applications, and includes things like configuration
file reading, .
A D V E R T I S E M E N T
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.
Configuration Files
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.
Do note however that these routines are marked deprecated for GNOME 2.0.
The reason is that there is now a much better library for storing
configuration data called
GConf. GConf will also be a part of the GNOME 1.4 release so you can
start using it for stable applications at that time.
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.
Reading Configuration Info
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);
Note that the string returned by
gnome_config_get_string should be freed with
g_free, the vector from gnome_config_get_vector
should also be freed with g_free.
Writing Configuration Info
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();
Privacy Functions
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.
Using gnome-config for Arbitrary
Files
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();
Note that it doesn't really make sense to use the private versions when
using an arbitrary absolute path, as there will be absolutely no
difference between the two.
Automatic Prefixes
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:
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.
.desktop Files
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:
You will notice that there are translations for Name and Comment fields in
Czech. For gnome programs to notice your .desktop file, it is usually
located somewhere under <prefix>/share/apps/, which
contains the hierarchy of the system menus. For the system to find your
icon, your icon should be placed inside the
<prefix>/share/pixmaps directory. Note that the prefix refers to the
location where GNOME was installed.
Utility and Files
Files
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. Also these functions are only for finding files that were
installed with the GNOME libraries. There is not at this time functions
to deal with data installed by your application. The functions are:
Table 3-1. File Finding Functions
Prototype
Description
char *gnome_libdir_file (const
char *filename)
Get a full path of a file in
the library directory or NULL if the file doesn't exist
These functions return a newly g_malloced
string and you should use g_free on the string
when you are done. The gnome_unconditional_*
functions don't check if the file actually exist and will just return a
file name. The normal functions will check and return
NULL if the file doesn't exist. So you shouldn't
use those functions when you will do saving. As an example we want to
get a pixmap from the standard pixmap directory, for example we need to
get the "gnome-help.png" icon:
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.
Utility
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.
Mime Types
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);
}
Note how easy it is to find out what files you got, and what type they are.
You would just need to add some code instead of the three dots that actually
compares the mime strings you got to some you have to figure out what you
can do with the files.
Meta Data
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.
Table 3-2. Metadata Functions
Prototype
Description
int gnome_metadata_rename (const
char *from, const char *to)
Notify the metadata database that
a file has been renamed
int gnome_metadata_copy (const
char *from, const char *to)
Notify the metadata database that
a file has been copied
int gnome_metadata_delete (const
char *file)
Notify the metadata database that
a file has been deleted
int gnome_metadata_set (const char
*file, const char *name, int size, const char *data)
Set data associated with the file
'file', and key 'name'. The data is pointed to by 'data' and is
'size' bytes long. GNOME_METADATA_OK is returned on success.
int gnome_metadata_get (const char
*file, const char *name, int *size, char **buffer)
Get data associated with file
'file' and key 'name'. Data will be copied to a buffer and
'buffer' will be set to point to it, and 'size' will be set to
the size of the buffer. GNOME_METADATA_OK is returned on
success.
char **gnome_metadata_list (const
char *file)
Get a list of the keys for which
there is some data set on 'file'. The list will be a newly
allocated, NULL terminated string vector and should be freed
with g_strfreev
Table 3-3. Metadata Return Values
Name
Description
GNOME_METADATA_OK
No error (this is actually 0)
GNOME_METADATA_IO_ERROR
IO or other low-level
communications/storage error.
GNOME_METADATA_NOT_FOUND
Information not found.
These functions don't actually do the operations on the files, they just
change the meta-data accordingly. So if your app does any of these
operations, it is nicer towards other apps, that it notifies the meta-data
database of the changes. You shouldn't rely on the data being stored. Only
non-critical data should be stored in the meta-data, since apps that do not
notify the database with these functions will make you loose your data for
the file. These functions will return 0 or
GNOME_METADATA_OK if there was no error, or an error-code (described
above).
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 GNOME_METADATA_OK 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);