45
43
#include "gossip-contact-info-dialog.h"
46
44
#include "gossip-contact-list.h"
47
45
#include "gossip-edit-contact-dialog.h"
46
#include "gossip-email.h"
48
47
#include "gossip-ft-window.h"
49
48
#include "gossip-log-window.h"
50
49
#include "gossip-marshal.h"
51
50
#include "gossip-sound.h"
52
#include "gossip-stock.h"
53
51
#include "gossip-ui-utils.h"
55
53
#define DEBUG_DOMAIN "ContactList"
57
/* Flashing delay for icons (milliseconds). */
58
#define FLASH_TIMEOUT 500
60
55
/* Active users are those which have recently changed state
61
56
* (e.g. online, offline or from normal to a busy state).
255
248
GtkTreeIter *iter,
256
249
GtkTreePath *path,
257
250
gpointer user_data);
258
static gint contact_list_sort_func (GtkTreeModel *model,
251
static gint contact_list_name_sort_func (GtkTreeModel *model,
255
static gint contact_list_state_sort_func (GtkTreeModel *model,
259
static gboolean contact_list_filter_func (GtkTreeModel *model,
261
GossipContactList *list);
262
262
static GList * contact_list_find_contact (GossipContactList *list,
263
263
GossipContact *contact);
264
264
static gboolean contact_list_find_contact_foreach (GtkTreeModel *model,
277
277
static void contact_list_action_remove_selected (GossipContactList *list);
278
278
static void contact_list_action_invite_selected (GossipContactList *list);
279
279
static void contact_list_action_rename_group_selected (GossipContactList *list);
280
static void contact_list_free_flash_timeout_data (FlashTimeoutData *timeout_data);
281
static void contact_list_flash_free_data (FlashData *data);
282
static gboolean contact_list_flash_timeout_func (FlashTimeoutData *timeout_data);
283
280
static void contact_list_event_added_cb (GossipEventManager *manager,
284
281
GossipEvent *event,
285
282
GossipContactList *list);
358
359
N_("_Send File..."), NULL, N_("Send a file"),
359
360
G_CALLBACK (contact_list_action_cb)
363
N_("Emai_l..."), NULL, N_("Email contact"),
364
G_CALLBACK (contact_list_action_cb)
361
366
{ "Log", GTK_STOCK_JUSTIFY_LEFT,
362
367
N_("_View Previous Conversations"), NULL, N_("View previous conversations with this contact"),
363
368
G_CALLBACK (contact_list_action_cb)
405
411
static GdkAtom drag_atoms_dest[G_N_ELEMENTS (drag_types_dest)];
406
412
static GdkAtom drag_atoms_source[G_N_ELEMENTS (drag_types_source)];
415
gossip_contact_list_sort_get_type (void)
417
static GType etype = 0;
420
static const GEnumValue values[] = {
421
{ GOSSIP_CONTACT_LIST_SORT_NAME,
422
"GOSSIP_CONTACT_LIST_SORT_NAME",
424
{ GOSSIP_CONTACT_LIST_SORT_STATE,
425
"GOSSIP_CONTACT_LIST_SORT_STATE",
430
etype = g_enum_register_static ("GossipContactListSort", values);
408
436
G_DEFINE_TYPE (GossipContactList, gossip_contact_list, GTK_TYPE_TREE_VIEW);
453
481
G_PARAM_READWRITE));
483
g_object_class_install_property (object_class,
485
g_param_spec_string ("filter",
487
"The text to use to filter the contact list",
491
g_object_class_install_property (object_class,
493
g_param_spec_enum ("sort-criterium",
495
"The sort criterium to use for sorting the contact list",
496
GOSSIP_TYPE_CONTACT_LIST_SORT,
497
GOSSIP_CONTACT_LIST_SORT_NAME,
455
500
g_type_class_add_private (object_class, sizeof (GossipContactListPriv));
625
682
gossip_contact_list_set_is_compact (GOSSIP_CONTACT_LIST (object),
626
683
g_value_get_boolean (value));
686
gossip_contact_list_set_filter (GOSSIP_CONTACT_LIST (object),
687
g_value_get_string (value));
689
case PROP_SORT_CRITERIUM:
690
gossip_contact_list_set_sort_criterium (GOSSIP_CONTACT_LIST (object),
691
g_value_get_enum (value));
629
694
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
784
849
/* Get online state before. */
785
850
if (iters && g_list_length (iters) > 0) {
788
iter = g_list_nth_data (iters, 0);
789
gtk_tree_model_get (model, iter, COL_IS_ONLINE, &was_online, -1);
851
gtk_tree_model_get (model, iters->data, COL_IS_ONLINE, &was_online, -1);
792
854
/* Is this really an update or an online/offline. */
819
881
pixbuf_presence = gossip_pixbuf_for_contact (contact);
820
pixbuf_composing = gossip_pixbuf_from_stock (GOSSIP_STOCK_TYPING,
822
pixbuf_avatar = gossip_pixbuf_avatar_from_contact_scaled (contact, 32, 32);
882
pixbuf_composing = gossip_stock_create_pixbuf (gossip_app_get_window (),
885
pixbuf_avatar = gossip_contact_get_avatar_pixbuf (contact);
887
g_object_ref (pixbuf_avatar);
824
890
pixbuf = pixbuf_presence;
832
898
pixbuf = pixbuf_composing;
835
gtk_tree_store_set (GTK_TREE_STORE (model), l->data,
901
gtk_tree_store_set (priv->store, l->data,
836
902
COL_PIXBUF_STATUS, pixbuf,
837
903
COL_STATUS, gossip_contact_get_status (contact),
838
904
COL_IS_ONLINE, now_online,
1005
1072
iters = contact_list_find_contact (list, contact);
1006
1073
for (l = iters; l; l = l->next) {
1007
1074
GtkTreePath *path;
1012
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
1076
gtk_tree_store_set (priv->store, l->data,
1013
1077
COL_IS_COMPOSING, composing,
1017
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
1081
gtk_tree_store_set (priv->store, l->data,
1018
1082
COL_PIXBUF_STATUS, pixbuf,
1022
path = gtk_tree_model_get_path (model, iter);
1023
gtk_tree_model_row_changed (model, path, iter);
1086
path = gtk_tree_model_get_path (model, l->data);
1087
gtk_tree_model_row_changed (model, path, l->data);
1024
1088
gtk_tree_path_free (path);
1038
1102
gboolean active,
1039
1103
gboolean set_changed)
1041
GtkTreeModel *model;
1044
model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
1105
GossipContactListPriv *priv;
1106
GtkTreeModel *model;
1109
priv = GET_PRIV (list);
1111
model = GTK_TREE_MODEL (priv->store);
1046
1113
iters = contact_list_find_contact (list, contact);
1047
1114
for (l = iters; l; l = l->next) {
1048
1115
GtkTreePath *path;
1053
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
1117
gtk_tree_store_set (priv->store, l->data,
1054
1118
COL_IS_ACTIVE, active,
1056
1121
gossip_debug (DEBUG_DOMAIN, "Set item %s", active ? "active" : "inactive");
1058
1123
if (set_changed) {
1059
path = gtk_tree_model_get_path (model, iter);
1060
gtk_tree_model_row_changed (model, path, iter);
1124
path = gtk_tree_model_get_path (model, l->data);
1125
gtk_tree_model_row_changed (model, path, l->data);
1061
1126
gtk_tree_path_free (path);
1250
contact_list_get_group_foreach (GtkTreeModel *model,
1258
/* Groups are only at the top level. */
1259
if (gtk_tree_path_get_depth (path) != 1) {
1263
gtk_tree_model_get (model, iter,
1265
COL_IS_GROUP, &is_group,
1268
if (is_group && strcmp (str, fg->name) == 0) {
1185
1279
contact_list_get_group (GossipContactList *list,
1186
1280
const gchar *name,
1188
1282
GtkTreeIter *iter_separator_to_set,
1189
1283
gboolean *created)
1191
GtkTreeModel *model;
1192
GtkTreeIter iter_group, iter_separator;
1285
GossipContactListPriv *priv;
1286
GtkTreeModel *model;
1287
GtkTreeIter iter_group, iter_separator;
1290
priv = GET_PRIV (list);
1195
1292
memset (&fg, 0, sizeof (fg));
1197
1294
fg.name = name;
1199
model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
1296
model = GTK_TREE_MODEL (priv->store);
1200
1297
gtk_tree_model_foreach (model,
1201
1298
(GtkTreeModelForeachFunc) contact_list_get_group_foreach,
1259
contact_list_get_group_foreach (GtkTreeModel *model,
1267
/* Groups are only at the top level. */
1268
if (gtk_tree_path_get_depth (path) != 1) {
1272
gtk_tree_model_get (model, iter,
1274
COL_IS_GROUP, &is_group,
1277
if (is_group && strcmp (str, fg->name) == 0) {
1288
1356
contact_list_add_contact (GossipContactList *list,
1289
1357
GossipContact *contact)
1305
1373
gboolean show_avatar = FALSE;
1307
1375
pixbuf_status = gossip_pixbuf_for_contact (contact);
1308
pixbuf_avatar = gossip_pixbuf_avatar_from_contact_scaled (
1376
pixbuf_avatar = gossip_contact_get_avatar_pixbuf (contact);
1377
if (pixbuf_avatar) {
1378
g_object_ref (pixbuf_avatar);
1311
1381
if (priv->show_avatars && !priv->is_compact) {
1312
1382
show_avatar = TRUE;
1315
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
1316
gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
1385
gossip_debug (DEBUG_DOMAIN, "");
1386
gossip_debug (DEBUG_DOMAIN,
1387
"vvvvvvvvvvvvvvvv FIXME: Errors may follow below (since filter work) vvvvvvvvvvvvvvvv");
1389
gossip_debug (DEBUG_DOMAIN,
1390
"**** GossipContact:%p, is GObject:%s, is GossipContact:%s, ADDING CONTACT #1",
1392
G_IS_OBJECT (contact) ? "yes" : "no",
1393
GOSSIP_IS_CONTACT (contact) ? "yes" : "no");
1395
gtk_tree_store_append (priv->store, &iter, NULL);
1396
gtk_tree_store_set (priv->store, &iter,
1317
1397
COL_PIXBUF_STATUS, pixbuf_status,
1318
1398
COL_PIXBUF_AVATAR, pixbuf_avatar,
1319
1399
COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
1358
1447
show_avatar = TRUE;
1362
gtk_tree_store_insert_after (GTK_TREE_STORE (model),
1363
&iter, &iter_group, NULL);
1364
gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
1450
gossip_debug (DEBUG_DOMAIN, "");
1451
gossip_debug (DEBUG_DOMAIN,
1452
"vvvvvvvvvvvvvvvv FIXME: Errors may follow below (since filter work) vvvvvvvvvvvvvvvv");
1454
gossip_debug (DEBUG_DOMAIN,
1455
"**** GossipContact:%p, is GObject:%s, is GossipContact:%s, ADDING CONTACT #2",
1457
G_IS_OBJECT (contact) ? "yes" : "no",
1458
GOSSIP_IS_CONTACT (contact) ? "yes" : "no");
1460
gtk_tree_store_insert_after (priv->store, &iter, &iter_group, NULL);
1461
gtk_tree_store_set (priv->store, &iter,
1365
1462
COL_PIXBUF_STATUS, pixbuf_status,
1366
1463
COL_PIXBUF_AVATAR, pixbuf_avatar,
1367
1464
COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
1442
1550
if (gtk_tree_model_iter_parent (model, &parent, l->data) &&
1443
1551
gtk_tree_model_iter_n_children (model, &parent) <= 2) {
1444
gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
1552
gtk_tree_store_remove (priv->store, &parent);
1446
gtk_tree_store_remove (GTK_TREE_STORE (model), l->data);
1554
gtk_tree_store_remove (priv->store, l->data);
1450
g_list_foreach (iters, (GFunc)gtk_tree_iter_free, NULL);
1558
g_list_foreach (iters, (GFunc) gtk_tree_iter_free, NULL);
1451
1559
g_list_free (iters);
1453
1561
if (remove_flash) {
1459
1567
contact_list_create_model (GossipContactList *list)
1461
GtkTreeModel *model;
1463
model = GTK_TREE_MODEL (
1464
gtk_tree_store_new (COL_COUNT,
1465
GDK_TYPE_PIXBUF, /* Status pixbuf */
1466
GDK_TYPE_PIXBUF, /* Avatar pixbuf */
1467
G_TYPE_BOOLEAN, /* Avatar pixbuf visible */
1468
G_TYPE_STRING, /* Name */
1469
G_TYPE_STRING, /* Status string */
1470
G_TYPE_BOOLEAN, /* Show status */
1471
GOSSIP_TYPE_CONTACT, /* Contact type */
1472
G_TYPE_BOOLEAN, /* Is group */
1473
G_TYPE_BOOLEAN, /* Is active */
1474
G_TYPE_BOOLEAN, /* Is online */
1475
G_TYPE_BOOLEAN, /* Is composing */
1476
G_TYPE_BOOLEAN)); /* Is separator */
1569
GossipContactListPriv *priv;
1570
GtkTreeModel *model;
1572
priv = GET_PRIV (list);
1575
g_object_unref (priv->store);
1579
g_object_unref (priv->filter);
1582
priv->store = gtk_tree_store_new (COL_COUNT,
1583
GDK_TYPE_PIXBUF, /* Status pixbuf */
1584
GDK_TYPE_PIXBUF, /* Avatar pixbuf */
1585
G_TYPE_BOOLEAN, /* Avatar pixbuf visible */
1586
G_TYPE_STRING, /* Name */
1587
G_TYPE_STRING, /* Status string */
1588
G_TYPE_BOOLEAN, /* Show status */
1589
GOSSIP_TYPE_CONTACT, /* Contact type */
1590
G_TYPE_BOOLEAN, /* Is group */
1591
G_TYPE_BOOLEAN, /* Is active */
1592
G_TYPE_BOOLEAN, /* Is online */
1593
G_TYPE_BOOLEAN, /* Is composing */
1594
G_TYPE_BOOLEAN); /* Is separator */
1596
/* Save normal model */
1597
model = GTK_TREE_MODEL (priv->store);
1599
/* Set up sorting */
1478
1600
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
1480
contact_list_sort_func,
1483
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1485
GTK_SORT_ASCENDING);
1487
gtk_tree_view_set_model (GTK_TREE_VIEW (list), model);
1489
g_object_unref (model);
1602
contact_list_name_sort_func,
1604
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
1606
contact_list_state_sort_func,
1609
gossip_contact_list_set_sort_criterium (list, priv->sort_criterium);
1612
priv->filter = gtk_tree_model_filter_new (model, NULL);
1614
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
1615
(GtkTreeModelFilterVisibleFunc)
1616
contact_list_filter_func,
1619
gtk_tree_view_set_model (GTK_TREE_VIEW (list), priv->filter);
1492
1622
static gboolean
2304
contact_list_sort_func (GtkTreeModel *model,
2305
GtkTreeIter *iter_a,
2306
GtkTreeIter *iter_b,
2444
contact_list_state_sort_func (GtkTreeModel *model,
2445
GtkTreeIter *iter_a,
2446
GtkTreeIter *iter_b,
2450
gchar *name_a, *name_b;
2451
gboolean is_separator_a, is_separator_b;
2452
GossipContact *contact_a, *contact_b;
2453
GossipPresence *presence_a, *presence_b;
2454
GossipPresenceState state_a, state_b;
2456
gtk_tree_model_get (model, iter_a,
2458
COL_CONTACT, &contact_a,
2459
COL_IS_SEPARATOR, &is_separator_a,
2461
gtk_tree_model_get (model, iter_b,
2463
COL_CONTACT, &contact_b,
2464
COL_IS_SEPARATOR, &is_separator_b,
2467
/* Separator or group? */
2468
if (is_separator_a || is_separator_b) {
2469
if (is_separator_a) {
2471
} else if (is_separator_b) {
2474
} else if (!contact_a && contact_b) {
2476
} else if (contact_a && !contact_b) {
2478
} else if (!contact_a && !contact_b) {
2480
ret_val = g_utf8_collate (name_a, name_b);
2487
/* If we managed to get this far, we can start looking at
2490
presence_a = gossip_contact_get_active_presence (GOSSIP_CONTACT (contact_a));
2491
presence_b = gossip_contact_get_active_presence (GOSSIP_CONTACT (contact_b));
2493
if (!presence_a && presence_b) {
2495
} else if (presence_a && !presence_b) {
2497
} else if (!presence_a && !presence_b) {
2498
/* Both offline, sort by name */
2499
ret_val = g_utf8_collate (name_a, name_b);
2501
state_a = gossip_presence_get_state (presence_a);
2502
state_b = gossip_presence_get_state (presence_b);
2504
if (state_a < state_b) {
2506
} else if (state_a > state_b) {
2509
/* Fallback: compare by name */
2510
ret_val = g_utf8_collate (name_a, name_b);
2519
g_object_unref (contact_a);
2523
g_object_unref (contact_b);
2530
contact_list_name_sort_func (GtkTreeModel *model,
2531
GtkTreeIter *iter_a,
2532
GtkTreeIter *iter_b,
2309
2535
gchar *name_a, *name_b;
2310
2536
GossipContact *contact_a, *contact_b;
2352
2578
return ret_val;
2582
contact_list_filter_show_contact (GossipContact *contact,
2583
const gchar *filter)
2588
/* Check contact id */
2589
str = g_utf8_casefold (gossip_contact_get_id (contact), -1);
2590
visible = G_STR_EMPTY (str) || strstr (str, filter);
2597
/* Check contact name */
2598
str = g_utf8_casefold (gossip_contact_get_name (contact), -1);
2599
visible = G_STR_EMPTY (str) || strstr (str, filter);
2606
contact_list_filter_show_group (GossipContactList *list,
2608
const gchar *filter)
2610
GossipContactListPriv *priv;
2611
const GList *contacts;
2614
gboolean show_group = FALSE;
2616
priv = GET_PRIV (list);
2618
str = g_utf8_casefold (group, -1);
2623
/* If the filter is the partially the group name, we show the
2626
if (strstr (str, filter)) {
2631
/* At this point, we need to check in advance if this
2632
* group should be shown because a contact we want to
2633
* show exists in it.
2635
contacts = gossip_session_get_contacts (priv->session);
2636
for (l = contacts; l && !show_group; l = l->next) {
2637
if (!gossip_contact_is_in_group (l->data, group)) {
2641
if (contact_list_filter_show_contact (l->data, filter)) {
2652
contact_list_filter_func (GtkTreeModel *model,
2654
GossipContactList *list)
2656
GossipContactListPriv *priv;
2658
gboolean is_separator;
2659
gboolean visible = TRUE;
2661
priv = GET_PRIV (list);
2663
if (G_STR_EMPTY (priv->filter_text)) {
2667
/* Check to see if iter matches any group names */
2668
gtk_tree_model_get (model, iter,
2669
COL_IS_GROUP, &is_group,
2670
COL_IS_SEPARATOR, &is_separator,
2676
gtk_tree_model_get (model, iter, COL_NAME, &name, -1);
2677
visible &= contact_list_filter_show_group (list,
2681
} else if (is_separator) {
2682
/* Do nothing here */
2684
GossipContact *contact;
2686
/* Check contact id */
2687
gtk_tree_model_get (model, iter, COL_CONTACT, &contact, -1);
2688
visible &= contact_list_filter_show_contact (contact,
2690
g_object_unref (contact);
2355
2696
static gboolean
2356
2697
contact_list_iter_equal_contact (GtkTreeModel *model,
2357
2698
GtkTreeIter *iter,
2719
contact_list_find_contact_foreach (GtkTreeModel *model,
2724
if (contact_list_iter_equal_contact (model, iter, fc->contact)) {
2726
fc->iters = g_list_append (fc->iters, gtk_tree_iter_copy (iter));
2729
/* We want to find ALL contacts that match, this means if we
2730
* have the same contact in 3 groups, all iters should be
2378
2737
contact_list_find_contact (GossipContactList *list,
2379
2738
GossipContact *contact)
2381
GtkTreeModel *model;
2740
GossipContactListPriv *priv;
2741
GtkTreeModel *model;
2745
priv = GET_PRIV (list);
2385
2747
memset (&fc, 0, sizeof (fc));
2387
2749
fc.contact = contact;
2389
model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
2751
model = GTK_TREE_MODEL (priv->store);
2390
2752
gtk_tree_model_foreach (model,
2391
2753
(GtkTreeModelForeachFunc) contact_list_find_contact_foreach,
2402
contact_list_find_contact_foreach (GtkTreeModel *model,
2407
if (contact_list_iter_equal_contact (model, iter, fc->contact)) {
2409
fc->iters = g_list_append (fc->iters, gtk_tree_iter_copy (iter));
2412
/* We want to find ALL contacts that match, this means if we
2413
* have the same contact in 3 groups, all iters should be
2420
2764
contact_list_action_cb (GtkAction *action,
2421
2765
GossipContactList *list)
2514
2870
GossipContact *contact)
2516
2872
GossipContactListPriv *priv;
2518
2874
gint event_id = 0;
2520
2876
priv = GET_PRIV (list);
2522
data = g_hash_table_lookup (priv->flash_table, contact);
2524
event_id = data->event_id;
2878
event = g_hash_table_lookup (priv->flash_table, contact);
2880
event_id = gossip_event_get_id (event);
2527
2883
g_signal_emit (list, signals[CONTACT_ACTIVATED], 0, contact, event_id);
2698
contact_list_free_flash_timeout_data (FlashTimeoutData *timeout_data)
2700
g_return_if_fail (timeout_data != NULL);
2702
gossip_debug (DEBUG_DOMAIN,
2703
"Contact:'%s' Cleaning up event flash data",
2704
gossip_contact_get_name (timeout_data->contact));
2706
g_object_unref (timeout_data->contact);
2708
g_slice_free (FlashTimeoutData, timeout_data);
2712
contact_list_flash_free_data (FlashData *data)
2714
g_return_if_fail (data != NULL);
2716
if (data->flash_timeout_id) {
2717
g_source_remove (data->flash_timeout_id);
2720
g_slice_free (FlashData, data);
3054
contact_list_foreach_contact_flash (GossipContact *contact,
3056
GossipContactList *list)
3058
GossipContactListPriv *priv;
3060
GtkTreeModel *model;
3061
GdkPixbuf *pixbuf = NULL;
3062
const gchar *stock_id = NULL;
3064
priv = GET_PRIV (list);
3066
iters = contact_list_find_contact (list, contact);
3068
gossip_debug (DEBUG_DOMAIN,
3069
"Contact:'%s' not found in treeview?",
3070
gossip_contact_get_name (contact));
3075
if (priv->flash_on) {
3076
stock_id = gossip_event_get_stock_id (event);
3080
pixbuf = gossip_stock_create_pixbuf (gossip_app_get_window (),
3082
GTK_ICON_SIZE_MENU);
3084
pixbuf = gossip_pixbuf_for_contact (contact);
3087
model = GTK_TREE_MODEL (priv->store);
3089
for (l = iters; l; l = l->next) {
3090
gtk_tree_store_set (priv->store, l->data,
3091
COL_PIXBUF_STATUS, pixbuf,
3095
g_object_unref (pixbuf);
3097
g_list_foreach (iters, (GFunc) gtk_tree_iter_free, NULL);
3098
g_list_free (iters);
2723
3102
static gboolean
2724
contact_list_flash_timeout_func (FlashTimeoutData *timeout_data)
3103
contact_list_flash (FlashTimeoutData *timeout_data)
2726
3105
GossipContactList *list;
2727
3106
GossipContactListPriv *priv;
2755
3134
if (data->flash_on) {
2756
switch (data->event_type) {
2757
case GOSSIP_EVENT_NEW_MESSAGE:
2758
case GOSSIP_EVENT_SERVER_MESSAGE:
2759
stock_id = GOSSIP_STOCK_MESSAGE;
2761
case GOSSIP_EVENT_FILE_TRANSFER_REQUEST:
2762
case GOSSIP_EVENT_SUBSCRIPTION_REQUEST:
2763
stock_id = GTK_STOCK_DIALOG_QUESTION;
2766
/* Shouldn't happen */
2767
stock_id = GTK_STOCK_DIALOG_WARNING;
3135
stock_id = gossip_event_get_stock_id (data->event);
2772
3138
gossip_debug (DEBUG_DOMAIN,
2780
3146
pixbuf = gossip_pixbuf_for_contact (contact);
2783
model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
3149
model = GTK_TREE_MODEL (priv->store);
2785
3151
for (l = iters; l; l = l->next) {
2786
gtk_tree_store_set (GTK_TREE_STORE (model), l->data,
3152
gtk_tree_store_set (priv->store, l->data,
2787
3153
COL_PIXBUF_STATUS, pixbuf,
2794
3160
g_list_free (iters);
3168
contact_list_flash_heartbeat_func (GossipHeartbeat *heartbeat,
3171
GossipContactListPriv *priv;
3173
priv = GET_PRIV (user_data);
3175
priv->flash_on = !priv->flash_on;
3177
g_hash_table_foreach (priv->flash_table,
3178
(GHFunc) contact_list_foreach_contact_flash,
3179
GOSSIP_CONTACT_LIST (user_data));
2802
3187
GossipContactList *list)
2804
3189
GossipContactListPriv *priv;
2805
GossipMessage *message;
2807
3190
GossipContact *contact;
2808
GossipEventType type;
2810
FlashTimeoutData *timeout_data;
2812
3192
priv = GET_PRIV (list);
2814
type = gossip_event_get_type (event);
2817
case GOSSIP_EVENT_NEW_MESSAGE:
2818
message = GOSSIP_MESSAGE (gossip_event_get_data (event));
2819
contact = gossip_message_get_sender (message);
2822
case GOSSIP_EVENT_SUBSCRIPTION_REQUEST:
2823
contact = GOSSIP_CONTACT (gossip_event_get_data (event));
2826
case GOSSIP_EVENT_FILE_TRANSFER_REQUEST:
2827
ft = GOSSIP_FT (gossip_event_get_data (event));
2828
contact = gossip_ft_get_contact (ft);
3194
contact = gossip_event_get_contact (event);
2833
3196
gossip_debug (DEBUG_DOMAIN,
2834
"Event type not added to the flashing event table",
3197
"Event type not added to the flashing event table");
2839
data = g_hash_table_lookup (priv->flash_table, contact);
3201
if (g_hash_table_lookup (priv->flash_table, contact)) {
2841
3202
/* Already flashing this item. */
2842
3203
gossip_debug (DEBUG_DOMAIN,
2843
3204
"Event already flashing for contact:'%s'",
2848
timeout_data = g_slice_new0 (FlashTimeoutData);
2850
timeout_data->list = list;
2851
timeout_data->contact = g_object_ref (contact);
2853
data = g_slice_new0 (FlashData);
2855
data->event_id = gossip_event_get_id (event);
2856
data->event_type = type;
2858
data->flash_on = TRUE;
2859
data->flash_timeout_id =
2860
g_timeout_add_full (G_PRIORITY_DEFAULT, FLASH_TIMEOUT,
2861
(GSourceFunc) contact_list_flash_timeout_func,
2863
(GDestroyNotify) contact_list_free_flash_timeout_data);
2865
g_hash_table_insert (priv->flash_table, g_object_ref (contact), data);
3209
g_hash_table_insert (priv->flash_table,
3210
g_object_ref (contact),
3211
g_object_ref (event));
3213
contact_list_ensure_flash_heartbeat (list);
2867
3215
gossip_debug (DEBUG_DOMAIN,
2868
3216
"Contact:'%s' added to the flashing event table",
2881
3229
GossipContactList *list)
2883
3231
GossipContactListPriv *priv;
2884
GossipMessage *message;
2886
3232
GossipContact *contact;
2887
GossipEventType type;
2890
3234
priv = GET_PRIV (list);
2892
type = gossip_event_get_type (event);
2895
case GOSSIP_EVENT_NEW_MESSAGE:
2896
message = GOSSIP_MESSAGE (gossip_event_get_data (event));
2897
contact = gossip_message_get_sender (message);
2900
case GOSSIP_EVENT_SUBSCRIPTION_REQUEST:
2901
contact = GOSSIP_CONTACT (gossip_event_get_data (event));
2904
case GOSSIP_EVENT_FILE_TRANSFER_REQUEST:
2905
ft = GOSSIP_FT (gossip_event_get_data (event));
2906
contact = gossip_ft_get_contact (ft);
3236
contact = gossip_event_get_contact (event);
3238
/* Only events with contacts is added to the list */
2914
data = g_hash_table_lookup (priv->flash_table, contact);
3243
if (!g_hash_table_lookup (priv->flash_table, contact)) {
2916
3244
/* Not flashing this contact. */
2920
3248
g_hash_table_remove (priv->flash_table, contact);
3250
contact_list_flash_heartbeat_maybe_stop (list);
2922
3252
gossip_debug (DEBUG_DOMAIN,
2923
3253
"Contact:'%s' removed from flashing event table",
3322
contact_list_ensure_flash_heartbeat (GossipContactList *list)
3324
GossipContactListPriv *priv;
3326
priv = GET_PRIV (list);
3328
if (priv->flash_heartbeat_id) {
3332
priv->flash_heartbeat_id =
3333
gossip_heartbeat_callback_add (gossip_app_get_flash_heartbeat (),
3334
contact_list_flash_heartbeat_func,
3339
contact_list_flash_heartbeat_maybe_stop (GossipContactList *list)
3341
GossipContactListPriv *priv;
3343
priv = GET_PRIV (list);
3345
if (priv->flash_heartbeat_id == 0) {
3349
if (g_hash_table_size (priv->flash_table) > 0) {
3353
gossip_heartbeat_callback_remove (gossip_app_get_flash_heartbeat (),
3354
priv->flash_heartbeat_id);
3355
priv->flash_heartbeat_id = 0;
2992
3358
GossipContactList *
2993
3359
gossip_contact_list_new (void)
3062
3429
return priv->show_offline;
3434
gossip_contact_list_get_show_avatars (GossipContactList *list)
3436
GossipContactListPriv *priv;
3438
g_return_val_if_fail (GOSSIP_IS_CONTACT_LIST (list), TRUE);
3440
priv = GET_PRIV (list);
3442
return priv->show_avatars;
3446
gossip_contact_list_get_is_compact (GossipContactList *list)
3448
GossipContactListPriv *priv;
3450
g_return_val_if_fail (GOSSIP_IS_CONTACT_LIST (list), TRUE);
3452
priv = GET_PRIV (list);
3454
return priv->is_compact;
3457
GossipContactListSort
3458
gossip_contact_list_get_sort_criterium (GossipContactList *list)
3460
GossipContactListPriv *priv;
3462
g_return_val_if_fail (GOSSIP_IS_CONTACT_LIST (list), 0);
3464
priv = GET_PRIV (list);
3466
return priv->sort_criterium;
3066
3470
gossip_contact_list_set_show_offline (GossipContactList *list,
3067
3471
gboolean show_offline)
3084
3488
contacts = gossip_session_get_contacts (priv->session);
3085
3489
for (l = contacts; l; l = l->next) {
3086
GossipContact *contact;
3088
contact = GOSSIP_CONTACT (l->data);
3090
contact_list_contact_update (list, contact);
3490
contact_list_contact_update (list, l->data);
3093
3493
/* Restore to original setting. */
3094
3494
priv->show_active = show_active;
3098
gossip_contact_list_get_show_avatars (GossipContactList *list)
3100
GossipContactListPriv *priv;
3102
g_return_val_if_fail (GOSSIP_IS_CONTACT_LIST (list), TRUE);
3104
priv = GET_PRIV (list);
3106
return priv->show_avatars;
3110
3498
gossip_contact_list_set_show_avatars (GossipContactList *list,
3111
3499
gboolean show_avatars)
3540
gossip_contact_list_set_sort_criterium (GossipContactList *list,
3541
GossipContactListSort sort_criterium)
3543
GossipContactListPriv *priv;
3545
g_return_if_fail (GOSSIP_IS_CONTACT_LIST (list));
3547
priv = GET_PRIV (list);
3549
priv->sort_criterium = sort_criterium;
3551
switch (sort_criterium) {
3552
case GOSSIP_CONTACT_LIST_SORT_STATE:
3553
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
3555
GTK_SORT_ASCENDING);
3558
case GOSSIP_CONTACT_LIST_SORT_NAME:
3559
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
3561
GTK_SORT_ASCENDING);
3567
gossip_contact_list_set_filter (GossipContactList *list,
3568
const gchar *filter)
3570
GossipContactListPriv *priv;
3572
g_return_if_fail (GOSSIP_IS_CONTACT_LIST (list));
3574
priv = GET_PRIV (list);
3576
g_free (priv->filter_text);
3578
priv->filter_text = g_utf8_casefold (filter, -1);
3580
priv->filter_text = NULL;
3583
gossip_debug (DEBUG_DOMAIN, "Refiltering with filter:'%s' (case folded)", filter);
3584
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));