#include <libempathy-gtk/empathy-ui-utils.h>
#include <libempathy-gtk/empathy-notify-manager.h>
+#include "empathy-chat-manager.h"
#include "empathy-chat-window.h"
#include "empathy-about-dialog.h"
#include "empathy-invite-participant-dialog.h"
GtkTargetList *contact_targets;
GtkTargetList *file_targets;
+ EmpathyChatManager *chat_manager;
+ gulong chat_manager_chats_changed_id;
+
/* Menu items. */
GtkUIManager *ui_manager;
GtkAction *menu_conv_insert_smiley;
GtkAction *menu_tabs_next;
GtkAction *menu_tabs_prev;
+ GtkAction *menu_tabs_undo_close_tab;
GtkAction *menu_tabs_left;
GtkAction *menu_tabs_right;
GtkAction *menu_tabs_detach;
{ "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 },
};
gtk_misc_set_padding (GTK_MISC (name_label), 2, 0);
gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
- g_object_set_data_full (G_OBJECT (chat),
+ g_object_set_data (G_OBJECT (chat),
is_tab_label ? "chat-window-tab-label" : "chat-window-menu-label",
- g_object_ref (name_label), g_object_unref);
+ name_label);
status_image = gtk_image_new ();
gtk_box_pack_start (GTK_BOX (event_box_hbox), status_image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (event_box_hbox), name_label, TRUE, TRUE, 0);
- g_object_set_data_full (G_OBJECT (chat),
+ g_object_set_data (G_OBJECT (chat),
is_tab_label ? "chat-window-tab-image" : "chat-window-menu-image",
- g_object_ref (status_image), g_object_unref);
- g_object_set_data_full (G_OBJECT (chat),
+ status_image);
+ g_object_set_data (G_OBJECT (chat),
is_tab_label ? "chat-window-tab-tooltip-widget" : "chat-window-menu-tooltip-widget",
- g_object_ref (event_box), g_object_unref);
+ event_box);
gtk_container_add (GTK_CONTAINER (event_box), event_box_hbox);
gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, TRUE, 0);
if (is_tab_label) {
close_button = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
- g_object_set_data_full (G_OBJECT (chat), "chat-window-tab-close-button",
- g_object_ref (close_button), g_object_unref);
+ g_object_set_data (G_OBJECT (chat), "chat-window-tab-close-button", close_button);
/* We don't want focus/keynav for the button to avoid clutter, and
* Ctrl-W works anyway.
{
gboolean first_page;
gboolean last_page;
+ gboolean wrap_around;
gboolean is_connected;
gint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
first_page = (page_num == 0);
last_page = (page_num == (num_pages - 1));
+ g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
+ &wrap_around, NULL);
is_connected = empathy_chat_get_tp_chat (priv->current_chat) != NULL;
- DEBUG ("Update window : Menu Contexts (Tabs & Conv)");
-
- gtk_action_set_sensitive (priv->menu_tabs_next, TRUE);
- gtk_action_set_sensitive (priv->menu_tabs_prev, TRUE);
+ gtk_action_set_sensitive (priv->menu_tabs_next, (!last_page ||
+ wrap_around));
+ gtk_action_set_sensitive (priv->menu_tabs_prev, (!first_page ||
+ wrap_around));
gtk_action_set_sensitive (priv->menu_tabs_detach, num_pages > 1);
gtk_action_set_sensitive (priv->menu_tabs_left, !first_page);
gtk_action_set_sensitive (priv->menu_tabs_right, !last_page);
"/chats_menubar/menu_contact");
orig_submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu));
- DEBUG ("Update window : Contact Menu");
-
if (orig_submenu == NULL || !GTK_WIDGET_VISIBLE (orig_submenu)) {
submenu = empathy_chat_get_contact_menu (priv->current_chat);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu), submenu);
{
gchar *name;
- DEBUG ("Update window : Title");
-
name = get_window_title_name (priv);
gtk_window_set_title (GTK_WINDOW (priv->dialog), name);
g_free (name);
n_chats = g_list_length (priv->chats);
- DEBUG ("Update window : Icon");
-
/* Update window icon */
if (priv->chats_new_msg) {
gtk_window_set_icon_name (GTK_WINDOW (priv->dialog),
GtkWidget *chat_close_button;
gint i;
- DEBUG ("Update window : Close Button");
-
if (num_pages == 1) {
chat = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), 0);
chat_close_button = g_object_get_data (G_OBJECT (chat),
num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
- DEBUG ("Update window");
-
/* Update Tab menu */
chat_window_menu_context_update (priv,
num_pages);
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));
EmpathyChatWindowPriv *priv;
EmpathyChat *chat;
gint index_, numPages;
+ gboolean wrap_around;
priv = GET_PRIV (window);
+ g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
+ &wrap_around, NULL);
+
chat = priv->current_chat;
index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
numPages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
- if (index_ == (numPages - 1)) {
+ if (index_ == (numPages - 1) && wrap_around) {
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
return;
}
EmpathyChatWindowPriv *priv;
EmpathyChat *chat;
gint index_, numPages;
+ gboolean wrap_around;
priv = GET_PRIV (window);
+ g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
+ &wrap_around, NULL);
+
chat = priv->current_chat;
index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
numPages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
- if (index_ <= 0) {
+ if (index_ <= 0 && wrap_around) {
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), numPages - 1);
return;
}
gtk_notebook_prev_page (GTK_NOTEBOOK (priv->notebook));
}
+static void
+chat_window_tabs_undo_close_tab_activate_cb (GtkAction *action,
+ EmpathyChatWindow *window)
+{
+ EmpathyChatWindowPriv *priv = GET_PRIV (window);
+ empathy_chat_manager_undo_closed_chat (priv->chat_manager);
+}
+
static void
chat_window_tabs_left_activate_cb (GtkAction *action,
EmpathyChatWindow *window)
priv = GET_PRIV (window);
- DEBUG ("Turning %s urgency hint", urgent ? "on" : "off");
gtk_window_set_urgency_hint (GTK_WINDOW (priv->dialog), urgent);
}
if (has_focus && priv->current_chat == chat) {
/* window and tab are focused so consider the message to be read */
+
+ /* FIXME: see Bug#610994 and coments about it in EmpathyChatPriv */
empathy_chat_messages_read (chat);
return;
}
{
EmpathyChatWindowPriv *priv;
- DEBUG ("Focus in event, updating title");
-
priv = GET_PRIV (window);
priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat);
}
static gboolean
-chat_window_drag_motion (GtkWidget *widget,
+chat_window_drag_drop (GtkWidget *widget,
GdkDragContext *context,
int x,
int y,
{
GdkAtom target;
EmpathyChatWindowPriv *priv;
- GdkAtom dest_target;
priv = GET_PRIV (window);
- target = gtk_drag_dest_find_target (widget, context, NULL);
+ 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 != GDK_NONE) {
+ gtk_drag_get_data (widget, context, target, time_);
+ return TRUE;
+ }
+
+ return FALSE;
+}
- dest_target = gdk_atom_intern_static_string ("text/uri-list");
- if (target == dest_target) {
+static gboolean
+chat_window_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint time_,
+ EmpathyChatWindow *window)
+{
+ GdkAtom target;
+ EmpathyChatWindowPriv *priv;
+
+ priv = GET_PRIV (window);
+
+ 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
return TRUE;
}
- /* Otherwise, it must be a notebook tab drag. Set to MOVE. */
- gdk_drag_status (context, GDK_ACTION_MOVE, time_);
- return TRUE;
+ return FALSE;
}
static void
EmpathyChatWindowPriv *priv;
priv = GET_PRIV (window);
-
- if (old_window == window) {
- DEBUG ("DND tab (within same window)");
- priv->dnd_same_window = TRUE;
- gtk_drag_finish (context, TRUE, FALSE, time_);
- return;
- }
-
- priv->dnd_same_window = FALSE;
+ priv->dnd_same_window = (old_window == window);
+ DEBUG ("DND tab (within same window: %s)",
+ priv->dnd_same_window ? "Yes" : "No");
}
-
- /* We should return TRUE to remove the data when doing
- * GDK_ACTION_MOVE, but we don't here otherwise it has
- * weird consequences, and we handle that internally
- * anyway with add_chat () and remove_chat ().
- */
- gtk_drag_finish (context, TRUE, FALSE, time_);
} else {
DEBUG ("DND from unknown source");
gtk_drag_finish (context, FALSE, FALSE, time_);
}
}
+static void
+chat_window_chat_manager_chats_changed_cb (EmpathyChatManager *chat_manager,
+ guint num_chats_in_manager,
+ EmpathyChatWindow *window)
+{
+ EmpathyChatWindowPriv *priv = GET_PRIV (window);
+
+ gtk_action_set_sensitive (priv->menu_tabs_undo_close_tab,
+ num_chats_in_manager > 0);
+}
+
static void
chat_window_finalize (GObject *object)
{
gtk_target_list_unref (priv->file_targets);
}
+ if (priv->chat_manager) {
+ g_signal_handler_disconnect (priv->chat_manager,
+ priv->chat_manager_chats_changed_id);
+ g_object_unref (priv->chat_manager);
+ priv->chat_manager = NULL;
+ }
+
chat_windows = g_list_remove (chat_windows, window);
gtk_widget_destroy (priv->dialog);
"menu_edit_find", &priv->menu_edit_find,
"menu_tabs_next", &priv->menu_tabs_next,
"menu_tabs_prev", &priv->menu_tabs_prev,
+ "menu_tabs_undo_close_tab", &priv->menu_tabs_undo_close_tab,
"menu_tabs_left", &priv->menu_tabs_left,
"menu_tabs_right", &priv->menu_tabs_right,
"menu_tabs_detach", &priv->menu_tabs_detach,
"menu_edit_find", "activate", chat_window_find_activate_cb,
"menu_tabs_next", "activate", chat_window_tabs_next_activate_cb,
"menu_tabs_prev", "activate", chat_window_tabs_previous_activate_cb,
+ "menu_tabs_undo_close_tab", "activate", chat_window_tabs_undo_close_tab_activate_cb,
"menu_tabs_left", "activate", chat_window_tabs_left_activate_cb,
"menu_tabs_right", "activate", chat_window_tabs_right_activate_cb,
"menu_tabs_detach", "activate", chat_window_detach_activate_cb,
/* Set up drag and drop */
gtk_drag_dest_set (GTK_WIDGET (priv->notebook),
- GTK_DEST_DEFAULT_ALL,
+ GTK_DEST_DEFAULT_HIGHLIGHT,
drag_types_dest,
G_N_ELEMENTS (drag_types_dest),
GDK_ACTION_MOVE | GDK_ACTION_COPY);
"drag-data-received",
G_CALLBACK (chat_window_drag_data_received),
window);
+ g_signal_connect (priv->notebook,
+ "drag-drop",
+ G_CALLBACK (chat_window_drag_drop),
+ window);
chat_windows = g_list_prepend (chat_windows, window);
priv->current_chat = NULL;
priv->notify_mgr = empathy_notify_manager_dup_singleton ();
+
+ priv->chat_manager = empathy_chat_manager_dup_singleton ();
+ priv->chat_manager_chats_changed_id =
+ g_signal_connect (priv->chat_manager, "chats-changed",
+ G_CALLBACK (chat_window_chat_manager_chats_changed_cb),
+ window);
+
+ chat_window_chat_manager_chats_changed_cb (priv->chat_manager,
+ empathy_chat_manager_get_num_chats (priv->chat_manager),
+ window);
}
EmpathyChatWindow *
GtkWidget *label;
GtkWidget *popup_label;
GtkWidget *child;
+ GValue value = { 0, };
g_return_if_fail (window != NULL);
g_return_if_fail (EMPATHY_IS_CHAT (chat));
gtk_notebook_append_page_menu (GTK_NOTEBOOK (priv->notebook), child, label, popup_label);
gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
- gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (priv->notebook), child,
- TRUE, TRUE, GTK_PACK_START);
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, TRUE);
+ gtk_container_child_set_property (GTK_CONTAINER (priv->notebook),
+ child, "tab-expand" , &value);
+ gtk_container_child_set_property (GTK_CONTAINER (priv->notebook),
+ child, "tab-fill" , &value);
+ g_value_unset (&value);
DEBUG ("Chat added (%d references)", G_OBJECT (chat)->ref_count);
}
EmpathyChatWindowPriv *priv;
gint position;
EmpathyContact *remote_contact;
+ EmpathyChatManager *chat_manager;
g_return_if_fail (window != NULL);
g_return_if_fail (EMPATHY_IS_CHAT (chat));
chat);
}
+ chat_manager = empathy_chat_manager_dup_singleton ();
+ empathy_chat_manager_closed_chat (chat_manager, chat);
+ g_object_unref (chat_manager);
+
position = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
GTK_WIDGET (chat));
gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), position);
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);
}