/* 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); }