[epiphany] Implement saving the page using the DataSource API



commit def58964b0e7fa099b524a6e8bc34bed893118f7
Author: Gustavo Noronha Silva <gns gnome org>
Date:   Thu Aug 20 14:59:07 2009 -0300

    Implement saving the page using the DataSource API
    
    Bug #562611

 embed/ephy-web-view.c |  239 ++++++++++++++++++++++++++++++++++++++++++++++++-
 embed/ephy-web-view.h |    2 +
 src/window-commands.c |   49 +++++++---
 3 files changed, 275 insertions(+), 15 deletions(-)
---
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index f95c4b1..5f1f49a 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
- *  Copyright © 2008 Gustavo Noronha Silva
+ *  Copyright © 2008, 2009 Gustavo Noronha Silva
  *  Copyright © 2009 Igalia S.L.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -2127,3 +2127,240 @@ ephy_web_view_get_title_composite (EphyWebView *view)
   return title != NULL ? title : "";
 }
 
+static void
+ephy_web_view_save_sub_resource_start (GList *subresources, char *destination_uri);
+
+static void
+ephy_web_view_close_cb (GOutputStream *ostream, GAsyncResult *result, GString *data)
+{
+  GList *subresources;
+  char *sub_destination_uri;
+  GError *error = NULL;
+
+  subresources = (GList*)g_object_get_data (G_OBJECT (ostream),
+                                            "ephy-web-view-save-subresources");
+
+  sub_destination_uri = (char*)g_object_get_data (G_OBJECT (ostream),
+                                                  "ephy-web-view-save-dest-uri");
+
+  g_output_stream_close_finish (ostream, result, &error);
+  g_object_unref (ostream);
+
+  if (error) {
+    g_list_free (subresources);
+    g_free (sub_destination_uri);
+    g_warning ("Unable to write to file: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  if (!subresources || !subresources->next) {
+    g_list_free (subresources);
+    g_free (sub_destination_uri);
+    return;
+  }
+
+  subresources = subresources->next;
+  ephy_web_view_save_sub_resource_start (subresources, sub_destination_uri);
+}
+
+static void
+ephy_web_view_save_write_cb (GOutputStream *ostream, GAsyncResult *result, GString *data)
+{
+  GError *error = NULL;
+  gssize written;
+
+  written = g_output_stream_write_finish (ostream, result, &error);
+  if (error) {
+    GList *subresources;
+    char *sub_destination_uri;
+
+    subresources = (GList*)g_object_get_data (G_OBJECT (ostream),
+                                             "ephy-web-view-save-subresources");
+    g_list_free (subresources);
+
+    sub_destination_uri = (char*)g_object_get_data (G_OBJECT (ostream),
+                                                    "ephy-web-view-save-dest-uri");
+    g_free (sub_destination_uri);
+
+    g_string_free (data, FALSE);
+    g_object_unref (ostream);
+
+    g_warning ("Unable to write to file: %s", error->message);
+
+    g_error_free (error);
+    return;
+  }
+
+  if (written == data->len) {
+    g_string_free (data, FALSE);
+    g_output_stream_close_async (ostream, G_PRIORITY_DEFAULT, NULL,
+                                 (GAsyncReadyCallback)ephy_web_view_close_cb,
+                                 NULL);
+    return;
+  }
+
+  data->len -= written;
+  data->str += written;
+
+  g_output_stream_write_async (ostream,
+                               data->str, data->len,
+                               G_PRIORITY_DEFAULT, NULL,
+                               (GAsyncReadyCallback)ephy_web_view_save_write_cb,
+                               data);
+}
+
+static void
+ephy_web_view_save_replace_cb (GFile *file, GAsyncResult *result, GString *const_data)
+{
+  GFileOutputStream *ostream;
+  GList *subresources;
+  char *sub_destination_uri;
+  GString *data;
+  GError *error = NULL;
+
+  subresources = (GList*)g_object_get_data (G_OBJECT (file),
+                                            "ephy-web-view-save-subresources");
+
+  sub_destination_uri = (char*)g_object_get_data (G_OBJECT (file),
+                                                  "ephy-web-view-save-dest-uri");
+
+  ostream = g_file_replace_finish (file, result, &error);
+  if (error) {
+    g_warning ("Failed to save page: %s", error->message);
+    g_list_free (subresources);
+    g_free (sub_destination_uri);
+    g_error_free (error);
+    return;
+  }
+
+  if (const_data) {
+    data = g_string_sized_new (const_data->len);
+    data->str = const_data->str;
+    data->len = const_data->len;
+  } else
+    data = g_string_new ("");
+
+  /* If we have subresources to handle, pass the information along */
+  if (subresources) {
+    g_object_set_data (G_OBJECT (ostream),
+                       "ephy-web-view-save-subresources",
+                       subresources);
+
+    g_object_set_data (G_OBJECT (ostream),
+                       "ephy-web-view-save-dest-uri",
+                       sub_destination_uri);
+  }
+
+  g_output_stream_write_async (G_OUTPUT_STREAM (ostream),
+                               data->str, data->len,
+                               G_PRIORITY_DEFAULT, NULL,
+                               (GAsyncReadyCallback)ephy_web_view_save_write_cb,
+                               data);
+}
+
+static void
+ephy_web_view_save_sub_resource_start (GList *subresources, char *destination_uri)
+{
+  WebKitWebResource *resource;
+  GFile *file;
+  char *resource_uri;
+  char *resource_name;
+  const GString *data;
+
+  resource = WEBKIT_WEB_RESOURCE (subresources->data);
+
+  resource_uri = (char*)webkit_web_resource_get_uri (resource);
+  resource_name = g_path_get_basename (resource_uri);
+
+  resource_uri = g_strdup_printf ("%s/%s",
+                                  destination_uri,
+                                  resource_name);
+
+  file = g_file_new_for_uri (resource_uri);
+  g_free (resource_uri);
+
+  g_object_set_data (G_OBJECT (file),
+                     "ephy-web-view-save-dest-uri",
+                     destination_uri);
+
+  g_object_set_data (G_OBJECT (file),
+                     "ephy-web-view-save-subresources",
+                     subresources);
+
+  data = webkit_web_resource_get_data (resource);
+
+  g_file_replace_async (file, NULL, FALSE,
+                        G_FILE_CREATE_REPLACE_DESTINATION|G_FILE_CREATE_PRIVATE,
+                        G_PRIORITY_DEFAULT, NULL,
+                        (GAsyncReadyCallback)ephy_web_view_save_replace_cb,
+                        (GString*)data);
+
+  g_object_unref (file);
+}
+
+static void
+ephy_web_view_save_sub_resources (EphyWebView *view, const char *uri, GList *subresources)
+{
+  GFile *file;
+  char *filename;
+  char *dotpos;
+  char *directory_uri;
+  char *destination_uri;
+  GError *error = NULL;
+
+  /* filename of the main resource without extension */
+  filename = g_path_get_basename (uri);
+  dotpos = g_strrstr (filename, ".");
+  if (dotpos)
+    *dotpos = '\0';
+
+  directory_uri = g_path_get_dirname (uri);
+  destination_uri = g_strdup_printf (_("%s/%s Files"), directory_uri, filename);
+
+  g_free (filename);
+  g_free (directory_uri);
+
+  file = g_file_new_for_uri (destination_uri);
+  if (!g_file_make_directory (file, NULL, &error)) {
+    g_warning ("Could not create directory: %s", error->message);
+    g_error_free (error);
+    g_object_unref (file);
+    return;
+  }
+  g_object_unref (file);
+
+  /* Now, let's start saving sub resources */
+  ephy_web_view_save_sub_resource_start (subresources, destination_uri);
+}
+
+void
+ephy_web_view_save (EphyWebView *view, const char *uri)
+{
+  WebKitWebFrame *frame;
+  WebKitWebDataSource *data_source;
+  GList *subresources;
+  const GString *data;
+  GFile *file;
+
+  /* Save main resource */
+  frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW(view));
+  data_source = webkit_web_frame_get_data_source (frame);
+  data = webkit_web_data_source_get_data (data_source);
+
+  file = g_file_new_for_uri (uri);
+  g_file_replace_async (file, NULL, FALSE,
+                        G_FILE_CREATE_REPLACE_DESTINATION|G_FILE_CREATE_PRIVATE,
+                        G_PRIORITY_DEFAULT, NULL,
+                        (GAsyncReadyCallback)ephy_web_view_save_replace_cb,
+                        (GString*)data);
+
+  g_object_unref (file);
+
+  /* If subresources exist, save them */
+  subresources = webkit_web_data_source_get_subresources (data_source);
+  if (!subresources)
+    return;
+
+  ephy_web_view_save_sub_resources (view, uri, subresources);
+}
diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h
index d50bf4f..29f1bd3 100644
--- a/embed/ephy-web-view.h
+++ b/embed/ephy-web-view.h
@@ -229,6 +229,8 @@ void                       ephy_web_view_set_loading_title       (EphyWebView
                                                                   gboolean                         is_address);
 void                       ephy_web_view_popups_manager_reset    (EphyWebView                     *view);
 
+void                       ephy_web_view_save                    (EphyWebView                     *view,
+                                                                  const char                      *uri);
 
 G_END_DECLS
 
diff --git a/src/window-commands.c b/src/window-commands.c
index e6790c7..b3d4373 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -276,6 +276,32 @@ open_response_cb (GtkDialog *dialog, int response, EphyWindow *window)
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
+static void
+save_response_cb (GtkDialog *dialog, int response, EphyEmbed *embed)
+{
+	if (response == GTK_RESPONSE_ACCEPT)
+	{
+		char *uri, *converted;
+
+		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+		if (uri != NULL)
+		{
+			converted = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL);
+
+			if (converted != NULL)
+			{
+				EphyWebView *web_view = ephy_embed_get_web_view (embed);
+				ephy_web_view_save (web_view, converted);
+			}
+
+			g_free (converted);
+			g_free (uri);
+	        }
+	}
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
 void
 window_cmd_file_open (GtkAction *action,
 		      EphyWindow *window)
@@ -299,26 +325,21 @@ window_cmd_file_save_as (GtkAction *action,
 			 EphyWindow *window)
 {
 	EphyEmbed *embed;
-	EphyEmbedPersist *persist;
+	EphyFileChooser *dialog;
 
 	embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
 	g_return_if_fail (embed != NULL);
 
-	persist = EPHY_EMBED_PERSIST
-		(g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL));
-
-	ephy_embed_persist_set_embed (persist, embed);
-	ephy_embed_persist_set_fc_title (persist, _("Save As"));
-	ephy_embed_persist_set_fc_parent (persist,GTK_WINDOW (window));
-
-	ephy_embed_persist_set_flags
-		(persist, EPHY_EMBED_PERSIST_MAINDOC | EPHY_EMBED_PERSIST_ASK_DESTINATION);
-	ephy_embed_persist_set_persist_key
-		(persist, CONF_STATE_SAVE_DIR);
+	dialog = ephy_file_chooser_new (_("Save"),
+					GTK_WIDGET (window),
+					GTK_FILE_CHOOSER_ACTION_SAVE,
+					CONF_STATE_SAVE_DIR,
+					EPHY_FILE_FILTER_ALL_SUPPORTED);
 
-	ephy_embed_persist_save (persist);
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (save_response_cb), embed);
 
-	g_object_unref (G_OBJECT(persist));
+	gtk_widget_show (GTK_WIDGET (dialog));
 }
 
 void



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