diff options
Diffstat (limited to 'capplets/appearance/mate-wp-xml.c')
-rw-r--r-- | capplets/appearance/mate-wp-xml.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/capplets/appearance/mate-wp-xml.c b/capplets/appearance/mate-wp-xml.c new file mode 100644 index 00000000..2157acf7 --- /dev/null +++ b/capplets/appearance/mate-wp-xml.c @@ -0,0 +1,451 @@ +/* + * Authors: Rodney Dawes <[email protected]> + * + * Copyright 2003-2006 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * 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 Street #330, Boston, MA 02111-1307, USA. + * + */ + +#include "appearance.h" +#include "mate-wp-item.h" +#include <gio/gio.h> +#include <string.h> +#include <libxml/parser.h> + +static gboolean mate_wp_xml_get_bool (const xmlNode * parent, + const gchar * prop_name) { + xmlChar * prop; + gboolean ret_val = FALSE; + + g_return_val_if_fail (parent != NULL, FALSE); + g_return_val_if_fail (prop_name != NULL, FALSE); + + prop = xmlGetProp ((xmlNode *) parent, (xmlChar*)prop_name); + if (prop != NULL) { + if (!g_ascii_strcasecmp ((gchar *)prop, "true") || !g_ascii_strcasecmp ((gchar *)prop, "1")) { + ret_val = TRUE; + } else { + ret_val = FALSE; + } + g_free (prop); + } + + return ret_val; +} + +static void mate_wp_xml_set_bool (const xmlNode * parent, + const xmlChar * prop_name, gboolean value) { + g_return_if_fail (parent != NULL); + g_return_if_fail (prop_name != NULL); + + if (value) { + xmlSetProp ((xmlNode *) parent, prop_name, (xmlChar *)"true"); + } else { + xmlSetProp ((xmlNode *) parent, prop_name, (xmlChar *)"false"); + } +} + +static void mate_wp_load_legacy (AppearanceData *data) { + FILE * fp; + gchar * foo, * filename; + + filename = g_build_filename (g_get_home_dir (), ".mate2", + "wallpapers.list", NULL); + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) { + if ((fp = fopen (filename, "r")) != NULL) { + foo = (gchar *) g_malloc (sizeof (gchar) * 4096); + while (fgets (foo, 4096, fp)) { + MateWPItem * item; + + if (foo[strlen (foo) - 1] == '\n') { + foo[strlen (foo) - 1] = '\0'; + } + + item = g_hash_table_lookup (data->wp_hash, foo); + if (item != NULL) { + continue; + } + + if (!g_file_test (foo, G_FILE_TEST_EXISTS)) { + continue; + } + + item = mate_wp_item_new (foo, data->wp_hash, data->thumb_factory); + if (item != NULL && item->fileinfo == NULL) { + mate_wp_item_free (item); + } + } + fclose (fp); + g_free (foo); + } + } + + g_free (filename); +} + +static void mate_wp_xml_load_xml (AppearanceData *data, + const gchar * filename) { + xmlDoc * wplist; + xmlNode * root, * list, * wpa; + xmlChar * nodelang; + const gchar * const * syslangs; + GdkColor color1, color2; + gint i; + + wplist = xmlParseFile (filename); + + if (!wplist) + return; + + syslangs = g_get_language_names (); + + root = xmlDocGetRootElement (wplist); + + for (list = root->children; list != NULL; list = list->next) { + if (!strcmp ((gchar *)list->name, "wallpaper")) { + MateWPItem * wp; + gchar *pcolor = NULL, *scolor = NULL; + gchar *s; + gboolean have_scale = FALSE, have_shade = FALSE; + + wp = g_new0 (MateWPItem, 1); + + wp->deleted = mate_wp_xml_get_bool (list, "deleted"); + + for (wpa = list->children; wpa != NULL; wpa = wpa->next) { + if (wpa->type == XML_COMMENT_NODE) { + continue; + } else if (!strcmp ((gchar *)wpa->name, "filename")) { + if (wpa->last != NULL && wpa->last->content != NULL) { + const char * none = "(none)"; + gchar *content = g_strstrip ((gchar *)wpa->last->content); + + if (!strcmp (content, none)) + wp->filename = g_strdup (content); + else if (g_utf8_validate (content, -1, NULL) && + g_file_test (content, G_FILE_TEST_EXISTS)) + wp->filename = g_strdup (content); + else + wp->filename = g_filename_from_utf8 (content, -1, NULL, NULL, NULL); + } else { + break; + } + } else if (!strcmp ((gchar *)wpa->name, "name")) { + if (wpa->last != NULL && wpa->last->content != NULL) { + nodelang = xmlNodeGetLang (wpa->last); + + if (wp->name == NULL && nodelang == NULL) { + wp->name = g_strdup (g_strstrip ((gchar *)wpa->last->content)); + } else { + for (i = 0; syslangs[i] != NULL; i++) { + if (!strcmp (syslangs[i], (gchar *)nodelang)) { + g_free (wp->name); + wp->name = g_strdup (g_strstrip ((gchar *)wpa->last->content)); + break; + } + } + } + + xmlFree (nodelang); + } else { + break; + } + } else if (!strcmp ((gchar *)wpa->name, "options")) { + if (wpa->last != NULL) { + wp->options = wp_item_string_to_option (g_strstrip ((gchar *)wpa->last->content)); + have_scale = TRUE; + } + } else if (!strcmp ((gchar *)wpa->name, "shade_type")) { + if (wpa->last != NULL) { + wp->shade_type = wp_item_string_to_shading (g_strstrip ((gchar *)wpa->last->content)); + have_shade = TRUE; + } + } else if (!strcmp ((gchar *)wpa->name, "pcolor")) { + if (wpa->last != NULL) { + pcolor = g_strdup (g_strstrip ((gchar *)wpa->last->content)); + } + } else if (!strcmp ((gchar *)wpa->name, "scolor")) { + if (wpa->last != NULL) { + scolor = g_strdup (g_strstrip ((gchar *)wpa->last->content)); + } + } else if (!strcmp ((gchar *)wpa->name, "text")) { + /* Do nothing here, libxml2 is being weird */ + } else { + g_warning ("Unknown Tag: %s", wpa->name); + } + } + + /* Make sure we don't already have this one and that filename exists */ + if (wp->filename == NULL || + g_hash_table_lookup (data->wp_hash, wp->filename) != NULL) { + + mate_wp_item_free (wp); + g_free (pcolor); + g_free (scolor); + continue; + } + + /* Verify the colors and alloc some GdkColors here */ + if (!have_scale) { + s = mateconf_client_get_string (data->client, WP_OPTIONS_KEY, NULL); + wp->options = wp_item_string_to_option (s); + g_free (s); + } + + if (!have_shade) { + s = mateconf_client_get_string (data->client, WP_SHADING_KEY, NULL); + wp->shade_type = wp_item_string_to_shading (s); + g_free (s); + } + + if (pcolor == NULL) { + pcolor = mateconf_client_get_string (data->client, + WP_PCOLOR_KEY, NULL); + } + if (scolor == NULL) { + scolor = mateconf_client_get_string (data->client, + WP_SCOLOR_KEY, NULL); + } + gdk_color_parse (pcolor, &color1); + gdk_color_parse (scolor, &color2); + g_free (pcolor); + g_free (scolor); + + wp->pcolor = gdk_color_copy (&color1); + wp->scolor = gdk_color_copy (&color2); + + if ((wp->filename != NULL && + g_file_test (wp->filename, G_FILE_TEST_EXISTS)) || + !strcmp (wp->filename, "(none)")) { + wp->fileinfo = mate_wp_info_new (wp->filename, data->thumb_factory); + + if (wp->name == NULL || !strcmp (wp->filename, "(none)")) { + g_free (wp->name); + wp->name = g_strdup (wp->fileinfo->name); + } + + mate_wp_item_ensure_mate_bg (wp); + mate_wp_item_update_description (wp); + g_hash_table_insert (data->wp_hash, wp->filename, wp); + } else { + mate_wp_item_free (wp); + wp = NULL; + } + } + } + xmlFreeDoc (wplist); +} + +static void mate_wp_file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + AppearanceData *data) { + gchar * filename; + + switch (event_type) { + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_CREATED: + filename = g_file_get_path (file); + mate_wp_xml_load_xml (data, filename); + g_free (filename); + break; + default: + break; + } +} + +static void mate_wp_xml_add_monitor (GFile *directory, + AppearanceData *data) { + GFileMonitor *monitor; + GError *error = NULL; + + monitor = g_file_monitor_directory (directory, + G_FILE_MONITOR_NONE, + NULL, + &error); + if (error != NULL) { + gchar *path; + + path = g_file_get_parse_name (directory); + g_warning ("Unable to monitor directory %s: %s", + path, error->message); + g_error_free (error); + g_free (path); + return; + } + + g_signal_connect (monitor, "changed", + G_CALLBACK (mate_wp_file_changed), + data); +} + +static void mate_wp_xml_load_from_dir (const gchar *path, + AppearanceData *data) { + GFile *directory; + GFileEnumerator *enumerator; + GError *error = NULL; + GFileInfo *info; + + if (!g_file_test (path, G_FILE_TEST_IS_DIR)) { + return; + } + + directory = g_file_new_for_path (path); + enumerator = g_file_enumerate_children (directory, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + &error); + if (error != NULL) { + g_warning ("Unable to check directory %s: %s", path, error->message); + g_error_free (error); + g_object_unref (directory); + return; + } + + while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL))) { + const gchar *filename; + gchar *fullpath; + + filename = g_file_info_get_name (info); + fullpath = g_build_filename (path, filename, NULL); + g_object_unref (info); + + mate_wp_xml_load_xml (data, fullpath); + g_free (fullpath); + } + g_file_enumerator_close (enumerator, NULL, NULL); + + mate_wp_xml_add_monitor (directory, data); + + g_object_unref (directory); +} + +void mate_wp_xml_load_list (AppearanceData *data) { + const char * const *system_data_dirs; + gchar * datadir; + gchar * wpdbfile; + gint i; + + wpdbfile = g_build_filename (g_get_home_dir (), + ".mate2", + "backgrounds.xml", + NULL); + + if (g_file_test (wpdbfile, G_FILE_TEST_EXISTS)) { + mate_wp_xml_load_xml (data, wpdbfile); + } else { + g_free (wpdbfile); + wpdbfile = g_build_filename (g_get_home_dir (), + ".mate2", + "wp-list.xml", + NULL); + if (g_file_test (wpdbfile, G_FILE_TEST_EXISTS)) { + mate_wp_xml_load_xml (data, wpdbfile); + } + } + g_free (wpdbfile); + + datadir = g_build_filename (g_get_user_data_dir (), + "mate-background-properties", + NULL); + mate_wp_xml_load_from_dir (datadir, data); + g_free (datadir); + + system_data_dirs = g_get_system_data_dirs (); + for (i = 0; system_data_dirs[i]; i++) { + datadir = g_build_filename (system_data_dirs[i], + "mate-background-properties", + NULL); + mate_wp_xml_load_from_dir (datadir, data); + g_free (datadir); + } + + mate_wp_xml_load_from_dir (WALLPAPER_DATADIR, data); + + mate_wp_load_legacy (data); +} + +static void mate_wp_list_flatten (const gchar * key, MateWPItem * item, + GSList ** list) { + g_return_if_fail (key != NULL); + g_return_if_fail (item != NULL); + + *list = g_slist_prepend (*list, item); +} + +void mate_wp_xml_save_list (AppearanceData *data) { + xmlDoc * wplist; + xmlNode * root, * wallpaper, * item; + GSList * list = NULL; + gchar * wpfile; + + g_hash_table_foreach (data->wp_hash, + (GHFunc) mate_wp_list_flatten, &list); + g_hash_table_destroy (data->wp_hash); + list = g_slist_reverse (list); + + wpfile = g_build_filename (g_get_home_dir (), + "/.mate2", + "backgrounds.xml", + NULL); + + xmlKeepBlanksDefault (0); + + wplist = xmlNewDoc ((xmlChar *)"1.0"); + xmlCreateIntSubset (wplist, (xmlChar *)"wallpapers", NULL, (xmlChar *)"mate-wp-list.dtd"); + root = xmlNewNode (NULL, (xmlChar *)"wallpapers"); + xmlDocSetRootElement (wplist, root); + + while (list != NULL) { + MateWPItem * wpitem = list->data; + const char * none = "(none)"; + gchar * filename; + const gchar * scale, * shade; + gchar * pcolor, * scolor; + + if (!strcmp (wpitem->filename, none) || + (g_utf8_validate (wpitem->filename, -1, NULL) && + g_file_test (wpitem->filename, G_FILE_TEST_EXISTS))) + filename = g_strdup (wpitem->filename); + else + filename = g_filename_to_utf8 (wpitem->filename, -1, NULL, NULL, NULL); + + pcolor = gdk_color_to_string (wpitem->pcolor); + scolor = gdk_color_to_string (wpitem->scolor); + scale = wp_item_option_to_string (wpitem->options); + shade = wp_item_shading_to_string (wpitem->shade_type); + + wallpaper = xmlNewChild (root, NULL, (xmlChar *)"wallpaper", NULL); + mate_wp_xml_set_bool (wallpaper, (xmlChar *)"deleted", wpitem->deleted); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"name", (xmlChar *)wpitem->name); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)filename); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"options", (xmlChar *)scale); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"shade_type", (xmlChar *)shade); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"pcolor", (xmlChar *)pcolor); + item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"scolor", (xmlChar *)scolor); + g_free (pcolor); + g_free (scolor); + g_free (filename); + + list = g_slist_delete_link (list, list); + mate_wp_item_free (wpitem); + } + xmlSaveFormatFile (wpfile, wplist, 1); + xmlFreeDoc (wplist); + g_free (wpfile); +} |