* Guifications - The end all, be all, toaster popup plugin * Copyright (C) 2003-2005 Gary Kramlich * 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 "gf_event_info.h" #include "gf_gtk_utils.h" #include "gf_notification.h" #include "gf_preferences.h" #include "gf_theme_ops.h" /******************************************************************************* ******************************************************************************/ gf_notification_new(GfTheme *theme) { GfNotification *notification; g_return_val_if_fail(theme, NULL); notification = g_new0(GfNotification, 1); notification->theme = theme; notification->use_gtk = TRUE; notification->height = 140; notification->width = 120; gf_notification_new_from_xmlnode(GfTheme *theme, xmlnode *node) { GfNotification *notification; g_return_val_if_fail(theme, NULL); g_return_val_if_fail(node, NULL); notification = gf_notification_new(theme); notification->n_type = g_strdup(xmlnode_get_attrib(node, "type")); if(!notification->n_type) { purple_debug_info("Guifications", "** Error: Notification type unknown\n"); gf_notification_destroy(notification); if(!g_utf8_collate(notification->n_type, GF_NOTIFICATION_MASTER)) gf_theme_set_master(theme, notification); data = xmlnode_get_attrib(node, "use_gtk"); notification->use_gtk = atoi(data); data = xmlnode_get_attrib(node, "background"); notification->background = g_strdup(data); data = xmlnode_get_attrib(node, "width"); notification->width = atoi(data); data = xmlnode_get_attrib(node, "height"); notification->height = atoi(data); data = xmlnode_get_attrib(node, "alias"); notification->alias = g_strdup(data); if(notification->use_gtk) { if(notification->width < GF_NOTIFICATION_MIN || notification->height < GF_NOTIFICATION_MIN) purple_debug_info("Guifications", "** Error: notification '%s' is using the " "gtk background but %dx%d is less than the %dx%d minimum\n", notification->width, notification->height, GF_NOTIFICATION_MIN, GF_NOTIFICATION_MIN); gf_notification_destroy(notification); } else if(!notification->background) { purple_debug_info("Guifications", "** Error: notification '%s' is not using the " "gtk background and does not have a background image\n", gf_notification_destroy(notification); child = xmlnode_get_child(node, "item"); item = gf_item_new_from_xmlnode(notification, child); gf_notification_add_item(notification, item); child = xmlnode_get_next_twin(child); gf_notification_copy(GfNotification *notification) { GfNotification *new_notification; g_return_val_if_fail(notification, NULL); new_notification = gf_notification_new(notification->theme); new_notification->n_type = g_strdup(notification->n_type); if(notification->background) new_notification->background = g_strdup(notification->background); new_notification->alias = g_strdup(notification->alias); new_notification->use_gtk = notification->use_gtk; new_notification->width = notification->width; new_notification->height = notification->height; for(l = notification->items; l; l = l->next) { item = gf_item_copy(GF_ITEM(l->data)); new_notification->items = g_list_append(new_notification->items, item); gf_notification_to_xmlnode(GfNotification *notification) { parent = xmlnode_new("notification"); xmlnode_set_attrib(parent, "type", notification->n_type); xmlnode_set_attrib(parent, "use_gtk", (notification->use_gtk) ? "1" : "0"); if(notification->background) xmlnode_set_attrib(parent, "background", notification->background); xmlnode_set_attrib(parent, "alias", notification->alias); data = g_strdup_printf("%d", notification->width); xmlnode_set_attrib(parent, "width", data); data = g_strdup_printf("%d", notification->height); xmlnode_set_attrib(parent, "height", data); for(l = notification->items; l; l = l->next) { if((child = gf_item_to_xmlnode(GF_ITEM(l->data)))) xmlnode_insert_child(parent, child); gf_notification_destroy(GfNotification *notification) { g_return_if_fail(notification); if(notification->n_type) { g_free(notification->n_type); notification->n_type = NULL; if(notification->background) { g_free(notification->background); notification->background = NULL; if(notification->alias) { g_free(notification->alias); notification->alias = NULL; if(notification->items) { for(l = notification->items; l; l = l->next) { g_list_free(notification->items); notification->items = NULL; gf_notification_set_type(GfNotification *notification, const gchar *n_type) { g_return_if_fail(notification); g_return_if_fail(n_type); g_free(notification->n_type); notification->n_type = g_strdup(n_type); gf_notification_get_type(GfNotification *notification) { g_return_val_if_fail(notification, NULL); return notification->n_type; gf_notification_set_use_gtk(GfNotification *notification, gboolean value) { g_return_if_fail(notification); notification->use_gtk = value; gf_notification_get_use_gtk(GfNotification *notification) { g_return_val_if_fail(notification, FALSE); return notification->use_gtk; gf_notification_set_background(GfNotification *notification, g_return_if_fail(notification); if(notification->background) g_free(notification->background); notification->background = g_strdup(background); gf_notification_get_background(GfNotification *notification) { g_return_val_if_fail(notification, NULL); return notification->background; gf_notification_set_width(GfNotification *notification, gint width) { g_return_if_fail(notification); notification->width = width; gf_notification_get_width(GfNotification *notification) { g_return_val_if_fail(notification, -1); return notification->width; gf_notification_set_height(GfNotification *notification, gint height) { g_return_if_fail(notification); notification->height = height; gf_notification_get_height(GfNotification *notification) { g_return_val_if_fail(notification, -1); return notification->height; gf_notification_add_item(GfNotification *notification, GfItem *item) { g_return_if_fail(notification); notification->items = g_list_append(notification->items, item); gf_notification_remove_item(GfNotification *notification, GfItem *item) { g_return_if_fail(notification); notification->items = g_list_remove(notification->items, item); gf_notification_get_items(GfNotification *notification) { g_return_val_if_fail(notification, NULL); return notification->items; gf_notification_get_alias(const GfNotification *notification) { g_return_val_if_fail(notification, NULL); return notification->alias; gf_notification_set_alias(GfNotification *notification, const gchar *alias) { g_return_if_fail(notification); g_free(notification->alias); notification->alias = (alias) ? g_strdup(alias) : NULL; /******************************************************************************* * Finding, rendering, all that fun stuff... ******************************************************************************/ gf_notifications_swap(GfNotification *notification1, GfNotification *notification2) { GfNotification *notification = NULL; GList *l = NULL, *l1 = NULL, *l2 = NULL; g_return_if_fail(notification1); g_return_if_fail(notification2); if(notification1->theme != notification2->theme) for(l = gf_theme_get_notifications(notification1->theme); l; l = l->next) { if(l->data == notification1) if(l->data == notification2) gf_notifications_for_event(const gchar *n_type) { GfNotification *notification; g_return_val_if_fail(n_type, NULL); for(t = gf_themes_get_loaded(); t; t = t->next) { theme = GF_THEME(t->data); for(n = gf_theme_get_notifications(theme); n; n = n->next) { notification = GF_NOTIFICATION(n->data); if(!g_ascii_strcasecmp(notification->n_type, n_type)) l = g_list_append(l, notification); gf_notification_find_for_event(const gchar *n_type) { GfNotification *notification = NULL; g_return_val_if_fail(n_type, NULL); n = gf_notifications_for_event(n_type); c = rand() % g_list_length(n); notification = GF_NOTIFICATION(g_list_nth_data(n, c)); gf_notification_find_for_theme(GfTheme *theme, const gchar *n_type) { GfNotification *notification = NULL; GList *n = NULL, *t = NULL; g_return_val_if_fail(theme, NULL); g_return_val_if_fail(n_type, NULL); /* Get the list of notifications for a theme */ for(t = gf_theme_get_notifications(theme); t; t = t->next) { notification = GF_NOTIFICATION(t->data); if(!gf_utils_strcmp(notification->n_type, n_type)) n = g_list_append(n, notification); notification = GF_NOTIFICATION(n->data); notification = GF_NOTIFICATION(g_list_nth_data(n, c)); gf_notification_render(GfNotification *notification, GfEventInfo *info) { GdkPixbuf *pixbuf = NULL; g_return_val_if_fail(notification, NULL); g_return_val_if_fail(info, NULL); if(notification->background) { /* create the pixbuf, return if it failed */ path = gf_theme_get_path(notification->theme); filename = g_build_filename(path, notification->background, NULL); pixbuf = gdk_pixbuf_new_from_file(filename, NULL); purple_debug_info("Guifications", "Couldn't not load notification background\n"); GdkPixmap *pixmap = NULL; pixmap = gf_gtk_theme_get_bg_pixmap(); gdk_drawable_get_size(GDK_DRAWABLE(pixmap), &width, &height); tile = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(pixmap), NULL, 0, 0, 0, 0, width, height); purple_debug_info("Guifications", "Failed to get the gtk theme " pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, notification->width, notification->height); gf_gtk_pixbuf_tile(pixbuf, tile); g_object_unref(G_OBJECT(tile)); pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, notification->width, notification->height); purple_debug_info("Guifications", "Failed to create notification background\n"); gf_gtk_theme_get_bg_color(&color); pixel = gf_gtk_color_pixel_from_gdk(&color); gdk_pixbuf_fill(pixbuf, pixel); for(l = notification->items; l; l = l->next) { gf_item_render(item, pixbuf, info); /* display it already!! */ gf_notification_get_theme(GfNotification *notification) { g_return_val_if_fail(notification, NULL); return notification->theme;