/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/fs/gnunet-fs-gtk_download-save-as.c * @brief functions for managing the 'save as' dialog * @author Christian Grothoff */ #include "gnunet-fs-gtk_download-save-as.h" #include "gnunet-fs-gtk.h" #include "gnunet-fs-gtk_event-handler.h" /** * State for a 'save as' dialog of a download. */ struct DownloadAsDialogContext { /** * Download context for which this dialog determines the * filename (and other options). */ struct DownloadContext *dc; /** * Builder for the dialog. */ GtkBuilder *builder; /** * Main dialog object. */ GtkWidget *dialog; /** * Final response code from the dialog. */ gint response; }; /** * Free resources associated with the given download context. * * @param dc context to free */ static void save_as_dialog_free_download_context (struct DownloadContext *dc) { if (NULL != dc->rr) gtk_tree_row_reference_free (dc->rr); GNUNET_free_non_null (dc->mime); GNUNET_free_non_null (dc->filename); if (NULL != dc->meta) GNUNET_CONTAINER_meta_data_destroy (dc->meta); if (NULL != dc->uri) GNUNET_FS_uri_destroy (dc->uri); GNUNET_free (dc); } /** * The 'save_as' dialog is being deleted. Check which state we're in * and either simply clean up or start the download with the * respective options (by calling the respective continuation). * * @param widget the dialog object * @param event the deletion event * @param user_data the 'structDownloadAsDialogContext' of the dialog * @return always FALSE */ gboolean GNUNET_GTK_save_as_dialog_delete_event_cb (GtkWidget * widget, GdkEvent * event, gpointer user_data) { struct DownloadAsDialogContext *dlc = user_data; GtkBuilder *builder; struct DownloadContext *dc; GtkWidget *cb; builder = dlc->builder; dc = dlc->dc; cb = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_save_as_recursive_check_button")); if (GTK_RESPONSE_OK != dlc->response) { save_as_dialog_free_download_context (dc); g_object_unref (G_OBJECT (dlc->builder)); GNUNET_free (dlc); return FALSE; } GNUNET_free_non_null (dc->filename); dc->filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (dlc->dialog)); dc->is_recursive = (TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES : GNUNET_NO; dc->anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_save_as_dialog_anonymity_spin_button"))); g_object_unref (G_OBJECT (builder)); GNUNET_free (dlc); GNUNET_FS_GTK_download_context_start_download (dc); return FALSE; } /** * The user clicked on the 'save as' button of the dialog. * Delete the window and start the download. * * @param dialog the dialog object * @param response_id response_id associated with the button * @param user_data the 'structDownloadAsDialogContext' of the dialog */ void GNUNET_GTK_save_as_dialog_response_cb (GtkDialog * dialog, gint response_id, gpointer user_data) { struct DownloadAsDialogContext *dlc = user_data; dlc->response = response_id; /* dialogs don't get delete-event the way normal windows do, call the handler manually */ GNUNET_GTK_save_as_dialog_delete_event_cb (GTK_WIDGET (dialog), NULL, user_data); gtk_widget_destroy (GTK_WIDGET (dialog)); } /** * Open the 'save as' dialog for a download. Calls the 'dc->cb' * continutation when the dialog is complete. Will release the 'dc' * resources if the dialog is cancelled. * * @param dc download context for the file/directory */ void GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc) { struct DownloadAsDialogContext *dlc; GtkWidget *cb; dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext)); dlc->dc = dc; dlc->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade", dlc); if (NULL == dlc->builder) { GNUNET_break (0); save_as_dialog_free_download_context (dc); GNUNET_free (dlc); return; } dlc->dialog = GTK_WIDGET (gtk_builder_get_object (dlc->builder, "GNUNET_GTK_save_as_dialog")); /* Enable recursive button for directories and set recursive 'default' value based on what the 'dc' tells us */ cb = GTK_WIDGET (gtk_builder_get_object (dlc->builder, "GNUNET_GTK_save_as_recursive_check_button")); if (GNUNET_FS_meta_data_test_for_directory (dc->meta)) gtk_widget_set_sensitive (cb, TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), dc->is_recursive); /* initialize filename based on filename from 'dc' */ if (NULL != dc->filename) { char *dirname; char *basename; dirname = GNUNET_strdup (dc->filename); basename = (char *) GNUNET_STRINGS_get_short_name (dirname); /* basename now points into 'dirname'; cut 'dirname' off at the '/' before basename */ if (basename > dirname) basename[-1] = '\0'; /* FIXME: remove following lines after testing... */ fprintf (stderr, "Splitting `%s' into `%s' + `%s' for file chooser dialog.\n", dc->filename, dirname, basename); gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlc->dialog), dirname); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlc->dialog), basename); GNUNET_free (dirname); } gtk_window_present (GTK_WINDOW (dlc->dialog)); } /** * Actually start the download that is specified by the given download * context and its options. Will add a download entry to the * respective tree model and trigger a start of the download using the * FS-API. * * @param dc download context of the download to execute */ void GNUNET_FS_GTK_download_context_start_download (struct DownloadContext *dc) { enum GNUNET_FS_DownloadOptions opt; struct GNUNET_FS_Handle *fs; struct DownloadEntry *de; uint64_t len; GtkTreeIter iter; GtkTreePath *path; de = GNUNET_malloc (sizeof (struct DownloadEntry)); de->uri = dc->uri; dc->uri = NULL; de->meta = dc->meta; dc->meta = NULL; if (NULL != dc->rr) { de->rr = gtk_tree_row_reference_copy (dc->rr); de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr)); path = gtk_tree_row_reference_get_path (de->rr); if ( (NULL != path) && (gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) ) { /* Store filename and anonymity as specified by the user. * These will be re-used when this is a directory, and the user * downloads its children. */ gtk_tree_store_set (de->ts, &iter, 15, dc->filename, 16, dc->anonymity, -1); } else { /* We could not find the referenced row in the search tab; this is conceivable as the search tab might have been closed by the user while the 'save as' dialog was open. In this case, this is equivalent to having no search, so we drop the (now invalid) 'sr' reference */ dc->sr = NULL; } if (NULL != path) gtk_tree_path_free (path); } fs = GNUNET_FS_GTK_get_fs_handle (); opt = GNUNET_FS_DOWNLOAD_OPTION_NONE; if (dc->is_recursive) opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE; len = GNUNET_FS_uri_chk_get_file_size (dc->uri); if (NULL != dc->sr) { GNUNET_break (NULL != GNUNET_FS_download_start_from_search (fs, dc->sr, dc->filename, NULL /* tempname */ , 0 /* offset */ , len, dc->anonymity, opt, de)); } else { GNUNET_break (NULL != GNUNET_FS_download_start (fs, de->uri, NULL /* meta */ , dc->filename, NULL /* tempname */ , 0 /* offset */ , len, dc->anonymity, opt, de, NULL /* parent download ctx */ )); } save_as_dialog_free_download_context (dc); } /* end of gnunet-fs-gtk-download.c */