#include <libempathy/empathy-contact.h>
#include <libempathy/empathy-message.h>
-#include <libempathy/empathy-dispatcher.h>
#include <libempathy/empathy-chatroom-manager.h>
#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-tp-contact-factory.h>
+#include <libempathy/empathy-contact-list.h>
#include <libempathy-gtk/empathy-images.h>
#include <libempathy-gtk/empathy-conf.h>
#include <libempathy-gtk/empathy-ui-utils.h>
#include <libempathy-gtk/empathy-notify-manager.h>
-#include <extensions/extensions.h>
-
#include "empathy-chat-window.h"
#include "empathy-about-dialog.h"
+#include "empathy-invite-participant-dialog.h"
#define DEBUG_FLAG EMPATHY_DEBUG_CHAT
#include <libempathy/empathy-debug.h>
GtkAction *menu_edit_cut;
GtkAction *menu_edit_copy;
GtkAction *menu_edit_paste;
+ GtkAction *menu_edit_find;
GtkAction *menu_tabs_next;
GtkAction *menu_tabs_prev;
{ "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_action_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
}
+static void
+chat_window_conversation_menu_update (EmpathyChatWindowPriv *priv,
+ EmpathyChatWindow *self)
+{
+ EmpathyTpChat *tp_chat;
+ TpConnection *connection;
+ GtkAction *action;
+ gboolean sensitive = FALSE;
+
+ g_return_if_fail (priv->current_chat != NULL);
+
+ action = gtk_ui_manager_get_action (priv->ui_manager,
+ "/chats_menubar/menu_conv/menu_conv_invite_participant");
+ tp_chat = empathy_chat_get_tp_chat (priv->current_chat);
+
+ if (tp_chat != NULL) {
+ connection = empathy_tp_chat_get_connection (tp_chat);
+
+ sensitive = empathy_tp_chat_can_add_contact (tp_chat) &&
+ (tp_connection_get_status (connection, NULL) ==
+ TP_CONNECTION_STATUS_CONNECTED);
+ }
+
+ gtk_action_set_sensitive (action, sensitive);
+}
+
static void
chat_window_contact_menu_update (EmpathyChatWindowPriv *priv,
EmpathyChatWindow *window)
chat_window_menu_context_update (priv,
num_pages);
+ chat_window_conversation_menu_update (priv, window);
+
chat_window_contact_menu_update (priv,
window);
}
static void
-upgrade_to_muc_cb (TpConnection *connection,
- gboolean yours,
- const char *object_path,
- GHashTable *properties,
- const GError *error,
- gpointer user_data,
- GObject *window)
-{
- if (error)
- {
- g_critical ("%s", error->message);
+got_contact_cb (EmpathyTpContactFactory *factory,
+ EmpathyContact *contact,
+ const GError *error,
+ gpointer user_data,
+ GObject *object)
+{
+ EmpathyTpChat *tp_chat = EMPATHY_TP_CHAT (user_data);
+
+ if (error != NULL) {
+ DEBUG ("Failed: %s", error->message);
return;
+ } else {
+ empathy_contact_list_add (EMPATHY_CONTACT_LIST (tp_chat),
+ contact, _("Inviting you to this room"));
}
-
- g_print ("GOT CHANNEL! %s\n", object_path);
}
static void
EmpathyChatWindow *window)
{
EmpathyChatWindowPriv *priv;
+ GtkWidget *dialog;
EmpathyTpChat *tp_chat;
- TpConnection *connection;
TpChannel *channel;
- GHashTable *props;
- GPtrArray *channels;
- char *invitees[3] = { NULL, };
-
- g_print ("INVITE PARTICIPANT\n");
+ int response;
+ TpAccount *account;
priv = GET_PRIV (window);
g_return_if_fail (priv->current_chat != NULL);
- /* FIXME: this is for upgrading a 1-to-1 channel to a MUC, inviting
- * a user to a MUC is much easier, and needs to be written */
-
tp_chat = empathy_chat_get_tp_chat (priv->current_chat);
- connection = empathy_tp_chat_get_connection (tp_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), account);
+ gtk_widget_show (dialog);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
- /* Ensure a MUC channel */
- channels = g_ptr_array_sized_new (1);
- g_ptr_array_add (channels, (char *) tp_proxy_get_object_path (channel));
+ if (response == GTK_RESPONSE_ACCEPT) {
+ TpConnection *connection;
+ EmpathyTpContactFactory *factory;
+ const char *id;
- invitees[0] = (char *) tp_channel_get_identifier (channel);
- // invitees[1] = /* FIXME: ask for this */
+ id = empathy_contact_selector_dialog_get_selected (
+ EMPATHY_CONTACT_SELECTOR_DIALOG (dialog), NULL);
+ if (EMP_STR_EMPTY (id)) goto out;
- props = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType", G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_UINT,
- TP_HANDLE_TYPE_NONE,
- EMP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels",
- TP_ARRAY_TYPE_OBJECT_PATH_LIST, channels,
- EMP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeIDs",
- G_TYPE_STRV, invitees,
- /* FIXME: InvitationMessage ? */
- NULL);
+ connection = tp_channel_borrow_connection (channel);
+ factory = empathy_tp_contact_factory_dup_singleton (connection);
- /* FIXME: this probably needs to go through EmpathyDispatcher */
- tp_cli_connection_interface_requests_call_ensure_channel (
- connection, -1, props, upgrade_to_muc_cb, NULL, NULL,
- G_OBJECT (window));
+ empathy_tp_contact_factory_get_from_id (factory, id,
+ got_contact_cb, tp_chat, NULL, NULL);
- g_hash_table_destroy (props);
+ g_object_unref (factory);
+ }
+
+out:
+ gtk_widget_destroy (dialog);
}
static void
empathy_chat_paste (priv->current_chat);
}
+static void
+chat_window_find_activate_cb (GtkAction *action,
+ EmpathyChatWindow *window)
+{
+ EmpathyChatWindowPriv *priv;
+
+ g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
+
+ priv = GET_PRIV (window);
+
+ empathy_chat_find (priv->current_chat);
+}
+
static void
chat_window_tabs_next_activate_cb (GtkAction *action,
EmpathyChatWindow *window)
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;
}
}
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_);
"menu_edit_cut", &priv->menu_edit_cut,
"menu_edit_copy", &priv->menu_edit_copy,
"menu_edit_paste", &priv->menu_edit_paste,
+ "menu_edit_find", &priv->menu_edit_find,
"menu_tabs_next", &priv->menu_tabs_next,
"menu_tabs_prev", &priv->menu_tabs_prev,
"menu_tabs_left", &priv->menu_tabs_left,
"menu_edit_cut", "activate", chat_window_cut_activate_cb,
"menu_edit_copy", "activate", chat_window_copy_activate_cb,
"menu_edit_paste", "activate", chat_window_paste_activate_cb,
+ "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_left", "activate", chat_window_tabs_left_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);
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);
}
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);
}