pidgin/pidginstatusbox.c

changeset 42199
adf6d358d438
parent 41337
a8b8e1703239
child 42450
bd1327c022d4
equal deleted inserted replaced
42198:4df23def5fe0 42199:adf6d358d438
26 26
27 #include <purple.h> 27 #include <purple.h>
28 28
29 #include "pidginstatusbox.h" 29 #include "pidginstatusbox.h"
30 #include "pidginiconname.h" 30 #include "pidginiconname.h"
31 31 #include "pidginstatusdisplay.h"
32 #define PRIMITIVE_FORMAT "primitive_%d" 32
33 #define SAVEDSTATUS_FORMAT "savedstatus_%lu" 33 #define SAVEDSTATUS_FORMAT "savedstatus_%lu"
34
35 typedef enum {
36 PIDGIN_STATUS_BOX_TYPE_SEPARATOR,
37 PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
38 PIDGIN_STATUS_BOX_TYPE_POPULAR,
39 PIDGIN_STATUS_BOX_TYPE_ACTION,
40 PIDGIN_STATUS_BOX_NUM_TYPES
41 } PidginStatusBoxItemType;
42 34
43 struct _PidginStatusBox { 35 struct _PidginStatusBox {
44 GtkBox parent; 36 GtkBox parent;
45 37
46 GtkListStore *model; 38 GtkWidget *button;
47 GtkWidget *combo; 39 PidginStatusDisplay *display;
48 40 GtkPopover *popover;
49 /* This is used to flipback to the correct status when one of the actions 41
50 * items is selected. 42 GMenu *primitives;
51 */ 43 GMenu *saved_statuses;
52 gchar *active_id; 44 GList *custom_widgets;
53 }; 45 };
54 46
55 enum {
56 ID_COLUMN,
57 TYPE_COLUMN, /* PidginStatusBoxItemType */
58 ICON_NAME_COLUMN,
59 PRIMITIVE_COLUMN,
60 TEXT_COLUMN,
61 /* This value depends on TYPE_COLUMN. For POPULAR types, this is the
62 * creation time.
63 */
64 DATA_COLUMN,
65 EMBLEM_VISIBLE_COLUMN,
66 NUM_COLUMNS
67 };
68
69 G_DEFINE_TYPE(PidginStatusBox, pidgin_status_box, GTK_TYPE_BOX) 47 G_DEFINE_TYPE(PidginStatusBox, pidgin_status_box, GTK_TYPE_BOX)
70
71 /* This prototype is necessary so we can block this signal handler when we are
72 * manually updating the combobox.
73 */
74 static void pidgin_status_box_combo_changed_cb(GtkComboBox *combo, gpointer user_data);
75 48
76 /****************************************************************************** 49 /******************************************************************************
77 * Helpers 50 * Helpers
78 *****************************************************************************/ 51 *****************************************************************************/
79 static void 52 static GtkWidget *
80 pidgin_status_box_update_to_status(PidginStatusBox *status_box, 53 pidgin_status_box_make_primitive_widget(const char *action, const char *id) {
81 PurpleSavedStatus *status) 54 GtkWidget *button = NULL;
82 { 55 GtkWidget *display = NULL;
83 gchar *id = NULL; 56 PurpleStatusPrimitive primitive = PURPLE_STATUS_UNSET;
84 gboolean set = FALSE; 57
58 primitive = purple_primitive_get_type_from_id(id);
59 display = pidgin_status_display_new_for_primitive(primitive);
60
61 button = gtk_button_new();
62 gtk_widget_add_css_class(button, "flat");
63 gtk_button_set_child(GTK_BUTTON(button), display);
64
65 gtk_actionable_set_action_name(GTK_ACTIONABLE(button), action);
66 gtk_actionable_set_action_target(GTK_ACTIONABLE(button),
67 (const char *)G_VARIANT_TYPE_INT32,
68 primitive);
69
70 return button;
71 }
72
73 static void
74 pidgin_status_box_populate_primitives(PidginStatusBox *status_box) {
75 GtkPopoverMenu *popover = GTK_POPOVER_MENU(status_box->popover);
76 GMenuModel *menu = G_MENU_MODEL(status_box->primitives);
77 gint n_items = 0;
78
79 n_items = g_menu_model_get_n_items(menu);
80 for(gint index = 0; index < n_items; index++) {
81 GtkWidget *button = NULL;
82 char *action = NULL;
83 char *target = NULL;
84 char *custom_id = NULL;
85
86 g_menu_model_get_item_attribute(menu, index, G_MENU_ATTRIBUTE_ACTION,
87 "s", &action);
88 g_menu_model_get_item_attribute(menu, index, G_MENU_ATTRIBUTE_TARGET,
89 "s", &target);
90 g_menu_model_get_item_attribute(menu, index, "custom", "s", &custom_id);
91
92 button = pidgin_status_box_make_primitive_widget(action, target);
93 gtk_popover_menu_add_child(popover, button, custom_id);
94
95 g_free(action);
96 g_free(target);
97 g_free(custom_id);
98 }
99 }
100
101 static char *
102 pidgin_status_box_make_savedstatus_widget(PurpleSavedStatus *saved_status,
103 GtkWidget **widget)
104 {
105 GtkWidget *button = NULL;
106 GtkWidget *display = NULL;
85 time_t creation_time = 0; 107 time_t creation_time = 0;
86 108
87 /* Try to set the combo box to the saved status. */ 109 display = pidgin_status_display_new_for_saved_status(saved_status);
88 creation_time = purple_savedstatus_get_creation_time(status); 110
89 id = g_strdup_printf(SAVEDSTATUS_FORMAT, creation_time); 111 if(!purple_savedstatus_is_transient(saved_status)) {
90 112 GtkWidget *image = gtk_image_new_from_icon_name("document-save");
91 set = gtk_combo_box_set_active_id(GTK_COMBO_BOX(status_box->combo), id); 113 gtk_widget_set_halign(image, GTK_ALIGN_END);
92 g_free(id); 114 gtk_widget_set_hexpand(image, TRUE);
93 115 gtk_box_append(GTK_BOX(display), image);
94 /* If we failed to set via the savedstatus, fallback to the primitive. */ 116 }
95 if(!set) { 117
96 PurpleStatusPrimitive primitive; 118 button = gtk_button_new();
97 119 gtk_widget_add_css_class(button, "flat");
98 primitive = purple_savedstatus_get_primitive_type(status); 120 gtk_button_set_child(GTK_BUTTON(button), display);
99 id = g_strdup_printf(PRIMITIVE_FORMAT, primitive); 121
100 122 creation_time = purple_savedstatus_get_creation_time(saved_status);
101 gtk_combo_box_set_active_id(GTK_COMBO_BOX(status_box->combo), id); 123 gtk_actionable_set_action_name(GTK_ACTIONABLE(button), "status.set-saved");
102 g_free(id); 124 gtk_actionable_set_action_target(GTK_ACTIONABLE(button),
103 } 125 (const char *)G_VARIANT_TYPE_INT64,
104 } 126 creation_time);
105 127 *widget = button;
106 static void 128
107 pidgin_status_box_add(PidginStatusBox *status_box, 129 return g_strdup_printf(SAVEDSTATUS_FORMAT, creation_time);
108 PidginStatusBoxItemType type, 130 }
109 PurpleStatusPrimitive primitive, const gchar *text, 131
110 gpointer data) 132 static void
111 { 133 pidgin_status_box_populate_saved_statuses(PidginStatusBox *status_box)
112 GtkTreeIter iter; 134 {
113 gchar *id = NULL, *escaped_text = NULL; 135 GtkPopoverMenu *popover_menu = NULL;
114 const gchar *icon_name = NULL; 136 GMenu *menu = NULL;
115 gboolean emblem_visible = FALSE;
116
117 escaped_text = g_markup_escape_text(text, -1);
118
119 if(type == PIDGIN_STATUS_BOX_TYPE_POPULAR) {
120 PurpleSavedStatus *saved_status = NULL;
121 time_t creation_time = GPOINTER_TO_INT(data);
122
123 saved_status = purple_savedstatus_find_by_creation_time(creation_time);
124
125 if(saved_status != NULL) {
126 id = g_strdup_printf(SAVEDSTATUS_FORMAT, creation_time);
127
128 if(!purple_savedstatus_is_transient(saved_status)) {
129 emblem_visible = TRUE;
130 }
131 }
132 }
133
134 if(id == NULL && primitive != PURPLE_STATUS_UNSET) {
135 id = g_strdup_printf(PRIMITIVE_FORMAT, primitive);
136 }
137
138 icon_name = pidgin_icon_name_from_status_primitive(primitive, NULL);
139
140 gtk_list_store_append(status_box->model, &iter);
141 gtk_list_store_set(status_box->model, &iter,
142 ID_COLUMN, id,
143 TYPE_COLUMN, type,
144 ICON_NAME_COLUMN, icon_name,
145 PRIMITIVE_COLUMN, primitive,
146 TEXT_COLUMN, escaped_text,
147 DATA_COLUMN, data,
148 EMBLEM_VISIBLE_COLUMN, emblem_visible,
149 -1);
150
151 g_free(escaped_text);
152 g_free(id);
153 }
154
155 static gboolean
156 pidgin_status_box_row_separator_func(GtkTreeModel *model, GtkTreeIter *iter,
157 G_GNUC_UNUSED gpointer data)
158 {
159 PidginStatusBoxItemType type;
160
161 gtk_tree_model_get(model, iter, TYPE_COLUMN, &type, -1);
162
163 return type == PIDGIN_STATUS_BOX_TYPE_SEPARATOR;
164 }
165
166 static void
167 pidgin_status_box_add_separator(PidginStatusBox *status_box) {
168 GtkTreeIter iter;
169
170 gtk_list_store_append(status_box->model, &iter);
171 gtk_list_store_set(status_box->model, &iter,
172 TYPE_COLUMN, PIDGIN_STATUS_BOX_TYPE_SEPARATOR,
173 -1);
174 }
175
176 static void
177 pidgin_status_box_update_saved_statuses(PidginStatusBox *status_box) {
178 GList *list, *cur; 137 GList *list, *cur;
179 138
180 list = purple_savedstatuses_get_popular(6); 139 list = purple_savedstatuses_get_popular(6);
181 if (list == NULL) { 140 if (list == NULL) {
182 /* Odd... oh well, nothing we can do about it. */ 141 /* Odd... oh well, nothing we can do about it. */
183 return; 142 return;
184 } 143 }
185 144
145 popover_menu = GTK_POPOVER_MENU(status_box->popover);
146 menu = status_box->saved_statuses;
186 for(cur = list; cur != NULL; cur = cur->next) { 147 for(cur = list; cur != NULL; cur = cur->next) {
187 PurpleSavedStatus *saved = cur->data; 148 PurpleSavedStatus *saved = cur->data;
188 GString *text = NULL; 149 GtkWidget *widget = NULL;
189 time_t creation_time; 150 char *id = NULL;
190 151 GMenuItem *item = NULL;
191 text = g_string_new(purple_savedstatus_get_title(saved)); 152
192 153 id = pidgin_status_box_make_savedstatus_widget(saved, &widget);
193 if(!purple_savedstatus_is_transient(saved)) { 154 item = g_menu_item_new(NULL, NULL);
194 /* 155 g_menu_item_set_attribute(item, "custom", "s", id);
195 * Transient statuses do not have a title, so the savedstatus 156 g_menu_append_item(menu, item);
196 * API returns the message when purple_savedstatus_get_title() is 157 gtk_popover_menu_add_child(popover_menu, widget, id);
197 * called, so we don't need to get the message a second time. 158 status_box->custom_widgets = g_list_prepend(status_box->custom_widgets,
198 */ 159 widget);
199 const gchar *message = NULL; 160
200 161 g_free(id);
201 message = purple_savedstatus_get_message(saved);
202 if(message != NULL) {
203 gchar *stripped = purple_markup_strip_html(message);
204
205 purple_util_chrreplace(stripped, '\n', ' ');
206 g_string_append_printf(text, " - %s", stripped);
207 g_free(stripped);
208 }
209 }
210
211 creation_time = purple_savedstatus_get_creation_time(saved);
212 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_POPULAR,
213 purple_savedstatus_get_primitive_type(saved),
214 text->str, GINT_TO_POINTER(creation_time));
215
216 g_string_free(text, TRUE);
217 } 162 }
218 163
219 g_list_free(list); 164 g_list_free(list);
220
221 pidgin_status_box_add_separator(status_box);
222 }
223
224 static void
225 pidgin_status_box_populate(PidginStatusBox *status_box) {
226 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
227 PURPLE_STATUS_AVAILABLE, _("Available"), NULL);
228 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
229 PURPLE_STATUS_AWAY, _("Away"), NULL);
230 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
231 PURPLE_STATUS_UNAVAILABLE, _("Do not disturb"),
232 NULL);
233 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
234 PURPLE_STATUS_INVISIBLE, _("Invisible"), NULL);
235 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_PRIMITIVE,
236 PURPLE_STATUS_OFFLINE, _("Offline"), NULL);
237
238 pidgin_status_box_add_separator(status_box);
239
240 pidgin_status_box_update_saved_statuses(status_box);
241
242 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_ACTION,
243 PURPLE_STATUS_UNSET, _("New Status..."),
244 "new-status");
245 pidgin_status_box_add(status_box, PIDGIN_STATUS_BOX_TYPE_ACTION,
246 PURPLE_STATUS_UNSET, _("Saved Statuses..."),
247 "status-manager");
248 } 165 }
249 166
250 /****************************************************************************** 167 /******************************************************************************
251 * Callbacks 168 * Callbacks
252 *****************************************************************************/ 169 *****************************************************************************/
253 static void 170 static void
254 pidgin_status_box_combo_changed_cb(GtkComboBox *combo, gpointer user_data) { 171 pidgin_status_box_set_primitive(G_GNUC_UNUSED GSimpleAction *action,
255 PidginStatusBox *status_box = user_data; 172 GVariant *parameter, gpointer data)
256 PidginStatusBoxItemType type; 173 {
174 PidginStatusBox *status_box = data;
257 PurpleSavedStatus *saved_status = NULL; 175 PurpleSavedStatus *saved_status = NULL;
258 PurpleStatusPrimitive primitive; 176 PurpleStatusPrimitive primitive;
259 GtkTreeIter iter; 177
260 gchar *id = NULL; 178 gtk_menu_button_popdown(GTK_MENU_BUTTON(status_box->button));
261 gpointer data; 179
262 180 if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) {
263 if(!gtk_combo_box_get_active_iter(combo, &iter)) { 181 g_critical("status.set-primitive action parameter is of incorrect type %s",
182 g_variant_get_type_string(parameter));
264 return; 183 return;
265 } 184 }
266 185
267 gtk_tree_model_get(GTK_TREE_MODEL(status_box->model), &iter, 186 primitive = g_variant_get_int32(parameter);
268 ID_COLUMN, &id, 187
269 TYPE_COLUMN, &type, 188 saved_status = purple_savedstatus_find_transient_by_type_and_message(primitive, NULL);
270 PRIMITIVE_COLUMN, &primitive, 189 if(saved_status == NULL) {
271 DATA_COLUMN, &data, 190 saved_status = purple_savedstatus_new(NULL, primitive);
272 -1);
273
274 if(type == PIDGIN_STATUS_BOX_TYPE_PRIMITIVE) {
275 saved_status = purple_savedstatus_find_transient_by_type_and_message(primitive, NULL);
276 if(saved_status == NULL) {
277 saved_status = purple_savedstatus_new(NULL, primitive);
278 }
279 } else if(type == PIDGIN_STATUS_BOX_TYPE_POPULAR) {
280 time_t creation_time = GPOINTER_TO_INT(data);
281
282 saved_status = purple_savedstatus_find_by_creation_time(creation_time);
283 } else if(type == PIDGIN_STATUS_BOX_TYPE_ACTION) {
284 GApplication *application = NULL;
285 const gchar *action_name = (const gchar *)data;
286
287 application = g_application_get_default();
288
289 g_action_group_activate_action(G_ACTION_GROUP(application),
290 action_name, NULL);
291
292 gtk_combo_box_set_active_id(combo, status_box->active_id);
293 } 191 }
294 192
295 if(saved_status != NULL) { 193 if(saved_status != NULL) {
296 if(saved_status != purple_savedstatus_get_current()) { 194 if(saved_status != purple_savedstatus_get_current()) {
297 purple_savedstatus_activate(saved_status); 195 purple_savedstatus_activate(saved_status);
298 } 196 }
299 197 }
300 g_free(status_box->active_id); 198 }
301 status_box->active_id = id; 199
302 } else { 200 static void
303 g_free(id); 201 pidgin_status_box_set_saved_status(G_GNUC_UNUSED GSimpleAction *action,
202 GVariant *parameter, gpointer data)
203 {
204 PidginStatusBox *status_box = data;
205 PurpleSavedStatus *saved_status = NULL;
206 time_t creation_time = 0;
207
208 gtk_menu_button_popdown(GTK_MENU_BUTTON(status_box->button));
209
210 if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT64)) {
211 g_critical("status.set-saved action parameter is of incorrect type %s",
212 g_variant_get_type_string(parameter));
213 return;
214 }
215
216 creation_time = (time_t)g_variant_get_int64(parameter);
217 saved_status = purple_savedstatus_find_by_creation_time(creation_time);
218
219 if(saved_status != NULL) {
220 if(saved_status != purple_savedstatus_get_current()) {
221 purple_savedstatus_activate(saved_status);
222 }
304 } 223 }
305 } 224 }
306 225
307 static void 226 static void
308 pidgin_status_box_savedstatus_changed_cb(PurpleSavedStatus *now, 227 pidgin_status_box_savedstatus_changed_cb(PurpleSavedStatus *now,
314 /* If we don't have a status, we have to bail. */ 233 /* If we don't have a status, we have to bail. */
315 if(now == NULL) { 234 if(now == NULL) {
316 return; 235 return;
317 } 236 }
318 237
319 pidgin_status_box_update_to_status(status_box, now); 238 pidgin_status_display_set_saved_status(status_box->display, now);
239 }
240
241 static void
242 pidgin_status_box_remove_custom_widget(GtkWidget *widget, gpointer user_data) {
243 GtkPopoverMenu *popover_menu = user_data;
244
245 gtk_popover_menu_remove_child(popover_menu, widget);
320 } 246 }
321 247
322 static void 248 static void
323 pidgin_status_box_savedstatus_updated_cb(G_GNUC_UNUSED PurpleSavedStatus *status, 249 pidgin_status_box_savedstatus_updated_cb(G_GNUC_UNUSED PurpleSavedStatus *status,
324 gpointer data) 250 gpointer data)
325 { 251 {
326 PidginStatusBox *status_box = data; 252 PidginStatusBox *status_box = data;
327 PurpleSavedStatus *current = NULL; 253
328 static gboolean getting_current = FALSE; 254 g_list_foreach(status_box->custom_widgets,
329 255 (GFunc)pidgin_status_box_remove_custom_widget,
330 /* purple_status_get_current will create a new status if this is a brand 256 status_box->popover);
331 * new install or the setting wasn't found. This leads to this handler 257 g_clear_list(&status_box->custom_widgets, NULL);
332 * getting stuck in a loop until it segfaults because the stack smashed 258 g_menu_remove_all(status_box->saved_statuses);
333 * into the heap. Anyways, we use this static boolean to check when this 259
334 * function is called by purple_status_get_current so we can bail out and 260 pidgin_status_box_populate_saved_statuses(status_box);
335 * break the loop.
336 */
337 if(getting_current) {
338 return;
339 }
340
341 gtk_list_store_clear(status_box->model);
342 pidgin_status_box_populate(status_box);
343
344 getting_current = TRUE;
345 current = purple_savedstatus_get_current();
346 pidgin_status_box_update_to_status(status_box, current);
347 getting_current = FALSE;
348 } 261 }
349 262
350 /****************************************************************************** 263 /******************************************************************************
351 * GObject Implementation 264 * GObject Implementation
352 *****************************************************************************/ 265 *****************************************************************************/
354 pidgin_status_box_finalize(GObject *obj) { 267 pidgin_status_box_finalize(GObject *obj) {
355 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(obj); 268 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(obj);
356 269
357 purple_signals_disconnect_by_handle(status_box); 270 purple_signals_disconnect_by_handle(status_box);
358 271
359 g_free(status_box->active_id); 272 g_clear_list(&status_box->custom_widgets, NULL);
360 273
361 G_OBJECT_CLASS(pidgin_status_box_parent_class)->finalize(obj); 274 G_OBJECT_CLASS(pidgin_status_box_parent_class)->finalize(obj);
362 } 275 }
363 276
364 static void 277 static void
365 pidgin_status_box_init(PidginStatusBox *status_box) { 278 pidgin_status_box_init(PidginStatusBox *status_box) {
366 gpointer handle; 279 gpointer handle;
280 GSimpleActionGroup *action_group = NULL;
281 GActionEntry actions[] = {
282 {
283 .name = "set-primitive",
284 .activate = pidgin_status_box_set_primitive,
285 .parameter_type = (const char *)G_VARIANT_TYPE_INT32,
286 }, {
287 .name = "set-saved",
288 .activate = pidgin_status_box_set_saved_status,
289 .parameter_type = (const char *)G_VARIANT_TYPE_INT64,
290 },
291 };
367 292
368 gtk_widget_init_template(GTK_WIDGET(status_box)); 293 gtk_widget_init_template(GTK_WIDGET(status_box));
369 294
370 gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(status_box->combo), 295 action_group = g_simple_action_group_new();
371 pidgin_status_box_row_separator_func, 296 g_action_map_add_action_entries(G_ACTION_MAP(action_group),
372 NULL, NULL); 297 actions, G_N_ELEMENTS(actions),
373 298 status_box);
374 pidgin_status_box_populate(status_box); 299 gtk_widget_insert_action_group(GTK_WIDGET(status_box), "status",
300 G_ACTION_GROUP(action_group));
301
302 status_box->popover = gtk_menu_button_get_popover(GTK_MENU_BUTTON(status_box->button));
303 gtk_popover_set_has_arrow(status_box->popover, FALSE);
304
305 pidgin_status_box_populate_primitives(status_box);
306 pidgin_status_box_populate_saved_statuses(status_box);
375 307
376 handle = purple_savedstatuses_get_handle(); 308 handle = purple_savedstatuses_get_handle();
377 purple_signal_connect(handle, "savedstatus-changed", status_box, 309 purple_signal_connect(handle, "savedstatus-changed", status_box,
378 G_CALLBACK(pidgin_status_box_savedstatus_changed_cb), 310 G_CALLBACK(pidgin_status_box_savedstatus_changed_cb),
379 status_box); 311 status_box);
388 status_box); 320 status_box);
389 } 321 }
390 322
391 static void 323 static void
392 pidgin_status_box_constructed(GObject *obj) { 324 pidgin_status_box_constructed(GObject *obj) {
325 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(obj);
393 PurpleSavedStatus *status = NULL; 326 PurpleSavedStatus *status = NULL;
394 327
395 G_OBJECT_CLASS(pidgin_status_box_parent_class)->constructed(obj); 328 G_OBJECT_CLASS(pidgin_status_box_parent_class)->constructed(obj);
396 329
397 status = purple_savedstatus_get_current(); 330 status = purple_savedstatus_get_current();
398 331 pidgin_status_display_set_saved_status(status_box->display, status);
399 pidgin_status_box_update_to_status(PIDGIN_STATUS_BOX(obj), status);
400 } 332 }
401 333
402 static void 334 static void
403 pidgin_status_box_class_init(PidginStatusBoxClass *klass) { 335 pidgin_status_box_class_init(PidginStatusBoxClass *klass) {
404 GObjectClass *obj_class = G_OBJECT_CLASS(klass); 336 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
411 widget_class, 343 widget_class,
412 "/im/pidgin/Pidgin3/Status/box.ui" 344 "/im/pidgin/Pidgin3/Status/box.ui"
413 ); 345 );
414 346
415 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox, 347 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox,
416 model); 348 button);
417 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox, 349 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox,
418 combo); 350 display);
419 351 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox,
420 gtk_widget_class_bind_template_callback(widget_class, 352 primitives);
421 pidgin_status_box_combo_changed_cb); 353 gtk_widget_class_bind_template_child(widget_class, PidginStatusBox,
354 saved_statuses);
422 } 355 }
423 356
424 /****************************************************************************** 357 /******************************************************************************
425 * Public API 358 * Public API
426 *****************************************************************************/ 359 *****************************************************************************/

mercurial