gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r19224 - in gnunet-gtk: contrib src/fs


From: gnunet
Subject: [GNUnet-SVN] r19224 - in gnunet-gtk: contrib src/fs
Date: Wed, 18 Jan 2012 09:24:26 +0100

Author: grothoff
Date: 2012-01-18 09:24:26 +0100 (Wed, 18 Jan 2012)
New Revision: 19224

Modified:
   gnunet-gtk/contrib/gnunet_fs_gtk_search_tab.glade
   gnunet-gtk/src/fs/gnunet-fs-gtk-download.c
   gnunet-gtk/src/fs/gnunet-fs-gtk-download.h
   gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c
Log:
LRN:

Whenever a file is downloaded, store its downloaded name in a treestore
(FIXME: when a previously downloaded .gnd file is opened, set
downloaded name appropriately? Or not, since it won't have
anonymity?), as well as the anonymity level that was used.
When one of its children is downloaded, this information is checked
and, if present, is used to construct the child filename (and
anonymity is used to download the child; FIXME: anonymity == -1 might
be used, if parent supplied a filename, but not anonymity? This might
need a fix), so it is downloaded without showing the "Save as" dialog.
(TODO: the logic behind constructing the child filename from the name
of already downloaded directory file relies on directory file having a
'.gnd' extension; if it isn't there, the whole thing fails (tries to
mkdir() with the name of the .gnd-less directory file, which isn't
possible); Enforce .gnd extension? Change the name to avoid conflict?)

In future it might be necessary to add a context menu item that
overrides this behaviour and shows the dialog anyway.

Also changes the way gtkfilechooser is set up, so that it fills the
entry with short filename only, without the directory part, and the
directory part is used to select a directory. Without this the entry
gets absolute filename or directoryname, and if you later change the
directory in the dialog, contents of the entry remain the same. It's
intended to be relative most of the time!

Slight API changes for "Save as" dialog, now it invokes a callback
(FIXME: this breaks "Download URI", as it is not adapted to the
callback yet, that must be fixed as soon as possible!).
To that end one of its static functions was made public.



Modified: gnunet-gtk/contrib/gnunet_fs_gtk_search_tab.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_fs_gtk_search_tab.glade   2012-01-18 08:23:55 UTC 
(rev 19223)
+++ gnunet-gtk/contrib/gnunet_fs_gtk_search_tab.glade   2012-01-18 08:24:26 UTC 
(rev 19224)
@@ -34,6 +34,10 @@
       <column type="gint"/>
       <!-- column-name completed -->
       <column type="guint64"/>
+      <!-- column-name downloaded_filename -->
+      <column type="gchararray"/>
+      <!-- column-name downloaded_anonymity -->
+      <column type="gint"/>
     </columns>
   </object>
   <object class="GtkWindow" id="_search_result_frame_window">

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk-download.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-download.c  2012-01-18 08:23:55 UTC (rev 
19223)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-download.c  2012-01-18 08:24:26 UTC (rev 
19224)
@@ -35,9 +35,8 @@
   struct DownloadContext *dc;
 };
 
-
-static void
-free_download_context (struct DownloadContext *dc)
+void
+GNUNET_GTK_save_as_dialog_free_download_context (struct DownloadContext *dc)
 {
   if (NULL != dc->rr)
     gtk_tree_row_reference_free (dc->rr);
@@ -50,7 +49,6 @@
   GNUNET_free (dc);  
 }
 
-
 gboolean
 GNUNET_GTK_save_as_dialog_delete_event_cb (GtkWidget * widget, GdkEvent * 
event,
                                            gpointer user_data)
@@ -58,12 +56,7 @@
   struct DownloadAsDialogContext *dlc = user_data;
   GtkBuilder *builder;
   struct DownloadContext *dc;
-  enum GNUNET_FS_DownloadOptions opt;
-  struct GNUNET_FS_Handle *fs;
-  struct DownloadEntry *de;
   GtkWidget *cb;
-  uint32_t anonymity;
-  uint64_t len;
 
   if (dlc == NULL)
   {
@@ -76,7 +69,7 @@
                    (builder, "GNUNET_GTK_save_as_recursive_check_button"));
   if (GTK_RESPONSE_OK != dlc->response)
   {
-    free_download_context (dc);
+    GNUNET_GTK_save_as_dialog_free_download_context (dc);
     g_object_unref (G_OBJECT (dlc->builder));
     GNUNET_free (dlc);
     return FALSE;
@@ -88,50 +81,16 @@
       (TRUE ==
        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
       GNUNET_NO;
-  fs = GNUNET_FS_GTK_get_fs_handle ();
-  opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
-  if (dc->is_recursive)
-    opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
-  anonymity =
+  dc->anonymity =
       gtk_spin_button_get_value (GTK_SPIN_BUTTON
                                  (gtk_builder_get_object
                                   (builder,
                                    
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
-  len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
   g_object_unref (G_OBJECT (builder));
 
-  de = GNUNET_malloc (sizeof (struct DownloadEntry));
-  de->uri = dc->uri;
-  dc->uri = NULL;
-  de->meta = dc->meta;
-  dc->meta = NULL;
-  if (dc->rr != NULL)
-  {
-    /* We're going to free "dc" very soon */
-    de->rr = gtk_tree_row_reference_copy (dc->rr);
-    de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
-  }
-  if (dc->sr != NULL)
-  {
-    GNUNET_break (NULL !=
-                  GNUNET_FS_download_start_from_search (fs, dc->sr,
-                                                        dc->filename,
-                                                        NULL /* tempname */ ,
-                                                        0 /* offset */ ,
-                                                        len, anonymity, opt,
-                                                        de));
-  }
-  else
-  {
-    GNUNET_break (NULL !=
-                  GNUNET_FS_download_start (fs, de->uri, NULL /* meta */ ,
-                                            dc->filename, NULL /* tempname */ ,
-                                            0 /* offset */ ,
-                                            len, anonymity, opt, de,
-                                            NULL /* parent download ctx */ ));
-  }
-  free_download_context (dc);
   GNUNET_free (dlc);
+
+  dc->cb (dc);
   return FALSE;
 }
 
@@ -168,7 +127,7 @@
   if (builder == NULL)
   {
     GNUNET_break (0);
-    free_download_context (dc);
+    GNUNET_GTK_save_as_dialog_free_download_context (dc);
     GNUNET_free (dlc);
     return;
   }
@@ -181,7 +140,17 @@
   ad = GTK_WIDGET (gtk_builder_get_object
                    (builder, "GNUNET_GTK_save_as_dialog"));
   if (dc->filename != NULL)
-    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad), dc->filename);
+  {
+    char *dirname;
+    char *basename;
+    dirname = GNUNET_strdup (dc->filename);
+    basename = (char *) GNUNET_STRINGS_get_short_name (dirname);
+    if (basename > dirname)
+      basename[-1] = '\0';
+    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (ad), dirname);
+    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad), basename);
+    GNUNET_free (dirname);
+  }
   dlc->builder = builder;
   dlc->dialog = ad;
   dlc->response = 0;

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk-download.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-download.h  2012-01-18 08:23:55 UTC (rev 
19223)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-download.h  2012-01-18 08:24:26 UTC (rev 
19224)
@@ -28,6 +28,10 @@
 #define GNUNET_FS_GTK_DOWNLOAD_H
 #include "gnunet-fs-gtk-common.h"
 
+struct DownloadContext;
+
+typedef void (*GNUNET_FS_DownloadAsCallback ) (struct DownloadContext *dc);
+
 /**
  * Information we keep for a download.
  */
@@ -79,10 +83,18 @@
    * (this is the same as sr->tab, but sr is opaque here).
    */
   struct SearchTab *tab;
+
+  /**
+   * A function to call once a filename is picked.
+   */
+  GNUNET_FS_DownloadAsCallback cb;
 };
 
 
+void
+GNUNET_GTK_save_as_dialog_free_download_context (struct DownloadContext *dc);
 
+
 void
 GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc);
 

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c     2012-01-18 08:23:55 UTC 
(rev 19223)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c     2012-01-18 08:24:26 UTC 
(rev 19224)
@@ -596,6 +596,8 @@
   guint applicability_rank;
   guint availability_certainty;
   gint availability_rank;
+  gchar *downloaded_filename;
+  gint downloaded_anonymity;
 
   if (TRUE == gtk_tree_model_iter_children (src_model, &src_child, src_iter))
   {
@@ -607,7 +609,8 @@
                           &uri_as_string, 8, &status_colour, 9, &search_result,
                           10, &mimetype, 11, &applicability_rank, 12,
                           &availability_certainty, 13, &availability_rank, 14,
-                          &completed, -1);
+                          &completed, 15, &downloaded_filename, 16,
+                          &downloaded_anonymity, -1);
       gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model), 
&dst_child,
                                          dst_iter, G_MAXINT, 0, meta, 1, uri, 
2,
                                          filesize, 3, preview, 4,
@@ -617,8 +620,11 @@
                                          search_result, 10, mimetype, 11,
                                          applicability_rank, 12,
                                          availability_certainty, 13,
-                                         availability_rank, 14, completed, -1);
+                                         availability_rank, 14, completed, 15,
+                                         downloaded_filename, 16,
+                                         downloaded_anonymity, -1);
       g_free (filename);
+      g_free (downloaded_filename);
       g_free (uri_as_string);
       g_free (status_colour);
       g_free (mimetype);
@@ -807,8 +813,166 @@
   return de;
 }
 
+/**
+ * This should get the default download directory
+ * (so that GNUnet won't offer the user to download files
+ * to the 'bin' subdirectory, or whatever is the cwd).
+ * Returns NULL on failure (such as non-existend directory).
+ * Should also preserve the last setting (so if the user
+ * saves files somewhere else, next time we default to
+ * somewhere else, at least until application restart, or maybe even
+ * between application restarts).
+ * Fills the @buffer up to @size bytes, returns a pointer to it.
+ */
+static char *
+get_default_download_directory (char *buffer, size_t size)
+{
+  return NULL;
+}
 
 /**
+ * Called recursively to build a suggested filename by
+ * prepending suggested names for its parent directories (if any).
+ * Might return NULL. Returned name might be absolute.
+ * local_parents is set to GNUNET_YES if all parents are directories,
+ * and are downloaded.
+ */
+static char *
+get_suggested_filename_anonymity (GtkTreeModel *tm, GtkTreeIter *iter, int top,
+    int *local_parents, int *anonymity, int *filename_is_absolute)
+{
+  char *result;
+  char *dirname;
+  char *local_filename, *filename;
+  int downloaded_anonymity;
+  int have_a_parent;
+  struct GNUNET_CONTAINER_MetaData *meta;
+  GtkTreeIter parent;
+  gtk_tree_model_get (tm, iter, 0, &meta, 15, &local_filename, 16, 
&downloaded_anonymity, -1);
+  if (local_filename == NULL && !top)
+    *local_parents = GNUNET_NO;
+  if (downloaded_anonymity != -1 && *anonymity == -1 && !top)
+    *anonymity = downloaded_anonymity;
+  if (gtk_tree_model_iter_parent (tm, &parent, iter))
+  {
+    have_a_parent = GNUNET_YES;
+    dirname = get_suggested_filename_anonymity (tm, &parent, GNUNET_NO, 
local_parents, anonymity, filename_is_absolute);
+  }
+  else
+  {
+    have_a_parent = GNUNET_NO;
+    dirname = NULL;
+    if (top)
+      *local_parents = GNUNET_NO;
+  }
+  if (local_filename == NULL)
+    filename = GNUNET_FS_meta_data_suggest_filename (meta);
+  else
+  {
+    /* This directory was downloaded as /foo/bar/baz/somedirname
+     * Hopefully, "somedirname" is actually "somedir.gnd"
+     * We need to strip the ".gnd" part to get "somedir", which is
+     * what we're going to use instead of suggested original filename
+     * Without the .gnd extension we're going to just use a copy
+     * of the directory file name - and that would fail. Sad.
+     */
+    const char *basename; 
+    if (dirname == NULL && !have_a_parent)
+    {
+      /* This is the ealderlest parent directory. Use absolute path. */
+      basename = (const char *) local_filename;
+      *filename_is_absolute = GNUNET_YES;
+    }
+    else
+      basename = GNUNET_STRINGS_get_short_name (local_filename);
+    if (basename != NULL && strlen (basename) > 0)
+    {
+      char *dot;
+      filename = GNUNET_strdup (basename);
+      dot = strrchr (filename, '.');
+      if (dot)
+        *dot = '\0';
+    }
+    else
+      filename = GNUNET_FS_meta_data_suggest_filename (meta);
+  }
+  if (dirname && filename)
+  {
+    GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename);
+    GNUNET_free (filename);
+    GNUNET_free (dirname);
+    return result;
+  }
+  else if (filename)
+    return filename;
+  else
+    return NULL;
+}
+
+static void
+open_download_as_callback (struct DownloadContext *dc)
+{
+  enum GNUNET_FS_DownloadOptions opt;
+  struct GNUNET_FS_Handle *fs;
+  struct DownloadEntry *de;
+  uint64_t len;
+
+  GtkTreeIter iter;
+  GtkTreePath *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);
+
+  de = GNUNET_malloc (sizeof (struct DownloadEntry));
+  de->uri = dc->uri;
+  dc->uri = NULL;
+  de->meta = dc->meta;
+  dc->meta = NULL;
+  if (dc->rr != NULL)
+  {
+    /* We're going to free "dc" very soon */
+    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);
+    GNUNET_assert (NULL != path);
+    if (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);
+    }
+    gtk_tree_path_free (path);
+
+  }
+  if (dc->sr != NULL)
+  {
+    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 */ ));
+  }
+  GNUNET_GTK_save_as_dialog_free_download_context (dc);
+}
+
+/**
  * Tell FS to start a download.  Begins by opening the
  * "save as" window.
  */
@@ -825,11 +989,16 @@
   struct SearchResult *sr;
   gchar *mime;
   struct DownloadContext *dc;
-  char *buf;
+  char *buf = NULL;
   char *tmp;
   size_t tmplen;
   char cwd[FILENAME_MAX];
+  char *download_directory;
   char *filename;
+  int local_parents;
+  int have_a_suggestion;
+  int anonymity;
+  int filename_is_absolute;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
       "Starting a %sdownload\n", sdc->recursive ? "recursive " : "");
@@ -858,24 +1027,32 @@
     return;
   }
 
-
-  /* FIXME: we should check if this download is a file in some directory
-     (gtk_tree_model_iter_get_parent) and if so obtain the name under which
-     the directory was stored! */
-  /* Calculate suggested filename; first, pre-pend current working directory */
-  filename = GNUNET_FS_meta_data_suggest_filename (meta);
-  if (NULL != getcwd (cwd, sizeof (cwd)))
+  download_directory = get_default_download_directory (cwd, sizeof (cwd));
+  /* If no download directory is known, try working directory */
+  if (download_directory == NULL)
+    download_directory = getcwd (cwd, sizeof (cwd));
+  /* Calculate suggested filename */
+  local_parents = GNUNET_YES;
+  anonymity = -1;
+  filename_is_absolute = GNUNET_NO;
+  filename = get_suggested_filename_anonymity (tm, &iter, GNUNET_YES, 
&local_parents, &anonymity, &filename_is_absolute);
+  have_a_suggestion = GNUNET_NO;
+  if (NULL != download_directory)
   {
     if (NULL == filename)
     {
-      buf = GNUNET_strdup (cwd);
+      buf = GNUNET_strdup (download_directory);
     }
     else
     {
-      GNUNET_asprintf (&tmp, "%s%s%s",
-                      cwd,
-                      DIR_SEPARATOR_STR,
-                      filename);
+      have_a_suggestion = GNUNET_YES;
+      if (filename_is_absolute)
+        GNUNET_asprintf (&tmp, "%s", filename);
+      else
+        GNUNET_asprintf (&tmp, "%s%s%s",
+                        download_directory,
+                        DIR_SEPARATOR_STR,
+                        filename);
       tmplen = strlen (tmp);
       /* now, if we have a directory, replace trailing '/' with ".gnd" */
       if (GNUNET_YES ==
@@ -906,10 +1083,15 @@
   dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
   dc->rr = gtk_tree_row_reference_new (tm, path);
   dc->sr = sr->result;
-  dc->anonymity = -1;
+  dc->anonymity = anonymity;
   dc->is_recursive = sdc->recursive;
   dc->tab = tab;
-  GNUNET_FS_GTK_open_download_as_dialog (dc);
+  dc->cb = &open_download_as_callback;
+  if (local_parents && have_a_suggestion)
+    /* Skip the dialog, call directly */
+    open_download_as_callback (dc);
+  else
+    GNUNET_FS_GTK_open_download_as_dialog (dc);
 }
 
 
@@ -1608,6 +1790,8 @@
                                      0 /* avail-cert */ ,
                                      13, 0, /* avail-rank */
                                      14, (guint64) 0, /* completed */
+                                     15, NULL, /* downloaded_filename */
+                                     16, -1, /* downloaded_anonymity */
                                      -1);
   if (tab != NULL)
   {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]