Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Coudoin <bcoudoin@src.gnome.org>2009-02-17 23:18:08 (GMT)
committer Bruno Coudoin <bcoudoin@src.gnome.org>2009-02-17 23:18:08 (GMT)
commit460c950a51fe6fdb51a10710a9b6f9d7085880c7 (patch)
tree83d31a852ea0ea4108307a9aad89f91c8e4532b5
parentb061947341f605b9d6318daeb8e3f643f51e3ff8 (diff)
merged 3722 from trunk
svn path=/branches/GCOMPRIS_8_3/; revision=3723
-rw-r--r--ChangeLog78
-rw-r--r--boards/missing_letter/Makefile.am5
-rw-r--r--boards/missing_letter/board1.xml.in108
-rw-r--r--boards/missing_letter/board2.xml.in40
-rw-r--r--boards/missing_letter/board3.xml.in40
-rw-r--r--boards/missing_letter/board4.xml.in40
-rw-r--r--configure.in14
-rw-r--r--src/boards/Makefile.am2
-rw-r--r--src/boards/advanced_colors.c2
-rw-r--r--src/boards/imageid.c2
-rw-r--r--src/boards/missingletter.c171
-rw-r--r--src/boards/missingletter_config.c599
-rw-r--r--src/boards/python/admin/board_list.py7
-rw-r--r--src/boards/read_colors.c2
-rw-r--r--src/boards/reading.c17
-rw-r--r--src/boards/shapegame.c2
-rw-r--r--src/boards/superbrain.c4
-rw-r--r--src/boards/wordprocessor.c2
-rw-r--r--src/gcompris/Makefile.am1
-rw-r--r--src/gcompris/board_config_wordlist.c38
-rw-r--r--src/gcompris/cache.c204
-rw-r--r--src/gcompris/config.c2
-rw-r--r--src/gcompris/dialog.c3
-rw-r--r--src/gcompris/gameutil.c42
-rw-r--r--src/gcompris/gameutil.h1
-rw-r--r--src/gcompris/gc_core.h7
-rw-r--r--src/gcompris/gc_net.c349
-rw-r--r--src/gcompris/gc_net.h11
-rw-r--r--src/gcompris/gcompris.c30
-rw-r--r--src/gcompris/images_selector.c6
-rw-r--r--src/gcompris/skin.c2
-rw-r--r--src/gcompris/wordlist.c2
32 files changed, 1258 insertions, 575 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b1c026..c7d0d63 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,81 @@
+
+2009-02-17 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - Merged 3722 fromm trunk
+ - Miquel DE IZARRA Added support for editing the content
+ of the missing letter activity.
+
+ * boards/missing_letter/Makefile.am:
+ * boards/missing_letter/board1.xml.in:
+ * boards/missing_letter/board2.xml.in:
+ * boards/missing_letter/board3.xml.in:
+ * boards/missing_letter/board4.xml.in:
+ * src/boards/Makefile.am:
+ * src/boards/missingletter.c: (pause_board), (start_board),
+ (end_board), (set_level), (missing_letter_next_level),
+ (missing_letter_create_item), (game_won), (init_xml),
+ (add_xml_data), (missing_read_xml_file),
+ (missing_destroy_board_list), (conf_ok), (config_start):
+ * src/boards/missingletter_config.c: (new_clicked),
+ (delete_clicked), (valid_entry), (apply_clicked), (up_clicked),
+ (down_clicked), (_save), (save_clicked), (level_changed),
+ (text_changed), (selection_changed), (destroy_conf_data),
+ (configure_colummns), (config_missing_letter):
+ * src/boards/reading.c: (reading_create_item), (get_random_word):
+ * src/gcompris/board_config_wordlist.c: (gc_board_config_wordlist):
+ * src/gcompris/gc_net.c: (gc_net_get_url_from_file),
+ (gc_cache_import_pixmap):
+ * src/gcompris/gc_net.h:
+ * src/gcompris/gcompris.c: (main):
+
+2009-02-05 Bruno coudoin <bruno.coudoin@free.fr>
+
+ From trunk 3720
+ Miguel DE IZARRA added support for online wordlist.
+ This save custom data in user_dir and make a content.txt (a md5sum
+ like file) listing custom files. Simply put this files in a web server
+ to diffuse in classroom.
+
+ GCompris clients are launch with --server and --cache-dir
+ On start, client download content.txt from server.
+
+ And when a client need a file:
+ - first he search in server list (from content.txt)
+ - if found, he check md5 of file in cache_dir
+ - if md5 isn't ok, file is download in cache_dir
+ file in cache_dir is used
+ - if not found, search in package_dir (like now)
+
+ * configure.in:
+ * src/boards/advanced_colors.c: (read_xml_file):
+ * src/boards/imageid.c: (read_xml_file):
+ * src/boards/missingletter.c: (read_xml_file):
+ * src/boards/python/admin/board_list.py:
+ * src/boards/read_colors.c: (read_xml_file):
+ * src/boards/shapegame.c: (read_xml_file):
+ * src/boards/superbrain.c: (mark_pieces):
+ * src/boards/wordprocessor.c: (load_buffer):
+ * src/gcompris/Makefile.am:
+ * src/gcompris/board_config_wordlist.c: (_return_clicked),
+ (gc_board_config_wordlist):
+ * src/gcompris/cache.c:
+ * src/gcompris/config.c: (set_locale_flag):
+ * src/gcompris/dialog.c:
+ * src/gcompris/gameutil.c: (gc_pixmap_load),
+ (gc_file_find_absolute), (gc_file_find_absolute_writeable):
+ * src/gcompris/gameutil.h:
+ * src/gcompris/gc_core.h:
+ * src/gcompris/gc_net.c: (load_md5file), (gc_net_init),
+ (gc_net_destroy), (gc_net_get_url_from_file), (gc_cache_init),
+ (gc_cache_get_relative), (gc_cache_add), (gc_cache_remove),
+ (_table_foreach), (gc_cache_save), (gc_cache_destroy):
+ * src/gcompris/gc_net.h:
+ * src/gcompris/gcompris.c: (setup_window), (cleanup), (main):
+ * src/gcompris/images_selector.c: (gc_selector_images_start),
+ (read_xml_file):
+ * src/gcompris/skin.c: (skin_xml_load):
+ * src/gcompris/wordlist.c: (gc_wordlist_save):
+
2009-02-01 Bruno coudoin <bruno.coudoin@free.fr>
From trunk 3718
diff --git a/boards/missing_letter/Makefile.am b/boards/missing_letter/Makefile.am
index 4bffd44..3d8c1e3 100644
--- a/boards/missing_letter/Makefile.am
+++ b/boards/missing_letter/Makefile.am
@@ -2,7 +2,10 @@
xmldir = $(pkgdatadir)/@PACKAGE_DATA_DIR@/missing_letter
xml_in_files = \
- board1.xml.in
+ board1.xml.in \
+ board2.xml.in \
+ board3.xml.in \
+ board4.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
diff --git a/boards/missing_letter/board1.xml.in b/boards/missing_letter/board1.xml.in
index 221d6db..4a9a491 100644
--- a/boards/missing_letter/board1.xml.in
+++ b/boards/missing_letter/board1.xml.in
@@ -36,113 +36,5 @@
<pixmapfile>imageid/bed.png</pixmapfile>
<_data>bed/_ed/b/l/f</_data>
</Board>
- <Board>
- <pixmapfile>imageid/bottle.png</pixmapfile>
- <_data>bottle/_ottle/b/t/p</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/cake.png</pixmapfile>
- <_data>cake/_ake/c/p/d</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/ballon.png</pixmapfile>
- <_data>ball/_all/b/p/d</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/avion.png</pixmapfile>
- <_data>plane/p_ane/l/j/i</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/chien.png</pixmapfile>
- <_data>dog/d_g/o/g/a</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/fish.png</pixmapfile>
- <_data>fish/_ish/f/h/l</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/car.png</pixmapfile>
- <_data>car/_ar/c/k/b</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/cartable.png</pixmapfile>
- <_data>satchel/_atchel/s/c/l</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/banana.png</pixmapfile>
- <_data>banana/_anana/b/p/d</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/maison.png</pixmapfile>
- <_data>house/h_use/o/f/u</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/pomme.png</pixmapfile>
- <_data>apple/appl_/e/h/a</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/bed.png</pixmapfile>
- <_data>bed/b_d/e/a/i</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/bottle.png</pixmapfile>
- <_data>bottle/b_ttle/o/u/d</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/cake.png</pixmapfile>
- <_data>cake/c_ke/a/o/e</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/ballon.png</pixmapfile>
- <_data>ball/b_ll/a/u/o</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/avion.png</pixmapfile>
- <_data>plane/pl_ne/a/o/s</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/chien.png</pixmapfile>
- <_data>dog/do_/g/p/q</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/fish.png</pixmapfile>
- <_data>fish/fis_/h/o/i</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/car.png</pixmapfile>
- <_data>car/ca_/r/w/k</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/cartable.png</pixmapfile>
- <_data>satchel/sa_chel/t/p/c</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/banana.png</pixmapfile>
- <_data>banana/ba_ana/n/m/b</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/maison.png</pixmapfile>
- <_data>house/_ouse/h/e/j</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/pomme.png</pixmapfile>
- <_data>apple/app_e/l/h/n</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/bed.png</pixmapfile>
- <_data>bed/be_/d/p/b</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/bottle.png</pixmapfile>
- <_data>bottle/bott_e/l/y/r</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/cake.png</pixmapfile>
- <_data>cake/ca_e/k/q/c</_data>
- </Board>
- <Board>
- <pixmapfile>imageid/ballon.png</pixmapfile>
- <_data>ball/bal_/l/h/s</_data>
- </Board>
</missing_letter>
diff --git a/boards/missing_letter/board2.xml.in b/boards/missing_letter/board2.xml.in
new file mode 100644
index 0000000..3f82d24
--- /dev/null
+++ b/boards/missing_letter/board2.xml.in
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+ <Board>
+ <pixmapfile>imageid/bottle.png</pixmapfile>
+ <_data>bottle/_ottle/b/t/p</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/cake.png</pixmapfile>
+ <_data>cake/_ake/c/p/d</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/ballon.png</pixmapfile>
+ <_data>ball/_all/b/p/d</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/avion.png</pixmapfile>
+ <_data>plane/p_ane/l/j/i</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/chien.png</pixmapfile>
+ <_data>dog/d_g/o/g/a</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/fish.png</pixmapfile>
+ <_data>fish/_ish/f/h/l</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/car.png</pixmapfile>
+ <_data>car/_ar/c/k/b</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/cartable.png</pixmapfile>
+ <_data>satchel/_atchel/s/c/l</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/banana.png</pixmapfile>
+ <_data>banana/_anana/b/p/d</_data>
+ </Board>
+</missing_letter>
+
diff --git a/boards/missing_letter/board3.xml.in b/boards/missing_letter/board3.xml.in
new file mode 100644
index 0000000..8d84227
--- /dev/null
+++ b/boards/missing_letter/board3.xml.in
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+ <Board>
+ <pixmapfile>imageid/maison.png</pixmapfile>
+ <_data>house/h_use/o/f/u</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/pomme.png</pixmapfile>
+ <_data>apple/appl_/e/h/a</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/bed.png</pixmapfile>
+ <_data>bed/b_d/e/a/i</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/bottle.png</pixmapfile>
+ <_data>bottle/b_ttle/o/u/d</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/cake.png</pixmapfile>
+ <_data>cake/c_ke/a/o/e</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/ballon.png</pixmapfile>
+ <_data>ball/b_ll/a/u/o</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/avion.png</pixmapfile>
+ <_data>plane/pl_ne/a/o/s</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/chien.png</pixmapfile>
+ <_data>dog/do_/g/p/q</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/fish.png</pixmapfile>
+ <_data>fish/fis_/h/o/i</_data>
+ </Board>
+</missing_letter>
+
diff --git a/boards/missing_letter/board4.xml.in b/boards/missing_letter/board4.xml.in
new file mode 100644
index 0000000..6cc224f
--- /dev/null
+++ b/boards/missing_letter/board4.xml.in
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+ <Board>
+ <pixmapfile>imageid/car.png</pixmapfile>
+ <_data>car/ca_/r/w/k</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/cartable.png</pixmapfile>
+ <_data>satchel/sa_chel/t/p/c</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/banana.png</pixmapfile>
+ <_data>banana/ba_ana/n/m/b</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/maison.png</pixmapfile>
+ <_data>house/_ouse/h/e/j</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/pomme.png</pixmapfile>
+ <_data>apple/app_e/l/h/n</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/bed.png</pixmapfile>
+ <_data>bed/be_/d/p/b</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/bottle.png</pixmapfile>
+ <_data>bottle/bott_e/l/y/r</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/cake.png</pixmapfile>
+ <_data>cake/ca_e/k/q/c</_data>
+ </Board>
+ <Board>
+ <pixmapfile>imageid/ballon.png</pixmapfile>
+ <_data>ball/bal_/l/h/s</_data>
+ </Board>
+</missing_letter>
+
diff --git a/configure.in b/configure.in
index 2f3700d..f7f181d 100644
--- a/configure.in
+++ b/configure.in
@@ -398,6 +398,20 @@ if test x$TETEX = xno; then
AC_MSG_WARN(Couldn't find texi2html usualy in the tetex package, please install it)
fi
+
+dnl GNET support
+AC_MSG_CHECKING([wether we build with GNET (if not, networking will be disabled)])
+AC_ARG_ENABLE(gnet,
+ AC_HELP_STRING(
+ [--disable-gnet],
+ [Turn on gnet (will let GCompris fetch content from a web server)]),
+ with_gnet="$enableval", with_gnet="no")
+AC_MSG_RESULT($with_gnet)
+
+if test x$with_gnet = xyes; then
+ PKG_CHECK_MODULES(GNET, gnet-2.0,, AC_MSG_ERROR([*** GNET not found!]))
+ AC_DEFINE([USE_GNET], 1,[Networking is enabled])
+fi
dnl SQLITE support
AC_MSG_CHECKING([wether we build with SQLITE (if not profile will be disabled)])
diff --git a/src/boards/Makefile.am b/src/boards/Makefile.am
index 2e705a1..7e714ef 100644
--- a/src/boards/Makefile.am
+++ b/src/boards/Makefile.am
@@ -170,7 +170,7 @@ libimageid_la_SOURCES = imageid.c
libmissingletter_la_LDFLAGS = $(shared) $(no_undefined) -module -avoid-version $(gc_libs) $(XML_LIBS)
libmissingletter_la_LIBADD =
-libmissingletter_la_SOURCES = missingletter.c
+libmissingletter_la_SOURCES = missingletter.c missingletter_config.c
libclick_on_letter_la_LDFLAGS = $(shared) $(no_undefined) -module -avoid-version $(gc_libs)
diff --git a/src/boards/advanced_colors.c b/src/boards/advanced_colors.c
index c1a8e14..2f94ef6 100644
--- a/src/boards/advanced_colors.c
+++ b/src/boards/advanced_colors.c
@@ -521,7 +521,7 @@ static gboolean read_xml_file(char *fname)
g_return_val_if_fail(fname!=NULL,FALSE);
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
diff --git a/src/boards/imageid.c b/src/boards/imageid.c
index 6499871..984dcfb 100644
--- a/src/boards/imageid.c
+++ b/src/boards/imageid.c
@@ -633,7 +633,7 @@ static gboolean read_xml_file(char *fname)
g_return_val_if_fail(fname!=NULL,FALSE);
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
diff --git a/src/boards/missingletter.c b/src/boards/missingletter.c
index ffe9621..4915082 100644
--- a/src/boards/missingletter.c
+++ b/src/boards/missingletter.c
@@ -27,7 +27,7 @@
#define SOUNDLISTFILE PACKAGE
-static GcomprisBoard *gcomprisBoard = NULL;
+GcomprisBoard *gcomprisBoard_missing = NULL;
static gboolean board_paused = TRUE;
static void start_board (GcomprisBoard *agcomprisBoard);
@@ -43,6 +43,9 @@ static void config_start(GcomprisBoard *agcomprisBoard,
GcomprisProfile *aProfile);
static void config_stop(void);
+/* from missingletter_config.c */
+void config_missing_letter(GcomprisBoardConf *config);
+
typedef struct _Board Board;
struct _Board {
char *pixmapfile;
@@ -56,12 +59,10 @@ struct _Board {
static Board * board;
/* XML */
-static gboolean read_xml_file(char *fname);
static void init_xml(void);
-static void add_xml_data(xmlDocPtr, xmlNodePtr, GNode *);
-static void parse_doc(xmlDocPtr doc);
-static gboolean read_xml_file(char *fname);
-static void destroy_board_list();
+static void add_xml_data(xmlDocPtr, xmlNodePtr, GList**);
+gboolean missing_read_xml_file(char *fname, GList**);
+void missing_destroy_board_list(GList *);
static void destroy_board(Board * board);
/* This is the list of boards */
@@ -70,12 +71,7 @@ static GList *board_list = NULL;
#define VERTICAL_SEPARATION 30
#define HORIZONTAL_SEPARATION 30
-//NUMBER_OF_SUBLEVELS*NUMBER_OF_LEVELS must equal the number of boards in XML file
-#define NUMBER_OF_SUBLEVELS 9
-#define NUMBER_OF_LEVELS 4
-
/* ================================================================ */
-static int board_number; // between 0 and board_list.length-1
static int right_word; // between 1 and 3, indicates which choice is the right one (the player clicks on it
static GnomeCanvasGroup *boardRootItem = NULL;
@@ -132,7 +128,7 @@ GET_BPLUGIN_INFO(missingletter)
*/
static void pause_board (gboolean pause)
{
- if(gcomprisBoard==NULL)
+ if(gcomprisBoard_missing==NULL)
return;
gc_bar_hide(FALSE);
@@ -150,6 +146,7 @@ static void pause_board (gboolean pause)
static void start_board (GcomprisBoard *agcomprisBoard)
{
GHashTable *config = gc_db_get_board_conf();
+ gchar * filename;
gc_locale_set(g_hash_table_lookup( config, "locale"));
@@ -157,19 +154,23 @@ static void start_board (GcomprisBoard *agcomprisBoard)
if(agcomprisBoard!=NULL)
{
- gcomprisBoard=agcomprisBoard;
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
+ gcomprisBoard_missing=agcomprisBoard;
+ gc_set_background(gnome_canvas_root(gcomprisBoard_missing->canvas),
"opt/missingletter-bg.jpg");
- gcomprisBoard->level=1;
- gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
- gcomprisBoard->sublevel=1;
- gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
+ gcomprisBoard_missing->level=1;
+
+ /* Calculate the maxlevel based on the available data file for this board */
+ gcomprisBoard_missing->maxlevel = 1;
+ while((filename = gc_file_find_absolute("%s/board%d.xml",
+ gcomprisBoard_missing->boarddir, ++gcomprisBoard_missing->maxlevel)))
+ g_free(filename);
+
+ gcomprisBoard_missing->maxlevel--;
+
+ gcomprisBoard_missing->sublevel=1;
+ gcomprisBoard_missing->number_of_sublevel=G_MAXINT;
+
init_xml();
- g_assert(NUMBER_OF_LEVELS*NUMBER_OF_SUBLEVELS == g_list_length(board_list));
- gc_score_start(SCORESTYLE_NOTE,
- 50,
- gcomprisBoard->height - 50,
- gcomprisBoard->number_of_sublevel);
gc_bar_set(GC_BAR_CONFIG | GC_BAR_LEVEL);
missing_letter_next_level();
@@ -182,27 +183,29 @@ static void start_board (GcomprisBoard *agcomprisBoard)
static void end_board ()
{
- if(gcomprisBoard!=NULL)
+ if(gcomprisBoard_missing!=NULL)
{
pause_board(TRUE);
gc_score_end();
missing_letter_destroy_all_items();
- destroy_board_list();
+ missing_destroy_board_list(board_list);
+ board_list = NULL;
}
gc_locale_reset();
- gcomprisBoard = NULL;
+ gcomprisBoard_missing = NULL;
}
static void
set_level (guint level)
{
- if(gcomprisBoard!=NULL)
+ if(gcomprisBoard_missing!=NULL)
{
- gcomprisBoard->level=level;
- gcomprisBoard->sublevel=1;
+ gcomprisBoard_missing->level=level;
+ gcomprisBoard_missing->sublevel=1;
+ init_xml();
missing_letter_next_level();
}
}
@@ -228,16 +231,16 @@ is_our_board (GcomprisBoard *gcomprisBoard)
/* set initial values for the next level */
static void missing_letter_next_level()
{
- gc_bar_set_level(gcomprisBoard);
+ gc_bar_set_level(gcomprisBoard_missing);
missing_letter_destroy_all_items();
selected_button = NULL;
gamewon = FALSE;
- gc_score_set(gcomprisBoard->sublevel);
+ gc_score_set(gcomprisBoard_missing->sublevel);
/* Try the next level */
- missing_letter_create_item(gnome_canvas_root(gcomprisBoard->canvas));
+ missing_letter_create_item(gnome_canvas_root(gcomprisBoard_missing->canvas));
}
/* ==================================== */
@@ -268,27 +271,24 @@ static GnomeCanvasItem *missing_letter_create_item(GnomeCanvasGroup *parent)
gint txt_area_x = 515;
gint txt_area_y = 435;
- board_number = (gcomprisBoard->level-1) * NUMBER_OF_SUBLEVELS + gcomprisBoard->sublevel-1;
-
- g_assert(board_number >= 0 && board_number < g_list_length(board_list));
place = g_random_int_range( 0, 3);
g_assert(place >= 0 && place < 3);
right_word = place+1;
boardRootItem = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+ gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard_missing->canvas),
gnome_canvas_group_get_type (),
"x", (double) 0,
"y", (double) 0,
NULL));
button_pixmap = gc_skin_pixmap_load("button.png");
/* display the image */
- board = g_list_nth_data(board_list, board_number);
+ board = g_list_nth_data(board_list, gcomprisBoard_missing->sublevel-1);
g_assert(board != NULL);
pixmap = gc_pixmap_load(board->pixmapfile);
- yOffset = (gcomprisBoard->height - gdk_pixbuf_get_height(button_pixmap) - gdk_pixbuf_get_height(pixmap) - 2*VERTICAL_SEPARATION)/2;
+ yOffset = (gcomprisBoard_missing->height - gdk_pixbuf_get_height(button_pixmap) - gdk_pixbuf_get_height(pixmap) - 2*VERTICAL_SEPARATION)/2;
text_s = gnome_canvas_item_new (boardRootItem,
gnome_canvas_text_get_type (),
@@ -345,7 +345,7 @@ static GnomeCanvasItem *missing_letter_create_item(GnomeCanvasGroup *parent)
break;
}
- yOffset = ( gcomprisBoard->height - 3*gdk_pixbuf_get_height(button_pixmap) - 2*VERTICAL_SEPARATION) / 2;
+ yOffset = ( gcomprisBoard_missing->height - 3*gdk_pixbuf_get_height(button_pixmap) - 2*VERTICAL_SEPARATION) / 2;
xOffset = (img_area_x-gdk_pixbuf_get_width(button_pixmap))/2;
button1 = gnome_canvas_item_new (boardRootItem,
gnome_canvas_pixbuf_get_type (),
@@ -438,13 +438,15 @@ static GnomeCanvasItem *missing_letter_create_item(GnomeCanvasGroup *parent)
}
/* ==================================== */
static void game_won() {
- gcomprisBoard->sublevel++;
+ gcomprisBoard_missing->sublevel++;
- if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
+ if(gcomprisBoard_missing->sublevel>gcomprisBoard_missing->number_of_sublevel) {
/* Try the next level */
- gcomprisBoard->sublevel=1;
- gcomprisBoard->level++;
- if(gcomprisBoard->level>gcomprisBoard->maxlevel) {
+ gcomprisBoard_missing->sublevel=1;
+ gcomprisBoard_missing->level++;
+ init_xml();
+
+ if(gcomprisBoard_missing->level>gcomprisBoard_missing->maxlevel) {
gc_bonus_end_display(GC_BOARD_FINISHED_TUXPLANE);
return;
}
@@ -563,16 +565,27 @@ static void init_xml()
{
char *filename;
- filename = gc_file_find_absolute("%s/board1.xml",
- gcomprisBoard->boarddir);
-
- g_assert(read_xml_file(filename)== TRUE);
-
+ if(board_list)
+ {
+ missing_destroy_board_list(board_list);
+ board_list = NULL;
+ }
+ filename = gc_file_find_absolute("%s/board%d.xml",
+ gcomprisBoard_missing->boarddir,
+ gcomprisBoard_missing->level);
+ missing_read_xml_file(filename, &board_list);
+ gcomprisBoard_missing->number_of_sublevel = g_list_length(board_list);
g_free(filename);
+
+ gc_score_end();
+ gc_score_start(SCORESTYLE_NOTE,
+ 50,
+ gcomprisBoard_missing->height - 50,
+ gcomprisBoard_missing->number_of_sublevel);
}
/* ==================================== */
-static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
+static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GList **list)
{
gchar *pixmapfile = NULL;
gchar *question = NULL, *answer = NULL;
@@ -594,22 +607,17 @@ static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
{
if(data==NULL)
{
- data = gettext((gchar *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1));
+ gchar *tmp;
+ tmp = (gchar *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
+ data = g_strdup(gettext(tmp));
+ g_free(tmp);
}
}
xmlnode = xmlnode->next;
}
- // I really don't know why this test, but otherwise, the list is doubled
- // with 1 line on 2 filled with NULL elements
- if ( pixmapfile == NULL || data == NULL)
- return;
-
-/* if ((i=sscanf(data, "%s / %s / %s / %s / %s", answer, question, l1, l2, l3)) != 5)
- printf("Error sscanf result != 5 = %i\n",i);
-*/
gchar **all_answer = g_strsplit(data, "/", 5);
- /* Dont free data, it's a gettext static message */
+ g_free(data);
answer = all_answer[0];
question = all_answer[1];
@@ -628,33 +636,23 @@ static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
g_strfreev(all_answer);
- board_list = g_list_append (board_list, board);
+ *list = g_list_append (*list, board);
}
-/* ==================================== */
-static void parse_doc(xmlDocPtr doc)
-{
- xmlNodePtr node;
-
- for(node = doc->children->children; node != NULL; node = node->next) {
- if ( g_strcasecmp((gchar *)node->name, "Board") == 0 )
- add_xml_data(doc, node,NULL);
- }
-
-}
/* ==================================== */
/* 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 */
-static gboolean read_xml_file(char *fname)
+gboolean missing_read_xml_file(char *fname, GList **list)
{
/* pointer to the new doc */
xmlDocPtr doc;
+ xmlNodePtr node;
g_return_val_if_fail(fname!=NULL,FALSE);
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
@@ -670,17 +668,21 @@ static gboolean read_xml_file(char *fname)
return FALSE;
}
- parse_doc(doc);
+ for(node = doc->children->children; node != NULL; node = node->next) {
+ if ( g_strcasecmp((gchar *)node->name, "Board") == 0 )
+ add_xml_data(doc, node, list);
+ }
xmlFreeDoc(doc);
return TRUE;
}
+
/* ======================================= */
-static void destroy_board_list() {
+void missing_destroy_board_list(GList *list) {
Board *board;
- while(g_list_length(board_list)>0)
+ while(g_list_length(list)>0)
{
- board = g_list_nth_data(board_list, 0);
- board_list = g_list_remove (board_list, board);
+ board = g_list_nth_data(list, 0);
+ list = g_list_remove (list, board);
destroy_board(board);
}
}
@@ -722,14 +724,14 @@ static void save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
if (!table){
- if (gcomprisBoard)
+ if (gcomprisBoard_missing)
pause_board(FALSE);
return NULL;
}
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
- if (gcomprisBoard){
+ if (gcomprisBoard_missing){
gc_locale_reset();
GHashTable *config;
@@ -744,8 +746,6 @@ static GcomprisConfCallback conf_ok(GHashTable *table)
if (profile_conf)
g_hash_table_destroy(config);
- destroy_board_list();
-
init_xml();
missing_letter_next_level();
@@ -754,6 +754,7 @@ static GcomprisConfCallback conf_ok(GHashTable *table)
board_conf = NULL;
profile_conf = NULL;
+ pause_board(FALSE);
return NULL;
}
@@ -765,7 +766,7 @@ config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
- if (gcomprisBoard)
+ if (gcomprisBoard_missing)
pause_board(TRUE);
gchar *label = g_strdup_printf(_("<b>%s</b> configuration\n for profile <b>%s</b>"),
@@ -783,7 +784,7 @@ config_start(GcomprisBoard *agcomprisBoard,
gchar *locale = g_hash_table_lookup( config, "locale");
gc_board_config_combo_locales(bconf, locale);
-
+ config_missing_letter(bconf);
}
diff --git a/src/boards/missingletter_config.c b/src/boards/missingletter_config.c
new file mode 100644
index 0000000..b3600b6
--- /dev/null
+++ b/src/boards/missingletter_config.c
@@ -0,0 +1,599 @@
+#include "gcompris/gcompris.h"
+#include <string.h>
+
+/* from missingletter.c */
+typedef struct _Board Board;
+struct _Board {
+ char *pixmapfile;
+ char *question;
+ char *answer;
+ char *l1;
+ char *l2;
+ char *l3;
+ };
+
+extern GcomprisBoard *gcomprisBoard_missing;
+gboolean missing_read_xml_file(char *fname, GList**);
+void missing_destroy_board_list(GList *);
+
+typedef struct
+ {
+ GtkComboBox *combo_level;
+ GtkTreeView *view;
+
+ GtkFileChooserButton *pixmap;
+ GtkEntry *question, *answer, *choice;
+ gboolean changed;
+ } _config_missing;
+
+enum
+ {
+ QUESTION_COLUMN,
+ ANSWER_COLUMN,
+ CHOICE_COLUMN,
+ PIXMAP_COLUMN,
+ PIXBUF_COLUMN,
+ N_COLUMNS
+ };
+
+#define ICON_SIZE 32
+
+static void new_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+
+ ls = GTK_LIST_STORE(gtk_tree_view_get_model(u->view));
+ gtk_list_store_append(ls, &iter);
+ gtk_list_store_set(ls, &iter,
+ QUESTION_COLUMN, "",
+ ANSWER_COLUMN, "",
+ CHOICE_COLUMN, "",
+ PIXMAP_COLUMN, "",
+ PIXBUF_COLUMN, NULL,
+ -1);
+ GtkTreeSelection* sel = gtk_tree_view_get_selection(u->view);
+ gtk_tree_selection_select_iter(sel , &iter);
+}
+
+static void delete_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+ u->changed = TRUE;
+ }
+}
+
+static gboolean valid_entry(gchar *question, gchar *answer,
+ gchar *choice, gchar *pixmap)
+{
+ gboolean result=FALSE;
+ gchar **split;
+
+ if(choice && question && answer && pixmap &&
+ strlen(choice)==3 && strlen(question) && strlen(answer)
+ && strchr(question, '_'))
+ {
+ split = g_strsplit(question, "_", 2);
+ if(g_str_has_prefix(answer, split[0]) &&
+ g_str_has_suffix(answer, split[1]) &&
+ answer[strlen(split[0])] == choice[0])
+ result = TRUE;
+ g_strfreev(split);
+ }
+ return result;
+}
+
+static void apply_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ const gchar *question, *answer, *choice;
+ gchar *pixmap, *pixfile;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ question = gtk_entry_get_text(u->question);
+ answer = gtk_entry_get_text(u->answer);
+ choice = gtk_entry_get_text(u->choice);
+ pixmap = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(u->pixmap));
+
+ if(valid_entry((gchar*)question, (gchar*) answer, (gchar*)choice, pixmap))
+ {
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ pixfile = gc_cache_import_pixmap(pixmap, "imageid", 300, 300);
+ GdkPixbuf *pixbuf =
+ gdk_pixbuf_new_from_file_at_size(pixmap, ICON_SIZE,
+ ICON_SIZE, NULL);
+
+ gtk_list_store_set(GTK_LIST_STORE(model),&iter,
+ QUESTION_COLUMN, question,
+ ANSWER_COLUMN, answer,
+ CHOICE_COLUMN, choice,
+ PIXMAP_COLUMN, pixfile,
+ PIXBUF_COLUMN, pixbuf,
+ -1);
+ u->changed = TRUE;
+ g_free(pixfile);
+ g_object_unref(pixbuf);
+ }
+ }
+ g_free(pixmap);
+}
+
+static void up_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+ GtkTreeIter itera, iterb;
+ GtkTreeModel *model;
+ GtkTreePath *tpa, *tpb;
+ gchar *pa, *pb;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &itera))
+ {
+ pa = gtk_tree_model_get_string_from_iter(model, &itera);
+ tpa = gtk_tree_path_new_from_string(pa);
+ tpb = gtk_tree_path_copy(tpa);
+ gtk_tree_path_prev(tpb);
+ pb = gtk_tree_path_to_string(tpb);
+ gtk_tree_model_get_iter_from_string(model, &iterb, pb);
+ gtk_list_store_swap(GTK_LIST_STORE(model), &itera, &iterb);
+ gtk_tree_path_free(tpa);
+ gtk_tree_path_free(tpb);
+ g_free(pa);
+ g_free(pb);
+ u->changed = TRUE;
+ }
+}
+
+static void down_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+ GtkTreeIter itera, iterb;
+ GtkTreeModel *model;
+ GtkTreePath *tpa, *tpb;
+ gchar *pa, *pb;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &itera))
+ {
+ pa = gtk_tree_model_get_string_from_iter(model, &itera);
+ tpa = gtk_tree_path_new_from_string(pa);
+ tpb = gtk_tree_path_copy(tpa);
+ gtk_tree_path_next(tpb);
+ pb = gtk_tree_path_to_string(tpb);
+ if(gtk_tree_model_get_iter_from_string(model, &iterb, pb))
+ gtk_list_store_swap(GTK_LIST_STORE(model), &itera, &iterb);
+ gtk_tree_path_free(tpa);
+ gtk_tree_path_free(tpb);
+ g_free(pa);
+ g_free(pb);
+ u->changed = TRUE;
+ }
+}
+
+static gboolean _save(GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+{
+ gchar *question, *answer, *choice, *pixmap;
+ gchar *tmp = NULL;
+ xmlNodePtr root, node;
+
+ gtk_tree_model_get (model, iter,
+ QUESTION_COLUMN, &question,
+ ANSWER_COLUMN, &answer,
+ CHOICE_COLUMN, &choice,
+ PIXMAP_COLUMN, &pixmap,
+ -1);
+ if(valid_entry(question, answer, choice, pixmap))
+ {
+ tmp = g_strdup_printf("%s/%s/%c/%c/%c",
+ answer, question,
+ choice[0], choice[1], choice[2]);
+
+ root =(xmlNodePtr)data;
+ node = xmlNewChild(root, NULL, BAD_CAST "Board", NULL);
+ xmlNewChild(node, NULL,BAD_CAST "pixmapfile", BAD_CAST pixmap);
+ xmlNewChild(node, NULL, BAD_CAST "data", BAD_CAST tmp);
+ }
+ g_free(tmp);
+ g_free(question);
+ g_free(answer);
+ g_free(choice);
+ return FALSE;
+}
+
+static void save_clicked(GtkButton *b, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkTreeModel *model;
+ gchar *filename;
+ xmlNodePtr root;
+ xmlDocPtr doc;
+ int level;
+
+ level = gtk_combo_box_get_active(u->combo_level)+1;
+ if(level==0)
+ return;
+ if(! u->changed)
+ return;
+ model = gtk_tree_view_get_model(u->view);
+ doc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
+ root = xmlNewNode(NULL, BAD_CAST "missing_letter");
+ xmlDocSetRootElement(doc,root);
+
+ gtk_tree_model_foreach(model, _save, root);
+
+ filename =
+ gc_file_find_absolute_writeable("%s/board%d.xml",
+ gcomprisBoard_missing->boarddir, level);
+ if(xmlSaveFormatFileEnc(filename, doc, NULL, 1)<0)
+ g_warning("Fail to write %s", filename);
+ g_free(filename);
+ xmlFreeDoc(doc);
+ u->changed = FALSE;
+}
+
+static void level_changed(GtkComboBox *combo, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+ gchar *filename;
+ GList *list=NULL, *l;
+ gchar *tmp;
+ int level, result;
+
+ level = gtk_combo_box_get_active(u->combo_level)+1;
+ if(level==0)
+ return;
+ if(u->changed)
+ {
+ GtkWidget *dialog;
+
+ dialog = gtk_dialog_new_with_buttons("Save changes ?",
+ NULL,
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch(result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ save_clicked(NULL, data);
+ break;
+ default:
+ u->changed=FALSE;
+ break;
+ }
+ gtk_widget_destroy (dialog);
+ }
+ ls = GTK_LIST_STORE(gtk_tree_view_get_model(u->view));
+ filename = gc_file_find_absolute("%s/board%d.xml",
+ gcomprisBoard_missing->boarddir, level);
+ missing_read_xml_file(filename,&list);
+ g_free(filename);
+ gtk_list_store_clear(ls);
+ for(l=list; l; l=l->next)
+ {
+ Board *b = l->data;
+ gchar *pixfile = gc_file_find_absolute(b->pixmapfile);
+ GdkPixbuf *pixbuf;
+
+ pixbuf =
+ gdk_pixbuf_new_from_file_at_size(pixfile, ICON_SIZE, ICON_SIZE,
+ NULL);
+
+ tmp = g_strdup_printf("%s%s%s", b->l1, b->l2, b->l3);
+
+ gtk_list_store_append(ls, &iter);
+ gtk_list_store_set(ls, &iter,
+ QUESTION_COLUMN, b->question,
+ ANSWER_COLUMN, b->answer,
+ CHOICE_COLUMN, tmp,
+ PIXMAP_COLUMN, b->pixmapfile,
+ PIXBUF_COLUMN, pixbuf,
+ -1);
+ g_free(tmp);
+ g_free(pixfile);
+ g_object_unref(pixbuf);
+ }
+ missing_destroy_board_list(list);
+}
+
+static void text_changed(GtkWidget *widget, gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+
+ const gchar *question, *answer, *choice;
+
+ question = gtk_entry_get_text(u->question);
+ answer = gtk_entry_get_text(u->answer);
+ choice = gtk_entry_get_text(u->choice);
+
+ if(widget == (GtkWidget*)u->answer)
+ {
+ if(g_str_has_prefix(answer,question))
+ {
+ gtk_entry_set_text(u->question,answer);
+ }
+ }
+ else if(widget ==(GtkWidget*) u->question)
+ {
+ if(strchr(question, '_'))
+ {
+ gchar ** split = g_strsplit(question,"_",2);
+ if(answer[strlen(split[0])]!= choice[0])
+ {
+ gchar *tmp;
+ tmp = g_new0(gchar, 4);
+ tmp[0]= answer[strlen(split[0])];
+ gtk_entry_set_text(u->choice, tmp);
+ g_free(tmp);
+ }
+ g_strfreev(split);
+ }
+ }
+}
+
+void selection_changed (GtkTreeSelection *selection,gpointer data)
+{
+ _config_missing *u = (_config_missing*)data;
+ gchar *question, *answer, *choice, *pixmap, *pixfile;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ QUESTION_COLUMN, &question,
+ ANSWER_COLUMN, &answer,
+ CHOICE_COLUMN, &choice,
+ PIXMAP_COLUMN, &pixmap,
+ -1);
+ gtk_entry_set_text(u->question, question);
+ gtk_entry_set_text(u->answer, answer);
+ gtk_entry_set_text(u->choice, choice);
+ pixfile = gc_file_find_absolute(pixmap);
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(u->pixmap), pixfile);
+
+ g_free(question);
+ g_free(answer);
+ g_free(choice);
+ g_free(pixmap);
+ g_free(pixfile);
+ }
+}
+
+void destroy_conf_data(void *not_used, gpointer *data)
+{
+ g_free(data);
+}
+
+static void configure_colummns(GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* pixbuf column */
+ renderer = gtk_cell_renderer_pixbuf_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Pixbuf"),
+ renderer, "pixbuf", PIXBUF_COLUMN, NULL);
+ gtk_tree_view_append_column(treeview, column);
+
+ /* Answer column */
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Answer"),
+ renderer, "text", ANSWER_COLUMN, NULL);
+ gtk_tree_view_append_column(treeview, column);
+
+ /* Question column */
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Question"),
+ renderer, "text", QUESTION_COLUMN, NULL);
+ gtk_tree_view_append_column(treeview, column);
+
+ /* Choice column */
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Choice"),
+ renderer, "text", CHOICE_COLUMN, NULL);
+ gtk_tree_view_append_column(treeview, column);
+#if 0
+ /* pixmap column */
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Pixmap"),
+ renderer, "text", PIXMAP_COLUMN, NULL);
+ gtk_tree_view_append_column(treeview, column);
+#endif
+}
+
+ void config_missing_letter(GcomprisBoardConf *config)
+ {
+ GtkWidget *frame, *view, *pixmap, *question, *answer, *choice;
+ GtkWidget *level, *vbox, *hbox, *label;
+ GtkWidget *bbox, *button, *table;
+ GtkFileFilter *file_filter;
+ _config_missing *conf_data;
+ int i;
+
+ conf_data = g_new0(_config_missing,1);
+
+ /* frame */
+ frame = gtk_frame_new("");
+ gtk_widget_show(frame);
+ gtk_box_pack_start(GTK_BOX(config->main_conf_box), frame, TRUE, TRUE, 8);
+
+ vbox = gtk_vbox_new(FALSE, 8);
+ gtk_widget_show(vbox);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ /* hbox */
+ hbox = gtk_hbox_new(FALSE, 8);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 8);
+
+ /* combo level */
+ label = gtk_label_new(_("Choice of the level"));
+ gtk_widget_show(label);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
+
+ level = gtk_combo_box_new_text();
+ for(i=1; i< gcomprisBoard_missing->maxlevel; i++)
+ {
+ gchar *tmp;
+ tmp = g_strdup_printf(_("Level %d"), i);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(level), tmp);
+ g_free(tmp);
+ }
+ gtk_widget_show(level);
+ gtk_box_pack_start(GTK_BOX(hbox), level, FALSE, FALSE, 8);
+
+ /* list view */
+ GtkListStore *list = gtk_list_store_new(N_COLUMNS,
+ G_TYPE_STRING, /*Question */
+ G_TYPE_STRING, /* Answer */
+ G_TYPE_STRING, /* Choice */
+ G_TYPE_STRING, /* pixmap */
+ GDK_TYPE_PIXBUF /* pixbuf */
+ );
+
+ view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+ configure_colummns(GTK_TREE_VIEW(view));
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (view), ANSWER_COLUMN);
+ gtk_widget_set_size_request(view, -1, 200);
+ gtk_widget_show(view);
+
+ GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL,NULL));
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_widget_show(GTK_WIDGET(scroll));
+ gtk_container_add(GTK_CONTAINER(scroll), view);
+
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scroll), TRUE, TRUE, 10);
+
+ /* button box */
+ bbox = gtk_hbutton_box_new();
+ gtk_widget_show(bbox);
+ gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 8);
+ button = gtk_button_new_from_stock(GTK_STOCK_NEW);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(new_clicked), (gpointer) conf_data);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(delete_clicked), (gpointer) conf_data);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(apply_clicked), (gpointer) conf_data);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(up_clicked), (gpointer) conf_data);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(down_clicked), (gpointer) conf_data);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(save_clicked), (gpointer) conf_data);
+
+ /* table */
+ table = gtk_table_new(2, 4, FALSE);
+ gtk_widget_show(table);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 8);
+
+ /* answer */
+ label = gtk_label_new(_("Answer"));
+ gtk_widget_show(label);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+
+ answer = gtk_entry_new();
+ gtk_widget_show(answer);
+ gtk_table_attach_defaults(GTK_TABLE(table), answer, 1, 2, 0, 1);
+
+ /* pixmap */
+ label = gtk_label_new(_("Picture"));
+ gtk_widget_show(label);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 0, 1);
+
+ pixmap = gtk_file_chooser_button_new(_("Choice of the filename"),
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+
+ file_filter = gtk_file_filter_new();
+ gtk_file_filter_add_pixbuf_formats(file_filter);
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(pixmap), file_filter);
+ gtk_widget_show(pixmap);
+ gtk_table_attach_defaults(GTK_TABLE(table), pixmap, 3, 4, 0, 1);
+
+ /* question */
+ label = gtk_label_new(_("Question"));
+ gtk_widget_show(label);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+
+ question = gtk_entry_new();
+ gtk_widget_show(question);
+ gtk_table_attach_defaults(GTK_TABLE(table), question, 1, 2, 1, 2);
+
+ /* choice */
+ label = gtk_label_new(_("Choice"));
+ gtk_widget_show(label);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 1, 2);
+
+ choice = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(choice), 3);
+ gtk_widget_show(choice);
+ gtk_table_attach_defaults(GTK_TABLE(table), choice, 3, 4, 1, 2);
+
+ conf_data -> combo_level = GTK_COMBO_BOX(level);
+ conf_data -> view = GTK_TREE_VIEW(view);
+ conf_data -> pixmap = GTK_FILE_CHOOSER_BUTTON(pixmap);
+ conf_data -> question = GTK_ENTRY(question);
+ conf_data -> answer = GTK_ENTRY(answer);
+ conf_data -> choice = GTK_ENTRY(choice);
+
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+
+ g_signal_connect(G_OBJECT(selection),
+ "changed",
+ G_CALLBACK(selection_changed),
+ (gpointer) conf_data);
+ g_signal_connect(G_OBJECT(frame), "destroy",
+ G_CALLBACK(destroy_conf_data), (gpointer) conf_data);
+ g_signal_connect(G_OBJECT(level), "changed",
+ G_CALLBACK(level_changed), (gpointer) conf_data);
+ g_signal_connect(G_OBJECT(question), "changed",
+ G_CALLBACK(text_changed), (gpointer) conf_data);
+ g_signal_connect(G_OBJECT(answer), "changed",
+ G_CALLBACK(text_changed), (gpointer) conf_data);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(level), 0);
+ level_changed(GTK_COMBO_BOX(level),conf_data);
+ }
+
diff --git a/src/boards/python/admin/board_list.py b/src/boards/python/admin/board_list.py
index f29a448..4408dd2 100644
--- a/src/boards/python/admin/board_list.py
+++ b/src/boards/python/admin/board_list.py
@@ -167,13 +167,6 @@ class Board_list:
self.button_locales_sound.show()
box3.pack_end(self.button_locales_sound, False, False, 0)
- self.button_wordlist = gtk.Button(_('Wordlist'))
- self.button_wordlist.connect("clicked", self.wordlist)
- self.button_wordlist.show()
- box3.pack_end(self.button_wordlist, False, False, 0)
- #not ready yet
- self.button_wordlist.set_sensitive(False)
-
self.button_login = gtk.Button(_('Login'))
self.button_login.connect("clicked", self.login_configure)
self.button_login.show()
diff --git a/src/boards/read_colors.c b/src/boards/read_colors.c
index 67dc229..b6e3c7e 100644
--- a/src/boards/read_colors.c
+++ b/src/boards/read_colors.c
@@ -473,7 +473,7 @@ static gboolean read_xml_file(char *fname)
g_return_val_if_fail(fname!=NULL,FALSE);
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
diff --git a/src/boards/reading.c b/src/boards/reading.c
index 49210fc..f530f3c 100644
--- a/src/boards/reading.c
+++ b/src/boards/reading.c
@@ -458,7 +458,15 @@ static gboolean reading_create_item(GnomeCanvasGroup *parent)
word = g_strdup(textToFind);
}
- g_assert(word!=NULL);
+ if(word==NULL)
+ {
+ gc_dialog(_("Skip this level. Not enough word in the list !"),
+ (DialogBoxCallBack)reading_next_level);
+ gcomprisBoard->level++;
+ if(gcomprisBoard->level>gcomprisBoard->maxlevel) // the current board is finished : bail out
+ gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
+ return FALSE;
+ }
if(textToFindIndex>=0)
textToFindIndex--;
@@ -777,6 +785,7 @@ static gchar *
get_random_word(const gchar* except)
{
gchar *word;
+ int count=0;
word = gc_wordlist_random_word_get(gc_wordlist, gcomprisBoard->level);
@@ -784,6 +793,12 @@ get_random_word(const gchar* except)
while(strcmp(except, word)==0)
{
g_free(word);
+
+ if(count++>100)
+ {
+ word = NULL;
+ break;
+ }
word = gc_wordlist_random_word_get(gc_wordlist, gcomprisBoard->level);
}
diff --git a/src/boards/shapegame.c b/src/boards/shapegame.c
index fd68350..3fdb49e 100644
--- a/src/boards/shapegame.c
+++ b/src/boards/shapegame.c
@@ -1743,7 +1743,7 @@ read_xml_file(char *fname)
g_return_val_if_fail(fname!=NULL,FALSE);
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
return FALSE;
diff --git a/src/boards/superbrain.c b/src/boards/superbrain.c
index 88295b1..f61015b 100644
--- a/src/boards/superbrain.c
+++ b/src/boards/superbrain.c
@@ -618,6 +618,10 @@ static void mark_pieces()
current_y_position -= Y_STEP;
+ GList *l;
+ for(l=listPieces; l; l= l->next)
+ g_free(l->data);
+
g_list_free(listPieces);
superbrain_create_item(boardRootItem);
diff --git a/src/boards/wordprocessor.c b/src/boards/wordprocessor.c
index 3420099..133077c 100644
--- a/src/boards/wordprocessor.c
+++ b/src/boards/wordprocessor.c
@@ -1027,7 +1027,7 @@ load_buffer(gchar *file, gchar *file_type)
GtkTextIter iter_start, iter_end;
/* parse the new file and put the result into newdoc */
- doc = gc_net_load_xml(file);
+ doc = xmlParseFile(file);
/* in case something went wrong */
if(!doc)
diff --git a/src/gcompris/Makefile.am b/src/gcompris/Makefile.am
index c4707ed..d6ebad3 100644
--- a/src/gcompris/Makefile.am
+++ b/src/gcompris/Makefile.am
@@ -77,7 +77,6 @@ gcompris_SOURCES = \
board_config.h board_config.c \
bonus.c \
bonus.h \
- cache.c \
config.c \
dialog.c \
drag.c \
diff --git a/src/gcompris/board_config_wordlist.c b/src/gcompris/board_config_wordlist.c
index c0dd7c1..a6364b2 100644
--- a/src/gcompris/board_config_wordlist.c
+++ b/src/gcompris/board_config_wordlist.c
@@ -49,7 +49,7 @@ static void _combo_level_changed(GtkComboBox *combo_level, gpointer user_data)
}
wordsArray = g_malloc0(sizeof(gpointer)*(g_slist_length(lw->words)+1));
-
+
for(i=0, list = lw->words; list; list=list->next)
{
wordsArray[i]=(gchar*)list->data;
@@ -118,6 +118,22 @@ static void _textview_changed(GtkWidget *w, gpointer data)
gtk_widget_set_sensitive(GTK_WIDGET(u->button), TRUE);
}
+static void _return_clicked(GtkWidget *w, gpointer data)
+{
+ int level;
+ user_param_type_wordlist *u = (user_param_type_wordlist*)data;
+ gchar *filename;
+
+ filename = gc_file_find_absolute_writeable(u->wordlist->filename);
+ gc_cache_remove(filename);
+ g_free(filename);
+
+ level = gtk_combo_box_get_active(u->combo_level)+1;
+ _combo_lang_changed(u->combo_lang, u);
+ gtk_combo_box_set_active(u->combo_level, level-1);
+ _combo_level_changed(u->combo_level, u);
+}
+
static void _button_clicked(GtkWidget *w, gpointer data)
{
user_param_type_wordlist *u = (user_param_type_wordlist*)data;
@@ -143,7 +159,7 @@ static void _button_clicked(GtkWidget *w, gpointer data)
static void _destroy(GtkWidget *w, gpointer data)
{
user_param_type_wordlist *u = (user_param_type_wordlist*)data;
-
+
gc_wordlist_free(u->wordlist);
g_free(u);
}
@@ -161,7 +177,7 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
const gchar *locale;
/* frame */
- frame = gtk_frame_new("Change wordlist");
+ frame = gtk_frame_new(_("Configure the list of words"));
gtk_widget_show(frame);
gtk_box_pack_start(GTK_BOX(config->main_conf_box), frame, FALSE, FALSE, 8);
@@ -190,7 +206,7 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
gtk_widget_show(combo_lang);
hbox = gtk_hbox_new(FALSE, 8);
- label = gtk_label_new(_("Choice language"));
+ label = gtk_label_new(_("Choice of the language"));
gtk_widget_show(label);
gtk_widget_show(hbox);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
@@ -202,7 +218,7 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
gtk_widget_show(combo_level);
hbox = gtk_hbox_new(FALSE, 8);
- label = gtk_label_new(_("Choice level"));
+ label = gtk_label_new(_("Choice of the level"));
gtk_widget_show(label);
gtk_widget_show(hbox);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
@@ -223,10 +239,18 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
gtk_container_add (GTK_CONTAINER(scroll), textview);
/* valid button */
+ hbox = gtk_hbox_new(FALSE, 8);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 8);
+
+ GtkWidget * b_default = gtk_button_new_with_label(_("Back to default"));
+ gtk_widget_show(b_default);
+ gtk_box_pack_start(GTK_BOX(hbox), b_default, FALSE, FALSE, 8);
+
button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
gtk_widget_show(button);
gtk_widget_set_sensitive(button, FALSE);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 8);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 8);
/* user_data */
user_data = g_malloc0(sizeof(user_param_type_wordlist));
@@ -246,6 +270,8 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
G_CALLBACK(_textview_changed), (gpointer)user_data);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(_button_clicked), (gpointer)user_data);
+ g_signal_connect(G_OBJECT(b_default), "clicked",
+ G_CALLBACK(_return_clicked), (gpointer)user_data);
_combo_lang_changed(GTK_COMBO_BOX(combo_lang), user_data);
diff --git a/src/gcompris/cache.c b/src/gcompris/cache.c
deleted file mode 100644
index 5eac982..0000000
--- a/src/gcompris/cache.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* gcompris - gameutil_net.c
- *
- * Time-stamp: <2006/07/10 01:24:04 bruno>
- *
- * Copyright (C) 2006 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "gcompris.h"
-#include "gc_core.h"
-#include <string.h>
-
-/** \file Implementation of the cache functionality
- *
- */
-
-/* The max size of the cache in bytes,
- * 0 = NO LIMITS
- * -1 = NO CACHE
- */
-#ifdef USE_GNET
-static int cache_max_size = 1000;
-
-static GHashTable *hash_cache = NULL;
-#endif
-
-/** For debug only
- */
-#ifdef USE_GNET
-static void
-_dump_cache(gchar *key,
- gchar *value,
- gpointer dummy)
-{
- printf("cache %s = %s\n", key, value);
-}
-
-static void dump_cache(void)
-{
- g_hash_table_foreach(hash_cache,
- (GHFunc) _dump_cache,
- NULL);
-}
-#endif
-
-/**
- * recursively parse the cache and fill up the hash with files there
- */
-void _cache_init(const gchar *basedir, const gchar *currentdir)
-{
-#ifdef USE_GNET
- GcomprisProperties *properties = gc_prop_get();
- GDir *dir;
- const gchar *file;
-
- if(!currentdir)
- currentdir = basedir;
-
- dir = g_dir_open(currentdir, 0, NULL);
-
- printf(" _cache_init %s\n", currentdir);
-
- while((file = g_dir_read_name(dir)))
- {
- gchar *fullfile = g_strconcat(currentdir, "/", file, NULL);
- printf(" processing file = %s\n", fullfile);
-
- if(g_file_test(fullfile, G_FILE_TEST_IS_DIR))
- {
- _cache_init(basedir, fullfile);
- }
- else if(g_file_test(fullfile, G_FILE_TEST_IS_REGULAR))
- {
- /* Strip file to get the KEY part out of it */
- printf(" Adding '%s' in the cache\n", fullfile);
- g_hash_table_insert(hash_cache,
- g_strconcat(properties->server, "/",
- fullfile + strlen(basedir) + 1,
- NULL),
- g_strdup(fullfile));
-
- }
- g_free(fullfile);
- }
-
- g_dir_close(dir);
-#endif
-}
-
-/** Initialize the cache system
- *
- * \param max_size: the max size in byte of the cache
- *
- */
-void gc_cache_init(int max_size)
-{
-#ifdef USE_GNET
- cache_max_size = max_size;
-
- /* No server defined, the cache is useless */
- if(!gc_prop_get()->server ||
- !gc_prop_get()->cache_dir)
- return;
-
- hash_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
- printf("gc_cache_init\n");
-
- /* try to create it */
- printf("Creating cache dir %s\n", gc_prop_get()->cache_dir);
- if(g_mkdir_with_parents(gc_prop_get()->cache_dir, 0755))
- {
- g_error("Failed to create the cache directory");
- }
- printf(" opened top directory\n");
- /* Load the previous cache directory if any */
- _cache_init(gc_prop_get()->cache_dir, NULL);
-
- dump_cache();
-#endif
-}
-
-/** End the cache system
- *
- */
-void gc_cache_end()
-{
-#ifdef USE_GNET
-
- if(!hash_cache)
- return;
-
- g_hash_table_destroy (hash_cache);
- hash_cache = NULL;
-#endif
-}
-
-
-#ifdef USE_GNET
-static void
-_clear_cache(gchar *key,
- gchar *value,
- gpointer dummy)
-{
- printf("NOT IMPLEMENTED: Clearing chache %s:%s\n", key, value);
-}
-#endif
-
-/** Clear the cache. All files in the cache are removed
- *
- */
-void gc_cache_clear()
-{
-#ifdef USE_GNET
- g_hash_table_foreach(hash_cache,
- (GHFunc) _clear_cache,
- NULL);
-
-#endif
-}
-
-/** Get a file from the cache based on it's URL
- *
- */
-gchar *gc_cache_get(gchar *url)
-{
-#ifdef USE_GNET
- return((char *)g_hash_table_lookup(hash_cache, url));
-#else
- return NULL;
-#endif
-}
-
-/** Put and Get a file from the cache. The data in 'buffer' are saved in the
- * cache under the name 'url'. A file is created and is returned.
- *
- * \param url: the url of the data in buffer
- * \param buffer: the data for the url
- * \param length: length of contents, or -1 if contents is a nul-terminated string
- *
- * \return a full path to the file in the cache
- */
-gchar *gc_cache_insert(const gchar *url, const char *buffer, gssize length)
-{
-#ifdef USE_GNET
- /* Save the buffer in the cache */
- if(g_file_set_contents("TBD", buffer, length, NULL))
- g_hash_table_replace(hash_cache, (gpointer) url, (gpointer) "TBD");
-#endif
- return("TBD");
-}
diff --git a/src/gcompris/config.c b/src/gcompris/config.c
index 18e18a3..3873a0e 100644
--- a/src/gcompris/config.c
+++ b/src/gcompris/config.c
@@ -630,7 +630,7 @@ set_locale_flag(gchar *locale)
if(filename)
{
- pixmap = gc_net_load_pixmap(filename);
+ pixmap = gdk_pixbuf_new_from_file(filename,NULL);
gnome_canvas_item_set (item_locale_flag,
"pixbuf", pixmap,
diff --git a/src/gcompris/dialog.c b/src/gcompris/dialog.c
index b28ec10..9c89f25 100644
--- a/src/gcompris/dialog.c
+++ b/src/gcompris/dialog.c
@@ -27,9 +27,6 @@ static GnomeCanvasGroup *rootDialogItem = NULL;
static GnomeCanvasItem *itemDialogText = NULL;
static gint item_event_ok(GnomeCanvasItem *item, GdkEvent *event, DialogBoxCallBack dbcb);
-typedef void (*sighandler_t)(int);
-
-
/*
* Close the dialog box if it was open. It not, do nothing.
*/
diff --git a/src/gcompris/gameutil.c b/src/gcompris/gameutil.c
index db4c416..efccb69 100644
--- a/src/gcompris/gameutil.c
+++ b/src/gcompris/gameutil.c
@@ -32,10 +32,6 @@
#include "gcompris.h"
-extern GnomeCanvas *canvas;
-
-typedef void (*sighandler_t)(int);
-
/* GdkPixbuf RGBA C-Source image dump for a NULL image*/
#ifdef __SUNPRO_C
#pragma align 4 (null_img)
@@ -87,7 +83,7 @@ GdkPixbuf *gc_pixmap_load(const gchar *format, ...)
filename = gc_file_find_absolute(pixmapfile);
if(filename)
- pixmap = gc_net_load_pixmap(filename);
+ pixmap = gdk_pixbuf_new_from_file(filename,NULL);
if (!filename || !pixmap)
{
@@ -542,8 +538,7 @@ gc_file_find_absolute(const gchar *format, ...)
va_end (args);
/* Check it's already found */
- if( g_file_test (filename, G_FILE_TEST_EXISTS)
- || gc_net_is_url(filename) )
+ if( g_file_test (filename, G_FILE_TEST_EXISTS))
{
return filename;
}
@@ -552,6 +547,9 @@ gc_file_find_absolute(const gchar *format, ...)
* Search it on the file system
*/
+ if(properties->server)
+ dir_to_search[i++] = "";
+ dir_to_search[i++] = properties->user_dir;
dir_to_search[i++] = properties->package_data_dir;
dir_to_search[i++] = NULL;
@@ -602,6 +600,7 @@ gc_file_find_absolute(const gchar *format, ...)
g_free(filename2);
goto FOUND;
}
+ g_free(absolute_filename);
/* Now check if this file is on the net */
if((absolute_filename = gc_net_get_url_from_file(filename2, NULL)))
@@ -640,6 +639,35 @@ gc_file_find_absolute(const gchar *format, ...)
return absolute_filename;
}
+gchar*
+gc_file_find_absolute_writeable(const gchar *format, ...)
+{
+ gchar *filename, *absolute_filename, *dirname;
+ GcomprisProperties *prop;
+ va_list args;
+
+ va_start (args, format);
+ filename = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ prop = gc_prop_get();
+ absolute_filename = g_build_filename(prop->user_dir, filename,NULL);
+ g_free(filename);
+ dirname = g_path_get_dirname(absolute_filename);
+ if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
+ {
+ if(g_mkdir_with_parents(dirname, 0755))
+ {
+ g_free(absolute_filename);
+ absolute_filename=NULL;
+ }
+ }
+ g_free(dirname);
+ if(absolute_filename)
+ gc_cache_add(absolute_filename);
+ return absolute_filename;
+}
+
/** Create a directory if needed.
*
* \param rootdir: the directory to create
diff --git a/src/gcompris/gameutil.h b/src/gcompris/gameutil.h
index d82a100..d838508 100644
--- a/src/gcompris/gameutil.h
+++ b/src/gcompris/gameutil.h
@@ -63,6 +63,7 @@ GnomeCanvasGroup *gc_difficulty_display(GnomeCanvasGroup *parent, double x, doub
/* find the complete filename looking for the file everywhere (printf formatting supported) */
gchar *gc_file_find_absolute(const gchar *filename, ...);
+gchar *gc_file_find_absolute_writeable(const gchar *filename, ...);
int gc_util_create_rootdir (gchar *rootdir);
void gc_activity_intro_play (GcomprisBoard *gcomprisBoard);
diff --git a/src/gcompris/gc_core.h b/src/gcompris/gc_core.h
index 9a80cb2..b5d4a72 100644
--- a/src/gcompris/gc_core.h
+++ b/src/gcompris/gc_core.h
@@ -49,11 +49,4 @@ void gc_mime_type_load();
/** log */
void gc_log_start (GcomprisBoard *gcomprisBoard);
-/** cache */
-void gc_cache_init(int max_size);
-void gc_cache_end();
-void gc_cache_clear();
-gchar *gc_cache_get(gchar *url);
-gchar *gc_cache_insert(const gchar *url, const char *buffer, gssize length);
-
#endif
diff --git a/src/gcompris/gc_net.c b/src/gcompris/gc_net.c
index 385a67b..455f925 100644
--- a/src/gcompris/gc_net.c
+++ b/src/gcompris/gc_net.c
@@ -21,10 +21,11 @@
#include "gc_net.h"
#include "gc_core.h"
-
+#include <string.h>
#ifdef USE_GNET
#include <gnet.h>
#endif
+#include <glib/gstdio.h>
/* FIXME: Should not be needed, a bug in gnet header ? */
gboolean gnet_http_get (const gchar *url,
@@ -32,17 +33,33 @@ gboolean gnet_http_get (const gchar *url,
gsize *length,
guint *response);
-#include <string.h>
-
#ifdef USE_GNET
-static GSList *server_content_list = NULL;
+static GHashTable *server_content = NULL;
#define SUPPORT_OR_RETURN(rv) {if(!gc_prop_get()->server) return rv;}
#else
#define SUPPORT_OR_RETURN(rv) { return rv; }
#endif
+static void load_md5file(GHashTable *ht, gchar *content)
+{
+ gchar **lines, **keyval;
+ int i;
-static inline int my_strcmp(gchar *a, gchar *b) { return strcmp( a, b); }
+ lines = g_strsplit(content, "\n", 0);
+ if(lines && lines[0])
+ {
+ for(i=0; lines[i]; i++)
+ {
+ keyval = g_strsplit(lines[i], " ", 2);
+ if(keyval && keyval[0])
+ {
+ g_hash_table_insert(ht, g_strdup(keyval[1]), g_strdup(keyval[0]));
+ }
+ g_strfreev(keyval);
+ }
+ }
+ g_strfreev(lines);
+}
/** Init the network library, must be called once before using it
*
@@ -70,15 +87,8 @@ void gc_net_init()
if(gnet_http_get(url, &buf, &buflen, &response) && response == 200)
{
- char line[200];
- int i = 0;
- /* Parse each line of the buffer and save it in 'server_content_list' */
- while( i < buflen)
- {
- sscanf(buf+i, "%s", (char *)&line);
- server_content_list = g_slist_prepend(server_content_list, g_strdup(line));
- i+=strlen(line)+1;
- }
+ server_content = g_hash_table_new(g_str_hash, g_str_equal);
+ load_md5file(server_content, buf);
}
else
{
@@ -93,81 +103,11 @@ void gc_net_init()
#endif
}
-/** Load a pixmap localy or from the network
- *
- * \param pixmapfile : a full URL to the file to load as an image
- * in case a local file is given, it will be loaded.
- * \return a GdkPixbuf or NULL
- */
-GdkPixbuf *gc_net_load_pixmap(const char *url)
-{
- if(!gc_net_is_url(url))
- return(gdk_pixbuf_new_from_file (url, NULL));
-
- SUPPORT_OR_RETURN(NULL);
-
-#ifdef USE_GNET
- gchar *buf = NULL;
- gsize buflen;
- guint response;
-
- g_warning("Loading image from url '%s'", url);
-
- if(gnet_http_get(url, &buf, &buflen, &response) && response == 200)
- {
- GdkPixbuf *pixmap=NULL;
- GdkPixbufLoader* loader;
- loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader, (guchar *)buf, buflen, NULL);
- g_free(buf);
- gdk_pixbuf_loader_close(loader, NULL);
- pixmap = gdk_pixbuf_loader_get_pixbuf(loader);
- if(!pixmap)
- g_warning("Loading image from url '%s' returned a null pointer", url);
-
- return(pixmap);
- }
-
- g_free(buf);
- return(NULL);
-
-#endif
-}
-
-/** Load an xml file from the network
- *
- * \param xmlfile : a full URL to the xml file to load as an xmlDocPtr
- * in case a local file is given, it will be loaded.
- * \return a xmlDocPtr or NULL
- */
-xmlDocPtr gc_net_load_xml(const char *url)
+void gc_net_destroy(void)
{
- if(!gc_net_is_url(url))
- return(xmlParseFile(url));
-
- SUPPORT_OR_RETURN(NULL);
-
-#ifdef USE_GNET
- gchar *buf = NULL;
- gsize buflen;
- guint response;
-
- g_warning("Loading xml file from url '%s'", url);
-
- if(gnet_http_get(url, &buf, &buflen, &response) && response == 200)
- {
- xmlDocPtr doc = xmlParseMemory((const char *)buf, buflen);
- g_free(buf);
- if(!buf)
- g_warning("Loading xml file from url '%s' returned a null pointer", url);
-
- return(doc);
- }
-
- g_free(buf);
- return(NULL);
-
-#endif
+ if(server_content)
+ g_hash_table_destroy(server_content);
+ server_content = NULL;
}
/** return an absolute URL if the given file is part of the file available on our server
@@ -182,51 +122,70 @@ gc_net_get_url_from_file(const gchar *format, ...)
#ifdef USE_GNET
GcomprisProperties *properties = gc_prop_get();
- gchar *file, *url;
+ gchar *file, *cache=NULL, *value;
va_list args;
+ gboolean cache_ok=FALSE;
va_start (args, format);
file = g_strdup_vprintf (format, args);
va_end (args);
- /* FIXME: In case the file does not starts with boards/, preprend it */
+ g_warning("gc_net_get_url_from_file '%s'", file);
+
+ value = g_hash_table_lookup(server_content, (gpointer) file);
+ if(value)
{
- if(strncmp(file, "boards/", 7))
- {
- gchar *file2 = g_strconcat("boards/", file, NULL);
- g_free(file);
- file = file2;
- }
- }
+ cache = g_strconcat(properties->cache_dir, "/", file, NULL);
+ if(g_file_test(cache, G_FILE_TEST_IS_REGULAR))
+ {
+ gchar * content;
+ gsize length;
+ GMD5 *md5cache, *md5serv;
- g_warning("gc_net_get_url_from_file '%s'", file);
- if(!g_slist_find_custom(server_content_list,(gconstpointer) file, (GCompareFunc) my_strcmp))
+ /* calc md5 of cache file */
+ g_file_get_contents(cache, &content, &length, NULL);
+ md5cache = gnet_md5_new(content, length);
+ g_free(content);
+
+ md5serv = gnet_md5_new_string(value);
+
+ cache_ok = gnet_md5_equal(md5serv, md5cache);
+
+ gnet_md5_delete(md5serv);
+ gnet_md5_delete(md5cache);
+ }
+ if(cache_ok==0)
{
- g_free(file);
- return NULL;
+ gchar *url;
+ gchar *buf = NULL;
+ gsize buflen;
+ guint response;
+
+ url = g_strconcat(properties->server, "/", file, NULL);
+ if(gnet_http_get(url, &buf, &buflen, &response) && response == 200)
+ {
+ gchar *dirname;
+
+ dirname = g_path_get_dirname(cache);
+ g_mkdir_with_parents(dirname, 0755);
+ g_free(dirname);
+ g_file_set_contents(cache, buf, buflen, NULL);
+ g_free(buf);
+ }
+ else
+ { /* file is in content.txt but not in server */
+ g_free(cache);
+ cache = NULL;
+ }
}
- url = g_strconcat(properties->server, "/", file, NULL);
+ }
g_free(file);
- g_warning("gc_net_get_url_from_file returns url '%s'", url);
- return url;
+ return cache;
#endif
}
-/** return TRUE if the url starts with http://
- *
- * \param url: an url to check
- * \return TRUE is the url starts with 'http://'
- */
-gboolean
-gc_net_is_url(const gchar *url)
-{
- if( !url || strncmp(url, "http://", 7) )
- return FALSE;
-
- return TRUE;
-}
-
+#if 0
/** return a glist with the content of the files in the given directory
*
* \param dir: the directory to scan
@@ -256,3 +215,157 @@ GSList *gc_net_dir_read_name(const gchar* dir, const gchar *ext)
return(filelist);
#endif
}
+#endif
+
+
+#define CONTENT_FILENAME "content.txt"
+
+static GHashTable *cache_content=NULL;
+
+void gc_cache_init(void)
+{
+ gchar *filename;
+ gchar *buf;
+ gsize buflen;
+
+ cache_content = g_hash_table_new(g_str_hash, g_str_equal);
+ filename = gc_file_find_absolute_writeable(CONTENT_FILENAME);
+
+ if(g_file_get_contents(filename, &buf, &buflen,NULL))
+ {
+ load_md5file(cache_content, buf);
+ g_free(buf);
+ }
+ g_free(filename);
+}
+
+static gchar *gc_cache_get_relative(gchar *filename)
+{
+ gchar *filename_content, *dirname;
+
+ filename_content = gc_file_find_absolute_writeable(CONTENT_FILENAME);
+ dirname = g_path_get_dirname(filename_content);
+ if(g_str_has_prefix(filename, dirname))
+ filename = filename + strlen(dirname) + 1;
+ g_free(filename_content);
+ g_free(dirname);
+ return filename;
+}
+
+void gc_cache_add(gchar *filename)
+{
+ if(cache_content==NULL)
+ return;
+ if(g_str_has_suffix(filename, CONTENT_FILENAME))
+ return;
+
+ filename = gc_cache_get_relative(filename);
+ g_hash_table_insert(cache_content, g_strdup(filename), g_strdup("0"));
+}
+
+gchar* gc_cache_import_pixmap(gchar *filename, gchar *boarddir, gint width, gint height)
+{
+ GdkPixbuf *pixmap;
+ gchar *basename, *file, *ext, *name, *abs;
+
+ if(!g_path_is_absolute(filename))
+ return g_strdup(filename);
+ basename = g_path_get_basename(filename);
+ name = g_build_filename(boarddir, basename,NULL);
+ abs = gc_file_find_absolute(name);
+ if(abs && strcmp(abs,filename)==0)
+ {
+ g_free(basename);
+ g_free(abs);
+ return name;
+ }
+ pixmap = gdk_pixbuf_new_from_file_at_size(filename, width, height,NULL);
+ if(!pixmap)
+ {
+ g_free(abs);
+ g_free(basename);
+ g_free(name);
+ return NULL;
+ }
+
+ file = gc_file_find_absolute_writeable(name);
+ ext = strchr(basename, '.')+1;
+ if(strcmp(ext, "jpg")==0)
+ ext ="jpeg";
+
+ gdk_pixbuf_save(pixmap, file, ext, NULL,NULL);
+
+ g_free(abs);
+ g_free(basename);
+ g_free(file);
+ return name;
+}
+
+void gc_cache_remove(gchar *filename)
+{
+ g_remove(filename);
+ filename = gc_cache_get_relative(filename);
+ g_hash_table_remove(cache_content, filename);
+}
+
+struct _table_data
+{
+FILE *pf;
+gchar *path;
+};
+
+static void _table_foreach(gpointer key, gpointer value, gpointer user_data)
+{
+ struct _table_data *data = (struct _table_data*)user_data;
+ gchar * content, *filename;
+ gsize length;
+ GMD5 *md5;
+
+ if(strcmp(value, "0")==0)
+ {
+ filename = g_build_filename(data->path, (gchar*)key, NULL);
+ if(g_file_get_contents(filename, &content, &length, NULL))
+ {
+ md5 = gnet_md5_new(content, length);
+ value = gnet_md5_get_string(md5);
+ gnet_md5_delete(md5);
+ g_free(content);
+ }
+ g_free(filename);
+ }
+ if(strcmp(value, "0"))
+ {
+ fprintf(data->pf, "%s %s\n", (gchar*)value, (gchar*)key);
+ }
+}
+
+void gc_cache_save(void)
+{
+ struct _table_data data;
+ FILE *pf;
+ gchar *filename;
+
+ filename = gc_file_find_absolute_writeable(CONTENT_FILENAME);
+ pf = fopen(filename, "w");
+ if(!pf)
+ {
+ g_warning("Couldn't save %s\n", filename);
+ return;
+ }
+
+ data.pf = pf;
+ data.path = g_path_get_dirname(filename);
+ g_hash_table_foreach(cache_content, _table_foreach, &data);
+
+ g_free(filename);
+ g_free(data.path);
+ fclose(pf);
+}
+
+void gc_cache_destroy(void)
+{
+ gc_cache_save();
+ g_hash_table_destroy(cache_content);
+ cache_content = NULL;
+}
+
diff --git a/src/gcompris/gc_net.h b/src/gcompris/gc_net.h
index dc777e1..b8675b5 100644
--- a/src/gcompris/gc_net.h
+++ b/src/gcompris/gc_net.h
@@ -35,10 +35,15 @@
#include "gcompris.h"
void gc_net_init();
-GdkPixbuf *gc_net_load_pixmap(const char *url);
-xmlDocPtr gc_net_load_xml(const char *url);
gchar *gc_net_get_url_from_file(const gchar *format, ...);
-gboolean gc_net_is_url(const char *url);
GSList *gc_net_dir_read_name(const gchar* dir, const gchar *ext);
+void gc_net_destroy();
+
+void gc_cache_init(void);
+void gc_cache_add(gchar *filename);
+gchar* gc_cache_import_pixmap(gchar *filename, gchar *boarddir, gint width, gint height);
+void gc_cache_remove(gchar *filename);
+void gc_cache_save(void);
+void gc_cache_destroy(void);
#endif
diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index fa13bf0..fafdbf8 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -675,7 +675,7 @@ static void setup_window ()
if(!icon_file)
g_warning ("Couldn't find file %s !", icon_file);
- icon_pixbuf = gc_net_load_pixmap(icon_file);
+ icon_pixbuf = gdk_pixbuf_new_from_file(icon_file,NULL);
if (!icon_pixbuf)
{
g_warning ("Failed to load pixbuf file: %s\n",
@@ -1057,6 +1057,8 @@ static void cleanup()
xf86_vidmode_set_fullscreen(FALSE);
#endif
gc_menu_destroy();
+ gc_net_destroy();
+ gc_cache_destroy();
gc_prop_destroy(gc_prop_get());
}
@@ -1692,8 +1694,7 @@ main (int argc, char *argv[])
}
}
}
- /* FIXME: Need to translate */
- printf("Number of activities: %d\n", board_count);
+ printf(_("Number of activities: %d\n"), board_count);
exit(0);
}
@@ -1729,7 +1730,7 @@ main (int argc, char *argv[])
{
if (g_access(properties->database, R_OK)==-1)
{
- printf("%s exists but is not readable or writable", properties->database);
+ printf(_("%s exists but is not readable or writable"), properties->database);
exit(0);
}
}
@@ -1788,8 +1789,10 @@ main (int argc, char *argv[])
if (popt_server){
#ifdef USE_GNET
properties->server = g_strdup(popt_server);
+ printf(" Server '%s'\n", properties->server);
#else
- printf("The --server option cannot be used because GCompris has been compiled without network support!");
+ printf(_("The --server option cannot be used because"
+ "GCompris has been compiled without network support!"));
exit(1);
#endif
}
@@ -1803,7 +1806,11 @@ main (int argc, char *argv[])
}
if (popt_server){
+ if(popt_cache_dir)
properties->cache_dir = g_strdup(popt_cache_dir);
+ else
+ properties->cache_dir = g_build_filename(g_get_user_cache_dir(), "gcompris", NULL);
+ printf(" Cache dir '%s'\n",properties->cache_dir);
}
if (popt_drag_mode){
@@ -1835,7 +1842,8 @@ main (int argc, char *argv[])
if(properties->profile == NULL)
{
- printf("ERROR: Profile '%s' is not found. Run 'gcompris --profile-list' to list available ones\n",
+ printf(_("ERROR: Profile '%s' is not found."
+ " Run 'gcompris --profile-list' to list available ones\n"),
popt_profile);
exit(1);
}
@@ -1871,6 +1879,10 @@ main (int argc, char *argv[])
/*------------------------------------------------------------*/
+ /* networking init */
+ gc_net_init();
+ gc_cache_init();
+
gc_skin_load(properties->skin);
if(properties->music || properties->fx)
@@ -1879,12 +1891,6 @@ main (int argc, char *argv[])
/* Gdk-Pixbuf */
gdk_rgb_init();
- /* Cache init */
- gc_cache_init(-1);
-
- /* networking init */
- gc_net_init();
-
setup_window ();
if (properties->fullscreen)
diff --git a/src/gcompris/images_selector.c b/src/gcompris/images_selector.c
index d97092c..f6cb334 100644
--- a/src/gcompris/images_selector.c
+++ b/src/gcompris/images_selector.c
@@ -277,8 +277,8 @@ gc_selector_images_start (GcomprisBoard *gcomprisBoard, gchar *dataset,
g_free(dataseturl);
dataseturl = g_strconcat("boards/", dataset, NULL);
-
- filelist = gc_net_dir_read_name(dataseturl, ".xml");
+ /* TODO */
+ filelist = NULL; //gc_net_dir_read_name(dataseturl, ".xml");
for (i = filelist; i != NULL; i = g_slist_next (i))
{
@@ -822,7 +822,7 @@ read_xml_file(gchar *fname)
g_return_val_if_fail(fname!=NULL, FALSE);
- doc = gc_net_load_xml(fname);
+ doc = xmlParseFile(fname);
/* in case something went wrong */
if(!doc)
diff --git a/src/gcompris/skin.c b/src/gcompris/skin.c
index 42d1d8b..a8abbe7 100644
--- a/src/gcompris/skin.c
+++ b/src/gcompris/skin.c
@@ -271,7 +271,7 @@ skin_xml_load (gchar* skin)
return;
}
- xmldoc = gc_net_load_xml(xmlfilename);
+ xmldoc = xmlParseFile(xmlfilename);
g_free(xmlfilename);
if(!xmldoc)
diff --git a/src/gcompris/wordlist.c b/src/gcompris/wordlist.c
index 9e2186a..59dfb61 100644
--- a/src/gcompris/wordlist.c
+++ b/src/gcompris/wordlist.c
@@ -385,7 +385,7 @@ void gc_wordlist_save(GcomprisWordlist *wordlist)
}
}
- filename = gc_file_find_absolute(wordlist->filename);
+ filename = gc_file_find_absolute_writeable(wordlist->filename);
if(filename)
{
if(xmlSaveFormatFileEnc(filename, doc, NULL, 1)<0)