pidgin/gtkstatusbox.c

changeset 40682
edbc992e77be
parent 40676
50284e37698c
child 40705
f7a1c67543e5
equal deleted inserted replaced
40681:675b8605dca2 40682:edbc992e77be
1 /* pidgin 1 /*
2 * Pidgin - Internet Messenger
3 * Copyright (C) Pidgin Developers <devel@pidgin.im>
2 * 4 *
3 * Pidgin is the legal property of its developers, whose names are too numerous 5 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this 6 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution. 7 * source distribution.
6 * 8 *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 17 * GNU General Public License for more details.
16 * 18 *
17 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 */ 21 */
21 22
22 /* 23 /*
23 * The status box is made up of two main pieces: 24 * The status box is made up of two main pieces:
24 * - The box that displays the current status, which is made 25 * - The box that displays the current status, which is made
51 #include "pidginstock.h" 52 #include "pidginstock.h"
52 53
53 /* Timeout for typing notifications in seconds */ 54 /* Timeout for typing notifications in seconds */
54 #define TYPING_TIMEOUT 4 55 #define TYPING_TIMEOUT 4
55 56
56 static void remove_typing_cb(PidginStatusBox *box); 57 typedef enum {
58 PIDGIN_STATUS_BOX_TYPE_SEPARATOR,
59 PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
60 PIDGIN_STATUS_BOX_TYPE_POPULAR,
61 PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR,
62 PIDGIN_STATUS_BOX_TYPE_CUSTOM,
63 PIDGIN_STATUS_BOX_TYPE_SAVED,
64 PIDGIN_STATUS_BOX_NUM_TYPES
65 } PidginStatusBoxItemType;
66
67 struct _PidginStatusBox {
68 GtkContainer parent_instance;
69
70 /*< public >*/
71 GtkListStore *store;
72 GtkListStore *dropdown_store;
73
74 PurpleAccount *account;
75
76 PurpleAccount *token_status_account;
77
78 GtkWidget *vbox;
79 gboolean editor_visible;
80 GtkWidget *editor;
81 GtkWidget *input;
82 GtkTextBuffer *buffer;
83
84 GdkCursor *hand_cursor;
85 GdkCursor *arrow_cursor;
86 int icon_size;
87 gboolean icon_opaque;
88
89
90 GtkWidget *cell_view;
91 GtkCellRenderer *icon_rend;
92 GtkCellRenderer *text_rend;
93
94 GdkPixbuf *error_pixbuf;
95
96 gboolean network_available;
97 gboolean connecting;
98
99 GtkTreeIter iter;
100 char *error;
101
102 /*
103 * These widgets are made for renderin'
104 * That's just what they'll do
105 * One of these days these widgets
106 * Are gonna render all over you
107 */
108 GtkWidget *hbox;
109 GtkWidget *toggle_button;
110 GtkWidget *vsep;
111 GtkWidget *arrow;
112
113 GtkWidget *popup_window;
114 GtkWidget *popup_frame;
115 GtkWidget *scrolled_window;
116 GtkWidget *cell_view_frame;
117 GtkTreeViewColumn *column;
118 GtkWidget *tree_view;
119 gboolean popup_in_progress;
120 GtkTreeRowReference *active_row;
121 };
122
123 static void pidgin_status_box_add(PidginStatusBox *status_box, PidginStatusBoxItemType type, GdkPixbuf *pixbuf, const char *text, const char *sec_text, gpointer data);
124 static void pidgin_status_box_add_separator(PidginStatusBox *status_box);
125 static void pidgin_status_box_set_network_available(PidginStatusBox *status_box, gboolean available);
126 static void activate_currently_selected_status(PidginStatusBox *status_box);
127
57 static void update_size (PidginStatusBox *box); 128 static void update_size (PidginStatusBox *box);
58 static gint get_statusbox_index(PidginStatusBox *box, PurpleSavedStatus *saved_status); 129 static gint get_statusbox_index(PidginStatusBox *box, PurpleSavedStatus *saved_status);
59 static PurpleAccount* check_active_accounts_for_identical_statuses(void); 130 static PurpleAccount* check_active_accounts_for_identical_statuses(void);
60 131
61 static void pidgin_status_box_pulse_typing(PidginStatusBox *status_box);
62 static void pidgin_status_box_refresh(PidginStatusBox *status_box); 132 static void pidgin_status_box_refresh(PidginStatusBox *status_box);
63 static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed); 133 static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed);
64 static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed); 134 static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed);
65 static void pidgin_status_box_changed(PidginStatusBox *box); 135 static void pidgin_status_box_changed(PidginStatusBox *box);
66 static void pidgin_status_box_get_preferred_height (GtkWidget *widget, 136 static void pidgin_status_box_get_preferred_height (GtkWidget *widget,
117 }; 187 };
118 188
119 enum { 189 enum {
120 PROP_0, 190 PROP_0,
121 PROP_ACCOUNT, 191 PROP_ACCOUNT,
122 };
123
124 static char *typing_stock_ids[7] = {
125 PIDGIN_STOCK_ANIMATION_TYPING0,
126 PIDGIN_STOCK_ANIMATION_TYPING1,
127 PIDGIN_STOCK_ANIMATION_TYPING2,
128 PIDGIN_STOCK_ANIMATION_TYPING3,
129 PIDGIN_STOCK_ANIMATION_TYPING4,
130 NULL
131 };
132
133 static char *connecting_stock_ids[] = {
134 PIDGIN_STOCK_ANIMATION_CONNECT0,
135 PIDGIN_STOCK_ANIMATION_CONNECT1,
136 PIDGIN_STOCK_ANIMATION_CONNECT2,
137 PIDGIN_STOCK_ANIMATION_CONNECT3,
138 PIDGIN_STOCK_ANIMATION_CONNECT4,
139 PIDGIN_STOCK_ANIMATION_CONNECT5,
140 PIDGIN_STOCK_ANIMATION_CONNECT6,
141 PIDGIN_STOCK_ANIMATION_CONNECT7,
142 PIDGIN_STOCK_ANIMATION_CONNECT8,
143 PIDGIN_STOCK_ANIMATION_CONNECT9,
144 PIDGIN_STOCK_ANIMATION_CONNECT10,
145 PIDGIN_STOCK_ANIMATION_CONNECT11,
146 PIDGIN_STOCK_ANIMATION_CONNECT12,
147 PIDGIN_STOCK_ANIMATION_CONNECT13,
148 PIDGIN_STOCK_ANIMATION_CONNECT14,
149 PIDGIN_STOCK_ANIMATION_CONNECT15,
150 PIDGIN_STOCK_ANIMATION_CONNECT16,
151 PIDGIN_STOCK_ANIMATION_CONNECT17,
152 PIDGIN_STOCK_ANIMATION_CONNECT18,
153 PIDGIN_STOCK_ANIMATION_CONNECT19,
154 PIDGIN_STOCK_ANIMATION_CONNECT20,
155 PIDGIN_STOCK_ANIMATION_CONNECT21,
156 PIDGIN_STOCK_ANIMATION_CONNECT22,
157 PIDGIN_STOCK_ANIMATION_CONNECT23,
158 PIDGIN_STOCK_ANIMATION_CONNECT24,
159 PIDGIN_STOCK_ANIMATION_CONNECT25,
160 PIDGIN_STOCK_ANIMATION_CONNECT26,
161 PIDGIN_STOCK_ANIMATION_CONNECT27,
162 PIDGIN_STOCK_ANIMATION_CONNECT28,
163 PIDGIN_STOCK_ANIMATION_CONNECT29,
164 PIDGIN_STOCK_ANIMATION_CONNECT30,
165 NULL
166 }; 192 };
167 193
168 static GtkContainerClass *parent_class = NULL; 194 static GtkContainerClass *parent_class = NULL;
169 195
170 static void pidgin_status_box_class_init (PidginStatusBoxClass *klass); 196 static void pidgin_status_box_class_init (PidginStatusBoxClass *klass);
306 332
307 static void 333 static void
308 pidgin_status_box_finalize(GObject *obj) 334 pidgin_status_box_finalize(GObject *obj)
309 { 335 {
310 PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(obj); 336 PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(obj);
311 gsize i;
312 337
313 purple_signals_disconnect_by_handle(statusbox); 338 purple_signals_disconnect_by_handle(statusbox);
314 purple_prefs_disconnect_by_handle(statusbox); 339 purple_prefs_disconnect_by_handle(statusbox);
315 340
316 if (statusbox->active_row) 341 if (statusbox->active_row)
317 gtk_tree_row_reference_free(statusbox->active_row); 342 gtk_tree_row_reference_free(statusbox->active_row);
318
319 for (i = 0; i < G_N_ELEMENTS(statusbox->connecting_pixbufs); i++) {
320 if (statusbox->connecting_pixbufs[i] != NULL)
321 g_object_unref(G_OBJECT(statusbox->connecting_pixbufs[i]));
322 }
323
324 for (i = 0; i < G_N_ELEMENTS(statusbox->typing_pixbufs); i++) {
325 if (statusbox->typing_pixbufs[i] != NULL)
326 g_object_unref(G_OBJECT(statusbox->typing_pixbufs[i]));
327 }
328 343
329 g_object_unref(G_OBJECT(statusbox->store)); 344 g_object_unref(G_OBJECT(statusbox->store));
330 g_object_unref(G_OBJECT(statusbox->dropdown_store)); 345 g_object_unref(G_OBJECT(statusbox->dropdown_store));
331 G_OBJECT_CLASS(parent_class)->finalize(obj); 346 G_OBJECT_CLASS(parent_class)->finalize(obj);
332 } 347 }
394 if (status_box->account || (status_box->token_status_account 409 if (status_box->account || (status_box->token_status_account
395 && purple_savedstatus_is_transient(saved_status))) 410 && purple_savedstatus_is_transient(saved_status)))
396 account_status = TRUE; 411 account_status = TRUE;
397 412
398 /* Primary */ 413 /* Primary */
399 if (status_box->typing != 0) 414 if (account_status)
400 {
401 GtkTreeIter iter;
402 PidginStatusBoxItemType type;
403 gpointer data;
404
405 /* Primary (get the status selected in the dropdown) */
406 path = gtk_tree_row_reference_get_path(status_box->active_row);
407 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path))
408 return;
409 gtk_tree_path_free(path);
410
411 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter,
412 TYPE_COLUMN, &type,
413 DATA_COLUMN, &data,
414 -1);
415 if (type == PIDGIN_STATUS_BOX_TYPE_PRIMITIVE)
416 primary = g_strdup(purple_primitive_get_name_from_type(GPOINTER_TO_INT(data)));
417 else
418 /* This should never happen, but just in case... */
419 primary = g_strdup("New status");
420 }
421 else if (account_status)
422 primary = g_strdup(purple_status_get_name(purple_account_get_active_status(acct))); 415 primary = g_strdup(purple_status_get_name(purple_account_get_active_status(acct)));
423 else if (purple_savedstatus_is_transient(saved_status)) 416 else if (purple_savedstatus_is_transient(saved_status))
424 primary = g_strdup(purple_primitive_get_name_from_type(purple_savedstatus_get_primitive_type(saved_status))); 417 primary = g_strdup(purple_primitive_get_name_from_type(purple_savedstatus_get_primitive_type(saved_status)));
425 else 418 else
426 primary = g_markup_escape_text(purple_savedstatus_get_title(saved_status), -1); 419 primary = g_markup_escape_text(purple_savedstatus_get_title(saved_status), -1);
427 420
428 /* Secondary */ 421 /* Secondary */
429 if (status_box->typing != 0) 422 if (status_box->connecting)
430 secondary = g_strdup(_("Typing"));
431 else if (status_box->connecting)
432 secondary = g_strdup(_("Connecting")); 423 secondary = g_strdup(_("Connecting"));
433 else if (!status_box->network_available) 424 else if (!status_box->network_available)
434 secondary = g_strdup(_("Waiting for network connection")); 425 secondary = g_strdup(_("Waiting for network connection"));
435 else if (purple_savedstatus_is_transient(saved_status)) 426 else if (purple_savedstatus_is_transient(saved_status))
436 secondary = NULL; 427 secondary = NULL;
449 else 440 else
450 secondary = NULL; 441 secondary = NULL;
451 } 442 }
452 443
453 /* Pixbuf */ 444 /* Pixbuf */
454 if (status_box->typing != 0) 445 {
455 stock = typing_stock_ids[status_box->typing_index];
456 else if (status_box->connecting)
457 stock = connecting_stock_ids[status_box->connecting_index];
458 else
459 {
460 PurpleStatusType *status_type; 446 PurpleStatusType *status_type;
461 PurpleStatusPrimitive prim; 447 PurpleStatusPrimitive prim;
462 if (account_status) { 448 if (account_status) {
463 status_type = purple_status_get_status_type(purple_account_get_active_status(acct)); 449 status_type = purple_status_get_status_type(purple_account_get_active_status(acct));
464 prim = purple_status_type_get_primitive(status_type); 450 prim = purple_status_type_get_primitive(status_type);
843 829
844 static gboolean 830 static gboolean
845 editor_remove_focus(GtkWidget *w, GdkEventKey *event, PidginStatusBox *status_box) 831 editor_remove_focus(GtkWidget *w, GdkEventKey *event, PidginStatusBox *status_box)
846 { 832 {
847 if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) { 833 if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) {
848 remove_typing_cb(status_box); 834 activate_currently_selected_status(status_box);
835 pidgin_status_box_refresh(status_box);
836
849 return TRUE; 837 return TRUE;
850 } 838 }
851 else if (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_ISO_Left_Tab) 839 else if (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_ISO_Left_Tab)
852 { 840 {
853 /* If last inserted character is a tab, then remove the focus from here */ 841 /* If last inserted character is a tab, then remove the focus from here */
855 g_signal_emit_by_name(G_OBJECT(top), "move-focus", 843 g_signal_emit_by_name(G_OBJECT(top), "move-focus",
856 (event->state & GDK_SHIFT_MASK) ? 844 (event->state & GDK_SHIFT_MASK) ?
857 GTK_DIR_TAB_BACKWARD: GTK_DIR_TAB_FORWARD); 845 GTK_DIR_TAB_BACKWARD: GTK_DIR_TAB_FORWARD);
858 return TRUE; 846 return TRUE;
859 } 847 }
860 if (status_box->typing == 0)
861 return FALSE;
862 848
863 /* Reset the status if Escape was pressed */ 849 /* Reset the status if Escape was pressed */
864 if (event->keyval == GDK_KEY_Escape) 850 if (event->keyval == GDK_KEY_Escape)
865 { 851 {
866 g_source_remove(status_box->typing);
867 status_box->typing = 0;
868
869 if (status_box->account != NULL) 852 if (status_box->account != NULL)
870 update_to_reflect_account_status(status_box, status_box->account, 853 update_to_reflect_account_status(status_box, status_box->account,
871 purple_account_get_active_status(status_box->account)); 854 purple_account_get_active_status(status_box->account));
872 else { 855 else {
873 status_menu_refresh_iter(status_box, TRUE); 856 status_menu_refresh_iter(status_box, TRUE);
874 pidgin_status_box_refresh(status_box); 857 pidgin_status_box_refresh(status_box);
875 } 858 }
876 return TRUE; 859 return TRUE;
877 } 860 }
878 861
879 pidgin_status_box_pulse_typing(status_box);
880 g_source_remove(status_box->typing);
881 status_box->typing = g_timeout_add_seconds(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, status_box);
882
883 return FALSE; 862 return FALSE;
884 } 863 }
885 864
886 static gboolean 865 static gboolean
887 dropdown_store_row_separator_func(GtkTreeModel *model, 866 dropdown_store_row_separator_func(GtkTreeModel *model,
893 872
894 if (type == PIDGIN_STATUS_BOX_TYPE_SEPARATOR) 873 if (type == PIDGIN_STATUS_BOX_TYPE_SEPARATOR)
895 return TRUE; 874 return TRUE;
896 875
897 return FALSE; 876 return FALSE;
898 }
899
900 static void
901 cache_pixbufs(PidginStatusBox *status_box)
902 {
903 GtkIconSize icon_size;
904 gsize i;
905
906 g_object_set(G_OBJECT(status_box->icon_rend), "xpad", 3, NULL);
907 icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
908
909 for (i = 0; i < G_N_ELEMENTS(status_box->connecting_pixbufs); i++) {
910 if (status_box->connecting_pixbufs[i] != NULL)
911 g_object_unref(G_OBJECT(status_box->connecting_pixbufs[i]));
912 if (connecting_stock_ids[i])
913 status_box->connecting_pixbufs[i] = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox),
914 connecting_stock_ids[i], icon_size, "PidginStatusBox");
915 else
916 status_box->connecting_pixbufs[i] = NULL;
917 }
918 status_box->connecting_index = 0;
919
920
921 for (i = 0; i < G_N_ELEMENTS(status_box->typing_pixbufs); i++) {
922 if (status_box->typing_pixbufs[i] != NULL)
923 g_object_unref(G_OBJECT(status_box->typing_pixbufs[i]));
924 if (typing_stock_ids[i])
925 status_box->typing_pixbufs[i] = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox),
926 typing_stock_ids[i], icon_size, "PidginStatusBox");
927 else
928 status_box->typing_pixbufs[i] = NULL;
929 }
930 status_box->typing_index = 0;
931 } 877 }
932 878
933 static void account_enabled_cb(PurpleAccount *acct, PidginStatusBox *status_box) 879 static void account_enabled_cb(PurpleAccount *acct, PidginStatusBox *status_box)
934 { 880 {
935 PurpleAccount *initial_token_acct = status_box->token_status_account; 881 PurpleAccount *initial_token_acct = status_box->token_status_account;
1289 } 1235 }
1290 1236
1291 static void 1237 static void
1292 pidgin_status_box_buffer_changed_cb(GtkTextBuffer *buffer, gpointer data) { 1238 pidgin_status_box_buffer_changed_cb(GtkTextBuffer *buffer, gpointer data) {
1293 PidginStatusBox *status_box = (PidginStatusBox*)data; 1239 PidginStatusBox *status_box = (PidginStatusBox*)data;
1294 if (gtk_widget_get_sensitive(GTK_WIDGET(status_box))) 1240
1295 {
1296 if (status_box->typing != 0) {
1297 pidgin_status_box_pulse_typing(status_box);
1298 g_source_remove(status_box->typing);
1299 }
1300 status_box->typing = g_timeout_add_seconds(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, status_box);
1301 }
1302 pidgin_status_box_refresh(status_box); 1241 pidgin_status_box_refresh(status_box);
1303 } 1242 }
1304 1243
1305 static void 1244 static void
1245 pidgin_status_box_save_message_cb(TalkatuInput *input, gpointer data) {
1246 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(data);
1247
1248 activate_currently_selected_status(status_box);
1249 pidgin_status_box_refresh(status_box);
1250 }
1251
1252 static void
1306 pidgin_status_box_init (PidginStatusBox *status_box) 1253 pidgin_status_box_init (PidginStatusBox *status_box)
1307 { 1254 {
1255 GNetworkMonitor *monitor = NULL;
1308 GtkCellRenderer *text_rend; 1256 GtkCellRenderer *text_rend;
1309 GtkCellRenderer *icon_rend; 1257 GtkCellRenderer *icon_rend;
1310 GtkCellRenderer *emblem_rend; 1258 GtkCellRenderer *emblem_rend;
1311 GtkWidget *toplevel; 1259 GtkWidget *toplevel;
1312 GtkTreeSelection *sel; 1260 GtkTreeSelection *sel;
1261 gboolean network_available = FALSE;
1313 1262
1314 gtk_widget_set_has_window(GTK_WIDGET(status_box), FALSE); 1263 gtk_widget_set_has_window(GTK_WIDGET(status_box), FALSE);
1315 status_box->editor_visible = FALSE; 1264 status_box->editor_visible = FALSE;
1316 status_box->network_available = purple_network_is_available(); 1265 status_box->network_available = purple_network_is_available();
1317 status_box->connecting = FALSE; 1266 status_box->connecting = FALSE;
1318 status_box->typing = 0;
1319 status_box->toggle_button = gtk_toggle_button_new(); 1267 status_box->toggle_button = gtk_toggle_button_new();
1320 status_box->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); 1268 status_box->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1321 status_box->cell_view = gtk_cell_view_new(); 1269 status_box->cell_view = gtk_cell_view_new();
1322 status_box->vsep = gtk_separator_new(GTK_ORIENTATION_VERTICAL); 1270 status_box->vsep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
1323 status_box->arrow = gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_BUTTON); 1271 status_box->arrow = gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
1405 g_object_set(status_box->text_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); 1353 g_object_set(status_box->text_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1406 1354
1407 status_box->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, FALSE); 1355 status_box->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, FALSE);
1408 status_box->editor = talkatu_editor_new(); 1356 status_box->editor = talkatu_editor_new();
1409 status_box->input = talkatu_editor_get_input(TALKATU_EDITOR(status_box->editor)); 1357 status_box->input = talkatu_editor_get_input(TALKATU_EDITOR(status_box->editor));
1358
1410 status_box->buffer = talkatu_html_buffer_new(); 1359 status_box->buffer = talkatu_html_buffer_new();
1411 gtk_text_view_set_buffer(GTK_TEXT_VIEW(status_box->input), status_box->buffer); 1360 gtk_text_view_set_buffer(GTK_TEXT_VIEW(status_box->input), status_box->buffer);
1412 1361
1413 g_signal_connect(G_OBJECT(status_box->buffer), "changed", 1362 g_signal_connect(G_OBJECT(status_box->buffer), "changed",
1414 G_CALLBACK(pidgin_status_box_buffer_changed_cb), 1363 G_CALLBACK(pidgin_status_box_buffer_changed_cb),
1436 1385
1437 gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(status_box->tree_view), dropdown_store_row_separator_func, NULL, NULL); 1386 gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(status_box->tree_view), dropdown_store_row_separator_func, NULL, NULL);
1438 1387
1439 status_box->token_status_account = check_active_accounts_for_identical_statuses(); 1388 status_box->token_status_account = check_active_accounts_for_identical_statuses();
1440 1389
1441 cache_pixbufs(status_box);
1442 pidgin_status_box_regenerate(status_box, TRUE); 1390 pidgin_status_box_regenerate(status_box, TRUE);
1443 1391
1444 purple_signal_connect(purple_savedstatuses_get_handle(), "savedstatus-changed", 1392 purple_signal_connect(purple_savedstatuses_get_handle(), "savedstatus-changed",
1445 status_box, 1393 status_box,
1446 PURPLE_CALLBACK(current_savedstatus_changed_cb), 1394 PURPLE_CALLBACK(current_savedstatus_changed_cb),
1462 status_box); 1410 status_box);
1463 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", status_box, 1411 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", status_box,
1464 PURPLE_CALLBACK(account_status_changed_cb), 1412 PURPLE_CALLBACK(account_status_changed_cb),
1465 status_box); 1413 status_box);
1466 1414
1467 g_signal_connect(G_OBJECT(g_network_monitor_get_default()), 1415 monitor = g_network_monitor_get_default();
1468 "network-changed", 1416 g_signal_connect(G_OBJECT(monitor), "network-changed",
1469 G_CALLBACK(pidgin_status_box_network_changed_cb), 1417 G_CALLBACK(pidgin_status_box_network_changed_cb),
1470 status_box); 1418 status_box);
1419 network_available = g_network_monitor_get_network_available(monitor);
1420 pidgin_status_box_set_network_available(status_box, network_available);
1471 } 1421 }
1472 1422
1473 static void 1423 static void
1474 pidgin_status_box_get_preferred_height(GtkWidget *widget, gint *minimum_height, 1424 pidgin_status_box_get_preferred_height(GtkWidget *widget, gint *minimum_height,
1475 gint *natural_height) 1425 gint *natural_height)
1557 } 1507 }
1558 1508
1559 GtkWidget * 1509 GtkWidget *
1560 pidgin_status_box_new() 1510 pidgin_status_box_new()
1561 { 1511 {
1562 return g_object_new(PIDGIN_TYPE_STATUS_BOX, "account", NULL, 1512 return g_object_new(PIDGIN_TYPE_STATUS_BOX, "account", NULL, NULL);
1563 "iconsel", TRUE, NULL);
1564 } 1513 }
1565 1514
1566 GtkWidget * 1515 GtkWidget *
1567 pidgin_status_box_new_with_account(PurpleAccount *account) 1516 pidgin_status_box_new_with_account(PurpleAccount *account)
1568 { 1517 {
1569 return g_object_new(PIDGIN_TYPE_STATUS_BOX, "account", account, 1518 return g_object_new(PIDGIN_TYPE_STATUS_BOX, "account", account, NULL);
1570 "iconsel", TRUE, NULL);
1571 } 1519 }
1572 1520
1573 /* 1521 /*
1574 * pidgin_status_box_add: 1522 * pidgin_status_box_add:
1575 * @status_box: The status box itself. 1523 * @status_box: The status box itself.
1678 return; 1626 return;
1679 status_box->connecting = connecting; 1627 status_box->connecting = connecting;
1680 pidgin_status_box_refresh(status_box); 1628 pidgin_status_box_refresh(status_box);
1681 } 1629 }
1682 1630
1683 void
1684 pidgin_status_box_pulse_connecting(PidginStatusBox *status_box)
1685 {
1686 if (!status_box)
1687 return;
1688 if (!connecting_stock_ids[++status_box->connecting_index])
1689 status_box->connecting_index = 0;
1690 pidgin_status_box_refresh(status_box);
1691 }
1692
1693 static void
1694 pidgin_status_box_pulse_typing(PidginStatusBox *status_box)
1695 {
1696 if (!typing_stock_ids[++status_box->typing_index])
1697 status_box->typing_index = 0;
1698 pidgin_status_box_refresh(status_box);
1699 }
1700
1701 static void 1631 static void
1702 activate_currently_selected_status(PidginStatusBox *status_box) 1632 activate_currently_selected_status(PidginStatusBox *status_box)
1703 { 1633 {
1704 PidginStatusBoxItemType type; 1634 PidginStatusBoxItemType type;
1705 gpointer data; 1635 gpointer data;
1902 } 1832 }
1903 1833
1904 gtk_widget_set_size_request(status_box->vbox, -1, -1); 1834 gtk_widget_set_size_request(status_box->vbox, -1, -1);
1905 } 1835 }
1906 1836
1907 static void remove_typing_cb(PidginStatusBox *status_box)
1908 {
1909 if (status_box->typing == 0)
1910 {
1911 /* Nothing has changed, so we don't need to do anything */
1912 status_menu_refresh_iter(status_box, FALSE);
1913 return;
1914 }
1915
1916 g_source_remove(status_box->typing);
1917 status_box->typing = 0;
1918
1919 activate_currently_selected_status(status_box);
1920 pidgin_status_box_refresh(status_box);
1921 }
1922
1923 static void pidgin_status_box_changed(PidginStatusBox *status_box) 1837 static void pidgin_status_box_changed(PidginStatusBox *status_box)
1924 { 1838 {
1925 GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row); 1839 GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row);
1926 GtkTreeIter iter; 1840 GtkTreeIter iter;
1927 PidginStatusBoxItemType type; 1841 PidginStatusBoxItemType type;
1939 1853
1940 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, 1854 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter,
1941 TYPE_COLUMN, &type, 1855 TYPE_COLUMN, &type,
1942 DATA_COLUMN, &data, 1856 DATA_COLUMN, &data,
1943 -1); 1857 -1);
1944 if ((wastyping = (status_box->typing != 0)))
1945 g_source_remove(status_box->typing);
1946 status_box->typing = 0;
1947 1858
1948 if (gtk_widget_get_sensitive(GTK_WIDGET(status_box))) 1859 if (gtk_widget_get_sensitive(GTK_WIDGET(status_box)))
1949 { 1860 {
1950 if (type == PIDGIN_STATUS_BOX_TYPE_POPULAR || type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR) 1861 if (type == PIDGIN_STATUS_BOX_TYPE_POPULAR || type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR)
1951 { 1862 {
2012 if (status_box->editor_visible) 1923 if (status_box->editor_visible)
2013 { 1924 {
2014 GtkTextIter start, end; 1925 GtkTextIter start, end;
2015 1926
2016 gtk_widget_show_all(status_box->vbox); 1927 gtk_widget_show_all(status_box->vbox);
2017 status_box->typing = g_timeout_add_seconds(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, status_box);
2018 gtk_widget_grab_focus(status_box->input); 1928 gtk_widget_grab_focus(status_box->input);
2019 1929
2020 gtk_text_buffer_get_start_iter(status_box->buffer, &start); 1930 gtk_text_buffer_get_start_iter(status_box->buffer, &start);
2021 gtk_text_buffer_get_end_iter(status_box->buffer, &end); 1931 gtk_text_buffer_get_end_iter(status_box->buffer, &end);
2022 gtk_text_buffer_select_range(status_box->buffer, &start, &end); 1932 gtk_text_buffer_select_range(status_box->buffer, &start, &end);

mercurial