diff options
author | Danielle Madeley <danielle.madeley@collabora.co.uk> | 2011-08-18 08:10:00 +0800 |
---|---|---|
committer | Danielle Madeley <danielle.madeley@collabora.co.uk> | 2011-08-18 08:10:00 +0800 |
commit | 2021c145e0c5eb6aa9eda91d58d54b13007113ad (patch) | |
tree | ab6b5ba09764a785e8c06efae2f69dca111089be /libempathy-gtk | |
parent | d3e8563fe9b3d3c0b5ee5f225964b8078e18d1e6 (diff) | |
parent | dc7080f5071a9130bbd9288b50f807b41a5f9864 (diff) | |
download | gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar.gz gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar.bz2 gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar.lz gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar.xz gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.tar.zst gsoc2013-empathy-2021c145e0c5eb6aa9eda91d58d54b13007113ad.zip |
Merge branch 'log-window-webview'
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/Makefile.am | 30 | ||||
-rw-r--r-- | libempathy-gtk/empathy-log-window.c | 470 | ||||
-rw-r--r-- | libempathy-gtk/empathy-log-window.ui | 12 | ||||
-rw-r--r-- | libempathy-gtk/empathy-theme-adium.c | 267 | ||||
-rw-r--r-- | libempathy-gtk/empathy-theme-manager.c | 21 | ||||
-rw-r--r-- | libempathy-gtk/empathy-webkit-utils.c | 300 | ||||
-rw-r--r-- | libempathy-gtk/empathy-webkit-utils.h | 42 |
7 files changed, 713 insertions, 429 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index 2920a2a42..33dcbfb93 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -14,7 +14,6 @@ AM_CPPFLAGS = \ $(GEOCLUE_CFLAGS) \ $(GEOCODE_CFLAGS) \ $(MEEGO_CFLAGS) \ - $(WEBKIT_CFLAGS) \ $(CHEESE_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) @@ -89,7 +88,11 @@ libempathy_gtk_handwritten_source = \ empathy-theme-irc.c \ empathy-theme-manager.c \ empathy-tls-dialog.c \ - empathy-ui-utils.c + empathy-ui-utils.c \ + empathy-plist.c \ + empathy-theme-adium.c \ + empathy-webkit-utils.c \ + $(NULL) libempathy_gtk_headers = \ empathy-account-chooser.h \ @@ -152,7 +155,12 @@ libempathy_gtk_headers = \ empathy-theme-irc.h \ empathy-theme-manager.h \ empathy-tls-dialog.h \ - empathy-ui-utils.h + empathy-ui-utils.h \ + empathy-plist.h \ + empathy-theme-adium.h \ + empathy-webkit-utils.h \ + $(NULL) + libempathy_gtk_la_SOURCES = \ $(libempathy_gtk_handwritten_source) \ @@ -175,7 +183,6 @@ libempathy_gtk_la_LIBADD = \ $(GEOCODE_LIBS) \ $(GCR_LIBS) \ $(MEEGO_LIBS) \ - $(WEBKIT_LIBS) \ $(CHEESE_LIBS) \ $(top_builddir)/libempathy/libempathy.la @@ -278,21 +285,6 @@ EXTRA_DIST += \ empathy-location-manager.h endif -if HAVE_WEBKIT -libempathy_gtk_handwritten_source += \ - empathy-plist.c \ - empathy-theme-adium.c -libempathy_gtk_headers += \ - empathy-plist.h \ - empathy-theme-adium.h -else -EXTRA_DIST += \ - empathy-plist.c \ - empathy-plist.h \ - empathy-theme-adium.c \ - empathy-theme-adium.h -endif - CLEANFILES = \ $(BUILT_SOURCES) \ stamp-empathy-gtk-enum-types.h diff --git a/libempathy-gtk/empathy-log-window.c b/libempathy-gtk/empathy-log-window.c index 69f461a2b..5620f4b7c 100644 --- a/libempathy-gtk/empathy-log-window.c +++ b/libempathy-gtk/empathy-log-window.c @@ -29,6 +29,7 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> +#include <webkit/webkit.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/proxy-subclass.h> @@ -46,6 +47,7 @@ #include <libempathy/empathy-camera-monitor.h> #include <libempathy/empathy-chatroom-manager.h> #include <libempathy/empathy-chatroom.h> +#include <libempathy/empathy-gsettings.h> #include <libempathy/empathy-message.h> #include <libempathy/empathy-request-util.h> #include <libempathy/empathy-utils.h> @@ -59,10 +61,13 @@ #include "empathy-images.h" #include "empathy-theme-manager.h" #include "empathy-ui-utils.h" +#include "empathy-webkit-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include <libempathy/empathy-debug.h> +#define EMPATHY_NS "http://live.gnome.org/Empathy" + G_DEFINE_TYPE (EmpathyLogWindow, empathy_log_window, GTK_TYPE_WINDOW); struct _EmpathyLogWindowPriv @@ -82,7 +87,7 @@ struct _EmpathyLogWindowPriv GtkWidget *treeview_who; GtkWidget *treeview_what; GtkWidget *treeview_when; - GtkWidget *treeview_events; + GtkWidget *webview; GtkTreeStore *store_events; @@ -102,6 +107,7 @@ struct _EmpathyLogWindowPriv TpBaseClient *observer; EmpathyContact *selected_contact; + EmpathyContact *events_contact; EmpathyCameraMonitor *camera_monitor; GBinding *button_video_binding; @@ -117,6 +123,9 @@ struct _EmpathyLogWindowPriv TpAccount *selected_account; gchar *selected_chat_id; gboolean selected_is_chatroom; + + GSettings *gsettings_chat; + GSettings *gsettings_desktop; }; static void log_window_search_entry_changed_cb (GtkWidget *entry, @@ -144,6 +153,9 @@ static void log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem, static void start_spinner (void); static void log_window_create_observer (EmpathyLogWindow *window); +static gboolean log_window_events_button_press_event (GtkWidget *webview, + GdkEventButton *event, EmpathyLogWindow *self); +static void log_window_update_buttons_sensitivity (EmpathyLogWindow *self); static void empathy_account_chooser_filter_has_logs (TpAccount *account, @@ -360,6 +372,157 @@ toolbutton_av_clicked (GtkToolButton *toolbutton, TRUE, video, gtk_get_current_event_time ()); } +static void +insert_or_change_row (EmpathyLogWindow *self, + const char *method, + GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + char *str = gtk_tree_path_to_string (path); + char *script, *text, *date, *stock_icon; + char *icon = NULL; + + gtk_tree_model_get (model, iter, + COL_EVENTS_TEXT, &text, + COL_EVENTS_PRETTY_DATE, &date, + COL_EVENTS_ICON, &stock_icon, + -1); + + if (!tp_str_empty (stock_icon)) + { + GtkIconInfo *icon_info = gtk_icon_theme_lookup_icon ( + gtk_icon_theme_get_default (), + stock_icon, + GTK_ICON_SIZE_MENU, 0); + + if (icon_info != NULL) + icon = g_strdup (gtk_icon_info_get_filename (icon_info)); + + gtk_icon_info_free (icon_info); + } + + script = g_strdup_printf ("javascript:%s([%s], '%s', '%s', '%s');", + method, + g_strdelimit (str, ":", ','), + text, + icon != NULL ? icon : "", + date); + + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview), + script); + + g_free (str); + g_free (text); + g_free (date); + g_free (stock_icon); + g_free (icon); + g_free (script); +} + +static void +store_events_row_inserted (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + EmpathyLogWindow *self) +{ + insert_or_change_row (self, "insertRow", model, path, iter); +} + +static void +store_events_row_changed (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + EmpathyLogWindow *self) +{ + insert_or_change_row (self, "changeRow", model, path, iter); +} + +static void +store_events_row_deleted (GtkTreeModel *model, + GtkTreePath *path, + EmpathyLogWindow *self) +{ + char *str = gtk_tree_path_to_string (path); + char *script; + + script = g_strdup_printf ("javascript:deleteRow([%s]);", + g_strdelimit (str, ":", ',')); + + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview), + script); + + g_free (str); + g_free (script); +} + +static void +store_events_has_child_rows (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + EmpathyLogWindow *self) +{ + char *str = gtk_tree_path_to_string (path); + char *script; + + script = g_strdup_printf ("javascript:hasChildRows([%s], %u);", + g_strdelimit (str, ":", ','), + gtk_tree_model_iter_has_child (model, iter)); + + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview), + script); + + g_free (str); + g_free (script); +} + +static void +store_events_rows_reordered (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + int *new_order, + EmpathyLogWindow *self) +{ + char *str = gtk_tree_path_to_string (path); + int i, children = gtk_tree_model_iter_n_children (model, iter); + char **new_order_strv, *new_order_s; + char *script; + + new_order_strv = g_new0 (char *, children + 1); + + for (i = 0; i < children; i++) + new_order_strv[i] = g_strdup_printf ("%i", new_order[i]); + + new_order_s = g_strjoinv (",", new_order_strv); + + script = g_strdup_printf ("javascript:reorderRows([%s], [%s]);", + str == NULL ? "" : g_strdelimit (str, ":", ','), + new_order_s); + + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview), + script); + + g_free (str); + g_free (script); + g_free (new_order_s); + g_strfreev (new_order_strv); +} + +static gboolean +events_webview_handle_navigation (WebKitWebView *webview, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision *policy_decision, + EmpathyLogWindow *window) +{ + empathy_url_show (GTK_WIDGET (webview), + webkit_network_request_get_uri (request)); + + webkit_web_policy_decision_ignore (policy_decision); + return TRUE; +} + static GObject * empathy_log_window_constructor (GType type, guint n_props, @@ -408,8 +571,14 @@ empathy_log_window_dispose (GObject *object) tp_clear_object (&self->priv->log_manager); tp_clear_object (&self->priv->selected_account); tp_clear_object (&self->priv->selected_contact); + tp_clear_object (&self->priv->events_contact); tp_clear_object (&self->priv->camera_monitor); + tp_clear_object (&self->priv->gsettings_chat); + tp_clear_object (&self->priv->gsettings_desktop); + + tp_clear_object (&self->priv->store_events); + G_OBJECT_CLASS (empathy_log_window_parent_class)->dispose (object); } @@ -444,7 +613,9 @@ empathy_log_window_init (EmpathyLogWindow *self) EmpathyAccountChooser *account_chooser; GtkBuilder *gui; gchar *filename; + GFile *gfile; GtkWidget *vbox, *accounts, *search, *label, *quit; + GtkWidget *scrolledwindow_events; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_LOG_WINDOW, EmpathyLogWindowPriv); @@ -455,6 +626,10 @@ empathy_log_window_init (EmpathyLogWindow *self) self->priv->log_manager = tpl_log_manager_dup_singleton (); + self->priv->gsettings_chat = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA); + self->priv->gsettings_desktop = g_settings_new ( + EMPATHY_PREFS_DESKTOP_INTERFACE_SCHEMA); + gtk_window_set_title (GTK_WINDOW (self), _("History")); gtk_widget_set_can_focus (GTK_WIDGET (self), FALSE); gtk_window_set_default_size (GTK_WINDOW (self), 800, 600); @@ -472,7 +647,7 @@ empathy_log_window_init (EmpathyLogWindow *self) "treeview_who", &self->priv->treeview_who, "treeview_what", &self->priv->treeview_what, "treeview_when", &self->priv->treeview_when, - "treeview_events", &self->priv->treeview_events, + "scrolledwindow_events", &scrolledwindow_events, "notebook", &self->priv->notebook, "spinner", &self->priv->spinner, NULL); @@ -564,6 +739,47 @@ empathy_log_window_init (EmpathyLogWindow *self) log_window_who_populate (self); + /* events */ + self->priv->webview = webkit_web_view_new (); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_events), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (scrolledwindow_events), + self->priv->webview); + gtk_widget_show (self->priv->webview); + + empathy_webkit_bind_font_setting (WEBKIT_WEB_VIEW (self->priv->webview), + self->priv->gsettings_desktop, + EMPATHY_PREFS_DESKTOP_INTERFACE_FONT_NAME); + + filename = empathy_file_lookup ("empathy-log-window.html", "data"); + gfile = g_file_new_for_path (filename); + g_free (filename); + + webkit_web_view_load_uri (WEBKIT_WEB_VIEW (self->priv->webview), + g_file_get_uri (gfile)); + g_object_unref (gfile); + + /* handle all navigation externally */ + g_signal_connect (self->priv->webview, "navigation-policy-decision-requested", + G_CALLBACK (events_webview_handle_navigation), self); + + /* listen to changes to the treemodel */ + g_signal_connect (self->priv->store_events, "row-inserted", + G_CALLBACK (store_events_row_inserted), self); + g_signal_connect (self->priv->store_events, "row-changed", + G_CALLBACK (store_events_row_changed), self); + g_signal_connect (self->priv->store_events, "row-deleted", + G_CALLBACK (store_events_row_deleted), self); + g_signal_connect (self->priv->store_events, "rows-reordered", + G_CALLBACK (store_events_rows_reordered), self); + g_signal_connect (self->priv->store_events, "row-has-child-toggled", + G_CALLBACK (store_events_has_child_rows), self); + + /* track clicked row */ + g_signal_connect (self->priv->webview, "button-press-event", + G_CALLBACK (log_window_events_button_press_event), self); + + log_window_update_buttons_sensitivity (self); gtk_widget_show (GTK_WIDGET (self)); } @@ -1056,8 +1272,10 @@ log_window_append_chat_message (TplEvent *event, { GtkTreeStore *store = log_window->priv->store_events; GtkTreeIter iter, parent; - gchar *pretty_date, *alias, *body, *msg; + gchar *pretty_date, *alias, *body; GDateTime *date; + EmpathyStringParser *parsers; + GString *msg; date = g_date_time_new_from_unix_utc ( tpl_event_get_timestamp (event)); @@ -1066,62 +1284,29 @@ log_window_append_chat_message (TplEvent *event, get_parent_iter_for_message (event, message, &parent); - msg = g_markup_escape_text (empathy_message_get_body (message), -1); alias = g_markup_escape_text ( tpl_entity_get_alias (tpl_event_get_sender (event)), -1); - /* If the user is searching, highlight the matched text */ - if (!EMP_STR_EMPTY (log_window->priv->last_find)) - { - gchar *str = g_regex_escape_string (log_window->priv->last_find, -1); - gchar *replacement = g_markup_printf_escaped ( - "<span background=\"yellow\">%s</span>", - log_window->priv->last_find); - GError *error = NULL; - GRegex *regex = g_regex_new (str, 0, 0, &error); + /* escape the text */ + parsers = empathy_webkit_get_string_parser ( + g_settings_get_boolean (log_window->priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SHOW_SMILEYS)); + msg = g_string_new (""); - if (regex == NULL) - { - DEBUG ("Could not create regex: %s", error->message); - g_error_free (error); - } - else - { - gchar *new_msg = g_regex_replace_literal (regex, - empathy_message_get_body (message), -1, 0, replacement, - 0, &error); - - if (new_msg != NULL) - { - /* We pass ownership of new_msg to msg, which is freed later */ - g_free (msg); - msg = new_msg; - } - else - { - DEBUG ("Error while performing string substitution: %s", - error->message); - g_error_free (error); - } - } - - g_free (str); - g_free (replacement); - - tp_clear_pointer (®ex, g_regex_unref); - } + empathy_string_parser_substr (empathy_message_get_body (message), -1, + parsers, msg); if (tpl_text_event_get_message_type (TPL_TEXT_EVENT (event)) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) { /* Translators: this is an emote: '* Danielle waves' */ - body = g_strdup_printf (_("<i>* %s %s</i>"), alias, msg); + body = g_strdup_printf (_("<i>* %s %s</i>"), alias, msg->str); } else { /* Translators: this is a message: 'Danielle: hello' * The string in bold is the sender's name */ - body = g_strdup_printf (_("<b>%s:</b> %s"), alias, msg); + body = g_strdup_printf (_("<b>%s:</b> %s"), alias, msg->str); } gtk_tree_store_append (store, &iter, &parent); @@ -1135,7 +1320,7 @@ log_window_append_chat_message (TplEvent *event, COL_EVENTS_EVENT, event, -1); - g_free (msg); + g_string_free (msg, TRUE); g_free (body); g_free (alias); g_free (pretty_date); @@ -1784,6 +1969,8 @@ log_window_find_populate (EmpathyLogWindow *self, if (EMP_STR_EMPTY (search_criteria)) { tp_clear_pointer (&self->priv->hits, tpl_log_manager_search_free); + webkit_web_view_set_highlight_text_matches ( + WEBKIT_WEB_VIEW (self->priv->webview), FALSE); log_window_who_populate (self); return; } @@ -1792,6 +1979,10 @@ log_window_find_populate (EmpathyLogWindow *self, log_window_when_changed_cb, self); + /* highlight the search text */ + webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (self->priv->webview), + search_criteria, FALSE, 0); + tpl_log_manager_search_async (self->priv->log_manager, search_criteria, TPL_EVENT_MASK_ANY, log_manager_searched_new_cb, NULL); @@ -1860,8 +2051,10 @@ log_window_update_buttons_sensitivity (EmpathyLogWindow *self) GtkTreePath *path; gboolean profile, chat, call, video; - tp_clear_object (&self->priv->selected_contact); + profile = chat = call = video = FALSE; + tp_clear_object (&self->priv->button_video_binding); + tp_clear_object (&self->priv->selected_contact); view = GTK_TREE_VIEW (self->priv->treeview_who); model = gtk_tree_view_get_model (view); @@ -1908,27 +2101,12 @@ log_window_update_buttons_sensitivity (EmpathyLogWindow *self) /* If the Who pane doesn't contain a contact (e.g. it has many * selected, or has 'Anyone', let's try to get the contact from * the selected event. */ - view = GTK_TREE_VIEW (self->priv->treeview_events); - model = gtk_tree_view_get_model (view); - selection = gtk_tree_view_get_selection (view); - if (gtk_tree_selection_count_selected_rows (selection) != 1) - goto out; - - if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) + if (self->priv->events_contact != NULL) + self->priv->selected_contact = g_object_ref (self->priv->events_contact); + else goto out; - gtk_tree_model_get (model, &iter, - COL_EVENTS_ACCOUNT, &account, - COL_EVENTS_TARGET, &target, - -1); - - self->priv->selected_contact = empathy_contact_from_tpl_contact (account, - target); - - g_object_unref (account); - g_object_unref (target); - capabilities = empathy_contact_get_capabilities (self->priv->selected_contact); profile = chat = TRUE; @@ -2325,39 +2503,95 @@ who_row_is_separator (GtkTreeModel *model, } static void -log_window_events_changed_cb (GtkTreeSelection *selection, - EmpathyLogWindow *self) +log_window_find_row (EmpathyLogWindow *self, + GdkEventButton *event) { - DEBUG ("log_window_events_changed_cb"); + WebKitHitTestResult *hit = webkit_web_view_get_hit_test_result ( + WEBKIT_WEB_VIEW (self->priv->webview), event); + WebKitDOMNode *inner_node; + + tp_clear_object (&self->priv->events_contact); + + g_object_get (hit, + "inner-node", &inner_node, + NULL); + + if (inner_node != NULL) + { + GtkTreeModel *model = GTK_TREE_MODEL (self->priv->store_events); + WebKitDOMNode *node; + const char *path = NULL; + GtkTreeIter iter; + + /* walk back up the DOM tree looking for a node with empathy:path set */ + for (node = inner_node; node != NULL; + node = webkit_dom_node_get_parent_node (node)) + { + if (!WEBKIT_DOM_IS_ELEMENT (node)) + continue; + + path = webkit_dom_element_get_attribute_ns ( + WEBKIT_DOM_ELEMENT (node), EMPATHY_NS, "path"); + + if (!tp_str_empty (path)) + break; + } + + /* look up the contact for this path */ + if (!tp_str_empty (path) && + gtk_tree_model_get_iter_from_string (model, &iter, path)) + { + TpAccount *account; + TplEntity *target; + + gtk_tree_model_get (model, &iter, + COL_EVENTS_ACCOUNT, &account, + COL_EVENTS_TARGET, &target, + -1); + + self->priv->events_contact = empathy_contact_from_tpl_contact ( + account, target); + + g_object_unref (account); + g_object_unref (target); + } + + g_object_unref (inner_node); + } + + g_object_unref (hit); log_window_update_buttons_sensitivity (self); } -static void -log_window_events_row_activated_cb (GtkTreeView *view, - GtkTreePath *path, - GtkTreeViewColumn *column, +static gboolean +log_window_events_button_press_event (GtkWidget *webview, + GdkEventButton *event, EmpathyLogWindow *self) { - if (gtk_tree_view_row_expanded (view, path)) - gtk_tree_view_collapse_row (view, path); - else - gtk_tree_view_expand_row (view, path, FALSE); + switch (event->button) + { + case 1: + log_window_find_row (self, event); + break; + + case 3: + empathy_webkit_context_menu_for_event ( + WEBKIT_WEB_VIEW (webview), event, 0); + return TRUE; + + default: + break; + } + + return FALSE; } static void log_window_events_setup (EmpathyLogWindow *self) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; GtkTreeSortable *sortable; - GtkTreeViewColumn *column; GtkTreeStore *store; - GtkCellRenderer *cell; - - view = GTK_TREE_VIEW (self->priv->treeview_events); - selection = gtk_tree_view_get_selection (view); /* new store */ self->priv->store_events = store = gtk_tree_store_new (COL_EVENTS_COUNT, @@ -2370,52 +2604,11 @@ log_window_events_setup (EmpathyLogWindow *self) TPL_TYPE_ENTITY, /* target */ TPL_TYPE_EVENT); /* event */ - model = GTK_TREE_MODEL (store); sortable = GTK_TREE_SORTABLE (store); - gtk_tree_view_set_model (view, model); - - /* new column */ - column = gtk_tree_view_column_new (); - - cell = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, cell, FALSE); - gtk_tree_view_column_add_attribute (column, cell, - "icon-name", COL_EVENTS_ICON); - - cell = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, - "markup", COL_EVENTS_TEXT); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, "xalign", 1.0, NULL); - gtk_tree_view_column_pack_end (column, cell, FALSE); - gtk_tree_view_column_add_attribute (column, cell, - "text", COL_EVENTS_PRETTY_DATE); - - gtk_tree_view_append_column (view, column); - - /* set up treeview properties */ - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - gtk_tree_view_set_headers_visible (view, FALSE); - gtk_tree_sortable_set_sort_column_id (sortable, COL_EVENTS_TS, GTK_SORT_ASCENDING); - - gtk_tree_view_set_enable_search (view, FALSE); - - /* set up signals */ - g_signal_connect (selection, "changed", - G_CALLBACK (log_window_events_changed_cb), - self); - - g_signal_connect (view, "row-activated", - G_CALLBACK (log_window_events_row_activated_cb), - self); - - g_object_unref (store); } static void @@ -2875,15 +3068,13 @@ log_window_what_setup (EmpathyLogWindow *self) static void log_window_maybe_expand_events (void) { - GtkTreeView *view; - GtkTreeModel *model; - - view = GTK_TREE_VIEW (log_window->priv->treeview_events); - model = gtk_tree_view_get_model (view); + GtkTreeModel *model = GTK_TREE_MODEL (log_window->priv->store_events); /* If there's only one result, expand it */ if (gtk_tree_model_iter_n_children (model, NULL) == 1) - gtk_tree_view_expand_all (view); + webkit_web_view_execute_script ( + WEBKIT_WEB_VIEW (log_window->priv->webview), + "javascript:expandAll()"); } static gboolean @@ -2932,7 +3123,6 @@ log_window_got_messages_for_date_cb (GObject *manager, gpointer user_data) { Ctx *ctx = user_data; - GtkTreeView *view; GtkTreeModel *model; GtkTreeIter iter; GList *events; @@ -3012,17 +3202,27 @@ log_window_got_messages_for_date_cb (GObject *manager, } g_list_free (events); - view = GTK_TREE_VIEW (log_window->priv->treeview_events); - model = gtk_tree_view_get_model (view); + model = GTK_TREE_MODEL (log_window->priv->store_events); n = gtk_tree_model_iter_n_children (model, NULL) - 1; if (n >= 0 && gtk_tree_model_iter_nth_child (model, &iter, NULL, n)) { GtkTreePath *path; + char *str, *script; path = gtk_tree_model_get_path (model, &iter); - gtk_tree_view_scroll_to_cell (view, path, NULL, FALSE, 0, 0); + str = gtk_tree_path_to_string (path); + + script = g_strdup_printf ("javascript:scrollToRow([%s]);", + g_strdelimit (str, ":", ',')); + + webkit_web_view_execute_script ( + WEBKIT_WEB_VIEW (log_window->priv->webview), + script); + gtk_tree_path_free (path); + g_free (str); + g_free (script); } out: diff --git a/libempathy-gtk/empathy-log-window.ui b/libempathy-gtk/empathy-log-window.ui index b07e42da5..08af5b65b 100644 --- a/libempathy-gtk/empathy-log-window.ui +++ b/libempathy-gtk/empathy-log-window.ui @@ -69,6 +69,9 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="toolbar_style">both</property> + <style> + <class name="primary-toolbar"/> + </style> <child> <object class="GtkToolButton" id="toolbutton_profile"> <property name="visible">True</property> @@ -270,15 +273,6 @@ <object class="GtkScrolledWindow" id="scrolledwindow_events"> <property name="visible">True</property> <property name="can_focus">True</property> - <child> - <object class="GtkTreeView" id="treeview_events"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection4"/> - </child> - </object> - </child> </object> </child> <child type="tab"> diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c index 14e149e18..4e32630d5 100644 --- a/libempathy-gtk/empathy-theme-adium.c +++ b/libempathy-gtk/empathy-theme-adium.c @@ -39,8 +39,8 @@ #include "empathy-smiley-manager.h" #include "empathy-ui-utils.h" #include "empathy-plist.h" -#include "empathy-string-parser.h" #include "empathy-images.h" +#include "empathy-webkit-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_CHAT #include <libempathy/empathy-debug.h> @@ -65,7 +65,10 @@ typedef struct { * marker for when we lose focus. */ GQueue acked_messages; GtkWidget *inspector_window; + GSettings *gsettings_chat; + GSettings *gsettings_desktop; + gboolean has_focus; gboolean has_unread_message; gboolean allow_scrolling; @@ -209,39 +212,6 @@ theme_adium_navigation_policy_decision_requested_cb (WebKitWebView * return TRUE; } -static void -theme_adium_copy_address_cb (GtkMenuItem *menuitem, - gpointer user_data) -{ - WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); - gchar *uri; - GtkClipboard *clipboard; - - g_object_get (G_OBJECT (hit_test_result), "link-uri", &uri, NULL); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - gtk_clipboard_set_text (clipboard, uri, -1); - - clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); - gtk_clipboard_set_text (clipboard, uri, -1); - - g_free (uri); -} - -static void -theme_adium_open_address_cb (GtkMenuItem *menuitem, - gpointer user_data) -{ - WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); - gchar *uri; - - g_object_get (G_OBJECT (hit_test_result), "link-uri", &uri, NULL); - - empathy_url_show (GTK_WIDGET (menuitem), uri); - - g_free (uri); -} - /* Replace each %@ in format with string passed in args */ static gchar * string_with_format (const gchar *format, @@ -293,65 +263,6 @@ theme_adium_load_template (EmpathyThemeAdium *theme) g_free (template); } -static void -theme_adium_match_newline (const gchar *text, - gssize len, - EmpathyStringReplace replace_func, - EmpathyStringParser *sub_parsers, - gpointer user_data) -{ - GString *string = user_data; - gint i; - gint prev = 0; - - if (len < 0) { - len = G_MAXSSIZE; - } - - /* Replace \n by <br/> */ - for (i = 0; i < len && text[i] != '\0'; i++) { - if (text[i] == '\n') { - empathy_string_parser_substr (text + prev, - i - prev, sub_parsers, - user_data); - g_string_append (string, "<br/>"); - prev = i + 1; - } - } - empathy_string_parser_substr (text + prev, i - prev, - sub_parsers, user_data); -} - -static void -theme_adium_replace_smiley (const gchar *text, - gssize len, - gpointer match_data, - gpointer user_data) -{ - EmpathySmileyHit *hit = match_data; - GString *string = user_data; - - /* Replace smiley by a <img/> tag */ - g_string_append_printf (string, - "<img src=\"%s\" alt=\"%.*s\" title=\"%.*s\"/>", - hit->path, (int)len, text, (int)len, text); -} - -static EmpathyStringParser string_parsers[] = { - {empathy_string_match_link, empathy_string_replace_link}, - {theme_adium_match_newline, NULL}, - {empathy_string_match_all, empathy_string_replace_escaped}, - {NULL, NULL} -}; - -static EmpathyStringParser string_parsers_with_smiley[] = { - {empathy_string_match_link, empathy_string_replace_link}, - {empathy_string_match_smiley, theme_adium_replace_smiley}, - {theme_adium_match_newline, NULL}, - {empathy_string_match_all, empathy_string_replace_escaped}, - {NULL, NULL} -}; - static gchar * theme_adium_parse_body (EmpathyThemeAdium *self, const gchar *text, @@ -362,11 +273,9 @@ theme_adium_parse_body (EmpathyThemeAdium *self, GString *string; /* Check if we have to parse smileys */ - if (g_settings_get_boolean (priv->gsettings_chat, - EMPATHY_PREFS_CHAT_SHOW_SMILEYS)) - parsers = string_parsers_with_smiley; - else - parsers = string_parsers; + parsers = empathy_webkit_get_string_parser ( + g_settings_get_boolean (priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SHOW_SMILEYS)); /* Parse text and construct string with links and smileys replaced * by html tags. Also escape text to make sure html code is @@ -1354,90 +1263,6 @@ theme_adium_message_acknowledged (EmpathyChatView *view, theme_adium_remove_mark_from_message (self, id); } -static void -theme_adium_context_menu_selection_done_cb (GtkMenuShell *menu, gpointer user_data) -{ - WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); - - g_object_unref (hit_test_result); -} - -static void -theme_adium_context_menu_for_event (EmpathyThemeAdium *theme, GdkEventButton *event) -{ - WebKitWebView *view = WEBKIT_WEB_VIEW (theme); - WebKitHitTestResult *hit_test_result; - WebKitHitTestResultContext context; - GtkWidget *menu; - GtkWidget *item; - - hit_test_result = webkit_web_view_get_hit_test_result (view, event); - g_object_get (G_OBJECT (hit_test_result), "context", &context, NULL); - - /* The menu */ - menu = empathy_context_menu_new (GTK_WIDGET (view)); - - /* Select all item */ - item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - g_signal_connect_swapped (item, "activate", - G_CALLBACK (webkit_web_view_select_all), - view); - - /* Copy menu item */ - if (webkit_web_view_can_copy_clipboard (view)) { - item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - g_signal_connect_swapped (item, "activate", - G_CALLBACK (webkit_web_view_copy_clipboard), - view); - } - - /* Clear menu item */ - item = gtk_separator_menu_item_new (); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - g_signal_connect_swapped (item, "activate", - G_CALLBACK (empathy_chat_view_clear), - view); - - /* We will only add the following menu items if we are - * right-clicking a link */ - if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) { - /* Separator */ - item = gtk_separator_menu_item_new (); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - /* Copy Link Address menu item */ - item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address")); - g_signal_connect (item, "activate", - G_CALLBACK (theme_adium_copy_address_cb), - hit_test_result); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - - /* Open Link menu item */ - item = gtk_menu_item_new_with_mnemonic (_("_Open Link")); - g_signal_connect (item, "activate", - G_CALLBACK (theme_adium_open_address_cb), - hit_test_result); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); - } - - g_signal_connect (GTK_MENU_SHELL (menu), "selection-done", - G_CALLBACK (theme_adium_context_menu_selection_done_cb), - hit_test_result); - - /* Display the menu */ - gtk_widget_show_all (menu); - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, - event->button, event->time); -} - static gboolean theme_adium_button_press_event (GtkWidget *widget, GdkEventButton *event) { @@ -1451,7 +1276,9 @@ theme_adium_button_press_event (GtkWidget *widget, GdkEventButton *event) * item ourselves, so we disable our customized menu * if the developer extras are enabled. */ if (!developer_tools_enabled) { - theme_adium_context_menu_for_event (EMPATHY_THEME_ADIUM (widget), event); + empathy_webkit_context_menu_for_event ( + WEBKIT_WEB_VIEW (widget), event, + EMPATHY_WEBKIT_MENU_CLEAR); return TRUE; } } @@ -1524,7 +1351,9 @@ theme_adium_finalize (GObject *object) EmpathyThemeAdiumPriv *priv = GET_PRIV (object); empathy_adium_data_unref (priv->data); + g_object_unref (priv->gsettings_chat); + g_object_unref (priv->gsettings_desktop); G_OBJECT_CLASS (empathy_theme_adium_parent_class)->finalize (object); } @@ -1621,64 +1450,6 @@ theme_adium_inspect_web_view_cb (WebKitWebInspector *inspector, return NULL; } -static PangoFontDescription * -theme_adium_get_default_font (void) -{ - GSettings *gsettings; - PangoFontDescription *pango_fd; - gchar *font_family; - - gsettings = g_settings_new (EMPATHY_PREFS_DESKTOP_INTERFACE_SCHEMA); - - font_family = g_settings_get_string (gsettings, - EMPATHY_PREFS_DESKTOP_INTERFACE_DOCUMENT_FONT_NAME); - - if (font_family == NULL) - return NULL; - - pango_fd = pango_font_description_from_string (font_family); - g_free (font_family); - g_object_unref (gsettings); - return pango_fd; -} - -static void -theme_adium_set_webkit_font (WebKitWebSettings *w_settings, - const gchar *name, - gint size) -{ - g_object_set (w_settings, "default-font-family", name, NULL); - g_object_set (w_settings, "default-font-size", size, NULL); -} - -static void -theme_adium_set_default_font (WebKitWebSettings *w_settings) -{ - PangoFontDescription *default_font_desc; - GdkScreen *current_screen; - gdouble dpi = 0; - gint pango_font_size = 0; - - default_font_desc = theme_adium_get_default_font (); - if (default_font_desc == NULL) - return ; - pango_font_size = pango_font_description_get_size (default_font_desc) - / PANGO_SCALE ; - if (pango_font_description_get_size_is_absolute (default_font_desc)) { - current_screen = gdk_screen_get_default (); - if (current_screen != NULL) { - dpi = gdk_screen_get_resolution (current_screen); - } else { - dpi = BORING_DPI_DEFAULT; - } - pango_font_size = (gint) (pango_font_size / (dpi / 72)); - } - theme_adium_set_webkit_font (w_settings, - pango_font_description_get_family (default_font_desc), - pango_font_size); - pango_font_description_free (default_font_desc); -} - static void theme_adium_constructed (GObject *object) { @@ -1686,18 +1457,21 @@ theme_adium_constructed (GObject *object) const gchar *font_family = NULL; gint font_size = 0; WebKitWebView *webkit_view = WEBKIT_WEB_VIEW (object); - WebKitWebSettings *webkit_settings; WebKitWebInspector *webkit_inspector; /* Set default settings */ font_family = tp_asv_get_string (priv->data->info, "DefaultFontFamily"); font_size = tp_asv_get_int32 (priv->data->info, "DefaultFontSize", NULL); - webkit_settings = webkit_web_view_get_settings (webkit_view); if (font_family && font_size) { - theme_adium_set_webkit_font (webkit_settings, font_family, font_size); + g_object_set (webkit_web_view_get_settings (webkit_view), + "default-font-family", font_family, + "default-font-size", font_size, + NULL); } else { - theme_adium_set_default_font (webkit_settings); + empathy_webkit_bind_font_setting (webkit_view, + priv->gsettings_desktop, + EMPATHY_PREFS_DESKTOP_INTERFACE_DOCUMENT_FONT_NAME); } /* Setup webkit inspector */ @@ -1819,6 +1593,9 @@ empathy_theme_adium_init (EmpathyThemeAdium *theme) NULL); priv->gsettings_chat = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA); + priv->gsettings_desktop = g_settings_new ( + EMPATHY_PREFS_DESKTOP_INTERFACE_SCHEMA); + g_signal_connect (priv->gsettings_chat, "changed::" EMPATHY_PREFS_CHAT_WEBKIT_DEVELOPER_TOOLS, G_CALLBACK (theme_adium_notify_enable_webkit_developer_tools_cb), diff --git a/libempathy-gtk/empathy-theme-manager.c b/libempathy-gtk/empathy-theme-manager.c index 2a6c393f2..c771392b9 100644 --- a/libempathy-gtk/empathy-theme-manager.c +++ b/libempathy-gtk/empathy-theme-manager.c @@ -39,10 +39,7 @@ #include "empathy-chat-text-view.h" #include "empathy-theme-boxes.h" #include "empathy-theme-irc.h" - -#ifdef HAVE_WEBKIT #include "empathy-theme-adium.h" -#endif #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include <libempathy/empathy-debug.h> @@ -56,12 +53,10 @@ typedef struct { guint emit_changed_idle; gboolean in_constructor; -#ifdef HAVE_WEBKIT EmpathyAdiumData *adium_data; gchar *adium_variant; /* list of weakref to EmpathyThemeAdium objects */ GList *adium_views; -#endif } EmpathyThemeManagerPriv; enum { @@ -85,7 +80,6 @@ static gboolean theme_manager_emit_changed_idle_cb (gpointer manager) { EmpathyThemeManagerPriv *priv = GET_PRIV (manager); -#ifdef HAVE_WEBKIT const gchar *adium_path = NULL; if (priv->adium_data) { @@ -94,7 +88,6 @@ theme_manager_emit_changed_idle_cb (gpointer manager) DEBUG ("Emit theme-changed with: name='%s' adium_path='%s' " "adium_variant='%s'", priv->name, adium_path, priv->adium_variant); -#endif /* HAVE_WEBKIT */ g_signal_emit (manager, signals[THEME_CHANGED], 0, NULL); priv->emit_changed_idle = 0; @@ -371,7 +364,6 @@ theme_manager_update_boxes_theme (EmpathyThemeManager *manager, } } -#ifdef HAVE_WEBKIT static EmpathyThemeAdium * theme_manager_create_adium_view (EmpathyThemeManager *manager) { @@ -451,7 +443,6 @@ theme_manager_notify_adium_variant_cb (GSettings *gsettings_chat, priv->adium_variant); } } -#endif /* HAVE_WEBKIT */ EmpathyChatView * empathy_theme_manager_create_view (EmpathyThemeManager *manager) @@ -463,11 +454,9 @@ empathy_theme_manager_create_view (EmpathyThemeManager *manager) DEBUG ("Using theme %s", priv->name); -#ifdef HAVE_WEBKIT if (strcmp (priv->name, "adium") == 0 && priv->adium_data != NULL) { return EMPATHY_CHAT_VIEW (theme_manager_create_adium_view (manager)); } -#endif if (strcmp (priv->name, "classic") == 0) { return EMPATHY_CHAT_VIEW (theme_manager_create_irc_view (manager)); @@ -583,11 +572,9 @@ theme_manager_finalize (GObject *object) clear_list_of_views (&priv->boxes_views); -#ifdef HAVE_WEBKIT clear_list_of_views (&priv->adium_views); g_free (priv->adium_variant); tp_clear_pointer (&priv->adium_data, empathy_adium_data_unref); -#endif G_OBJECT_CLASS (empathy_theme_manager_parent_class)->finalize (object); } @@ -632,7 +619,6 @@ empathy_theme_manager_init (EmpathyThemeManager *manager) EMPATHY_PREFS_CHAT_THEME, manager); -#ifdef HAVE_WEBKIT /* Take the adium path/variant and track changes */ g_signal_connect (priv->gsettings_chat, "changed::" EMPATHY_PREFS_CHAT_ADIUM_PATH, @@ -649,7 +635,6 @@ empathy_theme_manager_init (EmpathyThemeManager *manager) theme_manager_notify_adium_variant_cb (priv->gsettings_chat, EMPATHY_PREFS_CHAT_THEME_VARIANT, manager); -#endif priv->in_constructor = FALSE; } @@ -674,7 +659,6 @@ empathy_theme_manager_get_themes (void) return themes; } -#ifdef HAVE_WEBKIT static void find_themes (GList **list, const gchar *dirpath) { @@ -705,12 +689,10 @@ find_themes (GList **list, const gchar *dirpath) g_error_free (error); } } -#endif /* HAVE_WEBKIT */ GList * empathy_theme_manager_get_adium_themes (void) { -#ifdef HAVE_WEBKIT GList *themes_list = NULL; gchar *userpath = NULL; const gchar *const *paths = NULL; @@ -729,7 +711,4 @@ empathy_theme_manager_get_adium_themes (void) } return themes_list; -#else - return NULL; -#endif /* HAVE_WEBKIT */ } diff --git a/libempathy-gtk/empathy-webkit-utils.c b/libempathy-gtk/empathy-webkit-utils.c new file mode 100644 index 000000000..cac9af9d8 --- /dev/null +++ b/libempathy-gtk/empathy-webkit-utils.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2008-2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Xavier Claessens <xclaesse@gmail.com> + */ + +#include "config.h" + +#include <glib/gi18n.h> + +#include "empathy-webkit-utils.h" +#include "empathy-smiley-manager.h" +#include "empathy-ui-utils.h" + +#define BORING_DPI_DEFAULT 96 + +static void +empathy_webkit_match_newline (const gchar *text, + gssize len, + EmpathyStringReplace replace_func, + EmpathyStringParser *sub_parsers, + gpointer user_data) +{ + GString *string = user_data; + gint i; + gint prev = 0; + + if (len < 0) + len = G_MAXSSIZE; + + /* Replace \n by <br/> */ + for (i = 0; i < len && text[i] != '\0'; i++) + { + if (text[i] == '\n') + { + empathy_string_parser_substr (text + prev, i - prev, + sub_parsers, user_data); + g_string_append (string, "<br/>"); + prev = i + 1; + } + } + + empathy_string_parser_substr (text + prev, i - prev, + sub_parsers, user_data); +} + +static void +empathy_webkit_replace_smiley (const gchar *text, + gssize len, + gpointer match_data, + gpointer user_data) +{ + EmpathySmileyHit *hit = match_data; + GString *string = user_data; + + /* Replace smiley by a <img/> tag */ + g_string_append_printf (string, + "<img src=\"%s\" alt=\"%.*s\" title=\"%.*s\"/>", + hit->path, (int)len, text, (int)len, text); +} + +static EmpathyStringParser string_parsers[] = { + { empathy_string_match_link, empathy_string_replace_link }, + { empathy_webkit_match_newline, NULL }, + { empathy_string_match_all, empathy_string_replace_escaped }, + { NULL, NULL} +}; + +static EmpathyStringParser string_parsers_with_smiley[] = { + { empathy_string_match_link, empathy_string_replace_link }, + { empathy_string_match_smiley, empathy_webkit_replace_smiley }, + { empathy_webkit_match_newline, NULL }, + { empathy_string_match_all, empathy_string_replace_escaped }, + { NULL, NULL } +}; + +EmpathyStringParser * +empathy_webkit_get_string_parser (gboolean smileys) +{ + if (smileys) + return string_parsers_with_smiley; + else + return string_parsers; +} + +static gboolean +webkit_get_font_family (GValue *value, + GVariant *variant, + gpointer user_data) +{ + PangoFontDescription *font = pango_font_description_from_string ( + g_variant_get_string (variant, NULL)); + + if (font == NULL) + return FALSE; + + g_value_set_string (value, pango_font_description_get_family (font)); + pango_font_description_free (font); + + return TRUE; +} + +static gboolean +webkit_get_font_size (GValue *value, + GVariant *variant, + gpointer user_data) +{ + PangoFontDescription *font = pango_font_description_from_string ( + g_variant_get_string (variant, NULL)); + int size; + + if (font == NULL) + return FALSE; + + size = pango_font_description_get_size (font) / PANGO_SCALE; + + if (pango_font_description_get_size_is_absolute (font)) + { + GdkScreen *screen = gdk_screen_get_default (); + double dpi; + + if (screen != NULL) + dpi = gdk_screen_get_resolution (screen); + else + dpi = BORING_DPI_DEFAULT; + + size = (gint) (size / (dpi / 72)); + } + + g_value_set_int (value, size); + pango_font_description_free (font); + + return TRUE; +} + +void +empathy_webkit_bind_font_setting (WebKitWebView *webview, + GSettings *gsettings, + const char *key) +{ + WebKitWebSettings *settings = webkit_web_view_get_settings (webview); + + g_settings_bind_with_mapping (gsettings, key, + settings, "default-font-family", + G_SETTINGS_BIND_GET, + webkit_get_font_family, + NULL, + NULL, NULL); + g_settings_bind_with_mapping (gsettings, key, + settings, "default-font-size", + G_SETTINGS_BIND_GET, + webkit_get_font_size, + NULL, + NULL, NULL); +} + +static void +empathy_webkit_copy_address_cb (GtkMenuItem *menuitem, + gpointer user_data) +{ + WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); + gchar *uri; + GtkClipboard *clipboard; + + g_object_get (G_OBJECT (hit_test_result), + "link-uri", &uri, + NULL); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text (clipboard, uri, -1); + + clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + gtk_clipboard_set_text (clipboard, uri, -1); + + g_free (uri); +} + +static void +empathy_webkit_open_address_cb (GtkMenuItem *menuitem, + gpointer user_data) +{ + WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); + gchar *uri; + + g_object_get (G_OBJECT (hit_test_result), + "link-uri", &uri, + NULL); + + empathy_url_show (GTK_WIDGET (menuitem), uri); + + g_free (uri); +} + +static void +empathy_webkit_context_menu_selection_done_cb (GtkMenuShell *menu, + gpointer user_data) +{ + WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data); + + g_object_unref (hit_test_result); +} + +void +empathy_webkit_context_menu_for_event (WebKitWebView *view, + GdkEventButton *event, + EmpathyWebKitMenuFlags flags) +{ + WebKitHitTestResult *hit_test_result; + WebKitHitTestResultContext context; + GtkWidget *menu; + GtkWidget *item; + + hit_test_result = webkit_web_view_get_hit_test_result (view, event); + g_object_get (G_OBJECT (hit_test_result), + "context", &context, + NULL); + + /* The menu */ + menu = empathy_context_menu_new (GTK_WIDGET (view)); + + /* Select all item */ + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + g_signal_connect_swapped (item, "activate", + G_CALLBACK (webkit_web_view_select_all), + view); + + /* Copy menu item */ + if (webkit_web_view_can_copy_clipboard (view)) + { + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + g_signal_connect_swapped (item, "activate", + G_CALLBACK (webkit_web_view_copy_clipboard), + view); + } + + /* Clear menu item */ + if (flags & EMPATHY_WEBKIT_MENU_CLEAR) + { + item = gtk_separator_menu_item_new (); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + g_signal_connect_swapped (item, "activate", + G_CALLBACK (empathy_chat_view_clear), + view); + } + + /* We will only add the following menu items if we are + * right-clicking a link */ + if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) + { + /* Separator */ + item = gtk_separator_menu_item_new (); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + /* Copy Link Address menu item */ + item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address")); + g_signal_connect (item, "activate", + G_CALLBACK (empathy_webkit_copy_address_cb), + hit_test_result); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + + /* Open Link menu item */ + item = gtk_menu_item_new_with_mnemonic (_("_Open Link")); + g_signal_connect (item, "activate", + G_CALLBACK (empathy_webkit_open_address_cb), + hit_test_result); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + } + + g_signal_connect (GTK_MENU_SHELL (menu), "selection-done", + G_CALLBACK (empathy_webkit_context_menu_selection_done_cb), + hit_test_result); + + /* Display the menu */ + gtk_widget_show_all (menu); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); +} + diff --git a/libempathy-gtk/empathy-webkit-utils.h b/libempathy-gtk/empathy-webkit-utils.h new file mode 100644 index 000000000..322f94c32 --- /dev/null +++ b/libempathy-gtk/empathy-webkit-utils.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Xavier Claessens <xclaesse@gmail.com> + */ + +#ifndef _EMPATHY_WEBKIT_UTILS__H_ +#define _EMPATHY_WEBKIT_UTILS__H_ + +#include <webkit/webkit.h> + +#include "empathy-string-parser.h" + +G_BEGIN_DECLS + +typedef enum { + EMPATHY_WEBKIT_MENU_CLEAR = 1 << 0, +} EmpathyWebKitMenuFlags; + +EmpathyStringParser *empathy_webkit_get_string_parser (gboolean smileys); +void empathy_webkit_bind_font_setting (WebKitWebView *webview, + GSettings *gsettings, const char *key); +void empathy_webkit_context_menu_for_event (WebKitWebView *view, + GdkEventButton *event, EmpathyWebKitMenuFlags flags); + +G_END_DECLS + +#endif |