diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-02-01 11:50:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-02-01 11:50:19 +0000 |
commit | 937f070851bad5d125f70959cbbbd5fad939590d (patch) | |
tree | 0b910ec4da27642f3c4f75559a6e28b660c9d627 | |
parent | e5a7fa50c8813dedd8130d0ae58d9d4a83660a6f (diff) | |
download | gnunet-gtk-937f070851bad5d125f70959cbbbd5fad939590d.tar.gz gnunet-gtk-937f070851bad5d125f70959cbbbd5fad939590d.zip |
-more code cleanup, simplifications, bugfixes, etc.
-rw-r--r-- | src/fs/gnunet-fs-gtk-event_handler.c | 1840 | ||||
-rw-r--r-- | src/fs/gnunet-fs-gtk-event_handler.h | 58 |
2 files changed, 1046 insertions, 852 deletions
diff --git a/src/fs/gnunet-fs-gtk-event_handler.c b/src/fs/gnunet-fs-gtk-event_handler.c index 3b4dc667..78fc5cef 100644 --- a/src/fs/gnunet-fs-gtk-event_handler.c +++ b/src/fs/gnunet-fs-gtk-event_handler.c | |||
@@ -89,9 +89,10 @@ struct PublishEntry | |||
89 | 89 | ||
90 | 90 | ||
91 | /** | 91 | /** |
92 | * Information we keep for each search result. Used to quickly | 92 | * Information we keep for each search result entry in any search tab. |
93 | * identify the tab and row of the result; stored in the user-context | 93 | * An entry like this is also generated for downloads by-URI. Used to |
94 | * of the FS library for the search result. | 94 | * quickly identify the tab and row of the result; stored in the |
95 | * user-context of the FS library for the search result. | ||
95 | */ | 96 | */ |
96 | struct SearchResult | 97 | struct SearchResult |
97 | { | 98 | { |
@@ -154,6 +155,8 @@ static struct SearchTab *current_context_search_tab; | |||
154 | 155 | ||
155 | 156 | ||
156 | 157 | ||
158 | /* ***************** Search event handling ****************** */ | ||
159 | |||
157 | /** | 160 | /** |
158 | * This should get the default download directory (so that GNUnet | 161 | * This should get the default download directory (so that GNUnet |
159 | * won't offer the user to download files to the 'bin' subdirectory, | 162 | * won't offer the user to download files to the 'bin' subdirectory, |
@@ -735,92 +738,932 @@ search_list_on_menu (GtkWidget * widget, | |||
735 | } | 738 | } |
736 | 739 | ||
737 | 740 | ||
741 | /** | ||
742 | * Recalculate and update the label for a search, as we have | ||
743 | * received additional search results. | ||
744 | * | ||
745 | * @param tab search tab for which we should update the label | ||
746 | */ | ||
747 | static void | ||
748 | update_search_label (struct SearchTab *tab) | ||
749 | { | ||
750 | char *label_text; | ||
738 | 751 | ||
752 | while (tab->parent != NULL) | ||
753 | tab = tab->parent->tab; | ||
754 | if (tab->num_results > 0) | ||
755 | GNUNET_asprintf (&label_text, "%.*s%s (%u)", 20, tab->query_txt, | ||
756 | strlen (tab->query_txt) > 20 ? "..." : "", | ||
757 | tab->num_results); | ||
758 | else | ||
759 | GNUNET_asprintf (&label_text, "%.*s%s", 20, tab->query_txt, | ||
760 | strlen (tab->query_txt) > 20 ? "..." : ""); | ||
761 | gtk_label_set_text (tab->label, label_text); | ||
762 | gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), tab->query_txt); | ||
763 | GNUNET_free (label_text); | ||
764 | } | ||
739 | 765 | ||
740 | 766 | ||
741 | /* FIXME: go over code from here on and document & clean up... */ | 767 | /** |
768 | * Close a search tab and free associated state. Assumes that the | ||
769 | * respective tree model has already been cleaned up (this just | ||
770 | * updates the notebook and frees the 'tab' itself). | ||
771 | * | ||
772 | * @param tab search tab to close | ||
773 | */ | ||
774 | static void | ||
775 | close_search_tab (struct SearchTab *tab) | ||
776 | { | ||
777 | GtkNotebook *notebook; | ||
778 | int index; | ||
779 | int i; | ||
742 | 780 | ||
781 | if (tab->parent != NULL) | ||
782 | { | ||
783 | /* not a top-level search (namespace update search), do not close | ||
784 | tab here! */ | ||
785 | GNUNET_free (tab); | ||
786 | return; | ||
787 | } | ||
788 | notebook = | ||
789 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
790 | ("GNUNET_GTK_main_window_notebook")); | ||
791 | index = -1; | ||
792 | for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--) | ||
793 | if (tab->frame == gtk_notebook_get_nth_page (notebook, i)) | ||
794 | index = i; | ||
795 | gtk_notebook_remove_page (notebook, index); | ||
796 | g_object_unref (tab->builder); | ||
797 | GNUNET_free (tab->query_txt); | ||
798 | GNUNET_CONTAINER_DLL_remove (search_tab_head, search_tab_tail, tab); | ||
799 | if (tab == uri_tab) | ||
800 | uri_tab = NULL; | ||
801 | GNUNET_free (tab); | ||
802 | } | ||
743 | 803 | ||
744 | 804 | ||
805 | /** | ||
806 | * Free a particular search result and remove the respective | ||
807 | * entries from the respective tree store. This function | ||
808 | * is called when a search is stopped to clean up the state | ||
809 | * of the tab. | ||
810 | * | ||
811 | * @param sr the search result to clean up | ||
812 | */ | ||
813 | static void | ||
814 | free_search_result (struct SearchResult *sr) | ||
815 | { | ||
816 | GtkTreePath *tp; | ||
817 | GtkTreeModel *tm; | ||
818 | GtkTreeIter iter; | ||
819 | struct GNUNET_FS_Uri *uri; | ||
820 | struct GNUNET_CONTAINER_MetaData *meta; | ||
745 | 821 | ||
822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
823 | "Freeing a search result SR=%p\n", | ||
824 | sr); | ||
825 | if ( (NULL == sr) || | ||
826 | (NULL == sr->rr) || | ||
827 | (NULL == (tm = gtk_tree_row_reference_get_model (sr->rr))) || | ||
828 | (NULL == (tp = gtk_tree_row_reference_get_path (sr->rr))) ) | ||
829 | { | ||
830 | GNUNET_break (0); | ||
831 | return; | ||
832 | } | ||
833 | if (! gtk_tree_model_get_iter (tm, &iter, tp)) | ||
834 | { | ||
835 | GNUNET_break (0); | ||
836 | gtk_tree_path_free (tp); | ||
837 | return; | ||
838 | } | ||
839 | gtk_tree_path_free (tp); | ||
840 | gtk_tree_model_get (tm, &iter, 0, &meta, 1, &uri, -1); | ||
841 | if (uri != NULL) | ||
842 | GNUNET_FS_uri_destroy (uri); | ||
843 | if (meta != NULL) | ||
844 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
845 | gtk_tree_row_reference_free (sr->rr); | ||
846 | (void) gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter); | ||
847 | GNUNET_free (sr); | ||
848 | } | ||
746 | 849 | ||
747 | 850 | ||
748 | static struct DownloadEntry * | 851 | /** |
749 | change_download_colour (struct DownloadEntry *de, | 852 | * Selected row has changed in search result tree view, update preview |
750 | const char *colour) | 853 | * and metadata areas. |
854 | * | ||
855 | * @param tv the tree view in a search tab where the selection changed | ||
856 | * @param user_data the 'struct SearchTab' that contains the tree view | ||
857 | */ | ||
858 | static void | ||
859 | update_meta_data_views (GtkTreeView *tv, gpointer user_data) | ||
751 | { | 860 | { |
861 | struct SearchTab *tab = user_data; | ||
862 | GtkImage *image; | ||
863 | GtkListStore *ms; | ||
864 | GtkTreeSelection *sel; | ||
865 | GtkTreeModel *model; | ||
752 | GtkTreeIter iter; | 866 | GtkTreeIter iter; |
753 | GtkTreePath *path; | 867 | struct GNUNET_CONTAINER_MetaData *meta; |
868 | GdkPixbuf *pixbuf; | ||
754 | 869 | ||
755 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changing download DE=%p color to %s\n", de, colour); | 870 | GNUNET_assert (tab->query_txt != NULL); |
756 | path = gtk_tree_row_reference_get_path (de->rr); | 871 | image = |
757 | GNUNET_assert (NULL != path); | 872 | GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object |
758 | if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) | 873 | ("GNUNET_GTK_main_window_preview_image")); |
874 | ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object | ||
875 | ("GNUNET_GTK_meta_data_list_store")); | ||
876 | sel = gtk_tree_view_get_selection (tv); | ||
877 | gtk_list_store_clear (ms); | ||
878 | if (! gtk_tree_selection_get_selected (sel, &model, &iter)) | ||
879 | { | ||
880 | /* nothing selected, clear preview */ | ||
881 | gtk_image_clear (image); | ||
882 | return; | ||
883 | } | ||
884 | meta = NULL; | ||
885 | pixbuf = NULL; | ||
886 | gtk_tree_model_get (model, &iter, 0, &meta, 3, &pixbuf, -1); | ||
887 | if (NULL != pixbuf) | ||
888 | { | ||
889 | gtk_image_set_from_pixbuf (image, pixbuf); | ||
890 | g_object_unref (G_OBJECT (pixbuf)); | ||
891 | } | ||
892 | if (NULL != meta) | ||
893 | GNUNET_CONTAINER_meta_data_iterate (meta, | ||
894 | &GNUNET_FS_GTK_add_meta_data_to_list_store, | ||
895 | ms); | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Page switched in main notebook, update thumbnail and | ||
901 | * metadata views. | ||
902 | * | ||
903 | * @param dummy widget emitting the event, unused | ||
904 | * @param data master Gtk builder, unused | ||
905 | */ | ||
906 | void | ||
907 | GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy, | ||
908 | gpointer data) | ||
909 | { | ||
910 | GtkNotebook *notebook; | ||
911 | gint page; | ||
912 | GtkWidget *w; | ||
913 | struct SearchTab *tab; | ||
914 | GtkImage *image; | ||
915 | GtkListStore *ms; | ||
916 | GtkTreeView *tv; | ||
917 | |||
918 | notebook = | ||
919 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
920 | ("GNUNET_GTK_main_window_notebook")); | ||
921 | page = gtk_notebook_get_current_page (notebook); | ||
922 | w = gtk_notebook_get_nth_page (notebook, page); | ||
923 | for (tab = search_tab_head; NULL != tab; tab = tab->next) | ||
924 | { | ||
925 | if (tab->frame != w) | ||
926 | continue; | ||
927 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
928 | (tab->builder, "_search_result_frame")); | ||
929 | update_meta_data_views (tv, tab); | ||
930 | return; | ||
931 | } | ||
932 | /* active tab is not a search tab (likely the 'publish' tab), | ||
933 | clear meta data and preview widgets */ | ||
934 | image = | ||
935 | GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object | ||
936 | ("GNUNET_GTK_main_window_preview_image")); | ||
937 | gtk_image_clear (image); | ||
938 | ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object | ||
939 | ("GNUNET_GTK_meta_data_list_store")); | ||
940 | gtk_list_store_clear (ms); | ||
941 | } | ||
942 | |||
943 | |||
944 | /** | ||
945 | * User clicked on the 'close' button for a search tab. Tell FS to stop the search. | ||
946 | * | ||
947 | * @param button the 'close' button | ||
948 | * @param user_data the 'struct SearchTab' of the tab to close | ||
949 | */ | ||
950 | static void | ||
951 | stop_search (GtkButton *button, gpointer user_data) | ||
952 | { | ||
953 | struct SearchTab *tab = user_data; | ||
954 | struct GNUNET_FS_SearchContext *sc; | ||
955 | |||
956 | sc = tab->sc; | ||
957 | if (NULL == sc) | ||
759 | { | 958 | { |
760 | GNUNET_break (0); | 959 | GNUNET_break (0); |
761 | gtk_tree_path_free (path); | 960 | return; |
762 | return de; | ||
763 | } | 961 | } |
764 | gtk_tree_path_free (path); | 962 | tab->sc = NULL; |
765 | gtk_tree_store_set (de->ts, &iter, 8, colour, -1); | 963 | GNUNET_FS_search_stop (sc); |
766 | return de; | 964 | gtk_widget_hide (GTK_WIDGET (button)); |
965 | gtk_widget_hide (tab->pause_button); | ||
966 | gtk_widget_hide (tab->play_button); | ||
767 | } | 967 | } |
768 | 968 | ||
769 | 969 | ||
770 | static struct PublishEntry * | 970 | /** |
771 | change_publish_colour (struct PublishEntry *pe, const char *colour) | 971 | * The user clicked on the 'pause' button for a search tab. Tell FS to pause the search. |
972 | * | ||
973 | * @param button the 'pause' button | ||
974 | * @param user_data the 'struct SearchTab' of the tab to pause | ||
975 | */ | ||
976 | static void | ||
977 | pause_search (GtkButton *button, gpointer user_data) | ||
978 | { | ||
979 | struct SearchTab *tab = user_data; | ||
980 | |||
981 | if (NULL == tab->sc) | ||
982 | { | ||
983 | GNUNET_break (0); | ||
984 | return; | ||
985 | } | ||
986 | GNUNET_FS_search_pause (tab->sc); | ||
987 | gtk_widget_show (tab->play_button); | ||
988 | gtk_widget_hide (tab->pause_button); | ||
989 | } | ||
990 | |||
991 | |||
992 | /** | ||
993 | * The user clicked on the 'resume' button for a search tab. Tell FS to resume the search. | ||
994 | * | ||
995 | * @param button the 'resume' button | ||
996 | * @param user_data the 'struct SearchTab' of the tab to resume | ||
997 | */ | ||
998 | static void | ||
999 | continue_search (GtkButton * button, gpointer user_data) | ||
1000 | { | ||
1001 | struct SearchTab *tab = user_data; | ||
1002 | |||
1003 | if (NULL == tab->sc) | ||
1004 | { | ||
1005 | GNUNET_break (0); | ||
1006 | return; | ||
1007 | } | ||
1008 | GNUNET_FS_search_continue (tab->sc); | ||
1009 | gtk_widget_show (tab->pause_button); | ||
1010 | gtk_widget_hide (tab->play_button); | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | /** | ||
1015 | * User clicked on the 'clean' button of a search tab. | ||
1016 | * Stop completed downloads (or those that failed). Should | ||
1017 | * iterate over the underlying tree store and stop all | ||
1018 | * completed entries. Furthermore, if the resulting tree | ||
1019 | * store is empty and has no search associated with it, | ||
1020 | * the tab should be closed. | ||
1021 | * | ||
1022 | * @param button the button pressed by the user | ||
1023 | * @param user_data the 'struct SearchTab' of the respective tab to clean up | ||
1024 | */ | ||
1025 | static void | ||
1026 | clear_downloads (GtkButton * button, gpointer user_data) | ||
1027 | { | ||
1028 | struct SearchTab *tab = user_data; | ||
1029 | struct SearchResult *sr; | ||
1030 | GtkTreeModel *tm; | ||
1031 | GtkTreeIter iter; | ||
1032 | |||
1033 | tm = GTK_TREE_MODEL (tab->ts); | ||
1034 | if (TRUE != gtk_tree_model_get_iter_first (tm, &iter)) | ||
1035 | return; | ||
1036 | /* FIXME: this is a tree, what about cleaning up | ||
1037 | of the children? */ | ||
1038 | do | ||
1039 | { | ||
1040 | gtk_tree_model_get (tm, &iter, 9, &sr, -1); | ||
1041 | if ( (sr->download != NULL) && | ||
1042 | (sr->download->is_done == GNUNET_YES) ) | ||
1043 | { | ||
1044 | /* got a finished download, stop it */ | ||
1045 | GNUNET_FS_download_stop (sr->download->dc, GNUNET_YES); | ||
1046 | } | ||
1047 | if ( (NULL == sr->download) && | ||
1048 | (NULL == sr->result) ) | ||
1049 | { | ||
1050 | /* no active download and no associated FS-API search result; | ||
1051 | so this must be some left-over entry from an opened | ||
1052 | directory; clean it up */ | ||
1053 | free_search_result (sr); | ||
1054 | } | ||
1055 | } | ||
1056 | while (TRUE == gtk_tree_model_iter_next (tm, &iter)); | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /** | ||
1061 | * We received a search error message from the FS library. | ||
1062 | * Present it to the user in an appropriate form. | ||
1063 | * | ||
1064 | * @param tab search tab affected by the error message | ||
1065 | * @param emsg the error message | ||
1066 | */ | ||
1067 | static void | ||
1068 | handle_search_error (struct SearchTab *tab, | ||
1069 | const char *emsg) | ||
1070 | { | ||
1071 | gtk_label_set_text (tab->label, _("Error!")); | ||
1072 | gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), emsg); | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | /** | ||
1077 | * Obtain the string we will use to describe a search result from | ||
1078 | * the respective meta data. | ||
1079 | * | ||
1080 | * @param meta meta data to inspect | ||
1081 | * @return description of the result in utf-8, never NULL | ||
1082 | */ | ||
1083 | static char * | ||
1084 | get_description_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta) | ||
1085 | { | ||
1086 | char *desc; | ||
1087 | char *utf8_desc; | ||
1088 | |||
1089 | desc = | ||
1090 | GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
1091 | EXTRACTOR_METATYPE_PACKAGE_NAME, | ||
1092 | EXTRACTOR_METATYPE_TITLE, | ||
1093 | EXTRACTOR_METATYPE_BOOK_TITLE, | ||
1094 | EXTRACTOR_METATYPE_FILENAME, | ||
1095 | EXTRACTOR_METATYPE_DESCRIPTION, | ||
1096 | EXTRACTOR_METATYPE_SUMMARY, | ||
1097 | EXTRACTOR_METATYPE_ALBUM, | ||
1098 | EXTRACTOR_METATYPE_COMMENT, | ||
1099 | EXTRACTOR_METATYPE_SUBJECT, | ||
1100 | EXTRACTOR_METATYPE_KEYWORDS, | ||
1101 | -1); | ||
1102 | if (desc == NULL) | ||
1103 | return GNUNET_strdup (_("no description supplied")); | ||
1104 | utf8_desc = | ||
1105 | GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, | ||
1106 | strlen (desc) + 1); | ||
1107 | GNUNET_free (desc); | ||
1108 | if (utf8_desc == NULL) | ||
1109 | return GNUNET_strdup (_("no description supplied")); | ||
1110 | return utf8_desc; | ||
1111 | } | ||
1112 | |||
1113 | |||
1114 | /** | ||
1115 | * Obtain the mime type (or format description) will use to describe a search result from | ||
1116 | * the respective meta data. | ||
1117 | * | ||
1118 | * @param meta meta data to inspect | ||
1119 | * @return mime type to use, possibly NULL | ||
1120 | */ | ||
1121 | static char * | ||
1122 | get_mimetype_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta) | ||
1123 | { | ||
1124 | return GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
1125 | EXTRACTOR_METATYPE_MIMETYPE, | ||
1126 | EXTRACTOR_METATYPE_FORMAT, | ||
1127 | -1); | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /** | ||
1132 | * Some additional information about a search result has been | ||
1133 | * received. Update the view accordingly. | ||
1134 | * | ||
1135 | * @param sr search result that is being updated | ||
1136 | * @param meta updated meta data | ||
1137 | * @param availability_rank updated availability information | ||
1138 | * @param availability_certainty updated availability certainty | ||
1139 | * @param applicability_rank updated applicability information | ||
1140 | */ | ||
1141 | static void | ||
1142 | update_search_result (struct SearchResult *sr, | ||
1143 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1144 | int32_t availability_rank, | ||
1145 | uint32_t availability_certainty, | ||
1146 | uint32_t applicability_rank) | ||
1147 | { | ||
1148 | GtkTreeIter iter; | ||
1149 | struct GNUNET_CONTAINER_MetaData *ometa; | ||
1150 | GtkTreeView *tv; | ||
1151 | GtkTreePath *tp; | ||
1152 | GtkTreeStore *ts; | ||
1153 | GtkTreeModel *tm; | ||
1154 | char *desc; | ||
1155 | char *mime; | ||
1156 | GdkPixbuf *pixbuf; | ||
1157 | guint percent_avail; | ||
1158 | GtkNotebook *notebook; | ||
1159 | gint page; | ||
1160 | |||
1161 | if (sr == NULL) | ||
1162 | { | ||
1163 | GNUNET_break (0); | ||
1164 | return; | ||
1165 | } | ||
1166 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1167 | "Updating search result SR=%p with %d, %u, %u\n", | ||
1168 | sr, availability_rank, | ||
1169 | availability_certainty, applicability_rank); | ||
1170 | desc = get_description_from_metadata (meta); | ||
1171 | mime = get_mimetype_from_metadata (meta); | ||
1172 | pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta); | ||
1173 | tp = gtk_tree_row_reference_get_path (sr->rr); | ||
1174 | tm = gtk_tree_row_reference_get_model (sr->rr); | ||
1175 | ts = GTK_TREE_STORE (tm); | ||
1176 | gtk_tree_model_get_iter (tm, &iter, tp); | ||
1177 | gtk_tree_path_free (tp); | ||
1178 | gtk_tree_model_get (tm, &iter, 0, &ometa, -1); | ||
1179 | if (NULL != ometa) | ||
1180 | GNUNET_CONTAINER_meta_data_destroy (ometa); | ||
1181 | if (availability_certainty > 0) | ||
1182 | percent_avail = | ||
1183 | (availability_certainty + | ||
1184 | availability_rank) * 50 / availability_certainty; | ||
1185 | else | ||
1186 | percent_avail = 0; | ||
1187 | gtk_tree_store_set (ts, &iter, | ||
1188 | 0, GNUNET_CONTAINER_meta_data_duplicate (meta), | ||
1189 | 3, pixbuf /* preview */ , | ||
1190 | 5, (guint) percent_avail /* percent availability */ , | ||
1191 | 6, desc /* filename/description */ , | ||
1192 | 10, mime, 11, (guint) applicability_rank, 12, | ||
1193 | (guint) availability_certainty, 13, | ||
1194 | (gint) availability_rank, -1); | ||
1195 | if (pixbuf != NULL) | ||
1196 | g_object_unref (pixbuf); | ||
1197 | GNUNET_free (desc); | ||
1198 | GNUNET_free_non_null (mime); | ||
1199 | |||
1200 | notebook = | ||
1201 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
1202 | ("GNUNET_GTK_main_window_notebook")); | ||
1203 | page = gtk_notebook_get_current_page (notebook); | ||
1204 | if (gtk_notebook_get_nth_page (notebook, page) == sr->tab->frame) | ||
1205 | { | ||
1206 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
1207 | (sr->tab->builder, "_search_result_frame")); | ||
1208 | update_meta_data_views (tv, sr->tab); | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | |||
1213 | /** | ||
1214 | * Add a search result to the given search tab. This function is called | ||
1215 | * not only for 'normal' search results but also for directories that | ||
1216 | * are being opened and if the user manually enters a URI. | ||
1217 | * | ||
1218 | * @param tab search tab to extend, never NULL | ||
1219 | * @param iter set to position where search result is added (OUT only) | ||
1220 | * @param parent_rr reference to parent entry in search tab, NULL for normal | ||
1221 | * search results, | ||
1222 | * @param uri uri to add, can be NULL for top-level entry of a directory opened from disk | ||
1223 | * (in this case, we don't know the URI and should probably not | ||
1224 | * bother to calculate it) | ||
1225 | * @param meta metadata of the entry | ||
1226 | * @param result associated FS search result (can be NULL if this result | ||
1227 | * was part of a directory) | ||
1228 | * @param applicability_rank how relevant is the result | ||
1229 | * @return struct representing the search result (also stored in the tree | ||
1230 | * model at 'iter') | ||
1231 | */ | ||
1232 | struct SearchResult * | ||
1233 | GNUNET_GTK_add_search_result (struct SearchTab *tab, | ||
1234 | GtkTreeIter *iter, | ||
1235 | GtkTreeRowReference *parent_rr, | ||
1236 | const struct GNUNET_FS_Uri *uri, | ||
1237 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1238 | struct GNUNET_FS_SearchResult *result, | ||
1239 | uint32_t applicability_rank) | ||
1240 | { | ||
1241 | struct SearchResult *sr; | ||
1242 | GtkTreePath *tp; | ||
1243 | const char *status_colour; | ||
1244 | char *desc; | ||
1245 | char *mime; | ||
1246 | char *uris; | ||
1247 | GdkPixbuf *pixbuf; | ||
1248 | GtkTreeIter *pitr; | ||
1249 | GtkTreeIter pmem; | ||
1250 | GtkTreePath *path; | ||
1251 | GtkTreeModel *tm; | ||
1252 | GtkTreeStore *ts; | ||
1253 | uint64_t fsize; | ||
1254 | |||
1255 | if (NULL == uri) | ||
1256 | { | ||
1257 | /* opened directory file */ | ||
1258 | fsize = 0; | ||
1259 | status_colour = "gray"; | ||
1260 | mime = NULL; /* FIXME: should we set mime to directory? */ | ||
1261 | uris = GNUNET_strdup (_("no URI")); | ||
1262 | } | ||
1263 | else | ||
1264 | { | ||
1265 | if ( (GNUNET_FS_uri_test_loc (uri)) || | ||
1266 | (GNUNET_FS_uri_test_chk (uri)) ) | ||
1267 | { | ||
1268 | fsize = GNUNET_FS_uri_chk_get_file_size (uri); | ||
1269 | mime = get_mimetype_from_metadata (meta); | ||
1270 | status_colour = "white"; | ||
1271 | } | ||
1272 | else | ||
1273 | { | ||
1274 | /* FIXME: create mime type for namespaces? */ | ||
1275 | /* FIXME: can we encounter ksk URIs here too? */ | ||
1276 | fsize = 0; | ||
1277 | mime = GNUNET_strdup ("GNUnet namespace"); | ||
1278 | status_colour = "lightgreen"; | ||
1279 | } | ||
1280 | uris = GNUNET_FS_uri_to_string (uri); | ||
1281 | } | ||
1282 | desc = get_description_from_metadata (meta); | ||
1283 | pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta); | ||
1284 | |||
1285 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | ||
1286 | sr->result = result; | ||
1287 | sr->tab = tab; | ||
1288 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1289 | "Allocated a search result SR=%p\n", | ||
1290 | sr); | ||
1291 | if (parent_rr != NULL) | ||
1292 | { | ||
1293 | /* get piter from parent */ | ||
1294 | path = gtk_tree_row_reference_get_path (parent_rr); | ||
1295 | tm = gtk_tree_row_reference_get_model (parent_rr); | ||
1296 | if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (tm), &pmem, path)) | ||
1297 | { | ||
1298 | GNUNET_break (0); | ||
1299 | gtk_tree_path_free (path); | ||
1300 | /* desperate measure: make top-level entry */ | ||
1301 | pitr = NULL; | ||
1302 | } | ||
1303 | else | ||
1304 | { | ||
1305 | pitr = &pmem; | ||
1306 | } | ||
1307 | ts = GTK_TREE_STORE (tm); | ||
1308 | } | ||
1309 | else | ||
1310 | { | ||
1311 | /* top-level result */ | ||
1312 | pitr = NULL; | ||
1313 | ts = tab->ts; | ||
1314 | } | ||
1315 | gtk_tree_store_insert_with_values (ts, iter, pitr, G_MAXINT, | ||
1316 | 0, GNUNET_CONTAINER_meta_data_duplicate (meta), | ||
1317 | 1, (uri == NULL) ? NULL : GNUNET_FS_uri_dup (uri), | ||
1318 | 2, fsize, | ||
1319 | 3, pixbuf /* preview */ , | ||
1320 | 4, 0 /* percent progress */ , | ||
1321 | 5, 0 /* percent availability */ , | ||
1322 | 6, desc /* filename/description */ , | ||
1323 | 7, uris, | ||
1324 | 8, status_colour, | ||
1325 | 9, sr, | ||
1326 | 10, mime, | ||
1327 | 11, applicability_rank, | ||
1328 | 12, 0 /* avail-cert */ , | ||
1329 | 13, 0, /* avail-rank */ | ||
1330 | 14, (guint64) 0, /* completed */ | ||
1331 | 15, NULL, /* downloaded_filename */ | ||
1332 | 16, -1, /* downloaded_anonymity */ | ||
1333 | -1); | ||
1334 | if (pixbuf != NULL) | ||
1335 | g_object_unref (pixbuf); | ||
1336 | GNUNET_free (uris); | ||
1337 | GNUNET_free (desc); | ||
1338 | GNUNET_free_non_null (mime); | ||
1339 | |||
1340 | /* remember in 'sr' where we added the result */ | ||
1341 | tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), iter); | ||
1342 | sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), tp); | ||
1343 | gtk_tree_path_free (tp); | ||
1344 | |||
1345 | /* move up to the outermost tab, in case this is an 'inner' | ||
1346 | search (namespace update case) */ | ||
1347 | while (tab->parent != NULL) | ||
1348 | tab = tab->parent->tab; | ||
1349 | tab->num_results++; | ||
1350 | |||
1351 | return sr; | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | /** | ||
1356 | * We have received a search result from the FS API. Add it to the | ||
1357 | * respective search tab. The search result can be an 'inner' | ||
1358 | * search result (updated result for a namespace search) or a | ||
1359 | * top-level search result. Update the tree view and the label | ||
1360 | * of the search tab accordingly. | ||
1361 | * | ||
1362 | * @param tab the search tab where the new result should be added | ||
1363 | * @param parent parent search result (if this is a namespace update result), or NULL | ||
1364 | * @param uri URI of the search result | ||
1365 | * @param meta meta data for the result | ||
1366 | * @param result FS API handle to the result | ||
1367 | * @param applicability_rank how applicable is the result to the query | ||
1368 | * @return struct representing the search result (also stored in the tree | ||
1369 | * model at 'iter') | ||
1370 | */ | ||
1371 | static struct SearchResult * | ||
1372 | process_search_result (struct SearchTab *tab, | ||
1373 | struct SearchResult *parent, | ||
1374 | const struct GNUNET_FS_Uri *uri, | ||
1375 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1376 | struct GNUNET_FS_SearchResult *result, | ||
1377 | uint32_t applicability_rank) | ||
1378 | { | ||
1379 | struct SearchResult *sr; | ||
1380 | GtkTreeIter iter; | ||
1381 | |||
1382 | sr = GNUNET_GTK_add_search_result (tab, &iter, | ||
1383 | (parent != NULL) ? parent->rr : NULL, | ||
1384 | uri, | ||
1385 | meta, result, applicability_rank); | ||
1386 | update_search_label (tab); | ||
1387 | return sr; | ||
1388 | } | ||
1389 | |||
1390 | |||
1391 | /** | ||
1392 | * Setup a new search tab. | ||
1393 | * | ||
1394 | * @param sc context with FS for the search | ||
1395 | * @param query the query | ||
1396 | * @param anonymity anonymity level | ||
1397 | */ | ||
1398 | static struct SearchTab * | ||
1399 | setup_search (struct GNUNET_FS_SearchContext *sc, | ||
1400 | const struct GNUNET_FS_Uri *query) | ||
1401 | { | ||
1402 | struct SearchTab *tab; | ||
1403 | GtkTreeView *tv; | ||
1404 | GtkNotebook *notebook; | ||
1405 | GtkWindow *sf; | ||
1406 | gint pages; | ||
1407 | |||
1408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1409 | "Setting up a search for %p\n", sc); | ||
1410 | |||
1411 | tab = GNUNET_malloc (sizeof (struct SearchTab)); | ||
1412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1413 | "Allocated a tab %p\n", tab); | ||
1414 | GNUNET_CONTAINER_DLL_insert (search_tab_head, search_tab_tail, tab); | ||
1415 | tab->sc = sc; | ||
1416 | if (query == NULL) | ||
1417 | { | ||
1418 | tab->query_txt = GNUNET_strdup ("*"); | ||
1419 | } | ||
1420 | else | ||
1421 | { | ||
1422 | /* FS_uri functions should produce UTF-8, so let them be */ | ||
1423 | if (GNUNET_FS_uri_test_ksk (query)) | ||
1424 | tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query); | ||
1425 | else | ||
1426 | tab->query_txt = GNUNET_FS_uri_to_string (query); | ||
1427 | } | ||
1428 | tab->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_search_tab.glade", | ||
1429 | tab); | ||
1430 | tab->ts = | ||
1431 | GTK_TREE_STORE (gtk_builder_get_object | ||
1432 | (tab->builder, | ||
1433 | "GNUNET_GTK_file_sharing_result_tree_store")); | ||
1434 | /* load frame */ | ||
1435 | sf = GTK_WINDOW (gtk_builder_get_object | ||
1436 | (tab->builder, "_search_result_frame_window")); | ||
1437 | tab->frame = gtk_bin_get_child (GTK_BIN (sf)); | ||
1438 | g_object_ref (tab->frame); | ||
1439 | gtk_container_remove (GTK_CONTAINER (sf), tab->frame); | ||
1440 | gtk_widget_destroy (GTK_WIDGET (sf)); | ||
1441 | |||
1442 | /* load tab_label */ | ||
1443 | sf = GTK_WINDOW (gtk_builder_get_object | ||
1444 | (tab->builder, "_search_result_label_window")); | ||
1445 | tab->tab_label = gtk_bin_get_child (GTK_BIN (sf)); | ||
1446 | g_object_ref (tab->tab_label); | ||
1447 | gtk_container_remove (GTK_CONTAINER (sf), tab->tab_label); | ||
1448 | gtk_widget_destroy (GTK_WIDGET (sf)); | ||
1449 | |||
1450 | /* get refs to widgets */ | ||
1451 | tab->label = | ||
1452 | GTK_LABEL (gtk_builder_get_object | ||
1453 | (tab->builder, "_search_result_label_window_label")); | ||
1454 | |||
1455 | /* FIXME: connect these signals using glade!!! */ | ||
1456 | tab->close_button = | ||
1457 | GTK_WIDGET (gtk_builder_get_object | ||
1458 | (tab->builder, "_search_result_label_close_button")); | ||
1459 | g_signal_connect (G_OBJECT (tab->close_button), "clicked", | ||
1460 | G_CALLBACK (stop_search), tab); | ||
1461 | tab->clear_button = | ||
1462 | GTK_WIDGET (gtk_builder_get_object | ||
1463 | (tab->builder, "_search_result_label_clear_button")); | ||
1464 | g_signal_connect (G_OBJECT (tab->clear_button), "clicked", | ||
1465 | G_CALLBACK (clear_downloads), tab); | ||
1466 | tab->play_button = | ||
1467 | GTK_WIDGET (gtk_builder_get_object | ||
1468 | (tab->builder, "_search_result_label_play_button")); | ||
1469 | g_signal_connect (G_OBJECT (tab->play_button), "clicked", | ||
1470 | G_CALLBACK (continue_search), tab); | ||
1471 | tab->pause_button = | ||
1472 | GTK_WIDGET (gtk_builder_get_object | ||
1473 | (tab->builder, "_search_result_label_pause_button")); | ||
1474 | g_signal_connect (G_OBJECT (tab->pause_button), "clicked", | ||
1475 | G_CALLBACK (pause_search), tab); | ||
1476 | /* patch text */ | ||
1477 | update_search_label (tab); | ||
1478 | |||
1479 | /* add signal handlers; FIXME: again, connect these with glade... */ | ||
1480 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
1481 | (tab->builder, "_search_result_frame")); | ||
1482 | g_signal_connect (G_OBJECT (tv), "row-activated", | ||
1483 | G_CALLBACK (start_download_row_activated), tab); | ||
1484 | g_signal_connect (G_OBJECT (tv), "cursor-changed", | ||
1485 | G_CALLBACK (update_meta_data_views), tab); | ||
1486 | g_signal_connect (G_OBJECT (tv), "button_press_event", | ||
1487 | G_CALLBACK (search_list_on_menu), tab); | ||
1488 | g_signal_connect (G_OBJECT (tv), "popup-menu", | ||
1489 | G_CALLBACK (search_list_on_popup), tab); | ||
1490 | |||
1491 | |||
1492 | /* make visible */ | ||
1493 | notebook = | ||
1494 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
1495 | ("GNUNET_GTK_main_window_notebook")); | ||
1496 | pages = gtk_notebook_get_n_pages (notebook); | ||
1497 | gtk_notebook_insert_page (notebook, tab->frame, tab->tab_label, pages - 1); | ||
1498 | gtk_notebook_set_current_page (notebook, pages - 1); | ||
1499 | gtk_widget_show (GTK_WIDGET (notebook)); | ||
1500 | return tab; | ||
1501 | } | ||
1502 | |||
1503 | |||
1504 | /** | ||
1505 | * Setup an "inner" search, that is a subtree representing namespace | ||
1506 | * 'update' results. We use a 'struct SearchTab' to represent this | ||
1507 | * sub-search. In the GUI, the presentation is similar to search | ||
1508 | * results in a directory, except that this is for a namespace search | ||
1509 | * result that gave pointers to an alternative keyword to use and this | ||
1510 | * is the set of the results found for this alternative keyword. | ||
1511 | * | ||
1512 | * All of the 'widget' elements of the returned 'search tab' reference | ||
1513 | * the parent search. The whole construction is essentially a trick | ||
1514 | * to allow us to store the FS-API's 'SearchContext' somewhere and to | ||
1515 | * find it when we get this kind of 'inner' search results (so that we | ||
1516 | * can then place them in the tree view in the right spot). | ||
1517 | * | ||
1518 | * FIXME: don't we need a bit more information then? Like exactly where | ||
1519 | * this 'right spot' is? Not sure how just having 'sc' helps there, | ||
1520 | * as it is not a search result (!) to hang this up on! This might | ||
1521 | * essentially boil down to an issue with the FS API, not sure... | ||
1522 | * | ||
1523 | * @param sc context with FS for the search | ||
1524 | * @param parent parent search tab | ||
1525 | * @return struct representing the search result (also stored in the tree | ||
1526 | * model at 'iter') | ||
1527 | */ | ||
1528 | static struct SearchTab * | ||
1529 | setup_inner_search (struct GNUNET_FS_SearchContext *sc, | ||
1530 | struct SearchResult *parent) | ||
1531 | { | ||
1532 | struct SearchTab *ret; | ||
1533 | |||
1534 | ret = GNUNET_malloc (sizeof (struct SearchTab)); | ||
1535 | ret->parent = parent; | ||
1536 | ret->sc = sc; | ||
1537 | ret->query_txt = parent->tab->query_txt; | ||
1538 | ret->builder = parent->tab->builder; | ||
1539 | ret->frame = parent->tab->frame; | ||
1540 | ret->tab_label = parent->tab->tab_label; | ||
1541 | ret->close_button = parent->tab->close_button; | ||
1542 | ret->clear_button = parent->tab->clear_button; | ||
1543 | ret->play_button = parent->tab->play_button; | ||
1544 | ret->label = parent->tab->label; | ||
1545 | |||
1546 | return ret; | ||
1547 | } | ||
1548 | |||
1549 | |||
1550 | |||
1551 | |||
1552 | /** | ||
1553 | * Setup a new top-level entry in the URI tab. If necessary, create | ||
1554 | * the URI tab first. | ||
1555 | * | ||
1556 | * @param iter set to the new entry | ||
1557 | * @param srp set to search result | ||
1558 | * @param meta metadata for the new entry | ||
1559 | * @param uri URI for the new entry | ||
1560 | * @return NULL on error, otherwise tree store matching iter | ||
1561 | */ | ||
1562 | struct SearchTab * | ||
1563 | GNUNET_GTK_add_to_uri_tab (GtkTreeIter * iter, struct SearchResult **srp, | ||
1564 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1565 | const struct GNUNET_FS_Uri *uri) | ||
1566 | { | ||
1567 | struct SearchResult *sr; | ||
1568 | GtkNotebook *notebook; | ||
1569 | gint page; | ||
1570 | |||
1571 | if (uri_tab == NULL) | ||
1572 | { | ||
1573 | uri_tab = setup_search (NULL, NULL); | ||
1574 | gtk_widget_set_visible (uri_tab->close_button, FALSE); | ||
1575 | gtk_widget_set_visible (uri_tab->pause_button, FALSE); | ||
1576 | } | ||
1577 | else | ||
1578 | { | ||
1579 | /* make 'utab' the current page */ | ||
1580 | notebook = | ||
1581 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
1582 | ("GNUNET_GTK_main_window_notebook")); | ||
1583 | for (page = 0; page < gtk_notebook_get_n_pages (notebook); page++) | ||
1584 | if (uri_tab->frame == gtk_notebook_get_nth_page (notebook, page)) | ||
1585 | { | ||
1586 | gtk_notebook_set_current_page (notebook, page); | ||
1587 | break; | ||
1588 | } | ||
1589 | } | ||
1590 | sr = GNUNET_GTK_add_search_result (uri_tab, iter, NULL, uri, meta, NULL, 0); | ||
1591 | |||
1592 | if (NULL != srp) | ||
1593 | *srp = sr; | ||
1594 | return uri_tab; | ||
1595 | } | ||
1596 | |||
1597 | |||
1598 | |||
1599 | |||
1600 | |||
1601 | |||
1602 | /* ***************** Download event handling ****************** */ | ||
1603 | |||
1604 | |||
1605 | /** | ||
1606 | * Change the (background) color of the given download entry. | ||
1607 | * | ||
1608 | * @param de entry to change | ||
1609 | * @param color name of the color to use | ||
1610 | */ | ||
1611 | static void | ||
1612 | change_download_color (struct DownloadEntry *de, | ||
1613 | const char *color) | ||
772 | { | 1614 | { |
773 | GtkTreeIter iter; | 1615 | GtkTreeIter iter; |
774 | GtkTreePath *path; | 1616 | GtkTreePath *path; |
775 | 1617 | ||
776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changing publish PE=%p color to %s\n", pe, colour); | 1618 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
777 | if (pe == NULL) | 1619 | "Changing download DE=%p color to %s\n", |
1620 | de, color); | ||
1621 | path = gtk_tree_row_reference_get_path (de->rr); | ||
1622 | if (NULL == path) | ||
778 | { | 1623 | { |
779 | GNUNET_break (0); | 1624 | GNUNET_break (0); |
780 | return NULL; | 1625 | gtk_tree_path_free (path); |
1626 | return; | ||
781 | } | 1627 | } |
782 | path = gtk_tree_row_reference_get_path (pe->rr); | 1628 | if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) |
783 | if (TRUE != | ||
784 | gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path)) | ||
785 | { | 1629 | { |
786 | GNUNET_break (0); | 1630 | GNUNET_break (0); |
787 | gtk_tree_path_free (path); | 1631 | gtk_tree_path_free (path); |
788 | return pe; | 1632 | return; |
789 | } | 1633 | } |
790 | gtk_tree_path_free (path); | 1634 | gtk_tree_path_free (path); |
791 | gtk_tree_store_set (pe->tab->ts, &iter, 2, colour, -1); | 1635 | gtk_tree_store_set (de->ts, &iter, 8, color, -1); |
792 | return pe; | ||
793 | } | 1636 | } |
794 | 1637 | ||
795 | 1638 | ||
1639 | /** | ||
1640 | * A download operation was stopped. Remove all state associated with | ||
1641 | * it and reset the search result's background color to 'white'. | ||
1642 | * | ||
1643 | * @param de the download that was stopped | ||
1644 | */ | ||
796 | static void | 1645 | static void |
797 | stop_download (struct DownloadEntry *de, int is_suspend) | 1646 | stop_download (struct DownloadEntry *de) |
798 | { | 1647 | { |
799 | GtkTreeIter iter; | 1648 | GtkTreeIter iter; |
800 | GtkTreePath *path; | 1649 | GtkTreePath *path; |
801 | GtkTreeModel *tm; | 1650 | GtkTreeModel *tm; |
802 | struct SearchResult *search_result; | 1651 | struct SearchResult *search_result; |
803 | 1652 | ||
804 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping download DE=%p, %s\n", de, is_suspend ? "temporarily" : "permanently"); | ||
805 | path = gtk_tree_row_reference_get_path (de->rr); | 1653 | path = gtk_tree_row_reference_get_path (de->rr); |
806 | tm = gtk_tree_row_reference_get_model (de->rr); | 1654 | tm = gtk_tree_row_reference_get_model (de->rr); |
807 | if (path != NULL) | 1655 | if (path != NULL) |
808 | { | 1656 | { |
809 | if (TRUE != gtk_tree_model_get_iter (tm, &iter, path)) | 1657 | if (! gtk_tree_model_get_iter (tm, &iter, path)) |
1658 | { | ||
810 | GNUNET_break (0); | 1659 | GNUNET_break (0); |
1660 | } | ||
811 | else | 1661 | else |
812 | { | 1662 | { |
813 | gtk_tree_model_get (tm, &iter, 9, &search_result, -1); | 1663 | gtk_tree_model_get (tm, &iter, 9, &search_result, -1); |
814 | /*Always fails on downloads started by Download URI */ | 1664 | GNUNET_assert (search_result->download == de); |
815 | /*GNUNET_assert (search_result->download == de); */ | ||
816 | search_result->download = NULL; | 1665 | search_result->download = NULL; |
817 | if (NULL == search_result->result) | 1666 | change_download_color (de, "white"); |
818 | { | ||
819 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing it from the tree\n"); | ||
820 | (void) gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter); | ||
821 | } | ||
822 | else | ||
823 | change_download_colour (de, "white"); | ||
824 | } | 1667 | } |
825 | gtk_tree_path_free (path); | 1668 | gtk_tree_path_free (path); |
826 | } | 1669 | } |
@@ -978,7 +1821,7 @@ mark_download_error (struct DownloadEntry *de, const char *emsg) | |||
978 | 1821 | ||
979 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
980 | "Marking download error for DE=%p: %s\n", de, emsg); | 1823 | "Marking download error for DE=%p: %s\n", de, emsg); |
981 | de = change_download_colour (de, "red"); | 1824 | change_download_color (de, "red"); |
982 | de->is_done = GNUNET_YES; | 1825 | de->is_done = GNUNET_YES; |
983 | path = gtk_tree_row_reference_get_path (de->rr); | 1826 | path = gtk_tree_row_reference_get_path (de->rr); |
984 | if (TRUE != | 1827 | if (TRUE != |
@@ -1015,37 +1858,12 @@ mark_download_completed (struct DownloadEntry *de, uint64_t size, | |||
1015 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "It is a directory, scan its contents\n"); | 1858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "It is a directory, scan its contents\n"); |
1016 | GNUNET_FS_GTK_mmap_and_scan (filename, &add_directory_entry, &ade); | 1859 | GNUNET_FS_GTK_mmap_and_scan (filename, &add_directory_entry, &ade); |
1017 | } | 1860 | } |
1018 | (void) change_download_colour (de, "green"); | 1861 | change_download_color (de, "green"); |
1019 | return de; | 1862 | return de; |
1020 | } | 1863 | } |
1021 | 1864 | ||
1022 | 1865 | ||
1023 | static struct PublishEntry * | ||
1024 | mark_publish_progress (struct PublishEntry *pe, uint64_t size, | ||
1025 | uint64_t completed) | ||
1026 | { | ||
1027 | GtkTreeIter iter; | ||
1028 | GtkTreePath *path; | ||
1029 | 1866 | ||
1030 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1031 | "Marking publicaation progress for PE=%p, %llu/%llu\n", | ||
1032 | pe, completed, size); | ||
1033 | path = gtk_tree_row_reference_get_path (pe->rr); | ||
1034 | if (TRUE != | ||
1035 | gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path)) | ||
1036 | { | ||
1037 | GNUNET_break (0); | ||
1038 | gtk_tree_path_free (path); | ||
1039 | return pe; | ||
1040 | } | ||
1041 | gtk_tree_path_free (path); | ||
1042 | gtk_tree_store_set (pe->tab->ts, &iter, 3, | ||
1043 | (guint) ((size > | ||
1044 | 0) ? (100 * completed / | ||
1045 | size) : 100) /* progress */ , | ||
1046 | -1); | ||
1047 | return pe; | ||
1048 | } | ||
1049 | 1867 | ||
1050 | 1868 | ||
1051 | /** | 1869 | /** |
@@ -1195,13 +2013,13 @@ download_lost_parent (struct DownloadEntry *de, uint64_t size, | |||
1195 | if (size > completed) | 2013 | if (size > completed) |
1196 | { | 2014 | { |
1197 | if (is_active) | 2015 | if (is_active) |
1198 | change_download_colour (de, "yellow"); | 2016 | change_download_color (de, "yellow"); |
1199 | else | 2017 | else |
1200 | change_download_colour (de, "blue"); | 2018 | change_download_color (de, "blue"); |
1201 | } | 2019 | } |
1202 | else | 2020 | else |
1203 | { | 2021 | { |
1204 | change_download_colour (de, "green"); | 2022 | change_download_color (de, "green"); |
1205 | } | 2023 | } |
1206 | return de; | 2024 | return de; |
1207 | } | 2025 | } |
@@ -1234,6 +2052,7 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde, | |||
1234 | "Setting up download, initially DE=%p, PDE=%p for %p & %p into %llu/%llu `%s'\n", | 2052 | "Setting up download, initially DE=%p, PDE=%p for %p & %p into %llu/%llu `%s'\n", |
1235 | de, pde, sr, dc, completed, size, filename); | 2053 | de, pde, sr, dc, completed, size, filename); |
1236 | GNUNET_assert (NULL != uri); | 2054 | GNUNET_assert (NULL != uri); |
2055 | srp = NULL; | ||
1237 | if (de == NULL) | 2056 | if (de == NULL) |
1238 | { | 2057 | { |
1239 | de = GNUNET_malloc (sizeof (struct DownloadEntry)); | 2058 | de = GNUNET_malloc (sizeof (struct DownloadEntry)); |
@@ -1285,14 +2104,18 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde, | |||
1285 | return de; | 2104 | return de; |
1286 | } | 2105 | } |
1287 | gtk_tree_path_free (path); | 2106 | gtk_tree_path_free (path); |
1288 | gtk_tree_store_set (de->ts, &iter, 4, | 2107 | gtk_tree_store_set (de->ts, &iter, |
1289 | (guint) ((size > | 2108 | 4, (guint) ((size > |
1290 | 0) ? (100 * completed / | 2109 | 0) ? (100 * completed / |
1291 | size) : 100) /* progress */ , | 2110 | size) : 100) /* progress */ , |
1292 | 6, filename /* filename/description */ , | 2111 | 6, filename /* filename/description */ , |
1293 | 8, "blue" /* status colour: pending */ , | 2112 | 8, "blue" /* status colour: pending */ , |
2113 | 14, completed, | ||
1294 | -1); | 2114 | -1); |
1295 | gtk_tree_store_set (de->ts, &iter, 14, completed, -1); | 2115 | if (NULL != srp) |
2116 | gtk_tree_store_set (de->ts, &iter, | ||
2117 | 9, srp, | ||
2118 | -1); | ||
1296 | return de; | 2119 | return de; |
1297 | } | 2120 | } |
1298 | 2121 | ||
@@ -1301,119 +2124,82 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde, | |||
1301 | 2124 | ||
1302 | 2125 | ||
1303 | 2126 | ||
2127 | /* ***************** Publish event handling ****************** */ | ||
2128 | |||
2129 | |||
2130 | |||
2131 | |||
1304 | /** | 2132 | /** |
1305 | * Selected row has changed, update preview and metadata | 2133 | * Change the (background) color of the given publish entry. |
1306 | * areas. | 2134 | * |
2135 | * @param pe entry to change | ||
2136 | * @param color name of the color to use | ||
1307 | */ | 2137 | */ |
1308 | static void | 2138 | static void |
1309 | update_meta_data_views (GtkTreeView * tv, gpointer user_data) | 2139 | change_publish_color (struct PublishEntry *pe, |
2140 | const char *color) | ||
1310 | { | 2141 | { |
1311 | struct SearchTab *tab = user_data; | ||
1312 | GtkImage *image; | ||
1313 | GtkListStore *ms; | ||
1314 | GtkTreeSelection *sel; | ||
1315 | GtkTreeModel *model; | ||
1316 | GtkTreeIter iter; | 2142 | GtkTreeIter iter; |
1317 | struct GNUNET_CONTAINER_MetaData *meta; | 2143 | GtkTreePath *path; |
1318 | GdkPixbuf *pixbuf; | ||
1319 | |||
1320 | GNUNET_assert (tab->query_txt != NULL); | ||
1321 | image = | ||
1322 | GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object | ||
1323 | ("GNUNET_GTK_main_window_preview_image")); | ||
1324 | ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object | ||
1325 | ("GNUNET_GTK_meta_data_list_store")); | ||
1326 | 2144 | ||
1327 | sel = gtk_tree_view_get_selection (tv); | 2145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1328 | gtk_list_store_clear (ms); | 2146 | "Changing publish PE=%p color to %s\n", |
1329 | if (TRUE != gtk_tree_selection_get_selected (sel, &model, &iter)) | 2147 | pe, color); |
2148 | path = gtk_tree_row_reference_get_path (pe->rr); | ||
2149 | if (NULL == path) | ||
1330 | { | 2150 | { |
1331 | gtk_image_clear (image); | 2151 | GNUNET_break (0); |
1332 | return; | 2152 | return; |
1333 | } | 2153 | } |
1334 | meta = NULL; | 2154 | if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path)) |
1335 | pixbuf = NULL; | ||
1336 | gtk_tree_model_get (model, &iter, 0, &meta, 3, &pixbuf, -1); | ||
1337 | if (pixbuf != NULL) | ||
1338 | { | 2155 | { |
1339 | gtk_image_set_from_pixbuf (image, pixbuf); | 2156 | GNUNET_break (0); |
1340 | g_object_unref (G_OBJECT (pixbuf)); | 2157 | gtk_tree_path_free (path); |
1341 | } | 2158 | return; |
1342 | if (meta != NULL) | ||
1343 | { | ||
1344 | GNUNET_CONTAINER_meta_data_iterate (meta, | ||
1345 | &GNUNET_FS_GTK_add_meta_data_to_list_store, | ||
1346 | ms); | ||
1347 | } | 2159 | } |
2160 | gtk_tree_path_free (path); | ||
2161 | gtk_tree_store_set (pe->tab->ts, &iter, 2, color, -1); | ||
2162 | return; | ||
1348 | } | 2163 | } |
1349 | 2164 | ||
1350 | 2165 | ||
1351 | /** | 2166 | static struct PublishEntry * |
1352 | * Update the label for a search | 2167 | mark_publish_progress (struct PublishEntry *pe, uint64_t size, |
1353 | */ | 2168 | uint64_t completed) |
1354 | static void | ||
1355 | update_search_label (struct SearchTab *tab) | ||
1356 | { | ||
1357 | char *name; | ||
1358 | |||
1359 | while (tab->parent != NULL) | ||
1360 | tab = tab->parent->tab; | ||
1361 | if (tab->num_results > 0) | ||
1362 | GNUNET_asprintf (&name, "%.*s%s (%u)", 20, tab->query_txt, | ||
1363 | strlen (tab->query_txt) > 20 ? "..." : "", | ||
1364 | tab->num_results); | ||
1365 | else | ||
1366 | GNUNET_asprintf (&name, "%.*s%s", 20, tab->query_txt, | ||
1367 | strlen (tab->query_txt) > 20 ? "..." : ""); | ||
1368 | gtk_label_set_text (tab->label, name); | ||
1369 | gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), tab->query_txt); | ||
1370 | GNUNET_free (name); | ||
1371 | } | ||
1372 | |||
1373 | |||
1374 | /** | ||
1375 | * Close a search tab and free associated state. | ||
1376 | */ | ||
1377 | static void | ||
1378 | close_search_tab (struct SearchTab *tab) | ||
1379 | { | 2169 | { |
1380 | GtkNotebook *notebook; | 2170 | GtkTreeIter iter; |
1381 | int index; | 2171 | GtkTreePath *path; |
1382 | int i; | ||
1383 | 2172 | ||
1384 | if (tab->parent != NULL) | 2173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2174 | "Marking publicaation progress for PE=%p, %llu/%llu\n", | ||
2175 | pe, completed, size); | ||
2176 | path = gtk_tree_row_reference_get_path (pe->rr); | ||
2177 | if (TRUE != | ||
2178 | gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path)) | ||
1385 | { | 2179 | { |
1386 | /* not a top-level search, do not close tab here! */ | 2180 | GNUNET_break (0); |
1387 | GNUNET_free (tab); | 2181 | gtk_tree_path_free (path); |
1388 | return; | 2182 | return pe; |
1389 | } | 2183 | } |
1390 | 2184 | gtk_tree_path_free (path); | |
1391 | notebook = | 2185 | gtk_tree_store_set (pe->tab->ts, &iter, 3, |
1392 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | 2186 | (guint) ((size > |
1393 | ("GNUNET_GTK_main_window_notebook")); | 2187 | 0) ? (100 * completed / |
1394 | index = -1; | 2188 | size) : 100) /* progress */ , |
1395 | for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--) | 2189 | -1); |
1396 | if (tab->frame == gtk_notebook_get_nth_page (notebook, i)) | 2190 | return pe; |
1397 | index = i; | ||
1398 | gtk_notebook_remove_page (notebook, index); | ||
1399 | g_object_unref (tab->builder); | ||
1400 | GNUNET_free (tab->query_txt); | ||
1401 | GNUNET_CONTAINER_DLL_remove (search_tab_head, search_tab_tail, tab); | ||
1402 | if (tab == uri_tab) | ||
1403 | uri_tab = NULL; | ||
1404 | GNUNET_free (tab); | ||
1405 | } | 2191 | } |
1406 | 2192 | ||
1407 | 2193 | ||
1408 | /** | 2194 | /** |
1409 | * Close a publish tab and free associated state. | 2195 | * Close a publish tab and free associated state. |
1410 | */ | 2196 | */ |
1411 | static struct PublishEntry * | 2197 | static void |
1412 | handle_publish_completed (struct PublishEntry *ent, | 2198 | handle_publish_completed (struct PublishEntry *pe, |
1413 | const struct GNUNET_FS_Uri *uri) | 2199 | const struct GNUNET_FS_Uri *uri) |
1414 | { | 2200 | { |
1415 | ent->uri = GNUNET_FS_uri_dup (uri); | 2201 | pe->uri = GNUNET_FS_uri_dup (uri); |
1416 | return change_publish_colour (ent, "green"); | 2202 | change_publish_color (pe, "green"); |
1417 | } | 2203 | } |
1418 | 2204 | ||
1419 | 2205 | ||
@@ -1421,11 +2207,12 @@ handle_publish_completed (struct PublishEntry *ent, | |||
1421 | /** | 2207 | /** |
1422 | * Handle error. | 2208 | * Handle error. |
1423 | */ | 2209 | */ |
1424 | static struct PublishEntry * | 2210 | static void |
1425 | handle_publish_error (struct PublishEntry *ent, const char *emsg) | 2211 | handle_publish_error (struct PublishEntry *ent, |
2212 | const char *emsg) | ||
1426 | { | 2213 | { |
1427 | GNUNET_break (0); | 2214 | GNUNET_break (0); |
1428 | return change_publish_colour (ent, "red"); | 2215 | change_publish_color (ent, "red"); |
1429 | } | 2216 | } |
1430 | 2217 | ||
1431 | 2218 | ||
@@ -1471,616 +2258,15 @@ handle_publish_stop (struct PublishEntry *ent) | |||
1471 | } | 2258 | } |
1472 | 2259 | ||
1473 | 2260 | ||
1474 | /** | ||
1475 | * Tell FS to stop a search. | ||
1476 | */ | ||
1477 | static void | ||
1478 | stop_search (GtkButton * button, gpointer user_data) | ||
1479 | { | ||
1480 | struct SearchTab *tab = user_data; | ||
1481 | struct GNUNET_FS_SearchContext *sc; | ||
1482 | |||
1483 | if (NULL != (sc = tab->sc)) | ||
1484 | { | ||
1485 | tab->sc = NULL; | ||
1486 | GNUNET_FS_search_stop (sc); | ||
1487 | } | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | static void | ||
1492 | free_search_result (struct SearchResult *sr) | ||
1493 | { | ||
1494 | GtkTreePath *tp; | ||
1495 | GtkTreeModel *tm; | ||
1496 | GtkTreeIter iter; | ||
1497 | struct GNUNET_FS_Uri *uri; | ||
1498 | struct GNUNET_CONTAINER_MetaData *meta; | ||
1499 | |||
1500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1501 | "Freeing a search result SR=%p\n", sr); | ||
1502 | |||
1503 | if (sr == NULL) | ||
1504 | { | ||
1505 | GNUNET_break (0); | ||
1506 | return; | ||
1507 | } | ||
1508 | GNUNET_assert (sr->rr != NULL); | ||
1509 | tp = gtk_tree_row_reference_get_path (sr->rr); | ||
1510 | GNUNET_assert (tp != NULL); | ||
1511 | tm = gtk_tree_row_reference_get_model (sr->rr); | ||
1512 | GNUNET_assert (tm != NULL); | ||
1513 | if (TRUE != gtk_tree_model_get_iter (tm, &iter, tp)) | ||
1514 | { | ||
1515 | GNUNET_break (0); | ||
1516 | gtk_tree_path_free (tp); | ||
1517 | return; | ||
1518 | } | ||
1519 | gtk_tree_path_free (tp); | ||
1520 | gtk_tree_model_get (tm, &iter, 0, &meta, 1, &uri, -1); | ||
1521 | if (uri != NULL) | ||
1522 | GNUNET_FS_uri_destroy (uri); | ||
1523 | if (meta != NULL) | ||
1524 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
1525 | gtk_tree_row_reference_free (sr->rr); | ||
1526 | (void) gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter); | ||
1527 | GNUNET_free (sr); | ||
1528 | } | ||
1529 | |||
1530 | |||
1531 | /** | ||
1532 | * Stop completed downloads (or those that failed). Should | ||
1533 | * iterate over the underlying tree store and stop all | ||
1534 | * completed entries. Furthermore, if the resulting tree | ||
1535 | * store is empty and has no search associated with it, | ||
1536 | * the tab should be closed. | ||
1537 | */ | ||
1538 | static void | ||
1539 | clear_downloads (GtkButton * button, gpointer user_data) | ||
1540 | { | ||
1541 | struct SearchTab *tab = user_data; | ||
1542 | struct SearchResult *sr; | ||
1543 | GtkTreeModel *tm; | ||
1544 | GtkTreeIter iter; | ||
1545 | |||
1546 | tm = GTK_TREE_MODEL (tab->ts); | ||
1547 | if (TRUE != gtk_tree_model_get_iter_first (tm, &iter)) | ||
1548 | return; | ||
1549 | do | ||
1550 | { | ||
1551 | gtk_tree_model_get (tm, &iter, 9, &sr, -1); | ||
1552 | if (sr->download != NULL) | ||
1553 | { | ||
1554 | if (sr->download->is_done == GNUNET_YES) | ||
1555 | GNUNET_FS_download_stop (sr->download->dc, GNUNET_YES); | ||
1556 | } | ||
1557 | else if (sr->result == NULL) | ||
1558 | free_search_result (sr); | ||
1559 | } | ||
1560 | while (TRUE == gtk_tree_model_iter_next (tm, &iter)); | ||
1561 | } | ||
1562 | |||
1563 | |||
1564 | |||
1565 | /** | ||
1566 | * Tell FS to pause a search. | ||
1567 | */ | ||
1568 | static void | ||
1569 | pause_search (GtkButton * button, gpointer user_data) | ||
1570 | { | ||
1571 | struct SearchTab *tab = user_data; | ||
1572 | |||
1573 | if (tab->sc != NULL) | ||
1574 | { | ||
1575 | GNUNET_FS_search_pause (tab->sc); | ||
1576 | gtk_widget_show (tab->play_button); | ||
1577 | gtk_widget_hide (tab->pause_button); | ||
1578 | } | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | /** | ||
1583 | * Tell FS to resume a search. | ||
1584 | */ | ||
1585 | static void | ||
1586 | continue_search (GtkButton * button, gpointer user_data) | ||
1587 | { | ||
1588 | struct SearchTab *tab = user_data; | ||
1589 | |||
1590 | if (tab->sc != NULL) | ||
1591 | { | ||
1592 | GNUNET_FS_search_continue (tab->sc); | ||
1593 | gtk_widget_show (tab->pause_button); | ||
1594 | gtk_widget_hide (tab->play_button); | ||
1595 | } | ||
1596 | } | ||
1597 | 2261 | ||
1598 | 2262 | ||
1599 | /** | ||
1600 | * FIXME: what exactly are we freeing here on 'row_activated'? | ||
1601 | */ | ||
1602 | static void | ||
1603 | closure_notify_free (gpointer data, GClosure *closure) | ||
1604 | { | ||
1605 | GNUNET_free (data); | ||
1606 | } | ||
1607 | |||
1608 | 2263 | ||
1609 | /** | ||
1610 | * Setup a new search tab. | ||
1611 | * | ||
1612 | * @param sc context with FS for the search | ||
1613 | * @param query the query | ||
1614 | * @param anonymity anonymity level | ||
1615 | */ | ||
1616 | static struct SearchTab * | ||
1617 | setup_search (struct GNUNET_FS_SearchContext *sc, | ||
1618 | const struct GNUNET_FS_Uri *query) | ||
1619 | { | ||
1620 | struct SearchTab *tab; | ||
1621 | GtkTreeView *tv; | ||
1622 | GtkNotebook *notebook; | ||
1623 | GtkWindow *sf; | ||
1624 | gint pages; | ||
1625 | 2264 | ||
1626 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1627 | "Setting up a search for %p\n", sc); | ||
1628 | 2265 | ||
1629 | tab = GNUNET_malloc (sizeof (struct SearchTab)); | ||
1630 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1631 | "Allocated a tab %p\n", tab); | ||
1632 | GNUNET_CONTAINER_DLL_insert (search_tab_head, search_tab_tail, tab); | ||
1633 | tab->sc = sc; | ||
1634 | if (query == NULL) | ||
1635 | { | ||
1636 | tab->query_txt = GNUNET_strdup ("*"); | ||
1637 | } | ||
1638 | else | ||
1639 | { | ||
1640 | /* FS_uri functions should produce UTF-8, so let them be */ | ||
1641 | if (GNUNET_FS_uri_test_ksk (query)) | ||
1642 | tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query); | ||
1643 | else | ||
1644 | tab->query_txt = GNUNET_FS_uri_to_string (query); | ||
1645 | } | ||
1646 | tab->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_search_tab.glade", | ||
1647 | tab); | ||
1648 | tab->ts = | ||
1649 | GTK_TREE_STORE (gtk_builder_get_object | ||
1650 | (tab->builder, | ||
1651 | "GNUNET_GTK_file_sharing_result_tree_store")); | ||
1652 | /* load frame */ | ||
1653 | sf = GTK_WINDOW (gtk_builder_get_object | ||
1654 | (tab->builder, "_search_result_frame_window")); | ||
1655 | tab->frame = gtk_bin_get_child (GTK_BIN (sf)); | ||
1656 | g_object_ref (tab->frame); | ||
1657 | gtk_container_remove (GTK_CONTAINER (sf), tab->frame); | ||
1658 | gtk_widget_destroy (GTK_WIDGET (sf)); | ||
1659 | 2266 | ||
1660 | /* load tab_label */ | ||
1661 | sf = GTK_WINDOW (gtk_builder_get_object | ||
1662 | (tab->builder, "_search_result_label_window")); | ||
1663 | tab->tab_label = gtk_bin_get_child (GTK_BIN (sf)); | ||
1664 | g_object_ref (tab->tab_label); | ||
1665 | gtk_container_remove (GTK_CONTAINER (sf), tab->tab_label); | ||
1666 | gtk_widget_destroy (GTK_WIDGET (sf)); | ||
1667 | 2267 | ||
1668 | /* get refs to widgets */ | ||
1669 | tab->label = | ||
1670 | GTK_LABEL (gtk_builder_get_object | ||
1671 | (tab->builder, "_search_result_label_window_label")); | ||
1672 | 2268 | ||
1673 | /* FIXME: connect these signals using glade!!! */ | ||
1674 | tab->close_button = | ||
1675 | GTK_WIDGET (gtk_builder_get_object | ||
1676 | (tab->builder, "_search_result_label_close_button")); | ||
1677 | g_signal_connect (G_OBJECT (tab->close_button), "clicked", | ||
1678 | G_CALLBACK (stop_search), tab); | ||
1679 | tab->clear_button = | ||
1680 | GTK_WIDGET (gtk_builder_get_object | ||
1681 | (tab->builder, "_search_result_label_clear_button")); | ||
1682 | g_signal_connect (G_OBJECT (tab->clear_button), "clicked", | ||
1683 | G_CALLBACK (clear_downloads), tab); | ||
1684 | tab->play_button = | ||
1685 | GTK_WIDGET (gtk_builder_get_object | ||
1686 | (tab->builder, "_search_result_label_play_button")); | ||
1687 | g_signal_connect (G_OBJECT (tab->play_button), "clicked", | ||
1688 | G_CALLBACK (continue_search), tab); | ||
1689 | tab->pause_button = | ||
1690 | GTK_WIDGET (gtk_builder_get_object | ||
1691 | (tab->builder, "_search_result_label_pause_button")); | ||
1692 | g_signal_connect (G_OBJECT (tab->pause_button), "clicked", | ||
1693 | G_CALLBACK (pause_search), tab); | ||
1694 | /* patch text */ | ||
1695 | update_search_label (tab); | ||
1696 | 2269 | ||
1697 | /* add signal handlers; FIXME: again, connect these with glade... */ | ||
1698 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
1699 | (tab->builder, "_search_result_frame")); | ||
1700 | g_signal_connect_data (G_OBJECT (tv), "row-activated", | ||
1701 | G_CALLBACK (start_download_row_activated), tab, | ||
1702 | &closure_notify_free, 0); | ||
1703 | g_signal_connect (G_OBJECT (tv), "cursor-changed", | ||
1704 | G_CALLBACK (update_meta_data_views), tab); | ||
1705 | g_signal_connect (G_OBJECT (tv), "button_press_event", | ||
1706 | G_CALLBACK (search_list_on_menu), tab); | ||
1707 | g_signal_connect (G_OBJECT (tv), "popup-menu", | ||
1708 | G_CALLBACK (search_list_on_popup), tab); | ||
1709 | |||
1710 | |||
1711 | /* make visible */ | ||
1712 | notebook = | ||
1713 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
1714 | ("GNUNET_GTK_main_window_notebook")); | ||
1715 | pages = gtk_notebook_get_n_pages (notebook); | ||
1716 | gtk_notebook_insert_page (notebook, tab->frame, tab->tab_label, pages - 1); | ||
1717 | gtk_notebook_set_current_page (notebook, pages - 1); | ||
1718 | gtk_widget_show (GTK_WIDGET (notebook)); | ||
1719 | return tab; | ||
1720 | } | ||
1721 | |||
1722 | |||
1723 | /** | ||
1724 | * Setup an inner search. FIXME: explain what an 'inner' search is... | ||
1725 | * | ||
1726 | * @param sc context with FS for the search | ||
1727 | * @param parent parent search tab | ||
1728 | * @param anonymity anonymity level | ||
1729 | */ | ||
1730 | static struct SearchTab * | ||
1731 | setup_inner_search (struct GNUNET_FS_SearchContext *sc, | ||
1732 | struct SearchResult *parent) | ||
1733 | { | ||
1734 | struct SearchTab *ret; | ||
1735 | |||
1736 | ret = GNUNET_malloc (sizeof (struct SearchTab)); | ||
1737 | ret->parent = parent; | ||
1738 | ret->sc = sc; | ||
1739 | ret->query_txt = parent->tab->query_txt; | ||
1740 | ret->builder = parent->tab->builder; | ||
1741 | ret->frame = parent->tab->frame; | ||
1742 | ret->tab_label = parent->tab->tab_label; | ||
1743 | ret->close_button = parent->tab->close_button; | ||
1744 | ret->clear_button = parent->tab->clear_button; | ||
1745 | ret->play_button = parent->tab->play_button; | ||
1746 | ret->label = parent->tab->label; | ||
1747 | |||
1748 | return ret; | ||
1749 | } | ||
1750 | |||
1751 | |||
1752 | /** | ||
1753 | * Add a search result to the given search tab. | ||
1754 | * | ||
1755 | * @param tab search tab to extend | ||
1756 | * @param iter set to position where search result is added | ||
1757 | * @param parent_rr reference to parent entry in search tab | ||
1758 | * @param uri uri to add | ||
1759 | * @param meta metadata of the entry | ||
1760 | * @param result associated FS search result (can be NULL) | ||
1761 | * @param applicability_rank how relevant is the result | ||
1762 | * @return entry for the search result | ||
1763 | */ | ||
1764 | struct SearchResult * | ||
1765 | GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter, | ||
1766 | GtkTreeRowReference * parent_rr, | ||
1767 | const struct GNUNET_FS_Uri *uri, | ||
1768 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1769 | struct GNUNET_FS_SearchResult *result, | ||
1770 | uint32_t applicability_rank) | ||
1771 | { | ||
1772 | struct SearchResult *sr; | ||
1773 | GtkTreePath *tp; | ||
1774 | const char *status_colour; | ||
1775 | char *desc; | ||
1776 | char *mime; | ||
1777 | char *uris; | ||
1778 | GdkPixbuf *pixbuf; | ||
1779 | GtkTreeIter *pitr; | ||
1780 | GtkTreeIter pmem; | ||
1781 | GtkTreePath *path; | ||
1782 | GtkTreeModel *tm; | ||
1783 | GtkTreeStore *ts; | ||
1784 | uint64_t fsize; | ||
1785 | |||
1786 | if ((uri != NULL) && (!GNUNET_FS_uri_test_loc (uri)) && | ||
1787 | (!GNUNET_FS_uri_test_chk (uri))) | ||
1788 | { | ||
1789 | fsize = 0; | ||
1790 | mime = GNUNET_strdup ("GNUnet namespace"); | ||
1791 | status_colour = "lightgreen"; | ||
1792 | } | ||
1793 | else if (uri != NULL) | ||
1794 | { | ||
1795 | fsize = GNUNET_FS_uri_chk_get_file_size (uri); | ||
1796 | mime = | ||
1797 | GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
1798 | EXTRACTOR_METATYPE_MIMETYPE, | ||
1799 | EXTRACTOR_METATYPE_FORMAT, | ||
1800 | -1); | ||
1801 | status_colour = "white"; | ||
1802 | } | ||
1803 | else | ||
1804 | { | ||
1805 | fsize = 0; | ||
1806 | status_colour = "gray"; | ||
1807 | mime = NULL; | ||
1808 | } | ||
1809 | desc = | ||
1810 | GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
1811 | EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, | ||
1812 | EXTRACTOR_METATYPE_PACKAGE_NAME, | ||
1813 | EXTRACTOR_METATYPE_TITLE, | ||
1814 | EXTRACTOR_METATYPE_BOOK_TITLE, | ||
1815 | EXTRACTOR_METATYPE_FILENAME, | ||
1816 | EXTRACTOR_METATYPE_DESCRIPTION, | ||
1817 | EXTRACTOR_METATYPE_SUMMARY, | ||
1818 | EXTRACTOR_METATYPE_ALBUM, | ||
1819 | EXTRACTOR_METATYPE_COMMENT, | ||
1820 | EXTRACTOR_METATYPE_SUBJECT, | ||
1821 | EXTRACTOR_METATYPE_KEYWORDS, | ||
1822 | -1); | ||
1823 | if (desc == NULL) | ||
1824 | desc = GNUNET_strdup (_("no description supplied")); | ||
1825 | else | ||
1826 | { | ||
1827 | char *utf8_desc = NULL; | ||
1828 | |||
1829 | utf8_desc = | ||
1830 | GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, | ||
1831 | strlen (desc) + 1); | ||
1832 | GNUNET_free (desc); | ||
1833 | if (utf8_desc != NULL) | ||
1834 | desc = utf8_desc; | ||
1835 | else | ||
1836 | desc = NULL; | ||
1837 | } | ||
1838 | if (uri == NULL) | ||
1839 | uris = GNUNET_strdup (_("no URI")); | ||
1840 | else | ||
1841 | uris = GNUNET_FS_uri_to_string (uri); | ||
1842 | |||
1843 | pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta); | ||
1844 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | ||
1845 | sr->result = result; | ||
1846 | sr->tab = tab; | ||
1847 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1848 | "Allocated a search result SR=%p\n", sr); | ||
1849 | if (parent_rr != NULL) | ||
1850 | { | ||
1851 | /* get piter from parent */ | ||
1852 | path = gtk_tree_row_reference_get_path (parent_rr); | ||
1853 | tm = gtk_tree_row_reference_get_model (parent_rr); | ||
1854 | if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tm), &pmem, path)) | ||
1855 | { | ||
1856 | GNUNET_break (0); | ||
1857 | gtk_tree_path_free (path); | ||
1858 | /* desperate measure: make top-level entry */ | ||
1859 | pitr = NULL; | ||
1860 | } | ||
1861 | else | ||
1862 | { | ||
1863 | pitr = &pmem; | ||
1864 | } | ||
1865 | ts = GTK_TREE_STORE (tm); | ||
1866 | } | ||
1867 | else | ||
1868 | { | ||
1869 | /* top-level result */ | ||
1870 | pitr = NULL; | ||
1871 | ts = tab->ts; | ||
1872 | } | ||
1873 | gtk_tree_store_insert_with_values (ts, iter, pitr, G_MAXINT, 0, | ||
1874 | GNUNET_CONTAINER_meta_data_duplicate | ||
1875 | (meta), 1, | ||
1876 | (uri == | ||
1877 | NULL) ? NULL : GNUNET_FS_uri_dup (uri), 2, | ||
1878 | (uri == NULL) ? 0 : fsize, 3, | ||
1879 | pixbuf /* preview */ , | ||
1880 | 4, 0 /* percent progress */ , | ||
1881 | 5, 0 /* percent availability */ , | ||
1882 | 6, desc /* filename/description */ , | ||
1883 | 7, uris, 8, status_colour, 9, sr, 10, mime, | ||
1884 | 11, applicability_rank, 12, | ||
1885 | 0 /* avail-cert */ , | ||
1886 | 13, 0, /* avail-rank */ | ||
1887 | 14, (guint64) 0, /* completed */ | ||
1888 | 15, NULL, /* downloaded_filename */ | ||
1889 | 16, -1, /* downloaded_anonymity */ | ||
1890 | -1); | ||
1891 | if (tab != NULL) | ||
1892 | { | ||
1893 | while (tab->parent != NULL) | ||
1894 | tab = tab->parent->tab; | ||
1895 | tab->num_results++; | ||
1896 | } | ||
1897 | if (pixbuf != NULL) | ||
1898 | g_object_unref (pixbuf); | ||
1899 | GNUNET_free (uris); | ||
1900 | GNUNET_free_non_null (desc); | ||
1901 | GNUNET_free_non_null (mime); | ||
1902 | tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), iter); | ||
1903 | sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), tp); | ||
1904 | gtk_tree_path_free (tp); | ||
1905 | return sr; | ||
1906 | } | ||
1907 | |||
1908 | |||
1909 | static struct SearchResult * | ||
1910 | process_search_result (void *cls, struct SearchResult *parent, | ||
1911 | const struct GNUNET_FS_Uri *uri, | ||
1912 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1913 | struct GNUNET_FS_SearchResult *result, | ||
1914 | uint32_t applicability_rank) | ||
1915 | { | ||
1916 | struct SearchTab *tab = cls; | ||
1917 | struct SearchResult *sr; | ||
1918 | GtkTreeIter iter; | ||
1919 | |||
1920 | sr = GNUNET_GTK_add_search_result (tab, &iter, | ||
1921 | (parent != NULL) ? parent->rr : NULL, uri, | ||
1922 | meta, result, applicability_rank); | ||
1923 | update_search_label (tab); | ||
1924 | return sr; | ||
1925 | } | ||
1926 | |||
1927 | |||
1928 | /** | ||
1929 | * Setup a new top-level entry in the URI tab. If necessary, create | ||
1930 | * the URI tab first. | ||
1931 | * | ||
1932 | * @param iter set to the new entry | ||
1933 | * @param srp set to search result | ||
1934 | * @param meta metadata for the new entry | ||
1935 | * @param uri URI for the new entry | ||
1936 | * @return NULL on error, otherwise tree store matching iter | ||
1937 | */ | ||
1938 | struct SearchTab * | ||
1939 | GNUNET_GTK_add_to_uri_tab (GtkTreeIter * iter, struct SearchResult **srp, | ||
1940 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1941 | const struct GNUNET_FS_Uri *uri) | ||
1942 | { | ||
1943 | struct SearchResult *sr; | ||
1944 | GtkNotebook *notebook; | ||
1945 | gint page; | ||
1946 | |||
1947 | if (uri_tab == NULL) | ||
1948 | { | ||
1949 | uri_tab = setup_search (NULL, NULL); | ||
1950 | gtk_widget_set_visible (uri_tab->close_button, FALSE); | ||
1951 | gtk_widget_set_visible (uri_tab->pause_button, FALSE); | ||
1952 | } | ||
1953 | else | ||
1954 | { | ||
1955 | /* make 'utab' the current page */ | ||
1956 | notebook = | ||
1957 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
1958 | ("GNUNET_GTK_main_window_notebook")); | ||
1959 | for (page = 0; page < gtk_notebook_get_n_pages (notebook); page++) | ||
1960 | if (uri_tab->frame == gtk_notebook_get_nth_page (notebook, page)) | ||
1961 | { | ||
1962 | gtk_notebook_set_current_page (notebook, page); | ||
1963 | break; | ||
1964 | } | ||
1965 | } | ||
1966 | sr = GNUNET_GTK_add_search_result (uri_tab, iter, NULL, uri, meta, NULL, 0); | ||
1967 | |||
1968 | if (NULL != srp) | ||
1969 | *srp = sr; | ||
1970 | return uri_tab; | ||
1971 | } | ||
1972 | |||
1973 | |||
1974 | static struct SearchTab * | ||
1975 | handle_search_error (struct SearchTab *sr, const char *emsg) | ||
1976 | { | ||
1977 | /* FIXME: implement error handler */ | ||
1978 | GNUNET_break (0); | ||
1979 | return sr; | ||
1980 | } | ||
1981 | |||
1982 | |||
1983 | static struct SearchResult * | ||
1984 | update_search_result (struct SearchResult *sr, | ||
1985 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1986 | int32_t availability_rank, | ||
1987 | uint32_t availability_certainty, | ||
1988 | uint32_t applicability_rank) | ||
1989 | { | ||
1990 | GtkTreeIter iter; | ||
1991 | struct GNUNET_CONTAINER_MetaData *ometa; | ||
1992 | GtkTreeView *tv; | ||
1993 | GtkTreePath *tp; | ||
1994 | GtkTreeStore *ts; | ||
1995 | GtkTreeModel *tm; | ||
1996 | char *desc; | ||
1997 | char *mime; | ||
1998 | GdkPixbuf *pixbuf; | ||
1999 | guint percent_avail; | ||
2000 | GtkNotebook *notebook; | ||
2001 | gint page; | ||
2002 | |||
2003 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2004 | "Updating search result SR=%p with %d, %u, %u\n", | ||
2005 | sr, availability_rank, availability_certainty, applicability_rank); | ||
2006 | |||
2007 | if (sr == NULL) | ||
2008 | return NULL; | ||
2009 | desc = | ||
2010 | GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
2011 | EXTRACTOR_METATYPE_PACKAGE_NAME, | ||
2012 | EXTRACTOR_METATYPE_TITLE, | ||
2013 | EXTRACTOR_METATYPE_BOOK_TITLE, | ||
2014 | EXTRACTOR_METATYPE_FILENAME, | ||
2015 | EXTRACTOR_METATYPE_DESCRIPTION, | ||
2016 | EXTRACTOR_METATYPE_SUMMARY, | ||
2017 | EXTRACTOR_METATYPE_ALBUM, | ||
2018 | EXTRACTOR_METATYPE_COMMENT, | ||
2019 | EXTRACTOR_METATYPE_SUBJECT, | ||
2020 | EXTRACTOR_METATYPE_KEYWORDS, | ||
2021 | -1); | ||
2022 | if (desc == NULL) | ||
2023 | desc = GNUNET_strdup (_("no description supplied")); | ||
2024 | else | ||
2025 | { | ||
2026 | char *utf8_desc = NULL; | ||
2027 | |||
2028 | utf8_desc = | ||
2029 | GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, | ||
2030 | strlen (desc) + 1); | ||
2031 | GNUNET_free (desc); | ||
2032 | if (utf8_desc != NULL) | ||
2033 | desc = utf8_desc; | ||
2034 | else | ||
2035 | desc = NULL; | ||
2036 | } | ||
2037 | mime = | ||
2038 | GNUNET_CONTAINER_meta_data_get_first_by_types (meta, | ||
2039 | EXTRACTOR_METATYPE_MIMETYPE, | ||
2040 | EXTRACTOR_METATYPE_FORMAT, | ||
2041 | -1); | ||
2042 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2043 | "mime=`%s', desc=`%s'\n", mime, desc); | ||
2044 | pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta); | ||
2045 | tp = gtk_tree_row_reference_get_path (sr->rr); | ||
2046 | tm = gtk_tree_row_reference_get_model (sr->rr); | ||
2047 | ts = GTK_TREE_STORE (tm); | ||
2048 | gtk_tree_model_get_iter (tm, &iter, tp); | ||
2049 | gtk_tree_path_free (tp); | ||
2050 | gtk_tree_model_get (tm, &iter, 0, &ometa, -1); | ||
2051 | if (meta != NULL) | ||
2052 | GNUNET_CONTAINER_meta_data_destroy (ometa); | ||
2053 | if (availability_certainty > 0) | ||
2054 | percent_avail = | ||
2055 | (availability_certainty + | ||
2056 | availability_rank) * 50 / availability_certainty; | ||
2057 | else | ||
2058 | percent_avail = 0; | ||
2059 | gtk_tree_store_set (ts, &iter, 0, GNUNET_CONTAINER_meta_data_duplicate (meta), | ||
2060 | 3, pixbuf /* preview */ , | ||
2061 | 5, (guint) percent_avail /* percent availability */ , | ||
2062 | 6, desc /* filename/description */ , | ||
2063 | 10, mime, 11, (guint) applicability_rank, 12, | ||
2064 | (guint) availability_certainty, 13, | ||
2065 | (gint) availability_rank, -1); | ||
2066 | if (pixbuf != NULL) | ||
2067 | g_object_unref (pixbuf); | ||
2068 | GNUNET_free_non_null (desc); | ||
2069 | GNUNET_free_non_null (mime); | ||
2070 | |||
2071 | notebook = | ||
2072 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
2073 | ("GNUNET_GTK_main_window_notebook")); | ||
2074 | page = gtk_notebook_get_current_page (notebook); | ||
2075 | if (gtk_notebook_get_nth_page (notebook, page) == sr->tab->frame) | ||
2076 | { | ||
2077 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
2078 | (sr->tab->builder, "_search_result_frame")); | ||
2079 | |||
2080 | update_meta_data_views (tv, sr->tab); | ||
2081 | } | ||
2082 | return sr; | ||
2083 | } | ||
2084 | 2270 | ||
2085 | 2271 | ||
2086 | 2272 | ||
@@ -2226,6 +2412,10 @@ setup_publish (struct GNUNET_FS_PublishContext *pc, const char *fn, | |||
2226 | } | 2412 | } |
2227 | 2413 | ||
2228 | 2414 | ||
2415 | |||
2416 | |||
2417 | /* ***************** Master event handler ****************** */ | ||
2418 | |||
2229 | /** | 2419 | /** |
2230 | * Notification of FS to a client about the progress of an | 2420 | * Notification of FS to a client about the progress of an |
2231 | * operation. Callbacks of this type will be used for uploads, | 2421 | * operation. Callbacks of this type will be used for uploads, |
@@ -2260,16 +2450,13 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2260 | return ret; | 2450 | return ret; |
2261 | if (info->value.publish.specifics.resume.message != NULL) | 2451 | if (info->value.publish.specifics.resume.message != NULL) |
2262 | { | 2452 | { |
2263 | ret = | 2453 | handle_publish_error (ret, |
2264 | handle_publish_error (ret, | 2454 | info->value.publish.specifics.resume.message); |
2265 | info->value.publish.specifics.resume.message); | ||
2266 | } | 2455 | } |
2267 | else if (info->value.publish.specifics.resume.chk_uri != NULL) | 2456 | else if (info->value.publish.specifics.resume.chk_uri != NULL) |
2268 | { | 2457 | { |
2269 | ret = | 2458 | handle_publish_completed (ret, |
2270 | handle_publish_completed (ret, | 2459 | info->value.publish.specifics.resume.chk_uri); |
2271 | info->value.publish.specifics.resume. | ||
2272 | chk_uri); | ||
2273 | } | 2460 | } |
2274 | return ret; | 2461 | return ret; |
2275 | case GNUNET_FS_STATUS_PUBLISH_SUSPEND: | 2462 | case GNUNET_FS_STATUS_PUBLISH_SUSPEND: |
@@ -2280,12 +2467,13 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2280 | info->value.publish.size, | 2467 | info->value.publish.size, |
2281 | info->value.publish.completed); | 2468 | info->value.publish.completed); |
2282 | case GNUNET_FS_STATUS_PUBLISH_ERROR: | 2469 | case GNUNET_FS_STATUS_PUBLISH_ERROR: |
2283 | return handle_publish_error (info->value.publish.cctx, | 2470 | handle_publish_error (info->value.publish.cctx, |
2284 | info->value.publish.specifics.error.message); | 2471 | info->value.publish.specifics.error.message); |
2472 | return info->value.publish.cctx; | ||
2285 | case GNUNET_FS_STATUS_PUBLISH_COMPLETED: | 2473 | case GNUNET_FS_STATUS_PUBLISH_COMPLETED: |
2286 | return handle_publish_completed (info->value.publish.cctx, | 2474 | handle_publish_completed (info->value.publish.cctx, |
2287 | info->value.publish.specifics.completed. | 2475 | info->value.publish.specifics.completed.chk_uri); |
2288 | chk_uri); | 2476 | return info->value.publish.cctx; |
2289 | case GNUNET_FS_STATUS_PUBLISH_STOPPED: | 2477 | case GNUNET_FS_STATUS_PUBLISH_STOPPED: |
2290 | handle_publish_stop (info->value.publish.cctx); | 2478 | handle_publish_stop (info->value.publish.cctx); |
2291 | return NULL; | 2479 | return NULL; |
@@ -2313,7 +2501,7 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2313 | } | 2501 | } |
2314 | return ret; | 2502 | return ret; |
2315 | case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: | 2503 | case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: |
2316 | stop_download (info->value.download.cctx, GNUNET_YES); | 2504 | stop_download (info->value.download.cctx); |
2317 | return NULL; | 2505 | return NULL; |
2318 | case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: | 2506 | case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: |
2319 | return mark_download_progress (info->value.download.cctx, | 2507 | return mark_download_progress (info->value.download.cctx, |
@@ -2334,12 +2522,14 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2334 | info->value.download.size, | 2522 | info->value.download.size, |
2335 | info->value.download.filename); | 2523 | info->value.download.filename); |
2336 | case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: | 2524 | case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: |
2337 | stop_download (info->value.download.cctx, GNUNET_NO); | 2525 | stop_download (info->value.download.cctx); |
2338 | return NULL; | 2526 | return NULL; |
2339 | case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: | 2527 | case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: |
2340 | return change_download_colour (info->value.download.cctx, "yellow"); | 2528 | change_download_color (info->value.download.cctx, "yellow"); |
2529 | return info->value.download.cctx; | ||
2341 | case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: | 2530 | case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: |
2342 | return change_download_colour (info->value.download.cctx, "blue"); | 2531 | change_download_color (info->value.download.cctx, "blue"); |
2532 | return info->value.download.cctx; | ||
2343 | case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT: | 2533 | case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT: |
2344 | return download_lost_parent (info->value.download.cctx, | 2534 | return download_lost_parent (info->value.download.cctx, |
2345 | info->value.download.size, | 2535 | info->value.download.size, |
@@ -2353,9 +2543,8 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2353 | case GNUNET_FS_STATUS_SEARCH_RESUME: | 2543 | case GNUNET_FS_STATUS_SEARCH_RESUME: |
2354 | ret = setup_search (info->value.search.sc, info->value.search.query); | 2544 | ret = setup_search (info->value.search.sc, info->value.search.query); |
2355 | if (info->value.search.specifics.resume.message) | 2545 | if (info->value.search.specifics.resume.message) |
2356 | ret = | 2546 | handle_search_error (ret, |
2357 | handle_search_error (ret, | 2547 | info->value.search.specifics.resume.message); |
2358 | info->value.search.specifics.resume.message); | ||
2359 | return ret; | 2548 | return ret; |
2360 | case GNUNET_FS_STATUS_SEARCH_RESUME_RESULT: | 2549 | case GNUNET_FS_STATUS_SEARCH_RESUME_RESULT: |
2361 | ret = | 2550 | ret = |
@@ -2366,15 +2555,16 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2366 | result, | 2555 | result, |
2367 | info->value.search.specifics.resume_result. | 2556 | info->value.search.specifics.resume_result. |
2368 | applicability_rank); | 2557 | applicability_rank); |
2369 | return update_search_result (ret, | 2558 | update_search_result (ret, |
2370 | info->value.search.specifics.resume_result. | 2559 | info->value.search.specifics.resume_result. |
2371 | meta, | 2560 | meta, |
2372 | info->value.search.specifics.resume_result. | 2561 | info->value.search.specifics.resume_result. |
2373 | applicability_rank, | 2562 | applicability_rank, |
2374 | info->value.search.specifics.resume_result. | 2563 | info->value.search.specifics.resume_result. |
2375 | availability_certainty, | 2564 | availability_certainty, |
2376 | info->value.search.specifics.resume_result. | 2565 | info->value.search.specifics.resume_result. |
2377 | availability_rank); | 2566 | availability_rank); |
2567 | return ret; | ||
2378 | case GNUNET_FS_STATUS_SEARCH_SUSPEND: | 2568 | case GNUNET_FS_STATUS_SEARCH_SUSPEND: |
2379 | close_search_tab (info->value.search.cctx); | 2569 | close_search_tab (info->value.search.cctx); |
2380 | return NULL; | 2570 | return NULL; |
@@ -2390,17 +2580,19 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2390 | GNUNET_break (0); | 2580 | GNUNET_break (0); |
2391 | break; | 2581 | break; |
2392 | case GNUNET_FS_STATUS_SEARCH_UPDATE: | 2582 | case GNUNET_FS_STATUS_SEARCH_UPDATE: |
2393 | return update_search_result (info->value.search.specifics.update.cctx, | 2583 | update_search_result (info->value.search.specifics.update.cctx, |
2394 | info->value.search.specifics.update.meta, | 2584 | info->value.search.specifics.update.meta, |
2395 | info->value.search.specifics.update. | 2585 | info->value.search.specifics.update. |
2396 | applicability_rank, | 2586 | applicability_rank, |
2397 | info->value.search.specifics.update. | 2587 | info->value.search.specifics.update. |
2398 | availability_certainty, | 2588 | availability_certainty, |
2399 | info->value.search.specifics.update. | 2589 | info->value.search.specifics.update. |
2400 | availability_rank); | 2590 | availability_rank); |
2591 | return info->value.search.specifics.update.cctx; | ||
2401 | case GNUNET_FS_STATUS_SEARCH_ERROR: | 2592 | case GNUNET_FS_STATUS_SEARCH_ERROR: |
2402 | return handle_search_error (info->value.search.cctx, | 2593 | handle_search_error (info->value.search.cctx, |
2403 | info->value.search.specifics.error.message); | 2594 | info->value.search.specifics.error.message); |
2595 | return info->value.search.cctx; | ||
2404 | case GNUNET_FS_STATUS_SEARCH_PAUSED: | 2596 | case GNUNET_FS_STATUS_SEARCH_PAUSED: |
2405 | return info->value.search.cctx; | 2597 | return info->value.search.cctx; |
2406 | case GNUNET_FS_STATUS_SEARCH_CONTINUED: | 2598 | case GNUNET_FS_STATUS_SEARCH_CONTINUED: |
@@ -2443,48 +2635,4 @@ GNUNET_GTK_fs_event_handler (void *cls, | |||
2443 | } | 2635 | } |
2444 | 2636 | ||
2445 | 2637 | ||
2446 | /** | ||
2447 | * Page switched in main notebook, update thumbnail and | ||
2448 | * metadata views. | ||
2449 | */ | ||
2450 | void | ||
2451 | GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy, | ||
2452 | gpointer data) | ||
2453 | { | ||
2454 | GtkNotebook *notebook; | ||
2455 | gint page; | ||
2456 | GtkWidget *w; | ||
2457 | struct SearchTab *tab; | ||
2458 | GtkImage *image; | ||
2459 | GtkListStore *ms; | ||
2460 | GtkTreeView *tv; | ||
2461 | |||
2462 | notebook = | ||
2463 | GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object | ||
2464 | ("GNUNET_GTK_main_window_notebook")); | ||
2465 | page = gtk_notebook_get_current_page (notebook); | ||
2466 | w = gtk_notebook_get_nth_page (notebook, page); | ||
2467 | tab = search_tab_head; | ||
2468 | while (tab != NULL) | ||
2469 | { | ||
2470 | if (tab->frame == w) | ||
2471 | { | ||
2472 | tv = GTK_TREE_VIEW (gtk_builder_get_object | ||
2473 | (tab->builder, "_search_result_frame")); | ||
2474 | update_meta_data_views (tv, tab); | ||
2475 | return; | ||
2476 | } | ||
2477 | tab = tab->next; | ||
2478 | } | ||
2479 | image = | ||
2480 | GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object | ||
2481 | ("GNUNET_GTK_main_window_preview_image")); | ||
2482 | gtk_image_clear (image); | ||
2483 | ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object | ||
2484 | ("GNUNET_GTK_meta_data_list_store")); | ||
2485 | gtk_list_store_clear (ms); | ||
2486 | } | ||
2487 | |||
2488 | |||
2489 | |||
2490 | /* end of gnunet-fs-gtk-event_handler.c */ | 2638 | /* end of gnunet-fs-gtk-event_handler.c */ |
diff --git a/src/fs/gnunet-fs-gtk-event_handler.h b/src/fs/gnunet-fs-gtk-event_handler.h index fcca7cef..310ba97c 100644 --- a/src/fs/gnunet-fs-gtk-event_handler.h +++ b/src/fs/gnunet-fs-gtk-event_handler.h | |||
@@ -26,6 +26,10 @@ | |||
26 | #include "gnunet-fs-gtk-common.h" | 26 | #include "gnunet-fs-gtk-common.h" |
27 | 27 | ||
28 | 28 | ||
29 | /** | ||
30 | * State we keep for each (search) result entry in the | ||
31 | * tree view of a search tab. | ||
32 | */ | ||
29 | struct SearchResult; | 33 | struct SearchResult; |
30 | 34 | ||
31 | 35 | ||
@@ -54,31 +58,68 @@ struct SearchTab | |||
54 | */ | 58 | */ |
55 | struct GNUNET_FS_SearchContext *sc; | 59 | struct GNUNET_FS_SearchContext *sc; |
56 | 60 | ||
61 | /** | ||
62 | * Text of the search query. | ||
63 | */ | ||
57 | char *query_txt; | 64 | char *query_txt; |
58 | 65 | ||
66 | /** | ||
67 | * GtkBuilder object for the search tab. | ||
68 | */ | ||
59 | GtkBuilder *builder; | 69 | GtkBuilder *builder; |
60 | 70 | ||
71 | /** | ||
72 | * Frame instance of the search tab. | ||
73 | */ | ||
61 | GtkWidget *frame; | 74 | GtkWidget *frame; |
62 | 75 | ||
76 | /** | ||
77 | * The widget representing this search in the tab bar (not | ||
78 | * a GtkLabel, contains the actual label and the buttons). | ||
79 | */ | ||
63 | GtkWidget *tab_label; | 80 | GtkWidget *tab_label; |
64 | 81 | ||
82 | /** | ||
83 | * Button to stop and close the search. | ||
84 | */ | ||
65 | GtkWidget *close_button; | 85 | GtkWidget *close_button; |
66 | 86 | ||
87 | /** | ||
88 | * Button to clear all entries for downloads that have completed. | ||
89 | */ | ||
67 | GtkWidget *clear_button; | 90 | GtkWidget *clear_button; |
68 | 91 | ||
92 | /** | ||
93 | * Button to resume the search. | ||
94 | */ | ||
69 | GtkWidget *play_button; | 95 | GtkWidget *play_button; |
70 | 96 | ||
97 | /** | ||
98 | * Button to pause the search. | ||
99 | */ | ||
71 | GtkWidget *pause_button; | 100 | GtkWidget *pause_button; |
72 | 101 | ||
102 | /** | ||
103 | * Textual label in the 'tab_label' | ||
104 | */ | ||
73 | GtkLabel *label; | 105 | GtkLabel *label; |
74 | 106 | ||
107 | /** | ||
108 | * Tree store with the search results. | ||
109 | */ | ||
75 | GtkTreeStore *ts; | 110 | GtkTreeStore *ts; |
76 | 111 | ||
112 | /** | ||
113 | * Number of results we got for this search. | ||
114 | */ | ||
77 | unsigned int num_results; | 115 | unsigned int num_results; |
78 | 116 | ||
79 | }; | 117 | }; |
80 | 118 | ||
81 | 119 | ||
120 | /** | ||
121 | * Information we keep for each download. | ||
122 | */ | ||
82 | struct DownloadEntry | 123 | struct DownloadEntry |
83 | { | 124 | { |
84 | 125 | ||
@@ -156,14 +197,19 @@ GNUNET_GTK_add_to_uri_tab (GtkTreeIter * iter, struct SearchResult **sr, | |||
156 | /** | 197 | /** |
157 | * Add a search result to the given search tab. | 198 | * Add a search result to the given search tab. |
158 | * | 199 | * |
159 | * @param tab search tab to extend | 200 | * @param tab search tab to extend, never NULL |
160 | * @param iter set to position where search result is added | 201 | * @param iter set to position where search result is added (OUT only) |
161 | * @param parent_rr reference to parent entry in search tab | 202 | * @param parent_rr reference to parent entry in search tab, NULL for normal |
162 | * @param uri uri to add | 203 | * search results, |
204 | * @param uri uri to add, can be NULL for top-level entry of a directory opened from disk | ||
205 | * (in this case, we don't know the URI and should probably not | ||
206 | * bother to calculate it) | ||
163 | * @param meta metadata of the entry | 207 | * @param meta metadata of the entry |
164 | * @param result associated FS search result (can be NULL) | 208 | * @param result associated FS search result (can be NULL if this result |
209 | * was part of a directory) | ||
165 | * @param applicability_rank how relevant is the result | 210 | * @param applicability_rank how relevant is the result |
166 | * @return entry for the search result | 211 | * @return struct representing the search result (also stored in the tree |
212 | * model at 'iter') | ||
167 | */ | 213 | */ |
168 | struct SearchResult * | 214 | struct SearchResult * |
169 | GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter, | 215 | GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter, |