+2007-09-08 Xavier Claessens <xclaesse@gmail.com>
+
+ * libempathy-gtk/empathy-images.h:
+ * libempathy-gtk/empathy-chat.glade:
+ * libempathy-gtk/empathy-contact-list-view.c:
+ * libempathy-gtk/empathy-contact-list-store.c:
+ * libempathy-gtk/empathy-contact-list-store.h:
+ * libempathy-gtk/Makefile.am:
+ * libempathy-gtk/empathy-chat-window.c:
+ * libempathy/empathy-contact.c:
+ * libempathy/empathy-contact.h: Adding UI to start a VoIP call. It does
+ nothing yet. Most of the code is ported from Gossip patch
+ (Raphael Slinckx, Xavier Claessens).
+
2007-09-08 Xavier Claessens <xclaesse@gmail.com>
* libempathy/empathy-contact.c:
empathy-profile-chooser.c \
empathy-cell-renderer-expander.c \
empathy-cell-renderer-text.c \
+ empathy-cell-renderer-activatable.c \
empathy-spell.c \
empathy-spell-dialog.c \
empathy-contact-groups.c \
empathy-profile-chooser.h \
empathy-cell-renderer-expander.h \
empathy-cell-renderer-text.h \
+ empathy-cell-renderer-activatable.h \
empathy-spell.h \
empathy-spell-dialog.h \
empathy-contact-groups.h \
/* Menu items. */
GtkWidget *menu_conv_clear;
GtkWidget *menu_conv_insert_smiley;
+ GtkWidget *menu_conv_call;
+ GtkWidget *menu_conv_call_separator;
GtkWidget *menu_conv_log;
GtkWidget *menu_conv_separator;
GtkWidget *menu_conv_add_contact;
EmpathyChatWindow *window);
static void chat_window_add_contact_activate_cb (GtkWidget *menuitem,
EmpathyChatWindow *window);
+static void chat_window_call_activate_cb (GtkWidget *menuitem,
+ EmpathyChatWindow *window);
static void chat_window_log_activate_cb (GtkWidget *menuitem,
EmpathyChatWindow *window);
static void chat_window_show_contacts_toggled_cb (GtkWidget *menuitem,
"menu_conv", &menu_conv,
"menu_conv_clear", &priv->menu_conv_clear,
"menu_conv_insert_smiley", &priv->menu_conv_insert_smiley,
+ "menu_conv_call", &priv->menu_conv_call,
+ "menu_conv_call_separator", &priv->menu_conv_call_separator,
"menu_conv_log", &priv->menu_conv_log,
"menu_conv_separator", &priv->menu_conv_separator,
"menu_conv_add_contact", &priv->menu_conv_add_contact,
"chat_window", "configure-event", chat_window_configure_event_cb,
"menu_conv", "activate", chat_window_conv_activate_cb,
"menu_conv_clear", "activate", chat_window_clear_activate_cb,
+ "menu_conv_call", "activate", chat_window_call_activate_cb,
"menu_conv_log", "activate", chat_window_log_activate_cb,
"menu_conv_add_contact", "activate", chat_window_add_contact_activate_cb,
"menu_conv_info", "activate", chat_window_info_activate_cb,
// FIXME: empathy_add_contact_dialog_show (NULL, contact);
}
+static void
+chat_window_call_activate_cb (GtkWidget *menuitem,
+ EmpathyChatWindow *window)
+{
+ EmpathyChatWindowPriv *priv;
+
+ priv = GET_PRIV (window);
+
+ if (!empathy_chat_is_group_chat (priv->current_chat)) {
+ EmpathyPrivateChat *chat;
+ EmpathyContact *contact;
+
+ chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
+ contact = empathy_private_chat_get_contact (chat);
+ /* FIXME: Start VoIP */
+ }
+}
+
static void
chat_window_log_activate_cb (GtkWidget *menuitem,
EmpathyChatWindow *window)
}
static void
-chat_window_conv_activate_cb (GtkWidget *menuitem,
+chat_window_conv_activate_cb (GtkWidget *menuitem,
EmpathyChatWindow *window)
{
EmpathyChatWindowPriv *priv;
- EmpathyLogManager *manager;
+ EmpathyLogManager *manager;
gboolean log_exists = FALSE;
+ gboolean can_voip = FALSE;
priv = GET_PRIV (window);
empathy_chat_is_group_chat (priv->current_chat));
g_object_unref (manager);
+ if (!empathy_chat_is_group_chat (priv->current_chat)) {
+ EmpathyPrivateChat *chat;
+ EmpathyContact *contact;
+
+ chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
+ contact = empathy_private_chat_get_contact (chat);
+ can_voip = empathy_contact_can_voip (contact);
+ }
+
gtk_widget_set_sensitive (priv->menu_conv_log, log_exists);
+ g_object_set (priv->menu_conv_call, "visible", can_voip, NULL);
+ g_object_set (priv->menu_conv_call_separator, "visible", can_voip, NULL);
}
static void
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image235">
+ <widget class="GtkImage" id="image262">
<property name="visible">True</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator11">
+ <widget class="GtkSeparatorMenuItem" id="separator13">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_call">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Ca_ll</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="menu_conv_call_image">
+ <property name="visible">True</property>
+ <property name="icon_name">gnome-stock-mic</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="menu_conv_call_separator">
<property name="visible">True</property>
</widget>
</child>
<accelerator key="F3" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image236">
+ <widget class="GtkImage" id="image263">
<property name="visible">True</property>
<property name="stock">gtk-justify-left</property>
<property name="icon_size">1</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image237">
+ <widget class="GtkImage" id="image264">
<property name="visible">True</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image238">
+ <widget class="GtkImage" id="image265">
<property name="visible">True</property>
<property name="stock">gtk-info</property>
<property name="icon_size">1</property>
<accelerator key="W" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image239">
+ <widget class="GtkImage" id="image266">
<property name="visible">True</property>
<property name="stock">gtk-close</property>
<property name="icon_size">1</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image240">
+ <widget class="GtkImage" id="image267">
<property name="visible">True</property>
<property name="stock">gtk-new</property>
<property name="icon_size">1</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image241">
+ <widget class="GtkImage" id="image268">
<property name="visible">True</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
<accelerator key="X" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image242">
+ <widget class="GtkImage" id="image269">
<property name="visible">True</property>
<property name="stock">gtk-cut</property>
<property name="icon_size">1</property>
<accelerator key="C" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image243">
+ <widget class="GtkImage" id="image270">
<property name="visible">True</property>
<property name="stock">gtk-copy</property>
<property name="icon_size">1</property>
<accelerator key="V" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image244">
+ <widget class="GtkImage" id="image271">
<property name="visible">True</property>
<property name="stock">gtk-paste</property>
<property name="icon_size">1</property>
contact_list_store_setup (EmpathyContactListStore *store)
{
EmpathyContactListStorePriv *priv;
- GType types[] = {G_TYPE_STRING, /* Status icon-name */
- GDK_TYPE_PIXBUF, /* Avatar pixbuf */
- G_TYPE_BOOLEAN, /* Avatar pixbuf visible */
- G_TYPE_STRING, /* Name */
- G_TYPE_STRING, /* Status string */
- G_TYPE_BOOLEAN, /* Show status */
+ GType types[] = {G_TYPE_STRING, /* Status icon-name */
+ GDK_TYPE_PIXBUF, /* Avatar pixbuf */
+ G_TYPE_BOOLEAN, /* Avatar pixbuf visible */
+ G_TYPE_STRING, /* Name */
+ G_TYPE_STRING, /* Status string */
+ G_TYPE_BOOLEAN, /* Show status */
EMPATHY_TYPE_CONTACT, /* Contact type */
- G_TYPE_BOOLEAN, /* Is group */
- G_TYPE_BOOLEAN, /* Is active */
- G_TYPE_BOOLEAN, /* Is online */
- G_TYPE_BOOLEAN}; /* Is separator */
+ G_TYPE_BOOLEAN, /* Is group */
+ G_TYPE_BOOLEAN, /* Is active */
+ G_TYPE_BOOLEAN, /* Is online */
+ G_TYPE_BOOLEAN, /* Is separator */
+ G_TYPE_BOOLEAN}; /* Can VoIP */
priv = GET_PRIV (store);
g_signal_connect (contact, "notify::avatar",
G_CALLBACK (contact_list_store_contact_updated_cb),
store);
- g_signal_connect (contact, "notify::type",
+ g_signal_connect (contact, "notify::capabilities",
G_CALLBACK (contact_list_store_contact_updated_cb),
store);
COL_CONTACT, contact,
COL_IS_GROUP, FALSE,
COL_IS_SEPARATOR, FALSE,
+ COL_CAN_VOIP, empathy_contact_can_voip (contact),
-1);
}
COL_CONTACT, contact,
COL_IS_GROUP, FALSE,
COL_IS_SEPARATOR, FALSE,
+ COL_CAN_VOIP, empathy_contact_can_voip (contact),
-1);
g_free (l->data);
}
COL_IS_GROUP, FALSE,
COL_IS_ONLINE, now_online,
COL_IS_SEPARATOR, FALSE,
+ COL_CAN_VOIP, empathy_contact_can_voip (contact),
-1);
}
COL_IS_ACTIVE,
COL_IS_ONLINE,
COL_IS_SEPARATOR,
+ COL_CAN_VOIP,
COL_COUNT
} EmpathyContactListStoreCol;
#include "empathy-contact-groups.h"
#include "empathy-cell-renderer-expander.h"
#include "empathy-cell-renderer-text.h"
+#include "empathy-cell-renderer-activatable.h"
#include "empathy-ui-utils.h"
#include "empathy-contact-dialogs.h"
//#include "empathy-chat-invite.h"
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter,
- EmpathyContactListView *view);
+ EmpathyContactListView *view);
+static void contact_list_view_voip_cell_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EmpathyContactListView *view);
static void contact_list_view_avatar_cell_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *model,
EmpathyContactListView *view);
static GtkWidget * contact_list_view_get_contact_menu (EmpathyContactListView *view,
gboolean can_send_file,
- gboolean can_show_log);
+ gboolean can_show_log,
+ gboolean can_voip);
static gboolean contact_list_view_button_press_event_cb (EmpathyContactListView *view,
GdkEventButton *event,
gpointer user_data);
GtkTreePath *path,
GtkTreeViewColumn *col,
gpointer user_data);
+static void contact_list_view_voip_activated_cb (EmpathyCellRendererActivatable *cell,
+ const gchar *path_string,
+ EmpathyContactListView *view);
static void contact_list_view_row_expand_or_collapse_cb (EmpathyContactListView *view,
GtkTreeIter *iter,
GtkTreePath *path,
EmpathyContactListView *view);
static void contact_list_view_action_activated (EmpathyContactListView *view,
EmpathyContact *contact);
+static void contact_list_view_voip_activated (EmpathyContactListView *view,
+ EmpathyContact *contact);
enum {
PROP_0,
N_("_View Previous Conversations"), NULL, N_("View previous conversations with this contact"),
G_CALLBACK (contact_list_view_action_cb)
},
+ { "Call", EMPATHY_IMAGE_VOIP,
+ N_("_Call"), NULL, N_("Start a voice or video conversation with this contact"),
+ G_CALLBACK (contact_list_view_action_cb)
+ },
};
static guint n_entries = G_N_ELEMENTS (entries);
"<ui>"
" <popup name='Contact'>"
" <menuitem action='Chat'/>"
+ " <menuitem action='Call'/>"
" <menuitem action='Log'/>"
" <menuitem action='SendFile'/>"
" <separator/>"
GtkWidget *
empathy_contact_list_view_get_contact_menu (EmpathyContactListView *view,
- EmpathyContact *contact)
+ EmpathyContact *contact)
{
EmpathyLogManager *log_manager;
gboolean can_show_log;
gboolean can_send_file;
+ gboolean can_voip;
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
empathy_contact_get_account (contact),
empathy_contact_get_id (contact),
FALSE);
- can_send_file = FALSE;
g_object_unref (log_manager);
+ can_send_file = FALSE;
+ can_voip = empathy_contact_can_voip (contact);
return contact_list_view_get_contact_menu (view,
can_send_file,
- can_show_log);
+ can_show_log,
+ can_voip);
}
static void
gtk_tree_view_column_add_attribute (col, cell,
"is_group", COL_IS_GROUP);
+ /* Voip Capability Icon */
+ cell = empathy_cell_renderer_activatable_new ();
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_cell_data_func (
+ col, cell,
+ (GtkTreeCellDataFunc) contact_list_view_voip_cell_data_func,
+ view, NULL);
+
+ g_object_set (cell,
+ "visible", FALSE,
+ NULL);
+
+ g_signal_connect (cell, "path-activated",
+ G_CALLBACK (contact_list_view_voip_activated_cb),
+ view);
+
/* Avatar */
cell = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (col, cell, FALSE);
contact_list_view_cell_set_background (view, cell, is_group, is_active);
}
+static void
+contact_list_view_voip_cell_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EmpathyContactListView *view)
+{
+ gboolean is_group;
+ gboolean is_active;
+ gboolean can_voip;
+
+ gtk_tree_model_get (model, iter,
+ COL_IS_GROUP, &is_group,
+ COL_IS_ACTIVE, &is_active,
+ COL_CAN_VOIP, &can_voip,
+ -1);
+
+ g_object_set (cell,
+ "visible", !is_group && can_voip,
+ "icon-name", EMPATHY_IMAGE_VOIP,
+ NULL);
+
+ contact_list_view_cell_set_background (view, cell, is_group, is_active);
+}
+
static void
contact_list_view_avatar_cell_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
static GtkWidget *
contact_list_view_get_contact_menu (EmpathyContactListView *view,
gboolean can_send_file,
- gboolean can_show_log)
+ gboolean can_show_log,
+ gboolean can_voip)
{
EmpathyContactListViewPriv *priv;
GtkAction *action;
action = gtk_ui_manager_get_action (priv->ui, "/Contact/Log");
gtk_action_set_sensitive (action, can_show_log);
+ action = gtk_ui_manager_get_action (priv->ui, "/Contact/Call");
+ gtk_action_set_sensitive (action, can_voip);
+
action = gtk_ui_manager_get_action (priv->ui, "/Contact/SendFile");
gtk_action_set_visible (action, can_send_file);
}
}
+static void
+contact_list_view_voip_activated_cb (EmpathyCellRendererActivatable *cell,
+ const gchar *path_string,
+ EmpathyContactListView *view)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EmpathyContact *contact;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+ if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string)) {
+ return;
+ }
+
+ gtk_tree_model_get (model, &iter, COL_CONTACT, &contact, -1);
+
+ if (contact) {
+ contact_list_view_voip_activated (view, contact);
+ g_object_unref (contact);
+ }
+}
+
+
static void
contact_list_view_row_expand_or_collapse_cb (EmpathyContactListView *view,
GtkTreeIter *iter,
if (contact && strcmp (name, "Chat") == 0) {
contact_list_view_action_activated (view, contact);
}
+ else if (contact && strcmp (name, "Call") == 0) {
+ contact_list_view_voip_activated (view, contact);
+ }
else if (contact && strcmp (name, "Information") == 0) {
empathy_contact_information_dialog_show (contact, parent, FALSE);
}
g_object_unref (mc);
}
+static void
+contact_list_view_voip_activated (EmpathyContactListView *view,
+ EmpathyContact *contact)
+{
+ /* FIXME: Not implemented */
+}
+
#define EMPATHY_IMAGE_TYPING "empathy-typing"
#define EMPATHY_IMAGE_CONTACT_INFORMATION "gtk-info"
#define EMPATHY_IMAGE_GROUP_MESSAGE "empathy-group-message"
+#define EMPATHY_IMAGE_VOIP "gnome-stock-mic"
G_END_DECLS
return empathy_presence_state_get_default_status (MC_PRESENCE_OFFLINE);
}
+gboolean
+empathy_contact_can_voip (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
+
+ priv = GET_PRIV (contact);
+
+ return priv->capabilities & (EMPATHY_CAPABILITIES_AUDIO |
+ EMPATHY_CAPABILITIES_VIDEO);
+}
+
gboolean
empathy_contact_equal (gconstpointer v1,
gconstpointer v2)
gboolean is_user);
gboolean empathy_contact_is_online (EmpathyContact *contact);
const gchar * empathy_contact_get_status (EmpathyContact *contact);
+gboolean empathy_contact_can_voip (EmpathyContact *contact);
gboolean empathy_contact_equal (gconstpointer v1,
gconstpointer v2);
guint empathy_contact_hash (gconstpointer key);