aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk/empathy-theme-adium.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk/empathy-theme-adium.c')
-rw-r--r--libempathy-gtk/empathy-theme-adium.c191
1 files changed, 173 insertions, 18 deletions
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index 0370b9055..bb2b189ca 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -59,7 +59,7 @@ typedef struct {
gint64 last_timestamp;
gboolean last_is_backlog;
guint pages_loading;
- /* Queue of GValue* containing an EmpathyMessage or string */
+ /* Queue of QueuedItem*s containing an EmpathyMessage or string */
GQueue message_queue;
/* Queue of owned gchar* of message token to remove unread
* marker for when we lose focus. */
@@ -119,6 +119,45 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyThemeAdium, empathy_theme_adium,
G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CHAT_VIEW,
theme_adium_iface_init));
+enum {
+ QUEUED_EVENT,
+ QUEUED_MESSAGE,
+ QUEUED_EDIT
+};
+
+typedef struct {
+ guint type;
+ EmpathyMessage *msg;
+ char *str;
+} QueuedItem;
+
+static QueuedItem *
+queue_item (GQueue *queue,
+ guint type,
+ EmpathyMessage *msg,
+ const char *str)
+{
+ QueuedItem *item = g_slice_new0 (QueuedItem);
+
+ item->type = type;
+ if (msg != NULL)
+ item->msg = g_object_ref (msg);
+ item->str = g_strdup (str);
+
+ g_queue_push_tail (queue, item);
+
+ return item;
+}
+
+static void
+free_queued_item (QueuedItem *item)
+{
+ tp_clear_object (&item->msg);
+ g_free (item->str);
+
+ g_slice_free (QueuedItem, item);
+}
+
static void
theme_adium_update_enable_webkit_developer_tools (EmpathyThemeAdium *theme)
{
@@ -315,7 +354,8 @@ static EmpathyStringParser string_parsers_with_smiley[] = {
static gchar *
theme_adium_parse_body (EmpathyThemeAdium *self,
- const gchar *text)
+ const gchar *text,
+ const gchar *token)
{
EmpathyThemeAdiumPriv *priv = GET_PRIV (self);
EmpathyStringParser *parsers;
@@ -332,8 +372,19 @@ theme_adium_parse_body (EmpathyThemeAdium *self,
* by html tags. Also escape text to make sure html code is
* displayed verbatim. */
string = g_string_sized_new (strlen (text));
+
+ /* wrap this in HTML that allows us to find the message for later
+ * editing */
+ if (!tp_str_empty (token))
+ g_string_append_printf (string,
+ "<span id=\"message-token-%s\">",
+ token);
+
empathy_string_parser_substr (text, -1, parsers, string);
+ if (!tp_str_empty (token))
+ g_string_append (string, "</span>");
+
/* Wrap body in order to make tabs and multiple spaces displayed
* properly. See bug #625745. */
g_string_prepend (string, "<div style=\"display: inline; "
@@ -817,7 +868,6 @@ theme_adium_append_message (EmpathyChatView *view,
TpMessage *tp_msg;
TpAccount *account;
gchar *body_escaped;
- const gchar *body;
const gchar *name;
const gchar *contact_id;
EmpathyAvatar *avatar;
@@ -832,9 +882,7 @@ theme_adium_append_message (EmpathyChatView *view,
gboolean action;
if (priv->pages_loading != 0) {
- GValue *value = tp_g_value_slice_new (EMPATHY_TYPE_MESSAGE);
- g_value_set_object (value, msg);
- g_queue_push_tail (&priv->message_queue, value);
+ queue_item (&priv->message_queue, QUEUED_MESSAGE, msg, NULL);
return;
}
@@ -846,8 +894,9 @@ theme_adium_append_message (EmpathyChatView *view,
if (service_name == NULL)
service_name = tp_account_get_protocol (account);
timestamp = empathy_message_get_timestamp (msg);
- body = empathy_message_get_body (msg);
- body_escaped = theme_adium_parse_body (theme, body);
+ body_escaped = theme_adium_parse_body (theme,
+ empathy_message_get_body (msg),
+ empathy_message_get_token (msg));
name = empathy_contact_get_alias (sender);
contact_id = empathy_contact_get_id (sender);
action = (empathy_message_get_tptype (msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION);
@@ -1005,8 +1054,7 @@ theme_adium_append_event (EmpathyChatView *view,
gchar *str_escaped;
if (priv->pages_loading != 0) {
- g_queue_push_tail (&priv->message_queue,
- tp_g_value_slice_new_string (str));
+ queue_item (&priv->message_queue, QUEUED_EVENT, NULL, str);
return;
}
@@ -1016,6 +1064,104 @@ theme_adium_append_event (EmpathyChatView *view,
}
static void
+theme_adium_edit_message (EmpathyChatView *view,
+ EmpathyMessage *message)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+ WebKitDOMDocument *doc;
+ WebKitDOMElement *span;
+ gchar *id, *parsed_body;
+ gchar *tooltip, *timestamp;
+ GtkIconInfo *icon_info;
+ GError *error = NULL;
+
+ if (priv->pages_loading != 0) {
+ queue_item (&priv->message_queue, QUEUED_EDIT, message, NULL);
+ return;
+ }
+
+ id = g_strdup_printf ("message-token-%s",
+ empathy_message_get_supersedes (message));
+ /* we don't pass a token here, because doing so will return another
+ * <span> element, and we don't want nested <span> elements */
+ parsed_body = theme_adium_parse_body (EMPATHY_THEME_ADIUM (view),
+ empathy_message_get_body (message), NULL);
+
+ /* find the element */
+ doc = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+ span = webkit_dom_document_get_element_by_id (doc, id);
+
+ if (span == NULL) {
+ DEBUG ("Failed to find id '%s'", id);
+ goto except;
+ }
+
+ if (!WEBKIT_DOM_IS_HTML_ELEMENT (span)) {
+ DEBUG ("Not a HTML element");
+ goto except;
+ }
+
+ /* update the HTML */
+ webkit_dom_html_element_set_inner_html (WEBKIT_DOM_HTML_ELEMENT (span),
+ parsed_body, &error);
+
+ if (error != NULL) {
+ DEBUG ("Error setting new inner-HTML: %s", error->message);
+ g_error_free (error);
+ goto except;
+ }
+
+ /* set a tooltip */
+ timestamp = empathy_time_to_string_local (
+ empathy_message_get_timestamp (message),
+ "%H:%M:%S");
+ tooltip = g_strdup_printf (_("Message edited at %s"), timestamp);
+
+ webkit_dom_html_element_set_title (WEBKIT_DOM_HTML_ELEMENT (span),
+ tooltip);
+
+ g_free (tooltip);
+ g_free (timestamp);
+
+ /* mark this message as edited */
+ icon_info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (),
+ EMPATHY_IMAGE_EDIT_MESSAGE, 16, 0);
+
+ if (icon_info != NULL) {
+ /* set the icon as a background image using CSS
+ * FIXME: the icon won't update in response to theme changes */
+ gchar *style = g_strdup_printf (
+ "background-image:url('%s');"
+ "background-repeat:no-repeat;"
+ "background-position:left center;"
+ "padding-left:19px;", /* 16px icon + 3px padding */
+ gtk_icon_info_get_filename (icon_info));
+
+ webkit_dom_element_set_attribute (span, "style", style, &error);
+
+ if (error != NULL) {
+ DEBUG ("Error setting element style: %s",
+ error->message);
+ g_clear_error (&error);
+ /* not fatal */
+ }
+
+ g_free (style);
+ gtk_icon_info_free (icon_info);
+ }
+
+ goto finally;
+
+except:
+ DEBUG ("Could not find message to edit with: %s",
+ empathy_message_get_body (message));
+
+finally:
+ g_free (id);
+ g_free (parsed_body);
+}
+
+static void
theme_adium_scroll (EmpathyChatView *view,
gboolean allow_scrolling)
{
@@ -1311,6 +1457,7 @@ theme_adium_iface_init (EmpathyChatViewIface *iface)
{
iface->append_message = theme_adium_append_message;
iface->append_event = theme_adium_append_event;
+ iface->edit_message = theme_adium_edit_message;
iface->scroll = theme_adium_scroll;
iface->scroll_down = theme_adium_scroll_down;
iface->get_has_selection = theme_adium_get_has_selection;
@@ -1341,18 +1488,26 @@ theme_adium_load_finished_cb (WebKitWebView *view,
/* Display queued messages */
for (l = priv->message_queue.head; l != NULL; l = l->next) {
- GValue *value = l->data;
+ QueuedItem *item = l->data;
- if (G_VALUE_HOLDS_OBJECT (value)) {
- theme_adium_append_message (chat_view,
- g_value_get_object (value));
- } else {
- theme_adium_append_event (chat_view,
- g_value_get_string (value));
+ switch (item->type)
+ {
+ case QUEUED_MESSAGE:
+ theme_adium_append_message (chat_view, item->msg);
+ break;
+
+ case QUEUED_EDIT:
+ theme_adium_edit_message (chat_view, item->msg);
+ break;
+
+ case QUEUED_EVENT:
+ theme_adium_append_event (chat_view, item->str);
+ break;
}
- tp_g_value_slice_free (value);
+ free_queued_item (item);
}
+
g_queue_clear (&priv->message_queue);
}