Mercurial > grim > purple-plugin-pack
view autoprofile/widget.c @ 1028:314cfd774bc4
s/purple.guifications.org/plugins.guifications.org/
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 06 Aug 2009 12:30:12 -0700 |
parents | d98a0662234f |
children |
line wrap: on
line source
/*--------------------------------------------------------------------------* * AUTOPROFILE * * * * A Purple away message and profile manager that supports dynamic text * * * * AutoProfile is the legal property of its developers. Please refer to * * the COPYRIGHT file distributed with this source distribution. * * * * 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 "../common/pp_internal.h" #include "widget.h" #include "utility.h" #include <ctype.h> #include <string.h> static GStaticMutex widget_mutex = G_STATIC_MUTEX_INIT; static GList *widgets = NULL; static GHashTable *identifiers = NULL; static GRand *r = NULL; static char *widget_pref = "/plugins/gtk/autoprofile/widgets/widget_ids"; static void ap_widget_init_default_statuses () { // Make sure we don't keep on readding the default statuses if a user // deleted them if (!purple_prefs_exists (widget_pref)) { purple_prefs_add_none ("/plugins/gtk/autoprofile/widgets/42"); purple_prefs_add_string ( "/plugins/gtk/autoprofile/widgets/42/component", "Timestamp"); purple_prefs_add_string ( "/plugins/gtk/autoprofile/widgets/42/alias", "Timestamp"); purple_prefs_add_string ( "/plugins/gtk/autoprofile/widgets/42/timestamp_format", "Automatically created at %I:%M %p"); } } void ap_widget_init () { GList *node; ap_widget_init_default_statuses (); node = g_list_append (NULL, g_strdup ("42")); purple_prefs_add_string_list (widget_pref, node); free_string_list (node); } /* Basic functions */ static gchar *strip_whitespace (const gchar *text) { gchar *result, *end, *search; while (isspace (*text)) { text++; } end = NULL; search = result = g_strdup (text); while (*search) { if (end == NULL && isspace (*search)) { end = search; } if (!isspace (*search)) { end = NULL; } search++; } if (end != NULL) *end = '\0'; return result; } static void update_widget_ids () { GList *cur_node, *ids; struct widget *cur_widget; ids = NULL; for (cur_node = widgets; cur_node != NULL; cur_node = cur_node->next) { cur_widget = (struct widget *) cur_node->data; ids = g_list_append (ids, cur_widget->wid); } purple_prefs_set_string_list (widget_pref, ids); g_list_free (ids); } // Mutex is ALREADY HELD when this function is called static struct widget *ap_widget_find_internal (const gchar *search_text) { GList *cur_node; struct widget *cur_widget; gchar *alias; alias = strip_whitespace (search_text); cur_node = widgets; while (cur_node) { cur_widget = (struct widget *) cur_node->data; if (!purple_utf8_strcasecmp (alias, cur_widget->alias)) { free (alias); return cur_widget; } cur_node = cur_node->next; } free (alias); return NULL; } struct widget *ap_widget_find (const gchar *search_text) { struct widget *w; g_static_mutex_lock (&widget_mutex); w = ap_widget_find_internal (search_text); g_static_mutex_unlock (&widget_mutex); return w; } struct widget *ap_widget_find_by_identifier (const gchar *search_text) { struct widget *w; g_static_mutex_lock (&widget_mutex); w = (struct widget *) g_hash_table_lookup (identifiers, search_text); g_static_mutex_unlock (&widget_mutex); return w; } void ap_widget_start () { GList *widget_identifiers, *widget_identifiers_start; GString *pref_name; const gchar *identifier, *component_identifier; struct component *comp; struct widget *w; g_static_mutex_lock (&widget_mutex); r = g_rand_new (); widgets = NULL; identifiers = g_hash_table_new (g_str_hash, g_str_equal); pref_name = g_string_new (""); widget_identifiers_start = purple_prefs_get_string_list (widget_pref); for (widget_identifiers = widget_identifiers_start; widget_identifiers != NULL; widget_identifiers = widget_identifiers->next) { g_string_printf (pref_name, "/plugins/gtk/autoprofile/widgets/%s/component", (gchar *) widget_identifiers->data); component_identifier = purple_prefs_get_string (pref_name->str); if (component_identifier == NULL) { ap_debug_error ("widget", "widget does not have component information"); continue; } comp = ap_component_get_component (component_identifier); if (comp == NULL) { ap_debug_error ("widget", "no component matches widget identifier"); continue; } g_string_printf (pref_name, "/plugins/gtk/autoprofile/widgets/%s/alias", (gchar *) widget_identifiers->data); identifier = purple_prefs_get_string (pref_name->str); if (identifier == NULL) { ap_debug_error ("widget", "widget does not have alias information"); continue; } w = ap_widget_find_internal (identifier); if (w != NULL) { ap_debug_error ("widget", "widget alias already in use"); continue; } w = (struct widget *) malloc (sizeof (struct widget)); w->alias = g_strdup (identifier); w->wid = g_strdup ((gchar *) widget_identifiers->data); w->component = comp; w->data = g_hash_table_new (NULL, NULL); widgets = g_list_append (widgets, w); g_hash_table_insert (identifiers, w->wid, w); if (w->component->load) { w->component->load (w); } g_string_printf (pref_name, "loaded saved widget with alias %s and identifier %s", w->alias, w->wid); ap_debug_misc ("widget", pref_name->str); } free_string_list (widget_identifiers_start); g_string_free (pref_name, TRUE); g_static_mutex_unlock (&widget_mutex); ap_widget_gtk_start (); } void ap_widget_finish () { GList *tmp; struct widget *w; g_static_mutex_lock (&widget_mutex); ap_widget_gtk_finish (); g_hash_table_destroy (identifiers); identifiers = NULL; while (widgets) { w = (struct widget *) widgets->data; if (w->component->unload) { w->component->unload (w); } g_hash_table_destroy (w->data); free (w->alias); free (w->wid); free (w); tmp = widgets->next; g_list_free_1 (widgets); widgets = tmp; } g_rand_free (r); r = NULL; g_static_mutex_unlock (&widget_mutex); } gboolean ap_widget_has_content_changed () { GList *node; struct widget *w; gboolean changed = FALSE; g_static_mutex_lock (&widget_mutex); for (node = widgets; node != NULL; node = node->next) { w = (struct widget *) node->data; if (w->component->has_content_changed == NULL || w->component->has_content_changed (w)) { changed = TRUE; break; } } g_static_mutex_unlock (&widget_mutex); return changed; } GList *ap_widget_get_widgets () { GList *result; g_static_mutex_lock (&widget_mutex); result = g_list_copy (widgets); g_static_mutex_unlock (&widget_mutex); return result; } struct widget *ap_widget_create (struct component *comp) { struct widget *w; GString *s; gchar *identifier, *alias; int i; GList *node; g_static_mutex_lock (&widget_mutex); // Sanity check to make sure we dont "delete" old widgets by // overriding old pref if (identifiers == NULL) { ap_debug_warn ("widget", "tried to create widget when variables unitialized"); g_static_mutex_unlock (&widget_mutex); return NULL; } ap_debug ("widget", "instantiating new widget from component"); s = g_string_new (""); // Get alias w = ap_widget_find_internal (comp->identifier); alias = NULL; // Stupid compiler if (w == NULL) { alias = g_strdup (comp->identifier); } else { for (i = 1; i < 10000; i++) { g_string_printf (s, "%s%d", comp->identifier, i); w = ap_widget_find_internal (s->str); if (w == NULL) { alias = g_strdup (s->str); break; } } if (i == 10000) { // This would happen....very very rarely... ap_debug_error ("widget", "ran out of aliases for component"); g_string_free (s, TRUE); g_static_mutex_unlock (&widget_mutex); return NULL; } } // Get identifier while (TRUE) { i = g_rand_int (r); g_string_printf (s, "%d", i); node = widgets; while (node) { w = (struct widget *) node->data; if (!strcmp (s->str, w->wid)) { break; } node = node->next; } if (node == NULL) { identifier = g_strdup (s->str); break; } } w = (struct widget *) malloc (sizeof (struct widget)); w->alias = alias; w->wid = identifier; w->component = comp; w->data = g_hash_table_new (NULL, NULL); widgets = g_list_append (widgets, w); g_hash_table_insert (identifiers, w->wid, w); // Modify Purple prefs update_widget_ids (); g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s", w->wid); purple_prefs_add_none (s->str); g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/component", w->wid); purple_prefs_add_string (s->str, w->component->identifier); g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/alias", w->wid); purple_prefs_add_string (s->str, w->alias); // Initialize widget if (w->component->init_pref) { w->component->init_pref (w); } if (w->component->load) { w->component->load (w); } // Cleanup g_string_printf (s, "Created widget with alias %s and identifier %s", alias, identifier); ap_debug ("widget", s->str); g_string_free (s, TRUE); g_static_mutex_unlock (&widget_mutex); return w; } void ap_widget_delete (struct widget *w) { GString *s; if (w == NULL) { ap_debug_error ("widget", "attempt to delete NULL widget"); return; } g_static_mutex_lock (&widget_mutex); // Sanity check to make sure we dont "delete" old widgets by // overriding old pref if (identifiers == NULL) { ap_debug_warn ("widget", "tried to delete widget when variables unitialized"); g_static_mutex_unlock (&widget_mutex); return; } s = g_string_new (""); g_string_printf (s, "Deleting widget with alias %s and identifier %s", w->alias, w->wid); ap_debug ("widget", s->str); widgets = g_list_remove (widgets, w); g_hash_table_remove (identifiers, w->wid); update_widget_ids (); g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s", w->wid); purple_prefs_remove (s->str); g_string_free (s, TRUE); if (w->component->unload) { w->component->unload (w); } g_hash_table_destroy (w->data); free (w->wid); free (w->alias); free (w); g_static_mutex_unlock (&widget_mutex); } // TRUE if rename succeeds, FALSE otherwise gboolean ap_widget_rename (struct widget *orig, const gchar *new_alias) { struct widget *w; GString *s; gchar *orig_alias; g_static_mutex_lock (&widget_mutex); w = ap_widget_find_internal (new_alias); if (w != NULL && w != orig) { g_static_mutex_unlock (&widget_mutex); return FALSE; } orig_alias = orig->alias; orig->alias = g_strdup (new_alias); s = g_string_new (""); g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/alias", orig->wid); purple_prefs_set_string (s->str, new_alias); g_string_printf (s, "Changed alias of widget from %s to %s", orig_alias, new_alias); ap_debug ("widget", s->str); free (orig_alias); g_string_free (s, TRUE); g_static_mutex_unlock (&widget_mutex); return TRUE; } /* Widget data galore! */ void ap_widget_set_data (struct widget *w, int id, gpointer data) { g_static_mutex_lock (&widget_mutex); g_hash_table_insert (w->data, GINT_TO_POINTER(id), data); g_static_mutex_unlock (&widget_mutex); } gpointer ap_widget_get_data (struct widget *w, int id) { gpointer result; g_static_mutex_lock (&widget_mutex); result = g_hash_table_lookup (w->data, GINT_TO_POINTER(id)); g_static_mutex_unlock (&widget_mutex); return result; } /* Widget preferences galore! */ gchar *ap_prefs_get_pref_name (struct widget *w, const char *name) { GString *s; gchar *result; s = g_string_new (""); g_string_append (s, "/plugins/gtk/autoprofile/widgets/"); g_string_append_printf (s, "%s/%s", w->wid, name); result = s->str; g_string_free (s, FALSE); return result; } void ap_prefs_add_bool (struct widget *w, const char *name, gboolean value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_add_bool (pref, value); free (pref); } void ap_prefs_add_int (struct widget *w, const char *name, int value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_add_int (pref, value); free (pref); } void ap_prefs_add_none (struct widget *w, const char *name) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_add_none (pref); free (pref); } void ap_prefs_add_string (struct widget *w, const char *name, const char *value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_add_string (pref, value); free (pref); } void ap_prefs_add_string_list (struct widget *w, const char *name, GList *value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_add_string_list (pref, value); free (pref); } gboolean ap_prefs_get_bool (struct widget *w, const char *name) { gboolean result; gchar *pref = ap_prefs_get_pref_name (w, name); result = purple_prefs_get_bool (pref); free (pref); return result; } int ap_prefs_get_int (struct widget *w, const char *name) { int result; gchar *pref = ap_prefs_get_pref_name (w, name); result = purple_prefs_get_int (pref); free (pref); return result; } const char *ap_prefs_get_string (struct widget *w, const char *name) { const char *result; gchar *pref = ap_prefs_get_pref_name (w, name); result = purple_prefs_get_string (pref); free (pref); return result; } GList *ap_prefs_get_string_list (struct widget *w, const char *name) { GList *result; gchar *pref = ap_prefs_get_pref_name (w, name); result = purple_prefs_get_string_list (pref); free (pref); return result; } void ap_prefs_set_bool (struct widget *w, const char *name, gboolean value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_set_bool (pref, value); free (pref); ap_widget_prefs_updated (w); } void ap_prefs_set_int (struct widget *w, const char *name, int value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_set_int (pref, value); free (pref); ap_widget_prefs_updated (w); } void ap_prefs_set_string (struct widget *w, const char *name, const char *value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_set_string (pref, value); free (pref); ap_widget_prefs_updated (w); } void ap_prefs_set_string_list (struct widget *w, const char *name, GList *value) { gchar *pref = ap_prefs_get_pref_name (w, name); purple_prefs_set_string_list (pref, value); free (pref); ap_widget_prefs_updated (w); }