diff options
-rw-r--r-- | embed/ephy-embed-persist.c | 192 |
1 files changed, 188 insertions, 4 deletions
diff --git a/embed/ephy-embed-persist.c b/embed/ephy-embed-persist.c index 2c82c0381..f413af533 100644 --- a/embed/ephy-embed-persist.c +++ b/embed/ephy-embed-persist.c @@ -2,6 +2,7 @@ /* * Copyright © 2000-2003 Marco Pesenti Gritti * Copyright © 2003 Christian Persch + * Copyright © 2010 Igalia S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,10 +23,14 @@ #include "config.h" #include "ephy-embed-persist.h" +#include "ephy-embed-shell.h" #include "ephy-embed-type-builtins.h" +#include "ephy-file-chooser.h" +#include "ephy-file-helpers.h" #include "ephy-debug.h" #include <gtk/gtk.h> +#include <glib/gi18n.h> enum { @@ -55,6 +60,7 @@ struct _EphyEmbedPersistPrivate EphyEmbedPersistFlags flags; GtkWindow *fc_parent; guint32 user_time; + WebKitDownload *download; }; static void ephy_embed_persist_class_init (EphyEmbedPersistClass *klass); @@ -123,8 +129,8 @@ ephy_embed_persist_set_fc_title (EphyEmbedPersist *persist, * @value: the #EphyWindow which should be the filechooser's parent * * Sets the #EphyWindow which should be @persist's filechooser's parent. The - * filechooser will only be displayed if %EPHY_EMBED_PERSIST_ASK_DESTINATION has been - * set with ephy_embed_persist_set_flags(). + * filechooser will only be displayed if %EPHY_EMBED_PERSIST_ASK_DESTINATION + * has been set with ephy_embed_persist_set_flags(). **/ void ephy_embed_persist_set_fc_parent (EphyEmbedPersist *persist, @@ -134,6 +140,7 @@ ephy_embed_persist_set_fc_parent (EphyEmbedPersist *persist, GtkWindow **wptr; g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); + g_return_if_fail (gtk_widget_is_toplevel (GTK_WIDGET (value))); priv = persist->priv; @@ -476,6 +483,23 @@ ephy_embed_persist_init (EphyEmbedPersist *persist) } static void +ephy_embed_persist_dispose (GObject *object) +{ + EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); + EphyEmbedPersistPrivate *priv = persist->priv; + + if (priv->download) + { + g_object_unref (priv->download); + priv->download = NULL; + } + + LOG ("EphyEmbedPersist disposed %p", object); + + G_OBJECT_CLASS (ephy_embed_persist_parent_class)->dispose (object); +} + +static void ephy_embed_persist_finalize (GObject *object) { EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); @@ -505,6 +529,7 @@ ephy_embed_persist_class_init (EphyEmbedPersistClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ephy_embed_persist_finalize; + object_class->dispose = ephy_embed_persist_dispose; object_class->set_property = ephy_embed_persist_set_property; object_class->get_property = ephy_embed_persist_get_property; @@ -629,7 +654,74 @@ ephy_embed_persist_class_init (EphyEmbedPersistClass *klass) void ephy_embed_persist_cancel (EphyEmbedPersist *persist) { - g_object_unref (persist); + g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); + + /* webkit_download_cancel() triggers download_status_changed_cb() with + * status = WEBKIT_DOWNLOAD_STATUS_CANCELLED so we don't need to emit + * the signal. + */ + if (persist->priv->download) + { + webkit_download_cancel (persist->priv->download); + } + else + { + g_object_unref (persist); + } +} + +static void +response_cb (GtkDialog *dialog, + int response_id, + EphyEmbedPersist *persist) +{ + WebKitDownload *download; + + download = persist->priv->download; + + if (response_id == GTK_RESPONSE_ACCEPT) + { + char *uri; + + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER(dialog)); + + webkit_download_set_destination_uri (download, uri); + webkit_download_start (download); + + g_free (uri); + } + else + { + g_object_unref (persist); + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +download_status_changed_cb (GObject *object, + GParamSpec *pspec, + EphyEmbedPersist *persist) +{ + EphyEmbedPersistPrivate *priv; + WebKitDownload *download; + WebKitDownloadStatus status; + + priv = persist->priv; + download = WEBKIT_DOWNLOAD (object); + status = webkit_download_get_status (download); + + if (status == WEBKIT_DOWNLOAD_STATUS_FINISHED) + { + g_signal_emit_by_name (persist, "completed"); + g_object_unref (persist); + } + else if (status == WEBKIT_DOWNLOAD_STATUS_CANCELLED || + status == WEBKIT_DOWNLOAD_STATUS_ERROR) + { + g_signal_emit_by_name (persist, "cancelled"); + g_object_unref (persist); + } } /** @@ -639,7 +731,10 @@ ephy_embed_persist_cancel (EphyEmbedPersist *persist) * Begins saving the file specified in @persist. * * If @persist's #EphyEmbedPersistFlags include %EPHY_EMBED_PERSIST_ASK_DESTINATION, a - * filechooser dialog will be shown first. + * filechooser dialog will be shown first. If this flag is not set and no + * destination has been set, the target will be saved to the default download + * directory using the suggested name, if no suggested name can be get the + * download will fail. * * The file will continue to download in the background until either the * ::completed or the ::cancelled signals are emitted by @persist. @@ -649,8 +744,96 @@ ephy_embed_persist_cancel (EphyEmbedPersist *persist) gboolean ephy_embed_persist_save (EphyEmbedPersist *persist) { + EphyEmbedPersistPrivate *priv; + WebKitNetworkRequest *request; + + g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), FALSE); + + priv = persist->priv; + g_return_val_if_fail (priv->source != NULL, FALSE); + + /* Balanced when priv->download is not needed anymore: here, in + * ephy_embed_persist_cancel() and in download_status_changed_cb(). + */ g_object_ref (persist); + request = webkit_network_request_new (priv->source); + priv->download = webkit_download_new (request); + g_object_unref (request); + + g_signal_connect (priv->download, "notify::status", + G_CALLBACK (download_status_changed_cb), + persist); + + if (priv->flags & EPHY_EMBED_PERSIST_ASK_DESTINATION) + { + EphyFileChooser *dialog; + GtkWidget *window; + const char *suggested_filename; + + suggested_filename = webkit_download_get_suggested_filename (priv->download); + window = GTK_WIDGET (priv->fc_parent); + + dialog = ephy_file_chooser_new (priv->fc_title ? + priv->fc_title : _("Save"), + window, + GTK_FILE_CHOOSER_ACTION_SAVE, + priv->persist_key, + EPHY_FILE_FILTER_ALL_SUPPORTED); + + gtk_file_chooser_set_do_overwrite_confirmation + (GTK_FILE_CHOOSER (dialog), TRUE); + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER (dialog), suggested_filename); + + g_signal_connect (dialog, "response", + G_CALLBACK (response_cb), persist); + + gtk_widget_show (GTK_WIDGET (dialog)); + + return TRUE; + } + else + { + char *dest_uri; + + if (priv->dest) + { + dest_uri = g_filename_to_uri (priv->dest, NULL, NULL); + } + else + { + const char *suggested_filename = NULL; + char *downloads_dir; + char *dest_filename; + + suggested_filename = webkit_download_get_suggested_filename (priv->download); + + if (suggested_filename == NULL) + { + g_object_unref (persist); + return FALSE; + } + + downloads_dir = ephy_file_get_downloads_dir (); + dest_filename = g_build_filename (downloads_dir, + suggested_filename, + NULL); + g_free (downloads_dir); + + priv->dest = dest_filename; + dest_uri = g_filename_to_uri (dest_filename, NULL, NULL); + } + + webkit_download_set_destination_uri (priv->download, dest_uri); + webkit_download_start (priv->download); + + g_free (dest_uri); + + return TRUE; + } + + g_object_unref (persist); return FALSE; } @@ -675,5 +858,6 @@ ephy_embed_persist_save (EphyEmbedPersist *persist) char * ephy_embed_persist_to_string (EphyEmbedPersist *persist) { + g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); return NULL; } |