Usando el Marco de Desarrollo GnomeApp

Aunque el marco de desarrollo de aplicaciones GnomeApp pertenece a la biblioteca libgnomeui, realmente merece ser tratado de forma independiente. GnomeApp es la pieza que transforma un programa en una verdadera aplicación GNOME. Hace la programación simple y elegante y dota a las aplicaciones de muchos rasgos distintivos, haciéndolas consistentes con el entorno y configurables por el usuario. Programando ayudado sólo por GTK+, usted tendría que implementar multitud de aspectos en sus aplicaciones, reinventando la rueda en cada momento. Por contra, si emplea GnomeApp éste se hará cargo de la configuración de la IU (Interfaz de Usuario) por usted, permitiendo aún que el usuario pueda personalizarla y garantizando la consistencia entre diferentes aplicaciones.

Introducción a GnomeApp

GnomeApp es el widget básico detrás de cada aplicación en GNOME. Será su ventana principal y contendrá el documento sobre el que estaremos trabajando, los menús, barras de herramientas y barras de estado de la aplicación. Recordará así mismo la posición de las barras, permitiendo al usuario recuperarlas tal y como las dejó la última vez que utilizó el programa.

Creando una Ventana GnomeApp

Crear un nuevo widget GnomeApp es tan sencillo como llamar a gnome_app_new con el nombre de la aplicación, el cual es por lo general el nombre del ejecutable o cualquier otro que sea único relacionado con su programa, y el título de la ventana principal como argumentos. Luego usted deberá crear contenidos e ir añadiéndolos al widget GnomeApp mediante el método gnome_app_set_contents.

Añadir barras de menús, barras de herramientas y barras de estado no resulta más complicado: simplemente utilice gnome_app_set_toolbar, gnome_app_set_menus o gnome_app_set_statusbar. gnome_app_set_toolbar es adecuado para aplicaciones sencillas con tan solo una única barra de herramientas, si necesita mayor complejidad, use gnome_app_add_toolbar, que le permite añadir tantas barras de herramientas como precise.

Creación de Barras de Menús y de Herramientas

Creación Automática de Menús y Barras de Herramientas

En muchas de sus aplicaciones, usted no creará sus menús directamente sino que usará funciones de libgnomeui/gnome-app-helper.h que se ocupen de todo el proceso por usted. Todo lo que necesita es rellenar un par de estructuras con la información pertinente, llamar a gnome_app_create_menus o gnome_app_create_toolbar pasando dichas estructuras y ¡voila!, su aplicación tendrá ya menús y barras de herramientas. Algunas veces deseará pasar un puntero con la dirección de cierta información adicional a todas las retrollamadas que trabajen con esas estructuras, en tales ocasiones deberá usar gnome_app_create_toolbar_with_data y gnome_app_create_menus_with_data, y proveer un parámetro extra (El puntero).

Definición de la Estructura GnomeUIInfo

En este capítulo se describe la estructura que usted necesita rellenar para crear los menús de su aplicación (Realmente rellenará un vector de dichas estructuras). Se incluyen además los enumerados que precisará para completar la estructura.

/* Estos valores identifican la fuente pixmap que será agregado al 
elemento del menú  */
typedef enum {
        GNOME_APP_PIXMAP_NONE,          /* Sin pixmap */
        GNOME_APP_PIXMAP_STOCK,         /* Usa un pixmap de GNOME
                                           (GnomeStock) */
        GNOME_APP_PIXMAP_DATA,          /* Usa un pixmap xpm insertado en el 
                                           código (Un vector) */
        GNOME_APP_PIXMAP_FILENAME       /* Usa el pixmap contenido en el
                                           archivo especificado */
} GnomeUIPixmapType;

/* Esta es la estructura que define un elemento dentro de una barra de menús
 * o en una barra de herramientas. La idea es crear un vector de estas
 * estructuras con la información necesaria para crear los menús.
 * La forma más conveniente de trabajar con esta estructura es usar las macros
 * GNOMEUIINFO_* definidas más abajo.*/
typedef struct {
        GnomeUIInfoType type;     /* Tipo de elemento
        gchar *label;             /* Cadena usada en la etiqueta */
        gchar *hint;              /* Para los elementos pertenecientes a una 
                                     barra de herramientas se trata de la 
                                     sugerencia. Para los elementos de un menú,
                                     el mensaje de la barra de estado */
        gpointer moreinfo;        /* Para un elemento, un elemento conmutable,  
                                     o elemento de opción, esto es un puntero a 
                                     la función que será llamada cuando el 
                                     elemento sea activado. Para un subárbol,
                                     es un puntero a otro vector de estructuras
                                     GnomeUIInfo. Para un elemento de opción 
                                     principal, un puntero a un vector de
                                     estructuras GnomeUIInfo que representa el
                                     grupo de elementos de opción asociados. 
                                     Para un elemento de ayuda, especifica el 
                                     nodo que debe cargar (i.e. El 
                                     identificador de la aplicación), NULL
                                     indica el nombre del programa principal.
                                     Si se trata de los datos del constructor, 
                                     apunta a la estructura GnomeUIBuilderData
                                     para los elementos consecutivos [N.T: 
                                     haz que me entiendan, por favor :-)] */
        gpointer user_data;       /* Puntero a los datos que paseremos a las
                                     retrollamadas */
        gpointer unused_data;     /* Reservado para una futura extensión, 
                                     debería ser NULL por ahora */
        GnomeUIPixmapType pixmap_type;  /* Tipo de pixmap para
                                           el elemento */
        gpointer pixmap_info;     /* Puntero a la información del
                                     pixmap:
                                    
                                     Para GNOME_APP_PIXMAP_STOCK, un 
                                     puntero al nombre del icono.
                                    
                                     Para GNOME_APP_PIXMAP_DATA, un 
                                     puntero al xpm (Al vector).
                                    
                                     Para GNOME_APP_PIXMAP_FILENAME, un 
                                     puntero al nombre del archivo 
                                     (Una cadena) */
        guint accelerator_key;    /* Atajo del teclado, o 0 si no hay */
        GdkModifierType ac_mods;  /* Máscara de las teclas modificadas por 
                                     el atajo */

        GtkWidget *widget;        /* Rellenado por gnome_app_create*,
                                     podrá ajustarlo una vez haya sido 
                                     creado */
} GnomeUIInfo;

No se preocupe si le cuesta recordar todos los elementos o no comprende lo que significan. Si usted no sabe lo que representa un miembro de la estructura, sencillamente dejeló en NULL o 0. También puede recurrir a copiar el menú de otra aplicación que haga lo que usted desea y modificarlo un poco para ajustarlo a su propio desarrollo, esto es a menudo mejor y más rápido que perder el tiempo hurgando en la estructura.

Macros Útiles

La mayoría de las veces, crear entradas en un menú será muy simple gracias a ciertas macros. Por ejemplo, para finalizar un menú, usaríamos la macro GNOMEUIINFO_END o para insertar un separador GNOMEUIINFO_SEPARATOR. El resto de los elementos pueden ser también creados mediante macros, aunque deberemos proporcionar cierta información a las mismas. Por ejemplo, si desea crear un elemento con un xpm insertado en código, usted puede usar la macro GNOMEUIINFO_ITEM(etiqueta, sugerencia, retrollamada, xpm_data), donde etiqueta es el texto que aparecerá en el menú, sugerencia es la ayuda que recibirá el usuario cuando se coloque sobre el elemento (NULL indica ninguna sugerencia), retrollamada es la función que es invocada cuando el usuario presiona el elemento, y xpm_data es un puntero al vector xpm que usted desea usar como icono. Si no quiere que aparezca el icono, use GNOMEUIINFO_ITEM_NONE(etiqueta, sugerencia, retrollamada). Si lo que busca es añadir un elemento con un icono estándar de GNOME (De estos hablaremos más adelante) deberá usar GNOMEUIINFO_ITEM_STOCK(etiqueta, sugerencia, retrollamada, stock_id) donde stock_id es el identificador del icono que quiera usar. Luego, para crear su barra de menús principal o para insertar submenús dentro ella, puede usar GNOMEUIINFO_SUBTREE(etiqueta, arbol) y GNOMEUIINFO_SUBTREE_STOCK(etiqueta, arbol, stock_id), donde 'arbol' es el vector de estructuras GnomeUIInfo que usted quiere emplear como submenú. Existen otras pocas macros que también manejan esta estructura, pero por lo general las que se usan más a menudo son éstas. Como ha visto, no precisa comprender la compleja estructura GnomeUIInfo y sus miembros para crear efectivos menús.

Macros para crear Elementos y Menús Genéricos

Todas las aplicaciones contienen un par de menús genéricos, así que para mantener una cierta consistencia, se aportan una serie de macros que rellenaran estos menús todo por usted, sólo tendrá que escribir las retrollamas necesarias y adaptarlos a un poco a su aplicación. Las ventajas de usar macros son consistencia entre aplicaciones, posibilidad de configuración por parte del usuario e internacionalización de los programas.

Elementos de Menú

La mayoría de estas macros tienen la forma: GNOMEUIINFO_MENU_<nombre>_ITEM (retrollamada, datos). Hay una excepción, la macro que crea el elemento "Nuevo xxx" (N.T: nuevo archivo de un procesador de textos, p.ej). La guía de estilo de GNOME especifica que la palabra "Nuevo" debe estar dentro de la etiqueta del elemento. No se menciona ni el nombre completo del elemento ni su sugerencia particular, a diferencia del resto de los elementos genéricos. Para permitir que el programador pueda ajustar estos campos, se opta por utilizar una macro con una sintaxis particular para el elemento "Nuevo xxx": GNOMEUIINFO_MENU_NEW_ITEM(etiqueta, sugerencia, retrollamada, datos). La "etiqueta" debería comenzar con "Nuevo ". Téngase en cuenta que si usted tiene más elementos "Nuevo", necesita usar la macro que crea un subárbol para elementos de este tipo, este procedimiento será explicado más tarde.

Tabla 4. El Menú Archivo

MacroDescripción
GNOMEUIINFO_MENU_NEW_ITEM(etiqueta, suger, cb, datos)Elemento "Nuevo" (Necesita una etiqueta y una sugerencia)
GNOMEUIINFO_MENU_OPEN_ITEM(cb, datos)Elemento "Abrir"
GNOMEUIINFO_MENU_SAVE_ITEM(cb, datos)Elemento "Guardar"
GNOMEUIINFO_MENU_SAVE_AS_ITEM(cb, datos)Elemento "Guardar como"
GNOMEUIINFO_MENU_REVERT_ITEM(cb, datos)Elemento "Revertir"
GNOMEUIINFO_MENU_PRINT_ITEM(cb, datos)Elemento "Imprimir"
GNOMEUIINFO_MENU_PRINT_SETUP_ITEM(cb, datos)Elemento "Ajustes para impresión"
GNOMEUIINFO_MENU_CLOSE_ITEM(cb, datos)Elemento "Cerrar"
GNOMEUIINFO_MENU_EXIT_ITEM(cb, datos)Elemento "Salir"

Tabla 5. El Menú Editar

MacroDescripción
GNOMEUIINFO_MENU_CUT_ITEM(cb, datos)Elemento "Cortar"
GNOMEUIINFO_MENU_COPY_ITEM(cb, datos)Elemento "Copiar"
GNOMEUIINFO_MENU_PASTE_ITEM(cb, datos)Elemento "Pegar"
GNOMEUIINFO_MENU_SELECT_ALL_ITEM(cb, datos)Elemento "Marcar Todo"
GNOMEUIINFO_MENU_CLEAR_ITEM(cb, datos)Elemento "Limpiar"
GNOMEUIINFO_MENU_UNDO_ITEM(cb, datos)Elemento "Deshacer"
GNOMEUIINFO_MENU_REDO_ITEM(cb, datos)Elemento "Rehacer"
GNOMEUIINFO_MENU_FIND_ITEM(cb, datos)Elemento "Buscar"
GNOMEUIINFO_MENU_FIND_AGAIN_ITEM(cb, datos)Elemento "Buscar Otra vez"
GNOMEUIINFO_MENU_REPLACE_ITEM(cb, datos)Elemento "Reemplazar"
GNOMEUIINFO_MENU_PROPERTIES_ITEM(cb, datos)Elemento "Propiedades", las propiedades del objeto manipulado

Tabla 6. El Menú Opciones

MacroDescripción
GNOMEUIINFO_MENU_PREFERENCES_ITEM(cb, datos)Elemento "Preferencias", ajustar preferencias de la aplicación

Tabla 7. El Menú Ventana

MacroDescripción
GNOMEUIINFO_MENU_NEW_WINDOW_ITEM(cb, datos)Elemento "Nueva ventana"
GNOMEUIINFO_MENU_CLOSE_WINDOW_ITEM(cb, datos)Elemento "Cerrar ventana"

Tabla 8. El Menú Ayuda

MacroDescripción
GNOMEUIINFO_MENU_ABOUT_ITEM(cb, datos)Elemento "Acerca de"

Tabla 9. El Menú Juego

MacroDescripción
GNOMEUIINFO_MENU_NEW_GAME_ITEM(cb, datos)Elemento "Nuevo juego"
GNOMEUIINFO_MENU_PAUSE_GAME_ITEM(cb, datos)Elemento "Pausa"
GNOMEUIINFO_MENU_RESTART_GAME_ITEM(cb, datos)Elemento "Reiniciar"
GNOMEUIINFO_MENU_UNDO_MOVE_ITEM(cb, datos)Elemento "Anular"
GNOMEUIINFO_MENU_REDO_MOVE_ITEM(cb, datos)Elemento "Rehacer"
GNOMEUIINFO_MENU_HINT_ITEM(cb, datos)Elemento "Sugerencia"
GNOMEUIINFO_MENU_SCORES_ITEM(cb, datos)Elemento "Puntuación"
GNOMEUIINFO_MENU_END_GAME_ITEM(cb, datos)Elemento "Terminar juego"

Menús, árboles y subárboles

Ya hemos mencionado anteriormente el subárbol "Nuevo". Para usarlo, debería utilizar la macro GNOMEUIINFO_MENU_NEW_SUBTREE (arbol), donde arbol es otro vector de estructuras GnomeUIInfo con diferentes elementos "Nuevo".

Existen también menús de "primer nivel" (N.T: toplevel) genéricos, entendiéndose como menús de "primer nivel" aquellos que se encuentran directamente sobe la barra de menús. El mecanismo para trabajar con ellos es el mismo: debe pasar el vector de estructuras GnomeUIInfo a la macro correspondiente.

Tabla 10. Macros para crear Menús de Primer Nivel.

MacroDescripción
GNOMEUIINFO_MENU_FILE_TREE(arbol)Menú "Archivo"
GNOMEUIINFO_MENU_EDIT_TREE(arbol)Menú "Editar"
GNOMEUIINFO_MENU_VIEW_TREE(arbol)Menú "Presentación"
GNOMEUIINFO_MENU_SETTINGS_TREE(arbol)Menú "Opciones"
GNOMEUIINFO_MENU_FILES_TREE(arbol)Menú "Archivos"
GNOMEUIINFO_MENU_WINDOWS_TREE(arbol)Menú "Ventanas"
GNOMEUIINFO_MENU_HELP_TREE(arbol)Menú "Ayuda"
GNOMEUIINFO_MENU_GAME_TREE(arbol)Menú "Juego"

A veces, usted deseará trabajar con la ruta (N.T: path) de un elemento de cierto menú, por ejemplo para añadir elementos al menú "Documentos". Para esto, necesitará las macros de la forma GNOME_MENU_<nombre>_STRING y GNOME_MENU_<nombre>_PATH. Dichas macros se expandirán a la cadena apropiada. La macro que termina en _STRING se expandirá al nombre del menú, y la macro que finaliza en _PATH al nombre del menú seguido de un "/". <nombre> puede ser uno de los siguientes identificadores: FILE, EDIT, VIEW, SETTINGS, NEW, FILES o WINDOWS.

Menú de Ayuda

Su aplicación debería contener un menú de ayuda, que podría ser definido de esta manera:

     GNOMEUIINFO_HELP("mi_aplicación"),
     GNOMEUIINFO_MENU_ABOUT_ITEM(retrollamada, datos),
     GNOMEUIINFO_END

La macro GNOMEUIINFO_HELP toma el nombre de su aplicación e inspecciona los archivos de ayuda de GNOME buscando el apropiado. FIXME[ORIGINAL]: necesitamos añadir alguna sección acerca de los archivos de ayuda y algunos ejemplos.

Ejemplo

Una aplicación muy sencilla que hace uso de todo lo estudiado hasta ahora:

/*
 * Un sencillo no integrado en el árbol GNOME, sin usar i18n
 * uiinfo.c
 */
/* La cabecera GNOME más básica */
#include <gnome.h>

/* Una retrollamada para los botones */
static void
a_callback(GtkWidget *button, gpointer data)
{
        /* Imprime una cadena cada vez que es llamada */
        g_print("Dentro de la Retrollamada\n");
}

GnomeUIInfo file_menu[] = {
        GNOMEUIINFO_MENU_EXIT_ITEM(gtk_main_quit,NULL),
        GNOMEUIINFO_END
};

GnomeUIInfo some_menu[] = {
        GNOMEUIINFO_ITEM_NONE("_Menuitem","Un elemento de menú",
                              a_callback),
        GNOMEUIINFO_SEPARATOR,
        GNOMEUIINFO_ITEM_NONE("M_enuitem2","Otro elemento de menú",
                              a_callback),
        GNOMEUIINFO_END
};

GnomeUIInfo menubar[] = {
        GNOMEUIINFO_MENU_FILE_TREE(file_menu),
        GNOMEUIINFO_SUBTREE("_Un menú",some_menu),
        GNOMEUIINFO_END
};

GnomeUIInfo toolbar[] = {
        GNOMEUIINFO_ITEM_STOCK("Salir","Salir del programa",
                               gtk_main_quit,
                               GNOME_STOCK_PIXMAP_EXIT),
        GNOMEUIINFO_END
};

int
main(int argc, char *argv[])
{
        GtkWidget *app;
        GtkWidget *button;
        GtkWidget *hbox;
        GtkWidget *label;

        /* Inicializa GNOME, muy similar a gtk_init */
        gnome_init ("menu-basic-example", "0.1", argc, argv);
        
        /* Crea un widget GnomeApp, el cual crea una ventana
           para su aplicación */
        app = gnome_app_new ("menu-basic-example",
                             "Aplicación básica GNOME");

        /* Engancha "delete_event", el evento que es emitido
           cuando el usuario cierra la ventana, a gtk_main_quit,
           que es la función que fuerza a salir del bucle
           gtk_main y finaliza la aplicación */
        gtk_signal_connect (GTK_OBJECT (app), "delete_event",
                            GTK_SIGNAL_FUNC (gtk_main_quit),
                            NULL);

        /* Crea una etiqueta como contenido */
        label = gtk_label_new("BLAH BLAH BLAH BLAH BLAH");

        /* Añade la etiqueta a la ventana */
        gnome_app_set_contents (GNOME_APP (app), label);

        /* Crea los menús para la aplicación */
        gnome_app_create_menus (GNOME_APP (app), menubar);

        /* Crea la barra de herramientas de la aplicación */
        gnome_app_create_toolbar (GNOME_APP (app), toolbar);

        /* Muestra todos los contenidos de app y a él mismo */
        gtk_widget_show_all(app);
        
        /* Entra en el bucle principal */
        gtk_main ();
        
        return 0;
}

¡Voila!, una aplicación con un menú y una barra de herramientas. Como puede ver, añadir nuevos elementos en los menús se reduce a añadir más definiciones al vector de estructuras GnomeUIInfo correspondiente.

Atajos del Teclado

Probablemente haya notado los guiones bajos en las etiquetas de los elementos del menú, estos especifican los atajos del teclado asociados a ese menú concreto. La forma en la que funcionan los atajos es muy similar a como lo hacen en otros entornos gráficos del mercado: podrá seleccionar un elemento determinado con sólo <tecla> si se encuentra dentro del menú o alt-<tecla> en caso contrario.

GnomeAppBar, la Barra de Estado

Toda aplicación debería incluir una barra de estado en la parte baja de la ventana principal. Esta barra debería mostrar mensajes y advertencias acerca del funcionamiento actual de la aplicación. Usted podrá manejarla a su antojo usando las funciones de mensajes de GnomeApp (descritas en la sección Dialogando con el Usuario). La barra de estado también puede aportar ayuda acerca de los elementos del menú o una barra de progreso. Estas son las funciones más importantes que trabajan con GnomeAppBar.

Tabla 11. Métodos Importantes de GnomeAppBar

PrototipoDescripción
GtkWidget * gnome_appbar_new (gboolean hay_progreso, gboolean hay_estado, GnomePreferencesType interactividad)Crea un nuevo widget GnomeAppBar. opcionalmente con una barra de progreso si 'hay_progreso' es TRUE, y una barra de estado si 'hay_estado' es TRUE. La 'interactividad' nos dice si la barra ha de ser interactiva, lo cual puede ser nunca, siempre o depender de las preferencias del usuario, GNOME_PREFERENCES_USER, que es posiblemente la mejor opción. Piense que la implementación de la barra de estado interactiva aún no esta finalizada
void gnome_appbar_set_status (GnomeAppBar * appbar, const gchar * estado)Fija el texto de la barra de estado, sin alterar appbar
void gnome_appbar_set_default (GnomeAppBar * appbar, const gchar * texto_por_defecto)Fija el texto por defecto de la barra de estado, el texto aparecerá cuando no haya necesidad de mostrar nada
void gnome_appbar_push (GnomeAppBar * appbar, const gchar * estado)Apila un mensaje
void gnome_appbar_pop (GnomeAppBar * appbar)Saca un mensaje de la pila de mensajes de estado
void gnome_appbar_clear_stack (GnomeAppBar * appbar)Vacia la pila de mensajes de estado
void gnome_appbar_refresh (GnomeAppBar * appbar)Refresca la barra de estado y fija el actual valor de la pila al valor por defecto. Útil para limpiar mensajes provenientes del método gnome_appbar_set_status
void gnome_appbar_set_progress (GnomeAppBar * appbar, gfloat porcentaje)Ajusta el porcentaje de la barra de progreso
GtkProgress * gnome_appbar_get_progress (GnomeAppBar * appbar)Obtiene el widget GtkProgress, que es la barra de progreso, para poder manipularlo directamente

Par añadir una barra de aplicación a una ventana GnomeApp, use el método gnome_app_set_statusbar. Para poder visualizar las sugerencias del menú en la barra, debe llamar a gnome_app_install_menu_hints con un puntero a su definición GnomeUIInfo de la barra de menús principal. Por ejemplo, podríamos añadir dicha funcionalidad con el siguiente código:

GtkWidget *w;

w = gnome_appbar_new(FALSE, TRUE, GNOME_PREFERENCES_USER);
gnome_app_set_statusbar(GNOME_APP(app), w);

gnome_app_install_menu_hints(GNOME_APP(app), menubar);

Suponiendo que 'app' es su ventana de aplicación GnomeApp y 'menubar' es un puntero GnomeUIInfo a su definición de la barra de menús principal de la aplicación.

La forma en la que trabaja la barra de estado es amontonando los mensajes en una pila: el mensaje más reciente es el que se muestra en pantalla. Esto es útil ya que en muchas ocasiones le interesará mantener un mensaje concreto en la barra la mayor parte del tiempo e ir mostrando pequeños mensajes de vez en cuando. El nuevo mensaje será apilado sobre el principal y una vez mostrado cederá paso al mensaje original, que volverá así a estar en la cima de la pila y a aparecer en la barra.

Debe tener en cuenta que la barra de estado puede hacerse cargo de muchos detalles automáticamente, sin precisar nuestra supervisión directa. Por ejemplo, de mostrar mensajes informativos en la barra se ocupa gnome_app_flash descrito más tarde en la sección Dialogando con el Usuario.

Dialogando con el Usuario

En ocasiones, usted deseará comunicarse con el usuario, puede que necesite mostrar un error o un mensaje indicando el estado de su operación. Existen opciones accesibles al usuario que marcan dónde y cómo se recibe esta información. Si quiere que su código se comporte de forma consistente con esta característica, deberá usar las siguientes funciones cuando precise crear un nuevo cuadro de diálogo.

Tabla 12. Funciones de Mensajes de GnomeApp

PrototipoDescripción
GtkWidget * gnome_app_message (GnomeApp * app, const gchar * mensaje)Muestra un mensaje y solicita confirmación al usuario. Si se trata de un diálogo, devolverá un puntero a dicho diálogo que puede ser obviado sin problemas a menos que desee hacer algo con él posteriormente.
void gnome_app_flash (GnomeApp * app, const gchar * flash)Muestra un mensaje en la barra de estado durante un par de segundos. Evidentemente, su uso debería restringirse a mensajes no críticos o no necesarios para el correcto uso de la aplicación.
GtkWidget * gnome_app_error (GnomeApp * app, const gchar * error)Similar a gnome_app_message, pero muestra un error al usuario en vez de un mensaje.
GtkWidget * gnome_app_warning (GnomeApp * app, const gchar * warning)También similar a gnome_app_message, esta vez aparece una advertencia.

El siguiente ejemplo muestra como usar estas funciones.

        FILE *fp;

        fp = fopen(archivo,"r");
        if(!fp) {
                char *err = g_strdup_printf(_("No pude abrir: %s"),
                                            archivo);
                gnome_app_error(GNOME_APP(app),err);
                g_free(err);
                ...
        }

Puede que lo que necesite su aplicación es solicitar datos del usuario. Las siguientes funciones cubren este supuesto y reciben como argumento un puntero a una función, del tipo GnomeReplyCallback o GnomeStringCallback. La función (el contenido del puntero) deber tener como parámetros un entero o una cadena de caracteres y un puntero de datos. No cuente con que la retrollamada sea invocada siempre, pudiera ser que la línea de estado estuviese ocupada en cuyo caso se obviará la retrollamada y se devolverá NULL. Si la función se ejecuta devolverá el widget de diálogo. Otro aspecto destacable es que se trata de funciones no bloqueantes, lo que quiere decir que no se debe actuar una vez se han llamado como si ya hubieran acabado su ejecución.

Tabla 13. Funciones de Petición de Datos de GnomeApp

PrototipoDescripción
GtkWidget * gnome_app_question (GnomeApp * app, const gchar * pregunta, GnomeReplyCallback retrollamada, gpointer datos)Una pregunta cuya contestación es sí o no. La retrollamada de respuesta recibe 0 ó 1 respectivamente.
GtkWidget * gnome_app_question_modal (GnomeApp * app, const gchar * pregunta, GnomeReplyCallback retrollamada, gpointer datos)Similar a la anterior, aunque permite al usuario interactuar con el resto de la aplicación a pesar de que no haya respondido o no haya cerrado el diálogo.
GtkWidget * gnome_app_ok_cancel (GnomeApp * app, const gchar * mensaje, GnomeReplyCallback retrollamada, gpointer datos)Una pregunta del tipo Sí o Cancelar.
GtkWidget * gnome_app_ok_cancel_modal (GnomeApp * app, const gchar * mensaje, GnomeReplyCallback retrollamada, gpointer datos)La versión modal de la función gnome_app_ok_cancel.
GtkWidget * gnome_app_request_string (GnomeApp * app, const gchar * inductor, GnomeStringCallback retrollamada, gpointer datos)Pregunta al usuario con un inductor de órdenes (N.T: prompt) igual a 'inductor'. La retrollamada recibirá NULL si el usuario cancela el diálogo. La memoria que ocupa la cadena que recibe la retrollamada deberá ser liberada por el programador.
GtkWidget * gnome_app_request_password (GnomeApp * app, const gchar * inductor, GnomeStringCallback retrollamada, gpointer datos)Pide al usuario una contraseña, mostrando 'inductor'. Idéntica a gnome_app_request_string, con la salvedad de que el texto no se muestra en pantalla.

Por ejemplo, solicitaremos al usuario confirmación para eliminar un objeto.

static void
really_delete_handler(int respuesta, gpointer datos)
{
        GtkWidget *un_widget;

        un_widget = GTK_WIDGET(datos);

        if(respuesta == 0) {
                ... /* "Sí" ha sido seleccionado */
        }
}

...

/* Mostrar una pregunta del tipo Sí/No, pasaremos some_widget como el
   argumento 'datos' al manejador really_delete_handler */
gnome_app_question(GNOME_APP(app),_("¿Desea borrar el objeto?"),
                   really_delete_handler,
                   un_widget);