};
static const GtkTargetEntry drag_types_dest[] = {
+ { "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
{ "text/plain", 0, DND_DRAG_TYPE_STRING },
};
static const GtkTargetEntry drag_types_dest_file[] = {
+ { "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
};
}
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)) {
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);
}
}
}
+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,
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);
}
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,
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);
contact_list_view_cell_set_background (view, cell, is_group, is_active);
}
+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,
"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);
}
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;
GtkTreeModel *model;
gboolean is_group;
gchar *name;
+ gboolean fake;
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
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) {
return NULL;
}
+ if (is_fake_group != NULL)
+ *is_fake_group = fake;
+
return name;
}
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;
GtkWidget *menu;
GtkWidget *item;
GtkWidget *image;
+ gboolean is_fake_group;
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
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;
}
{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
{ "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB },
{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
+ { "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
};
static const GtkTargetEntry drag_types_dest_contact[] = {
};
static const GtkTargetEntry drag_types_dest_file[] = {
+ /* must be first to be prioritized, in order to receive the
+ * note's file path from Tomboy instead of an URI */
+ { "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
};
EmpathyTpChat *tp_chat;
TpChannel *channel;
int response;
+ TpAccount *account;
priv = GET_PRIV (window);
tp_chat = empathy_chat_get_tp_chat (priv->current_chat);
channel = empathy_tp_chat_get_channel (tp_chat);
+ account = empathy_chat_get_account (priv->current_chat);
dialog = empathy_invite_participant_dialog_new (
- GTK_WINDOW (priv->dialog));
+ GTK_WINDOW (priv->dialog), account);
gtk_widget_show (dialog);
response = gtk_dialog_run (GTK_DIALOG (dialog));
int x,
int y,
guint time_,
- gpointer user_data)
+ EmpathyChatWindow *window)
{
- GdkAtom target, uri_target, contact_target;
+ GdkAtom target;
+ EmpathyChatWindowPriv *priv;
- target = gtk_drag_dest_find_target (widget, context, NULL);
- uri_target = gdk_atom_intern_static_string ("text/uri-list");
- contact_target = gdk_atom_intern_static_string ("text/contact-id");
+ priv = GET_PRIV (window);
+
+ target = gtk_drag_dest_find_target (widget, context, priv->file_targets);
+ if (target == GDK_NONE)
+ target = gtk_drag_dest_find_target (widget, context, priv->contact_targets);
- if (target == uri_target || target == contact_target) {
+ if (target != GDK_NONE) {
gtk_drag_get_data (widget, context, target, time_);
return TRUE;
}
{
GdkAtom target;
EmpathyChatWindowPriv *priv;
- GdkAtom dest_target;
priv = GET_PRIV (window);
- target = gtk_drag_dest_find_target (widget, context, NULL);
-
- dest_target = gdk_atom_intern_static_string ("text/uri-list");
- if (target == dest_target) {
+ target = gtk_drag_dest_find_target (widget, context, priv->file_targets);
+ if (target != GDK_NONE) {
/* This is a file drag. Ensure the contact is online and set the
drag type to COPY. Note that it's possible that the tab will
be switched by GTK+ after a timeout from drag_motion without
return TRUE;
}
- dest_target = gdk_atom_intern_static_string ("text/contact-id");
- if (target == dest_target) {
+ target = gtk_drag_dest_find_target (widget, context, priv->contact_targets);
+ if (target != GDK_NONE) {
/* This is a drag of a contact from a contact list. Set to COPY.
FIXME: If this drag is to a MUC window, it invites the user.
Otherwise, it opens a chat. Should we use a different drag
priv = GET_PRIV (window);
empathy_chat_window_switch_to_chat (window, chat);
- empathy_window_present (GTK_WINDOW (priv->dialog), TRUE);
+ empathy_window_present (GTK_WINDOW (priv->dialog));
gtk_widget_grab_focus (chat->input_text_view);
}