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 */ /* on_view_page_source */
void on_view_page_source(gpointer data) 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 typedef struct _GHtml
{ {
Surfer * surfer; Surfer * surfer;
char * source; /* XXX keep the size */
/* history */ /* history */
GList * history; GList * history;
@ -104,6 +105,7 @@ static int _ghtml_document_load(GHtml * ghtml, gchar const * url,
gchar const * post); gchar const * post);
static int _ghtml_document_reload(GHtml * ghtml); static int _ghtml_document_reload(GHtml * ghtml);
static gchar * _ghtml_make_url(gchar const * base, gchar const * url); 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 void _ghtml_stop(GHtml * ghtml);
static GHtmlConn * _ghtml_stream_load(GHtml * ghtml, HtmlStream * stream, static GHtmlConn * _ghtml_stream_load(GHtml * ghtml, HtmlStream * stream,
gchar const * url, gchar const * post); gchar const * url, gchar const * post);
@ -131,6 +133,7 @@ GtkWidget * ghtml_new(Surfer * surfer)
if((ghtml = malloc(sizeof(*ghtml))) == NULL) if((ghtml = malloc(sizeof(*ghtml))) == NULL)
return NULL; return NULL;
ghtml->surfer = surfer; ghtml->surfer = surfer;
ghtml->source = NULL;
ghtml->history = NULL; ghtml->history = NULL;
ghtml->current = NULL; ghtml->current = NULL;
ghtml->conns = 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 */ /* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * widget) 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 */ /* ghtml_stop */
static void _ghtml_stop(GHtml * ghtml) static void _ghtml_stop(GHtml * ghtml)
{ {
size_t i; size_t i;
free(ghtml->source);
ghtml->source = NULL;
for(i = 0; i < ghtml->conns_cnt; i++) for(i = 0; i < ghtml->conns_cnt; i++)
if(ghtml->conns[i] != NULL) if(ghtml->conns[i] != NULL)
_ghtmlconn_delete(ghtml->conns[i]); _ghtmlconn_delete(ghtml->conns[i]);
@ -693,6 +724,7 @@ static gboolean _stream_load_watch_file(GIOChannel * source,
_ghtmlconn_delete(conn); _ghtmlconn_delete(conn);
return FALSE; return FALSE;
} }
_ghtml_source_append(conn->ghtml, buf, len);
html_stream_write(conn->stream, buf, len); html_stream_write(conn->stream, buf, len);
conn->file_read+=len; conn->file_read+=len;
if(conn->file_size > 0) if(conn->file_size > 0)
@ -774,7 +806,11 @@ static void _http_data_complete(GConnHttpEventData * event, GHtmlConn * conn)
else else
{ {
if(size > 0) 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); html_stream_write(conn->stream, buf, size);
}
_http_data_progress(event, conn); _http_data_progress(event, conn);
} }
ghtml = conn->ghtml; ghtml = conn->ghtml;
@ -795,6 +831,8 @@ static void _http_data_partial(GConnHttpEventData * event, GHtmlConn * conn)
_ghtmlconn_delete(conn); _ghtmlconn_delete(conn);
return; return;
} }
if(conn == conn->ghtml->conns[0]) /* XXX ugly */
_ghtml_source_append(conn->ghtml, buf, size);
html_stream_write(conn->stream, buf, size); html_stream_write(conn->stream, buf, size);
_http_data_progress(event, conn); _http_data_progress(event, conn);
} }
@ -856,7 +894,7 @@ static void _http_redirect(GConnHttpEventRedirect * event, GHtmlConn * conn)
char buf[256] = "Redirecting..."; char buf[256] = "Redirecting...";
char * url = event->new_location; char * url = event->new_location;
if(url == NULL) if(conn == conn->ghtml->conns[0] && url == NULL) /* XXX ugly */
{ {
surfer_set_status(ghtml->surfer, buf); surfer_set_status(ghtml->surfer, buf);
return; return;
@ -872,6 +910,8 @@ static void _http_redirect(GConnHttpEventRedirect * event, GHtmlConn * conn)
event->auto_redirect, event->num_redirects, event->auto_redirect, event->num_redirects,
event->max_redirects); event->max_redirects);
#endif #endif
if(conn != conn->ghtml->conns[0]) /* XXX ugly */
return;
_ghtml_set_base(ghtml, url); _ghtml_set_base(ghtml, url);
surfer_set_location(ghtml->surfer, url); surfer_set_location(ghtml->surfer, url);
surfer_set_status(ghtml->surfer, buf); 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 */ /* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * ghtml) 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 */ /* ghtml_get_title */
char const * ghtml_get_title(GtkWidget * widget) 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) char const * ghtml_get_title(GtkWidget * ghtml)
{ {
GtkWidget * view; 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_link_message(GtkWidget * ghtml);
char const * ghtml_get_location(GtkWidget * ghtml); char const * ghtml_get_location(GtkWidget * ghtml);
char const * ghtml_get_source(GtkWidget * ghtml);
char const * ghtml_get_title(GtkWidget * ghtml); char const * ghtml_get_title(GtkWidget * ghtml);
int ghtml_set_base(GtkWidget * ghtml, char const * url); 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"); gtk_window_set_icon_name(GTK_WINDOW(surfer->window), "stock_internet");
#endif #endif
surfer_set_title(surfer, NULL); 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); on_closex), surfer);
vbox = gtk_vbox_new(FALSE, 0); vbox = gtk_vbox_new(FALSE, 0);
#ifndef EMBEDDED #ifndef EMBEDDED
@ -185,6 +185,7 @@ Surfer * surfer_new(char const * url)
surfer->tb_back = _surfer_toolbar[0].widget; surfer->tb_back = _surfer_toolbar[0].widget;
surfer->tb_forward = _surfer_toolbar[1].widget; surfer->tb_forward = _surfer_toolbar[1].widget;
surfer->tb_stop = _surfer_toolbar[2].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; 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_back), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), FALSE);
@ -270,7 +271,7 @@ static gboolean _new_idle(gpointer data)
{ {
Surfer * surfer = data; Surfer * surfer = data;
ghtml_load_url(surfer->view, surfer->url); surfer_open(surfer, surfer->url);
return FALSE; 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 */ static int i = 0; /* XXX should be set per-window */
GtkWidget * widget; GtkWidget * widget;
char * p;
widget = gtk_bin_get_child(GTK_BIN(surfer->lb_path)); widget = gtk_bin_get_child(GTK_BIN(surfer->lb_path));
gtk_entry_set_text(GTK_ENTRY(widget), url); 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) if(i == 8)
gtk_combo_box_remove_text(GTK_COMBO_BOX(surfer->lb_path), 0); gtk_combo_box_remove_text(GTK_COMBO_BOX(surfer->lb_path), 0);
else else
@ -358,6 +365,8 @@ void surfer_set_status(Surfer * surfer, char const * status)
surfer->statusbar_id = gtk_statusbar_push(sb, surfer->statusbar_id = gtk_statusbar_push(sb,
gtk_statusbar_get_context_id(sb, ""), (status != NULL) gtk_statusbar_get_context_id(sb, ""), (status != NULL)
? status : "Ready"); ? status : "Ready");
if(status == NULL)
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), FALSE);
if(status == NULL) if(status == NULL)
{ {
gtk_progress_bar_set_text(pb, " "); gtk_progress_bar_set_text(pb, " ");
@ -378,8 +387,8 @@ void surfer_set_title(Surfer * surfer, char const * title)
{ {
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "%s%s%s", "Web surfer", title != NULL snprintf(buf, sizeof(buf), "%s%s%s", "Web surfer", (title != NULL)
? " - " : "", title != NULL ? title : ""); ? " - " : "", (title != NULL) ? title : "");
gtk_window_set_title(GTK_WINDOW(surfer->window), buf); 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_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", 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"); gtk_window_set_title(GTK_WINDOW(dialog), "Question");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL); 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) dialog = gtk_message_dialog_new((surfer != NULL)
? GTK_WINDOW(surfer->window) : NULL, ? GTK_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT, 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"); gtk_window_set_title(GTK_WINDOW(dialog), "Error");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL); gtk_widget_destroy), NULL);
@ -489,6 +502,7 @@ gboolean surfer_go_back(Surfer * surfer)
{ {
gboolean ret; gboolean ret;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ret = ghtml_go_back(surfer->view); ret = ghtml_go_back(surfer->view);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_back), ret); gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_back), ret);
return ret; return ret;
@ -500,6 +514,7 @@ gboolean surfer_go_forward(Surfer * surfer)
{ {
gboolean ret; gboolean ret;
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ret = ghtml_go_forward(surfer->view); ret = ghtml_go_forward(surfer->view);
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), ret); gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_forward), ret);
return ret; return ret;
@ -522,6 +537,7 @@ void surfer_open(Surfer * surfer, char const * url)
{ {
if(url != NULL) if(url != NULL)
{ {
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_stop(surfer->view); ghtml_stop(surfer->view);
ghtml_load_url(surfer->view, url); ghtml_load_url(surfer->view, url);
} }
@ -555,6 +571,7 @@ void surfer_open_dialog(Surfer * surfer)
/* surfer_refresh */ /* surfer_refresh */
void surfer_refresh(Surfer * surfer) void surfer_refresh(Surfer * surfer)
{ {
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_refresh(surfer->view); ghtml_refresh(surfer->view);
} }
@ -562,6 +579,7 @@ void surfer_refresh(Surfer * surfer)
/* surfer_reload */ /* surfer_reload */
void surfer_reload(Surfer * surfer) void surfer_reload(Surfer * surfer)
{ {
gtk_widget_set_sensitive(GTK_WIDGET(surfer->tb_stop), TRUE);
ghtml_reload(surfer->view); 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 */ /* surfer_warning */
void surfer_warning(Surfer * surfer, char const * message) 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) dialog = gtk_message_dialog_new((surfer != NULL)
? GTK_WINDOW(surfer->window) : NULL, ? GTK_WINDOW(surfer->window) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT, 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"); gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
gtk_widget_destroy), NULL); gtk_widget_destroy), NULL);

View File

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