aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2012-12-20 08:11:59 +0000
committerLRN <lrn1986@gmail.com>2012-12-20 08:11:59 +0000
commit2159c6ec96392bbde5f0749747eba109cc56861a (patch)
tree71384a7269824026723c84764b0080bee7693166
parent52e002de9a56d56439ce37d57bad766264f41a10 (diff)
downloadgnunet-gtk-2159c6ec96392bbde5f0749747eba109cc56861a.tar.gz
gnunet-gtk-2159c6ec96392bbde5f0749747eba109cc56861a.zip
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.
-rw-r--r--contrib/gnunet_fs_gtk_download_as_dialog.glade3
-rw-r--r--contrib/gnunet_fs_gtk_main_window.glade32
-rw-r--r--src/fs/gnunet-fs-gtk_download-save-as.c107
-rw-r--r--src/fs/gnunet-fs-gtk_download-save-as.h22
-rw-r--r--src/fs/gnunet-fs-gtk_event-handler.c627
-rw-r--r--src/fs/gnunet-fs-gtk_event-handler.h4
6 files changed, 393 insertions, 402 deletions
diff --git a/contrib/gnunet_fs_gtk_download_as_dialog.glade b/contrib/gnunet_fs_gtk_download_as_dialog.glade
index 31587f41..2fa82b48 100644
--- a/contrib/gnunet_fs_gtk_download_as_dialog.glade
+++ b/contrib/gnunet_fs_gtk_download_as_dialog.glade
@@ -19,6 +19,7 @@
19 <property name="type_hint">dialog</property> 19 <property name="type_hint">dialog</property>
20 <property name="action">save</property> 20 <property name="action">save</property>
21 <property name="use_preview_label">False</property> 21 <property name="use_preview_label">False</property>
22 <property name="do_overwrite_confirmation">True</property>
22 <property name="preview_widget_active">False</property> 23 <property name="preview_widget_active">False</property>
23 <signal name="response" handler="GNUNET_GTK_save_as_dialog_response_cb"/> 24 <signal name="response" handler="GNUNET_GTK_save_as_dialog_response_cb"/>
24 <signal name="delete_event" handler="GNUNET_GTK_save_as_dialog_delete_event_cb"/> 25 <signal name="delete_event" handler="GNUNET_GTK_save_as_dialog_delete_event_cb"/>
@@ -28,7 +29,7 @@
28 <property name="orientation">vertical</property> 29 <property name="orientation">vertical</property>
29 <property name="spacing">2</property> 30 <property name="spacing">2</property>
30 <child> 31 <child>
31 <object class="GtkHBox" id="hbox2"> 32 <object class="GtkHBox" id="GNUNET_GTK_save_as_dialog_options_hbox">
32 <property name="visible">True</property> 33 <property name="visible">True</property>
33 <child> 34 <child>
34 <object class="GtkLabel" id="GNUNET_GTK_save_as_dialog_anonymity_label"> 35 <object class="GtkLabel" id="GNUNET_GTK_save_as_dialog_anonymity_label">
diff --git a/contrib/gnunet_fs_gtk_main_window.glade b/contrib/gnunet_fs_gtk_main_window.glade
index d2bc993f..6fc375cd 100644
--- a/contrib/gnunet_fs_gtk_main_window.glade
+++ b/contrib/gnunet_fs_gtk_main_window.glade
@@ -807,6 +807,24 @@
807 <property name="position">1</property> 807 <property name="position">1</property>
808 </packing> 808 </packing>
809 </child> 809 </child>
810 <child>
811 <object class="GtkButton" id="GNUNET_GTK_search_frame_download_filename_change_button">
812 <property name="label">…</property>
813 <property name="use_action_appearance">False</property>
814 <property name="height_request">1</property>
815 <property name="visible">True</property>
816 <property name="can_focus">True</property>
817 <property name="receives_default">False</property>
818 <property name="focus_on_click">False</property>
819 <signal name="clicked" handler="GNUNET_GTK_search_frame_download_filename_change_button_clicked_cb" swapped="no"/>
820 </object>
821 <packing>
822 <property name="expand">False</property>
823 <property name="fill">False</property>
824 <property name="pack_type">end</property>
825 <property name="position">2</property>
826 </packing>
827 </child>
810 </object> 828 </object>
811 <packing> 829 <packing>
812 <property name="expand">False</property> 830 <property name="expand">False</property>
@@ -1163,6 +1181,20 @@
1163 <widget name="main_window_search_mime_combobox"/> 1181 <widget name="main_window_search_mime_combobox"/>
1164 </widgets> 1182 </widgets>
1165 </object> 1183 </object>
1184 <object class="GtkSizeGroup" id="GNUNET_FS_GTK_download_frame_vsize_group">
1185 <property name="mode">vertical</property>
1186 <property name="ignore_hidden">True</property>
1187 <widgets>
1188 <widget name="GNUNET_GTK_search_frame_download_location_label"/>
1189 <widget name="GNUNET_GTK_search_frame_download_filename_label"/>
1190 <widget name="GNUNET_GTK_search_frame_download_anonymity_label"/>
1191 <widget name="GNUNET_GTK_search_frame_download_location_chooser"/>
1192 <widget name="GNUNET_GTK_search_frame_download_filename_entry"/>
1193 <widget name="GNUNET_GTK_search_frame_download_filename_change_button"/>
1194 <widget name="main_window_download_anonymity_combobox_alignment"/>
1195 <widget name="GNUNET_GTK_search_frame_download_recursive_checkbox"/>
1196 </widgets>
1197 </object>
1166 <object class="GtkAdjustment" id="expiration_year_adjustment"> 1198 <object class="GtkAdjustment" id="expiration_year_adjustment">
1167 <property name="upper">9999</property> 1199 <property name="upper">9999</property>
1168 <property name="step_increment">1</property> 1200 <property name="step_increment">1</property>
diff --git a/src/fs/gnunet-fs-gtk_download-save-as.c b/src/fs/gnunet-fs-gtk_download-save-as.c
index 9d54763f..76022afa 100644
--- a/src/fs/gnunet-fs-gtk_download-save-as.c
+++ b/src/fs/gnunet-fs-gtk_download-save-as.c
@@ -55,6 +55,14 @@ struct DownloadAsDialogContext
55 */ 55 */
56 char *dirname; 56 char *dirname;
57 57
58 /**
59 * Set to GNUNET_YES if pressing "Save" button should initiate the download
60 * right away, set to GNUNET_NO if it should only change directory and file
61 * names on the download panel.
62 * Popup menu sets it to GNUNET_YES, download panel "Change name" button sets
63 * it to GNUNET_NO.
64 */
65 int download_directly;
58}; 66};
59 67
60 68
@@ -100,9 +108,7 @@ GNUNET_FS_GTK_free_download_entry (struct DownloadEntry *de)
100 108
101 109
102/** 110/**
103 * The 'save_as' dialog is being deleted. Check which state we're in 111 * The 'save_as' dialog is being deleted. Clean up.
104 * and either simply clean up or start the download with the
105 * respective options (by calling the respective continuation).
106 * 112 *
107 * @param widget the dialog object 113 * @param widget the dialog object
108 * @param event the deletion event 114 * @param event the deletion event
@@ -151,39 +157,50 @@ GNUNET_GTK_save_as_dialog_response_cb (GtkDialog * dialog,
151 GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (dlc->dialog)); 157 GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (dlc->dialog));
152 cb = GTK_TOGGLE_BUTTON (gtk_builder_get_object 158 cb = GTK_TOGGLE_BUTTON (gtk_builder_get_object
153 (dlc->builder, "GNUNET_GTK_save_as_recursive_check_button")); 159 (dlc->builder, "GNUNET_GTK_save_as_recursive_check_button"));
154 de->is_recursive = 160 if (dlc->download_directly)
155 (TRUE == 161 {
156 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES : 162 de->is_recursive =
157 GNUNET_NO; 163 (TRUE ==
158 de->anonymity = 164 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
159 (uint32_t) gtk_spin_button_get_value (GTK_SPIN_BUTTON 165 GNUNET_NO;
160 (gtk_builder_get_object 166 de->anonymity =
161 (dlc->builder, 167 (uint32_t) gtk_spin_button_get_value (GTK_SPIN_BUTTON
162 "GNUNET_GTK_save_as_dialog_anonymity_spin_button"))); 168 (gtk_builder_get_object
169 (dlc->builder,
170 "GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
171 }
163 gtk_widget_destroy (GTK_WIDGET (dialog)); 172 gtk_widget_destroy (GTK_WIDGET (dialog));
173 if (dlc->download_directly)
174 GNUNET_FS_GTK_download_context_start_download (de);
175 else if (de->sr != NULL && de->sr->tab != NULL && de->sr->rr != NULL)
176 {
177 /* Update download panel */
178 GNUNET_FS_GTK_set_item_downloaded_name (de->sr->tab->ts, de->sr->rr, de->filename);
179 GNUNET_FS_GTK_free_download_entry (de);
180 }
164 /* we were successful, do not remove the directory (if we created one) */ 181 /* we were successful, do not remove the directory (if we created one) */
165 GNUNET_free_non_null (dlc->dirname); 182 GNUNET_free_non_null (dlc->dirname);
166 dlc->dirname = NULL; 183 dlc->dirname = NULL;
167 clean_up_download_as_context (dlc); 184 clean_up_download_as_context (dlc);
168 GNUNET_FS_GTK_download_context_start_download (de);
169} 185}
170 186
171 187/* FIXME: implement handling for corner cases:
172/** 188 * A) Selection changes in search tab while SaveAs dialog is open.
173 * Open the 'save as' dialog for a download. Calls the 'dc->cb' 189 * If it's in direct download mode, ignore that; otherwise destroy the dialog.
174 * continutation when the dialog is complete. Will release the 'dc' 190 * B) Download! is pressed in download panel (or the search result is otherwise
175 * resources if the dialog is cancelled. 191 * being downloaded without using saveas dialog) while SaveAs dialog is open.
176 * 192 * Destroy SaveAs dialog.
177 * @param de download context for the file/directory
178 */ 193 */
179void 194static void
180GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de) 195open_saveas_dialog (struct DownloadEntry *de, int download_directly)
181{ 196{
182 struct DownloadAsDialogContext *dlc; 197 struct DownloadAsDialogContext *dlc;
183 GtkWidget *cb; 198 GtkWidget *cb;
199 GtkWidget *hb;
184 200
185 dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext)); 201 dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext));
186 dlc->de = de; 202 dlc->de = de;
203 dlc->download_directly = download_directly;
187 dlc->builder = 204 dlc->builder =
188 GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade", 205 GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade",
189 dlc); 206 dlc);
@@ -201,10 +218,19 @@ GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de)
201 set recursive 'default' value based on what the 'dc' tells us */ 218 set recursive 'default' value based on what the 'dc' tells us */
202 cb = GTK_WIDGET (gtk_builder_get_object 219 cb = GTK_WIDGET (gtk_builder_get_object
203 (dlc->builder, "GNUNET_GTK_save_as_recursive_check_button")); 220 (dlc->builder, "GNUNET_GTK_save_as_recursive_check_button"));
204 if (GNUNET_YES == de->is_directory) 221 hb = GTK_WIDGET (gtk_builder_get_object (dlc->builder, "GNUNET_GTK_save_as_dialog_options_hbox"));
205 gtk_widget_set_sensitive (cb, TRUE); 222 if (download_directly)
206 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), 223 {
207 de->is_recursive); 224 if (GNUNET_YES == de->is_directory)
225 gtk_widget_set_sensitive (cb, TRUE);
226 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb),
227 de->is_recursive);
228 gtk_widget_show (hb);
229 }
230 else
231 {
232 gtk_widget_hide (hb);
233 }
208 234
209 /* initialize filename based on filename from 'dc' */ 235 /* initialize filename based on filename from 'dc' */
210 if (NULL != de->filename) 236 if (NULL != de->filename)
@@ -240,6 +266,35 @@ GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de)
240 gtk_window_present (GTK_WINDOW (dlc->dialog)); 266 gtk_window_present (GTK_WINDOW (dlc->dialog));
241} 267}
242 268
269/**
270 * Open the 'save as' dialog for a download. Calls the 'dc->cb'
271 * continutation when the dialog is complete. Will release the 'dc'
272 * resources if the dialog is cancelled.
273 * Pressing 'Save' button will initiate the download.
274 *
275 * @param de download context for the file/directory
276 */
277void
278GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de)
279{
280 open_saveas_dialog (de, GNUNET_YES);
281}
282
283/**
284 * Open the 'save as' dialog for a download. Calls the 'dc->cb'
285 * continutation when the dialog is complete. Will release the 'dc'
286 * resources if the dialog is cancelled.
287 * Pressing 'Save' button will change selected directory and
288 * file name in download panel, but will not initiate the download.
289 *
290 * @param de download context for the file/directory
291 */
292void
293GNUNET_FS_GTK_open_change_download_name_dialog (struct DownloadEntry *de)
294{
295 open_saveas_dialog (de, GNUNET_NO);
296}
297
243 298
244/** 299/**
245 * Actually start the download that is specified by the given download 300 * Actually start the download that is specified by the given download
diff --git a/src/fs/gnunet-fs-gtk_download-save-as.h b/src/fs/gnunet-fs-gtk_download-save-as.h
index db0f8018..9dae7d1a 100644
--- a/src/fs/gnunet-fs-gtk_download-save-as.h
+++ b/src/fs/gnunet-fs-gtk_download-save-as.h
@@ -43,16 +43,28 @@ GNUNET_FS_GTK_download_context_start_download (struct DownloadEntry *de);
43 43
44 44
45/** 45/**
46 * Open the 'save as' dialog for a download. Calls 46 * Open the 'save as' dialog for a download. Calls the 'dc->cb'
47 * 'GNUNET_FS_GTK_download_context_start_download' when the dialog is 47 * continutation when the dialog is complete. Will release the 'dc'
48 * complete. Will release the 'dc' resources if the dialog is 48 * resources if the dialog is cancelled.
49 * cancelled. 49 * Pressing 'Save' button will initiate the download.
50 * 50 *
51 * @param dc download context for the file/directory 51 * @param de download context for the file/directory
52 */ 52 */
53void 53void
54GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de); 54GNUNET_FS_GTK_open_download_as_dialog (struct DownloadEntry *de);
55 55
56/**
57 * Open the 'save as' dialog for a download. Calls the 'dc->cb'
58 * continutation when the dialog is complete. Will release the 'dc'
59 * resources if the dialog is cancelled.
60 * Pressing 'Save' button will change selected directory and
61 * file name in download panel, but will not initiate the download.
62 *
63 * @param de download context for the file/directory
64 */
65void
66GNUNET_FS_GTK_open_change_download_name_dialog (struct DownloadEntry *de);
67
56 68
57/** 69/**
58 * Free resources associated with the given download entry. 70 * Free resources associated with the given download entry.
diff --git a/src/fs/gnunet-fs-gtk_event-handler.c b/src/fs/gnunet-fs-gtk_event-handler.c
index 737dfca5..42780d4b 100644
--- a/src/fs/gnunet-fs-gtk_event-handler.c
+++ b/src/fs/gnunet-fs-gtk_event-handler.c
@@ -262,11 +262,16 @@ static struct SearchTab *uri_tab;
262static struct PublishTab *publish_tab; 262static struct PublishTab *publish_tab;
263 263
264/** 264/**
265 * Special tab we use to store publishing operations. 265 * Currently displayed search tab
266 */ 266 */
267static struct SearchTab *current_search_tab = NULL; 267static struct SearchTab *current_search_tab = NULL;
268 268
269/** 269/**
270 * Currently selected row in a search tab.
271 */
272static GtkTreePath *current_selected_search_result = NULL;
273
274/**
270 * Animation to display while publishing. 275 * Animation to display while publishing.
271 */ 276 */
272static struct GNUNET_FS_AnimationContext *animation_publishing; 277static struct GNUNET_FS_AnimationContext *animation_publishing;
@@ -393,120 +398,6 @@ get_default_download_directory (char *buffer, size_t size)
393} 398}
394 399
395/** 400/**
396 * Called recursively to build a suggested filename by prepending
397 * suggested names for its parent directories (if any).
398 *
399 * @param tm tree model this function gets the data from
400 * @param iter current position in the tree, for which we want a suggested filename
401 * @param top GNUNET_YES for the original call to this function,
402 * GNUNET_NO for recursive calls; used to decide if the
403 * current call is eligible to set 'anonymity' and 'local_parents'
404 * @param local_parents set to GNUNET_YES if all parents are directories, and are downloaded.
405 * @param anonymity set to the anonymity level of the closest ancestor download (if any);
406 * set to "-1" for uninitialized initially (will be left at -1 if
407 * no suitable parent download was found)
408 * @param filename_is_absolute set to GNUNET_YES if the suggestion is an absolute filename,
409 * GNUNET_NO for relative filenames (gotten from meta data)
410 * @return suggested filename, possibly NULL
411 */
412static char *
413get_suggested_filename_anonymity (GtkTreeModel *tm,
414 GtkTreeIter *iter,
415 int top,
416 int *local_parents,
417 int *anonymity,
418 int *filename_is_absolute)
419{
420 char *result;
421 char *dirname;
422 char *local_filename;
423 char *filename;
424 int downloaded_anonymity;
425 int have_a_parent;
426 struct GNUNET_CONTAINER_MetaData *meta;
427 GtkTreeIter parent;
428 const char *basename;
429 char *dot;
430
431 /* FIXME-BUG-MAYBE: this function is likely responsible for not always
432 suggesting the best filename... To be investigated some more... */
433 gtk_tree_model_get (tm, iter,
434 SEARCH_TAB_MC_METADATA, &meta,
435 SEARCH_TAB_MC_DOWNLOADED_FILENAME, &local_filename,
436 SEARCH_TAB_MC_DOWNLOADED_ANONYMITY,
437 &downloaded_anonymity,
438 -1);
439 if (GNUNET_NO == top)
440 {
441 if (NULL != local_filename)
442 *local_parents = GNUNET_YES;
443 else
444 *local_parents = GNUNET_NO;
445 if ( (downloaded_anonymity != -1) &&
446 (*anonymity == -1) )
447 *anonymity = downloaded_anonymity;
448 }
449 if (gtk_tree_model_iter_parent (tm, &parent, iter))
450 {
451 have_a_parent = GNUNET_YES;
452 dirname = get_suggested_filename_anonymity (tm, &parent, GNUNET_NO,
453 local_parents, anonymity,
454 filename_is_absolute);
455 }
456 else
457 {
458 have_a_parent = GNUNET_NO;
459 dirname = NULL;
460 }
461 if (local_filename == NULL)
462 {
463 filename = GNUNET_FS_meta_data_suggest_filename (meta);
464 }
465 else
466 {
467 /* This directory was downloaded as /foo/bar/baz/somedirname
468 * Hopefully, "somedirname" is actually "somedir.gnd"
469 * We need to strip the ".gnd" part to get "somedir", which is
470 * what we're going to use instead of suggested original filename
471 * Without the .gnd extension we're going to just use a copy
472 * of the directory file name - and that would fail. Sad.
473 */
474 if ( (NULL == dirname) && (GNUNET_NO == have_a_parent))
475 {
476 /* This is the root. Use absolute path. */
477 basename = (const char *) local_filename;
478 *filename_is_absolute = GNUNET_YES;
479 }
480 else
481 {
482 basename = GNUNET_STRINGS_get_short_name (local_filename);
483 }
484 if ( (NULL != basename) && (strlen (basename) > 0) )
485 {
486 filename = GNUNET_strdup (basename);
487 dot = strrchr (filename, '.');
488 if (dot)
489 *dot = '\0';
490 }
491 else
492 {
493 filename = GNUNET_FS_meta_data_suggest_filename (meta);
494 }
495 }
496 if ( (NULL != dirname) && (NULL != filename) )
497 {
498 GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename);
499 GNUNET_free (filename);
500 GNUNET_free (dirname);
501 return result;
502 }
503 if (NULL != filename)
504 return filename;
505 return NULL;
506}
507
508
509/**
510 * finished_chain - non-NULL for top-level call (for the item we're about to download), NULL otherwise 401 * finished_chain - non-NULL for top-level call (for the item we're about to download), NULL otherwise
511 * 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, 402 * 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,
512 * returning a finished relative filename that might only need .gnd appended to it, nothing else. 403 * returning a finished relative filename that might only need .gnd appended to it, nothing else.
@@ -586,6 +477,9 @@ build_relative_name (GtkTreeModel *tm,
586 gchar *bname = g_path_get_basename (filename); 477 gchar *bname = g_path_get_basename (filename);
587 int chain_ok; 478 int chain_ok;
588 char *dot_gnd; 479 char *dot_gnd;
480 /* FIXME: Use better checking (don't compare paths as strings,
481 * only verify directory inode is the same, or something).
482 */
589#if WINDOWS 483#if WINDOWS
590 /* Kind of stricmp() for utf-8 */ 484 /* Kind of stricmp() for utf-8 */
591 gchar *tmp = g_utf8_casefold (our_dirname, -1); 485 gchar *tmp = g_utf8_casefold (our_dirname, -1);
@@ -631,6 +525,18 @@ build_relative_name (GtkTreeModel *tm,
631} 525}
632 526
633 527
528/**
529 * Builds a suggested filename by prepending
530 * suggested names for its parent directories (if any).
531 *
532 * @param tm tree model this function gets the data from
533 * @param iter current position in the tree, for which we want a suggested filename
534 * @param download_directory will receive a pointer to download directory.
535 * free it with GNUNET_free() when done.
536 * Will never be NULL on return (CWD will be used as a fallback).
537 * @param anonymity will receive suggested anonymity (or -1 if anonymity can't be suggested)
538 * @return suggested filename relative to download directory (free with GNUNET_free()), or NULL
539 */
634static char * 540static char *
635get_suggested_filename_anonymity2 (GtkTreeModel *tm, 541get_suggested_filename_anonymity2 (GtkTreeModel *tm,
636 GtkTreeIter *iter, 542 GtkTreeIter *iter,
@@ -642,7 +548,7 @@ get_suggested_filename_anonymity2 (GtkTreeModel *tm,
642 char *relname; 548 char *relname;
643 char *filename; 549 char *filename;
644 char *tmp; 550 char *tmp;
645 int downloaded_anonymity; 551 int downloaded_anonymity = -1;
646 struct GNUNET_CONTAINER_MetaData *meta; 552 struct GNUNET_CONTAINER_MetaData *meta;
647 size_t tmplen; 553 size_t tmplen;
648 int finished_chain; 554 int finished_chain;
@@ -697,7 +603,10 @@ get_suggested_filename_anonymity2 (GtkTreeModel *tm,
697 result = GNUNET_strdup (tmp); 603 result = GNUNET_strdup (tmp);
698 } 604 }
699 } 605 }
606 else
607 result = NULL;
700 *download_directory = GNUNET_strdup (downloaddir); 608 *download_directory = GNUNET_strdup (downloaddir);
609 *anonymity = downloaded_anonymity;
701 GNUNET_free (filename); 610 GNUNET_free (filename);
702 g_free (downloaddir); 611 g_free (downloaddir);
703 g_free (relname); 612 g_free (relname);
@@ -705,141 +614,6 @@ get_suggested_filename_anonymity2 (GtkTreeModel *tm,
705} 614}
706 615
707/** 616/**
708 * This function is called when the user double-clicks on a search
709 * result. Begins the download, if necessary by opening the "save as"
710 * window.
711 *
712 * @param tree_view tree view with the details
713 * @param path path selecting which entry we want to download
714 * @param tab the search tab where the user triggered the download request
715 * @param is_recursive was the request for a recursive download?
716 * @param save_as force opening the 'save as' dialog?
717 */
718static void
719start_download (GtkTreeView *tree_view,
720 GtkTreePath *path,
721 struct SearchTab *tab,
722 int is_recursive,
723 int save_as)
724{
725 GtkTreeModel *tm;
726 GtkTreeIter iter;
727 struct GNUNET_FS_Uri *uri;
728 struct GNUNET_CONTAINER_MetaData *meta;
729 struct SearchResult *sr;
730 struct DownloadEntry *de;
731 char *buf = NULL;
732 char *tmp;
733 size_t tmplen;
734 char cwd[FILENAME_MAX];
735 char *download_directory;
736 char *filename;
737 int local_parents;
738 int have_a_suggestion;
739 int anonymity;
740 int filename_is_absolute;
741
742 tm = gtk_tree_view_get_model (tree_view);
743 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
744 {
745 GNUNET_break (0);
746 return;
747 }
748 gtk_tree_model_get (tm, &iter,
749 SEARCH_TAB_MC_METADATA, &meta,
750 SEARCH_TAB_MC_URI, &uri,
751 SEARCH_TAB_MC_SEARCH_RESULT, &sr,
752 -1);
753 if (NULL == uri)
754 {
755 /* user clicked on directory that was opened (not downloaded!), so we
756 have no URI and downloading makes no sense. Ignore! */
757 return;
758 }
759 if (NULL != sr->download)
760 {
761 /* download already active! */
762 return;
763 }
764 if (!(GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))
765 {
766 /* can only download chk/loc URIs, ignore */
767 /* break because in this case, we should not have even gotten here */
768 GNUNET_break (0);
769 return;
770 }
771
772 download_directory = get_default_download_directory (cwd, sizeof (cwd));
773 /* If no download directory is known, try working directory */
774 if (download_directory == NULL)
775 download_directory = getcwd (cwd, sizeof (cwd));
776 /* Calculate suggested filename */
777 local_parents = GNUNET_NO;
778 anonymity = -1;
779 filename_is_absolute = GNUNET_NO;
780 filename = get_suggested_filename_anonymity (tm, &iter, GNUNET_YES,
781 &local_parents, &anonymity,
782 &filename_is_absolute);
783 have_a_suggestion = GNUNET_NO;
784 if (NULL != download_directory)
785 {
786 if (NULL == filename)
787 {
788 buf = GNUNET_strdup (download_directory);
789 }
790 else
791 {
792 have_a_suggestion = GNUNET_YES;
793 if (filename_is_absolute)
794 GNUNET_asprintf (&tmp, "%s", filename);
795 else
796 GNUNET_asprintf (&tmp, "%s%s%s",
797 download_directory,
798 DIR_SEPARATOR_STR,
799 filename);
800 tmplen = strlen (tmp);
801 /* now, if we have a directory, replace trailing '/' with ".gnd" */
802 if (GNUNET_YES ==
803 GNUNET_FS_meta_data_test_for_directory (meta))
804 {
805 if ( (tmp[tmplen-1] == '/') ||
806 (tmp[tmplen-1] == '\\') )
807 tmp[tmplen-1] = '\0';
808 GNUNET_asprintf (&buf,
809 "%s%s",
810 tmp,
811 GNUNET_FS_DIRECTORY_EXT);
812 GNUNET_free (tmp);
813 }
814 else
815 {
816 buf = tmp;
817 }
818 }
819 }
820 GNUNET_free_non_null (filename);
821
822 /* now setup everything for the save-as dialog */
823 de = GNUNET_malloc (sizeof (struct DownloadEntry));
824 de->uri = GNUNET_FS_uri_dup (uri);
825 de->filename = buf;
826 de->sr = sr;
827 sr->download = de;
828 de->anonymity = anonymity;
829 de->is_recursive = is_recursive;
830 de->is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
831 if (save_as)
832 have_a_suggestion = GNUNET_NO;
833 if ( (GNUNET_YES == local_parents) &&
834 (GNUNET_YES == have_a_suggestion) )
835 /* Skip the dialog, call directly */
836 GNUNET_FS_GTK_download_context_start_download (de);
837 else
838 GNUNET_FS_GTK_open_download_as_dialog (de);
839}
840
841
842/**
843 * Context for the search list popup menu. 617 * Context for the search list popup menu.
844 */ 618 */
845struct SearchListPopupContext 619struct SearchListPopupContext
@@ -879,79 +653,6 @@ search_list_popup_selection_done (GtkMenuShell *menushell,
879 GNUNET_free (spc); 653 GNUNET_free (spc);
880} 654}
881 655
882
883/**
884 * This function is called when the user double-clicks on a search
885 * result. Begins the download, if necessary by opening the "save as"
886 * window.
887 *
888 * @param tree_view tree view with the details
889 * @param path path selecting which entry we want to download
890 * @param column unused entry specifying which column the mouse was in
891 * @param user_data the 'struct SearchTab' that was activated
892 */
893void
894GNUNET_FS_GTK_search_treeview_row_activated (GtkTreeView * tree_view,
895 GtkTreePath * path,
896 GtkTreeViewColumn * column,
897 gpointer user_data)
898{
899 struct SearchTab *tab = user_data;
900 struct GNUNET_FS_Uri *uri;
901 GtkTreeModel *tm;
902 GtkTreeIter iter;
903
904 tm = gtk_tree_view_get_model (tree_view);
905 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
906 {
907 GNUNET_break (0);
908 return;
909 }
910 gtk_tree_model_get (tm, &iter,
911 SEARCH_TAB_MC_URI, &uri, -1);
912 if (NULL == uri)
913 {
914 /* user clicked on directory that was opened (not downloaded!), so we
915 have no URI and downloading makes no sense. Ignore! */
916 return;
917 }
918 if (GNUNET_FS_uri_test_ksk (uri) ||
919 GNUNET_FS_uri_test_sks (uri))
920 {
921 GNUNET_FS_GTK_handle_uri (uri, 1);
922 return;
923 }
924 /* must be chk/loc URI, start download */
925 start_download (tree_view, path, tab, GNUNET_NO, GNUNET_NO);
926}
927
928
929/**
930 * "Download" was selected in the current search context menu.
931 *
932 * @param spc the 'struct SearchListPopupContext' of the menu
933 * @param is_recursive was this the 'recursive' option?
934 * @parma save_as was this the 'save as' option?
935 */
936static void
937start_download_ctx_menu_helper (struct SearchListPopupContext *spc,
938 int is_recursive,
939 int save_as)
940{
941 GtkTreePath *path;
942 GtkTreeView *tv;
943
944 path = gtk_tree_row_reference_get_path (spc->rr);
945 tv = GTK_TREE_VIEW (gtk_builder_get_object
946 (spc->tab->builder,
947 "_search_result_frame"));
948 start_download (tv, path, spc->tab,
949 is_recursive,
950 save_as);
951 gtk_tree_path_free (path);
952}
953
954
955/** 656/**
956 * Selected row has changed in search result tree view, update preview 657 * Selected row has changed in search result tree view, update preview
957 * and metadata areas. 658 * and metadata areas.
@@ -964,8 +665,14 @@ GNUNET_FS_GTK_search_treeview_cursor_changed (GtkTreeView *tv,
964 gpointer user_data); 665 gpointer user_data);
965 666
966 667
668/**
669 * save_as - GNUNET_YES to open SaveAs dialog, GNUNET_NO to start downloading.
670 * download_directly - GNUNET_YES to make SaveAs dialog initiate the download,
671 * GNUNET_NO to only change names on the download panel.
672 * Ingored if save_as is GNUNET_NO.
673 */
967static void 674static void
968start_download2 () 675start_download2 (int save_as, int download_directly)
969{ 676{
970 struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context (); 677 struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context ();
971 struct SearchTab *st = GNUNET_FS_GTK_get_current_search_tab (); 678 struct SearchTab *st = GNUNET_FS_GTK_get_current_search_tab ();
@@ -998,6 +705,16 @@ start_download2 ()
998 SEARCH_TAB_MC_SEARCH_RESULT, &sr, 705 SEARCH_TAB_MC_SEARCH_RESULT, &sr,
999 -1); 706 -1);
1000 707
708 if (uri == NULL)
709 return;
710
711 if (GNUNET_FS_uri_test_ksk (uri) ||
712 GNUNET_FS_uri_test_sks (uri))
713 {
714 GNUNET_FS_GTK_handle_uri (uri, 1);
715 return;
716 }
717
1001 if (!((NULL == sr->download) && (NULL != uri) && 718 if (!((NULL == sr->download) && (NULL != uri) &&
1002 ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri))))) 719 ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))))
1003 return; 720 return;
@@ -1031,14 +748,56 @@ start_download2 ()
1031 de->is_recursive = recursive; 748 de->is_recursive = recursive;
1032 de->is_directory = GNUNET_FS_meta_data_test_for_directory (meta); 749 de->is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
1033 750
1034 GNUNET_FS_GTK_download_context_start_download (de); 751 if (save_as == GNUNET_NO)
752 GNUNET_FS_GTK_download_context_start_download (de);
753 else if (download_directly == GNUNET_YES)
754 GNUNET_FS_GTK_open_download_as_dialog (de);
755 else
756 GNUNET_FS_GTK_open_change_download_name_dialog (de);
1035 757
1036 gtk_tree_path_free (path); 758 gtk_tree_path_free (path);
1037 g_free (downloaddir); 759 g_free (downloaddir);
1038 760
1039 if (GNUNET_GTK_tree_model_get_next_flat_iter (model, &iter, !recursive, &next_item)) 761 if (!save_as)
1040 gtk_tree_selection_select_iter (sel, &next_item); 762 {
1041 GNUNET_FS_GTK_search_treeview_cursor_changed (tv, st); 763 if (GNUNET_GTK_tree_model_get_next_flat_iter (model, &iter, !recursive, &next_item))
764 gtk_tree_selection_select_iter (sel, &next_item);
765 GNUNET_FS_GTK_search_treeview_cursor_changed (tv, st);
766 }
767}
768
769/**
770 * "Download" was selected in the current search context menu.
771 *
772 * @param spc the 'struct SearchListPopupContext' of the menu
773 * @param is_recursive was this the 'recursive' option?
774 * @parma save_as was this the 'save as' option?
775 */
776static void
777start_download_ctx_menu_helper (struct SearchListPopupContext *spc,
778 int is_recursive,
779 int save_as)
780{
781 start_download2 (save_as, GNUNET_YES);
782}
783
784/**
785 * This function is called when the user double-clicks on a search
786 * result. Begins the download, if necessary by opening the "save as"
787 * window.
788 *
789 * @param tree_view tree view with the details
790 * @param path path selecting which entry we want to download
791 * @param column unused entry specifying which column the mouse was in
792 * @param user_data the 'struct SearchTab' that was activated
793 */
794void
795GNUNET_FS_GTK_search_treeview_row_activated (GtkTreeView * tree_view,
796 GtkTreePath * path,
797 GtkTreeViewColumn * column,
798 gpointer user_data)
799{
800 start_download2 (GNUNET_NO, GNUNET_NO);
1042} 801}
1043 802
1044 803
@@ -1052,7 +811,21 @@ void
1052GNUNET_GTK_search_frame_download_download_button_clicked_cb ( 811GNUNET_GTK_search_frame_download_download_button_clicked_cb (
1053 GtkButton *button, gpointer user_data) 812 GtkButton *button, gpointer user_data)
1054{ 813{
1055 start_download2 (); 814 start_download2 (GNUNET_NO, GNUNET_NO);
815}
816
817/**
818 * User clicked on "..." button at the download options panel, next
819 * to the Download As entry.
820 *
821 * @param button the "..." button
822 * @param user_data the main window context
823 */
824void
825GNUNET_GTK_search_frame_download_filename_change_button_clicked_cb (
826 GtkButton *button, gpointer user_data)
827{
828 start_download2 (GNUNET_YES, GNUNET_NO);
1056} 829}
1057 830
1058 831
@@ -1093,10 +866,9 @@ start_download_recursively_ctx_menu (GtkMenuItem *item, gpointer user_data)
1093 * @param user_data the 'struct SearchListPopupContext' of the menu 866 * @param user_data the 'struct SearchListPopupContext' of the menu
1094 */ 867 */
1095static void 868static void
1096start_download_as_ctx_menu (GtkMenuItem *item, gpointer user_data) 869download_as_ctx_menu (GtkMenuItem *item, gpointer user_data)
1097{ 870{
1098 struct SearchListPopupContext *spc = user_data; 871 struct SearchListPopupContext *spc = user_data;
1099
1100 start_download_ctx_menu_helper (spc, GNUNET_NO, GNUNET_YES); 872 start_download_ctx_menu_helper (spc, GNUNET_NO, GNUNET_YES);
1101} 873}
1102 874
@@ -1112,9 +884,12 @@ abort_download_ctx_menu (GtkMenuItem *item, gpointer user_data)
1112{ 884{
1113 struct SearchListPopupContext *spc = user_data; 885 struct SearchListPopupContext *spc = user_data;
1114 struct DownloadEntry *de = spc->sr->download; 886 struct DownloadEntry *de = spc->sr->download;
887 GtkTreeView *tv;
1115 888
1116 GNUNET_assert (de->dc != NULL); 889 GNUNET_assert (de->dc != NULL);
1117 GNUNET_FS_download_stop (de->dc, GNUNET_YES); 890 GNUNET_FS_download_stop (de->dc, GNUNET_YES);
891 tv = GTK_TREE_VIEW (gtk_builder_get_object (spc->tab->builder, "_search_result_frame"));
892 GNUNET_FS_GTK_search_treeview_cursor_changed (tv, spc->tab);
1118} 893}
1119 894
1120 895
@@ -1187,6 +962,8 @@ search_list_popup (GtkTreeModel *tm,
1187 struct SearchResult *sr; 962 struct SearchResult *sr;
1188 struct GNUNET_FS_Uri *uri; 963 struct GNUNET_FS_Uri *uri;
1189 struct SearchListPopupContext *spc; 964 struct SearchListPopupContext *spc;
965 struct GNUNET_CONTAINER_MetaData *meta;
966 gboolean is_directory = FALSE;
1190 967
1191 spc = GNUNET_malloc (sizeof (struct SearchListPopupContext)); 968 spc = GNUNET_malloc (sizeof (struct SearchListPopupContext));
1192 spc->tab = tab; 969 spc->tab = tab;
@@ -1195,8 +972,12 @@ search_list_popup (GtkTreeModel *tm,
1195 gtk_tree_path_free (path); 972 gtk_tree_path_free (path);
1196 gtk_tree_model_get (tm, iter, 973 gtk_tree_model_get (tm, iter,
1197 SEARCH_TAB_MC_URI, &uri, 974 SEARCH_TAB_MC_URI, &uri,
975 SEARCH_TAB_MC_METADATA, &meta,
1198 SEARCH_TAB_MC_SEARCH_RESULT, &sr, 976 SEARCH_TAB_MC_SEARCH_RESULT, &sr,
1199 -1); 977 -1);
978 if (meta != NULL)
979 is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
980
1200 spc->sr = sr; 981 spc->sr = sr;
1201 menu = GTK_MENU (gtk_menu_new ()); 982 menu = GTK_MENU (gtk_menu_new ());
1202 if ( (NULL == sr->download) && 983 if ( (NULL == sr->download) &&
@@ -1212,19 +993,22 @@ search_list_popup (GtkTreeModel *tm,
1212 TRUE); 993 TRUE);
1213 gtk_widget_show (child); 994 gtk_widget_show (child);
1214 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child); 995 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
1215 996
1216 child = gtk_menu_item_new_with_label (_("Download _recursively")); 997 if (is_directory)
1217 g_signal_connect (child, "activate", 998 {
1218 G_CALLBACK (start_download_recursively_ctx_menu), spc); 999 child = gtk_menu_item_new_with_label (_("Download _recursively"));
1219 gtk_label_set_use_underline (GTK_LABEL 1000 g_signal_connect (child, "activate",
1220 (gtk_bin_get_child (GTK_BIN (child))), 1001 G_CALLBACK (start_download_recursively_ctx_menu), spc);
1221 TRUE); 1002 gtk_label_set_use_underline (GTK_LABEL
1222 gtk_widget_show (child); 1003 (gtk_bin_get_child (GTK_BIN (child))),
1223 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child); 1004 TRUE);
1005 gtk_widget_show (child);
1006 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
1007 }
1224 1008
1225 child = gtk_menu_item_new_with_label (_("Download _as...")); 1009 child = gtk_menu_item_new_with_label (_("Download _as..."));
1226 g_signal_connect (child, "activate", 1010 g_signal_connect (child, "activate",
1227 G_CALLBACK (start_download_as_ctx_menu), spc); 1011 G_CALLBACK (download_as_ctx_menu), spc);
1228 gtk_label_set_use_underline (GTK_LABEL 1012 gtk_label_set_use_underline (GTK_LABEL
1229 (gtk_bin_get_child (GTK_BIN (child))), 1013 (gtk_bin_get_child (GTK_BIN (child))),
1230 TRUE); 1014 TRUE);
@@ -1773,6 +1557,7 @@ GNUNET_FS_GTK_search_treeview_cursor_changed (GtkTreeView *tv,
1773 GtkTreeIter iter; 1557 GtkTreeIter iter;
1774 struct GNUNET_CONTAINER_MetaData *meta; 1558 struct GNUNET_CONTAINER_MetaData *meta;
1775 GdkPixbuf *pixbuf; 1559 GdkPixbuf *pixbuf;
1560 GtkTreePath *selpath;
1776 struct SearchResult *sr; 1561 struct SearchResult *sr;
1777 struct GNUNET_FS_Uri *uri; 1562 struct GNUNET_FS_Uri *uri;
1778 struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context (); 1563 struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context ();
@@ -1785,6 +1570,9 @@ GNUNET_FS_GTK_search_treeview_cursor_changed (GtkTreeView *tv,
1785 /* nothing selected, clear preview */ 1570 /* nothing selected, clear preview */
1786 gtk_image_clear (mctx->preview_image); 1571 gtk_image_clear (mctx->preview_image);
1787 gtk_widget_hide (GTK_WIDGET (mctx->download_panel)); 1572 gtk_widget_hide (GTK_WIDGET (mctx->download_panel));
1573 if (current_selected_search_result != NULL)
1574 gtk_tree_path_free (current_selected_search_result);
1575 current_selected_search_result = NULL;
1788 return; 1576 return;
1789 } 1577 }
1790 meta = NULL; 1578 meta = NULL;
@@ -1797,38 +1585,48 @@ GNUNET_FS_GTK_search_treeview_cursor_changed (GtkTreeView *tv,
1797 SEARCH_TAB_MC_SEARCH_RESULT, &sr, 1585 SEARCH_TAB_MC_SEARCH_RESULT, &sr,
1798 -1); 1586 -1);
1799 1587
1800 if ((NULL == sr->download) && (NULL != uri) && 1588 selpath = gtk_tree_model_get_path (model, &iter);
1801 ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))) 1589 if (current_selected_search_result == NULL || gtk_tree_path_compare (selpath, current_selected_search_result) != 0)
1802 { 1590 {
1803 char *download_directory; 1591 if ((NULL == sr->download) && (NULL != uri) &&
1804 char *filename; 1592 ((GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri))))
1805 int anonymity; 1593 {
1806 int is_directory; 1594 char *download_directory;
1595 char *filename;
1596 int anonymity;
1597 int is_directory;
1807 1598
1808 /* Calculate suggested filename */ 1599 /* Calculate suggested filename */
1809 anonymity = -1; 1600 anonymity = -1;
1810 download_directory = NULL; 1601 download_directory = NULL;
1811 filename = get_suggested_filename_anonymity2 (model, &iter, 1602 filename = get_suggested_filename_anonymity2 (model, &iter,
1812 &download_directory, &anonymity); 1603 &download_directory, &anonymity);
1813 1604
1814 is_directory = GNUNET_FS_meta_data_test_for_directory (meta); 1605 is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
1815 gtk_widget_set_sensitive (GTK_WIDGET (mctx->download_recursive_checkbutton), is_directory); 1606 gtk_widget_set_sensitive (GTK_WIDGET (mctx->download_recursive_checkbutton), is_directory);
1816 1607
1817 /* TODO: make this configurable */ 1608 /* TODO: make this configurable */
1818 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mctx->download_recursive_checkbutton), is_directory); 1609 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mctx->download_recursive_checkbutton), is_directory);
1819 1610
1820 /* TODO: make this configurable */ 1611 /* TODO: make this configurable */
1821 GNUNET_GTK_select_anonymity_combo_level (mctx->download_anonymity_combo, anonymity >= 0 ? anonymity : 1); 1612 GNUNET_GTK_select_anonymity_combo_level (mctx->download_anonymity_combo, anonymity >= 0 ? anonymity : 1);
1822 1613
1823 gtk_entry_set_text (mctx->download_name_entry, filename != NULL ? filename : NULL); 1614 gtk_entry_set_text (mctx->download_name_entry, filename != NULL ? filename : NULL);
1824 gtk_file_chooser_set_current_folder (mctx->download_location_chooser, download_directory); 1615 gtk_file_chooser_set_current_folder (mctx->download_location_chooser, download_directory);
1825 1616
1826 gtk_widget_show_all (GTK_WIDGET (mctx->download_panel)); 1617 gtk_widget_show_all (GTK_WIDGET (mctx->download_panel));
1827 GNUNET_free (filename); 1618 GNUNET_free_non_null (filename);
1828 GNUNET_free (download_directory); 1619 GNUNET_free (download_directory);
1620 }
1621 else
1622 gtk_widget_hide (GTK_WIDGET (mctx->download_panel));
1623 if (current_selected_search_result != NULL)
1624 gtk_tree_path_free (current_selected_search_result);
1625 current_selected_search_result = selpath;
1829 } 1626 }
1830 else 1627 else
1831 gtk_widget_hide (GTK_WIDGET (mctx->download_panel)); 1628 gtk_tree_path_free (selpath);
1629
1832 1630
1833 if (NULL != pixbuf) 1631 if (NULL != pixbuf)
1834 { 1632 {
@@ -1880,6 +1678,9 @@ GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy,
1880 clear meta data and preview widgets */ 1678 clear meta data and preview widgets */
1881 gtk_image_clear (mctx->preview_image); 1679 gtk_image_clear (mctx->preview_image);
1882 gtk_list_store_clear (mctx->md_liststore); 1680 gtk_list_store_clear (mctx->md_liststore);
1681 if (current_selected_search_result != NULL)
1682 gtk_tree_path_free (current_selected_search_result);
1683 current_selected_search_result = NULL;
1883} 1684}
1884 1685
1885 1686
@@ -2122,7 +1923,6 @@ update_search_result (struct SearchResult *sr,
2122 GNUNET_break (0); 1923 GNUNET_break (0);
2123 return; 1924 return;
2124 } 1925 }
2125 gtk_tree_path_free (tp);
2126 desc = GNUNET_FS_GTK_get_description_from_metadata (meta, &desc_is_a_dup); 1926 desc = GNUNET_FS_GTK_get_description_from_metadata (meta, &desc_is_a_dup);
2127 mime = get_mimetype_from_metadata (meta); 1927 mime = get_mimetype_from_metadata (meta);
2128 pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta); 1928 pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
@@ -2157,10 +1957,20 @@ update_search_result (struct SearchResult *sr,
2157 page = gtk_notebook_get_current_page (mctx->notebook); 1957 page = gtk_notebook_get_current_page (mctx->notebook);
2158 if (gtk_notebook_get_nth_page (mctx->notebook, page) == sr->tab->frame) 1958 if (gtk_notebook_get_nth_page (mctx->notebook, page) == sr->tab->frame)
2159 { 1959 {
2160 tv = GTK_TREE_VIEW (gtk_builder_get_object 1960 GtkTreeSelection *sel;
2161 (sr->tab->builder, "_search_result_frame")); 1961 GtkTreeModel *model;
2162 GNUNET_FS_GTK_search_treeview_cursor_changed (tv, sr->tab); 1962 GtkTreeIter iter;
1963 tv = GTK_TREE_VIEW (gtk_builder_get_object (sr->tab->builder, "_search_result_frame"));
1964 sel = gtk_tree_view_get_selection (tv);
1965 if (gtk_tree_selection_get_selected (sel, &model, &iter))
1966 {
1967 GtkTreePath *selpath = gtk_tree_model_get_path (model, &iter);
1968 if (gtk_tree_path_compare (selpath, tp) == 0)
1969 GNUNET_FS_GTK_search_treeview_cursor_changed (tv, sr->tab);
1970 gtk_tree_path_free (selpath);
1971 }
2163 } 1972 }
1973 gtk_tree_path_free (tp);
2164} 1974}
2165 1975
2166 1976
@@ -2313,6 +2123,85 @@ GNUNET_GTK_add_search_result (struct SearchTab *tab,
2313 2123
2314 2124
2315/** 2125/**
2126 * Sets downloaded name on an item referenced by @rr
2127 * in a tree store @ts to @filename.
2128 * Used by SaveAs dialog to communicate back new filename
2129 * (unless SaveAs dialog initiates the download by itself).
2130 * Arguments can be taken from DownloadEntry.
2131 *
2132 * @param ts treestore
2133 * @param rr row reference
2134 * @param filename new filename
2135 */
2136void
2137GNUNET_FS_GTK_set_item_downloaded_name (GtkTreeStore *ts, GtkTreeRowReference *rr, gchar *filename)
2138{
2139 struct GNUNET_GTK_MainWindowContext *mctx = GNUNET_FS_GTK_get_main_context ();
2140 GtkTreeIter iter;
2141 GtkTreePath *path;
2142
2143 path = gtk_tree_row_reference_get_path (rr);
2144 if (path)
2145 {
2146 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &iter, path))
2147 {
2148 /* TODO: maybe create a new store slot for user-defined filenames?
2149 * Also - maybe separate slots for downloaddir and relative filename?
2150 */
2151 /* This code relies on download panel contents being re-populated every 0.2 seconds,
2152 * thus it updates the treestore item property, from which suggested filename
2153 * is derived.
2154 */
2155 /*
2156 char *download_directory;
2157 char *suggested_filename;
2158 int anonymity = -1;
2159
2160 gtk_tree_store_set (ts, &iter, SEARCH_TAB_MC_DOWNLOADED_FILENAME, filename, -1);
2161
2162 download_directory = NULL;
2163 suggested_filename = get_suggested_filename_anonymity2 (GTK_TREE_MODEL (ts), &iter,
2164 &download_directory, &anonymity);
2165
2166 gtk_entry_set_text (mctx->download_name_entry, suggested_filename != NULL ? suggested_filename : NULL);
2167 gtk_file_chooser_set_current_folder (mctx->download_location_chooser, download_directory);
2168
2169 GNUNET_free_non_null (suggested_filename);
2170 GNUNET_free (download_directory);
2171 */
2172 /* This code relies on download panel contents NOT being re-populated every 0.2 seconds,
2173 * thus it only updates download panel contents - these changes will be lost after
2174 * selecting a different item and then coming back to this one.
2175 */
2176 gchar *current = g_strdup (filename);
2177 gchar *dirname = NULL;
2178 /* We take the filename user gave us, then check its parent directories until
2179 * we find one that actually exists (SaveAs dialog might have some options about
2180 * only picking existing names, but better be safe.
2181 * gtk_file_chooser_set_current_folder() does NOT work with non-existing dirnames!
2182 */
2183 do
2184 {
2185 dirname = g_path_get_dirname (current);
2186 g_free (current);
2187 if (g_file_test (dirname, G_FILE_TEST_EXISTS))
2188 {
2189 gchar *relname = &filename[strlen (dirname)];
2190 while (relname[0] == '/' || relname[0] == '\\')
2191 relname++;
2192 gtk_entry_set_text (mctx->download_name_entry, relname);
2193 gtk_file_chooser_set_current_folder (mctx->download_location_chooser, dirname);
2194 break;
2195 }
2196 current = dirname;
2197 } while (dirname[0] != '.'); /* FIXME: Check that this condition is correct */
2198 g_free (dirname);
2199 }
2200 gtk_tree_path_free (path);
2201 }
2202}
2203
2204/**
2316 * We have received a search result from the FS API. Add it to the 2205 * We have received a search result from the FS API. Add it to the
2317 * respective search tab. The search result can be an 'inner' 2206 * respective search tab. The search result can be an 'inner'
2318 * search result (updated result for a namespace search) or a 2207 * search result (updated result for a namespace search) or a
diff --git a/src/fs/gnunet-fs-gtk_event-handler.h b/src/fs/gnunet-fs-gtk_event-handler.h
index 472ae731..a7247c80 100644
--- a/src/fs/gnunet-fs-gtk_event-handler.h
+++ b/src/fs/gnunet-fs-gtk_event-handler.h
@@ -176,7 +176,6 @@ struct DownloadEntry
176 * Has the download completed (or failed)? 176 * Has the download completed (or failed)?
177 */ 177 */
178 int is_done; 178 int is_done;
179
180}; 179};
181 180
182 181
@@ -249,6 +248,9 @@ GNUNET_GTK_add_search_result (struct SearchTab *tab,
249 uint32_t applicability_rank); 248 uint32_t applicability_rank);
250 249
251 250
251void
252GNUNET_FS_GTK_set_item_downloaded_name (GtkTreeStore *ts, GtkTreeRowReference *rr, gchar *filename);
253
252/** 254/**
253 * Notification of FS to a client about the progress of an 255 * Notification of FS to a client about the progress of an
254 * operation. Callbacks of this type will be used for uploads, 256 * operation. Callbacks of this type will be used for uploads,