| 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; |
| 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; |
| 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); |