EFocusTracker tracks the input focus within a window and helps keep the sensitivity of "selectable" actions in the main menu up-to-date. Selectable actions include Cut, Copy, Paste, Select All and Delete. EFocusTracker has built-in support for widgets that implement the GtkEditable interface such as GtkEntry and GtkTextView. It also supports custom widgets that implement the ESelectable interface, which is a subset of GtkEditable and can apply to anything that displays selectable content (esp. tree views and ETables). This commit integrates EFocusTracker with EShellWindow, CompEditor, EMsgComposer, and ESignatureManager. It also bumps the GtkHTML requirement to 2.29.5 to utilize the new GtkhtmlEditor:html constructor property.
1620 lines
39 KiB
C
1620 lines
39 KiB
C
/*
|
|
* e-web-view.c
|
|
*
|
|
* This program 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 of the License, or (at your option) version 3.
|
|
*
|
|
* This program 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 the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
*
|
|
*/
|
|
|
|
#include "e-web-view.h"
|
|
|
|
#include <config.h>
|
|
#include <string.h>
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
#include <camel/camel-internet-address.h>
|
|
#include <camel/camel-url.h>
|
|
|
|
#include "e-util/e-util.h"
|
|
#include "e-util/e-binding.h"
|
|
#include "e-util/e-plugin-ui.h"
|
|
|
|
#include "e-popup-action.h"
|
|
#include "e-selectable.h"
|
|
|
|
#define E_WEB_VIEW_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE \
|
|
((obj), E_TYPE_WEB_VIEW, EWebViewPrivate))
|
|
|
|
typedef struct _EWebViewRequest EWebViewRequest;
|
|
|
|
struct _EWebViewPrivate {
|
|
GList *requests;
|
|
GtkUIManager *ui_manager;
|
|
gchar *selected_uri;
|
|
|
|
GtkAction *open_proxy;
|
|
GtkAction *print_proxy;
|
|
GtkAction *save_as_proxy;
|
|
|
|
/* Lockdown Options */
|
|
guint disable_printing : 1;
|
|
guint disable_save_to_disk : 1;
|
|
};
|
|
|
|
struct _EWebViewRequest {
|
|
GFile *file;
|
|
EWebView *web_view;
|
|
GCancellable *cancellable;
|
|
GInputStream *input_stream;
|
|
GtkHTMLStream *output_stream;
|
|
gchar buffer[4096];
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_ANIMATE,
|
|
PROP_CARET_MODE,
|
|
PROP_DISABLE_PRINTING,
|
|
PROP_DISABLE_SAVE_TO_DISK,
|
|
PROP_OPEN_PROXY,
|
|
PROP_PRINT_PROXY,
|
|
PROP_SAVE_AS_PROXY,
|
|
PROP_SELECTED_URI
|
|
};
|
|
|
|
enum {
|
|
POPUP_EVENT,
|
|
STATUS_MESSAGE,
|
|
STOP_LOADING,
|
|
UPDATE_ACTIONS,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static gpointer parent_class;
|
|
static guint signals[LAST_SIGNAL];
|
|
|
|
static const gchar *ui =
|
|
"<ui>"
|
|
" <popup name='context'>"
|
|
" <menuitem action='copy-clipboard'/>"
|
|
" <separator/>"
|
|
" <placeholder name='custom-actions-1'>"
|
|
" <menuitem action='open'/>"
|
|
" <menuitem action='save-as'/>"
|
|
" <menuitem action='http-open'/>"
|
|
" <menuitem action='send-message'/>"
|
|
" <menuitem action='print'/>"
|
|
" </placeholder>"
|
|
" <placeholder name='custom-actions-2'>"
|
|
" <menuitem action='uri-copy'/>"
|
|
" <menuitem action='mailto-copy'/>"
|
|
" </placeholder>"
|
|
" <placeholder name='custom-actions-3'/>"
|
|
" <separator/>"
|
|
" <menuitem action='select-all'/>"
|
|
" </popup>"
|
|
"</ui>";
|
|
|
|
static EWebViewRequest *
|
|
web_view_request_new (EWebView *web_view,
|
|
const gchar *uri,
|
|
GtkHTMLStream *stream)
|
|
{
|
|
EWebViewRequest *request;
|
|
GList *list;
|
|
|
|
request = g_slice_new (EWebViewRequest);
|
|
|
|
/* Try to detect file paths posing as URIs. */
|
|
if (*uri == '/')
|
|
request->file = g_file_new_for_path (uri);
|
|
else
|
|
request->file = g_file_new_for_uri (uri);
|
|
|
|
request->web_view = g_object_ref (web_view);
|
|
request->cancellable = g_cancellable_new ();
|
|
request->input_stream = NULL;
|
|
request->output_stream = stream;
|
|
|
|
list = request->web_view->priv->requests;
|
|
list = g_list_prepend (list, request);
|
|
request->web_view->priv->requests = list;
|
|
|
|
return request;
|
|
}
|
|
|
|
static void
|
|
web_view_request_free (EWebViewRequest *request)
|
|
{
|
|
GList *list;
|
|
|
|
list = request->web_view->priv->requests;
|
|
list = g_list_remove (list, request);
|
|
request->web_view->priv->requests = list;
|
|
|
|
g_object_unref (request->file);
|
|
g_object_unref (request->web_view);
|
|
g_object_unref (request->cancellable);
|
|
|
|
if (request->input_stream != NULL)
|
|
g_object_unref (request->input_stream);
|
|
|
|
g_slice_free (EWebViewRequest, request);
|
|
}
|
|
|
|
static void
|
|
web_view_request_cancel (EWebViewRequest *request)
|
|
{
|
|
g_cancellable_cancel (request->cancellable);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_request_check_for_error (EWebViewRequest *request,
|
|
GError *error)
|
|
{
|
|
GtkHTML *html;
|
|
GtkHTMLStream *stream;
|
|
|
|
if (error == NULL)
|
|
return FALSE;
|
|
|
|
/* XXX Should we log errors that are not cancellations? */
|
|
|
|
html = GTK_HTML (request->web_view);
|
|
stream = request->output_stream;
|
|
|
|
gtk_html_end (html, stream, GTK_HTML_STREAM_ERROR);
|
|
web_view_request_free (request);
|
|
g_error_free (error);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
web_view_request_stream_read_cb (GInputStream *input_stream,
|
|
GAsyncResult *result,
|
|
EWebViewRequest *request)
|
|
{
|
|
GtkHTML *html;
|
|
gssize bytes_read;
|
|
GError *error = NULL;
|
|
|
|
html = GTK_HTML (request->web_view);
|
|
bytes_read = g_input_stream_read_finish (input_stream, result, &error);
|
|
|
|
if (web_view_request_check_for_error (request, error))
|
|
return;
|
|
|
|
if (bytes_read == 0) {
|
|
gtk_html_end (
|
|
GTK_HTML (request->web_view),
|
|
request->output_stream, GTK_HTML_STREAM_OK);
|
|
web_view_request_free (request);
|
|
return;
|
|
}
|
|
|
|
gtk_html_write (
|
|
GTK_HTML (request->web_view),
|
|
request->output_stream, request->buffer, bytes_read);
|
|
|
|
g_input_stream_read_async (
|
|
request->input_stream, request->buffer,
|
|
sizeof (request->buffer), G_PRIORITY_DEFAULT,
|
|
request->cancellable, (GAsyncReadyCallback)
|
|
web_view_request_stream_read_cb, request);
|
|
}
|
|
|
|
static void
|
|
web_view_request_read_cb (GFile *file,
|
|
GAsyncResult *result,
|
|
EWebViewRequest *request)
|
|
{
|
|
GFileInputStream *input_stream;
|
|
GError *error = NULL;
|
|
|
|
/* Input stream might be NULL, so don't use cast macro. */
|
|
input_stream = g_file_read_finish (file, result, &error);
|
|
request->input_stream = (GInputStream *) input_stream;
|
|
|
|
if (web_view_request_check_for_error (request, error))
|
|
return;
|
|
|
|
g_input_stream_read_async (
|
|
request->input_stream, request->buffer,
|
|
sizeof (request->buffer), G_PRIORITY_DEFAULT,
|
|
request->cancellable, (GAsyncReadyCallback)
|
|
web_view_request_stream_read_cb, request);
|
|
}
|
|
|
|
static void
|
|
action_copy_clipboard_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
e_web_view_copy_clipboard (web_view);
|
|
}
|
|
|
|
static void
|
|
action_http_open_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
const gchar *uri;
|
|
gpointer parent;
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
action_mailto_copy_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
CamelURL *curl;
|
|
CamelInternetAddress *inet_addr;
|
|
GtkClipboard *clipboard;
|
|
const gchar *uri;
|
|
gchar *text;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
/* This should work because we checked it in update_actions(). */
|
|
curl = camel_url_new (uri, NULL);
|
|
g_return_if_fail (curl != NULL);
|
|
|
|
inet_addr = camel_internet_address_new ();
|
|
camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
|
text = camel_address_encode (CAMEL_ADDRESS (inet_addr));
|
|
if (text == NULL || *text == '\0')
|
|
text = g_strdup (uri + strlen ("mailto:"));
|
|
|
|
camel_object_unref (inet_addr);
|
|
camel_url_free (curl);
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
|
gtk_clipboard_set_text (clipboard, text, -1);
|
|
gtk_clipboard_store (clipboard);
|
|
|
|
g_free (text);
|
|
}
|
|
|
|
static void
|
|
action_select_all_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
e_web_view_select_all (web_view);
|
|
}
|
|
|
|
static void
|
|
action_send_message_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
const gchar *uri;
|
|
gpointer parent;
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
action_uri_copy_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
GtkClipboard *clipboard;
|
|
const gchar *uri;
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
gtk_clipboard_set_text (clipboard, uri, -1);
|
|
gtk_clipboard_store (clipboard);
|
|
}
|
|
|
|
static GtkActionEntry uri_entries[] = {
|
|
|
|
{ "uri-copy",
|
|
GTK_STOCK_COPY,
|
|
N_("_Copy Link Location"),
|
|
NULL,
|
|
N_("Copy the link to the clipboard"),
|
|
G_CALLBACK (action_uri_copy_cb) }
|
|
};
|
|
|
|
static GtkActionEntry http_entries[] = {
|
|
|
|
{ "http-open",
|
|
"emblem-web",
|
|
N_("_Open Link in Browser"),
|
|
NULL,
|
|
N_("Open the link in a web browser"),
|
|
G_CALLBACK (action_http_open_cb) }
|
|
};
|
|
|
|
static GtkActionEntry mailto_entries[] = {
|
|
|
|
{ "mailto-copy",
|
|
GTK_STOCK_COPY,
|
|
N_("_Copy Email Address"),
|
|
NULL,
|
|
N_("Copy the email address to the clipboard"),
|
|
G_CALLBACK (action_mailto_copy_cb) },
|
|
|
|
{ "send-message",
|
|
"mail-message-new",
|
|
N_("_Send New Message To..."),
|
|
NULL,
|
|
N_("Send a mail message to this address"),
|
|
G_CALLBACK (action_send_message_cb) }
|
|
};
|
|
|
|
static GtkActionEntry selection_entries[] = {
|
|
|
|
{ "copy-clipboard",
|
|
GTK_STOCK_COPY,
|
|
NULL,
|
|
NULL,
|
|
N_("Copy the selection"),
|
|
G_CALLBACK (action_copy_clipboard_cb) },
|
|
};
|
|
|
|
static GtkActionEntry standard_entries[] = {
|
|
|
|
{ "select-all",
|
|
GTK_STOCK_SELECT_ALL,
|
|
NULL,
|
|
NULL,
|
|
N_("Select all text and images"),
|
|
G_CALLBACK (action_select_all_cb) }
|
|
};
|
|
|
|
static gboolean
|
|
web_view_button_press_event_cb (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
GtkHTML *frame)
|
|
{
|
|
gboolean event_handled = FALSE;
|
|
gchar *uri;
|
|
|
|
if (event != NULL && event->button != 3)
|
|
return FALSE;
|
|
|
|
uri = e_web_view_extract_uri (web_view, event, frame);
|
|
|
|
if (uri != NULL && g_str_has_prefix (uri, "##")) {
|
|
g_free (uri);
|
|
return FALSE;
|
|
}
|
|
|
|
g_signal_emit (
|
|
web_view, signals[POPUP_EVENT], 0,
|
|
event, uri, &event_handled);
|
|
|
|
g_free (uri);
|
|
|
|
return event_handled;
|
|
}
|
|
|
|
static void
|
|
web_view_menu_item_select_cb (EWebView *web_view,
|
|
GtkWidget *widget)
|
|
{
|
|
GtkAction *action;
|
|
GtkActivatable *activatable;
|
|
const gchar *tooltip;
|
|
|
|
activatable = GTK_ACTIVATABLE (widget);
|
|
action = gtk_activatable_get_related_action (activatable);
|
|
tooltip = gtk_action_get_tooltip (action);
|
|
|
|
if (tooltip == NULL)
|
|
return;
|
|
|
|
e_web_view_status_message (web_view, tooltip);
|
|
}
|
|
|
|
static void
|
|
web_view_menu_item_deselect_cb (EWebView *web_view)
|
|
{
|
|
e_web_view_status_message (web_view, NULL);
|
|
}
|
|
|
|
static void
|
|
web_view_connect_proxy_cb (EWebView *web_view,
|
|
GtkAction *action,
|
|
GtkWidget *proxy)
|
|
{
|
|
if (!GTK_IS_MENU_ITEM (proxy))
|
|
return;
|
|
|
|
g_signal_connect_swapped (
|
|
proxy, "select",
|
|
G_CALLBACK (web_view_menu_item_select_cb), web_view);
|
|
|
|
g_signal_connect_swapped (
|
|
proxy, "deselect",
|
|
G_CALLBACK (web_view_menu_item_deselect_cb), web_view);
|
|
}
|
|
|
|
static void
|
|
web_view_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id) {
|
|
case PROP_ANIMATE:
|
|
e_web_view_set_animate (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_CARET_MODE:
|
|
e_web_view_set_caret_mode (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_DISABLE_PRINTING:
|
|
e_web_view_set_disable_printing (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_DISABLE_SAVE_TO_DISK:
|
|
e_web_view_set_disable_save_to_disk (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_OPEN_PROXY:
|
|
e_web_view_set_open_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_PRINT_PROXY:
|
|
e_web_view_set_print_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_SAVE_AS_PROXY:
|
|
e_web_view_set_save_as_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_SELECTED_URI:
|
|
e_web_view_set_selected_uri (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_string (value));
|
|
return;
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
web_view_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id) {
|
|
case PROP_ANIMATE:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_animate (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_CARET_MODE:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_caret_mode (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_DISABLE_PRINTING:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_disable_printing (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_DISABLE_SAVE_TO_DISK:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_disable_save_to_disk (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_OPEN_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_open_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_PRINT_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_print_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_SAVE_AS_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_save_as_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_SELECTED_URI:
|
|
g_value_set_string (
|
|
value, e_web_view_get_selected_uri (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
web_view_dispose (GObject *object)
|
|
{
|
|
EWebViewPrivate *priv;
|
|
|
|
priv = E_WEB_VIEW_GET_PRIVATE (object);
|
|
|
|
if (priv->ui_manager != NULL) {
|
|
g_object_unref (priv->ui_manager);
|
|
priv->ui_manager = NULL;
|
|
}
|
|
|
|
if (priv->open_proxy != NULL) {
|
|
g_object_unref (priv->open_proxy);
|
|
priv->open_proxy = NULL;
|
|
}
|
|
|
|
if (priv->print_proxy != NULL) {
|
|
g_object_unref (priv->print_proxy);
|
|
priv->print_proxy = NULL;
|
|
}
|
|
|
|
if (priv->save_as_proxy != NULL) {
|
|
g_object_unref (priv->save_as_proxy);
|
|
priv->save_as_proxy = NULL;
|
|
}
|
|
|
|
/* Chain up to parent's dispose() method. */
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
web_view_finalize (GObject *object)
|
|
{
|
|
EWebViewPrivate *priv;
|
|
|
|
priv = E_WEB_VIEW_GET_PRIVATE (object);
|
|
|
|
/* All URI requests should be complete or cancelled by now. */
|
|
if (priv->requests != NULL)
|
|
g_warning ("Finalizing EWebView with active URI requests");
|
|
|
|
g_free (priv->selected_uri);
|
|
|
|
/* Chain up to parent's finalize() method. */
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_button_press_event (GtkWidget *widget,
|
|
GdkEventButton *event)
|
|
{
|
|
GtkWidgetClass *widget_class;
|
|
EWebView *web_view;
|
|
|
|
web_view = E_WEB_VIEW (widget);
|
|
|
|
if (web_view_button_press_event_cb (web_view, event, NULL))
|
|
return TRUE;
|
|
|
|
/* Chain up to parent's button_press_event() method. */
|
|
widget_class = GTK_WIDGET_CLASS (parent_class);
|
|
return widget_class->button_press_event (widget, event);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_scroll_event (GtkWidget *widget,
|
|
GdkEventScroll *event)
|
|
{
|
|
if (event->state & GDK_CONTROL_MASK) {
|
|
switch (event->direction) {
|
|
case GDK_SCROLL_UP:
|
|
gtk_html_zoom_in (GTK_HTML (widget));
|
|
return TRUE;
|
|
case GDK_SCROLL_DOWN:
|
|
gtk_html_zoom_out (GTK_HTML (widget));
|
|
return TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
web_view_url_requested (GtkHTML *html,
|
|
const gchar *uri,
|
|
GtkHTMLStream *stream)
|
|
{
|
|
EWebViewRequest *request;
|
|
|
|
request = web_view_request_new (E_WEB_VIEW (html), uri, stream);
|
|
|
|
g_file_read_async (
|
|
request->file, G_PRIORITY_DEFAULT,
|
|
request->cancellable, (GAsyncReadyCallback)
|
|
web_view_request_read_cb, request);
|
|
}
|
|
|
|
static void
|
|
web_view_link_clicked (GtkHTML *html,
|
|
const gchar *uri)
|
|
{
|
|
gpointer parent;
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (html));
|
|
parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
|
|
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
web_view_on_url (GtkHTML *html,
|
|
const gchar *uri)
|
|
{
|
|
EWebView *web_view;
|
|
CamelInternetAddress *address;
|
|
CamelURL *curl;
|
|
const gchar *format = NULL;
|
|
gchar *message = NULL;
|
|
gchar *who;
|
|
|
|
web_view = E_WEB_VIEW (html);
|
|
|
|
if (uri == NULL || *uri == '\0')
|
|
goto exit;
|
|
|
|
if (g_str_has_prefix (uri, "mailto:"))
|
|
format = _("Click to mail %s");
|
|
else if (g_str_has_prefix (uri, "callto:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "h323:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "sip:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "##"))
|
|
message = g_strdup (_("Click to hide/unhide addresses"));
|
|
else
|
|
message = g_strdup_printf (_("Click to open %s"), uri);
|
|
|
|
if (format == NULL)
|
|
goto exit;
|
|
|
|
/* XXX Use something other than Camel here. Surely
|
|
* there's other APIs around that can do this. */
|
|
curl = camel_url_new (uri, NULL);
|
|
address = camel_internet_address_new ();
|
|
camel_address_decode (CAMEL_ADDRESS (address), curl->path);
|
|
who = camel_address_format (CAMEL_ADDRESS (address));
|
|
camel_object_unref (address);
|
|
camel_url_free (curl);
|
|
|
|
if (who == NULL)
|
|
who = g_strdup (strchr (uri, ':') + 1);
|
|
|
|
message = g_strdup_printf (format, who);
|
|
|
|
g_free (who);
|
|
|
|
exit:
|
|
e_web_view_status_message (web_view, message);
|
|
|
|
g_free (message);
|
|
}
|
|
|
|
static void
|
|
web_view_iframe_created (GtkHTML *html,
|
|
GtkHTML *iframe)
|
|
{
|
|
g_signal_connect_swapped (
|
|
iframe, "button-press-event",
|
|
G_CALLBACK (web_view_button_press_event_cb), html);
|
|
}
|
|
|
|
static gchar *
|
|
web_view_extract_uri (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
GtkHTML *html)
|
|
{
|
|
gchar *uri;
|
|
|
|
if (event != NULL)
|
|
uri = gtk_html_get_url_at (html, event->x, event->y);
|
|
else
|
|
uri = gtk_html_get_cursor_url (html);
|
|
|
|
return uri;
|
|
}
|
|
|
|
static gboolean
|
|
web_view_popup_event (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
const gchar *uri)
|
|
{
|
|
if (uri != NULL)
|
|
e_web_view_unselect_all (web_view);
|
|
|
|
e_web_view_set_selected_uri (web_view, uri);
|
|
e_web_view_show_popup_menu (web_view, event, NULL, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
web_view_stop_loading (EWebView *web_view)
|
|
{
|
|
g_list_foreach (
|
|
web_view->priv->requests, (GFunc)
|
|
web_view_request_cancel, NULL);
|
|
|
|
gtk_html_stop (GTK_HTML (web_view));
|
|
}
|
|
|
|
static void
|
|
web_view_update_actions (EWebView *web_view)
|
|
{
|
|
GtkActionGroup *action_group;
|
|
gboolean have_selection;
|
|
gboolean scheme_is_http = FALSE;
|
|
gboolean scheme_is_mailto = FALSE;
|
|
gboolean uri_is_valid = FALSE;
|
|
gboolean visible;
|
|
const gchar *group_name;
|
|
const gchar *uri;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
have_selection = e_web_view_is_selection_active (web_view);
|
|
|
|
/* Parse the URI early so we know if the actions will work. */
|
|
if (uri != NULL) {
|
|
CamelURL *curl;
|
|
|
|
curl = camel_url_new (uri, NULL);
|
|
uri_is_valid = (curl != NULL);
|
|
camel_url_free (curl);
|
|
|
|
scheme_is_http =
|
|
(g_ascii_strncasecmp (uri, "http:", 5) == 0) ||
|
|
(g_ascii_strncasecmp (uri, "https:", 6) == 0);
|
|
|
|
scheme_is_mailto =
|
|
(g_ascii_strncasecmp (uri, "mailto:", 7) == 0);
|
|
}
|
|
|
|
/* Allow copying the URI even if it's malformed. */
|
|
group_name = "uri";
|
|
visible = (uri != NULL) && !scheme_is_mailto;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "http";
|
|
visible = uri_is_valid && scheme_is_http;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "mailto";
|
|
visible = uri_is_valid && scheme_is_mailto;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "selection";
|
|
visible = have_selection;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "standard";
|
|
visible = (uri == NULL);
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "lockdown-printing";
|
|
visible = (uri == NULL) && !web_view->priv->disable_printing;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "lockdown-save-to-disk";
|
|
visible = (uri == NULL) && !web_view->priv->disable_save_to_disk;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_update_actions (ESelectable *selectable,
|
|
EFocusTracker *focus_tracker,
|
|
GdkAtom *clipboard_targets,
|
|
gint n_clipboard_targets)
|
|
{
|
|
EWebView *web_view;
|
|
GtkAction *action;
|
|
const gchar *tooltip;
|
|
gboolean sensitive;
|
|
|
|
web_view = E_WEB_VIEW (selectable);
|
|
|
|
/* Copy Clipboard */
|
|
|
|
action = e_web_view_get_action (web_view, "copy-clipboard");
|
|
sensitive = gtk_action_get_sensitive (action);
|
|
tooltip = gtk_action_get_tooltip (action);
|
|
|
|
action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
|
|
/* Select All */
|
|
|
|
action = e_web_view_get_action (web_view, "select-all");
|
|
sensitive = gtk_action_get_sensitive (action);
|
|
tooltip = gtk_action_get_tooltip (action);
|
|
|
|
action = e_focus_tracker_get_select_all_action (focus_tracker);
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_copy_clipboard (ESelectable *selectable)
|
|
{
|
|
e_web_view_copy_clipboard (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_select_all (ESelectable *selectable)
|
|
{
|
|
e_web_view_select_all (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
web_view_class_init (EWebViewClass *class)
|
|
{
|
|
GObjectClass *object_class;
|
|
GtkWidgetClass *widget_class;
|
|
GtkHTMLClass *html_class;
|
|
|
|
parent_class = g_type_class_peek_parent (class);
|
|
g_type_class_add_private (class, sizeof (EWebViewPrivate));
|
|
|
|
object_class = G_OBJECT_CLASS (class);
|
|
object_class->set_property = web_view_set_property;
|
|
object_class->get_property = web_view_get_property;
|
|
object_class->dispose = web_view_dispose;
|
|
object_class->finalize = web_view_finalize;
|
|
|
|
widget_class = GTK_WIDGET_CLASS (class);
|
|
widget_class->button_press_event = web_view_button_press_event;
|
|
widget_class->scroll_event = web_view_scroll_event;
|
|
|
|
html_class = GTK_HTML_CLASS (class);
|
|
html_class->url_requested = web_view_url_requested;
|
|
html_class->link_clicked = web_view_link_clicked;
|
|
html_class->on_url = web_view_on_url;
|
|
html_class->iframe_created = web_view_iframe_created;
|
|
|
|
class->extract_uri = web_view_extract_uri;
|
|
class->popup_event = web_view_popup_event;
|
|
class->stop_loading = web_view_stop_loading;
|
|
class->update_actions = web_view_update_actions;
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_ANIMATE,
|
|
g_param_spec_boolean (
|
|
"animate",
|
|
"Animate Images",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_CARET_MODE,
|
|
g_param_spec_boolean (
|
|
"caret-mode",
|
|
"Caret Mode",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_DISABLE_PRINTING,
|
|
g_param_spec_boolean (
|
|
"disable-printing",
|
|
"Disable Printing",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_DISABLE_SAVE_TO_DISK,
|
|
g_param_spec_boolean (
|
|
"disable-save-to-disk",
|
|
"Disable Save-to-Disk",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_OPEN_PROXY,
|
|
g_param_spec_object (
|
|
"open-proxy",
|
|
"Open Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_PRINT_PROXY,
|
|
g_param_spec_object (
|
|
"print-proxy",
|
|
"Print Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SAVE_AS_PROXY,
|
|
g_param_spec_object (
|
|
"save-as-proxy",
|
|
"Save As Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SELECTED_URI,
|
|
g_param_spec_string (
|
|
"selected-uri",
|
|
"Selected URI",
|
|
NULL,
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
signals[POPUP_EVENT] = g_signal_new (
|
|
"popup-event",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, popup_event),
|
|
g_signal_accumulator_true_handled, NULL,
|
|
e_marshal_BOOLEAN__BOXED_STRING,
|
|
G_TYPE_BOOLEAN, 2,
|
|
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
|
|
G_TYPE_STRING);
|
|
|
|
signals[STATUS_MESSAGE] = g_signal_new (
|
|
"status-message",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, status_message),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_STRING);
|
|
|
|
signals[STOP_LOADING] = g_signal_new (
|
|
"stop-loading",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, stop_loading),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
signals[UPDATE_ACTIONS] = g_signal_new (
|
|
"update-actions",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, update_actions),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_init (ESelectableInterface *interface)
|
|
{
|
|
interface->update_actions = web_view_selectable_update_actions;
|
|
interface->copy_clipboard = web_view_selectable_copy_clipboard;
|
|
interface->select_all = web_view_selectable_select_all;
|
|
}
|
|
|
|
static void
|
|
web_view_init (EWebView *web_view)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
GtkActionGroup *action_group;
|
|
EPopupAction *popup_action;
|
|
const gchar *domain = GETTEXT_PACKAGE;
|
|
const gchar *id;
|
|
GError *error = NULL;
|
|
|
|
web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
|
|
|
|
ui_manager = gtk_ui_manager_new ();
|
|
web_view->priv->ui_manager = ui_manager;
|
|
|
|
g_signal_connect_swapped (
|
|
ui_manager, "connect-proxy",
|
|
G_CALLBACK (web_view_connect_proxy_cb), web_view);
|
|
|
|
action_group = gtk_action_group_new ("uri");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, uri_entries,
|
|
G_N_ELEMENTS (uri_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("http");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, http_entries,
|
|
G_N_ELEMENTS (http_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("mailto");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, mailto_entries,
|
|
G_N_ELEMENTS (mailto_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("selection");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, selection_entries,
|
|
G_N_ELEMENTS (selection_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("standard");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, standard_entries,
|
|
G_N_ELEMENTS (standard_entries), web_view);
|
|
|
|
popup_action = e_popup_action_new ("open");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
e_mutual_binding_new (
|
|
web_view, "open-proxy",
|
|
popup_action, "related-action");
|
|
|
|
/* Support lockdown. */
|
|
|
|
action_group = gtk_action_group_new ("lockdown-printing");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
popup_action = e_popup_action_new ("print");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
e_mutual_binding_new (
|
|
web_view, "print-proxy",
|
|
popup_action, "related-action");
|
|
|
|
action_group = gtk_action_group_new ("lockdown-save-to-disk");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
popup_action = e_popup_action_new ("save-as");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
e_mutual_binding_new (
|
|
web_view, "save-as-proxy",
|
|
popup_action, "related-action");
|
|
|
|
/* Because we are loading from a hard-coded string, there is
|
|
* no chance of I/O errors. Failure here implies a malformed
|
|
* UI definition. Full stop. */
|
|
gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
|
|
if (error != NULL)
|
|
g_error ("%s", error->message);
|
|
|
|
id = "org.gnome.evolution.webview";
|
|
e_plugin_ui_register_manager (ui_manager, id, web_view);
|
|
e_plugin_ui_enable_manager (ui_manager, id);
|
|
}
|
|
|
|
GType
|
|
e_web_view_get_type (void)
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (G_UNLIKELY (type == 0)) {
|
|
static const GTypeInfo type_info = {
|
|
sizeof (EWebViewClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) web_view_class_init,
|
|
(GClassFinalizeFunc) NULL,
|
|
NULL, /* class_data */
|
|
sizeof (EWebView),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) web_view_init,
|
|
NULL /* value_table */
|
|
};
|
|
|
|
static const GInterfaceInfo selectable_info = {
|
|
(GInterfaceInitFunc) web_view_selectable_init,
|
|
(GInterfaceFinalizeFunc) NULL,
|
|
NULL /* interface_data */
|
|
};
|
|
|
|
type = g_type_register_static (
|
|
GTK_TYPE_HTML, "EWebView", &type_info, 0);
|
|
|
|
g_type_add_interface_static (
|
|
type, E_TYPE_SELECTABLE, &selectable_info);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
GtkWidget *
|
|
e_web_view_new (void)
|
|
{
|
|
return g_object_new (E_TYPE_WEB_VIEW, NULL);
|
|
}
|
|
|
|
void
|
|
e_web_view_clear (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_load_empty (GTK_HTML (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_load_string (EWebView *web_view,
|
|
const gchar *string)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (string != NULL && *string != '\0')
|
|
gtk_html_load_from_string (GTK_HTML (web_view), string, -1);
|
|
else
|
|
e_web_view_clear (web_view);
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_animate (EWebView *web_view)
|
|
{
|
|
/* XXX This is just here to maintain symmetry
|
|
* with e_web_view_set_animate(). */
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_get_animate (GTK_HTML (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_set_animate (EWebView *web_view,
|
|
gboolean animate)
|
|
{
|
|
/* XXX GtkHTML does not utilize GObject properties as well
|
|
* as it could. This just wraps gtk_html_set_animate()
|
|
* so we can get a "notify::animate" signal. */
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_set_animate (GTK_HTML (web_view), animate);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "animate");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_caret_mode (EWebView *web_view)
|
|
{
|
|
/* XXX This is just here to maintain symmetry
|
|
* with e_web_view_set_caret_mode(). */
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_get_caret_mode (GTK_HTML (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_set_caret_mode (EWebView *web_view,
|
|
gboolean caret_mode)
|
|
{
|
|
/* XXX GtkHTML does not utilize GObject properties as well
|
|
* as it could. This just wraps gtk_html_set_caret_mode()
|
|
* so we can get a "notify::caret-mode" signal. */
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_set_caret_mode (GTK_HTML (web_view), caret_mode);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "caret-mode");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_disable_printing (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->disable_printing;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_disable_printing (EWebView *web_view,
|
|
gboolean disable_printing)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
web_view->priv->disable_printing = disable_printing;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "disable-printing");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_disable_save_to_disk (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->disable_save_to_disk;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_disable_save_to_disk (EWebView *web_view,
|
|
gboolean disable_save_to_disk)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
web_view->priv->disable_save_to_disk = disable_save_to_disk;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "disable-save-to-disk");
|
|
}
|
|
|
|
const gchar *
|
|
e_web_view_get_selected_uri (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->selected_uri;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_selected_uri (EWebView *web_view,
|
|
const gchar *selected_uri)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_free (web_view->priv->selected_uri);
|
|
web_view->priv->selected_uri = g_strdup (selected_uri);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "selected-uri");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_open_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->open_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_open_proxy (EWebView *web_view,
|
|
GtkAction *open_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (open_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (open_proxy));
|
|
g_object_ref (open_proxy);
|
|
}
|
|
|
|
if (web_view->priv->open_proxy != NULL)
|
|
g_object_unref (web_view->priv->open_proxy);
|
|
|
|
web_view->priv->open_proxy = open_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "open-proxy");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_print_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->print_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_print_proxy (EWebView *web_view,
|
|
GtkAction *print_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (print_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (print_proxy));
|
|
g_object_ref (print_proxy);
|
|
}
|
|
|
|
if (web_view->priv->print_proxy != NULL)
|
|
g_object_unref (web_view->priv->print_proxy);
|
|
|
|
web_view->priv->print_proxy = print_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "print-proxy");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_save_as_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->save_as_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_save_as_proxy (EWebView *web_view,
|
|
GtkAction *save_as_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (save_as_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (save_as_proxy));
|
|
g_object_ref (save_as_proxy);
|
|
}
|
|
|
|
if (web_view->priv->save_as_proxy != NULL)
|
|
g_object_unref (web_view->priv->save_as_proxy);
|
|
|
|
web_view->priv->save_as_proxy = save_as_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "save-as-proxy");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_action (EWebView *web_view,
|
|
const gchar *action_name)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
g_return_val_if_fail (action_name != NULL, NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
|
|
return e_lookup_action (ui_manager, action_name);
|
|
}
|
|
|
|
GtkActionGroup *
|
|
e_web_view_get_action_group (EWebView *web_view,
|
|
const gchar *group_name)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
g_return_val_if_fail (group_name != NULL, NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
|
|
return e_lookup_action_group (ui_manager, group_name);
|
|
}
|
|
|
|
gchar *
|
|
e_web_view_extract_uri (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
GtkHTML *frame)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
if (frame == NULL)
|
|
frame = GTK_HTML (web_view);
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_val_if_fail (class->extract_uri != NULL, NULL);
|
|
|
|
return class->extract_uri (web_view, event, frame);
|
|
}
|
|
|
|
void
|
|
e_web_view_copy_clipboard (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "copy");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_is_selection_active (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_command (GTK_HTML (web_view), "is-selection-active");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_scroll_forward (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_command (GTK_HTML (web_view), "scroll-forward");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_scroll_backward (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_command (GTK_HTML (web_view), "scroll-backward");
|
|
}
|
|
|
|
void
|
|
e_web_view_select_all (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "select-all");
|
|
}
|
|
|
|
void
|
|
e_web_view_unselect_all (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "unselect-all");
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_100 (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "zoom-reset");
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_in (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "zoom-in");
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_out (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "zoom-out");
|
|
}
|
|
|
|
GtkUIManager *
|
|
e_web_view_get_ui_manager (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->ui_manager;
|
|
}
|
|
|
|
GtkWidget *
|
|
e_web_view_get_popup_menu (EWebView *web_view)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
GtkWidget *menu;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
menu = gtk_ui_manager_get_widget (ui_manager, "/context");
|
|
g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
|
|
|
|
return menu;
|
|
}
|
|
|
|
void
|
|
e_web_view_show_popup_menu (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
GtkMenuPositionFunc func,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *menu;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
e_web_view_update_actions (web_view);
|
|
|
|
menu = e_web_view_get_popup_menu (web_view);
|
|
|
|
if (event != NULL)
|
|
gtk_menu_popup (
|
|
GTK_MENU (menu), NULL, NULL, func,
|
|
user_data, event->button, event->time);
|
|
else
|
|
gtk_menu_popup (
|
|
GTK_MENU (menu), NULL, NULL, func,
|
|
user_data, 0, gtk_get_current_event_time ());
|
|
}
|
|
|
|
void
|
|
e_web_view_status_message (EWebView *web_view,
|
|
const gchar *status_message)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[STATUS_MESSAGE], 0, status_message);
|
|
}
|
|
|
|
void
|
|
e_web_view_stop_loading (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[STOP_LOADING], 0);
|
|
}
|
|
|
|
void
|
|
e_web_view_update_actions (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[UPDATE_ACTIONS], 0);
|
|
}
|