30 #include <glib/gi18n.h> 31 #include <glib/gstdio.h> 32 #include <sys/types.h> 41 #include <webkit/webkit.h> 45 #include "gnc-gui-query.h" 48 #include "gnc-html-webkit.h" 49 #include "gnc-html-history.h" 52 G_DEFINE_TYPE(GncHtmlWebkit, gnc_html_webkit, GNC_TYPE_HTML )
54 static void gnc_html_webkit_dispose( GObject* obj );
55 static void gnc_html_webkit_finalize( GObject* obj );
57 #define GNC_HTML_WEBKIT_GET_PRIVATE(o) (GNC_HTML_WEBKIT(o)->priv) 59 #include "gnc-html-webkit-p.h" 62 static QofLogModule log_module = GNC_MOD_HTML;
69 extern GHashTable* gnc_html_object_handlers;
72 extern GHashTable* gnc_html_stream_handlers;
75 extern GHashTable* gnc_html_url_handlers;
77 static char error_404_format[] =
"<html><body><h3>%s</h3><p>%s</body></html>";
78 static char error_404_title[] = N_(
"Not found");
79 static char error_404_body[] = N_(
"The specified URL could not be loaded.");
81 #define BASE_URI_NAME "base-uri" 82 #define GNC_PREF_RPT_DFLT_ZOOM "default-zoom" 84 static WebKitNavigationResponse webkit_navigation_requested_cb(
85 WebKitWebView* web_view,
86 WebKitWebFrame* frame,
87 WebKitNetworkRequest* request,
89 static gboolean webkit_on_load_error (WebKitWebView *web_view,
90 WebKitWebFrame *web_frame, gchar *uri,
91 GError *error, gpointer data);
92 static void webkit_resource_load_error (WebKitWebView *web_view,
93 WebKitWebFrame *web_frame,
94 WebKitWebResource *resource,
95 GError *error, gpointer data);
96 static void webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url,
98 static gchar* handle_embedded_object( GncHtmlWebkit*
self, gchar* html_str );
100 static void gnc_html_set_base_cb( GtkHTML* gtkhtml,
const gchar* base, gpointer data );
101 static void gnc_html_link_clicked_cb( GtkHTML* html,
const gchar* url, gpointer data );
102 static gboolean gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
106 static int gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
107 gpointer user_data );
109 static void impl_webkit_show_url( GncHtml*
self, URLType type,
110 const gchar* location,
const gchar* label,
111 gboolean new_window_hint );
112 static void impl_webkit_show_data( GncHtml*
self,
const gchar* data,
int datalen );
113 static void impl_webkit_reload( GncHtml*
self, gboolean force_rebuild );
114 static void impl_webkit_copy_to_clipboard( GncHtml*
self );
115 static gboolean impl_webkit_export_to_file( GncHtml*
self,
const gchar* filepath );
116 static void impl_webkit_print( GncHtml*
self,
const gchar* jobname, gboolean export_pdf );
117 static void impl_webkit_cancel( GncHtml*
self );
118 static void impl_webkit_set_parent( GncHtml*
self, GtkWindow* parent );
119 static void impl_webkit_default_zoom_changed(gpointer prefs, gchar *pref, gpointer user_data);
122 gnc_html_webkit_init( GncHtmlWebkit*
self )
124 GncHtmlWebkitPrivate* priv;
125 GncHtmlWebkitPrivate* new_priv;
126 GtkStyleContext *stylecontext;
127 WebKitWebSettings* webkit_settings = NULL;
128 const char* default_font_family = NULL;
129 PangoFontDescription *font_desc;
132 new_priv = g_realloc( GNC_HTML(
self)->priv,
sizeof(GncHtmlWebkitPrivate) );
133 priv =
self->priv = new_priv;
134 GNC_HTML(
self)->priv = (GncHtmlPrivate*)priv;
136 priv->html_string = NULL;
137 priv->web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
140 stylecontext = gtk_widget_get_style_context (GTK_WIDGET(priv->web_view));
141 gtk_style_context_get (stylecontext, gtk_widget_get_state_flags (GTK_WIDGET(priv->web_view)),
142 "font", &font_desc, NULL);
144 default_font_family = pango_font_description_get_family (font_desc);
145 pango_font_description_free (font_desc);
148 webkit_settings = webkit_web_view_get_settings (priv->web_view);
149 g_object_set (G_OBJECT(webkit_settings),
"default-encoding",
"utf-8", NULL);
150 if (default_font_family == NULL)
152 PWARN(
"webkit_settings: Cannot get default font family.");
156 g_object_set (G_OBJECT(webkit_settings),
157 "default-font-family", default_font_family,
159 PINFO(
"webkit_settings: Set default font to [%s]", default_font_family);
163 webkit_web_view_set_full_content_zoom (priv->web_view, TRUE);
164 webkit_web_view_set_zoom_level (priv->web_view, zoom);
167 gtk_container_add( GTK_CONTAINER(priv->base.container),
168 GTK_WIDGET(priv->web_view) );
170 g_object_ref_sink( priv->base.container );
173 g_signal_connect( priv->web_view,
"navigation-requested",
174 G_CALLBACK(webkit_navigation_requested_cb),
177 g_signal_connect( priv->web_view,
"hovering-over-link",
178 G_CALLBACK(webkit_on_url_cb),
182 g_signal_connect( priv->html,
"set_base",
183 G_CALLBACK(gnc_html_set_base_cb),
186 g_signal_connect(priv->html,
"link_clicked",
187 G_CALLBACK(gnc_html_link_clicked_cb),
190 g_signal_connect (priv->html,
"object_requested",
191 G_CALLBACK (gnc_html_object_requested_cb),
194 g_signal_connect (priv->html,
"button_press_event",
195 G_CALLBACK (gnc_html_button_press_cb),
198 g_signal_connect (priv->html,
"submit",
199 G_CALLBACK(gnc_html_submit_cb),
202 g_signal_connect (priv->web_view,
"load-error",
203 G_CALLBACK (webkit_on_load_error),
206 g_signal_connect (priv->web_view,
"resource-load-failed",
207 G_CALLBACK (webkit_resource_load_error),
211 GNC_PREF_RPT_DFLT_ZOOM,
212 impl_webkit_default_zoom_changed,
215 LEAVE(
"retval %p",
self);
219 gnc_html_webkit_class_init( GncHtmlWebkitClass* klass )
221 GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
222 GncHtmlClass* html_class = GNC_HTML_CLASS(klass);
224 gobject_class->dispose = gnc_html_webkit_dispose;
225 gobject_class->finalize = gnc_html_webkit_finalize;
227 html_class->show_url = impl_webkit_show_url;
228 html_class->show_data = impl_webkit_show_data;
229 html_class->reload = impl_webkit_reload;
230 html_class->copy_to_clipboard = impl_webkit_copy_to_clipboard;
231 html_class->export_to_file = impl_webkit_export_to_file;
232 html_class->print = impl_webkit_print;
233 html_class->cancel = impl_webkit_cancel;
234 html_class->set_parent = impl_webkit_set_parent;
238 gnc_html_webkit_dispose( GObject* obj )
240 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(obj);
241 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
243 if ( priv->web_view != NULL )
245 gtk_container_remove( GTK_CONTAINER(priv->base.container),
246 GTK_WIDGET(priv->web_view) );
247 priv->web_view = NULL;
250 if ( priv->html_string != NULL )
252 g_free( priv->html_string );
253 priv->html_string = NULL;
257 GNC_PREF_RPT_DFLT_ZOOM,
258 impl_webkit_default_zoom_changed,
261 G_OBJECT_CLASS(gnc_html_webkit_parent_class)->dispose( obj );
265 gnc_html_webkit_finalize( GObject* obj )
267 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(obj);
274 G_OBJECT_CLASS(gnc_html_webkit_parent_class)->finalize( obj );
280 extract_base_name(URLType type,
const gchar* path)
282 gchar machine_rexp[] =
"^(//[^/]*)/*(/.*)?$";
283 gchar path_rexp[] =
"^/*(.*)/+([^/]*)$";
284 regex_t compiled_m, compiled_p;
286 gchar * machine = NULL, * location = NULL, * base = NULL;
287 gchar * basename = NULL;
290 if (!path)
return NULL;
292 regcomp(&compiled_m, machine_rexp, REG_EXTENDED);
293 regcomp(&compiled_p, path_rexp, REG_EXTENDED);
295 if (!g_strcmp0 (type, URL_TYPE_HTTP) ||
296 !g_strcmp0 (type, URL_TYPE_SECURE) ||
297 !g_strcmp0 (type, URL_TYPE_FTP))
302 if (!regexec(&compiled_m, path, 4, match, 0))
305 if (match[1].rm_so != -1)
307 machine = g_strndup(path + match[1].rm_so,
308 match[1].rm_eo - match[1].rm_so);
311 if (match[2].rm_so != -1)
313 location = g_strndup(path + match[2].rm_so,
314 match[2].rm_eo - match[2].rm_so);
321 location = g_strdup(path);
326 if (!regexec(&compiled_p, location, 4, match, 0))
328 if (match[1].rm_so != -1)
330 base = g_strndup(location + match[1].rm_so,
331 match[1].rm_eo - match[1].rm_so);
340 regfree(&compiled_m);
341 regfree(&compiled_p);
345 if (base && (strlen(base) > 0))
347 basename = g_strconcat(machine,
"/", base,
"/", NULL);
351 basename = g_strconcat(machine,
"/", NULL);
356 if (base && (strlen(base) > 0))
358 basename = g_strdup(base);
385 handle_embedded_object( GncHtmlWebkit*
self, gchar* html_str )
390 gchar* remainder_str = html_str;
392 gchar* end_object_tag;
393 gchar* object_contents;
394 gchar* html_str_start = NULL;
395 gchar* html_str_middle;
396 gchar* html_str_result = NULL;
397 gchar* classid_start;
403 object_tag = g_strstr_len( remainder_str, -1,
"<object classid=" );
407 classid_start = object_tag + strlen(
"<object classid=" ) + 1;
408 classid_end = g_strstr_len( classid_start, -1,
"\"" );
409 classid_str = g_strndup( classid_start, (classid_end - classid_start) );
411 end_object_tag = g_strstr_len( object_tag, -1,
"</object>" );
412 if ( end_object_tag == NULL )
416 g_free (classid_str);
417 g_free (html_str_result);
418 return g_strdup (html_str);
420 end_object_tag += strlen(
"</object>" );
421 object_contents = g_strndup( object_tag, (end_object_tag - object_tag) );
423 h = g_hash_table_lookup( gnc_html_object_handlers, classid_str );
426 (void)h( GNC_HTML(
self), object_contents, &html_str_middle );
430 html_str_middle = g_strdup_printf(
"No handler found for classid \"%s\"", classid_str );
433 html_str_start = html_str_result;
434 new_chunk = g_strndup (remainder_str, (object_tag - remainder_str));
436 html_str_result = g_strconcat (new_chunk, html_str_middle, NULL);
438 html_str_result = g_strconcat (html_str_start, new_chunk, html_str_middle, NULL);
440 g_free( html_str_start );
442 g_free( html_str_middle );
444 remainder_str = end_object_tag;
445 object_tag = g_strstr_len( remainder_str, -1,
"<object classid=" );
450 html_str_start = html_str_result;
451 html_str_result = g_strconcat (html_str_start, remainder_str, NULL);
452 g_free (html_str_start);
455 html_str_result = g_strdup (remainder_str);
457 return html_str_result;
467 load_to_stream( GncHtmlWebkit*
self, URLType type,
468 const gchar* location,
const gchar* label )
472 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
474 DEBUG(
"type %s, location %s, label %s", type ? type :
"(null)",
475 location ? location :
"(null)", label ? label :
"(null)");
477 g_return_val_if_fail(
self != NULL, FALSE );
479 if ( gnc_html_stream_handlers != NULL )
481 GncHTMLStreamCB stream_handler;
483 stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
484 if ( stream_handler )
486 GncHtml *weak_html = GNC_HTML(
self);
489 g_object_add_weak_pointer(G_OBJECT(
self), (gpointer *)(&weak_html));
491 ok = stream_handler(location, &fdata, &fdata_len);
500 g_object_remove_weak_pointer(G_OBJECT(
self),
501 (gpointer*)(&weak_html));
505 fdata = fdata ? fdata : g_strdup(
"");
510 if (g_strstr_len(fdata, -1,
"<object classid=") != NULL) {
512 new_fdata = handle_embedded_object(
self, fdata);
518 if (priv->html_string != NULL) {
519 g_free(priv->html_string);
521 priv->html_string = g_strdup(fdata);
522 impl_webkit_show_data(GNC_HTML(
self), fdata, strlen(fdata));
528 fdata = fdata ? fdata :
529 g_strdup_printf( error_404_format,
530 _(error_404_title), _(error_404_body) );
531 webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
538 while ( gtk_events_pending() )
540 gtk_main_iteration();
551 if ( !g_strcmp0( type, URL_TYPE_SECURE ) ||
552 !g_strcmp0( type, URL_TYPE_HTTP ) )
555 if ( !g_strcmp0( type, URL_TYPE_SECURE ) )
557 if ( !https_allowed() )
559 gnc_error_dialog (GTK_WINDOW (priv->base.parent),
"%s",
560 _(
"Secure HTTP access is disabled. " 561 "You can enable it in the Network section of " 562 "the Preferences dialog."));
567 if ( !http_allowed() )
569 gnc_error_dialog (GTK_WINDOW (priv->base.parent),
"%s",
570 _(
"Network HTTP access is disabled. " 571 "You can enable it in the Network section of " 572 "the Preferences dialog."));
576 gnc_build_url( type, location, label );
582 PWARN(
"load_to_stream for inappropriate type\n" 584 location ? location :
"(null)",
585 label ? label :
"(null)" );
586 fdata = g_strdup_printf( error_404_format,
587 _(error_404_title), _(error_404_body) );
588 webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
604 gnc_html_link_clicked_cb( GtkHTML* html,
const gchar* url, gpointer data )
607 gchar* location = NULL;
609 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(data);
611 DEBUG(
"Clicked %s", url);
612 type = gnc_html_parse_url( GNC_HTML(
self), url, &location, &label );
613 gnc_html_show_url( GNC_HTML(
self), type, location, label, 0 );
624 static WebKitNavigationResponse
625 webkit_navigation_requested_cb( WebKitWebView* web_view, WebKitWebFrame* frame,
626 WebKitNetworkRequest* request,
630 gchar* location = NULL;
632 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(data);
633 const gchar* url = webkit_network_request_get_uri( request );
635 ENTER(
"requesting %s", url );
636 if ( strcmp( url, BASE_URI_NAME ) == 0 )
638 LEAVE(
"URI is %s", BASE_URI_NAME);
639 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
642 type = gnc_html_parse_url( GNC_HTML(
self), url, &location, &label );
643 if ( strcmp( type,
"file" ) == 0 )
645 LEAVE(
"URI type is 'file'");
646 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
648 gnc_html_show_url( GNC_HTML(
self), type, location, label, 0 );
654 return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
658 webkit_on_load_error (WebKitWebView *web_view, WebKitWebFrame *web_frame,
659 gchar *uri, GError *error, gpointer data)
661 PERR (
"WebKit load of %s failed due to %s\n", uri, error->message);
666 webkit_resource_load_error (WebKitWebView *web_view, WebKitWebFrame *web_frame,
667 WebKitWebResource *resource, GError *error,
670 const gchar *uri = webkit_web_resource_get_uri (resource);
671 const gchar *type = webkit_web_resource_get_mime_type (resource);
672 PERR (
"WebKit load of resource %s, type %s, failed due to %s\n",
673 uri, type, error->message);
683 gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
686 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(data);
690 if ( !eb || !(eb->classid) || !gnc_html_object_handlers )
return FALSE;
692 h = g_hash_table_lookup( gnc_html_object_handlers, eb->classid );
695 return h( GNC_HTML(
self), eb, data );
709 webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url, gpointer data )
711 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(data);
712 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
714 DEBUG(
"Rollover %s", url ? url :
"(null)" );
715 g_free( priv->base.current_link );
716 priv->base.current_link = g_strdup( url );
717 if ( priv->base.flyover_cb )
719 (priv->base.flyover_cb)( GNC_HTML(
self), url, priv->base.flyover_cb_data );
729 gnc_html_set_base_cb( GtkHTML* gtkhtml,
const gchar* base,
732 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(data);
733 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
735 gchar* location = NULL;
738 DEBUG(
"Setting base location to %s", base );
739 type = gnc_html_parse_url( GNC_HTML(
self), base, &location, &label );
741 g_free( priv->base.base_location );
744 priv->base.base_type = type;
745 priv->base.base_location = location;
756 gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
759 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(user_data);
760 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
762 DEBUG(
"Button Press" );
763 if ( priv->base.button_cb != NULL )
765 (priv->base.button_cb)( GNC_HTML(
self), event, priv->base.button_cb_data );
781 gnc_html_open_scm( GncHtmlWebkit*
self,
const gchar * location,
782 const gchar * label,
int newwin )
784 PINFO(
"location='%s'", location ? location :
"(null)");
795 impl_webkit_show_data( GncHtml*
self,
const gchar* data,
int datalen )
797 GncHtmlWebkitPrivate* priv;
798 #define TEMPLATE_REPORT_FILE_NAME "gnc-report-XXXXXX.html" 803 g_return_if_fail(
self != NULL );
804 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
806 ENTER(
"datalen %d, data %20.20s", datalen, data );
808 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
815 filename = g_build_filename(g_get_tmp_dir(), TEMPLATE_REPORT_FILE_NAME, (gchar *)NULL);
816 fd = g_mkstemp( filename );
817 impl_webkit_export_to_file(
self, filename );
820 uri = g_strdup_printf(
"file:///%s", filename );
822 uri = g_strdup_printf(
"file://%s", filename );
825 DEBUG(
"Loading uri '%s'", uri);
826 webkit_web_view_load_uri( priv->web_view, uri );
841 impl_webkit_show_url( GncHtml*
self, URLType type,
842 const gchar* location,
const gchar* label,
843 gboolean new_window_hint )
845 GncHTMLUrlCB url_handler;
847 GncHtmlWebkitPrivate* priv;
848 gboolean stream_loaded = FALSE;
850 g_return_if_fail(
self != NULL );
851 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
852 g_return_if_fail( location != NULL );
854 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
857 if ( new_window_hint == 0 )
859 if ( priv->base.urltype_cb )
861 new_window = !((priv->base.urltype_cb)( type ));
875 gnc_html_cancel( GNC_HTML(
self) );
878 if ( gnc_html_url_handlers )
880 url_handler = g_hash_table_lookup( gnc_html_url_handlers, type );
892 result.load_to_stream = FALSE;
893 result.url_type = type;
894 result.location = NULL;
896 result.base_type = URL_TYPE_FILE;
897 result.base_location = NULL;
898 result.error_message = NULL;
899 result.parent = GTK_WINDOW (priv->base.parent);
901 ok = url_handler( location, label, new_window, &result );
904 if ( result.error_message )
906 gnc_error_dialog (GTK_WINDOW (priv->base.parent),
"%s", result.error_message );
911 gnc_error_dialog (GTK_WINDOW (priv->base.parent), _(
"There was an error accessing %s."), location );
914 if ( priv->base.load_cb )
916 priv->base.load_cb( GNC_HTML(
self), result.url_type,
917 location, label, priv->base.load_cb_data );
920 else if ( result.load_to_stream )
922 gnc_html_history_node *hnode;
923 const char *new_location;
924 const char *new_label;
926 new_location = result.location ? result.location : location;
927 new_label = result.label ? result.label : label;
928 hnode = gnc_html_history_node_new( result.url_type, new_location, new_label );
930 gnc_html_history_append( priv->base.history, hnode );
932 g_free( priv->base.base_location );
933 priv->base.base_type = result.base_type;
934 priv->base.base_location =
935 g_strdup( extract_base_name( result.base_type, new_location ) );
936 DEBUG(
"resetting base location to %s",
937 priv->base.base_location ? priv->base.base_location :
"(null)" );
939 stream_loaded = load_to_stream( GNC_HTML_WEBKIT(
self),
941 new_location, new_label );
943 if ( stream_loaded && priv->base.load_cb != NULL )
945 priv->base.load_cb( GNC_HTML(
self), result.url_type,
946 new_location, new_label, priv->base.load_cb_data );
950 g_free( result.location );
951 g_free( result.label );
952 g_free( result.base_location );
953 g_free( result.error_message );
958 if ( g_strcmp0( type, URL_TYPE_SCHEME ) == 0 )
960 gnc_html_open_scm( GNC_HTML_WEBKIT(
self), location, label, new_window );
963 else if ( g_strcmp0( type, URL_TYPE_JUMP ) == 0 )
967 else if ( g_strcmp0( type, URL_TYPE_SECURE ) == 0 ||
968 g_strcmp0( type, URL_TYPE_HTTP ) == 0 ||
969 g_strcmp0( type, URL_TYPE_FILE ) == 0 )
974 if ( g_strcmp0( type, URL_TYPE_SECURE ) == 0 )
976 if ( !https_allowed() )
978 gnc_error_dialog (GTK_WINDOW (priv->base.parent),
"%s",
979 _(
"Secure HTTP access is disabled. " 980 "You can enable it in the Network section of " 981 "the Preferences dialog.") );
986 if ( g_strcmp0( type, URL_TYPE_HTTP ) == 0 )
988 if ( !http_allowed() )
990 gnc_error_dialog (GTK_WINDOW (priv->base.parent),
"%s",
991 _(
"Network HTTP access is disabled. " 992 "You can enable it in the Network section of " 993 "the Preferences dialog.") );
998 priv->base.base_type = type;
1000 if ( priv->base.base_location != NULL ) g_free( priv->base.base_location );
1001 priv->base.base_location = extract_base_name( type, location );
1004 gnc_html_history_append( priv->base.history,
1005 gnc_html_history_node_new( type, location, label ) );
1006 stream_loaded = load_to_stream( GNC_HTML_WEBKIT(
self), type,
1015 PERR(
"URLType %s not supported.", type );
1018 if ( stream_loaded && priv->base.load_cb != NULL )
1020 (priv->base.load_cb)( GNC_HTML(
self), type, location, label, priv->base.load_cb_data );
1033 impl_webkit_reload( GncHtml*
self, gboolean force_rebuild )
1035 GncHtmlWebkitPrivate* priv;
1037 g_return_if_fail(
self != NULL );
1038 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
1040 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1042 if ( force_rebuild )
1044 gnc_html_history_node *n = gnc_html_history_get_current( priv->base.history );
1046 gnc_html_show_url(
self, n->type, n->location, n->label, 0 );
1049 webkit_web_view_reload( priv->web_view );
1059 gnc_html_webkit_new(
void )
1061 GncHtmlWebkit*
self = g_object_new( GNC_TYPE_HTML_WEBKIT, NULL );
1062 return GNC_HTML(
self);
1071 webkit_cancel_helper(gpointer key, gpointer value, gpointer user_data)
1074 g_list_free((GList *)value);
1079 impl_webkit_cancel( GncHtml*
self )
1081 GncHtmlWebkitPrivate* priv;
1083 g_return_if_fail(
self != NULL );
1084 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
1086 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1091 g_hash_table_foreach_remove( priv->base.request_info, webkit_cancel_helper, NULL );
1095 impl_webkit_copy_to_clipboard( GncHtml*
self )
1097 GncHtmlWebkitPrivate* priv;
1099 g_return_if_fail(
self != NULL );
1100 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
1102 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1103 if ( webkit_web_view_can_copy_clipboard( priv->web_view ) )
1105 webkit_web_view_copy_clipboard( priv->web_view );
1117 impl_webkit_export_to_file( GncHtml*
self,
const char *filepath )
1120 GncHtmlWebkitPrivate* priv;
1122 g_return_val_if_fail(
self != NULL, FALSE );
1123 g_return_val_if_fail( GNC_IS_HTML_WEBKIT(
self), FALSE );
1124 g_return_val_if_fail( filepath != NULL, FALSE );
1126 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1127 if ( priv->html_string == NULL )
1131 fh = g_fopen( filepath,
"w" );
1135 gint len = strlen( priv->html_string );
1137 written = fwrite( priv->html_string, 1, len, fh );
1140 if ( written != len )
1166 impl_webkit_print( GncHtml*
self,
const gchar* jobname, gboolean export_pdf )
1168 gchar *export_filename = NULL;
1169 GncHtmlWebkitPrivate* priv;
1170 WebKitWebFrame* frame;
1171 GtkPrintOperation* op = gtk_print_operation_new();
1172 GError* error = NULL;
1173 GtkPrintSettings *print_settings;
1175 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1176 frame = webkit_web_view_get_main_frame( priv->web_view );
1179 print_settings = gtk_print_operation_get_print_settings (op);
1180 if (!print_settings)
1182 print_settings = gtk_print_settings_new();
1183 gtk_print_operation_set_print_settings(op, print_settings);
1186 gtk_print_operation_set_unit( op, GTK_UNIT_POINTS );
1190 if (g_str_has_suffix(jobname,
".pdf"))
1192 export_filename = g_strdup(jobname);
1196 export_filename = g_strconcat(jobname,
".pdf", NULL);
1205 gchar *export_dirname = NULL;
1211 dialog = gtk_file_chooser_dialog_new (_(
"Export to PDF File"),
1213 GTK_FILE_CHOOSER_ACTION_SAVE,
1214 _(
"_Cancel"), GTK_RESPONSE_CANCEL,
1215 _(
"_Save"), GTK_RESPONSE_ACCEPT,
1217 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
1220 basename = g_path_get_basename(jobname);
1221 if (strcmp(basename, jobname) != 0)
1223 gchar *tmp_basename;
1224 gchar *tmp_dirname = g_path_get_dirname(jobname);
1226 if (g_file_test(tmp_dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1230 export_dirname = tmp_dirname;
1235 tmp_basename = g_path_get_basename(export_filename);
1236 g_free(export_filename);
1237 export_filename = tmp_basename;
1239 g_free(tmp_dirname);
1244 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(dialog), export_filename);
1249 const char* tmp_dirname = gtk_print_settings_get(print_settings,
1252 if (g_file_test(tmp_dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1254 export_dirname = g_strdup(tmp_dirname);
1261 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), export_dirname);
1263 g_free(export_dirname);
1265 result = gtk_dialog_run (GTK_DIALOG (dialog));
1271 if (result == GTK_RESPONSE_ACCEPT)
1275 char *tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1276 g_free(export_filename);
1277 export_filename = tmp;
1280 dirname = g_path_get_dirname(export_filename);
1281 if (g_file_test(dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1287 gtk_widget_destroy (dialog);
1289 if (result != GTK_RESPONSE_ACCEPT)
1292 g_free(export_filename);
1293 g_object_unref( op );
1298 gtk_print_operation_set_export_filename(op, export_filename);
1301 webkit_web_frame_print_full( frame, op, GTK_PRINT_OPERATION_ACTION_EXPORT, &error );
1307 if (gtk_print_settings_has_key(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI))
1311 const gchar *olduri = gtk_print_settings_get(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
1312 gchar *dirname = g_path_get_dirname(olduri);
1313 gchar *newuri = (g_strcmp0(dirname,
".") == 0)
1314 ? g_strdup(export_filename)
1315 : g_build_filename(dirname, export_filename, NULL);
1319 gtk_print_settings_set(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI, newuri);
1327 gtk_print_settings_set(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI, export_filename);
1331 webkit_web_frame_print_full( frame, op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, &error );
1334 if ( error != NULL )
1336 GtkWidget* window = gtk_widget_get_toplevel( GTK_WIDGET(priv->web_view) );
1337 GtkWidget* dialog = gtk_message_dialog_new( gtk_widget_is_toplevel(window) ? GTK_WINDOW(window) : NULL,
1338 GTK_DIALOG_DESTROY_WITH_PARENT,
1341 "%s", error->message );
1342 g_error_free( error );
1344 g_signal_connect( dialog,
"response", G_CALLBACK(gtk_widget_destroy), NULL);
1345 gtk_widget_show( dialog );
1350 g_object_unref( op );
1351 g_free(export_filename);
1355 impl_webkit_set_parent( GncHtml*
self, GtkWindow* parent )
1357 GncHtmlWebkitPrivate* priv;
1359 g_return_if_fail(
self != NULL );
1360 g_return_if_fail( GNC_IS_HTML_WEBKIT(
self) );
1362 priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1363 priv->base.parent = GTK_WIDGET(parent);
1367 impl_webkit_default_zoom_changed(gpointer prefs, gchar *pref, gpointer user_data)
1370 GncHtmlWebkit*
self = GNC_HTML_WEBKIT(user_data);
1371 GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(
self);
1373 g_return_if_fail(user_data != NULL);
1376 webkit_web_view_set_zoom_level (priv->web_view, zoom);
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
#define GNC_GTK_PRINT_SETTINGS_EXPORT_DIR
Key for saving the PDF-export directory in the print settings.
#define PINFO(format, args...)
Print an informational note.
#define DEBUG(format, args...)
Print a debugging message.
void gnc_print_operation_save_print_settings(GtkPrintOperation *op)
Retrieve the print settings from the GtkPrintOperation op and save them in a static variable...
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
#define PWARN(format, args...)
Log a warning.
Account handling public routines.
void gnc_print_operation_init(GtkPrintOperation *op, const gchar *jobname)
If print settings have been saved by gnc_print_operation_save_print_settings(), then set them on the ...
All type declarations for the whole Gnucash engine.
Generic api to store and retrieve preferences.
#define LEAVE(format, args...)
Print a function exit debugging message.
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
gdouble gnc_prefs_get_float(const gchar *group, const gchar *pref_name)
Get an float value from the preferences backend.