gnunet-svn
[Top][All Lists]
Advanced

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

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


From: gnunet
Subject: [GNUnet-SVN] r25572 - in gnunet-gtk: contrib src/fs
Date: Thu, 20 Dec 2012 09:11:59 +0100

Author: LRN
Date: 2012-12-20 09:11:59 +0100 (Thu, 20 Dec 2012)
New Revision: 25572

Modified:
   gnunet-gtk/contrib/gnunet_fs_gtk_download_as_dialog.glade
   gnunet-gtk/contrib/gnunet_fs_gtk_main_window.glade
   gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c
   gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h
   gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c
   gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h
Log:
Finish fixing #2621

Ask for overwrite confirmation in SaveAs dialog.
Add a filenamechange button ("...") next to DownloadAs entry. This button
  calls the SaveAs dialog, but without anonymity and recursiveness widgets
  (they are hidden), and it does not initiate the download, just changes
  the names in download panel.
Add vsize group for download panel widgets, they all have the same height
  now.
SaveAs dialog, "Download" and "Download recursively" context menu items
  now use the same code that "Download!" button uses (start_download2,
  etc). Old code that they used to need is now removed.
  Note that this _requires_ selection to follow context menu
  (right-clicking on a search result MUST select that search result before
  popping up context menu).
Fixed small bugs in get_suggested_filename_anonymity2 (proper
  initialization for anonymity and result).
GNUNET_FS_GTK_open_change_download_name_dialog() can be used to change
  download name from other files (it's public, unlike direct operations on
  treestore).
Fixed some comments.
Currently selected search result is now remembered in
  current_selected_search_result variable. It is checked on every item
  update, and if selection did not change, then download panel is not
  re-populated (re-population would have destroyed any user changes to
  download panel contents; item updates are made several times per
  second).
Don't trigger GNUNET_FS_GTK_search_treeview_cursor_changed when updated
  item is not currently selected.
Omit the "Download recursively" context menu item for search results that
  are known to not to be directories.

Modified: gnunet-gtk/contrib/gnunet_fs_gtk_download_as_dialog.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_fs_gtk_download_as_dialog.glade   2012-12-20 
00:39:17 UTC (rev 25571)
+++ gnunet-gtk/contrib/gnunet_fs_gtk_download_as_dialog.glade   2012-12-20 
08:11:59 UTC (rev 25572)
@@ -19,6 +19,7 @@
     <property name="type_hint">dialog</property>
     <property name="action">save</property>
     <property name="use_preview_label">False</property>
+    <property name="do_overwrite_confirmation">True</property>
     <property name="preview_widget_active">False</property>
     <signal name="response" handler="GNUNET_GTK_save_as_dialog_response_cb"/>
     <signal name="delete_event" 
handler="GNUNET_GTK_save_as_dialog_delete_event_cb"/>
@@ -28,7 +29,7 @@
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkHBox" id="hbox2">
+          <object class="GtkHBox" id="GNUNET_GTK_save_as_dialog_options_hbox">
             <property name="visible">True</property>
             <child>
               <object class="GtkLabel" 
id="GNUNET_GTK_save_as_dialog_anonymity_label">

Modified: gnunet-gtk/contrib/gnunet_fs_gtk_main_window.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_fs_gtk_main_window.glade  2012-12-20 00:39:17 UTC 
(rev 25571)
+++ gnunet-gtk/contrib/gnunet_fs_gtk_main_window.glade  2012-12-20 08:11:59 UTC 
(rev 25572)
@@ -807,6 +807,24 @@
                             <property name="position">1</property>
                           </packing>
                         </child>
+                        <child>
+                          <object class="GtkButton" 
id="GNUNET_GTK_search_frame_download_filename_change_button">
+                            <property name="label">…</property>
+                            <property 
name="use_action_appearance">False</property>
+                            <property name="height_request">1</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="focus_on_click">False</property>
+                            <signal name="clicked" 
handler="GNUNET_GTK_search_frame_download_filename_change_button_clicked_cb" 
swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="pack_type">end</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -1163,6 +1181,20 @@
       <widget name="main_window_search_mime_combobox"/>
     </widgets>
   </object>
+  <object class="GtkSizeGroup" id="GNUNET_FS_GTK_download_frame_vsize_group">
+    <property name="mode">vertical</property>
+    <property name="ignore_hidden">True</property>
+    <widgets>
+      <widget name="GNUNET_GTK_search_frame_download_location_label"/>
+      <widget name="GNUNET_GTK_search_frame_download_filename_label"/>
+      <widget name="GNUNET_GTK_search_frame_download_anonymity_label"/>
+      <widget name="GNUNET_GTK_search_frame_download_location_chooser"/>
+      <widget name="GNUNET_GTK_search_frame_download_filename_entry"/>
+      <widget name="GNUNET_GTK_search_frame_download_filename_change_button"/>
+      <widget name="main_window_download_anonymity_combobox_alignment"/>
+      <widget name="GNUNET_GTK_search_frame_download_recursive_checkbox"/>
+    </widgets>
+  </object>
   <object class="GtkAdjustment" id="expiration_year_adjustment">
     <property name="upper">9999</property>
     <property name="step_increment">1</property>

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c  2012-12-20 00:39:17 UTC 
(rev 25571)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c  2012-12-20 08:11:59 UTC 
(rev 25572)
@@ -55,6 +55,14 @@
    */
   char *dirname;
 
+  /**
+   * Set to GNUNET_YES if pressing "Save" button should initiate the download
+   * right away, set to GNUNET_NO if it should only change directory and file
+   * names on the download panel.
+   * Popup menu sets it to GNUNET_YES, download panel "Change name" button sets
+   * it to GNUNET_NO.
+   */
+  int download_directly;
 };
 
 
@@ -100,9 +108,7 @@
 
 
 /**
- * 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).
+ * The 'save_as' dialog is being deleted.  Clean up.
  *
  * @param widget the dialog object
  * @param event the deletion event
@@ -151,39 +157,50 @@
       GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER 
(dlc->dialog));
   cb = GTK_TOGGLE_BUTTON (gtk_builder_get_object
                          (dlc->builder, 
"GNUNET_GTK_save_as_recursive_check_button"));
-  de->is_recursive =
-      (TRUE ==
-       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
-      GNUNET_NO;
-  de->anonymity =
-    (uint32_t) gtk_spin_button_get_value (GTK_SPIN_BUTTON
-                                         (gtk_builder_get_object
-                                          (dlc->builder,
-                                           
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
+  if (dlc->download_directly)
+  {
+    de->is_recursive =
+        (TRUE ==
+         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
+        GNUNET_NO;
+    de->anonymity =
+      (uint32_t) gtk_spin_button_get_value (GTK_SPIN_BUTTON
+                                           (gtk_builder_get_object
+                                            (dlc->builder,
+                                             
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
+  }
   gtk_widget_destroy (GTK_WIDGET (dialog));
+  if (dlc->download_directly)
+    GNUNET_FS_GTK_download_context_start_download (de);
+  else if (de->sr != NULL && de->sr->tab != NULL && de->sr->rr != NULL)
+  {
+    /* Update download panel */
+    GNUNET_FS_GTK_set_item_downloaded_name (de->sr->tab->ts, de->sr->rr, 
de->filename);
+    GNUNET_FS_GTK_free_download_entry (de);
+  }
   /* we were successful, do not remove the directory (if we created one) */
   GNUNET_free_non_null (dlc->dirname);
   dlc->dirname = NULL;
   clean_up_download_as_context (dlc);
-  GNUNET_FS_GTK_download_context_start_download (de);
 }
 
-
-/**
- * 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 de download context for the file/directory 
+/* FIXME: implement handling for corner cases:
+ * A) Selection changes in search tab while SaveAs dialog is open.
+ *    If it's in direct download mode, ignore that; otherwise destroy the 
dialog.
+ * B) Download! is pressed in download panel (or the search result is otherwise
+ *    being downloaded without using saveas dialog) while SaveAs dialog is 
open.
+ *    Destroy SaveAs dialog.
  */
-void
-GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de)
+static void
+open_saveas_dialog (struct DownloadEntry *de, int download_directly)
 {
   struct DownloadAsDialogContext *dlc;
   GtkWidget *cb;
+  GtkWidget *hb;
 
   dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext));
   dlc->de = de;
+  dlc->download_directly = download_directly;
   dlc->builder =
     GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade",
                                dlc);
@@ -201,10 +218,19 @@
      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_YES == de->is_directory)
-    gtk_widget_set_sensitive (cb, TRUE);  
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb),
-                               de->is_recursive);   
+  hb = GTK_WIDGET (gtk_builder_get_object (dlc->builder, 
"GNUNET_GTK_save_as_dialog_options_hbox"));
+  if (download_directly)
+  {
+    if (GNUNET_YES == de->is_directory)
+      gtk_widget_set_sensitive (cb, TRUE);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb),
+                                 de->is_recursive);
+    gtk_widget_show (hb);
+  }
+  else
+  {
+    gtk_widget_hide (hb);
+  }
 
   /* initialize filename based on filename from 'dc' */
   if (NULL != de->filename)
@@ -240,8 +266,37 @@
   gtk_window_present (GTK_WINDOW (dlc->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.
+ * Pressing 'Save' button will initiate the download.
+ *
+ * @param de download context for the file/directory
+ */
+void
+GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de)
+{
+  open_saveas_dialog (de, GNUNET_YES);
+}
 
 /**
+ * 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.
+ * Pressing 'Save' button will change selected directory and
+ * file name in download panel, but will not initiate the download.
+ *
+ * @param de download context for the file/directory
+ */
+void
+GNUNET_FS_GTK_open_change_download_name_dialog (struct DownloadEntry *de)
+{
+  open_saveas_dialog (de, GNUNET_NO);
+}
+
+
+/**
  * 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

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h  2012-12-20 00:39:17 UTC 
(rev 25571)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h  2012-12-20 08:11:59 UTC 
(rev 25572)
@@ -43,17 +43,29 @@
 
 
 /**
- * Open the 'save as' dialog for a download.  Calls
- * 'GNUNET_FS_GTK_download_context_start_download' when the dialog is
- * complete.  Will release the 'dc' resources if the dialog is
- * cancelled.
+ * 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.
+ * Pressing 'Save' button will initiate the download.
  *
- * @param dc download context for the file/directory 
+ * @param de download context for the file/directory
  */
 void
 GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de);
 
+/**
+ * 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.
+ * Pressing 'Save' button will change selected directory and
+ * file name in download panel, but will not initiate the download.
+ *
+ * @param de download context for the file/directory
+ */
+void
+GNUNET_FS_GTK_open_change_download_name_dialog (struct DownloadEntry *de);
 
+
 /**
  * Free resources associated with the given download entry.
  *

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c     2012-12-20 00:39:17 UTC 
(rev 25571)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c     2012-12-20 08:11:59 UTC 
(rev 25572)
@@ -262,11 +262,16 @@
 static struct PublishTab *publish_tab;
 
 /**
- * Special tab we use to store publishing operations.
+ * Currently displayed search tab
  */
 static struct SearchTab *current_search_tab = NULL;
 
 /**
+ * Currently selected row in a search tab.
+ */
+static GtkTreePath *current_selected_search_result = NULL;
+
+/**
  * Animation to display while publishing.
  */
 static struct GNUNET_FS_AnimationContext *animation_publishing;
@@ -393,120 +398,6 @@
 }
 
 /**
- * Called recursively to build a suggested filename by prepending
- * suggested names for its parent directories (if any).
- *
- * @param tm tree model this function gets the data from
- * @param iter current position in the tree, for which we want a suggested 
filename
- * @param top GNUNET_YES for the original call to this function,
- *            GNUNET_NO for recursive calls; used to decide if the
- *            current call is eligible to set 'anonymity' and 'local_parents'
- * @param local_parents set to GNUNET_YES if all parents are directories, and 
are downloaded.
- * @param anonymity set to the anonymity level of the closest ancestor 
download (if any);
- *                      set to "-1" for uninitialized initially (will be left 
at -1 if
- *                      no suitable parent download was found)
- * @param filename_is_absolute set to GNUNET_YES if the suggestion is an 
absolute filename,
- *                             GNUNET_NO for relative filenames (gotten from 
meta data)
- * @return suggested filename, possibly NULL
- */
-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;
-  char *filename;
-  int downloaded_anonymity;
-  int have_a_parent;
-  struct GNUNET_CONTAINER_MetaData *meta;
-  GtkTreeIter parent;
-  const char *basename; 
-  char *dot;
-
-  /* FIXME-BUG-MAYBE: this function is likely responsible for not always
-     suggesting the best filename... To be investigated some more... */
-  gtk_tree_model_get (tm, iter,
-                      SEARCH_TAB_MC_METADATA, &meta, 
-                      SEARCH_TAB_MC_DOWNLOADED_FILENAME, &local_filename, 
-                      SEARCH_TAB_MC_DOWNLOADED_ANONYMITY,
-                      &downloaded_anonymity, 
-                      -1);  
-  if (GNUNET_NO == top)
-  {
-    if (NULL != local_filename)
-      *local_parents = GNUNET_YES;
-    else
-      *local_parents = GNUNET_NO;
-    if  ( (downloaded_anonymity != -1) &&
-         (*anonymity == -1) )
-      *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 (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.
-     */
-    if ( (NULL == dirname) && (GNUNET_NO == have_a_parent))
-    {
-      /* This is the root. Use absolute path. */
-      basename = (const char *) local_filename;
-      *filename_is_absolute = GNUNET_YES;
-    }
-    else
-    {
-      basename = GNUNET_STRINGS_get_short_name (local_filename);
-    }
-    if ( (NULL != basename) && (strlen (basename) > 0) )
-    {
-      filename = GNUNET_strdup (basename);
-      dot = strrchr (filename, '.');
-      if (dot)
-        *dot = '\0';
-    }
-    else
-    {
-      filename = GNUNET_FS_meta_data_suggest_filename (meta);
-    }
-  }
-  if ( (NULL != dirname) && (NULL != filename) )
-  {
-    GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename);
-    GNUNET_free (filename);
-    GNUNET_free (dirname);
-    return result;
-  }
-  if (NULL != filename)
-    return filename;
-  return NULL;
-}
-
-
-/**
  * finished_chain - non-NULL for top-level call (for the item we're about to 
download), NULL otherwise
  *   function sets it to GNUNET_YES if the item we're about to download was, 
in fact, already downloaded once, and thus we provide a name for it,
  *   returning a finished relative filename that might only need .gnd appended 
to it, nothing else.
@@ -586,6 +477,9 @@
       gchar *bname = g_path_get_basename (filename);
       int chain_ok;
       char *dot_gnd;
+      /* FIXME: Use better checking (don't compare paths as strings,
+       * only verify directory inode is the same, or something).
+       */
 #if WINDOWS
       /* Kind of stricmp() for utf-8 */
       gchar *tmp = g_utf8_casefold (our_dirname, -1);
@@ -631,6 +525,18 @@
 }
 
 
+/**
+ * Builds a suggested filename by prepending
+ * suggested names for its parent directories (if any).
+ *
+ * @param tm tree model this function gets the data from
+ * @param iter current position in the tree, for which we want a suggested 
filename
+ * @param download_directory will receive a pointer to download directory.
+ *                           free it with GNUNET_free() when done.
+ *                           Will never be NULL on return (CWD will be used as 
a fallback).
+ * @param anonymity will receive suggested anonymity (or -1 if anonymity can't 
be suggested)
+ * @return suggested filename relative to download directory (free with 
GNUNET_free()), or NULL
+ */
 static char *
 get_suggested_filename_anonymity2 (GtkTreeModel *tm,
                                   GtkTreeIter *iter, 
@@ -642,7 +548,7 @@
   char *relname;
   char *filename;
   char *tmp;
-  int downloaded_anonymity;
+  int downloaded_anonymity = -1;
   struct GNUNET_CONTAINER_MetaData *meta;
   size_t tmplen;
   int finished_chain;
@@ -697,7 +603,10 @@
         result = GNUNET_strdup (tmp);
     }
   }
+  else
+    result = NULL;
   *download_directory = GNUNET_strdup (downloaddir);
+  *anonymity = downloaded_anonymity;
   GNUNET_free (filename);
   g_free (downloaddir);
   g_free (relname);
@@ -705,141 +614,6 @@
 }
 
 /**
- * This function is called when the user double-clicks on a search
- * result.  Begins the download, if necessary by opening the "save as"
- * window.
- *
- * @param tree_view tree view with the details
- * @param path path selecting which entry we want to download
- * @param tab the search tab where the user triggered the download request
- * @param is_recursive was the request for a recursive download?
- * @param save_as force opening the 'save as' dialog?
- */
-static void
-start_download (GtkTreeView *tree_view, 
-               GtkTreePath *path,
-                struct SearchTab *tab,
-               int is_recursive,
-               int save_as)
-{
-  GtkTreeModel *tm;
-  GtkTreeIter iter;
-  struct GNUNET_FS_Uri *uri;
-  struct GNUNET_CONTAINER_MetaData *meta;
-  struct SearchResult *sr;
-  struct DownloadEntry *de;
-  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;
-
-  tm = gtk_tree_view_get_model (tree_view);
-  if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  gtk_tree_model_get (tm, &iter,
-                      SEARCH_TAB_MC_METADATA, &meta,
-                      SEARCH_TAB_MC_URI, &uri,
-                      SEARCH_TAB_MC_SEARCH_RESULT, &sr,
-                      -1);
-  if (NULL == uri)
-  {
-    /* user clicked on directory that was opened (not downloaded!), so we
-       have no URI and downloading makes no sense. Ignore! */
-    return;
-  }
-  if (NULL != sr->download)
-  {
-    /* download already active! */
-    return;
-  }
-  if (!(GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))
-  {
-    /* can only download chk/loc URIs, ignore */
-    /* break because in this case, we should not have even gotten here */
-    GNUNET_break (0);
-    return;
-  }
-
-  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_NO;
-  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 (download_directory);
-    }
-    else
-    {
-      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 ==
-         GNUNET_FS_meta_data_test_for_directory (meta))
-      {
-       if ( (tmp[tmplen-1] == '/') ||
-            (tmp[tmplen-1] == '\\') )
-         tmp[tmplen-1] = '\0';
-       GNUNET_asprintf (&buf,
-                        "%s%s",
-                        tmp,
-                        GNUNET_FS_DIRECTORY_EXT);
-       GNUNET_free (tmp);           
-      }
-      else
-      {
-       buf = tmp;
-      }
-    }
-  }
-  GNUNET_free_non_null (filename);
-
-  /* now setup everything for the save-as dialog */
-  de = GNUNET_malloc (sizeof (struct DownloadEntry));
-  de->uri = GNUNET_FS_uri_dup (uri);
-  de->filename = buf;
-  de->sr = sr;
-  sr->download = de;
-  de->anonymity = anonymity;
-  de->is_recursive = is_recursive;
-  de->is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
-  if (save_as)
-    have_a_suggestion = GNUNET_NO;
-  if ( (GNUNET_YES == local_parents) &&
-       (GNUNET_YES == have_a_suggestion) )
-    /* Skip the dialog, call directly */
-    GNUNET_FS_GTK_download_context_start_download (de);
-  else
-    GNUNET_FS_GTK_open_download_as_dialog (de);
-}
-
-
-/**
  * Context for the search list popup menu.
  */
 struct SearchListPopupContext
@@ -879,80 +653,7 @@
   GNUNET_free (spc);
 }
 
-
 /**
- * This function is called when the user double-clicks on a search
- * result.  Begins the download, if necessary by opening the "save as"
- * window.
- *
- * @param tree_view tree view with the details
- * @param path path selecting which entry we want to download
- * @param column unused entry specifying which column the mouse was in
- * @param user_data the 'struct SearchTab' that was activated
- */
-void
-GNUNET_FS_GTK_search_treeview_row_activated (GtkTreeView * tree_view, 
-                                            GtkTreePath * path,
-                                            GtkTreeViewColumn * column, 
-                                            gpointer user_data)
-{
-  struct SearchTab *tab = user_data;
-  struct GNUNET_FS_Uri *uri;
-  GtkTreeModel *tm;
-  GtkTreeIter iter;
-
-  tm = gtk_tree_view_get_model (tree_view);
-  if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  gtk_tree_model_get (tm, &iter,
-                      SEARCH_TAB_MC_URI, &uri, -1);
-  if (NULL == uri)
-  {
-    /* user clicked on directory that was opened (not downloaded!), so we
-       have no URI and downloading makes no sense. Ignore! */
-    return;
-  }
-  if (GNUNET_FS_uri_test_ksk (uri) ||
-      GNUNET_FS_uri_test_sks (uri))
-  {
-    GNUNET_FS_GTK_handle_uri (uri, 1);
-    return;
-  }
-  /* must be chk/loc URI, start download */
-  start_download (tree_view, path, tab, GNUNET_NO, GNUNET_NO);
-}
-
-
-/**
- * "Download" was selected in the current search context menu.
- * 
- * @param spc the 'struct SearchListPopupContext' of the menu 
- * @param is_recursive was this the 'recursive' option?
- * @parma save_as was this the 'save as' option?
- */
-static void
-start_download_ctx_menu_helper (struct SearchListPopupContext *spc,
-                               int is_recursive,
-                               int save_as)
-{
-  GtkTreePath *path;
-  GtkTreeView *tv;
-
-  path = gtk_tree_row_reference_get_path (spc->rr);
-  tv = GTK_TREE_VIEW (gtk_builder_get_object
-                      (spc->tab->builder,
-                       "_search_result_frame"));
-  start_download (tv, path, spc->tab,
-                 is_recursive,
-                 save_as);
-  gtk_tree_path_free (path);
-}
-
-
-/**
  * Selected row has changed in search result tree view, update preview
  * and metadata areas.
  *
@@ -964,8 +665,14 @@
                                              gpointer user_data);
 
 
+/**
+ * save_as - GNUNET_YES to open SaveAs dialog, GNUNET_NO to start downloading.
+ * download_directly - GNUNET_YES to make SaveAs dialog initiate the download,
+ *                     GNUNET_NO to only change names on the download panel.
+ *                     Ingored if save_as is GNUNET_NO.
+ */
 static void
-start_download2 ()
+start_download2 (int save_as, int download_directly)
 {
   struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context 
();
   struct SearchTab *st = GNUNET_FS_GTK_get_current_search_tab ();
@@ -998,6 +705,16 @@
                       SEARCH_TAB_MC_SEARCH_RESULT, &sr,
                       -1);
 
+  if (uri == NULL)
+    return;
+
+  if (GNUNET_FS_uri_test_ksk (uri) ||
+      GNUNET_FS_uri_test_sks (uri))
+  {
+    GNUNET_FS_GTK_handle_uri (uri, 1);
+    return;
+  }
+
   if (!((NULL == sr->download) && (NULL != uri) &&
       ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))))
     return;
@@ -1031,18 +748,60 @@
   de->is_recursive = recursive;
   de->is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
 
-  GNUNET_FS_GTK_download_context_start_download (de);
+  if (save_as == GNUNET_NO)
+    GNUNET_FS_GTK_download_context_start_download (de);
+  else if (download_directly == GNUNET_YES)
+    GNUNET_FS_GTK_open_download_as_dialog (de);
+  else
+    GNUNET_FS_GTK_open_change_download_name_dialog (de);
 
   gtk_tree_path_free (path);
   g_free (downloaddir);
 
-  if (GNUNET_GTK_tree_model_get_next_flat_iter (model, &iter, !recursive, 
&next_item))
-    gtk_tree_selection_select_iter (sel, &next_item);
-  GNUNET_FS_GTK_search_treeview_cursor_changed (tv, st);
+  if (!save_as)
+  {
+    if (GNUNET_GTK_tree_model_get_next_flat_iter (model, &iter, !recursive, 
&next_item))
+      gtk_tree_selection_select_iter (sel, &next_item);
+    GNUNET_FS_GTK_search_treeview_cursor_changed (tv, st);
+  }
 }
 
+/**
+ * "Download" was selected in the current search context menu.
+ *
+ * @param spc the 'struct SearchListPopupContext' of the menu
+ * @param is_recursive was this the 'recursive' option?
+ * @parma save_as was this the 'save as' option?
+ */
+static void
+start_download_ctx_menu_helper (struct SearchListPopupContext *spc,
+                               int is_recursive,
+                               int save_as)
+{
+  start_download2 (save_as, GNUNET_YES);
+}
 
 /**
+ * This function is called when the user double-clicks on a search
+ * result.  Begins the download, if necessary by opening the "save as"
+ * window.
+ *
+ * @param tree_view tree view with the details
+ * @param path path selecting which entry we want to download
+ * @param column unused entry specifying which column the mouse was in
+ * @param user_data the 'struct SearchTab' that was activated
+ */
+void
+GNUNET_FS_GTK_search_treeview_row_activated (GtkTreeView * tree_view,
+                                            GtkTreePath * path,
+                                            GtkTreeViewColumn * column,
+                                            gpointer user_data)
+{
+  start_download2 (GNUNET_NO, GNUNET_NO);
+}
+
+
+/**
  * User clicked on "Download!" button at the download options panel.
  *
  * @param button the "Download!" button
@@ -1052,10 +811,24 @@
 GNUNET_GTK_search_frame_download_download_button_clicked_cb (
     GtkButton *button, gpointer user_data)
 {
-  start_download2 ();
+  start_download2 (GNUNET_NO, GNUNET_NO);
 }
 
+/**
+ * User clicked on "..." button at the download options panel, next
+ * to the Download As entry.
+ *
+ * @param button the "..." button
+ * @param user_data the main window context
+ */
+void
+GNUNET_GTK_search_frame_download_filename_change_button_clicked_cb (
+    GtkButton *button, gpointer user_data)
+{
+  start_download2 (GNUNET_YES, GNUNET_NO);
+}
 
+
 /**
  * "Download" was selected in the current search context menu.
  * 
@@ -1093,10 +866,9 @@
  * @param user_data the 'struct SearchListPopupContext' of the menu 
  */
 static void
-start_download_as_ctx_menu (GtkMenuItem *item, gpointer user_data)
+download_as_ctx_menu (GtkMenuItem *item, gpointer user_data)
 {
   struct SearchListPopupContext *spc = user_data;
-
   start_download_ctx_menu_helper (spc, GNUNET_NO, GNUNET_YES);
 }
 
@@ -1112,9 +884,12 @@
 {
   struct SearchListPopupContext *spc = user_data;
   struct DownloadEntry *de = spc->sr->download;
+  GtkTreeView *tv;
 
   GNUNET_assert (de->dc != NULL);
   GNUNET_FS_download_stop (de->dc, GNUNET_YES);
+  tv = GTK_TREE_VIEW (gtk_builder_get_object (spc->tab->builder, 
"_search_result_frame"));
+  GNUNET_FS_GTK_search_treeview_cursor_changed (tv, spc->tab);
 }
 
 
@@ -1187,6 +962,8 @@
   struct SearchResult *sr;
   struct GNUNET_FS_Uri *uri;
   struct SearchListPopupContext *spc;
+  struct GNUNET_CONTAINER_MetaData *meta;
+  gboolean is_directory = FALSE;
 
   spc = GNUNET_malloc (sizeof (struct SearchListPopupContext));
   spc->tab = tab;
@@ -1195,8 +972,12 @@
   gtk_tree_path_free (path);
   gtk_tree_model_get (tm, iter,
                       SEARCH_TAB_MC_URI, &uri,
+                      SEARCH_TAB_MC_METADATA, &meta,
                       SEARCH_TAB_MC_SEARCH_RESULT, &sr,
                       -1);
+  if (meta != NULL)
+    is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
+
   spc->sr = sr;
   menu = GTK_MENU (gtk_menu_new ());
   if ( (NULL == sr->download) &&
@@ -1212,19 +993,22 @@
                                 TRUE);
     gtk_widget_show (child);
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
-    
-    child = gtk_menu_item_new_with_label (_("Download _recursively"));
-    g_signal_connect (child, "activate",
-                     G_CALLBACK (start_download_recursively_ctx_menu), spc);
-    gtk_label_set_use_underline (GTK_LABEL
-                                (gtk_bin_get_child (GTK_BIN (child))),
-                                TRUE);
-    gtk_widget_show (child);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
 
+    if (is_directory)
+    {
+      child = gtk_menu_item_new_with_label (_("Download _recursively"));
+      g_signal_connect (child, "activate",
+                       G_CALLBACK (start_download_recursively_ctx_menu), spc);
+      gtk_label_set_use_underline (GTK_LABEL
+                                  (gtk_bin_get_child (GTK_BIN (child))),
+                                  TRUE);
+      gtk_widget_show (child);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+    }
+
     child = gtk_menu_item_new_with_label (_("Download _as..."));
     g_signal_connect (child, "activate",
-                     G_CALLBACK (start_download_as_ctx_menu), spc);
+                     G_CALLBACK (download_as_ctx_menu), spc);
     gtk_label_set_use_underline (GTK_LABEL
                                 (gtk_bin_get_child (GTK_BIN (child))),
                                 TRUE);
@@ -1773,6 +1557,7 @@
   GtkTreeIter iter;
   struct GNUNET_CONTAINER_MetaData *meta;
   GdkPixbuf *pixbuf;
+  GtkTreePath *selpath;
   struct SearchResult *sr;
   struct GNUNET_FS_Uri *uri;
   struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context 
();
@@ -1785,6 +1570,9 @@
     /* nothing selected, clear preview */
     gtk_image_clear (mctx->preview_image);
     gtk_widget_hide (GTK_WIDGET (mctx->download_panel));
+    if (current_selected_search_result != NULL)
+      gtk_tree_path_free (current_selected_search_result);
+    current_selected_search_result = NULL;
     return;
   }
   meta = NULL;
@@ -1797,39 +1585,49 @@
                       SEARCH_TAB_MC_SEARCH_RESULT, &sr,
                       -1);
 
-  if ((NULL == sr->download) && (NULL != uri) &&
-      ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri))))
+  selpath = gtk_tree_model_get_path (model, &iter);
+  if (current_selected_search_result == NULL || gtk_tree_path_compare 
(selpath, current_selected_search_result) != 0)
   {
-    char *download_directory;
-    char *filename;
-    int anonymity;
-    int is_directory;
+    if ((NULL == sr->download) && (NULL != uri) &&
+        ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri))))
+    {
+      char *download_directory;
+      char *filename;
+      int anonymity;
+      int is_directory;
 
-    /* Calculate suggested filename */
-    anonymity = -1;
-    download_directory = NULL;
-    filename = get_suggested_filename_anonymity2 (model, &iter,
-        &download_directory, &anonymity);
+      /* Calculate suggested filename */
+      anonymity = -1;
+      download_directory = NULL;
+      filename = get_suggested_filename_anonymity2 (model, &iter,
+          &download_directory, &anonymity);
 
-    is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
-    gtk_widget_set_sensitive (GTK_WIDGET 
(mctx->download_recursive_checkbutton), is_directory);
+      is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
+      gtk_widget_set_sensitive (GTK_WIDGET 
(mctx->download_recursive_checkbutton), is_directory);
 
-    /* TODO: make this configurable */
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(mctx->download_recursive_checkbutton), is_directory);
+      /* TODO: make this configurable */
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(mctx->download_recursive_checkbutton), is_directory);
 
-    /* TODO: make this configurable */
-    GNUNET_GTK_select_anonymity_combo_level (mctx->download_anonymity_combo, 
anonymity >= 0 ? anonymity : 1);
+      /* TODO: make this configurable */
+      GNUNET_GTK_select_anonymity_combo_level (mctx->download_anonymity_combo, 
anonymity >= 0 ? anonymity : 1);
 
-    gtk_entry_set_text (mctx->download_name_entry, filename != NULL ? filename 
: NULL);
-    gtk_file_chooser_set_current_folder (mctx->download_location_chooser, 
download_directory);
+      gtk_entry_set_text (mctx->download_name_entry, filename != NULL ? 
filename : NULL);
+      gtk_file_chooser_set_current_folder (mctx->download_location_chooser, 
download_directory);
     
-    gtk_widget_show_all (GTK_WIDGET (mctx->download_panel));
-    GNUNET_free (filename);
-    GNUNET_free (download_directory);
+      gtk_widget_show_all (GTK_WIDGET (mctx->download_panel));
+      GNUNET_free_non_null (filename);
+      GNUNET_free (download_directory);
+    }
+    else
+      gtk_widget_hide (GTK_WIDGET (mctx->download_panel));
+    if (current_selected_search_result != NULL)
+      gtk_tree_path_free (current_selected_search_result);
+    current_selected_search_result = selpath;
   }
   else
-    gtk_widget_hide (GTK_WIDGET (mctx->download_panel));
+    gtk_tree_path_free (selpath);
 
+
   if (NULL != pixbuf)
   {
     gtk_image_set_from_pixbuf (mctx->preview_image, pixbuf);
@@ -1880,6 +1678,9 @@
      clear meta data and preview widgets */
   gtk_image_clear (mctx->preview_image);
   gtk_list_store_clear (mctx->md_liststore);
+  if (current_selected_search_result != NULL)
+    gtk_tree_path_free (current_selected_search_result);
+  current_selected_search_result = NULL;
 }
 
 
@@ -2122,7 +1923,6 @@
     GNUNET_break (0);
     return;
   }
-  gtk_tree_path_free (tp);
   desc = GNUNET_FS_GTK_get_description_from_metadata (meta, &desc_is_a_dup);
   mime = get_mimetype_from_metadata (meta);
   pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
@@ -2157,10 +1957,20 @@
   page = gtk_notebook_get_current_page (mctx->notebook);
   if (gtk_notebook_get_nth_page (mctx->notebook, page) == sr->tab->frame)
   {
-    tv = GTK_TREE_VIEW (gtk_builder_get_object
-                        (sr->tab->builder, "_search_result_frame"));
-    GNUNET_FS_GTK_search_treeview_cursor_changed (tv, sr->tab);
+    GtkTreeSelection *sel;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    tv = GTK_TREE_VIEW (gtk_builder_get_object (sr->tab->builder, 
"_search_result_frame"));
+    sel = gtk_tree_view_get_selection (tv);
+    if (gtk_tree_selection_get_selected (sel, &model, &iter))
+    {
+      GtkTreePath *selpath = gtk_tree_model_get_path (model, &iter);
+      if (gtk_tree_path_compare (selpath, tp) == 0)
+        GNUNET_FS_GTK_search_treeview_cursor_changed (tv, sr->tab);
+      gtk_tree_path_free (selpath);
+    }
   }
+  gtk_tree_path_free (tp);
 }
 
 
@@ -2313,6 +2123,85 @@
 
 
 /**
+ * Sets downloaded name on an item referenced by @rr
+ * in a tree store @ts to @filename.
+ * Used by SaveAs dialog to communicate back new filename
+ * (unless SaveAs dialog initiates the download by itself).
+ * Arguments can be taken from DownloadEntry.
+ *
+ * @param ts treestore
+ * @param rr row reference
+ * @param filename new filename
+ */
+void
+GNUNET_FS_GTK_set_item_downloaded_name (GtkTreeStore *ts, GtkTreeRowReference 
*rr, gchar *filename)
+{
+  struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context 
();
+  GtkTreeIter iter;
+  GtkTreePath *path;
+
+  path = gtk_tree_row_reference_get_path (rr);
+  if (path)
+  {
+    if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &iter, path))
+    {
+      /* TODO: maybe create a new store slot for user-defined filenames?
+       * Also - maybe separate slots for downloaddir and relative filename?
+       */
+      /* This code relies on download panel contents being re-populated every 
0.2 seconds,
+       * thus it updates the treestore item property, from which suggested 
filename
+       * is derived.
+       */
+      /*
+      char *download_directory;
+      char *suggested_filename;
+      int anonymity = -1;
+
+      gtk_tree_store_set (ts, &iter, SEARCH_TAB_MC_DOWNLOADED_FILENAME, 
filename, -1);
+
+      download_directory = NULL;
+      suggested_filename = get_suggested_filename_anonymity2 (GTK_TREE_MODEL 
(ts), &iter,
+          &download_directory, &anonymity);
+
+      gtk_entry_set_text (mctx->download_name_entry, suggested_filename != 
NULL ? suggested_filename : NULL);
+      gtk_file_chooser_set_current_folder (mctx->download_location_chooser, 
download_directory);
+
+      GNUNET_free_non_null (suggested_filename);
+      GNUNET_free (download_directory);
+      */
+      /* This code relies on download panel contents NOT being re-populated 
every 0.2 seconds,
+       * thus it only updates download panel contents - these changes will be 
lost after
+       * selecting a different item and then coming back to this one.
+       */
+      gchar *current = g_strdup (filename);
+      gchar *dirname = NULL;
+      /* We take the filename user gave us, then check its parent directories 
until
+       * we find one that actually exists (SaveAs dialog might have some 
options about
+       * only picking existing names, but better be safe.
+       * gtk_file_chooser_set_current_folder() does NOT work with non-existing 
dirnames!
+       */
+      do
+      {
+        dirname = g_path_get_dirname (current);
+        g_free (current);
+        if (g_file_test (dirname, G_FILE_TEST_EXISTS))
+        {
+          gchar *relname = &filename[strlen (dirname)];
+          while (relname[0] == '/' || relname[0] == '\\')
+            relname++;
+          gtk_entry_set_text (mctx->download_name_entry, relname);
+          gtk_file_chooser_set_current_folder 
(mctx->download_location_chooser, dirname);
+          break;
+        }
+        current = dirname;
+      } while (dirname[0] != '.'); /* FIXME: Check that this condition is 
correct */
+      g_free (dirname);
+    }
+    gtk_tree_path_free (path);
+  }
+}
+
+/**
  * We have received a search result from the FS API.  Add it to the
  * respective search tab.  The search result can be an 'inner'
  * search result (updated result for a namespace search) or a

Modified: gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h     2012-12-20 00:39:17 UTC 
(rev 25571)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h     2012-12-20 08:11:59 UTC 
(rev 25572)
@@ -176,7 +176,6 @@
    * Has the download completed (or failed)?
    */
   int is_done;
-
 };
 
 
@@ -249,6 +248,9 @@
                               uint32_t applicability_rank);
 
 
+void
+GNUNET_FS_GTK_set_item_downloaded_name (GtkTreeStore *ts, GtkTreeRowReference 
*rr, gchar *filename);
+
 /**
  * Notification of FS to a client about the progress of an
  * operation.  Callbacks of this type will be used for uploads,




reply via email to

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