Notably implemented the "View source" feature (works only with GtkHtml so far)

This commit is contained in:
Pierre Pronchery 2010-03-04 22:33:54 +00:00
parent bff74f19c4
commit edcccde42e
8 changed files with 154 additions and 10 deletions

View File

@ -132,7 +132,9 @@ void on_view_normal_size(gpointer data)
/* on_view_page_source */
void on_view_page_source(gpointer data)
{
/* FIXME implement */
Surfer * surfer = data;
surfer_view_source(surfer);
}

View File

@ -53,6 +53,7 @@ typedef struct _GHtmlConn GHtmlConn;
typedef struct _GHtml
{
Surfer * surfer;
char * source; /* XXX keep the size */
/* history */
GList * history;
@ -104,6 +105,7 @@ static int _ghtml_document_load(GHtml * ghtml, gchar const * url,
gchar const * post);
static int _ghtml_document_reload(GHtml * ghtml);
static gchar * _ghtml_make_url(gchar const * base, gchar const * url);
static int _ghtml_source_append(GHtml * ghtml, char const * buf, size_t size);
static void _ghtml_stop(GHtml * ghtml);
static GHtmlConn * _ghtml_stream_load(GHtml * ghtml, HtmlStream * stream,
gchar const * url, gchar const * post);
@ -131,6 +133,7 @@ GtkWidget * ghtml_new(Surfer * surfer)
if((ghtml = malloc(sizeof(*ghtml))) == NULL)
return NULL;
ghtml->surfer = surfer;
ghtml->source = NULL;
ghtml->history = NULL;
ghtml->current = NULL;
ghtml->conns = NULL;
@ -204,6 +207,16 @@ char const * ghtml_get_location(GtkWidget * widget)
}
/* ghtml_get_source */
char const * ghtml_get_source(GtkWidget * widget)
{
GHtml * ghtml;
ghtml = g_object_get_data(G_OBJECT(widget), "ghtml");
return ghtml->source;
}
/* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * widget)
{
@ -522,11 +535,29 @@ static int _ghtml_document_reload(GHtml * ghtml)
}
/* ghtml_source_append */
static int _ghtml_source_append(GHtml * ghtml, char const * buf, size_t size)
{
size_t len = (ghtml->source != NULL) ? strlen(ghtml->source) : 0;
char * p;
/* FIXME this may lose data (eg if it contains NULL bytes) */
if((p = realloc(ghtml->source, len + size + 1)) == NULL)
return 1; /* XXX report error */
ghtml->source = p;
memcpy(p + len, buf, size);
p[len + size] = '\0';
return 0;
}
/* ghtml_stop */
static void _ghtml_stop(GHtml * ghtml)
{
size_t i;
free(ghtml->source);
ghtml->source = NULL;
for(i = 0; i < ghtml->conns_cnt; i++)
if(ghtml->conns[i] != NULL)
_ghtmlconn_delete(ghtml->conns[i]);
@ -693,6 +724,7 @@ static gboolean _stream_load_watch_file(GIOChannel * source,
_ghtmlconn_delete(conn);
return FALSE;
}
_ghtml_source_append(conn->ghtml, buf, len);
html_stream_write(conn->stream, buf, len);
conn->file_read+=len;
if(conn->file_size > 0)
@ -774,7 +806,11 @@ static void _http_data_complete(GConnHttpEventData * event, GHtmlConn * conn)
else
{
if(size > 0)
{
if(conn == conn->ghtml->conns[0]) /* XXX ugly */
_ghtml_source_append(conn->ghtml, buf, size);
html_stream_write(conn->stream, buf, size);
}
_http_data_progress(event, conn);
}
ghtml = conn->ghtml;
@ -795,6 +831,8 @@ static void _http_data_partial(GConnHttpEventData * event, GHtmlConn * conn)
_ghtmlconn_delete(conn);
return;
}
if(conn == conn->ghtml->conns[0]) /* XXX ugly */
_ghtml_source_append(conn->ghtml, buf, size);
html_stream_write(conn->stream, buf, size);
_http_data_progress(event, conn);
}
@ -856,7 +894,7 @@ static void _http_redirect(GConnHttpEventRedirect * event, GHtmlConn * conn)
char buf[256] = "Redirecting...";
char * url = event->new_location;
if(url == NULL)
if(conn == conn->ghtml->conns[0] && url == NULL) /* XXX ugly */
{
surfer_set_status(ghtml->surfer, buf);
return;
@ -872,6 +910,8 @@ static void _http_redirect(GConnHttpEventRedirect * event, GHtmlConn * conn)
event->auto_redirect, event->num_redirects,
event->max_redirects);
#endif
if(conn != conn->ghtml->conns[0]) /* XXX ugly */
return;
_ghtml_set_base(ghtml, url);
surfer_set_location(ghtml->surfer, url);
surfer_set_status(ghtml->surfer, buf);

View File

@ -308,6 +308,14 @@ char const * ghtml_get_location(GtkWidget * ghtml)
}
/* ghtml_get_source */
char const * ghtml_get_source(GtkWidget * widget)
{
/* FIXME really implement */
return NULL;
}
/* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * ghtml)
{

View File

@ -119,6 +119,14 @@ char const * ghtml_get_location(GtkWidget * widget)
}
/* ghtml_get_source */
char const * ghtml_get_source(GtkWidget * widget)
{
/* FIXME really implement */
return NULL;
}
/* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * widget)
{

View File

@ -136,6 +136,21 @@ char const * ghtml_get_location(GtkWidget * ghtml)
}
/* ghtml_get_source */
char const * ghtml_get_source(GtkWidget * ghtml)
{
GtkWidget * view;
WebKitWebFrame * frame;
WebKitWebDataSource * source;
/* FIXME doesn't seem to work */
view = g_object_get_data(G_OBJECT(ghtml), "view");
frame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(view));
source = webkit_web_frame_get_data_source(frame);
return webkit_web_data_source_get_data(source);
}
char const * ghtml_get_title(GtkWidget * ghtml)
{
GtkWidget * view;

View File

@ -32,6 +32,7 @@ gboolean ghtml_can_go_forward(GtkWidget * ghtml);
char const * ghtml_get_link_message(GtkWidget * ghtml);
char const * ghtml_get_location(GtkWidget * ghtml);
char const * ghtml_get_source(GtkWidget * ghtml);
char const * ghtml_get_title(GtkWidget * ghtml);
int ghtml_set_base(GtkWidget * ghtml, char const * url);

View File

@ -168,7 +168,7 @@ Surfer * surfer_new(char const * url)
gtk_window_set_icon_name(GTK_WINDOW(surfer->window), "stock_internet");
#endif
surfer_set_title(surfer, NULL);
g_signal_connect(G_OBJECT(surfer->window), "delete_event", G_CALLBACK(
g_signal_connect(G_OBJECT(surfer->window), "delete-event", G_CALLBACK(
on_closex), surfer);
vbox = gtk_vbox_new(FALSE, 0);
#ifndef EMBEDDED
@ -185,6 +185,7 @@ Surfer * surfer_new(char const * url)
surfer->tb_back = _surfer_toolbar[0].widget;
surfer->tb_forward = _surfer_toolbar[1].widget;
surfer->tb_stop = _surfer_toolbar[2].widget;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), FALSE);
surfer->tb_refresh = _surfer_toolbar[3].widget;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_back), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), FALSE);
@ -270,7 +271,7 @@ static gboolean _new_idle(gpointer data)
{
Surfer * surfer = data;
ghtml_load_url(surfer->view, surfer->url);
surfer_open(surfer, surfer->url);
return FALSE;
}
@ -315,10 +316,16 @@ void surfer_set_location(Surfer * surfer, char const * url)
{
static int i = 0; /* XXX should be set per-window */
GtkWidget * widget;
char * p;
widget = gtk_bin_get_child(GTK_BIN(surfer->lb_path));
gtk_entry_set_text(GTK_ENTRY(widget), url);
/* FIXME also set surfer->url? what about history? */
/* FIXME what about history? */
if((p = strdup(url)) != NULL)
{
free(surfer->url);
surfer->url = p;
}
if(i == 8)
gtk_combo_box_remove_text(GTK_COMBO_BOX(surfer->lb_path), 0);
else
@ -358,6 +365,8 @@ void surfer_set_status(Surfer * surfer, char const * status)
surfer->statusbar_id = gtk_statusbar_push(sb,
gtk_statusbar_get_context_id(sb, ""), (status != NULL)
? status : "Ready");
if(status == NULL)
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), FALSE);
if(status == NULL)
{
gtk_progress_bar_set_text(pb, " ");
@ -378,8 +387,8 @@ void surfer_set_title(Surfer * surfer, char const * title)
{
char buf[256];
snprintf(buf, sizeof(buf), "%s%s%s", "Web surfer", title != NULL
? " - " : "", title != NULL ? title : "");
snprintf(buf, sizeof(buf), "%s%s%s", "Web surfer", (title != NULL)
? " - " : "", (title != NULL) ? title : "");
gtk_window_set_title(GTK_WINDOW(surfer->window), buf);
}
@ -426,7 +435,9 @@ int surfer_confirm(Surfer * surfer, char const * message)
? GTK_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s",
message);
"Question");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"%s", message);
gtk_window_set_title(GTK_WINDOW(dialog), "Question");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL);
@ -475,7 +486,9 @@ int surfer_error(Surfer * surfer, char const * message, int ret)
dialog = gtk_message_dialog_new((surfer != NULL)
? GTK_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", "Error");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"%s", message);
gtk_window_set_title(GTK_WINDOW(dialog), "Error");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL);
@ -489,6 +502,7 @@ gboolean surfer_go_back(Surfer * surfer)
{
gboolean ret;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ret = ghtml_go_back(surfer->view);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_back), ret);
return ret;
@ -500,6 +514,7 @@ gboolean surfer_go_forward(Surfer * surfer)
{
gboolean ret;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ret = ghtml_go_forward(surfer->view);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), ret);
return ret;
@ -522,6 +537,7 @@ void surfer_open(Surfer * surfer, char const * url)
{
if(url != NULL)
{
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_stop(surfer->view);
ghtml_load_url(surfer->view, url);
}
@ -555,6 +571,7 @@ void surfer_open_dialog(Surfer * surfer)
/* surfer_refresh */
void surfer_refresh(Surfer * surfer)
{
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_refresh(surfer->view);
}
@ -562,6 +579,7 @@ void surfer_refresh(Surfer * surfer)
/* surfer_reload */
void surfer_reload(Surfer * surfer)
{
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_reload(surfer->view);
}
@ -642,6 +660,55 @@ void surfer_unselect_all(Surfer * surfer)
}
/* surfer_view_source */
static gboolean _on_source_closex(GtkWidget * widget, GdkEvent * event,
gpointer data);
void surfer_view_source(Surfer * surfer)
{
GtkWidget * window;
GtkWidget * scrolled;
GtkWidget * widget;
GtkTextBuffer * tbuf;
PangoFontDescription * desc;
char buf[256];
char const * source;
if(surfer->url == NULL)
return;
if((source = ghtml_get_source(surfer->view)) == NULL)
return; /* FIXME download to a temporary file and open */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
snprintf(buf, sizeof(buf), "%s%s", "Web surfer - Source of ",
surfer->url);
gtk_window_set_title(GTK_WINDOW(window), buf);
g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(
_on_source_closex), NULL);
scrolled = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
widget = gtk_text_view_new();
desc = pango_font_description_new();
pango_font_description_set_family(desc, "monospace");
gtk_widget_modify_font(widget, desc);
pango_font_description_free(desc);
gtk_text_view_set_editable(GTK_TEXT_VIEW(widget), FALSE);
tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
/* FIXME probably should convert to UTF-8 when not already */
gtk_text_buffer_set_text(tbuf, source, strlen(source));
gtk_container_add(GTK_CONTAINER(scrolled), widget);
gtk_container_add(GTK_CONTAINER(window), scrolled);
gtk_widget_show_all(window);
}
static gboolean _on_source_closex(GtkWidget * widget, GdkEvent * event,
gpointer data)
{
return FALSE;
}
/* surfer_warning */
void surfer_warning(Surfer * surfer, char const * message)
{
@ -650,7 +717,9 @@ void surfer_warning(Surfer * surfer, char const * message)
dialog = gtk_message_dialog_new((surfer != NULL)
? GTK_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", message);
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", "Warning");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"%s", message);
gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL);

View File

@ -93,6 +93,7 @@ void surfer_go_home(Surfer * surfer);
void surfer_refresh(Surfer * surfer);
void surfer_reload(Surfer * surfer);
void surfer_stop(Surfer * surfer);
void surfer_view_source(Surfer * surfer);
/* selection */
void surfer_select_all(Surfer * surfer);