aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/empathy-conf.h1
-rw-r--r--libempathy-gtk/empathy-contact-dialogs.c3
-rw-r--r--libempathy-gtk/empathy-contact-list-store.c220
-rw-r--r--libempathy-gtk/empathy-contact-list-store.h9
-rw-r--r--libempathy-gtk/empathy-contact-list-view.c129
-rw-r--r--libempathy-gtk/empathy-contact-list-view.h3
-rw-r--r--libempathy-gtk/empathy-contact-menu.c49
-rw-r--r--libempathy-gtk/empathy-contact-menu.h1
-rw-r--r--libempathy-gtk/empathy-contact-selector-dialog.c76
-rw-r--r--libempathy-gtk/empathy-contact-selector-dialog.h7
-rw-r--r--libempathy-gtk/empathy-contact-widget.c86
-rw-r--r--libempathy-gtk/empathy-contact-widget.h1
-rw-r--r--libempathy-gtk/empathy-string-parser.c8
-rw-r--r--libempathy-gtk/empathy-ui-utils.c22
-rw-r--r--libempathy-gtk/empathy-ui-utils.h3
15 files changed, 529 insertions, 89 deletions
diff --git a/libempathy-gtk/empathy-conf.h b/libempathy-gtk/empathy-conf.h
index 2a74c1da5..21e3b3810 100644
--- a/libempathy-gtk/empathy-conf.h
+++ b/libempathy-gtk/empathy-conf.h
@@ -82,6 +82,7 @@ struct _EmpathyConfClass {
#define EMPATHY_PREFS_USE_CONN EMPATHY_PREFS_PATH "/use_conn"
#define EMPATHY_PREFS_AUTOCONNECT EMPATHY_PREFS_PATH "/autoconnect"
#define EMPATHY_PREFS_IMPORT_ASKED EMPATHY_PREFS_PATH "/import_asked"
+#define EMPATHY_PREFS_BUTTERFLY_LOGS_MIGRATED EMPATHY_PREFS_PATH "/butterfly_logs_migrated"
#define EMPATHY_PREFS_FILE_TRANSFER_DEFAULT_FOLDER EMPATHY_PREFS_PATH "/file_transfer/default_folder"
#define EMPATHY_PREFS_LOCATION_PUBLISH EMPATHY_PREFS_PATH "/location/publish"
#define EMPATHY_PREFS_LOCATION_RESOURCE_NETWORK EMPATHY_PREFS_PATH "/location/resource_network"
diff --git a/libempathy-gtk/empathy-contact-dialogs.c b/libempathy-gtk/empathy-contact-dialogs.c
index 52e43e163..fed8d04cb 100644
--- a/libempathy-gtk/empathy-contact-dialogs.c
+++ b/libempathy-gtk/empathy-contact-dialogs.c
@@ -261,7 +261,8 @@ empathy_contact_edit_dialog_show (EmpathyContact *contact,
/* Contact info widget */
contact_widget = empathy_contact_widget_new (contact,
EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
- EMPATHY_CONTACT_WIDGET_EDIT_GROUPS);
+ EMPATHY_CONTACT_WIDGET_EDIT_GROUPS |
+ EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE);
gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
contact_widget,
diff --git a/libempathy-gtk/empathy-contact-list-store.c b/libempathy-gtk/empathy-contact-list-store.c
index 53a0934b3..9feb4461f 100644
--- a/libempathy-gtk/empathy-contact-list-store.c
+++ b/libempathy-gtk/empathy-contact-list-store.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <glib.h>
+#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <telepathy-glib/util.h>
@@ -105,6 +106,10 @@ static void contact_list_store_members_changed_cb (EmpathyCon
gchar *message,
gboolean is_member,
EmpathyContactListStore *store);
+static void contact_list_store_favourites_changed_cb (EmpathyContactList *list_iface,
+ EmpathyContact *contact,
+ gboolean is_favourite,
+ EmpathyContactListStore *store);
static void contact_list_store_member_renamed_cb (EmpathyContactList *list_iface,
EmpathyContact *old_contact,
EmpathyContact *new_contact,
@@ -142,7 +147,8 @@ static void contact_list_store_get_group (EmpathyCon
const gchar *name,
GtkTreeIter *iter_group_to_set,
GtkTreeIter *iter_separator_to_set,
- gboolean *created);
+ gboolean *created,
+ gboolean is_fake_group);
static gint contact_list_store_state_sort_func (GtkTreeModel *model,
GtkTreeIter *iter_a,
GtkTreeIter *iter_b,
@@ -192,6 +198,10 @@ contact_list_store_iface_setup (gpointer user_data)
G_CALLBACK (contact_list_store_members_changed_cb),
store);
g_signal_connect (priv->list,
+ "favourites-changed",
+ G_CALLBACK (contact_list_store_favourites_changed_cb),
+ store);
+ g_signal_connect (priv->list,
"groups-changed",
G_CALLBACK (contact_list_store_groups_changed_cb),
store);
@@ -338,6 +348,9 @@ contact_list_store_dispose (GObject *object)
G_CALLBACK (contact_list_store_members_changed_cb),
object);
g_signal_handlers_disconnect_by_func (priv->list,
+ G_CALLBACK (contact_list_store_favourites_changed_cb),
+ object);
+ g_signal_handlers_disconnect_by_func (priv->list,
G_CALLBACK (contact_list_store_groups_changed_cb),
object);
g_object_unref (priv->list);
@@ -715,11 +728,13 @@ empathy_contact_list_store_row_separator_func (GtkTreeModel *model,
gchar *
empathy_contact_list_store_get_parent_group (GtkTreeModel *model,
GtkTreePath *path,
- gboolean *path_is_group)
+ gboolean *path_is_group,
+ gboolean *is_fake_group)
{
GtkTreeIter parent_iter, iter;
gchar *name = NULL;
gboolean is_group;
+ gboolean fake;
g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
@@ -749,6 +764,7 @@ empathy_contact_list_store_get_parent_group (GtkTreeModel *model,
gtk_tree_model_get (model, &iter,
EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake,
-1);
if (!is_group) {
g_free (name);
@@ -760,6 +776,9 @@ empathy_contact_list_store_get_parent_group (GtkTreeModel *model,
*path_is_group = TRUE;
}
+ if (is_fake_group != NULL)
+ *is_fake_group = fake;
+
return name;
}
@@ -824,6 +843,7 @@ contact_list_store_setup (EmpathyContactListStore *store)
G_TYPE_BOOLEAN, /* Can make audio calls */
G_TYPE_BOOLEAN, /* Can make video calls */
EMPATHY_TYPE_CONTACT_LIST_FLAGS, /* Flags */
+ G_TYPE_BOOLEAN, /* Is a fake group */
};
priv = GET_PRIV (store);
@@ -917,6 +937,25 @@ contact_list_store_members_changed_cb (EmpathyContactList *list_iface,
}
static void
+contact_list_store_favourites_changed_cb (EmpathyContactList *list_iface,
+ EmpathyContact *contact,
+ gboolean is_favourite,
+ EmpathyContactListStore *store)
+{
+ EmpathyContactListStorePriv *priv;
+
+ priv = GET_PRIV (store);
+
+ DEBUG ("Contact %s (%d) is %s a favourite",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ is_favourite ? "now" : "no longer");
+
+ contact_list_store_remove_contact (store, contact);
+ contact_list_store_add_contact (store, contact);
+}
+
+static void
contact_list_store_member_renamed_cb (EmpathyContactList *list_iface,
EmpathyContact *old_contact,
EmpathyContact *new_contact,
@@ -969,6 +1008,27 @@ contact_list_store_groups_changed_cb (EmpathyContactList *list_iface,
}
static void
+add_contact_to_store (GtkTreeStore *store,
+ GtkTreeIter *iter,
+ EmpathyContact *contact,
+ EmpathyContactListFlags flags)
+{
+ gtk_tree_store_set (store, iter,
+ EMPATHY_CONTACT_LIST_STORE_COL_NAME, empathy_contact_get_name (contact),
+ EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, contact,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, FALSE,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, FALSE,
+ EMPATHY_CONTACT_LIST_STORE_COL_CAN_AUDIO_CALL,
+ empathy_contact_get_capabilities (contact) &
+ EMPATHY_CAPABILITIES_AUDIO,
+ EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
+ empathy_contact_get_capabilities (contact) &
+ EMPATHY_CAPABILITIES_VIDEO,
+ EMPATHY_CONTACT_LIST_STORE_COL_FLAGS, flags,
+ -1);
+}
+
+static void
contact_list_store_add_contact (EmpathyContactListStore *store,
EmpathyContact *contact)
{
@@ -994,8 +1054,18 @@ contact_list_store_add_contact (EmpathyContactListStore *store,
flags = empathy_contact_manager_get_flags_for_connection (
EMPATHY_CONTACT_MANAGER (priv->list), connection);
}
- /* If no groups just add it at the top level. */
if (!groups) {
+#if HAVE_FAVOURITE_CONTACTS
+ GtkTreeIter iter_group;
+
+ contact_list_store_get_group (store, EMPATHY_CONTACT_LIST_STORE_UNGROUPED,
+ &iter_group, NULL, NULL, TRUE);
+
+ gtk_tree_store_insert_after (GTK_TREE_STORE (store), &iter,
+ &iter_group, NULL);
+#else
+ /* FIXME: remove this in 2.31.x */
+ /* If no groups just add it at the top level. */
GtkTreeModel *model = GTK_TREE_MODEL (store);
if (gtk_tree_model_get_iter_first (model, &iter)) do {
@@ -1014,48 +1084,41 @@ contact_list_store_add_contact (EmpathyContactListStore *store,
} while (gtk_tree_model_iter_next (model, &iter));
gtk_tree_store_append (GTK_TREE_STORE (store), &iter, NULL);
- gtk_tree_store_set (GTK_TREE_STORE (store), &iter,
- EMPATHY_CONTACT_LIST_STORE_COL_NAME, empathy_contact_get_name (contact),
- EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, contact,
- EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, FALSE,
- EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, FALSE,
- EMPATHY_CONTACT_LIST_STORE_COL_CAN_AUDIO_CALL,
- empathy_contact_get_capabilities (contact) &
- EMPATHY_CAPABILITIES_AUDIO,
- EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
- empathy_contact_get_capabilities (contact) &
- EMPATHY_CAPABILITIES_VIDEO,
- EMPATHY_CONTACT_LIST_STORE_COL_FLAGS, flags,
- -1);
+#endif
+
+ add_contact_to_store (GTK_TREE_STORE (store), &iter, contact, flags);
}
/* Else add to each group. */
for (l = groups; l; l = l->next) {
GtkTreeIter iter_group;
- contact_list_store_get_group (store, l->data, &iter_group, NULL, NULL);
+ contact_list_store_get_group (store, l->data, &iter_group, NULL, NULL, FALSE);
gtk_tree_store_insert_after (GTK_TREE_STORE (store), &iter,
&iter_group, NULL);
- gtk_tree_store_set (GTK_TREE_STORE (store), &iter,
- EMPATHY_CONTACT_LIST_STORE_COL_NAME, empathy_contact_get_name (contact),
- EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, contact,
- EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, FALSE,
- EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, FALSE,
- EMPATHY_CONTACT_LIST_STORE_COL_CAN_AUDIO_CALL,
- empathy_contact_get_capabilities (contact) &
- EMPATHY_CAPABILITIES_AUDIO,
- EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
- empathy_contact_get_capabilities (contact) &
- EMPATHY_CAPABILITIES_VIDEO,
- EMPATHY_CONTACT_LIST_STORE_COL_FLAGS, flags,
- -1);
+
+ add_contact_to_store (GTK_TREE_STORE (store), &iter, contact, flags);
g_free (l->data);
}
g_list_free (groups);
- contact_list_store_contact_update (store, contact);
+#ifdef HAVE_FAVOURITE_CONTACTS
+ if (empathy_contact_list_is_favourite (priv->list, contact)) {
+ /* Add contact to the fake 'Favorites' group */
+ GtkTreeIter iter_group;
+
+ contact_list_store_get_group (store, EMPATHY_CONTACT_LIST_STORE_FAVORITE,
+ &iter_group, NULL, NULL, TRUE);
+
+ gtk_tree_store_insert_after (GTK_TREE_STORE (store), &iter,
+ &iter_group, NULL);
+ add_contact_to_store (GTK_TREE_STORE (store), &iter, contact, flags);
+ }
+#endif
+
+ contact_list_store_contact_update (store, contact);
}
static void
@@ -1389,7 +1452,8 @@ contact_list_store_get_group (EmpathyContactListStore *store,
const gchar *name,
GtkTreeIter *iter_group_to_set,
GtkTreeIter *iter_separator_to_set,
- gboolean *created)
+ gboolean *created,
+ gboolean is_fake_group)
{
EmpathyContactListStorePriv *priv;
GtkTreeModel *model;
@@ -1420,6 +1484,7 @@ contact_list_store_get_group (EmpathyContactListStore *store,
EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, TRUE,
EMPATHY_CONTACT_LIST_STORE_COL_IS_ACTIVE, FALSE,
EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, FALSE,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, is_fake_group,
-1);
if (iter_group_to_set) {
@@ -1462,44 +1527,77 @@ contact_list_store_get_group (EmpathyContactListStore *store,
}
static gint
+compare_separator_and_groups (gboolean is_separator_a,
+ gboolean is_separator_b,
+ const gchar *name_a,
+ const gchar *name_b,
+ EmpathyContact *contact_a,
+ EmpathyContact *contact_b,
+ gboolean fake_group_a,
+ gboolean fake_group_b)
+{
+ if (is_separator_a || is_separator_b) {
+ /* We have at least one separator */
+ if (is_separator_a) {
+ return -1;
+ } else if (is_separator_b) {
+ return 1;
+ }
+ }
+
+ /* One group and one contact */
+ if (!contact_a && contact_b) {
+ return 1;
+ } else if (contact_a && !contact_b) {
+ return -1;
+ } else if (!contact_a && !contact_b) {
+ /* Two groups. The 'Ungrouped' fake group is display at the bottom of the
+ * contact list and the 'Favorites' at the top. */
+ if (fake_group_a && !tp_strdiff (name_a, EMPATHY_CONTACT_LIST_STORE_UNGROUPED))
+ return 1;
+ else if (fake_group_b && !tp_strdiff (name_b, EMPATHY_CONTACT_LIST_STORE_UNGROUPED))
+ return -1;
+ else if (fake_group_a && !tp_strdiff (name_a, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+ return -1;
+ else if (fake_group_b && !tp_strdiff (name_b, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+ return 1;
+ else
+ return g_utf8_collate (name_a, name_b);
+ }
+
+ /* Two contacts, ordering depends of the sorting policy */
+ return 0;
+}
+
+static gint
contact_list_store_state_sort_func (GtkTreeModel *model,
GtkTreeIter *iter_a,
GtkTreeIter *iter_b,
gpointer user_data)
{
- gint ret_val = 0;
+ gint ret_val;
gchar *name_a, *name_b;
gboolean is_separator_a, is_separator_b;
EmpathyContact *contact_a, *contact_b;
+ gboolean fake_group_a, fake_group_b;
gtk_tree_model_get (model, iter_a,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name_a,
EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact_a,
EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator_a,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake_group_a,
-1);
gtk_tree_model_get (model, iter_b,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name_b,
EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact_b,
EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator_b,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake_group_b,
-1);
- /* Separator or group? */
- if (is_separator_a || is_separator_b) {
- if (is_separator_a) {
- ret_val = -1;
- } else if (is_separator_b) {
- ret_val = 1;
- }
- } else if (!contact_a && contact_b) {
- ret_val = 1;
- } else if (contact_a && !contact_b) {
- ret_val = -1;
- } else if (!contact_a && !contact_b) {
- /* Handle groups */
- ret_val = g_utf8_collate (name_a, name_b);
- }
+ ret_val = compare_separator_and_groups (is_separator_a, is_separator_b,
+ name_a, name_b, contact_a, contact_b, fake_group_a, fake_group_b);
- if (ret_val) {
+ if (ret_val != 0) {
goto free_and_out;
}
@@ -1538,38 +1636,28 @@ contact_list_store_name_sort_func (GtkTreeModel *model,
{
gchar *name_a, *name_b;
EmpathyContact *contact_a, *contact_b;
- gboolean is_separator_a, is_separator_b;
+ gboolean is_separator_a = FALSE, is_separator_b = FALSE;
gint ret_val;
+ gboolean fake_group_a, fake_group_b;
gtk_tree_model_get (model, iter_a,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name_a,
EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact_a,
EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator_a,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake_group_a,
-1);
gtk_tree_model_get (model, iter_b,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name_b,
EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact_b,
EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator_b,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake_group_b,
-1);
- /* If contact is NULL it means it's a group. */
+ ret_val = compare_separator_and_groups (is_separator_a, is_separator_b,
+ name_a, name_b, contact_a, contact_b, fake_group_a, fake_group_b);
- if (is_separator_a || is_separator_b) {
- if (is_separator_a) {
- ret_val = -1;
- } else if (is_separator_b) {
- ret_val = 1;
- }
- } else if (!contact_a && contact_b) {
- ret_val = 1;
- } else if (contact_a && !contact_b) {
- ret_val = -1;
- } else {
+ if (ret_val == 0)
ret_val = g_utf8_collate (name_a, name_b);
- }
-
- g_free (name_a);
- g_free (name_b);
if (contact_a) {
g_object_unref (contact_a);
diff --git a/libempathy-gtk/empathy-contact-list-store.h b/libempathy-gtk/empathy-contact-list-store.h
index afefd28cf..1b36ea651 100644
--- a/libempathy-gtk/empathy-contact-list-store.h
+++ b/libempathy-gtk/empathy-contact-list-store.h
@@ -63,9 +63,13 @@ typedef enum {
EMPATHY_CONTACT_LIST_STORE_COL_CAN_AUDIO_CALL,
EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
EMPATHY_CONTACT_LIST_STORE_COL_FLAGS,
- EMPATHY_CONTACT_LIST_STORE_COL_COUNT
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP,
+ EMPATHY_CONTACT_LIST_STORE_COL_COUNT,
} EmpathyContactListStoreCol;
+#define EMPATHY_CONTACT_LIST_STORE_UNGROUPED _("Ungrouped")
+#define EMPATHY_CONTACT_LIST_STORE_FAVORITE _("Favorite People")
+
struct _EmpathyContactListStore {
GtkTreeStore parent;
gpointer priv;
@@ -101,7 +105,8 @@ gboolean empathy_contact_list_store_row_separator_func (GtkTre
gpointer data);
gchar * empathy_contact_list_store_get_parent_group (GtkTreeModel *model,
GtkTreePath *path,
- gboolean *path_is_group);
+ gboolean *path_is_group,
+ gboolean *is_fake_group);
gboolean empathy_contact_list_store_search_equal_func (GtkTreeModel *model,
gint column,
const gchar *key,
diff --git a/libempathy-gtk/empathy-contact-list-view.c b/libempathy-gtk/empathy-contact-list-view.c
index e8fddf0ac..8e8342275 100644
--- a/libempathy-gtk/empathy-contact-list-view.c
+++ b/libempathy-gtk/empathy-contact-list-view.c
@@ -157,6 +157,11 @@ contact_list_view_query_tooltip_cb (EmpathyContactListView *view,
}
running++;
+ /* Don't show the tooltip if there's already a popup menu */
+ if (gtk_menu_get_for_attach_widget (GTK_WIDGET (view)) != NULL) {
+ goto OUT;
+ }
+
if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (view), &x, &y,
keyboard_mode,
&model, &path, &iter)) {
@@ -235,6 +240,21 @@ contact_list_view_drag_got_contact (EmpathyTpContactFactory *factory,
data->old_group, data->new_group);
list = empathy_contact_list_store_get_list_iface (priv->store);
+
+ if (!tp_strdiff (data->new_group, EMPATHY_CONTACT_LIST_STORE_FAVORITE)) {
+ /* Mark contact as favourite */
+ empathy_contact_list_add_to_favourites (list, contact);
+ return;
+ }
+
+ if (!tp_strdiff (data->old_group, EMPATHY_CONTACT_LIST_STORE_FAVORITE)) {
+ /* Remove contact as favourite */
+ empathy_contact_list_remove_from_favourites (list, contact);
+ /* Don't try to remove it */
+ g_free (data->old_group);
+ data->old_group = NULL;
+ }
+
if (data->new_group) {
empathy_contact_list_add_to_group (list, contact, data->new_group);
}
@@ -244,6 +264,27 @@ contact_list_view_drag_got_contact (EmpathyTpContactFactory *factory,
}
static gboolean
+group_can_be_modified (const gchar *name,
+ gboolean is_fake_group,
+ gboolean adding)
+{
+ /* Real groups can always be modified */
+ if (!is_fake_group)
+ return TRUE;
+
+ /* The favorite fake group can be modified so users can
+ * add/remove favorites using DnD */
+ if (!tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+ return TRUE;
+
+ /* We can remove contacts from the 'ungrouped' fake group */
+ if (!adding && !tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_UNGROUPED))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
contact_list_view_contact_drag_received (GtkWidget *view,
GdkDragContext *context,
GtkTreeModel *model,
@@ -263,23 +304,30 @@ contact_list_view_contact_drag_received (GtkWidget *view,
gchar *new_group = NULL;
gchar *old_group = NULL;
gboolean success = TRUE;
+ gboolean new_group_is_fake, old_group_is_fake = TRUE;
priv = GET_PRIV (view);
sel_data = (const gchar *) gtk_selection_data_get_data (selection);
new_group = empathy_contact_list_store_get_parent_group (model,
- path, NULL);
+ path, NULL, &new_group_is_fake);
+
+ if (!group_can_be_modified (new_group, new_group_is_fake, TRUE))
+ return FALSE;
/* Get source group information. */
if (priv->drag_row) {
source_path = gtk_tree_row_reference_get_path (priv->drag_row);
if (source_path) {
old_group = empathy_contact_list_store_get_parent_group (
- model, source_path, NULL);
+ model, source_path, NULL, &old_group_is_fake);
gtk_tree_path_free (source_path);
}
}
+ if (!group_can_be_modified (old_group, old_group_is_fake, FALSE))
+ return FALSE;
+
if (!tp_strdiff (old_group, new_group)) {
g_free (new_group);
g_free (old_group);
@@ -681,6 +729,10 @@ contact_list_view_popup_menu_idle_cb (gpointer user_data)
}
if (menu) {
+ g_signal_connect (menu, "deactivate",
+ G_CALLBACK (gtk_menu_detach), NULL);
+ gtk_menu_attach_to_widget (GTK_MENU (menu),
+ GTK_WIDGET (data->view), NULL);
gtk_widget_show (menu);
gtk_menu_popup (GTK_MENU (menu),
NULL, NULL, NULL, NULL,
@@ -796,6 +848,10 @@ contact_list_view_call_activated_cb (
gtk_menu_shell_append (shell, item);
gtk_widget_show (item);
+ g_signal_connect (menu, "deactivate",
+ G_CALLBACK (gtk_menu_detach), NULL);
+ gtk_menu_attach_to_widget (GTK_MENU (menu),
+ GTK_WIDGET (view), NULL);
gtk_widget_show (menu);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
event->button, event->time);
@@ -868,6 +924,43 @@ contact_list_view_pixbuf_cell_data_func (GtkTreeViewColumn *tree_column,
}
static void
+contact_list_view_group_icon_cell_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EmpathyContactListView *view)
+{
+ GdkPixbuf *pixbuf = NULL;
+ gboolean is_group;
+ gchar *name;
+
+ gtk_tree_model_get (model, iter,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group,
+ EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name,
+ -1);
+
+ if (!is_group)
+ goto out;
+
+ if (tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+ goto out;
+
+ pixbuf = empathy_pixbuf_from_icon_name ("emblem-favorite",
+ GTK_ICON_SIZE_MENU);
+
+out:
+ g_object_set (cell,
+ "visible", pixbuf != NULL,
+ "pixbuf", pixbuf,
+ NULL);
+
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+
+ g_free (name);
+}
+
+static void
contact_list_view_audio_call_cell_data_func (
GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
@@ -1104,6 +1197,22 @@ contact_list_view_setup (EmpathyContactListView *view)
"visible", FALSE,
NULL);
+ /* Group icon */
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_cell_data_func (
+ col, cell,
+ (GtkTreeCellDataFunc) contact_list_view_group_icon_cell_data_func,
+ view, NULL);
+
+ g_object_set (cell,
+ "xpad", 0,
+ "ypad", 0,
+ "visible", FALSE,
+ "width", 16,
+ "height", 16,
+ NULL);
+
/* Name */
cell = empathy_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (col, cell, TRUE);
@@ -1446,7 +1555,8 @@ empathy_contact_list_view_get_flags (EmpathyContactListView *view)
}
gchar *
-empathy_contact_list_view_get_selected_group (EmpathyContactListView *view)
+empathy_contact_list_view_get_selected_group (EmpathyContactListView *view,
+ gboolean *is_fake_group)
{
EmpathyContactListViewPriv *priv;
GtkTreeSelection *selection;
@@ -1454,6 +1564,7 @@ empathy_contact_list_view_get_selected_group (EmpathyContactListView *view)
GtkTreeModel *model;
gboolean is_group;
gchar *name;
+ gboolean fake;
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
@@ -1467,6 +1578,7 @@ empathy_contact_list_view_get_selected_group (EmpathyContactListView *view)
gtk_tree_model_get (model, &iter,
EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group,
EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name,
+ EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, &fake,
-1);
if (!is_group) {
@@ -1474,6 +1586,9 @@ empathy_contact_list_view_get_selected_group (EmpathyContactListView *view)
return NULL;
}
+ if (is_fake_group != NULL)
+ *is_fake_group = fake;
+
return name;
}
@@ -1510,7 +1625,7 @@ contact_list_view_group_remove_activate_cb (GtkMenuItem *menuitem,
EmpathyContactListViewPriv *priv = GET_PRIV (view);
gchar *group;
- group = empathy_contact_list_view_get_selected_group (view);
+ group = empathy_contact_list_view_get_selected_group (view, NULL);
if (group) {
gchar *text;
GtkWindow *parent;
@@ -1538,6 +1653,7 @@ empathy_contact_list_view_get_group_menu (EmpathyContactListView *view)
GtkWidget *menu;
GtkWidget *item;
GtkWidget *image;
+ gboolean is_fake_group;
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
@@ -1546,8 +1662,9 @@ empathy_contact_list_view_get_group_menu (EmpathyContactListView *view)
return NULL;
}
- group = empathy_contact_list_view_get_selected_group (view);
- if (!group) {
+ group = empathy_contact_list_view_get_selected_group (view, &is_fake_group);
+ if (!group || is_fake_group) {
+ /* We can't alter fake groups */
return NULL;
}
diff --git a/libempathy-gtk/empathy-contact-list-view.h b/libempathy-gtk/empathy-contact-list-view.h
index 17de5239b..41b968dbf 100644
--- a/libempathy-gtk/empathy-contact-list-view.h
+++ b/libempathy-gtk/empathy-contact-list-view.h
@@ -73,7 +73,8 @@ EmpathyContactListView * empathy_contact_list_view_new (Empathy
EmpathyContactFeatureFlags contact_features);
EmpathyContact * empathy_contact_list_view_dup_selected (EmpathyContactListView *view);
EmpathyContactListFlags empathy_contact_list_view_get_flags (EmpathyContactListView *view);
-gchar * empathy_contact_list_view_get_selected_group (EmpathyContactListView *view);
+gchar * empathy_contact_list_view_get_selected_group (EmpathyContactListView *view,
+ gboolean *is_fake_group);
GtkWidget * empathy_contact_list_view_get_contact_menu (EmpathyContactListView *view);
GtkWidget * empathy_contact_list_view_get_group_menu (EmpathyContactListView *view);
diff --git a/libempathy-gtk/empathy-contact-menu.c b/libempathy-gtk/empathy-contact-menu.c
index 54bb4b286..23522d40e 100644
--- a/libempathy-gtk/empathy-contact-menu.c
+++ b/libempathy-gtk/empathy-contact-menu.c
@@ -134,6 +134,13 @@ empathy_contact_menu_new (EmpathyContact *contact,
gtk_widget_show (item);
}
+#if HAVE_FAVOURITE_CONTACTS
+ /* Favorite checkbox */
+ item = empathy_contact_favourite_menu_item_new (contact);
+ gtk_menu_shell_append (shell, item);
+ gtk_widget_show (item);
+#endif
+
return menu;
}
@@ -396,6 +403,48 @@ empathy_contact_share_my_desktop_menu_item_new (EmpathyContact *contact)
return item;
}
+#if HAVE_FAVOURITE_CONTACTS
+static void
+favourite_menu_item_toggled_cb (GtkCheckMenuItem *item,
+ EmpathyContact *contact)
+{
+ EmpathyContactManager *manager;
+ EmpathyContactList *list;
+
+ manager = empathy_contact_manager_dup_singleton ();
+ list = EMPATHY_CONTACT_LIST (manager);
+
+ if (gtk_check_menu_item_get_active (item)) {
+ empathy_contact_list_add_to_favourites (list, contact);
+ } else {
+ empathy_contact_list_remove_from_favourites (list, contact);
+ }
+
+ g_object_unref (manager);
+}
+
+GtkWidget *
+empathy_contact_favourite_menu_item_new (EmpathyContact *contact)
+{
+ GtkWidget *item;
+ EmpathyContactManager *manager;
+
+ item = gtk_check_menu_item_new_with_label (_("Favorite"));
+
+ manager = empathy_contact_manager_dup_singleton ();
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
+ empathy_contact_list_is_favourite (EMPATHY_CONTACT_LIST (manager),
+ contact));
+
+ g_signal_connect (item, "toggled",
+ G_CALLBACK (favourite_menu_item_toggled_cb),
+ contact);
+
+ g_object_unref (manager);
+ return item;
+}
+#endif
+
static void
contact_info_menu_item_activate_cb (EmpathyContact *contact)
{
diff --git a/libempathy-gtk/empathy-contact-menu.h b/libempathy-gtk/empathy-contact-menu.h
index 2c623e6ba..25f18e03f 100644
--- a/libempathy-gtk/empathy-contact-menu.h
+++ b/libempathy-gtk/empathy-contact-menu.h
@@ -50,6 +50,7 @@ GtkWidget * empathy_contact_edit_menu_item_new (EmpathyContact *cont
GtkWidget * empathy_contact_invite_menu_item_new (EmpathyContact *contact);
GtkWidget * empathy_contact_file_transfer_menu_item_new (EmpathyContact *contact);
GtkWidget * empathy_contact_share_my_desktop_menu_item_new (EmpathyContact *contact);
+GtkWidget * empathy_contact_favourite_menu_item_new (EmpathyContact *contact);
G_END_DECLS
diff --git a/libempathy-gtk/empathy-contact-selector-dialog.c b/libempathy-gtk/empathy-contact-selector-dialog.c
index 3c59061ae..c09b25cef 100644
--- a/libempathy-gtk/empathy-contact-selector-dialog.c
+++ b/libempathy-gtk/empathy-contact-selector-dialog.c
@@ -55,6 +55,7 @@ struct _EmpathyContactSelectorDialogPriv {
GtkWidget *account_chooser;
GtkWidget *entry_id;
EmpathyContactManager *contact_manager;
+ TpAccount *filter_account;
gboolean show_account_chooser;
};
@@ -65,7 +66,8 @@ struct _EmpathyContactSelectorDialogPriv {
enum {
PROP_0,
- PROP_SHOW_ACCOUNT_CHOOSER
+ PROP_SHOW_ACCOUNT_CHOOSER,
+ PROP_FILTER_ACCOUNT
};
enum {
@@ -103,8 +105,25 @@ contact_selector_dialog_account_changed_cb (GtkWidget *widget,
}
else
{
- members = empathy_contact_list_get_members (
- EMPATHY_CONTACT_LIST (priv->contact_manager));
+ if (priv->filter_account != NULL)
+ {
+ EmpathyTpContactList *contact_list;
+
+ connection = tp_account_get_connection (priv->filter_account);
+ if (connection == NULL)
+ return;
+
+ contact_list = empathy_contact_manager_get_list (
+ priv->contact_manager, connection);
+
+ members = empathy_contact_list_get_members (
+ EMPATHY_CONTACT_LIST (contact_list));
+ }
+ else
+ {
+ members = empathy_contact_list_get_members (
+ EMPATHY_CONTACT_LIST (priv->contact_manager));
+ }
}
/* Add members to the completion */
@@ -361,6 +380,11 @@ empathy_contact_selector_dialog_get_property (GObject *self,
empathy_contact_selector_dialog_get_show_account_chooser (dialog));
break;
+ case PROP_FILTER_ACCOUNT:
+ g_value_set_object (value,
+ empathy_contact_selector_dialog_get_filter_account (dialog));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
break;
@@ -382,6 +406,11 @@ empathy_contact_selector_dialog_set_property (GObject *self,
g_value_get_boolean (value));
break;
+ case PROP_FILTER_ACCOUNT:
+ empathy_contact_selector_dialog_set_filter_account (dialog,
+ g_value_get_object (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
break;
@@ -419,6 +448,11 @@ empathy_contact_selector_dialog_dispose (GObject *object)
priv->contact_manager = NULL;
}
+ if (priv->filter_account != NULL) {
+ g_object_unref (priv->filter_account);
+ priv->filter_account = NULL;
+ }
+
if (G_OBJECT_CLASS (empathy_contact_selector_dialog_parent_class)->dispose)
G_OBJECT_CLASS (empathy_contact_selector_dialog_parent_class)->dispose (
object);
@@ -445,6 +479,14 @@ empathy_contact_selector_dialog_class_init (
"Whether or not this dialog should show an account chooser",
TRUE,
G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_FILTER_ACCOUNT,
+ g_param_spec_object ("filter-account",
+ "Account to filter contacts",
+ "if 'show-account-chooser' is unset, only the contacts from this "
+ "account are displayed",
+ TP_TYPE_ACCOUNT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
const gchar *
@@ -502,3 +544,31 @@ empathy_contact_selector_dialog_get_show_account_chooser (
priv = GET_PRIV (self);
return priv->show_account_chooser;
}
+
+void
+empathy_contact_selector_dialog_set_filter_account (
+ EmpathyContactSelectorDialog *self,
+ TpAccount *account)
+{
+ EmpathyContactSelectorDialogPriv *priv;
+
+ g_return_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self));
+
+ priv = GET_PRIV (self);
+ priv->filter_account = g_object_ref (account);
+
+ g_object_notify (G_OBJECT (self), "filter-account");
+}
+
+TpAccount *
+empathy_contact_selector_dialog_get_filter_account (
+ EmpathyContactSelectorDialog *self)
+{
+ EmpathyContactSelectorDialogPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self), NULL);
+
+ priv = GET_PRIV (self);
+ return priv->filter_account;
+
+}
diff --git a/libempathy-gtk/empathy-contact-selector-dialog.h b/libempathy-gtk/empathy-contact-selector-dialog.h
index 87b2812f4..318a9bcac 100644
--- a/libempathy-gtk/empathy-contact-selector-dialog.h
+++ b/libempathy-gtk/empathy-contact-selector-dialog.h
@@ -62,6 +62,13 @@ void empathy_contact_selector_dialog_set_show_account_chooser (
gboolean empathy_contact_selector_dialog_get_show_account_chooser (
EmpathyContactSelectorDialog *self);
+void empathy_contact_selector_dialog_set_filter_account (
+ EmpathyContactSelectorDialog *self,
+ TpAccount *account);
+
+TpAccount * empathy_contact_selector_dialog_get_filter_account (
+ EmpathyContactSelectorDialog *self);
+
/* TYPE MACROS */
#define EMPATHY_TYPE_CONTACT_SELECTOR_DIALOG \
(empathy_contact_selector_dialog_get_type ())
diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c
index 696a8cda4..82a5ac703 100644
--- a/libempathy-gtk/empathy-contact-widget.c
+++ b/libempathy-gtk/empathy-contact-widget.c
@@ -82,6 +82,7 @@ typedef struct
EmpathyContact *contact;
EmpathyContactWidgetFlags flags;
guint widget_id_timeout;
+ gulong fav_sig_id;
GtkWidget *vbox_contact_widget;
@@ -100,6 +101,7 @@ typedef struct
GtkWidget *label_status;
GtkWidget *table_contact;
GtkWidget *vbox_avatar;
+ GtkWidget *favourite_checkbox;
/* Location */
GtkWidget *vbox_location;
@@ -448,7 +450,6 @@ contact_widget_groups_setup (EmpathyContactWidget *information)
{
if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS)
{
- information->manager = empathy_contact_manager_dup_singleton ();
contact_widget_model_setup (information);
}
}
@@ -964,6 +965,21 @@ contact_widget_presence_notify_cb (EmpathyContactWidget *information)
gtk_widget_show (information->image_state);
}
+#if HAVE_FAVOURITE_CONTACTS
+static void
+contact_widget_favourites_changed_cb (EmpathyContactManager *manager,
+ EmpathyContact *contact,
+ gboolean is_favourite,
+ EmpathyContactWidget *information)
+{
+ if (contact != information->contact)
+ return;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (
+ information->favourite_checkbox), is_favourite);
+}
+#endif
+
static void
contact_widget_remove_contact (EmpathyContactWidget *information)
{
@@ -1052,6 +1068,20 @@ contact_widget_contact_update (EmpathyContactWidget *information)
contact_widget_presence_notify_cb (information);
contact_widget_avatar_notify_cb (information);
+#if HAVE_FAVOURITE_CONTACTS
+ if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE)
+ {
+ gboolean is_favourite;
+
+ is_favourite = empathy_contact_list_is_favourite (
+ EMPATHY_CONTACT_LIST (information->manager),
+ information->contact);
+
+ contact_widget_favourites_changed_cb (information->manager,
+ information->contact, is_favourite, information);
+ }
+#endif
+
gtk_widget_show (information->label_alias);
gtk_widget_show (information->widget_alias);
gtk_widget_show (information->hbox_presence);
@@ -1181,6 +1211,28 @@ contact_widget_id_focus_out_cb (GtkWidget *widget,
return FALSE;
}
+#if HAVE_FAVOURITE_CONTACTS
+static void
+favourite_toggled_cb (GtkToggleButton *button,
+ EmpathyContactWidget *information)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (button);
+
+ if (active)
+ {
+ empathy_contact_list_add_to_favourites (
+ EMPATHY_CONTACT_LIST (information->manager), information->contact);
+ }
+ else
+ {
+ empathy_contact_list_remove_from_favourites (
+ EMPATHY_CONTACT_LIST (information->manager), information->contact);
+ }
+}
+#endif
+
static void
contact_widget_contact_setup (EmpathyContactWidget *information)
{
@@ -1318,6 +1370,27 @@ contact_widget_contact_setup (EmpathyContactWidget *information)
gtk_label_set_selectable (GTK_LABEL (information->label_status), FALSE);
}
gtk_widget_show (information->widget_alias);
+
+#if HAVE_FAVOURITE_CONTACTS
+ /* Favorite */
+ if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE)
+ {
+ information->favourite_checkbox = gtk_check_button_new_with_label (
+ _("Favorite"));
+
+ g_signal_connect (information->favourite_checkbox, "toggled",
+ G_CALLBACK (favourite_toggled_cb), information);
+
+ gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
+ information->favourite_checkbox, 0, 2, 3, 4);
+
+ information->fav_sig_id = g_signal_connect (information->manager,
+ "favourites-changed",
+ G_CALLBACK (contact_widget_favourites_changed_cb), information);
+
+ gtk_widget_show (information->favourite_checkbox);
+ }
+#endif
}
static void
@@ -1330,10 +1403,11 @@ contact_widget_destroy_cb (GtkWidget *widget,
{
g_source_remove (information->widget_id_timeout);
}
- if (information->manager)
- {
- g_object_unref (information->manager);
- }
+
+ if (information->fav_sig_id != 0)
+ g_signal_handler_disconnect (information->manager, information->fav_sig_id);
+
+ g_object_unref (information->manager);
g_slice_free (EmpathyContactWidget, information);
}
@@ -1401,6 +1475,8 @@ empathy_contact_widget_new (EmpathyContact *contact,
"EmpathyContactWidget",
information);
+ information->manager = empathy_contact_manager_dup_singleton ();
+
/* Create widgets */
contact_widget_contact_setup (information);
contact_widget_groups_setup (information);
diff --git a/libempathy-gtk/empathy-contact-widget.h b/libempathy-gtk/empathy-contact-widget.h
index 04b567f4d..af669477e 100644
--- a/libempathy-gtk/empathy-contact-widget.h
+++ b/libempathy-gtk/empathy-contact-widget.h
@@ -61,6 +61,7 @@ typedef enum
EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP = 1 << 5,
EMPATHY_CONTACT_WIDGET_SHOW_LOCATION = 1 << 6,
EMPATHY_CONTACT_WIDGET_NO_SET_ALIAS = 1 << 7,
+ EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE = 1 << 8,
} EmpathyContactWidgetFlags;
GtkWidget * empathy_contact_widget_new (EmpathyContact *contact,
diff --git a/libempathy-gtk/empathy-string-parser.c b/libempathy-gtk/empathy-string-parser.c
index 5c3fb1972..a661cd477 100644
--- a/libempathy-gtk/empathy-string-parser.c
+++ b/libempathy-gtk/empathy-string-parser.c
@@ -203,6 +203,14 @@ empathy_add_link_markup (const gchar *text)
g_return_val_if_fail (text != NULL, NULL);
+ /* GtkLabel with links could make infinite loop because of
+ * GNOME bug #612066. It is fixed in GTK >= 2.18.8 and GTK >= 2.19.7.
+ * FIXME: Remove this check once we have an hard dep on GTK 2.20 */
+ if (gtk_check_version (2, 18, 8) != NULL ||
+ (gtk_minor_version == 19 && gtk_micro_version < 7)) {
+ return g_markup_escape_text (text, -1);
+ }
+
string = g_string_sized_new (strlen (text));
empathy_string_parser_substr (text, -1, parsers, string);
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 807b6afaf..4503a39cc 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -1385,10 +1385,10 @@ empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon)
/* Takes care of moving the window to the current workspace. */
void
-empathy_window_present (GtkWindow *window,
- gboolean steal_focus)
+empathy_window_present (GtkWindow *window)
{
GdkWindow *gdk_window;
+ guint32 timestamp;
g_return_if_fail (GTK_IS_WINDOW (window));
@@ -1410,7 +1410,12 @@ empathy_window_present (GtkWindow *window,
gtk_widget_hide (GTK_WIDGET (window));
}
- gtk_window_present_with_time (window, G_MAXINT32);
+ timestamp = gtk_get_current_event_time ();
+ if (timestamp == 0)
+ /* No event, fallback to _NET_WM_USER_TIME */
+ timestamp = gdk_x11_display_get_user_time (gdk_display_get_default ());
+
+ gtk_window_present_with_time (window, timestamp);
gtk_window_set_skip_taskbar_hint (window, FALSE);
gtk_window_deiconify (window);
}
@@ -1631,6 +1636,9 @@ empathy_send_file_with_file_chooser (EmpathyContact *contact)
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), FALSE);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget),
+ g_get_home_dir ());
+
g_signal_connect (widget, "response",
G_CALLBACK (file_manager_send_file_response_cb),
contact);
@@ -1669,6 +1677,7 @@ void
empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
{
GtkWidget *widget;
+ const gchar *dir;
widget = gtk_file_chooser_dialog_new (_("Select a destination"),
NULL,
@@ -1683,6 +1692,13 @@ empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
gtk_file_chooser_set_do_overwrite_confirmation
(GTK_FILE_CHOOSER (widget), TRUE);
+ dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD);
+ if (dir == NULL)
+ /* Fallback to $HOME if $XDG_DOWNLOAD_DIR is not set */
+ dir = g_get_home_dir ();
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), dir);
+
g_signal_connect (widget, "response",
G_CALLBACK (file_manager_receive_file_response_cb), handler);
diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h
index 38732c7f9..8834cb4c9 100644
--- a/libempathy-gtk/empathy-ui-utils.h
+++ b/libempathy-gtk/empathy-ui-utils.h
@@ -104,8 +104,7 @@ gboolean empathy_text_iter_backward_search (const GtkTextIter*iter,
const GtkTextIter*limit);
/* Windows */
gboolean empathy_window_get_is_visible (GtkWindow *window);
-void empathy_window_present (GtkWindow *window,
- gboolean steal_focus);
+void empathy_window_present (GtkWindow *window);
void empathy_window_iconify (GtkWindow *window,
GtkStatusIcon *status_icon);
GtkWindow * empathy_get_toplevel_window (GtkWidget *widget);