#include <libempathy/empathy-tp-contact-factory.h>
#include <libempathy/empathy-contact-list.h>
#include <libempathy/empathy-request-util.h>
+#include <libempathy/empathy-individual-manager.h>
#include <libempathy-gtk/empathy-images.h>
#include <libempathy-gtk/empathy-contact-dialogs.h>
typedef enum {
DND_DRAG_TYPE_CONTACT_ID,
+ DND_DRAG_TYPE_INDIVIDUAL_ID,
DND_DRAG_TYPE_URI_LIST,
DND_DRAG_TYPE_TAB
} DndDragType;
static const GtkTargetEntry drag_types_dest[] = {
{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
+ { "text/x-individual-id", 0, DND_DRAG_TYPE_INDIVIDUAL_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[] = {
{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
+ { "text/x-individual-id", 0, DND_DRAG_TYPE_INDIVIDUAL_ID },
};
static const GtkTargetEntry drag_types_dest_file[] = {
return NULL;
}
+static void
+remove_all_chats (EmpathyChatWindow *window)
+{
+ EmpathyChatWindowPriv *priv;
+
+ priv = GET_PRIV (window);
+ g_object_ref (window);
+
+ while (priv->chats) {
+ empathy_chat_window_remove_chat (window, priv->chats->data);
+ }
+
+ g_object_unref (window);
+}
+
+static void
+confirm_close_response_cb (GtkWidget *dialog,
+ int response,
+ EmpathyChatWindow *window)
+{
+ EmpathyChat *chat;
+
+ chat = g_object_get_data (G_OBJECT (dialog), "chat");
+
+ gtk_widget_destroy (dialog);
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ return;
+
+ if (chat != NULL) {
+ empathy_chat_window_remove_chat (window, chat);
+ } else {
+ remove_all_chats (window);
+ }
+}
+
+static void
+confirm_close (EmpathyChatWindow *window,
+ gboolean close_window,
+ guint n_rooms,
+ EmpathyChat *chat)
+{
+ EmpathyChatWindowPriv *priv;
+ GtkWidget *dialog;
+ gchar *primary, *secondary;
+
+ g_return_if_fail (n_rooms > 0);
+
+ if (n_rooms > 1) {
+ g_return_if_fail (chat == NULL);
+ } else {
+ g_return_if_fail (chat != NULL);
+ }
+
+ priv = GET_PRIV (window);
+
+ /* If there are no chats in this window, how could we possibly have got
+ * here?
+ */
+ g_return_if_fail (priv->chats != NULL);
+
+ /* Treat closing a window which only has one tab exactly like closing
+ * that tab.
+ */
+ if (close_window && priv->chats->next == NULL) {
+ close_window = FALSE;
+ chat = priv->chats->data;
+ }
+
+ if (close_window) {
+ primary = g_strdup (_("Close this window?"));
+
+ if (n_rooms == 1) {
+ gchar *chat_name = empathy_chat_dup_name (chat);
+ secondary = g_strdup_printf (
+ _("Closing this window will leave %s. You will "
+ "not receive any further messages until you "
+ "rejoin it."),
+ chat_name);
+ g_free (chat_name);
+ } else {
+ secondary = g_strdup_printf (
+ /* Note to translators: the number of chats will
+ * always be at least 2.
+ */
+ ngettext (
+ "Closing this window will leave a chat room. You will "
+ "not receive any further messages until you rejoin it.",
+ "Closing this window will leave %u chat rooms. You will "
+ "not receive any further messages until you rejoin them.",
+ n_rooms),
+ n_rooms);
+ }
+ } else {
+ gchar *chat_name = empathy_chat_dup_name (chat);
+ primary = g_strdup_printf (_("Leave %s?"), chat_name);
+ secondary = g_strdup (_("You will not receive any further messages from this chat "
+ "room until you rejoin it."));
+ g_free (chat_name);
+ }
+
+ dialog = gtk_message_dialog_new (
+ GTK_WINDOW (priv->dialog),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CANCEL,
+ "%s", primary);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ g_object_set (dialog, "secondary-text", secondary, NULL);
+
+ g_free (primary);
+ g_free (secondary);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ close_window ? _("Close window") : _("Leave room"),
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ if (!close_window) {
+ g_object_set_data (G_OBJECT (dialog), "chat", chat);
+ }
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (confirm_close_response_cb), window);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+/* Returns TRUE if we should check if the user really wants to leave. If it's
+ * a multi-user chat, and it has a TpChat (so there's an underlying channel, so
+ * the user is actually in the room as opposed to having been kicked or gone
+ * offline or something), then we should check.
+ */
+static gboolean
+chat_needs_close_confirmation (EmpathyChat *chat)
+{
+ return (empathy_chat_is_room (chat)
+ && empathy_chat_get_tp_chat (chat) != NULL);
+}
+
+static void
+maybe_close_chat (EmpathyChatWindow *window,
+ EmpathyChat *chat)
+{
+ g_return_if_fail (chat != NULL);
+
+ if (chat_needs_close_confirmation (chat)) {
+ confirm_close (window, FALSE, 1, chat);
+ } else {
+ empathy_chat_window_remove_chat (window, chat);
+ }
+}
+
static void
chat_window_close_clicked_cb (GtkAction *action,
EmpathyChat *chat)
EmpathyChatWindow *window;
window = chat_window_find_chat (chat);
- empathy_chat_window_remove_chat (window, chat);
+ maybe_close_chat (window, chat);
}
static void
append_markup_printf (tooltip, "\n%s", _("Typing a message."));
}
+ if (remote_contact != NULL) {
+ const gchar * const *types;
+
+ types = empathy_contact_get_client_types (remote_contact);
+ if (types != NULL && !tp_strdiff (types[0], "phone")) {
+ /* I'm on a phone ! */
+ gchar *tmp = name;
+
+ name = g_strdup_printf ("☎ %s", name);
+ g_free (tmp);
+ }
+ }
+
markup = g_string_free (tooltip, FALSE);
widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget");
gtk_widget_set_tooltip_markup (widget, markup);
g_free (markup);
/* Update tab and menu label */
+ if (empathy_chat_is_highlighted (chat)) {
+ markup = g_markup_printf_escaped (
+ "<span color=\"red\" weight=\"bold\">%s</span>",
+ name);
+ } else {
+ markup = g_markup_escape_text (name, -1);
+ }
+
widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
- gtk_label_set_text (GTK_LABEL (widget), name);
+ gtk_label_set_markup (GTK_LABEL (widget), markup);
widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-label");
- gtk_label_set_text (GTK_LABEL (widget), name);
+ gtk_label_set_markup (GTK_LABEL (widget), markup);
+ g_free (markup);
/* Update the window if it's the current chat */
if (priv->current_chat == chat) {
g_return_if_fail (priv->current_chat != NULL);
- empathy_chat_window_remove_chat (window, priv->current_chat);
+ maybe_close_chat (window, priv->current_chat);
}
static void
EmpathyChatWindow *window)
{
EmpathyChatWindowPriv *priv = GET_PRIV (window);
+ EmpathyChat *chat = NULL;
+ guint n_rooms = 0;
+ GList *l;
DEBUG ("Delete event received");
- g_object_ref (window);
- while (priv->chats) {
- empathy_chat_window_remove_chat (window, priv->chats->data);
+ for (l = priv->chats; l != NULL; l = l->next) {
+ if (chat_needs_close_confirmation (l->data)) {
+ chat = l->data;
+ n_rooms++;
+ }
+ }
+
+ if (n_rooms > 0) {
+ confirm_close (window, TRUE, n_rooms,
+ (n_rooms == 1 ? chat : NULL));
+ } else {
+ remove_all_chats (window);
}
- g_object_unref (window);
return TRUE;
}
g_free (escaped);
}
-static void
-chat_window_set_highlight_room_labels (EmpathyChat *chat)
-{
- gchar *markup, *name;
- GtkWidget *widget;
-
- if (!empathy_chat_is_room (chat))
- return;
-
- name = empathy_chat_dup_name (chat);
- markup = g_markup_printf_escaped (
- "<span color=\"red\" weight=\"bold\">%s</span>",
- name);
-
- widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
- gtk_label_set_markup (GTK_LABEL (widget), markup);
-
- widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-label");
- gtk_label_set_markup (GTK_LABEL (widget), markup);
-
- g_free (name);
- g_free (markup);
-}
-
static gboolean
empathy_chat_window_has_focus (EmpathyChatWindow *window)
{
chat_window_new_message_cb (EmpathyChat *chat,
EmpathyMessage *message,
gboolean pending,
+ gboolean should_highlight,
EmpathyChatWindow *window)
{
EmpathyChatWindowPriv *priv;
if (chatroom != NULL && empathy_chatroom_is_always_urgent (chatroom)) {
needs_urgency = TRUE;
} else {
- needs_urgency = empathy_message_should_highlight (message);
+ needs_urgency = should_highlight;
}
} else {
needs_urgency = TRUE;
}
if (needs_urgency) {
- chat_window_set_highlight_room_labels (chat);
-
if (!has_focus) {
chat_window_set_urgency_hint (window, TRUE);
}
return FALSE;
}
+static void
+drag_data_received_individual_id (EmpathyChatWindow *self,
+ GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time_)
+{
+ const gchar *id;
+ EmpathyIndividualManager *manager = NULL;
+ FolksIndividual *individual;
+ EmpathyChatWindowPriv *priv = GET_PRIV (self);
+ EmpathyTpChat *chat;
+ TpContact *tp_contact;
+ TpConnection *conn;
+ EmpathyContact *contact;
+
+ id = (const gchar *) gtk_selection_data_get_data (selection);
+
+ DEBUG ("DND invididual %s", id);
+
+ if (priv->current_chat == NULL)
+ goto out;
+
+ chat = empathy_chat_get_tp_chat (priv->current_chat);
+ if (chat == NULL)
+ goto out;
+
+ if (!empathy_tp_chat_can_add_contact (chat)) {
+ DEBUG ("Can't invite contact to %s",
+ tp_proxy_get_object_path (chat));
+ goto out;
+ }
+
+ manager = empathy_individual_manager_dup_singleton ();
+
+ individual = empathy_individual_manager_lookup_member (manager, id);
+ if (individual == NULL) {
+ DEBUG ("Failed to find individual %s", id);
+ goto out;
+ }
+
+ conn = tp_channel_borrow_connection ((TpChannel *) chat);
+ tp_contact = empathy_get_tp_contact_for_individual (individual, conn);
+ if (tp_contact == NULL) {
+ DEBUG ("Can't find a TpContact on connection %s for %s",
+ tp_proxy_get_object_path (conn), id);
+ goto out;
+ }
+
+ DEBUG ("Inviting %s to join %s", tp_contact_get_identifier (tp_contact),
+ tp_channel_get_identifier ((TpChannel *) chat));
+
+ contact = empathy_contact_dup_from_tp_contact (tp_contact);
+ empathy_contact_list_add (EMPATHY_CONTACT_LIST (chat), contact, NULL);
+ g_object_unref (contact);
+
+out:
+ gtk_drag_finish (context, TRUE, FALSE, time_);
+ tp_clear_object (&manager);
+}
+
static void
chat_window_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
*/
gtk_drag_finish (context, TRUE, FALSE, time_);
}
+ else if (info == DND_DRAG_TYPE_INDIVIDUAL_ID) {
+ drag_data_received_individual_id (window, widget, context, x, y,
+ selection, info, time_);
+ }
else if (info == DND_DRAG_TYPE_URI_LIST) {
EmpathyChatWindowPriv *priv;
EmpathyContact *contact;
}
empathy_chat_window_switch_to_chat (window, chat);
- empathy_window_present_with_time (GTK_WINDOW (priv->dialog),
- x_timestamp);
+
+ /* Don't use empathy_window_present_with_time () which would move the window
+ * to our current desktop but move to the window's desktop instead. This is
+ * more coherent with Shell's 'app is ready' notication which moves the view
+ * to the app desktop rather than moving the app itself. */
+ empathy_move_to_window_desktop (GTK_WINDOW (priv->dialog), x_timestamp);
gtk_widget_grab_focus (chat->input_text_view);
}