Back to index

gcompris  8.2.2
file_selector.c
Go to the documentation of this file.
00001 /* gcompris - file_selector.c
00002  *
00003  * Time-stamp: <2006/08/20 10:29:31 bruno>
00004  *
00005  * Copyright (C) 2000 Bruno Coudoin
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 #include <string.h>
00030 
00031 /* libxml includes */
00032 #include <libxml/tree.h>
00033 #include <libxml/parser.h>
00034 
00035 #include "gcompris.h"
00036 #include "gc_core.h"
00037 
00038 #define SOUNDLISTFILE PACKAGE
00039 
00040 #define MODE_LOAD 1
00041 #define MODE_SAVE 2
00042 static gint mode;
00043 
00044 static gint           item_event_file_selector(GnomeCanvasItem *item,
00045                                             GdkEvent *event,
00046                                             gpointer data);
00047 static gint           item_event_scroll(GnomeCanvasItem *item,
00048                                       GdkEvent *event,
00049                                       GnomeCanvas *canvas);
00050 static gint           item_event_directory(GnomeCanvasItem *item,
00051                                          GdkEvent *event,
00052                                          char *dir);
00053 static void           display_files(GnomeCanvasItem *rootitem, gchar *rootdir);
00054 static int            display_file_selector(int mode,
00055                                           GcomprisBoard *gcomprisBoard,
00056                                           gchar *rootdir,
00057                                           gchar *file_types,
00058                                           FileSelectorCallBack iscb);
00059 static void           entry_enter_callback( GtkWidget *widget,
00060                                           GtkWidget *entry );
00061 static void           free_stuff (GtkObject *obj, gchar* data);
00062 
00063 static gboolean              file_selector_displayed = FALSE;
00064 
00065 static GnomeCanvasItem      *rootitem = NULL;
00066 static GnomeCanvasItem      *file_root_item = NULL;
00067 
00068 static FileSelectorCallBack  fileSelectorCallBack = NULL;
00069 static GtkWidget            *gtk_combo_filetypes = NULL;
00070 
00071 static gchar *current_rootdir = NULL;
00072 static GtkEntry *widget_entry = NULL;
00073 
00074 static GList  *file_list = NULL;
00075 
00076 /* Represent the limits of control area */
00077 static guint32 control_area_x1;
00078 static guint32 control_area_y1;
00079 static guint32 directory_label_y;
00080 
00081 /* Represent the limits of the file area */
00082 #define       DRAWING_AREA_X1      40.0
00083 #define DRAWING_AREA_Y1     220.0
00084 #define DRAWING_AREA_X2     760.0
00085 #define DRAWING_AREA_Y2     500.0
00086 
00087 #define HORIZONTAL_NUMBER_OF_IMAGE 5
00088 #define VERTICAL_NUMBER_OF_IMAGE   3
00089 #define IMAGE_GAP                  18
00090 
00091 #define IMAGE_WIDTH  (DRAWING_AREA_X2-DRAWING_AREA_X1)/HORIZONTAL_NUMBER_OF_IMAGE-IMAGE_GAP
00092 #define IMAGE_HEIGHT (DRAWING_AREA_Y2-DRAWING_AREA_Y1)/VERTICAL_NUMBER_OF_IMAGE-IMAGE_GAP
00093 
00094 /*
00095  * Mime type management
00096  * --------------------
00097  */
00098 typedef struct {
00099   gchar              *mimetype;
00100   gchar              *description;
00101   gchar              *extension;
00102   gchar              *icon;
00103 } GcomprisMimeType;
00104 
00105 static GHashTable* mimetypes_hash = NULL;
00106 static GHashTable* mimetypes_ext_hash  = NULL; /* Mime type with the key being the extension   */
00107 static GHashTable* mimetypes_desc_hash = NULL; /* Mime type with the key being the description */
00108 
00109 /*
00110  * Main entry point
00111  * ----------------
00112  *
00113  */
00114 
00115 /*
00116  * Do all the file_selector display and register the events
00117  * file_types is A Comma separated text explaining the different file types
00118  */
00119 
00120 void gc_selector_file_save (GcomprisBoard *gcomprisBoard, gchar *rootdir,
00121                               gchar *file_types,
00122                               FileSelectorCallBack iscb)
00123 {
00124   display_file_selector(MODE_SAVE, gcomprisBoard, rootdir, file_types,
00125                      iscb);
00126 }
00127 
00128 void gc_selector_file_load (GcomprisBoard *gcomprisBoard, gchar *rootdir,
00129                               gchar *file_types,
00130                               FileSelectorCallBack iscb)
00131 {
00132   display_file_selector(MODE_LOAD, gcomprisBoard, rootdir, file_types,
00133                      iscb);
00134 }
00135 
00136 /*
00137  * Remove the displayed file_selector.
00138  * Do nothing if none is currently being dislayed
00139  */
00140 void gc_selector_file_stop ()
00141 {
00142   GcomprisBoard *gcomprisBoard = gc_board_get_current();
00143 
00144   if(gcomprisBoard!=NULL && file_selector_displayed)
00145     gc_board_pause(FALSE);
00146 
00147   // Destroy the file_selector box
00148   /* FIXME: Crashes randomly */
00149   if(rootitem!=NULL)
00150     gtk_object_destroy(GTK_OBJECT(rootitem));
00151 
00152   rootitem = NULL;
00153 
00154   /* No need to destroy it since it's in rootitem but just clear it */
00155   file_root_item = NULL;
00156 
00157   /* Cleanup the file list */
00158   if(file_list) {
00159     //    g_list_foreach(file_list, (GFunc)g_free, NULL);
00160     g_list_free(file_list);
00161   }
00162   file_list = NULL;
00163 
00164   gc_bar_hide(FALSE);
00165   file_selector_displayed = FALSE;
00166 }
00167 
00168 
00169 
00170 /*-------------------------------------------------------------------------------*/
00171 /*-------------------------------------------------------------------------------*/
00172 /*-------------------------------------------------------------------------------*/
00173 /*-------------------------------------------------------------------------------*/
00174 
00175 
00176 static int
00177 display_file_selector(int the_mode,
00178                     GcomprisBoard *gcomprisBoard,
00179                     gchar *rootdir,
00180                     gchar *file_types,
00181                     FileSelectorCallBack iscb) {
00182 
00183 
00184   GnomeCanvasItem  *item, *item2;
00185   GdkPixbuf      *pixmap = NULL;
00186   gint            y = 0;
00187   gint            y_start = 0;
00188   gint            x_start = 0;
00189   gchar                 *name = NULL;
00190   gchar            *full_rootdir;
00191   gchar            *sub_string;
00192   gchar            *file_types_string = NULL;
00193 
00194   mode = the_mode;
00195 
00196   /* Get the coordinate x y of the control area from the skin */
00197   control_area_x1   = gc_skin_get_number_default("gcompris/fileselectx", 85);
00198   control_area_y1   = gc_skin_get_number_default("gcompris/fileselecty", 80);
00199   directory_label_y = gc_skin_get_number_default("gcompris/fileselectdiry", 180);
00200 
00201   if(file_types) {
00202     file_types_string = g_strdup(file_types);
00203   }
00204 
00205   if(rootitem)
00206     return 0;
00207 
00208   gc_bar_hide(TRUE);
00209 
00210   gc_board_pause(TRUE);
00211 
00212   name = gcomprisBoard->name;
00213   fileSelectorCallBack=iscb;
00214 
00215   rootitem = \
00216     gnome_canvas_item_new (gnome_canvas_root(gc_get_canvas()),
00217                         gnome_canvas_group_get_type (),
00218                         "x", (double)0,
00219                         "y", (double)0,
00220                         NULL);
00221 
00222   pixmap = gc_skin_pixmap_load("file_selector_bg.png");
00223   y_start = (BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2;
00224   x_start = (BOARDWIDTH - gdk_pixbuf_get_width(pixmap))/2;
00225   item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00226                             gnome_canvas_pixbuf_get_type (),
00227                             "pixbuf", pixmap,
00228                             "x", (double) x_start,
00229                             "y", (double) y_start,
00230                             NULL);
00231   y = BOARDHEIGHT - (BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2 + 20;
00232   gdk_pixbuf_unref(pixmap);
00233 
00234   /* Entry area */
00235   widget_entry = (GtkEntry *)gtk_entry_new ();
00236   gtk_entry_set_max_length(widget_entry, 30);
00237   item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00238                             gnome_canvas_widget_get_type (),
00239                             "widget", GTK_WIDGET(widget_entry),
00240                             "x", (double) control_area_x1,
00241                             "y", (double) control_area_y1,
00242                             "width", 230.0,
00243                             "height", 30.0,
00244                             "anchor", GTK_ANCHOR_NW,
00245                             "size_pixels", FALSE,
00246                             NULL);
00247   gtk_signal_connect(GTK_OBJECT(widget_entry), "activate",
00248                    GTK_SIGNAL_FUNC(entry_enter_callback),
00249                    widget_entry);
00250 
00251   gtk_widget_show(GTK_WIDGET(widget_entry));
00252 
00253   /*
00254    * Create the combo with the file types
00255    * ------------------------------------
00256    */
00257   if(mode==MODE_SAVE && file_types_string && *file_types_string!='\0') {
00258     GcomprisMimeType *mimeType = NULL;
00259     char *str;
00260     gchar *result;
00261 
00262     gtk_combo_filetypes = gtk_combo_box_new_text();
00263 
00264     /* Extract first string */
00265     str = (char *)strtok(file_types_string, " ");
00266     /* Extract the mime type */
00267     mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_hash, str));
00268     if(mimeType) {
00269       result = strdup(gettext(mimeType->description));
00270     } else {
00271       result = str;
00272     }
00273 
00274 
00275     gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_filetypes), result);
00276 
00277     while ( (sub_string=(char *)strtok(NULL, " ")) != NULL)
00278       {
00279        /* Extract the mime type */
00280        mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_hash, sub_string));
00281        if(mimeType) {
00282          result = strdup(gettext(mimeType->description));
00283        } else {
00284          result = str;
00285        }
00286 
00287        gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_filetypes), result);
00288       }
00289 
00290     gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00291                         gnome_canvas_widget_get_type (),
00292                         "widget", GTK_WIDGET(gtk_combo_filetypes),
00293                         "x", (double) control_area_x1 + 400,
00294                         "y", (double) control_area_y1,
00295                         "width", 250.0,
00296                         "height", 35.0,
00297                         "anchor", GTK_ANCHOR_NW,
00298                         "size_pixels", FALSE,
00299                         NULL);
00300 
00301     gtk_widget_show(GTK_WIDGET(gtk_combo_filetypes));
00302     gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_filetypes), 0);
00303     g_free(file_types_string);
00304   }
00305 
00306 
00307   y_start += 110;
00308 
00309 
00310   /*
00311    * Buttons
00312    * -------
00313    */
00314 
00315   pixmap = gc_skin_pixmap_load("button_large.png");
00316 
00317   // CANCEL
00318   item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00319                             gnome_canvas_pixbuf_get_type (),
00320                             "pixbuf", pixmap,
00321                             "x", (double) (BOARDWIDTH*0.33) - gdk_pixbuf_get_width(pixmap)/2,
00322                             "y", (double) y - gdk_pixbuf_get_height(pixmap) - 25,
00323                             NULL);
00324 
00325   gtk_signal_connect(GTK_OBJECT(item), "event",
00326                    (GtkSignalFunc) item_event_file_selector,
00327                    "/cancel/");
00328   gtk_signal_connect(GTK_OBJECT(item), "event",
00329                    (GtkSignalFunc) gc_item_focus_event,
00330                    NULL);
00331 
00332   item2 = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00333                              gnome_canvas_text_get_type (),
00334                              "text", _("CANCEL"),
00335                              "font", gc_skin_font_title,
00336                              "x", (double)  BOARDWIDTH*0.33,
00337                              "y", (double)  y - gdk_pixbuf_get_height(pixmap),
00338                              "anchor", GTK_ANCHOR_CENTER,
00339                              "fill_color_rgba", gc_skin_color_text_button,
00340                              NULL);
00341   gtk_signal_connect(GTK_OBJECT(item2), "event",
00342                    (GtkSignalFunc) item_event_file_selector,
00343                    "/cancel/");
00344   gtk_signal_connect(GTK_OBJECT(item2), "event",
00345                    (GtkSignalFunc) gc_item_focus_event,
00346                    item);
00347 
00348   // OK
00349   item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00350                             gnome_canvas_pixbuf_get_type (),
00351                             "pixbuf", pixmap,
00352                             "x", (double) (BOARDWIDTH*0.66) - gdk_pixbuf_get_width(pixmap)/2,
00353                             "y", (double) y - gdk_pixbuf_get_height(pixmap) - 25,
00354                             NULL);
00355 
00356   gtk_signal_connect(GTK_OBJECT(item), "event",
00357                    (GtkSignalFunc) item_event_file_selector,
00358                    "/ok/");
00359   gtk_signal_connect(GTK_OBJECT(item), "event",
00360                    (GtkSignalFunc) gc_item_focus_event,
00361                    NULL);
00362 
00363   item2 = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
00364                              gnome_canvas_text_get_type (),
00365                              "text", (mode==MODE_LOAD ? _("LOAD") : _("SAVE")),
00366                              "font", gc_skin_font_title,
00367                              "x", (double)  BOARDWIDTH*0.66,
00368                              "y", (double)  y - gdk_pixbuf_get_height(pixmap),
00369                              "anchor", GTK_ANCHOR_CENTER,
00370                              "fill_color_rgba", gc_skin_color_text_button,
00371                              NULL);
00372   gtk_signal_connect(GTK_OBJECT(item2), "event",
00373                    (GtkSignalFunc) item_event_file_selector,
00374                    "/ok/");
00375   gtk_signal_connect(GTK_OBJECT(item2), "event",
00376                    (GtkSignalFunc) gc_item_focus_event,
00377                    item);
00378   gdk_pixbuf_unref(pixmap);
00379 
00380 
00381 
00382   file_selector_displayed = TRUE;
00383 
00384   full_rootdir = g_strconcat(gc_prop_current_user_dirname_get(), "/", rootdir, NULL);
00385   gc_util_create_rootdir(full_rootdir);
00386 
00387   current_rootdir = full_rootdir;
00388 
00389   display_files(rootitem, full_rootdir);
00390 
00391   return 0;
00392 
00393 }
00394 
00395 static void
00396 free_stuff (GtkObject *obj, gchar *data)
00397 {
00398   g_free(data);
00399 }
00400 
00401 static void display_files(GnomeCanvasItem *root_item, gchar *rootdir)
00402 {
00403   GnomeCanvasItem *item;
00404   double iw, ih;
00405   const gchar *one_dirent;
00406   GDir  *dir;
00407 
00408   /* Initial image position */
00409   guint ix  = 0.0;
00410   guint iy  = 0.0;
00411 
00412   GtkWidget     *w;
00413   GnomeCanvasItem *bg_item;
00414 
00415   GnomeCanvas   *canvas; /* The scrolled part */
00416 
00417   GList  *dir_list  = NULL;
00418   GList  *listrunner;
00419 
00420   if(!rootitem)
00421     return;
00422 
00423   /* Display the directory content */
00424   dir = g_dir_open(rootdir, 0, NULL);
00425 
00426   if (!dir) {
00427     g_warning("gcompris_file_selector : no root directory found in %s", rootdir);
00428     g_free(rootdir);
00429     return;
00430   }
00431 
00432   /* Delete the previous file root if any */
00433   if(file_root_item!=NULL) {
00434     gtk_object_destroy(GTK_OBJECT(file_root_item));
00435   }
00436 
00437   /* Cleanup the file list */
00438   if(file_list) {
00439     //g_list_foreach(file_list, (GFunc)g_free, NULL);
00440     g_list_free(file_list);
00441   }
00442   file_list = NULL;
00443 
00444   /* Create a root item to put the image list in it */
00445   file_root_item = \
00446     gnome_canvas_item_new (GNOME_CANVAS_GROUP(root_item),
00447                         gnome_canvas_group_get_type (),
00448                         "x", (double)0,
00449                         "y", (double)0,
00450                         NULL);
00451 
00452   /*
00453    * Create the scrollbar
00454    * --------------------
00455    */
00456   canvas     = GNOME_CANVAS(gnome_canvas_new ());
00457 
00458   gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
00459                       gnome_canvas_widget_get_type (),
00460                       "widget", GTK_WIDGET(canvas),
00461                       "x", (double) DRAWING_AREA_X1,
00462                       "y", (double) DRAWING_AREA_Y1,
00463                       "width",  DRAWING_AREA_X2- DRAWING_AREA_X1 - 20.0,
00464                       "height", DRAWING_AREA_Y2-DRAWING_AREA_Y1 - 35.0,
00465                       NULL);
00466 
00467   gtk_widget_show (GTK_WIDGET(canvas));
00468 
00469   /* Set the new canvas to the background color or it's white */
00470   bg_item = gnome_canvas_item_new (gnome_canvas_root(canvas),
00471                       gnome_canvas_rect_get_type (),
00472                       "x1", (double) 0,
00473                       "y1", (double) 0,
00474                       "x2", (double) DRAWING_AREA_X2- DRAWING_AREA_X1,
00475                       "y2", (double) DRAWING_AREA_Y2-DRAWING_AREA_Y1,
00476                       "fill_color_rgba", gc_skin_get_color("gcompris/fileselectbg"),
00477                       NULL);
00478 
00479 
00480   w = gtk_vscrollbar_new (GTK_LAYOUT(canvas)->vadjustment);
00481 
00482   gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
00483                       gnome_canvas_widget_get_type (),
00484                       "widget", GTK_WIDGET(w),
00485                       "x", (double) DRAWING_AREA_X2 - 15.0,
00486                       "y", (double) DRAWING_AREA_Y1,
00487                       "width", 30.0,
00488                       "height", DRAWING_AREA_Y2-DRAWING_AREA_Y1 - 20.0,
00489                       NULL);
00490   gtk_widget_show (w);
00491   gnome_canvas_set_center_scroll_region (GNOME_CANVAS (canvas), FALSE);
00492 
00493   /* Set the scrollwheel event */
00494   gtk_signal_connect(GTK_OBJECT(canvas), "event",
00495                    (GtkSignalFunc) item_event_scroll,
00496                    GNOME_CANVAS(canvas));
00497 
00498   /* Display the directory name
00499    * --------------------------
00500    */
00501 
00502   item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(file_root_item),
00503                             gnome_canvas_text_get_type (),
00504                             "text", rootdir,
00505                             "x", (double)control_area_x1,
00506                             "y", (double)directory_label_y,
00507                             "fill_color_rgba", gc_skin_get_color("gcompris/fileselectcol"),
00508                             "anchor", GTK_ANCHOR_NW,
00509                             NULL);
00510 
00511 
00512   iw = IMAGE_WIDTH;
00513   ih = IMAGE_HEIGHT;
00514 
00515   /* Insert all files in a sorted list */
00516 
00517   while((one_dirent = g_dir_read_name(dir)) != NULL) {
00518     gchar *filename;
00519 
00520     filename = g_strdup_printf("%s/%s",
00521                             rootdir, (gchar*)(one_dirent));
00522 
00523     if(g_file_test(filename, G_FILE_TEST_IS_DIR)) {
00524       dir_list = g_list_insert_sorted(dir_list, filename,
00525                                    (GCompareFunc)strcmp);
00526     } else {
00527       file_list = g_list_insert_sorted(file_list, filename,
00528                                    (GCompareFunc)strcmp);
00529     }
00530   }
00531 
00532   /* Concat the directory list and file list */
00533   file_list = g_list_concat(dir_list, file_list);
00534 
00535   /* We have the list sorted, now display it */
00536   listrunner = g_list_first(file_list);
00537   while(listrunner) {
00538     /* add the file to the display */
00539     GdkPixbuf *pixmap_current;
00540 
00541     gchar *allfilename = listrunner->data;
00542     gchar *filename    = g_path_get_basename(allfilename);
00543     gchar *ext         = strrchr(filename, '.');
00544 
00545 
00546 
00547     if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
00548       pixmap_current  = gc_pixmap_load(gc_skin_image_get("directory.png"));
00549     } else if(ext) {
00550       /* Need to find an icon for this extension */
00551       GcomprisMimeType *mimeType = NULL;
00552 
00553       /* Extract the mime type for this extension */
00554       mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_ext_hash, ext));
00555       if(mimeType) {
00556        if(mimeType->icon) {
00557          pixmap_current  = gc_pixmap_load(mimeType->icon);
00558          if(pixmap_current==NULL) {
00559            g_warning("Cannot find icon %s for mimetype %s", mimeType->icon, mimeType->description);
00560            pixmap_current  = gc_pixmap_load(gc_skin_image_get("file.png"));
00561          } else {
00562            /* We can remove the extension now that we have an icon */
00563            *ext='\0';
00564          }
00565        } else {
00566          pixmap_current  = gc_pixmap_load(gc_skin_image_get("file.png"));
00567        }
00568       } else {
00569        pixmap_current  = gc_pixmap_load(gc_skin_image_get("file.png"));
00570       }
00571     } else {
00572       pixmap_current  = gc_pixmap_load(gc_skin_image_get("file.png"));
00573     }
00574 
00575     item = gnome_canvas_item_new (gnome_canvas_root(canvas),
00576                               gnome_canvas_pixbuf_get_type (),
00577                               "pixbuf", pixmap_current,
00578                               "x", (double)ix + (IMAGE_WIDTH + IMAGE_GAP
00579                                                - gdk_pixbuf_get_width(pixmap_current))/2,
00580                               "y", (double)iy,
00581                               NULL);
00582 
00583     gdk_pixbuf_unref(pixmap_current);
00584 
00585     if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
00586       gtk_signal_connect(GTK_OBJECT(item), "event",
00587                       (GtkSignalFunc) item_event_directory,
00588                       allfilename);
00589     } else {
00590       gtk_signal_connect(GTK_OBJECT(item), "event",
00591                       (GtkSignalFunc) item_event_file_selector,
00592                       allfilename);
00593     }
00594     gtk_signal_connect(GTK_OBJECT(item), "event",
00595                      (GtkSignalFunc) gc_item_focus_event,
00596                      NULL);
00597 
00598     g_signal_connect (item, "destroy",
00599                     G_CALLBACK (free_stuff),
00600                     allfilename);
00601 
00602     item = gnome_canvas_item_new (gnome_canvas_root(canvas),
00603                               gnome_canvas_text_get_type (),
00604                               "text", filename,
00605                               "x", (double)ix + (IMAGE_WIDTH + IMAGE_GAP)/2,
00606                               "y", (double)iy + IMAGE_HEIGHT - 5,
00607                               "anchor", GTK_ANCHOR_CENTER,
00608                               "fill_color_rgba", gc_skin_get_color("gcompris/fileselectcol"),
00609                               NULL);
00610 
00611     if(g_file_test(allfilename, G_FILE_TEST_IS_DIR)) {
00612       gtk_signal_connect(GTK_OBJECT(item), "event",
00613                       (GtkSignalFunc) item_event_directory,
00614                       allfilename);
00615     } else {
00616       gtk_signal_connect(GTK_OBJECT(item), "event",
00617                       (GtkSignalFunc) item_event_file_selector,
00618                       allfilename);
00619     }
00620 
00621     ix+=IMAGE_WIDTH + IMAGE_GAP;
00622     if(ix>=DRAWING_AREA_X2 - DRAWING_AREA_X1 -IMAGE_GAP)
00623       {
00624        ix=0;
00625 
00626        iy+=IMAGE_HEIGHT + IMAGE_GAP;
00627 
00628        gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0,
00629                                    DRAWING_AREA_X2- DRAWING_AREA_X1,
00630                                    iy + IMAGE_HEIGHT + IMAGE_GAP);
00631 
00632        if(iy>=DRAWING_AREA_Y2-DRAWING_AREA_Y1) {
00633          gnome_canvas_item_set(bg_item,
00634                             "y2", (double)iy + IMAGE_HEIGHT + IMAGE_GAP,
00635                             NULL);
00636        }
00637       }
00638     listrunner = g_list_next(listrunner);
00639   }
00640 
00641   g_dir_close(dir);
00642 
00643 }
00644 
00645 /* Callback when a directory is selected */
00646 static gint
00647 item_event_directory(GnomeCanvasItem *item, GdkEvent *event, gchar *dir)
00648 {
00649 
00650   if(!rootitem)
00651     return FALSE;
00652 
00653   switch (event->type)
00654     {
00655     case GDK_ENTER_NOTIFY:
00656       break;
00657     case GDK_LEAVE_NOTIFY:
00658       break;
00659     case GDK_BUTTON_PRESS:
00660       if(strcmp(g_path_get_basename(dir), "..")==0) {
00661        /* Up one level. Remove .. and one directory on the right of the path */
00662        dir[strlen(dir)-3] = '\0';
00663        dir=g_path_get_dirname(dir);
00664       }
00665       display_files(rootitem, g_strdup(dir));
00666       gtk_entry_set_text(widget_entry, "");
00667       break;
00668     default:
00669       break;
00670     }
00671   return FALSE;
00672 
00673 }
00674 
00675 /* Callback when a scroll event happens */
00676 static gint
00677 item_event_scroll(GnomeCanvasItem *item, GdkEvent *event, GnomeCanvas *canvas)
00678 {
00679   int x, y;
00680   if(!rootitem)
00681     return FALSE;
00682 
00683   switch (event->type)
00684     {
00685     case GDK_SCROLL:
00686       gnome_canvas_get_scroll_offsets (canvas, &x, &y);
00687       if ( event->scroll.direction == GDK_SCROLL_UP )
00688        gnome_canvas_scroll_to (canvas, x, y - 20);
00689       else if ( event->scroll.direction == GDK_SCROLL_DOWN )
00690        gnome_canvas_scroll_to (canvas, x, y + 20);
00691 
00692       break;
00693     default:
00694       break;
00695     }
00696   return FALSE;
00697 }
00698 
00699 /* Callback when a file is selected */
00700 static gint
00701 item_event_file_selector(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
00702 {
00703 
00704   if(!rootitem)
00705     return FALSE;
00706 
00707   switch (event->type)
00708     {
00709     case GDK_ENTER_NOTIFY:
00710       break;
00711     case GDK_LEAVE_NOTIFY:
00712       break;
00713     case GDK_BUTTON_PRESS:
00714       if(!strcmp((char *)data, "/ok/"))   {
00715 
00716        /* Nothing selected, please cancel instead */
00717        if(strcmp(gtk_entry_get_text(widget_entry),"")==0) {
00718          return FALSE;
00719        }
00720 
00721        if(fileSelectorCallBack!=NULL) {
00722          gchar *result=NULL;
00723          gchar *file_type=NULL;
00724 
00725          result = g_strdup_printf("%s/%s", current_rootdir, gtk_entry_get_text(widget_entry));
00726 
00727          if(mode==MODE_SAVE) {
00728            GcomprisMimeType *mimeType = NULL;
00729            GtkTreeModel *model;
00730            GtkTreeIter iter;
00731 
00732            model = gtk_combo_box_get_model ((GtkComboBox *)gtk_combo_filetypes);
00733            if (gtk_combo_box_get_active_iter ((GtkComboBox *)gtk_combo_filetypes, &iter)) {
00734              gtk_tree_model_get (model, &iter, 0, &file_type, -1);
00735            }
00736 
00737            /* Extract the mime type */
00738            mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_desc_hash, file_type));
00739            g_free(file_type);
00740            if(mimeType && mimeType->mimetype) {
00741              file_type = strdup(mimeType->mimetype);
00742              if(!g_str_has_suffix(result,mimeType->extension)) {
00743               gchar *old_result = result;
00744               result = g_strconcat(result, mimeType->extension, NULL);
00745               g_free(old_result);
00746              }
00747            }
00748          } else {
00749            /* LOAD Mode, get the file_type from the extension in the mimetype */
00750            GcomprisMimeType *mimeType = NULL;
00751            gchar *ext         = strrchr(result, '.');
00752 
00753            /* Extract the mime type */
00754            if(ext) {
00755              mimeType = (GcomprisMimeType *)(g_hash_table_lookup(mimetypes_ext_hash, ext));
00756              if(mimeType && mimeType->mimetype) {
00757               if(file_type) {
00758                 g_free(file_type);
00759               }
00760               file_type = strdup(mimeType->mimetype);
00761              }
00762            }
00763 
00764          }
00765 
00766          /* Callback with the proper params */
00767          fileSelectorCallBack(result, file_type);
00768 
00769          if(file_type) {
00770            g_free(file_type);
00771          }
00772 
00773          /* DO NOT FREE RESULT OR PYTHON SIDE WILL BE IN TROUBLE */
00774          //     if(result) {
00775          //       g_free(result);
00776          //     }
00777        }
00778        gc_selector_file_stop();
00779       } else if(!strcmp((char *)data, "/cancel/")) {
00780        gc_selector_file_stop();
00781       } else {
00782        gtk_entry_set_text(widget_entry, g_path_get_basename((gchar *)data));
00783       }
00784       break;
00785     default:
00786       break;
00787     }
00788   return FALSE;
00789 
00790 }
00791 
00792 static void entry_enter_callback( GtkWidget *widget,
00793                               GtkWidget *entry )
00794 {
00795   gchar *entry_text;
00796 
00797   if(!rootitem)
00798     return;
00799 
00800   entry_text = (char *)gtk_entry_get_text(GTK_ENTRY(entry));
00801 }
00802 
00803 /*
00804  * MimeType PARSING
00805  * ----------------
00806  */
00807 
00808 void parseMime (xmlDocPtr doc, xmlNodePtr xmlnode) {
00809 
00810   GcomprisMimeType *gcomprisMime = g_malloc0 (sizeof (GcomprisMimeType));
00811 
00812   gcomprisMime->mimetype    = (gchar *)xmlGetProp(xmlnode, BAD_CAST "mimetype");
00813   gcomprisMime->extension   = (gchar *)xmlGetProp(xmlnode, BAD_CAST "extension");
00814   gcomprisMime->icon        = (gchar *)xmlGetProp(xmlnode, BAD_CAST "icon");
00815 
00816   for (xmlnode = xmlnode->xmlChildrenNode; xmlnode != NULL; xmlnode = xmlnode->next) {
00817     if (xmlHasProp(xmlnode, BAD_CAST "lang"))
00818       continue;
00819 
00820     /* get the title of the board */
00821     if (!strcmp((char *)xmlnode->name, "description"))
00822       gcomprisMime->description = (gchar *)xmlNodeListGetString(doc,
00823                                                         xmlnode->xmlChildrenNode, 0);
00824   }
00825 
00826   if(!gcomprisMime->mimetype || !gcomprisMime->extension || !gcomprisMime->description ) {
00827     g_warning("Incomplete mimetype description\n");
00828     g_free(gcomprisMime);
00829     return;
00830   }
00831 
00832   g_message("Mime type mimetype=%s description=%s extension=%s icon=%s\n",
00833            gcomprisMime->mimetype,
00834            gcomprisMime->description,
00835            gcomprisMime->extension,
00836            gcomprisMime->icon);
00837 
00838   g_hash_table_insert(mimetypes_hash,      gcomprisMime->mimetype,    gcomprisMime);
00839   g_hash_table_insert(mimetypes_ext_hash,  gcomprisMime->extension,   gcomprisMime);
00840   g_hash_table_insert(mimetypes_desc_hash, gettext(gcomprisMime->description), gcomprisMime);
00841 
00842   return;
00843 }
00844 
00845 static void parse_doc(xmlDocPtr doc) {
00846   xmlNodePtr cur;
00847 
00848   cur = xmlDocGetRootElement(doc);
00849   if (cur == NULL) {
00850     fprintf(stderr,"empty document\n");
00851     xmlFreeDoc(doc);
00852     return;
00853   }
00854   cur = cur->xmlChildrenNode;
00855 
00856   while (cur != NULL) {
00857     if ((!xmlStrcmp(cur->name, (const xmlChar *)"MimeType"))){
00858       parseMime (doc, cur);
00859     }
00860 
00861     cur = cur->next;
00862   }
00863 
00864   return;
00865 }
00866 
00867 
00868 /* read an xml file into our memory structures and update our view,
00869    dump any old data we have in memory if we can load a new set */
00870 gboolean load_mime_type_from_file(gchar *fname)
00871 {
00872   /* pointer to the new doc */
00873   xmlDocPtr doc;
00874 
00875   g_return_val_if_fail(fname!=NULL,FALSE);
00876 
00877   /* if the file doesn't exist */
00878   if(!g_file_test ((fname), G_FILE_TEST_EXISTS))
00879     {
00880       g_warning("Couldn't find file %s !", fname);
00881       return FALSE;
00882     }
00883 
00884   /* parse the new file and put the result into newdoc */
00885   doc = xmlParseFile(fname);
00886 
00887   /* in case something went wrong */
00888   if(!doc)
00889     return FALSE;
00890 
00891   if(/* if there is no root element */
00892      !doc->children ||
00893      /* if it doesn't have a name */
00894      !doc->children->name ||
00895      /* if it isn't the good node */
00896      g_strcasecmp((gchar *)doc->children->name,"MimeTypeRoot")!=0) {
00897     xmlFreeDoc(doc);
00898     return FALSE;
00899   }
00900 
00901   /* parse our document and replace old data */
00902   parse_doc(doc);
00903 
00904   xmlFreeDoc(doc);
00905 
00906   return TRUE;
00907 }
00908 
00916 void gc_mime_type_load()
00917 {
00918   const gchar  *one_dirent;
00919   GcomprisProperties *properties = gc_prop_get();
00920   GDir   *dir;
00921   gchar  *mime_dir;
00922 
00923   if(mimetypes_hash) {
00924     return;
00925   }
00926 
00927   mime_dir = g_strconcat(properties->package_data_dir, "/gcompris/mimetypes/", NULL);
00928 
00929   mimetypes_hash      = g_hash_table_new (g_str_hash, g_str_equal);
00930   mimetypes_ext_hash  = g_hash_table_new (g_str_hash, g_str_equal);
00931   mimetypes_desc_hash = g_hash_table_new (g_str_hash, g_str_equal);
00932 
00933   /* Load the Pixpmaps directory file names */
00934   dir = g_dir_open(mime_dir, 0, NULL);
00935 
00936   if (!dir) {
00937     g_warning("gc_mime_type_load : no mime types found in %s", mime_dir);
00938   } else {
00939 
00940     while((one_dirent = g_dir_read_name(dir)) != NULL) {
00941       /* add the board to the list */
00942       gchar *filename;
00943 
00944       filename = g_strdup_printf("%s/%s", mime_dir, one_dirent);
00945 
00946       if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
00947        g_free(filename);
00948        continue;
00949       }
00950 
00951       if(file_end_with_xml(one_dirent)) {
00952        load_mime_type_from_file(filename);
00953       }
00954       g_free(filename);
00955     }
00956   }
00957   g_free(mime_dir);
00958   g_dir_close(dir);
00959 }