aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-01 11:50:19 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-01 11:50:19 +0000
commit937f070851bad5d125f70959cbbbd5fad939590d (patch)
tree0b910ec4da27642f3c4f75559a6e28b660c9d627
parente5a7fa50c8813dedd8130d0ae58d9d4a83660a6f (diff)
downloadgnunet-gtk-937f070851bad5d125f70959cbbbd5fad939590d.tar.gz
gnunet-gtk-937f070851bad5d125f70959cbbbd5fad939590d.zip
-more code cleanup, simplifications, bugfixes, etc.
-rw-r--r--src/fs/gnunet-fs-gtk-event_handler.c1840
-rw-r--r--src/fs/gnunet-fs-gtk-event_handler.h58
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 */
96struct SearchResult 97struct 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 */
747static void
748update_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 */
774static void
775close_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 */
813static void
814free_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
748static struct DownloadEntry * 851/**
749change_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 */
858static void
859update_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 */
906void
907GNUNET_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 */
950static void
951stop_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
770static struct PublishEntry * 970/**
771change_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 */
976static void
977pause_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 */
998static void
999continue_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 */
1025static void
1026clear_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 */
1067static void
1068handle_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 */
1083static char *
1084get_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 */
1121static char *
1122get_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 */
1141static void
1142update_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 */
1232struct SearchResult *
1233GNUNET_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 */
1371static struct SearchResult *
1372process_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 */
1398static struct SearchTab *
1399setup_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 */
1528static struct SearchTab *
1529setup_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 */
1562struct SearchTab *
1563GNUNET_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 */
1611static void
1612change_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 */
796static void 1645static void
797stop_download (struct DownloadEntry *de, int is_suspend) 1646stop_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
1023static struct PublishEntry *
1024mark_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 */
1308static void 2138static void
1309update_meta_data_views (GtkTreeView * tv, gpointer user_data) 2139change_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/** 2166static struct PublishEntry *
1352 * Update the label for a search 2167mark_publish_progress (struct PublishEntry *pe, uint64_t size,
1353 */ 2168 uint64_t completed)
1354static void
1355update_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 */
1377static void
1378close_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 */
1411static struct PublishEntry * 2197static void
1412handle_publish_completed (struct PublishEntry *ent, 2198handle_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 */
1424static struct PublishEntry * 2210static void
1425handle_publish_error (struct PublishEntry *ent, const char *emsg) 2211handle_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 */
1477static void
1478stop_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
1491static void
1492free_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 */
1538static void
1539clear_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 */
1568static void
1569pause_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 */
1585static void
1586continue_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 */
1602static void
1603closure_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 */
1616static struct SearchTab *
1617setup_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 */
1730static struct SearchTab *
1731setup_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 */
1764struct SearchResult *
1765GNUNET_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
1909static struct SearchResult *
1910process_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 */
1938struct SearchTab *
1939GNUNET_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
1974static struct SearchTab *
1975handle_search_error (struct SearchTab *sr, const char *emsg)
1976{
1977 /* FIXME: implement error handler */
1978 GNUNET_break (0);
1979 return sr;
1980}
1981
1982
1983static struct SearchResult *
1984update_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 */
2450void
2451GNUNET_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 */
29struct SearchResult; 33struct 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 */
82struct DownloadEntry 123struct 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 */
168struct SearchResult * 214struct SearchResult *
169GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter, 215GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter,