diff options
Diffstat (limited to 'src/fs/gnunet-fs-gtk-event_handler.c')
-rw-r--r-- | src/fs/gnunet-fs-gtk-event_handler.c | 218 |
1 files changed, 201 insertions, 17 deletions
diff --git a/src/fs/gnunet-fs-gtk-event_handler.c b/src/fs/gnunet-fs-gtk-event_handler.c index aa870b0c..32852aef 100644 --- a/src/fs/gnunet-fs-gtk-event_handler.c +++ b/src/fs/gnunet-fs-gtk-event_handler.c | |||
@@ -596,6 +596,8 @@ move_children (GtkTreeModel * src_model, GtkTreeIter * src_iter, | |||
596 | guint applicability_rank; | 596 | guint applicability_rank; |
597 | guint availability_certainty; | 597 | guint availability_certainty; |
598 | gint availability_rank; | 598 | gint availability_rank; |
599 | gchar *downloaded_filename; | ||
600 | gint downloaded_anonymity; | ||
599 | 601 | ||
600 | if (TRUE == gtk_tree_model_iter_children (src_model, &src_child, src_iter)) | 602 | if (TRUE == gtk_tree_model_iter_children (src_model, &src_child, src_iter)) |
601 | { | 603 | { |
@@ -607,7 +609,8 @@ move_children (GtkTreeModel * src_model, GtkTreeIter * src_iter, | |||
607 | &uri_as_string, 8, &status_colour, 9, &search_result, | 609 | &uri_as_string, 8, &status_colour, 9, &search_result, |
608 | 10, &mimetype, 11, &applicability_rank, 12, | 610 | 10, &mimetype, 11, &applicability_rank, 12, |
609 | &availability_certainty, 13, &availability_rank, 14, | 611 | &availability_certainty, 13, &availability_rank, 14, |
610 | &completed, -1); | 612 | &completed, 15, &downloaded_filename, 16, |
613 | &downloaded_anonymity, -1); | ||
611 | gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model), &dst_child, | 614 | gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model), &dst_child, |
612 | dst_iter, G_MAXINT, 0, meta, 1, uri, 2, | 615 | dst_iter, G_MAXINT, 0, meta, 1, uri, 2, |
613 | filesize, 3, preview, 4, | 616 | filesize, 3, preview, 4, |
@@ -617,8 +620,11 @@ move_children (GtkTreeModel * src_model, GtkTreeIter * src_iter, | |||
617 | search_result, 10, mimetype, 11, | 620 | search_result, 10, mimetype, 11, |
618 | applicability_rank, 12, | 621 | applicability_rank, 12, |
619 | availability_certainty, 13, | 622 | availability_certainty, 13, |
620 | availability_rank, 14, completed, -1); | 623 | availability_rank, 14, completed, 15, |
624 | downloaded_filename, 16, | ||
625 | downloaded_anonymity, -1); | ||
621 | g_free (filename); | 626 | g_free (filename); |
627 | g_free (downloaded_filename); | ||
622 | g_free (uri_as_string); | 628 | g_free (uri_as_string); |
623 | g_free (status_colour); | 629 | g_free (status_colour); |
624 | g_free (mimetype); | 630 | g_free (mimetype); |
@@ -807,6 +813,164 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde, | |||
807 | return de; | 813 | return de; |
808 | } | 814 | } |
809 | 815 | ||
816 | /** | ||
817 | * This should get the default download directory | ||
818 | * (so that GNUnet won't offer the user to download files | ||
819 | * to the 'bin' subdirectory, or whatever is the cwd). | ||
820 | * Returns NULL on failure (such as non-existend directory). | ||
821 | * Should also preserve the last setting (so if the user | ||
822 | * saves files somewhere else, next time we default to | ||
823 | * somewhere else, at least until application restart, or maybe even | ||
824 | * between application restarts). | ||
825 | * Fills the @buffer up to @size bytes, returns a pointer to it. | ||
826 | */ | ||
827 | static char * | ||
828 | get_default_download_directory (char *buffer, size_t size) | ||
829 | { | ||
830 | return NULL; | ||
831 | } | ||
832 | |||
833 | /** | ||
834 | * Called recursively to build a suggested filename by | ||
835 | * prepending suggested names for its parent directories (if any). | ||
836 | * Might return NULL. Returned name might be absolute. | ||
837 | * local_parents is set to GNUNET_YES if all parents are directories, | ||
838 | * and are downloaded. | ||
839 | */ | ||
840 | static char * | ||
841 | get_suggested_filename_anonymity (GtkTreeModel *tm, GtkTreeIter *iter, int top, | ||
842 | int *local_parents, int *anonymity, int *filename_is_absolute) | ||
843 | { | ||
844 | char *result; | ||
845 | char *dirname; | ||
846 | char *local_filename, *filename; | ||
847 | int downloaded_anonymity; | ||
848 | int have_a_parent; | ||
849 | struct GNUNET_CONTAINER_MetaData *meta; | ||
850 | GtkTreeIter parent; | ||
851 | gtk_tree_model_get (tm, iter, 0, &meta, 15, &local_filename, 16, &downloaded_anonymity, -1); | ||
852 | if (local_filename == NULL && !top) | ||
853 | *local_parents = GNUNET_NO; | ||
854 | if (downloaded_anonymity != -1 && *anonymity == -1 && !top) | ||
855 | *anonymity = downloaded_anonymity; | ||
856 | if (gtk_tree_model_iter_parent (tm, &parent, iter)) | ||
857 | { | ||
858 | have_a_parent = GNUNET_YES; | ||
859 | dirname = get_suggested_filename_anonymity (tm, &parent, GNUNET_NO, local_parents, anonymity, filename_is_absolute); | ||
860 | } | ||
861 | else | ||
862 | { | ||
863 | have_a_parent = GNUNET_NO; | ||
864 | dirname = NULL; | ||
865 | if (top) | ||
866 | *local_parents = GNUNET_NO; | ||
867 | } | ||
868 | if (local_filename == NULL) | ||
869 | filename = GNUNET_FS_meta_data_suggest_filename (meta); | ||
870 | else | ||
871 | { | ||
872 | /* This directory was downloaded as /foo/bar/baz/somedirname | ||
873 | * Hopefully, "somedirname" is actually "somedir.gnd" | ||
874 | * We need to strip the ".gnd" part to get "somedir", which is | ||
875 | * what we're going to use instead of suggested original filename | ||
876 | * Without the .gnd extension we're going to just use a copy | ||
877 | * of the directory file name - and that would fail. Sad. | ||
878 | */ | ||
879 | const char *basename; | ||
880 | if (dirname == NULL && !have_a_parent) | ||
881 | { | ||
882 | /* This is the ealderlest parent directory. Use absolute path. */ | ||
883 | basename = (const char *) local_filename; | ||
884 | *filename_is_absolute = GNUNET_YES; | ||
885 | } | ||
886 | else | ||
887 | basename = GNUNET_STRINGS_get_short_name (local_filename); | ||
888 | if (basename != NULL && strlen (basename) > 0) | ||
889 | { | ||
890 | char *dot; | ||
891 | filename = GNUNET_strdup (basename); | ||
892 | dot = strrchr (filename, '.'); | ||
893 | if (dot) | ||
894 | *dot = '\0'; | ||
895 | } | ||
896 | else | ||
897 | filename = GNUNET_FS_meta_data_suggest_filename (meta); | ||
898 | } | ||
899 | if (dirname && filename) | ||
900 | { | ||
901 | GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename); | ||
902 | GNUNET_free (filename); | ||
903 | GNUNET_free (dirname); | ||
904 | return result; | ||
905 | } | ||
906 | else if (filename) | ||
907 | return filename; | ||
908 | else | ||
909 | return NULL; | ||
910 | } | ||
911 | |||
912 | static void | ||
913 | open_download_as_callback (struct DownloadContext *dc) | ||
914 | { | ||
915 | enum GNUNET_FS_DownloadOptions opt; | ||
916 | struct GNUNET_FS_Handle *fs; | ||
917 | struct DownloadEntry *de; | ||
918 | uint64_t len; | ||
919 | |||
920 | GtkTreeIter iter; | ||
921 | GtkTreePath *path; | ||
922 | |||
923 | fs = GNUNET_FS_GTK_get_fs_handle (); | ||
924 | opt = GNUNET_FS_DOWNLOAD_OPTION_NONE; | ||
925 | if (dc->is_recursive) | ||
926 | opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE; | ||
927 | len = GNUNET_FS_uri_chk_get_file_size (dc->uri); | ||
928 | |||
929 | de = GNUNET_malloc (sizeof (struct DownloadEntry)); | ||
930 | de->uri = dc->uri; | ||
931 | dc->uri = NULL; | ||
932 | de->meta = dc->meta; | ||
933 | dc->meta = NULL; | ||
934 | if (dc->rr != NULL) | ||
935 | { | ||
936 | /* We're going to free "dc" very soon */ | ||
937 | de->rr = gtk_tree_row_reference_copy (dc->rr); | ||
938 | de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr)); | ||
939 | |||
940 | path = gtk_tree_row_reference_get_path (de->rr); | ||
941 | GNUNET_assert (NULL != path); | ||
942 | if (gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) | ||
943 | { | ||
944 | /* Store filename and anonymity as specified by the user. | ||
945 | * These will be re-used when this is a directory, and the user | ||
946 | * downloads its children. | ||
947 | */ | ||
948 | gtk_tree_store_set (de->ts, &iter, 15, dc->filename, 16, dc->anonymity, -1); | ||
949 | } | ||
950 | gtk_tree_path_free (path); | ||
951 | |||
952 | } | ||
953 | if (dc->sr != NULL) | ||
954 | { | ||
955 | GNUNET_break (NULL != | ||
956 | GNUNET_FS_download_start_from_search (fs, dc->sr, | ||
957 | dc->filename, | ||
958 | NULL /* tempname */ , | ||
959 | 0 /* offset */ , | ||
960 | len, dc->anonymity, opt, | ||
961 | de)); | ||
962 | } | ||
963 | else | ||
964 | { | ||
965 | GNUNET_break (NULL != | ||
966 | GNUNET_FS_download_start (fs, de->uri, NULL /* meta */ , | ||
967 | dc->filename, NULL /* tempname */ , | ||
968 | 0 /* offset */ , | ||
969 | len, dc->anonymity, opt, de, | ||
970 | NULL /* parent download ctx */ )); | ||
971 | } | ||
972 | GNUNET_GTK_save_as_dialog_free_download_context (dc); | ||
973 | } | ||
810 | 974 | ||
811 | /** | 975 | /** |
812 | * Tell FS to start a download. Begins by opening the | 976 | * Tell FS to start a download. Begins by opening the |
@@ -825,11 +989,16 @@ start_download (GtkTreeView * tree_view, GtkTreePath * path, | |||
825 | struct SearchResult *sr; | 989 | struct SearchResult *sr; |
826 | gchar *mime; | 990 | gchar *mime; |
827 | struct DownloadContext *dc; | 991 | struct DownloadContext *dc; |
828 | char *buf; | 992 | char *buf = NULL; |
829 | char *tmp; | 993 | char *tmp; |
830 | size_t tmplen; | 994 | size_t tmplen; |
831 | char cwd[FILENAME_MAX]; | 995 | char cwd[FILENAME_MAX]; |
996 | char *download_directory; | ||
832 | char *filename; | 997 | char *filename; |
998 | int local_parents; | ||
999 | int have_a_suggestion; | ||
1000 | int anonymity; | ||
1001 | int filename_is_absolute; | ||
833 | 1002 | ||
834 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1003 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
835 | "Starting a %sdownload\n", sdc->recursive ? "recursive " : ""); | 1004 | "Starting a %sdownload\n", sdc->recursive ? "recursive " : ""); |
@@ -858,24 +1027,32 @@ start_download (GtkTreeView * tree_view, GtkTreePath * path, | |||
858 | return; | 1027 | return; |
859 | } | 1028 | } |
860 | 1029 | ||
861 | 1030 | download_directory = get_default_download_directory (cwd, sizeof (cwd)); | |
862 | /* FIXME: we should check if this download is a file in some directory | 1031 | /* If no download directory is known, try working directory */ |
863 | (gtk_tree_model_iter_get_parent) and if so obtain the name under which | 1032 | if (download_directory == NULL) |
864 | the directory was stored! */ | 1033 | download_directory = getcwd (cwd, sizeof (cwd)); |
865 | /* Calculate suggested filename; first, pre-pend current working directory */ | 1034 | /* Calculate suggested filename */ |
866 | filename = GNUNET_FS_meta_data_suggest_filename (meta); | 1035 | local_parents = GNUNET_YES; |
867 | if (NULL != getcwd (cwd, sizeof (cwd))) | 1036 | anonymity = -1; |
1037 | filename_is_absolute = GNUNET_NO; | ||
1038 | filename = get_suggested_filename_anonymity (tm, &iter, GNUNET_YES, &local_parents, &anonymity, &filename_is_absolute); | ||
1039 | have_a_suggestion = GNUNET_NO; | ||
1040 | if (NULL != download_directory) | ||
868 | { | 1041 | { |
869 | if (NULL == filename) | 1042 | if (NULL == filename) |
870 | { | 1043 | { |
871 | buf = GNUNET_strdup (cwd); | 1044 | buf = GNUNET_strdup (download_directory); |
872 | } | 1045 | } |
873 | else | 1046 | else |
874 | { | 1047 | { |
875 | GNUNET_asprintf (&tmp, "%s%s%s", | 1048 | have_a_suggestion = GNUNET_YES; |
876 | cwd, | 1049 | if (filename_is_absolute) |
877 | DIR_SEPARATOR_STR, | 1050 | GNUNET_asprintf (&tmp, "%s", filename); |
878 | filename); | 1051 | else |
1052 | GNUNET_asprintf (&tmp, "%s%s%s", | ||
1053 | download_directory, | ||
1054 | DIR_SEPARATOR_STR, | ||
1055 | filename); | ||
879 | tmplen = strlen (tmp); | 1056 | tmplen = strlen (tmp); |
880 | /* now, if we have a directory, replace trailing '/' with ".gnd" */ | 1057 | /* now, if we have a directory, replace trailing '/' with ".gnd" */ |
881 | if (GNUNET_YES == | 1058 | if (GNUNET_YES == |
@@ -906,10 +1083,15 @@ start_download (GtkTreeView * tree_view, GtkTreePath * path, | |||
906 | dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); | 1083 | dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); |
907 | dc->rr = gtk_tree_row_reference_new (tm, path); | 1084 | dc->rr = gtk_tree_row_reference_new (tm, path); |
908 | dc->sr = sr->result; | 1085 | dc->sr = sr->result; |
909 | dc->anonymity = -1; | 1086 | dc->anonymity = anonymity; |
910 | dc->is_recursive = sdc->recursive; | 1087 | dc->is_recursive = sdc->recursive; |
911 | dc->tab = tab; | 1088 | dc->tab = tab; |
912 | GNUNET_FS_GTK_open_download_as_dialog (dc); | 1089 | dc->cb = &open_download_as_callback; |
1090 | if (local_parents && have_a_suggestion) | ||
1091 | /* Skip the dialog, call directly */ | ||
1092 | open_download_as_callback (dc); | ||
1093 | else | ||
1094 | GNUNET_FS_GTK_open_download_as_dialog (dc); | ||
913 | } | 1095 | } |
914 | 1096 | ||
915 | 1097 | ||
@@ -1608,6 +1790,8 @@ GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter, | |||
1608 | 0 /* avail-cert */ , | 1790 | 0 /* avail-cert */ , |
1609 | 13, 0, /* avail-rank */ | 1791 | 13, 0, /* avail-rank */ |
1610 | 14, (guint64) 0, /* completed */ | 1792 | 14, (guint64) 0, /* completed */ |
1793 | 15, NULL, /* downloaded_filename */ | ||
1794 | 16, -1, /* downloaded_anonymity */ | ||
1611 | -1); | 1795 | -1); |
1612 | if (tab != NULL) | 1796 | if (tab != NULL) |
1613 | { | 1797 | { |