[gtkhtml] Bug 598567 - Can only insert local image files



commit 44be36ff903d507194e21051737f3f1aa0aa2228
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Oct 20 16:37:18 2009 -0400

    Bug 598567 - Can only insert local image files

 components/editor/gtkhtml-editor-builder.ui |    1 +
 components/editor/gtkhtml-editor-private.c  |  214 ++++++++++++++++++++++++++-
 components/editor/gtkhtml-editor-private.h  |   26 ++++
 components/editor/gtkhtml-editor-signals.c  |    8 +-
 components/editor/gtkhtml-editor.c          |   87 +++++++-----
 components/editor/gtkhtml-editor.h          |    4 +-
 6 files changed, 295 insertions(+), 45 deletions(-)
---
diff --git a/components/editor/gtkhtml-editor-builder.ui b/components/editor/gtkhtml-editor-builder.ui
index 05afc91..939d36e 100644
--- a/components/editor/gtkhtml-editor-builder.ui
+++ b/components/editor/gtkhtml-editor-builder.ui
@@ -3094,6 +3094,7 @@
                       <object class="GtkFileChooserButton" id="image-properties-source-file-chooser">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="local_only">False</property>
                         <signal handler="gtkhtml_editor_image_properties_source_file_set_cb" name="file_set" object="image-properties-window"/>
                       </object>
                       <packing>
diff --git a/components/editor/gtkhtml-editor-private.c b/components/editor/gtkhtml-editor-private.c
index 14b8509..8a44207 100644
--- a/components/editor/gtkhtml-editor-private.c
+++ b/components/editor/gtkhtml-editor-private.c
@@ -153,6 +153,166 @@ editor_replace_all_cb (GtkhtmlEditor *editor,
 
 /************************* End Spell Dialog Callbacks ************************/
 
+/************************ Begin URI Request Callbacks ************************/
+
+static GtkhtmlEditorRequest *
+editor_request_new (GtkhtmlEditor *editor,
+                    const gchar *uri,
+                    GtkHTMLStream *stream,
+                    GCancellable *cancellable,
+                    GAsyncReadyCallback callback,
+                    gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GtkhtmlEditorRequest *request;
+	GList *list;
+
+	request = g_slice_new (GtkhtmlEditorRequest);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (editor), callback,
+		user_data, gtkhtml_editor_request_async);
+
+	if (cancellable != NULL)
+		g_object_ref (cancellable);
+
+	/* 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->editor = g_object_ref (editor);
+	request->cancellable = cancellable;
+	request->simple = simple;
+	request->input_stream = NULL;
+	request->output_stream = stream;
+
+	list = request->editor->priv->requests;
+	list = g_list_prepend (list, request);
+	request->editor->priv->requests = list;
+
+	return request;
+}
+
+static void
+editor_request_free (GtkhtmlEditorRequest *request)
+{
+	GList *list;
+
+	/* Do not free the GSimpleAsyncResult. */
+
+	list = request->editor->priv->requests;
+	list = g_list_remove (list, request);
+	request->editor->priv->requests = list;
+
+	g_object_unref (request->file);
+	g_object_unref (request->editor);
+
+	if (request->cancellable != NULL)
+		g_object_unref (request->cancellable);
+
+	if (request->input_stream != NULL)
+		g_object_unref (request->input_stream);
+
+	g_slice_free (GtkhtmlEditorRequest, request);
+}
+
+static gboolean
+editor_request_check_for_error (GtkhtmlEditorRequest *request,
+                                GError *error)
+{
+	GtkHTML *html;
+	GtkHTMLStream *stream;
+	GSimpleAsyncResult *simple;
+
+	if (error == NULL)
+		return FALSE;
+
+	stream = request->output_stream;
+	html = gtkhtml_editor_get_html (request->editor);
+	gtk_html_end (html, stream, GTK_HTML_STREAM_ERROR);
+
+	/* Steal the result. */
+	simple = request->simple;
+	request->simple = NULL;
+
+	g_simple_async_result_set_from_error (simple, error);
+	g_simple_async_result_complete (simple);
+	g_error_free (error);
+
+	editor_request_free (request);
+
+	return TRUE;
+}
+
+static void
+editor_request_stream_read_cb (GInputStream *input_stream,
+                               GAsyncResult *result,
+                               GtkhtmlEditorRequest *request)
+{
+	GtkHTML *html;
+	GtkHTMLStream *stream;
+	gssize bytes_read;
+	GError *error = NULL;
+
+	stream = request->output_stream;
+	html = gtkhtml_editor_get_html (request->editor);
+
+	bytes_read = g_input_stream_read_finish (input_stream, result, &error);
+
+	if (editor_request_check_for_error (request, error))
+		return;
+
+	if (bytes_read == 0) {
+		GSimpleAsyncResult *simple;
+
+		/* Steal the result. */
+		simple = request->simple;
+		request->simple = NULL;
+
+		gtk_html_end (html, stream, GTK_HTML_STREAM_OK);
+
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+		g_simple_async_result_complete (simple);
+		editor_request_free (request);
+
+		return;
+	}
+
+	gtk_html_write (html, stream, request->buffer, bytes_read);
+
+	g_input_stream_read_async (
+		request->input_stream, request->buffer,
+		sizeof (request->buffer), G_PRIORITY_DEFAULT,
+		request->cancellable, (GAsyncReadyCallback)
+		editor_request_stream_read_cb, request);
+}
+
+static void
+editor_request_read_cb (GFile *file,
+                        GAsyncResult *result,
+                        GtkhtmlEditorRequest *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 (editor_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)
+		editor_request_stream_read_cb, request);
+}
+
+/************************* End URI Request Callbacks *************************/
+
 void
 gtkhtml_editor_private_init (GtkhtmlEditor *editor)
 {
@@ -412,6 +572,10 @@ gtkhtml_editor_private_finalize (GtkhtmlEditor *editor)
 {
 	GtkhtmlEditorPrivate *priv = editor->priv;
 
+	/* All URI requests should be complete or cancelled by now. */
+	if (priv->requests != NULL)
+		g_warning ("Finalizing GtkhtmlEditor with active URI requests");
+
 	g_hash_table_destroy (priv->available_spell_checkers);
 	g_hash_table_destroy (priv->spell_suggestion_menus);
 
@@ -561,8 +725,8 @@ gtkhtml_editor_insert_file (GtkhtmlEditor *editor,
 		GTK_STOCK_OPEN, GTK_RESPONSE_OK,
 		NULL);
 
-	gtk_dialog_set_default_response (
-		GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
 	g_signal_connect (dialog, "response", response_cb, editor);
 
@@ -574,6 +738,52 @@ gtkhtml_editor_insert_file (GtkhtmlEditor *editor,
 }
 
 void
+gtkhtml_editor_request_async (GtkhtmlEditor *editor,
+                              const gchar *uri,
+                              GtkHTMLStream *stream,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+	GtkhtmlEditorRequest *request;
+
+	g_return_if_fail (GTKHTML_IS_EDITOR (editor));
+	g_return_if_fail (uri != NULL);
+	g_return_if_fail (stream != NULL);
+	g_return_if_fail (callback != NULL);
+
+	if (cancellable != NULL)
+		g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+	request = editor_request_new (
+		editor, uri, stream, cancellable, callback, user_data);
+
+	g_file_read_async (
+		request->file, G_PRIORITY_DEFAULT,
+		request->cancellable, (GAsyncReadyCallback)
+		editor_request_read_cb, request);
+}
+
+gboolean
+gtkhtml_editor_request_finish (GtkhtmlEditor *editor,
+                               GAsyncResult *result,
+                               GError **error)
+{
+	GSimpleAsyncResult *simple;
+	gboolean success;
+
+	g_return_val_if_fail (GTKHTML_IS_EDITOR (editor), FALSE);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	success = g_simple_async_result_get_op_res_gboolean (simple);
+	g_simple_async_result_propagate_error (simple, error);
+	g_object_unref (simple);
+
+	return success;
+}
+
+void
 gtkhtml_editor_show_uri (GtkWindow *parent,
                          const gchar *uri)
 {
diff --git a/components/editor/gtkhtml-editor-private.h b/components/editor/gtkhtml-editor-private.h
index df3cb6b..a9df794 100644
--- a/components/editor/gtkhtml-editor-private.h
+++ b/components/editor/gtkhtml-editor-private.h
@@ -84,6 +84,8 @@
 
 G_BEGIN_DECLS
 
+typedef struct _GtkhtmlEditorRequest GtkhtmlEditorRequest;
+
 typedef enum {
 	EDITOR_MODE_HTML,
 	EDITOR_MODE_TEXT
@@ -161,6 +163,10 @@ struct _GtkhtmlEditorPrivate {
 
 	HTMLObject *table_object;
 
+	/* Active URI Requests */
+
+	GList *requests;
+
 	/*** Miscellaneous ***/
 
 	/* Note, 'filename' is not used by GtkhtmlEditor itself but is here
@@ -175,6 +181,17 @@ struct _GtkhtmlEditorPrivate {
 	gboolean changed;
 };
 
+struct _GtkhtmlEditorRequest {
+	GtkhtmlEditor *editor;
+	GCancellable *cancellable;
+	GSimpleAsyncResult *simple;
+
+	GFile *file;
+	GInputStream *input_stream;
+	GtkHTMLStream *output_stream;
+	gchar buffer[4096];
+};
+
 void		gtkhtml_editor_private_init	 (GtkhtmlEditor *editor);
 void		gtkhtml_editor_private_dispose	 (GtkhtmlEditor *editor);
 void		gtkhtml_editor_private_finalize	 (GtkhtmlEditor *editor);
@@ -192,6 +209,15 @@ gboolean	gtkhtml_editor_get_file_contents (const gchar *filename,
 gint		gtkhtml_editor_insert_file	 (GtkhtmlEditor *editor,
 						  const gchar *title,
 						  GCallback response_cb);
+void		gtkhtml_editor_request_async	 (GtkhtmlEditor *editor,
+						  const gchar *uri,
+						  GtkHTMLStream *stream,
+						  GCancellable *cancellable,
+						  GAsyncReadyCallback callback,
+						  gpointer user_data);
+gboolean	gtkhtml_editor_request_finish	 (GtkhtmlEditor *editor,
+						  GAsyncResult *result,
+						  GError **error);
 void		gtkhtml_editor_show_uri		 (GtkWindow *parent,
 						  const gchar *uri);
 void		gtkhtml_editor_spell_check	 (GtkhtmlEditor *editor,
diff --git a/components/editor/gtkhtml-editor-signals.c b/components/editor/gtkhtml-editor-signals.c
index 20a0446..3cafd98 100644
--- a/components/editor/gtkhtml-editor-signals.c
+++ b/components/editor/gtkhtml-editor-signals.c
@@ -784,12 +784,8 @@ gtkhtml_editor_image_properties_show_window_cb (GtkWidget *window))
 		|| html_object_get_data (parent, "template_image") == NULL)
 		&& image->image_ptr->url != NULL) {
 
-		gchar *filename;
-
-		filename = gtk_html_filename_from_uri (image->image_ptr->url);
-		gtk_file_chooser_set_filename (
-			GTK_FILE_CHOOSER (widget), filename);
-		g_free (filename);
+		gtk_file_chooser_set_uri (
+			GTK_FILE_CHOOSER (widget), image->image_ptr->url);
 	} else
 		gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (widget));
 
diff --git a/components/editor/gtkhtml-editor.c b/components/editor/gtkhtml-editor.c
index fad0cee..737af53 100644
--- a/components/editor/gtkhtml-editor.c
+++ b/components/editor/gtkhtml-editor.c
@@ -473,30 +473,6 @@ static GtkHTMLEditorAPI editor_api = {
 	editor_method_set_language
 };
 
-static void
-editor_cut_clipboard (GtkhtmlEditor *editor)
-{
-	gtk_html_command (gtkhtml_editor_get_html (editor), "cut");
-}
-
-static void
-editor_copy_clipboard (GtkhtmlEditor *editor)
-{
-	gtk_html_command (gtkhtml_editor_get_html (editor), "copy");
-}
-
-static void
-editor_paste_clipboard (GtkhtmlEditor *editor)
-{
-	gtk_html_command (gtkhtml_editor_get_html (editor), "paste");
-}
-
-static void
-editor_select_all (GtkhtmlEditor *editor)
-{
-	gtk_html_command (gtkhtml_editor_get_html (editor), "select-all");
-}
-
 static GObject *
 editor_constructor (GType type,
                     guint n_construct_properties,
@@ -727,6 +703,49 @@ editor_finalize (GObject *object)
 }
 
 static void
+editor_cut_clipboard (GtkhtmlEditor *editor)
+{
+	gtk_html_command (gtkhtml_editor_get_html (editor), "cut");
+}
+
+static void
+editor_copy_clipboard (GtkhtmlEditor *editor)
+{
+	gtk_html_command (gtkhtml_editor_get_html (editor), "copy");
+}
+
+static void
+editor_paste_clipboard (GtkhtmlEditor *editor)
+{
+	gtk_html_command (gtkhtml_editor_get_html (editor), "paste");
+}
+
+static void
+editor_select_all (GtkhtmlEditor *editor)
+{
+	gtk_html_command (gtkhtml_editor_get_html (editor), "select-all");
+}
+
+static void
+editor_uri_requested_ready_cb (GtkhtmlEditor *editor,
+                               GAsyncResult *result)
+{
+	/* XXX Do something in the event of an error? */
+	gtkhtml_editor_request_finish (editor, result, NULL);
+}
+
+static void
+editor_uri_requested (GtkhtmlEditor *editor,
+                      const gchar *uri,
+                      GtkHTMLStream *stream)
+{
+	/* XXX Currently no way to cancel this. */
+	gtkhtml_editor_request_async (
+		editor, uri, stream, NULL, (GAsyncReadyCallback)
+		editor_uri_requested_ready_cb, NULL);
+}
+
+static void
 editor_class_init (GtkhtmlEditorClass *class)
 {
 	GObjectClass *object_class;
@@ -745,6 +764,7 @@ editor_class_init (GtkhtmlEditorClass *class)
 	class->copy_clipboard = editor_copy_clipboard;
 	class->paste_clipboard = editor_paste_clipboard;
 	class->select_all = editor_select_all;
+	class->uri_requested = editor_uri_requested;
 
 	g_object_class_install_property (
 		object_class,
@@ -1608,26 +1628,23 @@ gtkhtml_editor_insert_html (GtkhtmlEditor *editor,
 	gtk_html_insert_html (html, html_text);
 }
 
-/* inserts local files only, as inlined */
 void
-gtkhtml_editor_insert_image	(GtkhtmlEditor *editor,
-				 const gchar *filename_uri)
+gtkhtml_editor_insert_image (GtkhtmlEditor *editor,
+                             const gchar *image_uri)
 {
 	GtkHTML *html;
+	HTMLObject *image;
 
 	g_return_if_fail (GTKHTML_IS_EDITOR (editor));
-	g_return_if_fail (filename_uri != NULL);
+	g_return_if_fail (image_uri != NULL);
 
 	html = gtkhtml_editor_get_html (editor);
 
-	if (html) {
-		HTMLObject *image;
+	image = html_image_new (
+		html_engine_get_image_factory (html->engine), image_uri,
+		NULL, NULL, 0, 0, 0, 0, 0, NULL, HTML_VALIGN_NONE, FALSE);
 
-		image = html_image_new (
-			html_engine_get_image_factory (html->engine), filename_uri,
-			NULL, NULL, 0, 0, 0, 0, 0, NULL, HTML_VALIGN_NONE, FALSE);
-		html_engine_paste_object (html->engine, image, 1);
-	}
+	html_engine_paste_object (html->engine, image, 1);
 }
 
 gboolean
diff --git a/components/editor/gtkhtml-editor.h b/components/editor/gtkhtml-editor.h
index 57f8831..6973352 100644
--- a/components/editor/gtkhtml-editor.h
+++ b/components/editor/gtkhtml-editor.h
@@ -83,7 +83,7 @@ struct _GtkhtmlEditorClass {
 	void		(*object_deleted)	(GtkhtmlEditor *editor);
 	void		(*uri_requested)	(GtkhtmlEditor *editor,
 						 const gchar *uri,
-						 GtkHTMLStream *output);
+						 GtkHTMLStream *stream);
 };
 
 GType		gtkhtml_editor_get_type		(void);
@@ -165,7 +165,7 @@ gboolean	gtkhtml_editor_is_previous_paragraph_empty
 void		gtkhtml_editor_insert_html	(GtkhtmlEditor *editor,
 						 const gchar *html_text);
 void		gtkhtml_editor_insert_image	(GtkhtmlEditor *editor,
-						 const gchar *filename_uri);
+						 const gchar *image_uri);
 gboolean	gtkhtml_editor_search_by_data	(GtkhtmlEditor *editor,
 						 glong level,
 						 const gchar *klass,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]