/* gcompris - file_selector.c
*
* Copyright (C) 2000 Bruno Coudoin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
/**
* A file selector for gcompris
*
*/
#include
#include
#include
/* libxml includes */
#include
#include
#include "gcompris.h"
#include "gc_core.h"
#define SOUNDLISTFILE PACKAGE
#define MODE_LOAD 1
#define MODE_SAVE 2
static gint mode;
static gint item_event_file_selector(GnomeCanvasItem *item,
GdkEvent *event,
gpointer data);
static gint item_event_scroll(GnomeCanvasItem *item,
GdkEvent *event,
GnomeCanvas *canvas);
static gint item_event_directory(GnomeCanvasItem *item,
GdkEvent *event,
char *dir);
static void display_files(GnomeCanvasItem *rootitem, gchar *rootdir);
static int display_file_selector(int mode,
GcomprisBoard *gcomprisBoard,
gchar *rootdir,
gchar *file_types,
FileSelectorCallBack iscb);
static void entry_enter_callback( GtkWidget *widget,
GtkWidget *entry );
static void free_stuff (GtkObject *obj, gchar* data);
static gboolean file_selector_displayed = FALSE;
static GnomeCanvasItem *rootitem = NULL;
static GnomeCanvasItem *file_root_item = NULL;
static FileSelectorCallBack fileSelectorCallBack = NULL;
static GtkWidget *gtk_combo_filetypes = NULL;
static gchar *current_rootdir = NULL;
static GtkEntry *widget_entry = NULL;
static GList *file_list = NULL;
/* Represent the limits of control area */
static guint32 control_area_x1;
static guint32 control_area_y1;
static guint32 directory_label_y;
/* Represent the limits of the file area */
#define DRAWING_AREA_X1 40.0
#define DRAWING_AREA_Y1 220.0
#define DRAWING_AREA_X2 760.0
#define DRAWING_AREA_Y2 500.0
#define HORIZONTAL_NUMBER_OF_IMAGE 5
#define VERTICAL_NUMBER_OF_IMAGE 3
#define IMAGE_GAP 18
#define IMAGE_WIDTH (DRAWING_AREA_X2-DRAWING_AREA_X1)/HORIZONTAL_NUMBER_OF_IMAGE-IMAGE_GAP
#define IMAGE_HEIGHT (DRAWING_AREA_Y2-DRAWING_AREA_Y1)/VERTICAL_NUMBER_OF_IMAGE-IMAGE_GAP
/*
* Mime type management
* --------------------
*/
typedef struct {
gchar *mimetype;
gchar *description;
gchar *extension;
gchar *icon;
} GcomprisMimeType;
static GHashTable* mimetypes_hash = NULL;
static GHashTable* mimetypes_ext_hash = NULL; /* Mime type with the key being the extension */
static GHashTable* mimetypes_desc_hash = NULL; /* Mime type with the key being the description */
/*
* Main entry point
* ----------------
*
*/
/*
* Do all the file_selector display and register the events
* file_types is A Comma separated text explaining the different file types
*/
void gc_selector_file_save (GcomprisBoard *gcomprisBoard, gchar *rootdir,
gchar *file_types,
FileSelectorCallBack iscb)
{
display_file_selector(MODE_SAVE, gcomprisBoard, rootdir, file_types,
iscb);
}
void gc_selector_file_load (GcomprisBoard *gcomprisBoard, gchar *rootdir,
gchar *file_types,
FileSelectorCallBack iscb)
{
display_file_selector(MODE_LOAD, gcomprisBoard, rootdir, file_types,
iscb);
}
/*
* Remove the displayed file_selector.
* Do nothing if none is currently being dislayed
*/
void gc_selector_file_stop ()
{
GcomprisBoard *gcomprisBoard = gc_board_get_current();
if(gcomprisBoard!=NULL && file_selector_displayed)
gc_board_pause(FALSE);
// Destroy the file_selector box
/* FIXME: Crashes randomly */
if(rootitem!=NULL)
gtk_object_destroy(GTK_OBJECT(rootitem));
rootitem = NULL;
/* No need to destroy it since it's in rootitem but just clear it */
file_root_item = NULL;
/* Cleanup the file list */
if(file_list) {
// g_list_foreach(file_list, (GFunc)g_free, NULL);
g_list_free(file_list);
}
file_list = NULL;
gc_bar_hide(FALSE);
file_selector_displayed = FALSE;
}
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
static int
display_file_selector(int the_mode,
GcomprisBoard *gcomprisBoard,
gchar *rootdir,
gchar *file_types,
FileSelectorCallBack iscb) {
GnomeCanvasItem *item, *item2;
GdkPixbuf *pixmap = NULL;
gint y = 0;
gint y_start = 0;
gint x_start = 0;
gchar *name = NULL;
gchar *full_rootdir;
gchar *sub_string;
gchar *file_types_string = NULL;
mode = the_mode;
/* Get the coordinate x y of the control area from the skin */
control_area_x1 = gc_skin_get_number_default("gcompris/fileselectx", 85);
control_area_y1 = gc_skin_get_number_default("gcompris/fileselecty", 80);
directory_label_y = gc_skin_get_number_default("gcompris/fileselectdiry", 180);
if(file_types) {
file_types_string = g_strdup(file_types);
}
if(rootitem)
return 0;
gc_bar_hide(TRUE);
gc_board_pause(TRUE);
name = gcomprisBoard->name;
fileSelectorCallBack=iscb;
rootitem = \
gnome_canvas_item_new (gnome_canvas_root(gc_get_canvas()),
gnome_canvas_group_get_type (),
"x", (double)0,
"y", (double)0,
NULL);
pixmap = gc_skin_pixmap_load("file_selector_bg.png");
y_start = (BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2;
x_start = (BOARDWIDTH - gdk_pixbuf_get_width(pixmap))/2;
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) x_start,
"y", (double) y_start,
NULL);
y = BOARDHEIGHT - (BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2 + 20;
gdk_pixbuf_unref(pixmap);
/* Entry area */
widget_entry = (GtkEntry *)gtk_entry_new ();
if(mode==MODE_SAVE)
gtk_entry_set_max_length(widget_entry, 30);
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_widget_get_type (),
"widget", GTK_WIDGET(widget_entry),
"x", (double) control_area_x1,
"y", (double) control_area_y1,
"width", 230.0,
"height", 30.0,
"anchor", GTK_ANCHOR_NW,
"size_pixels", FALSE,
NULL);
gtk_signal_connect(GTK_OBJECT(widget_entry), "activate",
GTK_SIGNAL_FUNC(entry_enter_callback),
widget_entry);
gtk_widget_show(GTK_WIDGET(widget_entry));
/*
* Create the combo with the file types
* ------------------------------------
*/
if(mode==MODE_SAVE && file_types_string && *file_types_string!='\0') {
GcomprisMimeType *mimeType = NULL;
char *str;
gchar *result;
gtk_combo_filetypes = gtk_combo_box_new_text();
/* Extract first string */
str = (char *)strtok(file_types_string, " ");
/* Extract the mime type */
mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_hash, str));
if(mimeType) {
result = strdup(gettext(mimeType->description));
} else {
result = strdup(str);
}
gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_filetypes), result);
g_free(result);
while ( (sub_string=(char *)strtok(NULL, " ")) != NULL)
{
/* Extract the mime type */
mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_hash, sub_string));
if(mimeType) {
result = strdup(gettext(mimeType->description));
} else {
result = strdup(str);
}
gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_filetypes), result);
g_free(result);
}
gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_widget_get_type (),
"widget", GTK_WIDGET(gtk_combo_filetypes),
"x", (double) control_area_x1 + 400,
"y", (double) control_area_y1,
"width", 250.0,
"height", 35.0,
"anchor", GTK_ANCHOR_NW,
"size_pixels", FALSE,
NULL);
gtk_widget_show(GTK_WIDGET(gtk_combo_filetypes));
gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_filetypes), 0);
g_free(file_types_string);
}
y_start += 110;
/*
* Buttons
* -------
*/
pixmap = gc_skin_pixmap_load("button_large.png");
// CANCEL
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (BOARDWIDTH*0.33) - gdk_pixbuf_get_width(pixmap)/2,
"y", (double) y - gdk_pixbuf_get_height(pixmap) - 25,
NULL);
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_file_selector,
"/cancel/");
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
item2 = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_text_get_type (),
"text", _("CANCEL"),
"font", gc_skin_font_title,
"x", (double) BOARDWIDTH*0.33,
"y", (double) y - gdk_pixbuf_get_height(pixmap),
"anchor", GTK_ANCHOR_CENTER,
"fill_color_rgba", gc_skin_color_text_button,
NULL);
gtk_signal_connect(GTK_OBJECT(item2), "event",
(GtkSignalFunc) item_event_file_selector,
"/cancel/");
gtk_signal_connect(GTK_OBJECT(item2), "event",
(GtkSignalFunc) gc_item_focus_event,
item);
// OK
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (BOARDWIDTH*0.66) - gdk_pixbuf_get_width(pixmap)/2,
"y", (double) y - gdk_pixbuf_get_height(pixmap) - 25,
NULL);
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_file_selector,
"/ok/");
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
item2 = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_text_get_type (),
"text", (mode==MODE_LOAD ? _("LOAD") : _("SAVE")),
"font", gc_skin_font_title,
"x", (double) BOARDWIDTH*0.66,
"y", (double) y - gdk_pixbuf_get_height(pixmap),
"anchor", GTK_ANCHOR_CENTER,
"fill_color_rgba", gc_skin_color_text_button,
NULL);
gtk_signal_connect(GTK_OBJECT(item2), "event",
(GtkSignalFunc) item_event_file_selector,
"/ok/");
gtk_signal_connect(GTK_OBJECT(item2), "event",
(GtkSignalFunc) gc_item_focus_event,
item);
gdk_pixbuf_unref(pixmap);
file_selector_displayed = TRUE;
full_rootdir = g_strconcat(gc_prop_get()->user_dir, "/", rootdir, NULL);
gc_util_create_rootdir(full_rootdir);
current_rootdir = full_rootdir;
display_files(rootitem, full_rootdir);
return 0;
}
static void
free_stuff (GtkObject *obj, gchar *data)
{
g_free(data);
}
static void display_files(GnomeCanvasItem *root_item, gchar *rootdir)
{
GnomeCanvasItem *item;
double iw, ih;
const gchar *one_dirent;
GDir *dir;
/* Initial image position */
guint ix = 0.0;
guint iy = 0.0;
GtkWidget *w;
GnomeCanvasItem *bg_item;
GnomeCanvas *canvas; /* The scrolled part */
GList *dir_list = NULL;
GList *listrunner;
if(!rootitem)
return;
/* Display the directory content */
dir = g_dir_open(rootdir, 0, NULL);
if (!dir) {
g_warning("gcompris_file_selector : no root directory found in %s", rootdir);
g_free(rootdir);
return;
}
/* Delete the previous file root if any */
if(file_root_item!=NULL) {
gtk_object_destroy(GTK_OBJECT(file_root_item));
}
/* Cleanup the file list */
if(file_list) {
//g_list_foreach(file_list, (GFunc)g_free, NULL);
g_list_free(file_list);
}
file_list = NULL;
/* Create a root item to put the image list in it */
file_root_item = \
gnome_canvas_item_new (GNOME_CANVAS_GROUP(root_item),
gnome_canvas_group_get_type (),
"x", (double)0,
"y", (double)0,
NULL);
/*
* Create the scrollbar
* --------------------
*/
canvas = GNOME_CANVAS(gnome_canvas_new ());
gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
gnome_canvas_widget_get_type (),
"widget", GTK_WIDGET(canvas),
"x", (double) DRAWING_AREA_X1,
"y", (double) DRAWING_AREA_Y1,
"width", DRAWING_AREA_X2- DRAWING_AREA_X1 - 20.0,
"height", DRAWING_AREA_Y2-DRAWING_AREA_Y1 - 35.0,
NULL);
gtk_widget_show (GTK_WIDGET(canvas));
/* Set the new canvas to the background color or it's white */
bg_item = gnome_canvas_item_new (gnome_canvas_root(canvas),
gnome_canvas_rect_get_type (),
"x1", (double) 0,
"y1", (double) 0,
"x2", (double) DRAWING_AREA_X2- DRAWING_AREA_X1,
"y2", (double) DRAWING_AREA_Y2-DRAWING_AREA_Y1,
"fill_color_rgba", gc_skin_get_color("gcompris/fileselectbg"),
NULL);
w = gtk_vscrollbar_new (GTK_LAYOUT(canvas)->vadjustment);
gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
gnome_canvas_widget_get_type (),
"widget", GTK_WIDGET(w),
"x", (double) DRAWING_AREA_X2 - 15.0,
"y", (double) DRAWING_AREA_Y1,
"width", 30.0,
"height", DRAWING_AREA_Y2-DRAWING_AREA_Y1 - 20.0,
NULL);
gtk_widget_show (w);
gnome_canvas_set_center_scroll_region (GNOME_CANVAS (canvas), FALSE);
/* Set the scrollwheel event */
gtk_signal_connect(GTK_OBJECT(canvas), "event",
(GtkSignalFunc) item_event_scroll,
GNOME_CANVAS(canvas));
/* Display the directory name
* --------------------------
*/
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
gnome_canvas_text_get_type (),
"text", rootdir,
"x", (double)control_area_x1,
"y", (double)directory_label_y,
"fill_color_rgba", gc_skin_get_color("gcompris/fileselectcol"),
"anchor", GTK_ANCHOR_NW,
NULL);
iw = IMAGE_WIDTH;
ih = IMAGE_HEIGHT;
/* Insert all files in a sorted list */
while((one_dirent = g_dir_read_name(dir)) != NULL) {
gchar *filename;
filename = g_strdup_printf("%s/%s",
rootdir, (gchar*)(one_dirent));
if(g_file_test(filename, G_FILE_TEST_IS_DIR)) {
dir_list = g_list_insert_sorted(dir_list, filename,
(GCompareFunc)strcmp);
} else {
file_list = g_list_insert_sorted(file_list, filename,
(GCompareFunc)strcmp);
}
}
/* Concat the directory list and file list */
file_list = g_list_concat(dir_list, file_list);
/* We have the list sorted, now display it */
listrunner = g_list_first(file_list);
while(listrunner) {
/* add the file to the display */
GdkPixbuf *pixmap_current;
gchar *allfilename = listrunner->data;
gchar *filename = g_path_get_basename(allfilename);
gchar *ext = strrchr(filename, '.');
if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
pixmap_current = gc_pixmap_load(gc_skin_image_get("directory.png"));
} else if(ext) {
/* Need to find an icon for this extension */
GcomprisMimeType *mimeType = NULL;
/* Extract the mime type for this extension */
mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_ext_hash, ext));
if(mimeType) {
if(mimeType->icon) {
pixmap_current = gc_pixmap_load(mimeType->icon);
if(pixmap_current==NULL) {
g_warning("Cannot find icon %s for mimetype %s", mimeType->icon, mimeType->description);
pixmap_current = gc_pixmap_load(gc_skin_image_get("file.png"));
} else {
/* We can remove the extension now that we have an icon */
*ext='\0';
}
} else {
pixmap_current = gc_pixmap_load(gc_skin_image_get("file.png"));
}
} else {
pixmap_current = gc_pixmap_load(gc_skin_image_get("file.png"));
}
} else {
pixmap_current = gc_pixmap_load(gc_skin_image_get("file.png"));
}
item = gnome_canvas_item_new (gnome_canvas_root(canvas),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap_current,
"x", (double)ix + (IMAGE_WIDTH + IMAGE_GAP
- gdk_pixbuf_get_width(pixmap_current))/2,
"y", (double)iy,
NULL);
gdk_pixbuf_unref(pixmap_current);
if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_directory,
allfilename);
} else {
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_file_selector,
allfilename);
}
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
g_signal_connect (item, "destroy",
G_CALLBACK (free_stuff),
allfilename);
item = gnome_canvas_item_new (gnome_canvas_root(canvas),
gnome_canvas_text_get_type (),
"text", filename,
"x", (double)ix + (IMAGE_WIDTH + IMAGE_GAP)/2,
"y", (double)iy + IMAGE_HEIGHT - 5,
"anchor", GTK_ANCHOR_CENTER,
"fill_color_rgba", gc_skin_get_color("gcompris/fileselectcol"),
NULL);
if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_directory,
allfilename);
} else {
gtk_signal_connect(GTK_OBJECT(item), "event",
(GtkSignalFunc) item_event_file_selector,
allfilename);
}
ix+=IMAGE_WIDTH + IMAGE_GAP;
if(ix>=DRAWING_AREA_X2 - DRAWING_AREA_X1 -IMAGE_GAP)
{
ix=0;
iy+=IMAGE_HEIGHT + IMAGE_GAP;
gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0,
DRAWING_AREA_X2- DRAWING_AREA_X1,
iy + IMAGE_HEIGHT + IMAGE_GAP);
if(iy>=DRAWING_AREA_Y2-DRAWING_AREA_Y1) {
gnome_canvas_item_set(bg_item,
"y2", (double)iy + IMAGE_HEIGHT + IMAGE_GAP,
NULL);
}
}
listrunner = g_list_next(listrunner);
}
g_dir_close(dir);
}
/* Callback when a directory is selected */
static gint
item_event_directory(GnomeCanvasItem *item, GdkEvent *event, gchar *dir)
{
if(!rootitem)
return FALSE;
switch (event->type)
{
case GDK_ENTER_NOTIFY:
break;
case GDK_LEAVE_NOTIFY:
break;
case GDK_BUTTON_PRESS:
if(strcmp(g_path_get_basename(dir), "..")==0) {
/* Up one level. Remove .. and one directory on the right of the path */
dir[strlen(dir)-3] = '\0';
dir=g_path_get_dirname(dir);
}
display_files(rootitem, g_strdup(dir));
gtk_entry_set_text(widget_entry, "");
break;
default:
break;
}
return FALSE;
}
/* Callback when a scroll event happens */
static gint
item_event_scroll(GnomeCanvasItem *item, GdkEvent *event, GnomeCanvas *canvas)
{
int x, y;
if(!rootitem)
return FALSE;
switch (event->type)
{
case GDK_SCROLL:
gnome_canvas_get_scroll_offsets (canvas, &x, &y);
if ( event->scroll.direction == GDK_SCROLL_UP )
gnome_canvas_scroll_to (canvas, x, y - 20);
else if ( event->scroll.direction == GDK_SCROLL_DOWN )
gnome_canvas_scroll_to (canvas, x, y + 20);
break;
default:
break;
}
return FALSE;
}
/* Callback when a file is selected */
static gint
item_event_file_selector(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
{
if(!rootitem)
return FALSE;
switch (event->type)
{
case GDK_ENTER_NOTIFY:
break;
case GDK_LEAVE_NOTIFY:
break;
case GDK_BUTTON_PRESS:
if(!strcmp((char *)data, "/ok/")) {
/* Nothing selected, please cancel instead */
if(strcmp(gtk_entry_get_text(widget_entry),"")==0) {
return FALSE;
}
if(fileSelectorCallBack!=NULL) {
gchar *result=NULL;
gchar *file_type=NULL;
result = g_strdup_printf("%s/%s", current_rootdir, gtk_entry_get_text(widget_entry));
if(mode==MODE_SAVE) {
GcomprisMimeType *mimeType = NULL;
GtkTreeModel *model;
GtkTreeIter iter;
model = gtk_combo_box_get_model ((GtkComboBox *)gtk_combo_filetypes);
if (gtk_combo_box_get_active_iter ((GtkComboBox *)gtk_combo_filetypes, &iter)) {
gtk_tree_model_get (model, &iter, 0, &file_type, -1);
}
/* Extract the mime type */
mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_desc_hash, file_type));
g_free(file_type);
if(mimeType && mimeType->mimetype) {
file_type = strdup(mimeType->mimetype);
if(!g_str_has_suffix(result,mimeType->extension)) {
gchar *old_result = result;
result = g_strconcat(result, mimeType->extension, NULL);
g_free(old_result);
}
}
} else {
/* LOAD Mode, get the file_type from the extension in the mimetype */
GcomprisMimeType *mimeType = NULL;
gchar *ext = strrchr(result, '.');
/* Extract the mime type */
if(ext) {
mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_ext_hash, ext));
if(mimeType && mimeType->mimetype) {
if(file_type) {
g_free(file_type);
}
file_type = strdup(mimeType->mimetype);
}
}
}
/* Callback with the proper params */
fileSelectorCallBack(result, file_type);
if(file_type) {
g_free(file_type);
}
/* DO NOT FREE RESULT OR PYTHON SIDE WILL BE IN TROUBLE */
/* ADDENDUM: DOES NOT HURT ANYMORE, WHY ? */
if(result) {
g_free(result);
}
}
gc_selector_file_stop();
} else if(!strcmp((char *)data, "/cancel/")) {
gc_selector_file_stop();
} else {
gtk_entry_set_text(widget_entry, g_path_get_basename((gchar *)data));
}
break;
default:
break;
}
return FALSE;
}
static void entry_enter_callback( GtkWidget *widget,
GtkWidget *entry )
{
gchar *entry_text;
if(!rootitem)
return;
entry_text = (char *)gtk_entry_get_text(GTK_ENTRY(entry));
}
/*
* MimeType PARSING
* ----------------
*/
void parseMime (xmlDocPtr doc, xmlNodePtr xmlnode) {
GcomprisMimeType *gcomprisMime = g_malloc0 (sizeof (GcomprisMimeType));
gcomprisMime->mimetype = (gchar *)xmlGetProp(xmlnode, BAD_CAST "mimetype");
gcomprisMime->extension = (gchar *)xmlGetProp(xmlnode, BAD_CAST "extension");
gcomprisMime->icon = (gchar *)xmlGetProp(xmlnode, BAD_CAST "icon");
for (xmlnode = xmlnode->xmlChildrenNode; xmlnode != NULL; xmlnode = xmlnode->next) {
if (xmlHasProp(xmlnode, BAD_CAST "lang"))
continue;
/* get the title of the board */
if (!strcmp((char *)xmlnode->name, "description"))
gcomprisMime->description = (gchar *)xmlNodeListGetString(doc,
xmlnode->xmlChildrenNode, 0);
}
if(!gcomprisMime->mimetype || !gcomprisMime->extension || !gcomprisMime->description ) {
g_warning("Incomplete mimetype description\n");
g_free(gcomprisMime);
return;
}
g_message("Mime type mimetype=%s description=%s extension=%s icon=%s\n",
gcomprisMime->mimetype,
gcomprisMime->description,
gcomprisMime->extension,
gcomprisMime->icon);
g_hash_table_insert(mimetypes_hash, gcomprisMime->mimetype, gcomprisMime);
g_hash_table_insert(mimetypes_ext_hash, gcomprisMime->extension, gcomprisMime);
g_hash_table_insert(mimetypes_desc_hash, gettext(gcomprisMime->description), gcomprisMime);
return;
}
static void parse_doc(xmlDocPtr doc) {
xmlNodePtr cur;
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
g_warning("empty document\n");
xmlFreeDoc(doc);
return;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
if ((!xmlStrcmp(cur->name, (const xmlChar *)"MimeType"))){
parseMime (doc, cur);
}
cur = cur->next;
}
return;
}
/* read an xml file into our memory structures and update our view,
dump any old data we have in memory if we can load a new set */
gboolean load_mime_type_from_file(gchar *fname)
{
/* pointer to the new doc */
xmlDocPtr doc;
g_return_val_if_fail(fname!=NULL,FALSE);
/* if the file doesn't exist */
if(!g_file_test ((fname), G_FILE_TEST_EXISTS))
{
g_warning("Couldn't find file %s !", fname);
return FALSE;
}
/* parse the new file and put the result into newdoc */
doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
return FALSE;
if(/* if there is no root element */
!doc->children ||
/* if it doesn't have a name */
!doc->children->name ||
/* if it isn't the good node */
g_strcasecmp((gchar *)doc->children->name,"MimeTypeRoot")!=0) {
xmlFreeDoc(doc);
return FALSE;
}
/* parse our document and replace old data */
parse_doc(doc);
xmlFreeDoc(doc);
return TRUE;
}
/**
* gc_mime_type_load
* Load all the mime type in PACKAGE_DATA_DIR"/gcompris/mimetypes/ *.xml"
*
* Must be called once at GCompris startup.
*
*/
void gc_mime_type_load()
{
const gchar *one_dirent;
GcomprisProperties *properties = gc_prop_get();
GDir *dir;
gchar *mime_dir;
if(mimetypes_hash) {
return;
}
mime_dir = g_strconcat(properties->package_data_dir, "/gcompris/mimetypes/", NULL);
mimetypes_hash = g_hash_table_new (g_str_hash, g_str_equal);
mimetypes_ext_hash = g_hash_table_new (g_str_hash, g_str_equal);
mimetypes_desc_hash = g_hash_table_new (g_str_hash, g_str_equal);
/* Load the Pixpmaps directory file names */
dir = g_dir_open(mime_dir, 0, NULL);
if (!dir) {
g_warning("gc_mime_type_load : no mime types found in %s", mime_dir);
} else {
while((one_dirent = g_dir_read_name(dir)) != NULL) {
/* add the board to the list */
gchar *filename;
filename = g_strdup_printf("%s/%s", mime_dir, one_dirent);
if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
g_free(filename);
continue;
}
if(file_end_with_xml(one_dirent)) {
load_mime_type_from_file(filename);
}
g_free(filename);
}
}
g_free(mime_dir);
g_dir_close(dir);
}