[anjuta] npw: Improve translation of project wizard template



commit 648fa192c84a7d9d96118d4537f716db268dd931
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Sun May 30 12:05:33 2010 +0200

    npw: Improve translation of project wizard template
    
    Add an optional root node in .wiz format to make them valid XML file
    Read translation from .wiz file if available

 plugins/project-wizard/druid.c    |   18 +-
 plugins/project-wizard/header.c   |   34 +++-
 plugins/project-wizard/header.h   |    4 +-
 plugins/project-wizard/parser.c   |  444 ++++++++++++++++++++-----------------
 plugins/project-wizard/property.c |  117 +++++++++-
 plugins/project-wizard/property.h |    7 +-
 6 files changed, 382 insertions(+), 242 deletions(-)
---
diff --git a/plugins/project-wizard/druid.c b/plugins/project-wizard/druid.c
index e36ec4e..c40e8ad 100644
--- a/plugins/project-wizard/druid.c
+++ b/plugins/project-wizard/druid.c
@@ -215,7 +215,7 @@ cb_druid_add_summary_property (NPWProperty* property, gpointer user_data)
 	if (npw_property_get_options (property) & NPW_SUMMARY_OPTION)
 	{
 		g_string_append_printf (text, "%s %s\n",
-								_(npw_property_get_label (property)), 
+								npw_property_get_label (property), 
 								npw_property_get_value (property));
 	}
 }
@@ -233,7 +233,7 @@ npw_druid_fill_summary_page (NPWDruid* druid)
 
 	/* The project type is translated too, it is something like
 	 * generic, GNOME applet, Makefile project... */
-	g_string_append_printf (text, _("Project Type: %s\n"), _(npw_header_get_name (druid->header)));
+	g_string_append_printf (text, _("Project Type: %s\n"), npw_header_get_name (druid->header));
 
 	for (i = 0; (page = g_queue_peek_nth (druid->page_list, i)) != NULL; ++i)
 	{
@@ -291,8 +291,8 @@ cb_druid_insert_project_icon (gpointer data, gpointer user_data)
 	gtk_list_store_append (store, &iter);
 	pixbuf = gdk_pixbuf_new_from_file (npw_header_get_iconfile (header), NULL);
 	gtk_list_store_set (store, &iter, PIXBUF_COLUMN, pixbuf,
-						TEXT_COLUMN, _(npw_header_get_name (header)),
-						DESC_COLUMN, _(npw_header_get_description (header)),
+						TEXT_COLUMN, npw_header_get_name (header),
+						DESC_COLUMN, npw_header_get_description (header),
 						DATA_COLUMN, header,
 						-1);
 	
@@ -442,7 +442,7 @@ cb_druid_add_property (NPWProperty* property, gpointer user_data)
 
 		/* Add label and entry */
 		gtk_table_resize (data->table, data->row + 1, 2);
-		label = gtk_label_new (_(npw_property_get_label (property)));
+		label = gtk_label_new (npw_property_get_label (property));
 		gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 		gtk_misc_set_padding (GTK_MISC (label), 6, 6);
 		gtk_table_attach (data->table, label, 0, 1, data->row, data->row + 1,
@@ -466,7 +466,7 @@ npw_druid_fill_property_page (NPWDruid* druid, NPWPage* page)
 	gtk_container_foreach (GTK_CONTAINER (npw_page_get_widget (page)), cb_druid_destroy_widget, NULL);
  		
 	/* Update title	*/
-	gtk_assistant_set_page_title (GTK_ASSISTANT (druid->window), widget, _(npw_page_get_label (page)));
+	gtk_assistant_set_page_title (GTK_ASSISTANT (druid->window), widget, npw_page_get_label (page));
 
 	/* Add new widget */
 	data.druid = druid;
@@ -592,7 +592,7 @@ cb_save_valid_property (NPWProperty* property, gpointer user_data)
 		{
 			g_string_append_printf (data->error,
 									_("\nField \"%s\" is mandatory. Please enter it."),
-									_(npw_property_get_label (property)));
+									npw_property_get_label (property));
 			npw_property_remove_value (property);
 		}
 	}
@@ -607,12 +607,12 @@ cb_save_valid_property (NPWProperty* property, gpointer user_data)
 		case NPW_FILENAME_RESTRICTION:
 			g_string_append_printf (data->error,
 									_("Field \"%s\" must start with a letter, a digit or an underscore and contain only letters, digits, underscore, minus and dot. Please fix it."),
-									_(npw_property_get_label (property)));
+									npw_property_get_label (property));
 			break;
 		case NPW_DIRECTORY_RESTRICTION:
 			g_string_append_printf (data->error,
 									_("Field \"%s\" must start with a letter, a digit, an underscore or a directory separator and contain only letters, digits, underscore, directory separator, minus and dot. Please fix it."),
-									_(npw_property_get_label (property)));
+									npw_property_get_label (property));
 			break;
 		default:
 			g_string_append_printf (data->error,
diff --git a/plugins/project-wizard/header.c b/plugins/project-wizard/header.c
index 9101101..59c32ad 100644
--- a/plugins/project-wizard/header.c
+++ b/plugins/project-wizard/header.c
@@ -30,13 +30,17 @@
 #include "header.h"
 
 #include <glib.h>
+#include <glib/gi18n.h>
+
 #include <libanjuta/anjuta-utils.h>
 
 /*---------------------------------------------------------------------------*/
 
 struct _NPWHeader {
 	gchar* name;
+	gint name_lang;
 	gchar* description;
+	gint description_lang;
 	gchar* iconfile;
 	gchar* category;
 	gchar* filename;
@@ -60,6 +64,8 @@ npw_header_new (void)
 void
 npw_header_free (NPWHeader* self)
 {
+	if (self == NULL) return;
+	
 	g_free (self->name);
 	g_free (self->description);
 	g_free (self->iconfile);
@@ -67,23 +73,30 @@ npw_header_free (NPWHeader* self)
 	g_free (self->filename);
 	g_list_free (self->required_programs);
 	g_list_free (self->required_packages);
+	g_slice_free (NPWHeader, self);
 }
 
 void
-npw_header_set_name (NPWHeader* self, const gchar* name)
+npw_header_set_name (NPWHeader* self, const gchar* name, gint lang)
 {
-	self->name = g_strdup (name);
+	if (lang >= self->name_lang)
+	{
+		g_free (self->name);
+		self->name = g_strdup (name);
+		self->name_lang = lang;
+	}
 }
 
 const gchar*
 npw_header_get_name (const NPWHeader* self)
 {
-	return self->name;
+	return self->name_lang == 0 ? _(self->name) : self->name;
 }
 
 void
 npw_header_set_filename (NPWHeader* self, const gchar* filename)
 {
+	g_free (self->filename);
 	self->filename = g_strdup (filename);
 }
 
@@ -96,6 +109,7 @@ npw_header_get_filename (const NPWHeader* self)
 void
 npw_header_set_category (NPWHeader* self, const gchar* category)
 {
+	g_free (self->category);
 	self->category =g_strdup (category);
 }
 
@@ -106,20 +120,26 @@ npw_header_get_category (const NPWHeader* self)
 }
 
 void
-npw_header_set_description (NPWHeader* self, const gchar* description)
+npw_header_set_description (NPWHeader* self, const gchar* description, gint lang)
 {
-	self->description = g_strdup (description);
+	if (lang >= self->description_lang)
+	{
+		g_free (self->description);
+		self->description = g_strdup (description);
+		self->description_lang = lang;
+	}
 }
 
 const gchar*
 npw_header_get_description (const NPWHeader* self)
 {
-	return self->description;
+	return self->description_lang == 0 ? _(self->description) : self->description;
 }
 
 void
 npw_header_set_iconfile (NPWHeader* self, const gchar* iconfile)
 {
+	g_free (self->iconfile);
 	self->iconfile = g_strdup (iconfile);
 }
 
@@ -210,7 +230,7 @@ npw_header_list_free (GList* list)
 static gint
 compare_header_name (NPWHeader *a, NPWHeader *b)
 {
-	return g_ascii_strcasecmp (npw_header_get_name (a), npw_header_get_name (b));
+	return g_utf8_collate (npw_header_get_name (a), npw_header_get_name (b));
 }
 
 GList *
diff --git a/plugins/project-wizard/header.h b/plugins/project-wizard/header.h
index 9168202..7d4ccf5 100644
--- a/plugins/project-wizard/header.h
+++ b/plugins/project-wizard/header.h
@@ -29,7 +29,7 @@ typedef struct _NPWHeaderList NPWHeaderList;
 NPWHeader* npw_header_new (void);
 void npw_header_free (NPWHeader* self);
 
-void npw_header_set_name (NPWHeader* this, const gchar* name);
+void npw_header_set_name (NPWHeader* this, const gchar* name, gint lang);
 const gchar* npw_header_get_name (const NPWHeader* self);
 
 void npw_header_set_filename (NPWHeader* this, const gchar* filename);
@@ -38,7 +38,7 @@ const gchar* npw_header_get_filename (const NPWHeader* self);
 void npw_header_set_category (NPWHeader* this, const gchar* category);
 const gchar* npw_header_get_category(const NPWHeader* self);
 
-void npw_header_set_description (NPWHeader* this, const gchar* description);
+void npw_header_set_description (NPWHeader* this, const gchar* description, gint lang);
 const gchar* npw_header_get_description (const NPWHeader* self);
 
 void npw_header_set_iconfile (NPWHeader* this, const gchar* confile);
diff --git a/plugins/project-wizard/parser.c b/plugins/project-wizard/parser.c
index 12d2ce6..ffd51e2 100644
--- a/plugins/project-wizard/parser.c
+++ b/plugins/project-wizard/parser.c
@@ -38,8 +38,14 @@
 
 #define PROJECT_WIZARD_EXTENSION	".wiz"
 
+typedef struct {
+	const gchar *string;
+	gint id;
+} NPWStringMapping;
+
 typedef enum {
 	NPW_NO_TAG = 0,
+	NPW_PROJECT_TEMPLATE_TAG,
 	NPW_PROJECT_WIZARD_TAG,
 	NPW_NAME_TAG,
 	NPW_DESCRIPTION_TAG,
@@ -56,9 +62,33 @@ typedef enum {
 	NPW_ACTION_TAG,
 	NPW_RUN_TAG,
 	NPW_OPEN_TAG,
-	NPW_UNKNOW_TAG
+	NPW_UNKNOW_TAG,
+	NPW_LAST_TAG
 } NPWTag;
 
+static NPWStringMapping npw_tag_mapping [] = {
+		{"project-template", NPW_PROJECT_TEMPLATE_TAG},
+		{"project-wizard", NPW_PROJECT_WIZARD_TAG},
+		{"_name", NPW_NAME_TAG},
+		{"name", NPW_NAME_TAG},
+		{"_description", NPW_DESCRIPTION_TAG},
+		{"description", NPW_DESCRIPTION_TAG},
+		{"icon", NPW_ICON_TAG},
+		{"category", NPW_CATEGORY_TAG},
+		{"required-program", NPW_REQUIRED_PROGRAM_TAG},
+		{"required-package", NPW_REQUIRED_PACKAGE_TAG},
+		{"page", NPW_PAGE_TAG},
+		{"property", NPW_PROPERTY_TAG},
+		{"item", NPW_ITEM_TAG},
+		{"directory", NPW_DIRECTORY_TAG},
+		{"content", NPW_CONTENT_TAG},
+		{"file", NPW_FILE_TAG},
+		{"action", NPW_ACTION_TAG},
+		{"run", NPW_RUN_TAG},
+		{"open", NPW_OPEN_TAG},
+		{NULL, NPW_UNKNOW_TAG}
+	};
+
 typedef enum {
 	NPW_NO_ATTRIBUTE = 0,
 	NPW_NAME_ATTRIBUTE,
@@ -78,9 +108,36 @@ typedef enum {
 	NPW_AUTOGEN_ATTRIBUTE,
 	NPW_COMMAND_ATTRIBUTE,
 	NPW_FILE_ATTRIBUTE,
-	NPW_UNKNOW_ATTRIBUTE
+	NPW_XML_LANG_ATTRIBUTE,
+	NPW_UNKNOW_ATTRIBUTE,
+	NPW_LAST_ATTRIBUTE
 } NPWAttribute;
 
+static NPWStringMapping npw_attribute_mapping [] = {
+		{"name", NPW_NAME_ATTRIBUTE},
+		{"_label", NPW_LABEL_ATTRIBUTE},
+		{"label", NPW_LABEL_ATTRIBUTE},
+		{"_description", NPW_DESCRIPTION_ATTRIBUTE},
+		{"description", NPW_DESCRIPTION_ATTRIBUTE},
+		{"default", NPW_VALUE_ATTRIBUTE},
+		{"value", NPW_VALUE_ATTRIBUTE},
+		{"type", NPW_TYPE_ATTRIBUTE},
+		{"restriction", NPW_RESTRICTION_ATTRIBUTE},
+		{"summary", NPW_SUMMARY_ATTRIBUTE},
+		{"mandatory", NPW_MANDATORY_ATTRIBUTE},
+		{"editable", NPW_EDITABLE_ATTRIBUTE},
+		{"exist", NPW_EXIST_ATTRIBUTE},
+		{"source", NPW_SOURCE_ATTRIBUTE},
+		{"destination", NPW_DESTINATION_ATTRIBUTE},
+		{"executable", NPW_EXECUTABLE_ATTRIBUTE},
+		{"project", NPW_PROJECT_ATTRIBUTE},
+		{"autogen", NPW_AUTOGEN_ATTRIBUTE},
+		{"command", NPW_COMMAND_ATTRIBUTE},
+		{"file", NPW_FILE_ATTRIBUTE},
+		{"xml:lang", NPW_XML_LANG_ATTRIBUTE},
+		{NULL, NPW_UNKNOW_ATTRIBUTE}
+	};
+
 typedef enum {
 	NPW_HEADER_PARSER,
 	NPW_PAGE_PARSER,
@@ -144,151 +201,33 @@ npw_header_list_readdir (GList** list, const gchar* path)
 static NPWTag
 parse_tag (const char* name)
 {
-	if (strcmp (name, "project-wizard") == 0)
-	{
-		return NPW_PROJECT_WIZARD_TAG;
-	}
-	else if ((strcmp ("_name", name) == 0) || (strcmp ("name", name) == 0))
-	{
-		return NPW_NAME_TAG;
-	}
-	else if ((strcmp ("_description", name) == 0) || (strcmp ("description", name) == 0))
-	{
-		return NPW_DESCRIPTION_TAG;
-	}
-	else if (strcmp ("icon", name) == 0)
-	{
-		return NPW_ICON_TAG;
-	}
-	else if (strcmp ("category", name) == 0)
-	{
-		return NPW_CATEGORY_TAG;
-	}
-	else if (strcmp ("required-program", name) == 0)
-	{
-		return NPW_REQUIRED_PROGRAM_TAG;
-	}
-	else if (strcmp ("required-package", name) == 0)
-	{
-		return NPW_REQUIRED_PACKAGE_TAG;
-	}
-	else if (strcmp ("page", name) == 0)
-	{
-		return NPW_PAGE_TAG;
-	}
-	else if (strcmp ("property", name) == 0)
-	{
-		return NPW_PROPERTY_TAG;
-	}
-	else if (strcmp ("item", name) == 0)
-	{
-		return NPW_ITEM_TAG;
-	}	
-	else if (strcmp ("directory", name) == 0)
-	{
-		return NPW_DIRECTORY_TAG;
-	}
-	else if (strcmp ("content", name) == 0)
-	{
-		return NPW_CONTENT_TAG;
-	}
-	else if (strcmp ("file", name) == 0)
-	{
-		return NPW_FILE_TAG;
-	}
-	else if (strcmp ("action", name) == 0)
-	{
-		return NPW_ACTION_TAG;
-	}
-	else if (strcmp ("run", name) == 0)
-	{
-		return NPW_RUN_TAG;
-	}
-	else if (strcmp ("open", name) == 0)
-	{
-		return NPW_OPEN_TAG;
-	}
-	else
+	NPWStringMapping *mapping;
+
+	for (mapping = npw_tag_mapping; mapping->string != NULL; mapping++)
 	{
-		return NPW_UNKNOW_TAG;
+		if (strcmp (name, mapping->string) == 0)
+		{
+			return (NPWTag)mapping->id;
+		}
 	}
+	
+	return NPW_UNKNOW_TAG;
 }
 
 static NPWAttribute
 parse_attribute (const char* name)
 {
-	if (strcmp ("name", name) == 0)
-	{
-		return NPW_NAME_ATTRIBUTE;
-	}
-	else if (strcmp ("_label", name) == 0)
-	{
-		return NPW_LABEL_ATTRIBUTE;
-	}
-	else if (strcmp ("_description", name) == 0)
-	{
-		return NPW_DESCRIPTION_ATTRIBUTE;
-	}
-	else if (strcmp ("default", name) == 0 || strcmp ("value", name) == 0)
-	{
-		return NPW_VALUE_ATTRIBUTE;
-	}
-	else if (strcmp ("type", name) == 0)
-	{
-		return NPW_TYPE_ATTRIBUTE;
-	}
-	else if (strcmp ("restriction", name) == 0)
-	{
-		return NPW_RESTRICTION_ATTRIBUTE;
-	}
-	else if (strcmp ("summary", name) == 0)
-	{
-		return NPW_SUMMARY_ATTRIBUTE;
-	}
-	else if (strcmp ("mandatory", name) == 0)
-	{
-		return NPW_MANDATORY_ATTRIBUTE;
-	}
-	else if (strcmp ("editable", name) == 0)
-	{
-		return NPW_EDITABLE_ATTRIBUTE;
-	}
-	else if (strcmp ("exist", name) == 0)
-	{
-		return NPW_EXIST_ATTRIBUTE;
-	}
-	else if (strcmp ("source", name) == 0)
-	{
-		return NPW_SOURCE_ATTRIBUTE;
-	}
-	else if (strcmp ("destination", name) == 0)
-	{
-		return NPW_DESTINATION_ATTRIBUTE;
-	}
-	else if (strcmp ("executable", name) == 0)
-	{
-		return NPW_EXECUTABLE_ATTRIBUTE;
-	}
-	else if (strcmp ("project", name) == 0)
-	{
-		return NPW_PROJECT_ATTRIBUTE;
-	}
-	else if (strcmp ("autogen", name) == 0)
-	{
-		return NPW_AUTOGEN_ATTRIBUTE;
-	}
-	else if (strcmp ("command", name) == 0)
-	{
-		return NPW_COMMAND_ATTRIBUTE;
-	}
-	else if (strcmp ("file", name) == 0)
+	NPWStringMapping *mapping;
+
+	for (mapping = npw_attribute_mapping; mapping->string != NULL; mapping++)
 	{
-		return NPW_FILE_ATTRIBUTE;
-	}
-	else
-	{	
-		return NPW_UNKNOW_ATTRIBUTE;
+		if (strcmp (name, mapping->string) == 0)
+		{
+			return (NPWAttribute)mapping->id;
+		}
 	}
+	
+	return NPW_UNKNOW_ATTRIBUTE;
 }
 
 static gboolean
@@ -336,10 +275,53 @@ parser_critical (GMarkupParseContext* ctx, const gchar* format,...)
 	va_end (args);
 	g_free (msg);
 }
+
+/* Represent a language as an integer:
+ * < 0 for a not applicable language
+ *  0 for not specified language
+ * > 0 for an applicable language, higher number means a better match */
+static gint
+get_tag_language (const gchar** attributes,
+					const gchar** values)
+{
+	const gchar *lang = NULL;
+	
+	while (*attributes != NULL)
+	{
+		if (parse_attribute (*attributes) == NPW_XML_LANG_ATTRIBUTE)
+		{
+			lang = *values;
+		}
+		attributes++;
+		values++;
+	}
+	
+	if (lang != NULL)
+	{
+		const gchar* const *local;
+		gint id = G_MAXINT;
+		
+		for (local = g_get_language_names (); *local != NULL; local++)
+		{
+			id--;
+			if (strcmp (*local, lang) == 0)
+			{
+				return id;
+			}
+		}
+		
+		return -1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
 /* Parse project wizard block
  *---------------------------------------------------------------------------*/
 
-#define NPW_HEADER_PARSER_MAX_LEVEL	2	/* Maximum number of nested elements */
+#define NPW_HEADER_PARSER_MAX_LEVEL	3	/* Maximum number of nested elements */
 
 typedef struct _NPWHeaderParser
 {
@@ -355,6 +337,8 @@ typedef struct _NPWHeaderParser
 	NPWHeader* header;
 	/* Name of file read */
 	gchar* filename;
+	/* Language of current tag */
+	gint lang;
 } NPWHeaderParser;
 
 static void
@@ -374,9 +358,11 @@ parse_header_start (GMarkupParseContext* context,
 	{
 		/* Not inside an unknown element */
 		tag = parse_tag (name);
+		
 		switch (*parser->last)
 		{
 		case NPW_NO_TAG:
+		case NPW_PROJECT_TEMPLATE_TAG:
 			/* Top level element */
 			switch (tag)
 			{
@@ -388,6 +374,9 @@ parse_header_start (GMarkupParseContext* context,
 			case NPW_UNKNOW_TAG:
 				parser_warning (parser->ctx, "Unknown element \"%s\"", name);
 				break;
+			case NPW_PROJECT_TEMPLATE_TAG:
+				known = TRUE;
+				break;
 			default:
 				break;
 			}
@@ -402,6 +391,7 @@ parse_header_start (GMarkupParseContext* context,
 			case NPW_CATEGORY_TAG:
 			case NPW_REQUIRED_PROGRAM_TAG:
 			case NPW_REQUIRED_PACKAGE_TAG:
+				parser->lang = get_tag_language (attributes, values);
 				known = TRUE;
 				break;
 			default:
@@ -453,6 +443,7 @@ parse_header_end (GMarkupParseContext* context,
 			{
 				parser_critical (parser->ctx, "Missing name attribute");
 				npw_header_free (parser->header);
+				parser->header = NULL;
 			}
 
 			/* Stop parsing after first project wizard block
@@ -481,57 +472,28 @@ parse_header_text (GMarkupParseContext* context,
 	GError** error)
 {
 	NPWHeaderParser* parser = (NPWHeaderParser*)data;
+	char* filename;
+	char* path;
 
 	if (parser->unknown == 0)
 	{
 		switch (*parser->last)
 		{
 		case NPW_NAME_TAG:
-			if (npw_header_get_name (parser->header) == NULL)
-			{
-				npw_header_set_name (parser->header, text);
-			}
-			else
-			{
-				parser_critical (parser->ctx, "Duplicated name tag");
-			}
+			npw_header_set_name (parser->header, text, parser->lang);
 			break;
 		case NPW_DESCRIPTION_TAG:
-			if (npw_header_get_description (parser->header) == NULL)
-			{
-				npw_header_set_description (parser->header, text);
-			}
-			else
-			{
-				parser_critical (parser->ctx, "Duplicated description tag");
-			}
+			npw_header_set_description (parser->header, text, parser->lang);
 			break;
 		case NPW_ICON_TAG:
-			if (npw_header_get_iconfile (parser->header) == NULL)
-			{
-				char* filename;
-				char* path;
-
-				path = g_path_get_dirname (parser->filename);
-				filename = g_build_filename (path, text, NULL);
-				npw_header_set_iconfile (parser->header, filename);
-				g_free (path);
-				g_free (filename);
-			}
-			else
-			{
-				parser_critical (parser->ctx, "Duplicated icon tag");
-			}
+			path = g_path_get_dirname (parser->filename);
+			filename = g_build_filename (path, text, NULL);
+			npw_header_set_iconfile (parser->header, filename);
+			g_free (path);
+			g_free (filename);
 			break;
 		case NPW_CATEGORY_TAG:
-			if (npw_header_get_category (parser->header) == NULL)
-			{
-				npw_header_set_category (parser->header, text);
-			}
-			else
-			{
-				parser_critical (parser->ctx, "Duplicated category tag");
-			}
+			npw_header_set_category (parser->header, text);
 			break;
 		case NPW_REQUIRED_PROGRAM_TAG:
 			npw_header_add_required_program (parser->header, text);
@@ -540,6 +502,7 @@ parse_header_text (GMarkupParseContext* context,
 			npw_header_add_required_package (parser->header, text);
 			break;
 		case NPW_PROJECT_WIZARD_TAG:
+		case NPW_PROJECT_TEMPLATE_TAG:
 			/* Nothing to do */
 			break;
 		default:
@@ -667,7 +630,7 @@ npw_header_list_read (GList** list, const gchar* filename)
 /* Parse page block
  *---------------------------------------------------------------------------*/
 
-#define NPW_PAGE_PARSER_MAX_LEVEL	3	/* Maximum number of nested elements */
+#define NPW_PAGE_PARSER_MAX_LEVEL	4	/* Maximum number of nested elements */
 
 struct _NPWPageParser
 {
@@ -681,51 +644,90 @@ struct _NPWPageParser
 	guint unknown;
 	/* page number to read */
 	gint count;
+	/* previous page name list */
+	GList *previous;
 	/* Current page object */
 	NPWPage* page;
 	/* Current property object */
 	NPWProperty* property;
 };
 
+static const gchar *
+get_page_name (const gchar** attributes,
+				const gchar** values)
+{
+	while (*attributes != NULL)
+	{
+		if (parse_attribute (*attributes) == NPW_NAME_ATTRIBUTE)
+		{
+			return *values;
+		}
+		attributes++;
+		values++;
+	}
+
+	return NULL;
+}
+
 static gboolean
 parse_page (NPWPageParser* parser, 
 	const gchar** attributes,
 	const gchar** values)
 {
-	if (parser->count != 0)
-	{
-		/* Skip this page */
-		if (parser->count > 0) parser->count--;
+	const gchar *name;
+	
+	/* Check page name to avoid duplicated page due to translated version */
+	name = get_page_name (attributes, values);
+	if (name == NULL) return FALSE;
 
-		return FALSE;
+	/* If this is a new page, add it in the list and decrement counter */
+	if (g_list_find_custom (parser->previous, name, (GCompareFunc)strcmp) == NULL)
+	{
+		/* New page, add it in list and decrement counter */
+		parser->previous = g_list_prepend (parser->previous, strdup (name));
+		parser->count--;
 	}
-	else
+
+	/* Translated page must be after the non translated one */
+	if (parser->count == -1)
 	{
-		/* Read this page */
-		while (*attributes != NULL)
+		gint lang;
+		
+		lang = get_tag_language (attributes, values);
+
+		if (npw_page_set_language (parser->page, lang))
 		{
-			switch (parse_attribute (*attributes))
+			/* Read this page */
+			while (*attributes != NULL)
 			{
-			case NPW_NAME_ATTRIBUTE:
-				npw_page_set_name (parser->page, *values);
-				break;
-			case NPW_LABEL_ATTRIBUTE:
-				npw_page_set_label (parser->page, *values);
-				break;
-			case NPW_DESCRIPTION_ATTRIBUTE:
-				npw_page_set_description (parser->page, *values);
-				break;
-			default:
-				parser_warning (parser->ctx, "Unknown page attribute \"%s\"", *attributes);
-				break;
+				switch (parse_attribute (*attributes))
+				{
+				case NPW_NAME_ATTRIBUTE:
+					npw_page_set_name (parser->page, *values);
+					break;
+				case NPW_LABEL_ATTRIBUTE:
+					npw_page_set_label (parser->page, *values);
+					break;
+				case NPW_DESCRIPTION_ATTRIBUTE:
+					npw_page_set_description (parser->page, *values);
+					break;
+				case NPW_XML_LANG_ATTRIBUTE:
+					break;
+				default:
+					parser_warning (parser->ctx, "Unknown page attribute \"%s\"", *attributes);
+					break;
+				}
+				attributes++;
+				values++;
 			}
-			attributes++;
-			values++;
 		}
-		parser->count--;
-
+		
 		return TRUE;
 	}
+	else
+	{
+		return FALSE;
+	}
 }
 
 static gboolean
@@ -734,7 +736,8 @@ parse_property (NPWPageParser* parser,
 	const gchar** values)
 {
 	parser->property = npw_property_new ();
-	npw_page_add_property (parser->page, parser->property);
+
+	npw_property_set_language (parser->property, get_tag_language (attributes, values));
 
 	while (*attributes != NULL)
 	{
@@ -770,6 +773,8 @@ parse_property (NPWPageParser* parser,
 		case NPW_EXIST_ATTRIBUTE:
 			npw_property_set_exist_option (parser->property, parse_boolean_string (*values));
 			break;
+		case NPW_XML_LANG_ATTRIBUTE:
+			break;
 		default:
 			parser_warning (parser->ctx, "Unknown property attribute \"%s\"", *attributes);
 			break;
@@ -777,6 +782,7 @@ parse_property (NPWPageParser* parser,
 		attributes++;
 		values++;
 	}	
+	parser->property = npw_page_add_property (parser->page, parser->property);
 
 	return TRUE;
 }
@@ -788,7 +794,10 @@ parse_item (NPWPageParser* parser,
 {
 	const gchar* label = NULL;
 	const gchar* name = NULL;
-
+	gint lang;
+	
+	lang = get_tag_language (attributes, values);
+	
 	while (*attributes != NULL)
 	{
 		switch (parse_attribute (*attributes))
@@ -799,6 +808,8 @@ parse_item (NPWPageParser* parser,
 		case NPW_LABEL_ATTRIBUTE:
 			label = *values;
 			break;
+		case NPW_XML_LANG_ATTRIBUTE:
+			break;
 		default:
 			parser_warning (parser->ctx, "Unknown item attribute \"%s\"", *attributes);
 			break;
@@ -813,7 +824,7 @@ parse_item (NPWPageParser* parser,
 	}
 	else
 	{
-		npw_property_add_list_item (parser->property, name, label == NULL ? name : label);
+		npw_property_add_list_item (parser->property, name, label == NULL ? name : label, lang);
 	}
 
 	return TRUE;
@@ -836,9 +847,11 @@ parse_page_start (GMarkupParseContext* context,
 	{
 		/* Not inside an unknown element */
 		tag = parse_tag (name);
+		
 		switch (*parser->last)
 		{
 		case NPW_NO_TAG:
+		case NPW_PROJECT_TEMPLATE_TAG:
 			/* Top level element */
 			switch (tag)
 			{
@@ -848,6 +861,9 @@ parse_page_start (GMarkupParseContext* context,
 			case NPW_UNKNOW_TAG:
 				parser_warning (parser->ctx, "Unknown element \"%s\"", name);
 				break;
+			case NPW_PROJECT_TEMPLATE_TAG:
+				known = TRUE;
+				break;
 			default:
 				break;
 			}
@@ -946,9 +962,10 @@ npw_page_parser_new (NPWPage* page, const gchar* filename, gint count)
 	parser->last =parser->tag;
 
 	parser->count = count;
+	parser->previous = NULL;
 	parser->page = page;
 	parser->property = NULL;
-
+	
 	parser->ctx = g_markup_parse_context_new (&page_markup_parser, 0, parser, NULL);
 	g_assert (parser->ctx != NULL);
 
@@ -960,6 +977,8 @@ npw_page_parser_free (NPWPageParser* parser)
 {
 	g_return_if_fail (parser != NULL);
 
+	g_list_foreach (parser->previous, (GFunc)g_free, NULL);
+	g_list_free (parser->previous);
 	g_markup_parse_context_free (parser->ctx);
 	g_free (parser);
 }
@@ -1307,10 +1326,12 @@ parse_file_start (GMarkupParseContext* context,
 		switch (parent->tag)
 		{
 		case NPW_NO_TAG:
+		case NPW_PROJECT_TEMPLATE_TAG:
 			/* Top level element */
 			switch (tag)
 			{
 			case NPW_CONTENT_TAG:
+			case NPW_PROJECT_TEMPLATE_TAG:
 				child.tag = tag;
 				break;
 			case NPW_UNKNOW_TAG:
@@ -1472,7 +1493,8 @@ npw_file_list_parser_end_parse (NPWFileListParser* parser, GError** error)
 /* Parse action block
  *---------------------------------------------------------------------------*/
 
-#define NPW_ACTION_PARSER_MAX_LEVEL	2	/* Maximum number of nested elements */
+#define NPW_ACTION_PARSER_MAX_LEVEL	3
+	/* Maximum number of nested elements */
 
 struct _NPWActionListParser
 {
@@ -1574,6 +1596,7 @@ parse_action_start (GMarkupParseContext* context, const gchar* name, const gchar
 		switch (*parser->last)
 		{
 		case NPW_NO_TAG:
+		case NPW_PROJECT_TEMPLATE_TAG:
 			/* Top level element */
 			switch (tag)
 			{
@@ -1583,6 +1606,9 @@ parse_action_start (GMarkupParseContext* context, const gchar* name, const gchar
 			case NPW_UNKNOW_TAG:
 				parser_warning (parser->ctx, "Unknown element \"%s\"", name);
 				break;
+			case NPW_PROJECT_TEMPLATE_TAG:
+				known = TRUE;
+				break;
 			default:
 				break;
 			}
diff --git a/plugins/project-wizard/property.c b/plugins/project-wizard/property.c
index 7a90b4e..f9cf1a8 100644
--- a/plugins/project-wizard/property.c
+++ b/plugins/project-wizard/property.c
@@ -49,6 +49,7 @@ struct _NPWPage
 	gchar* name;
 	gchar* label;
 	gchar* description;
+	gint language;
 	GtkWidget *widget;
 };
 
@@ -59,6 +60,7 @@ struct _NPWProperty {
 	gchar* label;
 	gchar* description;
 	gchar* defvalue;
+	gint language;
 	NPWValue* value;
 	GtkWidget* widget;
 	GSList* items;
@@ -67,6 +69,7 @@ struct _NPWProperty {
 struct _NPWItem {
 	gchar* name;
 	gchar* label;
+	gint language;
 };
 
 static const gchar* NPWPropertyTypeString[] = {
@@ -89,13 +92,14 @@ static const gchar* NPWPropertyRestrictionString[] = {
  *---------------------------------------------------------------------------*/
 
 static NPWItem*
-npw_item_new (const gchar *name, const gchar *label)
+npw_item_new (const gchar *name, const gchar *label, gint language)
 {
 	NPWItem *item;
 	
 	item = g_slice_new (NPWItem);
 	item->name = g_strdup (name);
 	item->label = g_strdup (label);
+	item->language = language;
 	
 	return item;
 }
@@ -108,6 +112,18 @@ npw_item_free (NPWItem *item)
 	g_slice_free (NPWItem, item);
 }
 
+static gint
+npw_item_compare (const NPWItem *a, const NPWItem *b)
+{
+	return g_strcmp0 (a->name, b->name);
+}
+
+static const gchar *
+npw_item_get_label (const NPWItem *item)
+{
+	return item->language == 0 ? _(item->label) : item->label;
+}
+
 /* Property object
  *---------------------------------------------------------------------------*/
 
@@ -147,6 +163,12 @@ npw_property_restriction_from_string (const gchar* restriction)
 	return NPW_NO_RESTRICTION;
 }
 
+static gint
+npw_property_compare (const NPWProperty *a, const NPWProperty *b)
+{
+	return g_strcmp0 (npw_value_get_name (a->value), npw_value_get_name (b->value));
+}
+
 NPWProperty*
 npw_property_new (void)
 {
@@ -175,6 +197,12 @@ npw_property_free (NPWProperty* prop)
 }
 
 void
+npw_property_set_language (NPWProperty* prop, gint language)
+{
+	prop->language = language;
+}
+
+void
 npw_property_set_type (NPWProperty* prop, NPWPropertyType type)
 {
 	prop->type = type;
@@ -281,25 +309,27 @@ npw_property_get_name (const NPWProperty* prop)
 void
 npw_property_set_label (NPWProperty* prop, const gchar* label)
 {
+	g_free (prop->label);
 	prop->label = g_strdup (label);
 }
 
 const gchar*
 npw_property_get_label (const NPWProperty* prop)
 {
-	return prop->label;
+	return prop->language == 0 ? _(prop->label) : prop->label;
 }
 
 void
 npw_property_set_description (NPWProperty* prop, const gchar* description)
 {
+	g_free (prop->description);
 	prop->description = g_strdup (description);
 }
 
 const gchar*
 npw_property_get_description (const NPWProperty* prop)
 {
-	return prop->description;
+	return prop->language == 0 ? _(prop->description) : prop->description;
 }
 
 static void
@@ -509,10 +539,10 @@ npw_property_create_widget (NPWProperty* prop)
 		entry = gtk_combo_box_entry_new_text ();
 		for (node = prop->items; node != NULL; node = node->next)
 		{
-			gtk_combo_box_append_text (GTK_COMBO_BOX (entry), _(((NPWItem *)node->data)->label));
+			gtk_combo_box_append_text (GTK_COMBO_BOX (entry), npw_item_get_label((NPWItem *)node->data));
 			if ((value != NULL) && !get_value && (strcmp (value, ((NPWItem *)node->data)->name) == 0))
 			{
-				value = _(((NPWItem *)node->data)->label);
+				value = npw_item_get_label ((NPWItem *)node->data);
 				get_value = TRUE;
 			}
 		}
@@ -566,6 +596,7 @@ npw_property_set_default (NPWProperty* prop, const gchar* value)
 				sprintf(buffer,"%s%d",value, i);
 				if (!g_file_test (buffer, G_FILE_TEST_EXISTS)) break;
 			}
+			g_free (prop->defvalue);
 			prop->defvalue = buffer;
 			g_free (expand_value);
 
@@ -577,6 +608,7 @@ npw_property_set_default (NPWProperty* prop, const gchar* value)
 	 * the default property */
 	if (prop->defvalue != value)
 	{
+		g_free (prop->defvalue);
 		prop->defvalue = (value == NULL) ? NULL : g_strdup (value);
 	}
 }
@@ -628,7 +660,7 @@ npw_property_set_value_from_widget (NPWProperty* prop, NPWValueTag tag)
 		value = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (prop->widget))));
 		for (node = prop->items; node != NULL; node = node->next)
 		{
-			if (strcmp (value, _(((NPWItem *)node->data)->label)) == 0)
+			if (strcmp (value, npw_item_get_label((NPWItem *)node->data)) == 0)
 			{
 				value = ((NPWItem *)node->data)->name;
 				break;
@@ -690,12 +722,31 @@ npw_property_get_value (const NPWProperty* prop)
 }
 
 gboolean
-npw_property_add_list_item (NPWProperty* prop, const gchar* name, const gchar* label)
+npw_property_add_list_item (NPWProperty* prop, const gchar* name, const gchar* label, gint language)
 {
 	NPWItem* item;
+	GSList *find;
 
-	item = npw_item_new (name, label);
-	prop->items = g_slist_append (prop->items, item);
+	item = npw_item_new (name, label, language);
+	find = g_slist_find_custom (prop->items, item, (GCompareFunc)npw_item_compare);
+	if (find != NULL)
+	{
+		NPWItem* old_item = (NPWItem *)find->data;
+		
+		if (old_item->language <= item->language)
+		{
+			npw_item_free ((NPWItem *)find->data);
+			find->data = item;
+		}
+		else
+		{
+			npw_item_free (item);
+		}
+	}
+	else
+	{
+		prop->items = g_slist_append (prop->items, item);
+	}
 
 	return TRUE;
 }
@@ -800,6 +851,7 @@ npw_page_free (NPWPage* page)
 void
 npw_page_set_name (NPWPage* page, const gchar* name)
 {
+	g_free (page->name);
 	page->name = g_strdup (name);
 }
 
@@ -809,28 +861,44 @@ npw_page_get_name (const NPWPage* page)
 	return page->name;
 }
 
+gboolean
+npw_page_set_language (NPWPage *page, gint language)
+{
+	if (page->language <= language)
+	{
+		page->language = language;
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
 void
 npw_page_set_label (NPWPage* page, const gchar* label)
 {
+	g_free (page->label);
 	page->label = g_strdup (label);
 }
 
 const gchar*
 npw_page_get_label (const NPWPage* page)
 {
-	return page->label;
+	return page->language == 0 ? _(page->label) : page->label;
 }
 
 void
 npw_page_set_description (NPWPage* page, const gchar* description)
 {
+	g_free (page->description);
 	page->description = g_strdup (description);
 }
 
 const gchar*
 npw_page_get_description (const NPWPage* page)
 {
-	return page->description;
+	return page->language == 0 ? _(page->description) : page->description;
 }
 
 void
@@ -851,8 +919,31 @@ npw_page_foreach_property (const NPWPage* page, GFunc func, gpointer data)
 	g_list_foreach (page->properties, func, data);
 }
 
-void
+NPWProperty *
 npw_page_add_property (NPWPage* page, NPWProperty *prop)
 {
-	page->properties = g_list_append (page->properties, prop);
+	GList *find;
+	
+	find = g_list_find_custom (page->properties, prop, (GCompareFunc)npw_property_compare);
+	if (find == NULL)
+	{
+		page->properties = g_list_append (page->properties, prop);
+	}
+	else
+	{
+		NPWProperty* old_prop = (NPWProperty *)find->data;
+		
+		if (old_prop->language <= prop->language)
+		{
+			npw_property_free (old_prop);
+			find->data = prop;
+		}
+		else
+		{
+			npw_property_free (prop);
+			prop = old_prop;
+		}
+	}
+	
+	return prop;
 }
diff --git a/plugins/project-wizard/property.h b/plugins/project-wizard/property.h
index d50a65e..0002ba4 100644
--- a/plugins/project-wizard/property.h
+++ b/plugins/project-wizard/property.h
@@ -74,6 +74,7 @@ typedef enum {
 NPWProperty* npw_property_new (void);
 void npw_property_free (NPWProperty* prop);
 
+void npw_property_set_language (NPWProperty* prop, gint language);
 void npw_property_set_type (NPWProperty* prop, NPWPropertyType type);
 void npw_property_set_string_type (NPWProperty* prop, const gchar* type);
 NPWPropertyType npw_property_get_type (const NPWProperty* prop);
@@ -103,7 +104,7 @@ gboolean npw_property_save_value_from_widget (NPWProperty* prop);
 gboolean npw_property_remove_value (NPWProperty* prop);
 const char* npw_property_get_value (const NPWProperty* prop);
 
-gboolean npw_property_add_list_item (NPWProperty* prop, const char* name, const gchar* label);
+gboolean npw_property_add_list_item (NPWProperty* prop, const char* name, const gchar* label, gint language);
 
 void npw_property_set_mandatory_option (NPWProperty* prop, gboolean value);
 void npw_property_set_summary_option (NPWProperty* prop, gboolean value);
@@ -117,6 +118,8 @@ NPWPropertyBooleanValue npw_property_get_exist_option (const NPWProperty* prop);
 NPWPage* npw_page_new (GHashTable* value);
 void npw_page_free (NPWPage* page);
 
+gboolean npw_page_set_language (NPWPage* page, gint language);
+
 void npw_page_set_name (NPWPage* page, const gchar* name);
 const gchar* npw_page_get_name (const NPWPage* page);
 
@@ -130,6 +133,6 @@ void npw_page_set_widget (NPWPage* page, GtkWidget *widget);
 GtkWidget *npw_page_get_widget (const NPWPage *page);
 
 void npw_page_foreach_property (const NPWPage* page, GFunc func, gpointer data);
-void npw_page_add_property (NPWPage* page, NPWProperty* prop);
+NPWProperty *npw_page_add_property (NPWPage* page, NPWProperty* prop);
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]