pidgin/purple-plugin-pack

This took WAY too long to see. The logs shouldn't be sorted while we're
org.guifications.plugins
2008-08-03, rekkanoryo
f8496a6121df
This took WAY too long to see. The logs shouldn't be sorted while we're
still in the outer loop. Sort at the end once we've collected all the logs
we can.
/*--------------------------------------------------------------------------*
* 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 "widget.h"
#include "request.h"
#include "autoprofile.h"
#include "gtkprefs.h"
#include "gtkimhtml.h"
#define AP_RESPONSE_CHOOSE 98125
static GtkWidget *dialog_box = NULL;
static GtkWidget *dialog_box_contents = NULL;
static GtkWidget *dialog_box_preview = NULL;
static struct widget *dialog_box_widget = NULL;
static GStaticMutex preview_mutex = G_STATIC_MUTEX_INIT;
static GtkWidget *component_dialog = NULL;
static GtkWidget *choose_button = NULL;
static GtkWidget *widget_dialog = NULL;
static GtkWidget *delete_button = NULL;
static GtkWidget *rename_button = NULL;
static GtkListStore *tree_list = NULL;
static GHashTable *pref_names = NULL;
static void component_dialog_show ();
void ap_widget_prefs_updated (struct widget *w) {
gchar *output;
if (dialog_box_preview == NULL) return;
if (w != dialog_box_widget) return;
// TODO: Investigate how laggy this is, possibly add a timeout
output = w->component->generate (w);
g_static_mutex_lock (&preview_mutex);
gtk_imhtml_clear (GTK_IMHTML(dialog_box_preview));
gtk_imhtml_append_text (GTK_IMHTML(dialog_box_preview), output,
GTK_IMHTML_NO_SCROLL);
g_static_mutex_unlock (&preview_mutex);
free (output);
}
static void update_widget_list (GtkListStore *ls) {
GtkTreeIter iter;
GList *widgets, *widgets_start;
struct widget *w;
GString *s;
s = g_string_new ("");
gtk_list_store_clear (ls);
widgets_start = widgets = ap_widget_get_widgets ();
for (widgets = widgets_start; widgets != NULL; widgets = widgets->next) {
gtk_list_store_append (ls, &iter);
w = (struct widget *) widgets->data;
g_string_printf (s, "<b>%s</b>", w->alias);
gtk_list_store_set (ls, &iter,
0, s->str,
1, w,
-1);
}
g_list_free (widgets_start);
g_string_free (s, TRUE);
}
static void refresh_cb (GtkWidget *widget, gpointer data) {
struct widget *w;
w = (struct widget *) data;
ap_widget_prefs_updated (w);
}
/* Widget configuration menu */
static GtkWidget *get_widget_configuration (struct widget *w) {
GtkWidget *config, *hbox, *vbox, *sw;
GtkWidget *label, *button;
GtkWidget *menu;
GString *s;
gchar *output;
config = gtk_vbox_new (FALSE, 0);
/* Title/Description */
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER(hbox), 6);
gtk_box_pack_start (GTK_BOX(config), hbox, FALSE, FALSE, 0);
s = g_string_new ("");
g_string_printf (s, "<b>%s:</b> %s", w->component->name,
w->component->description);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(label), s->str);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
g_string_free (s, TRUE);
/* Separator */
gtk_box_pack_start (GTK_BOX (config), gtk_hseparator_new (),
FALSE, FALSE, 0);
/* Preview window */
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
gtk_box_pack_start (GTK_BOX(config), vbox, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, 8);
gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(label), _("<b>Preview</b>"));
gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("Refresh"));
gtk_box_pack_end (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (refresh_cb), w);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX(vbox), sw, TRUE, TRUE, 0);
dialog_box_preview = gtk_imhtml_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER(sw), dialog_box_preview);
pidgin_setup_imhtml (dialog_box_preview);
output = w->component->generate (w);
gtk_imhtml_append_text (GTK_IMHTML(dialog_box_preview),
output, GTK_IMHTML_NO_SCROLL);
free (output);
dialog_box_widget = w;
/* Separator */
gtk_box_pack_start (GTK_BOX (config), gtk_hseparator_new (),
FALSE, FALSE, 0);
/* Configuration stuff */
vbox = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
gtk_box_pack_start (GTK_BOX(config), vbox, TRUE, TRUE, 0);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(label), _("<b>Configuration</b>"));
gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
if (w->component->pref_menu == NULL ||
(menu = (w->component->pref_menu) (w)) == NULL) {
label = gtk_label_new (_("No options available for this component"));
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
} else {
gtk_box_pack_start (GTK_BOX (vbox), menu, TRUE, TRUE, 0);
}
return config;
}
/* Info message */
static GtkWidget *get_info_message () {
GtkWidget *page;
GtkWidget *aboutwin;
GtkWidget *text;
/* Make the box */
page = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (page), 12);
/* Window with info */
aboutwin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(aboutwin),
GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(aboutwin),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX(page), aboutwin, TRUE, TRUE, 0);
text = gtk_imhtml_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER(aboutwin), text);
pidgin_setup_imhtml (text);
/* Info text */
gtk_imhtml_append_text (GTK_IMHTML(text),
_("<b><u>Basic info</u></b><br>"), GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("A <b>widget</b> is a little piece/snippet of automatically "
"generated text. There are all sorts of widgets; each type has "
"different content (i.e. a random quote, text from a blog, the "
"song currently playing, etc).<br><br>"), GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("To use a widget, simply drag it from the list on the left and "
"drop it into a profile or status message. <i>It's that easy!</i>"
"<br><br>"), GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("<b>To edit your profile:</b> "
"Use the \"Info/profile\" tab in this window.<br>"),
GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("<b>To edit your available/away/status message:</b> "
"Use the regular Purple interface built into the bottom of the buddy "
"list.<br><br>"), GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("<b><u>Advanced Tips</u></b><br>"), GTK_IMHTML_NO_SCROLL);
gtk_imhtml_append_text (GTK_IMHTML(text),
_("You can insert a widget into a profile or status by typing its name. "
"To do this, just type \"[widget-name]\" wherever you want to "
"place a widget (names of widgets are listed on the left). <br><br>"
"<b>You type:</b> The song I am playing now is [iTunesInfo].<br>"
"<b>AutoProfile result:</b> The song I am playing now is "
"The Beatles - Yellow Submarine.<br><br>"), GTK_IMHTML_NO_SCROLL);
return page;
}
/* Dialog window actions */
static void widget_popup_rename_cb (
struct widget *w, const char *new_text) {
GtkTreeIter iter;
GValue val;
struct widget *cur_widget;
GString *s;
gtk_tree_model_get_iter_first (GTK_TREE_MODEL(tree_list), &iter);
while (TRUE) {
val.g_type = 0;
gtk_tree_model_get_value (GTK_TREE_MODEL(tree_list), &iter, 1, &val);
cur_widget = g_value_get_pointer(&val);
if (cur_widget == w) break;
if (!gtk_tree_model_iter_next (GTK_TREE_MODEL(tree_list), &iter)) {
purple_notify_error (NULL, NULL,
N_("Unable to change name"),
N_("The specified widget no longer exists."));
return;
}
}
if (ap_widget_rename (w, new_text)) {
s = g_string_new ("");
g_string_printf (s, "<b>%s</b>", w->alias);
// Set value in ls
gtk_list_store_set (tree_list, &iter,
0, s->str,
1, w,
-1);
g_string_free (s, TRUE);
} else {
purple_notify_error (NULL, NULL,
N_("Unable to change name"),
N_("The widget name you have specified is already in use."));
}
}
static void delete_cb (GtkWidget *button, GtkTreeSelection *sel)
{
GtkTreeModel *model;
GtkTreeIter iter;
GValue val;
struct widget *w;
gtk_tree_selection_get_selected (sel, &model, &iter);
val.g_type = 0;
gtk_tree_model_get_value (model, &iter, 1, &val);
w = g_value_get_pointer(&val);
ap_widget_delete (w);
gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
}
static void rename_cb (GtkWidget *button, GtkTreeSelection *sel)
{
GtkTreeModel *model;
GtkTreeIter iter;
GValue val;
struct widget *w;
gtk_tree_selection_get_selected (sel, &model, &iter);
val.g_type = 0;
gtk_tree_model_get_value (model, &iter, 1, &val);
w = g_value_get_pointer(&val);
purple_request_input(NULL,
_("Rename Widget"), NULL,
_("Enter a new name for this widget."), w->alias,
FALSE, FALSE, NULL,
_("Rename"), G_CALLBACK(widget_popup_rename_cb),
_("Cancel"), NULL, NULL, NULL, NULL, w);
}
static void add_cb (GtkWidget *button, GtkTreeSelection *sel)
{
component_dialog_show ();
}
void ap_widget_gtk_start () {
pref_names = g_hash_table_new (g_str_hash, g_str_equal);
}
void ap_widget_gtk_finish () {
done_with_widget_list ();
g_hash_table_destroy (pref_names);
pref_names = NULL;
}
static void widget_sel_cb (GtkTreeSelection *sel, GtkTreeModel *model) {
GtkTreeIter iter;
struct widget *w;
GValue val;
gtk_widget_destroy (dialog_box_contents);
if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
gtk_widget_set_sensitive(rename_button, FALSE);
gtk_widget_set_sensitive(delete_button, FALSE);
dialog_box_contents = get_info_message ();
dialog_box_preview = NULL;
dialog_box_widget = NULL;
} else {
gtk_widget_set_sensitive(rename_button, TRUE);
gtk_widget_set_sensitive(delete_button, TRUE);
val.g_type = 0;
gtk_tree_model_get_value (GTK_TREE_MODEL(tree_list), &iter, 1, &val);
w = g_value_get_pointer(&val);
dialog_box_contents = get_widget_configuration (w);
}
gtk_box_pack_start (GTK_BOX(dialog_box), dialog_box_contents,
TRUE, TRUE, 0);
gtk_widget_show_all (dialog_box);
}
GtkWidget *ap_widget_get_config_page ()
{
GtkTreeSelection *sel;
GtkWidget *vbox;
GtkWidget *add_button;
/* Arrange main parts of window */
dialog_box = gtk_hbox_new (FALSE, 0);
vbox = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX(dialog_box), vbox, FALSE, FALSE, 0);
get_widget_list (vbox, &sel);
g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (widget_sel_cb),
NULL);
add_button = gtk_button_new_with_label (_("New Widget"));
g_signal_connect (G_OBJECT(add_button), "clicked",
G_CALLBACK(add_cb), sel);
gtk_box_pack_start (GTK_BOX(vbox), add_button, FALSE, FALSE, 0);
rename_button = gtk_button_new_with_label (_("Rename"));
gtk_widget_set_sensitive(rename_button, FALSE);
g_signal_connect (G_OBJECT(rename_button), "clicked",
G_CALLBACK(rename_cb), sel);
gtk_box_pack_start (GTK_BOX(vbox), rename_button, FALSE, FALSE, 0);
delete_button = gtk_button_new_with_label (_("Delete"));
gtk_widget_set_sensitive(delete_button, FALSE);
g_signal_connect (G_OBJECT(delete_button), "clicked",
G_CALLBACK(delete_cb), sel);
gtk_box_pack_start (GTK_BOX(vbox), delete_button, FALSE, FALSE, 0);
dialog_box_contents = get_info_message ();
gtk_box_pack_start (GTK_BOX(dialog_box), dialog_box_contents,
TRUE, TRUE, 0);
return dialog_box;
}
/* DND */
static void
drag_data_get_cb(GtkWidget *widget, GdkDragContext *ctx,
GtkSelectionData *data, guint info, guint time,
gpointer user_data)
{
GtkListStore *ls = (GtkListStore *) user_data;
if (ls == NULL) return;
if (data->target == gdk_atom_intern ("STRING", FALSE)) {
GtkTreeRowReference *ref;
GtkTreePath *source_row;
GtkTreeIter iter;
GString *s;
struct widget *w;
GValue val = {0};
ref = g_object_get_data (G_OBJECT(ctx), "gtk-tree-view-source-row");
source_row = gtk_tree_row_reference_get_path (ref);
if (source_row == NULL) return;
gtk_tree_model_get_iter(GTK_TREE_MODEL(ls), &iter, source_row);
gtk_tree_model_get_value(GTK_TREE_MODEL(ls), &iter,
1, &val);
w = g_value_get_pointer (&val);
s = g_string_new ("");
g_string_printf (s, "[%s]", w->alias);
gtk_selection_data_set (data, gdk_atom_intern ("STRING", FALSE),
8, (guchar *)s->str, strlen(s->str)+1);
g_string_free (s, TRUE);
gtk_tree_path_free (source_row);
}
}
void done_with_widget_list () {
if (tree_list) {
g_object_unref (tree_list);
tree_list = NULL;
}
widget_dialog = NULL;
delete_button = NULL;
dialog_box = NULL;
dialog_box_contents = NULL;
dialog_box_preview = NULL;
dialog_box_widget = NULL;
if (component_dialog != NULL) {
gtk_widget_destroy (component_dialog);
component_dialog = NULL;
choose_button = NULL;
}
}
GtkWidget *get_widget_list (GtkWidget *box, GtkTreeSelection **sel)
{
GtkWidget *sw;
GtkWidget *event_view;
GtkCellRenderer *rend;
GtkTreeViewColumn *col;
GtkTargetEntry gte [] = {{"STRING", 0, GTK_IMHTML_DRAG_STRING}};
if (tree_list == NULL) {
tree_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(tree_list),
0, GTK_SORT_ASCENDING);
update_widget_list (tree_list);
g_object_ref (G_OBJECT(tree_list));
}
/* List of widgets */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX(box), sw, TRUE, TRUE, 0);
event_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_list));
*sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Widget"), rend,
"markup", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (event_view), col);
gtk_tree_view_column_set_sort_column_id (col, 0);
gtk_container_add (GTK_CONTAINER(sw), event_view);
/* Drag and Drop */
gtk_tree_view_enable_model_drag_source(
GTK_TREE_VIEW(event_view), GDK_BUTTON1_MASK, gte,
1, GDK_ACTION_COPY);
g_signal_connect(G_OBJECT(event_view), "drag-data-get",
G_CALLBACK(drag_data_get_cb), tree_list);
return event_view;
}
/*********************************************************
Component selection window
**********************************************************/
static void add_component (struct component *c) {
struct widget *w;
GtkTreeIter iter;
GString *s;
w = ap_widget_create (c);
if (w == NULL) return;
s = g_string_new ("");
gtk_list_store_append (tree_list, &iter);
g_string_printf (s, "<b>%s</b>", w->alias);
gtk_list_store_set (tree_list, &iter,
0, s->str,
1, w,
-1);
g_string_free (s, TRUE);
}
static void component_row_activate_cb (GtkTreeView *view, GtkTreePath *path,
GtkTreeViewColumn *column, gpointer null)
{
GtkTreeSelection *sel;
GtkTreeIter iter;
struct component *c;
GtkTreeModel *model;
sel = gtk_tree_view_get_selection (view);
if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
gtk_tree_model_get (model, &iter, 1, &c, -1);
add_component (c);
}
gtk_widget_destroy (component_dialog);
component_dialog = NULL;
choose_button = NULL;
}
static void component_response_cb(GtkWidget *d, int response,
GtkTreeSelection *sel)
{
GtkTreeModel *model;
GtkTreeIter iter;
GValue val;
struct component *c;
switch (response) {
case AP_RESPONSE_CHOOSE:
gtk_tree_selection_get_selected (sel, &model, &iter);
val.g_type = 0;
gtk_tree_model_get_value (model, &iter, 1, &val);
c = g_value_get_pointer(&val);
add_component (c);
case GTK_RESPONSE_CLOSE:
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT:
gtk_widget_destroy(d);
component_dialog = NULL;
choose_button = NULL;
break;
}
}
static void component_sel_cb (GtkTreeSelection *sel, GtkTreeModel *model) {
GtkTreeIter iter;
if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
gtk_widget_set_sensitive(choose_button, FALSE);
} else {
gtk_widget_set_sensitive(choose_button, TRUE);
}
}
static void update_component_list (GtkListStore *ls) {
GtkTreeIter iter;
GList *components;
struct component *c;
GString *s;
gchar *name, *description;
gtk_list_store_clear (ls);
s = g_string_new ("");
for (components = ap_component_get_components ();
components != NULL;
components = components->next) {
gtk_list_store_append (ls, &iter);
c = (struct component *) components->data;
name = g_markup_escape_text (c->name, -1);
description = g_markup_escape_text (c->description, -1);
g_string_printf (s, "<b>%s</b>\n%s", name, description);
gtk_list_store_set (ls, &iter,
0, s->str,
1, c,
-1);
free (name);
free (description);
}
g_string_free (s, TRUE);
}
static void component_dialog_show ()
{
GtkWidget *sw;
GtkWidget *event_view;
GtkListStore *ls;
GtkCellRenderer *rendt;
GtkTreeViewColumn *col;
GtkTreeSelection *sel;
if (component_dialog != NULL) {
gtk_window_present(GTK_WINDOW(component_dialog));
return;
}
component_dialog = gtk_dialog_new_with_buttons (_("Select a widget type"),
NULL,
GTK_DIALOG_NO_SEPARATOR,
NULL);
choose_button = gtk_dialog_add_button (GTK_DIALOG(component_dialog),
_("Create widget"), AP_RESPONSE_CHOOSE);
gtk_dialog_add_button (GTK_DIALOG(component_dialog),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_widget_set_sensitive (choose_button, FALSE);
sw = gtk_scrolled_window_new (NULL,NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX(GTK_DIALOG(component_dialog)->vbox), sw,
TRUE, TRUE, 0);
ls = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(ls),
0, GTK_SORT_ASCENDING);
update_component_list (ls);
event_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(ls));
g_signal_connect(G_OBJECT(event_view), "row-activated",
G_CALLBACK(component_row_activate_cb), event_view);
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
rendt = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Widget type"),
rendt,
"markup", 0,
NULL);
#if GTK_CHECK_VERSION(2,6,0)
gtk_tree_view_column_set_expand (col, TRUE);
g_object_set(rendt, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
#endif
gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col);
gtk_tree_view_column_set_sort_column_id (col, 0);
g_object_unref (G_OBJECT(ls));
gtk_container_add (GTK_CONTAINER(sw), event_view);
g_signal_connect (G_OBJECT (sel), "changed",
G_CALLBACK (component_sel_cb), NULL);
g_signal_connect(G_OBJECT(component_dialog), "response",
G_CALLBACK(component_response_cb), sel);
gtk_window_set_default_size(GTK_WINDOW(component_dialog), 550, 430);
gtk_widget_show_all(component_dialog);
}
/* Preferences stuff */
static void pref_callback (const char *name, PurplePrefType type,
gconstpointer val, gpointer data) {
struct widget *w = (struct widget *) data;
ap_widget_prefs_updated (w);
}
static const gchar *get_const_pref (struct widget *w, const char *key) {
gchar *pref, *result;
// This is here to prevent memory leaks
pref = ap_prefs_get_pref_name (w, key);
if (pref_names == NULL) {
pref_names = g_hash_table_new (g_str_hash, g_str_equal);
}
result = g_hash_table_lookup (pref_names, pref);
if (!result) {
g_hash_table_insert (pref_names, pref, pref);
return pref;
} else {
free (pref);
return result;
}
}
GtkWidget *ap_prefs_checkbox (struct widget *w, const char *title,
const char *key, GtkWidget *page)
{
GtkWidget *result;
const gchar *pref;
pref = get_const_pref (w, key);
result = pidgin_prefs_checkbox (title, pref, page);
purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
pref_callback, w);
return result;
}
GtkWidget *ap_prefs_dropdown_from_list (struct widget *w, GtkWidget *page,
const gchar *title, PurplePrefType type, const char *key, GList *menuitems)
{
GtkWidget *result;
const gchar *pref;
pref = get_const_pref (w, key);
result = pidgin_prefs_dropdown_from_list (
page, title, type, pref, menuitems);
purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
pref_callback, w);
return result;
}
GtkWidget *ap_prefs_labeled_entry (struct widget *w, GtkWidget *page,
const gchar *title, const char *key, GtkSizeGroup *sg) {
GtkWidget *result;
const gchar *pref;
pref = get_const_pref (w, key);
result = pidgin_prefs_labeled_entry (page, title, pref, sg);
purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
pref_callback, w);
return result;
}
GtkWidget *ap_prefs_labeled_spin_button (struct widget *w,
GtkWidget *page, const gchar *title, const char *key, int min,
int max, GtkSizeGroup *sg)
{
GtkWidget *result;
const gchar *pref;
pref = get_const_pref (w, key);
result = pidgin_prefs_labeled_spin_button (page, title, pref,
min, max, sg);
purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
pref_callback, w);
return result;
}