# HG changeset patch # User mikanbako # Date 1217500224 -32400 # Node ID 45da59a32019a717e219a911a4c00be486263370 # Parent 3c5fc8d7b5069cf871992dead3ea999a44c070af trying to make a dialog per conversation diff -r 3c5fc8d7b506 -r 45da59a32019 pidgin-twitter.c --- a/pidgin-twitter.c Thu Jul 31 17:22:02 2008 +0900 +++ b/pidgin-twitter.c Thu Jul 31 19:30:24 2008 +0900 @@ -762,6 +762,17 @@ } +static void +notify_that_input_screen_name(PurpleConversation *conv) +{ + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + GtkWidget *box = gtkconv->toolbar; + GtkWidget *pref_button = g_object_get_data(G_OBJECT(box), + PLUGIN_ID "-pref_button"); + + gtk_button_set_label(GTK_BUTTON(pref_button), ACCOUNT_PREF_BUTTON_NOTICE); +} + /***********************/ /* intrinsic functions */ /***********************/ @@ -771,8 +782,17 @@ { int utflen, bytes; gboolean twitter_ac = FALSE, wassr_ac = FALSE, identica_ac = FALSE; + PurpleConversation *conv = purple_find_conversation_with_account( + PURPLE_CONV_TYPE_ANY, + recipient, + account); twitter_debug("called\n"); + if(conv && !strcmp(EMPTY, service_account_get_string(conv, + OPT_SCREEN_NAME, + EMPTY))) + notify_that_input_screen_name(conv); + twitter_ac = is_twitter_account(account, recipient); wassr_ac = is_wassr_account(account, recipient); identica_ac = is_identica_account(account, recipient); @@ -1181,7 +1201,7 @@ detach_from_conv(PurpleConversation *conv, gpointer null) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - GtkWidget *box, *counter = NULL, *sep = NULL; + GtkWidget *box, *counter = NULL, *sep = NULL, *pref_button = NULL; g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), (GFunc) insert_text_cb, conv); @@ -1190,6 +1210,17 @@ box = gtkconv->toolbar; + /* remove account preference button */ + pref_button = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-pref_button"); + if(pref_button) { + g_signal_handlers_disconnect_by_func(G_OBJECT(pref_button), + (GFunc) open_account_preference_window, + purple_conversation_get_account(conv)->username); + gtk_container_remove(GTK_CONTAINER(box), pref_button); + g_object_unref(pref_button); + g_object_set_data(G_OBJECT(box), PLUGIN_ID "-pref_button", NULL); + } + /* remove counter */ counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); if(counter) { @@ -1319,8 +1350,11 @@ ~PURPLE_CONNECTION_HTML); /* check if the counter is enabled */ - if(!purple_prefs_get_bool(OPT_COUNTER)) + if(!purple_prefs_get_bool(OPT_COUNTER)) { + append_account_preference_button(gtkconv); + gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); return; + } /* get counter object */ counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); @@ -1346,10 +1380,29 @@ g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", G_CALLBACK(delete_text_cb), conv); + append_account_preference_button(gtkconv); + /* redraw window */ gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); } +static void +append_account_preference_button(PidginConversation *gtkconv) +{ + GtkWidget *pref_button; + GtkWidget *box = gtkconv->toolbar; + + pref_button = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-pref_button"); + g_return_if_fail(pref_button == NULL); + + pref_button = gtk_button_new_with_label(ACCOUNT_PREF_BUTTON_NORMAL); + g_signal_connect(G_OBJECT(pref_button), "clicked", + G_CALLBACK(open_account_preference_window), gtkconv); + gtk_box_pack_end(GTK_BOX(box), pref_button, FALSE, FALSE, 0); + gtk_widget_show_all(pref_button); + g_object_set_data(G_OBJECT(box), PLUGIN_ID "-pref_button", pref_button); +} + static gboolean is_twitter_account(PurpleAccount *account, const char *name) { @@ -2932,6 +2985,386 @@ return notebook; } +static void +open_account_preference_window(GtkWidget *pref_button, gpointer gtkconv_ptr) +{ + PidginConversation *gtkconv = (PidginConversation *) gtkconv_ptr; + PurpleConversation *conv = gtkconv->active_conv; + GtkWidget *dialog; + GtkWidget *notebook = gtk_notebook_new(); + gchar *title; + + title = g_strdup_printf("\"%s\" Account Preference", conv->title); + + dialog = gtk_dialog_new_with_buttons( + title, + GTK_WINDOW(pidgin_conv_get_window(gtkconv)->window), + 0, /* this dialog is destroyed by our signal hander */ + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + NULL); + g_free(title); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); + + /* This signal handler is to close the dialog + * when its parent notebook or window closed. + * NOTE : GTK_DIALOG_DESTROY_WITH_PARENT was not used + * because the dialog do not close when its parent notebook closed. + */ + g_signal_connect(G_OBJECT(pref_button), + "destroy", + G_CALLBACK(destroyed_pref_button_cb), + dialog); + /* This signal handler is to enable called_widged. */ + g_signal_connect(dialog, + "response", + G_CALLBACK(closed_account_preference_window_cb), + pref_button); + + /* Screen Name */ + build_screen_name_preference_form(conv, notebook); + /* API Base Post */ + if(is_twitter_conv(conv)) + build_twitter_api_preference_form(conv, notebook); + + gtk_button_set_label(GTK_BUTTON(pref_button), ACCOUNT_PREF_BUTTON_NORMAL); + gtk_widget_set_sensitive(pref_button, FALSE); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), notebook); + gtk_widget_show_all(GTK_WIDGET(dialog)); +} + +static void +build_screen_name_preference_form(PurpleConversation *conv, + GtkWidget *notebook) +{ + GtkWidget *tab_label, *child, *line, *container, *widget; + + child = gtk_vbox_new(FALSE, 0); + + /********************/ + /* screen name form */ + /********************/ + line = gtk_hbox_new(TRUE, 0); + + /* label */ + widget = gtk_label_new("screen name"); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 20, 0); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + /* entry */ + widget = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(widget), + service_account_get_string(conv, + OPT_SCREEN_NAME, + "")); + gtk_entry_set_activates_default(GTK_ENTRY(widget), TRUE); + g_object_set_data(G_OBJECT(widget), + PLUGIN_ID "-account_pref-key", + OPT_SCREEN_NAME); + g_signal_connect(G_OBJECT(widget), + "changed", + G_CALLBACK(account_preference_text_changed_cb), + conv); + container = gtk_alignment_new(1.0, 0.5, 1.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 0, 20); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + gtk_box_pack_start_defaults(GTK_BOX(child), line); + + /**************************************************/ + /* the explanation why a screen name is necessary */ + /**************************************************/ + line = gtk_hbox_new(FALSE, 0); + widget = gtk_label_new("If you do not input your screen name,"); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 20, 0, 20, 0); + gtk_box_pack_start(GTK_BOX(line), container, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(child), line, FALSE, FALSE, 0); + + line = gtk_hbox_new(FALSE, 0); + widget = gtk_label_new("you cannot see your icon."); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 20, 0); + gtk_box_pack_start(GTK_BOX(line), line, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(child), container, FALSE, FALSE, 0); + + /***************/ + /* create page */ + /***************/ + tab_label = gtk_label_new("Screen Name"); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child, tab_label); +} + +static void +build_twitter_api_preference_form(PurpleConversation *conv, + GtkWidget *notebook) +{ + GtkWidget *tab_label, *child, *line, *container, *widget; + GtkObject *adjust; + int value; + + child = gtk_vbox_new(FALSE, 0); + + /*****************************/ + /* Checkbox about to use API */ + /*****************************/ + + line = gtk_hbox_new(TRUE, 0); + widget = gtk_check_button_new_with_label("Get/post statuses via API"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), + service_account_get_bool(conv, + OPT_API_BASE_POST, + FALSE)); + g_object_set_data(G_OBJECT(widget), + PLUGIN_ID "-account_pref-key", + OPT_API_BASE_POST); + g_signal_connect(G_OBJECT(widget), + "toggled", + G_CALLBACK(account_preference_bool_toggled_cb), + conv); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 20, 0); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + gtk_box_pack_start_defaults(GTK_BOX(child), line); + + /*****************/ + /* Password Form */ + /*****************/ + + /* label */ + line = gtk_hbox_new(TRUE, 0); + widget = gtk_label_new("Password"); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 20, 0); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + /* entry */ + widget = gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); + gtk_entry_set_activates_default(GTK_ENTRY(widget), TRUE); + if (gtk_entry_get_invisible_char(GTK_ENTRY(widget)) == '*') + gtk_entry_set_invisible_char(GTK_ENTRY(widget), PIDGIN_INVISIBLE_CHAR); + gtk_entry_set_text(GTK_ENTRY(widget), + service_account_get_string(conv, + OPT_API_BASE_PASSWORD, + "")); + g_object_set_data(G_OBJECT(widget), + PLUGIN_ID "-account_pref-key", + OPT_API_BASE_PASSWORD); + g_signal_connect(G_OBJECT(widget), + "changed", + G_CALLBACK(account_preference_text_changed_cb), + conv); + container = gtk_alignment_new(1.0, 0.5, 1.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 0, 20); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + gtk_box_pack_start_defaults(GTK_BOX(child), line); + + /**************************/ + /* Retrieve interval Form */ + /**************************/ + + /* label */ + line = gtk_hbox_new(FALSE, 0); + widget = gtk_label_new("Retrieve interval"); + container = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 20, 0); + gtk_box_pack_start_defaults(GTK_BOX(line), container); + + /* spin button */ + value = service_account_get_int(conv, + OPT_API_BASE_GET_INTERVAL, + 0); + if(value == 0) { + value = TWITTER_DEFAULT_INTERVAL; + purple_prefs_set_int(OPT_API_BASE_GET_INTERVAL, value); + } + adjust = gtk_adjustment_new(value, 40, 3600, 10, 100, 100); + widget = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1.0, 0); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE); + gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(widget), TRUE); + g_object_set_data(G_OBJECT(widget), + PLUGIN_ID "-account_pref-key", + OPT_API_BASE_GET_INTERVAL); + g_signal_connect(G_OBJECT(widget), + "value-changed", + G_CALLBACK(account_preference_spin_changed_cb), + conv); + container = gtk_alignment_new(1.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 0, 0); + gtk_box_pack_start(GTK_BOX(line), container, FALSE, FALSE, 0); + + /* label */ + widget = gtk_label_new("sec"); + container = gtk_alignment_new(1.0, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(container), widget); + gtk_alignment_set_padding(GTK_ALIGNMENT(container), 0, 0, 0, 20); + gtk_box_pack_start(GTK_BOX(line), container, FALSE, FALSE, 0); + + gtk_box_pack_start_defaults(GTK_BOX(child), line); + + /***************/ + /* create page */ + /***************/ + + tab_label = gtk_label_new("API Based Access"); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child, tab_label); +} + +static void +account_preference_text_changed_cb(GtkEditable *editable, gpointer conv_ptr) +{ + PurpleConversation *conv = (PurpleConversation *) conv_ptr; + const char *key = g_object_get_data(G_OBJECT(editable), + PLUGIN_ID "-account_pref-key"); + gchar *value = gtk_editable_get_chars(editable, 0, -1); + + service_account_set_string(conv, key, value); + g_free(value); +} + +static void +account_preference_bool_toggled_cb(GtkToggleButton *togglebutton, + gpointer conv_ptr) +{ + PurpleConversation *conv = (PurpleConversation *) conv_ptr; + const char *key = g_object_get_data(G_OBJECT(togglebutton), + PLUGIN_ID "-account_pref-key"); + gboolean value = gtk_toggle_button_get_active(togglebutton); + + service_account_set_bool(conv, key, value); +} + +static void +account_preference_spin_changed_cb(GtkSpinButton *spinbutton, gpointer conv_ptr) +{ + PurpleConversation *conv = (PurpleConversation *) conv_ptr; + const char *key = g_object_get_data(G_OBJECT(spinbutton), + PLUGIN_ID "-account_pref-key"); + gint value = gtk_spin_button_get_value_as_int(spinbutton); + + service_account_set_int(conv, key, value); +} + +static void +destroyed_pref_button_cb(GtkWidget *pref_button, gpointer dialog) +{ + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static void +closed_account_preference_window_cb(GtkDialog *dialog, + gint response_id, + gpointer pref_button) +{ + g_signal_handlers_disconnect_by_func(GTK_WIDGET(pref_button), + (GFunc) destroyed_pref_button_cb, + dialog); + gtk_widget_set_sensitive(GTK_WIDGET(pref_button), TRUE); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static gchar* +create_key_with_service_account(PurpleConversation *conv, const char *key) +{ + return g_strdup_printf("%s:%s", key, conv->name); +} + +static void +service_account_set_string(PurpleConversation *conv, + const char *key, + const char *value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + + purple_account_set_string(account, key_with_account, value); + g_free(key_with_account); +} + +static const char* +service_account_get_string(PurpleConversation *conv, + const char *key, + const char *default_value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + const char *value = purple_account_get_string(account, + key_with_account, + default_value); + + g_free(key_with_account); + + return value; +} + +static void +service_account_set_int(PurpleConversation *conv, + const char *key, + int value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + + purple_account_set_int(account, key_with_account, value); + g_free(key_with_account); +} + +static int +service_account_get_int(PurpleConversation *conv, + const char *key, + int default_value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + int value = purple_account_get_int(account, + key_with_account, + default_value); + + g_free(key_with_account); + + return value; +} + +static void +service_account_set_bool(PurpleConversation *conv, + const char *key, + gboolean value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + + purple_account_set_bool(account, key_with_account, value); + g_free(key_with_account); +} + +static gboolean +service_account_get_bool(PurpleConversation *conv, + const char *key, + gboolean default_value) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + gchar *key_with_account = create_key_with_service_account(conv, key); + gboolean value = purple_account_get_bool(account, + key_with_account, + default_value); + + g_free(key_with_account); + + return value; +} + static PidginPluginUiInfo ui_info = { prefs_get_frame, 0, /* page number - reserved */ diff -r 3c5fc8d7b506 -r 45da59a32019 pidgin-twitter.h --- a/pidgin-twitter.h Thu Jul 31 17:22:02 2008 +0900 +++ b/pidgin-twitter.h Thu Jul 31 19:30:24 2008 +0900 @@ -118,6 +118,10 @@ #define OPT_API_BASE_GET_INTERVAL OPT_PIDGINTWITTER "/api_base_get_interval" #define OPT_LOG_OUTPUT OPT_PIDGINTWITTER "/log_output" +/* options depend on service account */ +#define OPT_SCREEN_NAME OPT_PIDGINTWITTER "/screen_name" +#define OPT_API_BASE_PASSWORD OPT_PIDGINTWITTER "/api_base_password" + /* formats and templates */ #define RECIPIENT_FORMAT_TWITTER "@%s" #define SENDER_FORMAT_TWITTER "%s%s: " @@ -130,6 +134,10 @@ #define OOPS_MESSAGE "Oops! Your update was over 140 characters. We sent the short version to your friends (they can view the entire update on the web).
" #define EMPTY "" +/* labels of account preference button */ +#define ACCOUNT_PREF_BUTTON_NORMAL "Account Preference" +#define ACCOUNT_PREF_BUTTON_NOTICE "(*)Account Preference" + /* patterns */ #define P_RECIPIENT "@([A-Za-z0-9_]+)" #define P_SENDER "^(\\r?\\n?)\\s*([A-Za-z0-9_]+): " @@ -185,6 +193,7 @@ static void delete_requested_icon_marks(PidginConversation *gtkconv, GHashTable *table); static void attach_to_window(void); static void attach_to_conv(PurpleConversation *conv, gpointer null); +static void append_account_preference_button(PidginConversation *gtkconv); static gboolean is_twitter_account(PurpleAccount *account, const char *name); static gboolean is_twitter_conv(PurpleConversation *conv); static gboolean is_wassr_account(PurpleAccount *account, const char *name); @@ -210,6 +219,21 @@ static void cancel_fetch_func(gpointer key, gpointer value, gpointer user_data); static gint get_service_type(PurpleConversation *conv); static GdkPixbuf *make_scaled_pixbuf(const gchar *url_text, gsize len); +static void open_account_preference_window(GtkWidget *called_widged, gpointer gtkconv_ptr); +static void build_screen_name_preference_form(PurpleConversation *conv, GtkWidget *notebook); +static void build_twitter_api_preference_form(PurpleConversation *conv, GtkWidget *notebook); +static void destroyed_pref_button_cb(GtkWidget *pref_button, gpointer dialog); +static void closed_account_preference_window_cb(GtkDialog *dialog, gint response_id, gpointer pref_button); +static void account_preference_text_changed_cb(GtkEditable *editable, gpointer conv_ptr); +static void account_preference_bool_toggled_cb(GtkToggleButton *togglebutton, gpointer conv_ptr); +static void account_preference_spin_changed_cb(GtkSpinButton *spinbutton, gpointer conv_ptr); +static gchar* create_key_with_service_account(PurpleConversation *conv, const char *key); +static void service_account_set_string(PurpleConversation *conv, const char *key, const char *value); +static const char* service_account_get_string(PurpleConversation *conv, const char *key, const char *default_value); +static void service_account_set_int(PurpleConversation *conv, const char *key, gboolean value); +static gboolean service_account_get_int(PurpleConversation *conv, const char *key, gboolean default_value); +static void service_account_set_bool(PurpleConversation *conv, const char *key, gboolean value); +static gboolean service_account_get_bool(PurpleConversation *conv, const char *key, gboolean default_value); static void parse_user(xmlNode *user, status_t *st); static void parse_status(xmlNode *status, status_t *st);