Logo Search packages:      
Sourcecode: guifications version File versions

gf_blist.c

/*
 * Guifications - The end all, be all, toaster popup plugin
 * Copyright (C) 2003-2004 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 <glib.h>
#include <gtk/gtk.h>
#include <string.h>

#include <blist.h>
#include <debug.h>
#include <gtkutils.h>
#include <plugin.h>
#include <request.h>

#include "gf_blist.h"
#include "gf_internal.h"
#include "gf_notification.h"
#include "gf_theme.h"
#include "gf_theme_info.h"
#include "gf_utils.h"

#define GF_NODE_SETTING "guifications-theme"

/******************************************************************************
 * Structs
 *****************************************************************************/
typedef struct _GfBlistDialog {
      GaimBlistNode *node;
      GaimRequestField *theme_field;
      gpointer handle;
} GfBlistDialog;

/******************************************************************************
 * Enums
 *****************************************************************************/
typedef enum _GfBlistThemeType {
      GF_BLIST_THEME_UNASSIGNED = 0,
      GF_BLIST_THEME_RANDOM,
      GF_BLIST_THEME_NONE,
      GF_BLIST_THEME_SPECIFIC,
      GF_BLIST_THEME_TYPES
} GfBlistThemeType;

/******************************************************************************
 * Globals
 *****************************************************************************/
static GList *dialogs = NULL;

/******************************************************************************
 * Dialog Callbacks
 *****************************************************************************/
static void
gf_blist_dialog_ok_cb(gpointer data, GaimRequestFields *fields) {
      GfBlistDialog *diag = (GfBlistDialog *)data;
      GList *l;
      const gchar *name = NULL;
      gint value = 0;

      value = gaim_request_field_choice_get_value(diag->theme_field);

      l = gaim_request_field_choice_get_labels(diag->theme_field);
      name = g_list_nth_data(l, value);

      if(diag->node) {
            switch(value) {
                  case GF_BLIST_THEME_UNASSIGNED:
                        gaim_blist_node_remove_setting(diag->node, GF_NODE_SETTING);
                        break;
                  case GF_BLIST_THEME_RANDOM:
                        gaim_blist_node_set_string(diag->node, GF_NODE_SETTING,
                                                               "(RANDOM)");
                        break;
                  case GF_BLIST_THEME_NONE:
                        gaim_blist_node_set_string(diag->node, GF_NODE_SETTING,
                                                               "(NONE)");
                        break;
                  default:
                        gaim_blist_node_set_string(diag->node, GF_NODE_SETTING, name);
            }
      }

      dialogs = g_list_remove(dialogs, diag);
      g_free(diag);
}

static void
gf_blist_dialog_cancel_cb(gpointer data, GaimRequestFields *fields) {
      GfBlistDialog *diag = (GfBlistDialog *)data;

      dialogs = g_list_remove(dialogs, diag);
      g_free(diag);
}

/******************************************************************************
 * Dialog Stuff
 *****************************************************************************/
static void
gf_blist_dialog_new(GaimBlistNode *node) {
      GfBlistDialog *dialog = NULL;
      GaimRequestFields *fields;
      GaimRequestFieldGroup *group;
      GList *l;
      gchar *info;
      const gchar *name = NULL, *node_type = NULL, *current = NULL;
      gint history = 0, i = 0;

      dialog = g_new0(GfBlistDialog, 1);

      if(!dialog)
            return;

      dialog->node = node;

      /* wow this should really be in blist.[ch] someone remind me to 
       * write a patch at some point.
       */
      if(GAIM_BLIST_NODE_IS_BUDDY(node)) {
            GaimBuddy *buddy = (GaimBuddy *)node;

            if(buddy->alias)
                  name = buddy->alias;
            else
                  name = buddy->name;

            node_type = _("buddy");
      } else if(GAIM_BLIST_NODE_IS_CONTACT(node)) {
            GaimContact *contact = (GaimContact *)node;

            if(contact->alias)
                  name = contact->alias;
            else {
                  if(contact->priority->alias)
                        name = contact->priority->alias;
                  else
                        name = contact->priority->name;
            }

            node_type = _("contact");
      } else if(GAIM_BLIST_NODE_IS_GROUP(node)) {
            GaimGroup *group = (GaimGroup *)node;
            name = group->name;
            node_type = _("group");
      }

      current = gaim_blist_node_get_string(node, GF_NODE_SETTING);

      fields = gaim_request_fields_new();
      group = gaim_request_field_group_new(NULL);
      gaim_request_fields_add_group(fields, group);

      dialog->theme_field = gaim_request_field_choice_new("theme",
                                                                                    _("_Theme"), 1);
      gaim_request_field_group_add_field(group, dialog->theme_field);

      gaim_request_field_choice_add(dialog->theme_field, _("Clear setting"));

      gaim_request_field_choice_add(dialog->theme_field, _("Random"));
      if(!gf_utils_strcmp("(RANDOM)", current))
            history = GF_BLIST_THEME_RANDOM;

      gaim_request_field_choice_add(dialog->theme_field, _("None"));
      if(!gf_utils_strcmp("(NONE)", current))
            history = GF_BLIST_THEME_NONE;

      for(l = gf_themes_get_loaded(); l; l = l->next) {
            GfTheme *theme = GF_THEME(l->data);
            GfThemeInfo *info = gf_theme_get_theme_info(theme);
            const gchar *theme_name;

            theme_name = gf_theme_info_get_name(info);
            gaim_request_field_choice_add(dialog->theme_field, theme_name);

            if(!gf_utils_strcmp(theme_name, current))
                  history = i + GF_BLIST_THEME_SPECIFIC;

            i++;
      }

      gaim_request_field_choice_set_default_value(dialog->theme_field, history);

      info = g_strdup_printf(_("Select a theme for the %s %s"),
                                       node_type, name);
      dialog->handle =
            gaim_request_fields(NULL, _("Select Guifications theme"),
                                          NULL, info, fields,
                                          _("OK"), G_CALLBACK(gf_blist_dialog_ok_cb),
                                          _("Cancel"), G_CALLBACK(gf_blist_dialog_cancel_cb),
                                          dialog);
      g_free(info);

      dialogs = g_list_append(dialogs, dialog);
}

/******************************************************************************
 * Menu Callbacks
 *****************************************************************************/
static void
gf_blist_menu_cb(GaimBlistNode *node, gpointer data) {
      /* Fix this up when we actually have a way to know if a request window
       * is still visible, ie: remind me to write a patch for that and to
       * "show" that window for the next gaim release..
       */
      gf_blist_dialog_new(node);
}

static void
gf_blist_drawing_menu_cb(GaimBlistNode *node, GList **menu) {
      GaimBlistNodeAction *action;

      /* theres no way to get the name of a chat yet so we don't support 
       * them yet.
       */
      if(GAIM_BLIST_NODE_IS_CHAT(node))
            return;

      /* add a separator */
      (*menu) = g_list_append(*menu, NULL);

      /* add our menu item */
      action = gaim_blist_node_action_new(_("Guifications Theme"),
                                                            gf_blist_menu_cb, NULL);
      (*menu) = g_list_append(*menu, action);
}

/******************************************************************************
 * Subsystem
 *****************************************************************************/
void
gf_blist_init(GaimPlugin *plugin) {
      gaim_signal_connect(gaim_blist_get_handle(),
                                    "blist-node-extended-menu",
                                    plugin,
                                    GAIM_CALLBACK(gf_blist_drawing_menu_cb),
                                    NULL);
}

void
gf_blist_uninit() {
      GfBlistDialog *diag;
      GList *l, *ll;

      for(l = dialogs; l; l = ll) {
            ll = l->next;

            diag = (GfBlistDialog *)l->data;

            gaim_request_close(GAIM_REQUEST_FIELDS, diag->handle);

            dialogs = g_list_remove(dialogs, diag);
            g_free(diag);
      }

      dialogs = NULL;
}

/* The pointer to a GfTheme is only used if gf_blist_get_theme_type returns
 * GF_BLIST_THEME_SPECIFIC.  If it returns random we handle that in the 
 * calling function.
 */
static GfBlistThemeType
gf_blist_get_theme_type(GaimBlistNode *node, GfTheme **theme) {
      const gchar *node_theme = NULL;

      g_return_val_if_fail(node, GF_BLIST_THEME_NONE);
      g_return_val_if_fail(theme, GF_BLIST_THEME_NONE);

      node_theme = gaim_blist_node_get_string(node, GF_NODE_SETTING);
      if(!node_theme)
            return GF_BLIST_THEME_UNASSIGNED;

      if(!gf_utils_strcmp(node_theme, "(RANDOM)")) {
            return GF_BLIST_THEME_RANDOM;
      } else if(!gf_utils_strcmp(node_theme, "(NONE)")) {
            return GF_BLIST_THEME_NONE;
      } else {
            *theme = gf_theme_find_theme_by_name(node_theme);

            /* if the specific theme is not loaded we fallback to a random theme
             * and do not touch the setting in the event that the user reloads
             * said specific theme.  In our words, lets not muck everything up if
             * the user unloads a theme they don't mean to :)
             */
            if(!*theme) 
                  return GF_BLIST_THEME_RANDOM;

            return GF_BLIST_THEME_SPECIFIC;
      }
}

GfNotification *
gf_blist_get_notification_for_buddy(GaimBuddy *buddy, const gchar *n_type) {
      GaimBlistNode *node = NULL;

      g_return_val_if_fail(buddy, NULL);
      g_return_val_if_fail(n_type, NULL);

      node = (GaimBlistNode *)buddy;
      g_return_val_if_fail(node, NULL);

      /* i don't really like the way this is setup.. but I also don't liek the
       * idea of typing this out three times...
       */
      while(node) {
            GfBlistThemeType theme_type;
            GfTheme *theme = NULL;

            /* grab the theme type right away */
            theme_type = gf_blist_get_theme_type(node, &theme);

            /* then update the parent so we avoid excessive checking */
            node = node->parent;

            /* no theme set, check the parent */
            if(theme_type == GF_BLIST_THEME_UNASSIGNED)
                  continue;

            if(theme_type == GF_BLIST_THEME_RANDOM)
                  return gf_notification_find_for_event(n_type);

            if(theme_type == GF_BLIST_THEME_NONE)
                  return NULL;

            if(theme_type == GF_BLIST_THEME_SPECIFIC)
                  return gf_notification_find_for_theme(theme, n_type);

            
      }

      return gf_notification_find_for_event(n_type);
}

Generated by  Doxygen 1.6.0   Back to index