Merge installed and user's files

master
Yevgen Muntyan 2006-08-23 02:41:56 -05:00
parent cd412fc8ae
commit bc5282ce26
2 changed files with 315 additions and 76 deletions

View File

@ -46,6 +46,8 @@
#define PROP_ENABLED "enabled" #define PROP_ENABLED "enabled"
#define PROP_OS "os" #define PROP_OS "os"
#define PROP_ID "id" #define PROP_ID "id"
#define PROP_DELETED "deleted"
#define PROP_BUILTIN "builtin"
enum { enum {
PROP_0, PROP_0,
@ -158,30 +160,44 @@ tools_store_add (MooUserToolType type,
} }
static char * static void
find_user_tools_file (int type) find_user_tools_file (int type,
char ***sys_files_p,
char **user_file_p)
{ {
char **files; char **files;
guint n_files; guint n_files;
char *filename = NULL;
int i; int i;
GPtrArray *sys_files = NULL;
*sys_files_p = NULL;
*user_file_p = NULL;
files = moo_get_data_files (FILENAMES[type], MOO_DATA_SHARE, &n_files); files = moo_get_data_files (FILENAMES[type], MOO_DATA_SHARE, &n_files);
if (!n_files) if (!n_files)
return NULL; return;
for (i = n_files - 1; i >= 0; --i) if (g_file_test (files[n_files - 1], G_FILE_TEST_EXISTS))
*user_file_p = g_strdup (files[n_files - 1]);
for (i = 0; i < (int) n_files - 1; ++i)
{ {
if (g_file_test (files[i], G_FILE_TEST_EXISTS)) if (g_file_test (files[i], G_FILE_TEST_EXISTS))
{ {
filename = g_strdup (files[i]); if (!sys_files)
break; sys_files = g_ptr_array_new ();
g_ptr_array_add (sys_files, g_strdup (files[i]));
} }
} }
if (sys_files)
{
g_ptr_array_add (sys_files, NULL);
*sys_files_p = (char**) g_ptr_array_free (sys_files, FALSE);
}
g_strfreev (files); g_strfreev (files);
return filename;
} }
@ -411,15 +427,28 @@ parse_element (MooMarkupNode *node,
info->position = MOO_USER_TOOL_POS_END; info->position = MOO_USER_TOOL_POS_END;
info->id = g_strdup (moo_markup_get_prop (node, PROP_ID)); info->id = g_strdup (moo_markup_get_prop (node, PROP_ID));
info->name = g_strdup (moo_markup_get_prop (node, PROP_NAME)); info->name = g_strdup (moo_markup_get_prop (node, PROP_NAME));
info->enabled = moo_markup_get_bool_prop (node, PROP_ENABLED, TRUE); info->enabled = moo_markup_get_bool_prop (node, PROP_ENABLED, TRUE);
info->deleted = moo_markup_get_bool_prop (node, PROP_DELETED, FALSE);
info->builtin = moo_markup_get_bool_prop (node, PROP_BUILTIN, FALSE);
if (!info->id)
{
g_warning ("tool id missing in file %s", file);
_moo_user_tool_info_unref (info);
return NULL;
}
if (info->deleted || info->builtin)
return info;
os = moo_markup_get_prop (node, PROP_OS); os = moo_markup_get_prop (node, PROP_OS);
#ifdef __WIN32__ if (!os || !os[0])
info->os_type = (!os || !g_ascii_strncasecmp (os, "win", 3)) ? MOO_USER_TOOL_WIN32 : MOO_USER_TOOL_UNIX; info->os_type = MOO_USER_TOOL_THIS_OS;
#else else if (!g_ascii_strncasecmp (os, "win", 3))
info->os_type = (!os || !g_ascii_strcasecmp (os, "unix")) ? MOO_USER_TOOL_UNIX : MOO_USER_TOOL_WIN32; info->os_type = MOO_USER_TOOL_WIN32;
#endif else
info->os_type = MOO_USER_TOOL_UNIX;
for (child = node->children; child != NULL; child = child->next) for (child = node->children; child != NULL; child = child->next)
{ {
@ -536,23 +565,18 @@ parse_doc (MooMarkupDoc *doc,
} }
GSList * static GSList *
_moo_edit_parse_user_tools (MooUserToolType type) parse_file_simple (const char *filename,
MooUserToolType type)
{ {
char *file;
MooMarkupDoc *doc; MooMarkupDoc *doc;
GError *error = NULL; GError *error = NULL;
GSList *list = NULL; GSList *list = NULL;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (type < N_TOOLS, NULL); g_return_val_if_fail (type < N_TOOLS, NULL);
_moo_command_init (); doc = moo_markup_parse_file (filename, &error);
file = find_user_tools_file (type);
if (!file)
return NULL;
doc = moo_markup_parse_file (file, &error);
if (doc) if (doc)
{ {
@ -561,39 +585,116 @@ _moo_edit_parse_user_tools (MooUserToolType type)
} }
else else
{ {
g_warning ("could not load file '%s': %s", file, error->message); g_warning ("could not load file '%s': %s", filename, error->message);
g_error_free (error); g_error_free (error);
} }
g_free (file);
return list; return list;
} }
static void
static GHashTable * parse_file (const char *filename,
collect_ids (const GSList *list) MooUserToolType type,
GSList **list,
GHashTable *ids)
{ {
GHashTable *ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); GSList *new_list;
while (list) new_list = parse_file_simple (filename, type);
if (!new_list)
return;
while (new_list)
{ {
const MooUserToolInfo *info = list->data; MooUserToolInfo *info, *old_info;
GSList *old_link;
if (info->id) info = new_list->data;
g_hash_table_insert (ids, g_strdup (info->id), GINT_TO_POINTER (TRUE)); g_return_if_fail (info->id != NULL);
list = list->next; old_link = g_hash_table_lookup (ids, info->id);
old_info = old_link ? old_link->data : NULL;
if (old_link)
{
*list = g_slist_delete_link (*list, old_link);
g_hash_table_remove (ids, info->id);
} }
return ids; if (info->deleted)
{
_moo_user_tool_info_unref (info);
info = NULL;
}
else if (info->builtin)
{
_moo_user_tool_info_unref (info);
info = old_info ? _moo_user_tool_info_ref (old_info) : NULL;
}
if (info)
{
*list = g_slist_prepend (*list, info);
g_hash_table_insert (ids, g_strdup (info->id), *list);
}
if (old_info)
_moo_user_tool_info_unref (old_info);
new_list = g_slist_delete_link (new_list, new_list);
}
} }
static const char * static GSList *
generate_id (const MooUserToolInfo *info, parse_user_tools (MooUserToolType type,
GHashTable **ids_p,
gboolean sys_only)
{
char **sys_files, *user_file;
GSList *list = NULL;
GHashTable *ids = NULL;
char **p;
g_return_val_if_fail (type < N_TOOLS, NULL);
_moo_command_init ();
find_user_tools_file (type, &sys_files, &user_file);
ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (p = sys_files; p && *p; ++p)
parse_file (*p, type, &list, ids);
if (!sys_only && user_file)
parse_file (user_file, type, &list, ids);
if (ids_p)
*ids_p = ids;
else
g_hash_table_destroy (ids);
g_strfreev (sys_files);
g_free (user_file);
return g_slist_reverse (list);
}
GSList *
_moo_edit_parse_user_tools (MooUserToolType type)
{
g_return_val_if_fail (type < N_TOOLS, NULL);
return parse_user_tools (type, NULL, FALSE);
}
static void
generate_id (MooUserToolInfo *info,
GHashTable *ids) GHashTable *ids)
{ {
char *base, *name; char *base, *name;
const char *id;
g_return_if_fail (info->id == NULL);
if (info->name) if (info->name)
name = get_name (info->name); name = get_name (info->name);
@ -605,8 +706,7 @@ generate_id (const MooUserToolInfo *info,
if (!g_hash_table_lookup (ids, base)) if (!g_hash_table_lookup (ids, base))
{ {
id = base; info->id = base;
g_hash_table_insert (ids, base, GINT_TO_POINTER (TRUE));
base = NULL; base = NULL;
} }
else else
@ -619,8 +719,7 @@ generate_id (const MooUserToolInfo *info,
if (!g_hash_table_lookup (ids, tmp)) if (!g_hash_table_lookup (ids, tmp))
{ {
id = tmp; info->id = tmp;
g_hash_table_insert (ids, tmp, GINT_TO_POINTER (TRUE));
break; break;
} }
@ -632,40 +731,177 @@ generate_id (const MooUserToolInfo *info,
g_free (name); g_free (name);
g_free (base); g_free (base);
return id; }
static void
assign_missing_ids (GSList *list)
{
GSList *l;
GHashTable *ids;
ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (l = list; l != NULL; l = l->next)
{
MooUserToolInfo *info = l->data;
if (info->id)
g_hash_table_insert (ids, g_strdup (info->id), l);
}
for (l = list; l != NULL; l = l->next)
{
MooUserToolInfo *info = l->data;
if (!info->id)
{
generate_id (info, ids);
g_hash_table_insert (ids, g_strdup (info->id), l);
}
}
g_hash_table_destroy (ids);
}
static void
add_deleted (const char *id,
GSList *link,
GSList **list)
{
MooUserToolInfo *info;
g_assert (!strcmp (((MooUserToolInfo*)link->data)->id, id));
info = _moo_user_tool_info_new ();
info->id = g_strdup (id);
info->deleted = TRUE;
*list = g_slist_prepend (*list, info);
}
static gboolean
string_equal (const char *s1,
const char *s2)
{
return !strcmp (s1 ? s1 : "", s2 ? s2 : "");
}
static gboolean
info_equal (MooUserToolInfo *info1,
MooUserToolInfo *info2)
{
if (info1 == info2)
return TRUE;
if (info1->deleted)
return info2->deleted != 0;
if (info1->builtin)
return info2->builtin != 0;
if (!info1->enabled != !info2->enabled)
return FALSE;
return info1->position == info2->position &&
info1->os_type == info2->os_type &&
info1->position == info2->position &&
info1->position == info2->position &&
info1->cmd_type == info2->cmd_type &&
string_equal (info1->name, info2->name) &&
string_equal (info1->accel, info2->accel) &&
string_equal (info1->menu, info2->menu) &&
string_equal (info1->langs, info2->langs) &&
string_equal (info1->options, info2->options) &&
_moo_command_type_data_equal (info1->cmd_type, info1->cmd_data, info2->cmd_data);
}
static GSList *
generate_real_list (MooUserToolType type,
GSList *list)
{
GSList *real_list = NULL;
GSList *sys_list;
GHashTable *sys_ids;
sys_list = parse_user_tools (type, &sys_ids, TRUE);
assign_missing_ids (list);
while (list)
{
MooUserToolInfo *new_info = NULL;
MooUserToolInfo *info = list->data;
GSList *sys_link;
sys_link = g_hash_table_lookup (sys_ids, info->id);
if (sys_link)
{
MooUserToolInfo *sys_info = sys_link->data;
if (info_equal (sys_info, info))
{
new_info = _moo_user_tool_info_new ();
new_info->id = g_strdup (sys_info->id);
new_info->builtin = TRUE;
}
else
{
new_info = _moo_user_tool_info_ref (info);
}
g_hash_table_remove (sys_ids, info->id);
}
else
{
new_info = _moo_user_tool_info_ref (info);
}
real_list = g_slist_prepend (real_list, new_info);
list = list->next;
}
g_hash_table_foreach (sys_ids, (GHFunc) add_deleted, &real_list);
g_hash_table_destroy (sys_ids);
g_slist_foreach (sys_list, (GFunc) _moo_user_tool_info_unref, NULL);
g_slist_free (sys_list);
return g_slist_reverse (real_list);
} }
void void
_moo_edit_save_user_tools (MooUserToolType type, _moo_edit_save_user_tools (MooUserToolType type,
const GSList *list) GSList *user_list)
{ {
MooMarkupDoc *doc; MooMarkupDoc *doc;
MooMarkupNode *root; MooMarkupNode *root;
GError *error = NULL; GError *error = NULL;
char *string; char *string;
GHashTable *ids; GSList *list;
g_return_if_fail (type < N_TOOLS); g_return_if_fail (type < N_TOOLS);
doc = moo_markup_doc_new ("tools"); doc = moo_markup_doc_new ("tools");
root = moo_markup_create_root_element (doc, ELEMENT_TOOLS); root = moo_markup_create_root_element (doc, ELEMENT_TOOLS);
ids = collect_ids (list); list = generate_real_list (type, user_list);
while (list) while (list)
{ {
MooMarkupNode *node; MooMarkupNode *node;
const MooUserToolInfo *info = list->data; MooUserToolInfo *info = list->data;
const char *id;
node = moo_markup_create_element (root, ELEMENT_TOOL); node = moo_markup_create_element (root, ELEMENT_TOOL);
moo_markup_set_prop (node, PROP_ID, info->id);
if (info->id) if (info->deleted)
id = info->id; {
moo_markup_set_bool_prop (node, PROP_DELETED, TRUE);
}
else if (info->builtin)
{
moo_markup_set_bool_prop (node, PROP_BUILTIN, TRUE);
}
else else
id = generate_id (info, ids); {
moo_markup_set_prop (node, PROP_ID, id);
if (info->name && info->name[0]) if (info->name && info->name[0])
moo_markup_set_prop (node, PROP_NAME, info->name); moo_markup_set_prop (node, PROP_NAME, info->name);
if (info->accel && info->accel[0]) if (info->accel && info->accel[0])
@ -681,8 +917,10 @@ _moo_edit_save_user_tools (MooUserToolType type,
_moo_command_format_markup (node, info->cmd_data, _moo_command_format_markup (node, info->cmd_data,
info->cmd_type, info->options); info->cmd_type, info->options);
}
list = list->next; _moo_user_tool_info_unref (info);
list = g_slist_delete_link (list, list);
} }
string = moo_markup_node_get_pretty_string (MOO_MARKUP_NODE (doc), 2); string = moo_markup_node_get_pretty_string (MOO_MARKUP_NODE (doc), 2);
@ -697,7 +935,6 @@ _moo_edit_save_user_tools (MooUserToolType type,
g_message ("done"); g_message ("done");
g_hash_table_destroy (ids);
g_free (string); g_free (string);
moo_markup_doc_unref (doc); moo_markup_doc_unref (doc);
} }

View File

@ -51,13 +51,15 @@ typedef struct {
char *langs; char *langs;
char *options; char *options;
MooUserToolPosition position; MooUserToolPosition position;
gboolean enabled;
MooUserToolOSType os_type; MooUserToolOSType os_type;
MooCommandType *cmd_type; MooCommandType *cmd_type;
MooCommandData *cmd_data; MooCommandData *cmd_data;
MooUserToolType type; MooUserToolType type;
char *file; char *file;
guint ref_count; guint ref_count : 29;
guint enabled : 1;
guint deleted : 1;
guint builtin : 1;
} MooUserToolInfo; } MooUserToolInfo;
GType _moo_user_tool_info_get_type (void) G_GNUC_CONST; GType _moo_user_tool_info_get_type (void) G_GNUC_CONST;
@ -74,7 +76,7 @@ typedef void (*MooToolFileParseFunc) (MooUserToolInfo *info,
/* caller must free the list and unref() the contents */ /* caller must free the list and unref() the contents */
GSList *_moo_edit_parse_user_tools (MooUserToolType type); GSList *_moo_edit_parse_user_tools (MooUserToolType type);
void _moo_edit_save_user_tools (MooUserToolType type, void _moo_edit_save_user_tools (MooUserToolType type,
const GSList *info); GSList *user_info);
G_END_DECLS G_END_DECLS