aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-fs-gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-fs-gtk.c')
-rw-r--r--src/fs/gnunet-fs-gtk.c415
1 files changed, 381 insertions, 34 deletions
diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c
index 67a7059f..3223ec7b 100644
--- a/src/fs/gnunet-fs-gtk.c
+++ b/src/fs/gnunet-fs-gtk.c
@@ -46,6 +46,7 @@ static struct GNUNET_FS_Handle *fs;
46 */ 46 */
47static struct EXTRACTOR_PluginList *plugins; 47static struct EXTRACTOR_PluginList *plugins;
48 48
49guint namespace_selector_window_leave_timeout_source = 0;
49 50
50/** 51/**
51 * Return handle for file-sharing operations. 52 * Return handle for file-sharing operations.
@@ -129,44 +130,389 @@ void
129GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy, gpointer data); 130GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy, gpointer data);
130 131
131 132
133void
134main_window_search_namespace_dropdown_button_toggled_cb (GtkToggleButton *togglebutton,
135 gpointer user_data)
136{
137 gboolean active;
138 GtkBuilder *builder = GTK_BUILDER (user_data);
139 GtkWidget *namespace_selector_window;
140 namespace_selector_window = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_window"));
141 g_object_get (G_OBJECT (togglebutton), "active", &active, NULL);
142 if (active)
143 {
144 GtkAllocation togglebutton_allocation;
145 GdkWindow *main_window_gdk;
146 gint mwg_x, mwg_y, tgb_x, tgb_y, popup_x, popup_y;
147
148 gtk_widget_get_allocation (GTK_WIDGET (togglebutton), &togglebutton_allocation);
149
150 main_window_gdk = gtk_widget_get_window (GTK_WIDGET (togglebutton));
151
152 gdk_window_get_origin (main_window_gdk, &mwg_x, &mwg_y);
153
154 /* FIXME: this might become a problem in other window managers,
155 * where reference point is not in the top-left corner.
156 * We want to show the window below the button.
157 */
158 tgb_x = mwg_x + togglebutton_allocation.x;
159 tgb_y = mwg_y + togglebutton_allocation.y;
160 popup_x = tgb_x;
161 popup_y = tgb_y + togglebutton_allocation.height;
162
163 gtk_window_move (GTK_WINDOW (namespace_selector_window), popup_x, popup_y);
164
165 gtk_widget_show (namespace_selector_window);
166 }
167 else
168 gtk_widget_hide (namespace_selector_window);
169}
170
171gboolean
172namespace_selector_window_leave_timeout_cb (gpointer user_data)
173{
174 GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (user_data);
175 /* This will eventually hide the namespace selector */
176 gtk_toggle_button_set_active (toggle_button, FALSE);
177 return FALSE;
178}
179
180gboolean
181main_window_search_namespace_dropdown_button_enter_notify_event_cb (
182 GtkWidget *widget, GdkEvent *event, gpointer user_data)
183{
184 if (namespace_selector_window_leave_timeout_source > 0)
185 g_source_remove (namespace_selector_window_leave_timeout_source);
186 return FALSE;
187}
188
189
190gboolean
191namespace_selector_window_leave_notify_event_cb (GtkWidget *widget,
192 GdkEvent *event, gpointer user_data)
193{
194 GtkBuilder *builder;
195 GtkToggleButton *toggle_button;
196 guint timeout_id;
197
198 builder = GTK_BUILDER (user_data);
199
200 toggle_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "main_window_search_namespace_dropdown_button"));
201
202 /* Place a timeout to hide the window. It will be cancelled if the cursor
203 * enters the namespace selector window or the toggle button within 100ms.
204 */
205 timeout_id = g_timeout_add (100, &namespace_selector_window_leave_timeout_cb, toggle_button);
206 if (namespace_selector_window_leave_timeout_source > 0)
207 g_source_remove (namespace_selector_window_leave_timeout_source);
208 namespace_selector_window_leave_timeout_source = timeout_id;
209
210 return FALSE;
211}
212
213gboolean
214GNUNET_GTK_get_tree_string (GtkTreeView *treeview, GtkTreePath *treepath,
215 guint column, gchar **value)
216{
217 gboolean ok;
218 GtkTreeModel *model;
219
220 model = gtk_tree_view_get_model (treeview);
221 if (!model)
222 return FALSE;
223
224 GtkTreeIter iter;
225 ok = gtk_tree_model_get_iter (model, &iter, treepath);
226 if (!ok)
227 return FALSE;
228
229 *value = NULL;
230 gtk_tree_model_get (model, &iter, column, value, -1);
231 if (*value == NULL)
232 return FALSE;
233 return TRUE;
234}
235
236gboolean
237get_selected_anonymity_level (GtkBuilder *builder, guint *p_level)
238{
239 GtkComboBox *combo;
240 GtkTreeIter iter;
241 GtkTreeModel *model;
242 guint level;
243
244 combo = GTK_COMBO_BOX(gtk_builder_get_object (builder,
245 "main_window_search_anonymity_combobox"));
246 if (!combo)
247 return FALSE;
248
249 if (!gtk_combo_box_get_active_iter (combo, &iter))
250 return FALSE;
251
252 model = gtk_combo_box_get_model (combo);
253 if (!model)
254 return FALSE;
255
256 gtk_tree_model_get (model, &iter, 1, &level, -1);
257 if (p_level)
258 *p_level = level;
259 return TRUE;
260}
261
262gboolean
263get_selected_namespace_treepath_iter_model_widget (GtkBuilder *builder,
264 GtkTreePath **p_treepath, GtkTreeIter *p_iter, GtkTreeModel **p_model,
265 GtkWidget **p_widget)
266{
267 GtkTreeSelection *selection;
268 GtkTreeModel *model;
269 GList *selected;
270 GtkTreePath *treepath;
271 GtkWidget *widget;
272
273 widget = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_treeview"));
274 if (!widget)
275 return FALSE;
276
277 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
278 model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
279 if (!selection || !model)
280 return FALSE;
281
282 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
283 if (!selected)
284 return FALSE;
285 if (selected->data == NULL)
286 {
287 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
288 g_list_free (selected);
289 return FALSE;
290 }
291 /* Free everything except the first path, keep it */
292 treepath = (GtkTreePath *) selected->data;
293 selected = g_list_remove (selected, selected->data);
294 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
295 g_list_free (selected);
296
297 if (p_iter && !gtk_tree_model_get_iter (model, p_iter, treepath))
298 {
299 gtk_tree_path_free (treepath);
300 return FALSE;
301 }
302 *p_treepath = treepath;
303 if (p_model)
304 *p_model = model;
305 if (p_widget)
306 *p_widget = widget;
307 return TRUE;
308}
309
310void
311namespace_selector_treeview_cursor_changed_cb (GtkWidget *widget,
312 gpointer user_data)
313{
314 GtkBuilder *builder;
315 GtkToggleButton *toggle_button;
316 GtkLabel *sel_namespace_label;
317 gchar *value;
318 GtkTreePath *treepath;
319
320 builder = GTK_BUILDER (user_data);
321
322 if (!get_selected_namespace_treepath_iter_model_widget (builder, &treepath, NULL, NULL, NULL))
323 return;
324
325 toggle_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "main_window_search_namespace_dropdown_button"));
326 if (!toggle_button)
327 return;
328
329 sel_namespace_label = GTK_LABEL (gtk_builder_get_object (builder, "main_window_search_selected_namespace_label"));
330 if (!sel_namespace_label)
331 return;
332
333 if (GNUNET_GTK_get_tree_string (GTK_TREE_VIEW (widget), treepath, 0,
334 &value))
335 gtk_label_set_text (sel_namespace_label, value);
336
337 gtk_tree_path_free (treepath);
338
339 /* This will eventually hide the namespace selector */
340 gtk_toggle_button_set_active (toggle_button, FALSE);
341}
342
343void
344main_window_search_button_clicked_cb (GtkButton *button, gpointer user_data)
345{
346 GtkBuilder *builder;
347 GtkTreePath *namespace_treepath = NULL;
348 GtkTreeModel *namespace_model = NULL;
349 GtkComboBox *mime_combo;
350 GtkTreeModel *mime_model;
351 GtkEntry *query_entry;
352 guint anonymity_level;
353 GtkTreeIter iter;
354 const char *entry_keywords;
355 gchar *keywords;
356 gchar *mime_keyword;
357
358 GNUNET_HashCode *nsid = NULL;
359 struct GNUNET_FS_Uri *uri;
360 char *emsg;
361
362 builder = GTK_BUILDER (user_data);
363
364 if (!get_selected_anonymity_level (builder, &anonymity_level))
365 return;
366
367 mime_combo = GTK_COMBO_BOX (GNUNET_FS_GTK_get_main_window_object
368 ("main_window_search_mime_combobox"));
369 mime_model = gtk_combo_box_get_model (mime_combo);
370 if (mime_model && gtk_combo_box_get_active_iter (mime_combo, &iter))
371 {
372 mime_keyword = NULL;
373 gtk_tree_model_get (mime_model, &iter, 0, &mime_keyword, -1);
374 }
375
376 get_selected_namespace_treepath_iter_model_widget (builder,
377 &namespace_treepath, &iter, &namespace_model, NULL);
378
379 query_entry = GTK_ENTRY (gtk_builder_get_object (builder,
380 "main_window_search_entry"));
381
382 entry_keywords = gtk_entry_get_text (query_entry);
383 if (mime_keyword != NULL)
384 {
385 keywords = g_strdup_printf ("%s %s", entry_keywords, mime_keyword);
386 g_free (mime_keyword);
387 }
388 else
389 keywords = g_strdup (entry_keywords);
390 if (namespace_treepath != NULL)
391 gtk_tree_model_get (namespace_model, &iter, 1, &nsid, -1);
392 if (nsid != NULL)
393 {
394 uri = GNUNET_FS_uri_sks_create_from_nsid (nsid, keywords);
395 GNUNET_assert (uri != NULL);
396 }
397 else
398 {
399 emsg = NULL;
400 uri = GNUNET_FS_uri_ksk_create (keywords, &emsg);
401 if (uri == NULL)
402 {
403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
404 _("Invalid keyword string `%s': %s"), keywords, emsg);
405 GNUNET_free_non_null (emsg);
406 return;
407 }
408 }
409 GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (), uri,
410 anonymity_level, GNUNET_FS_SEARCH_OPTION_NONE, NULL);
411
412 g_free (keywords);
413 GNUNET_FS_uri_destroy (uri);
414}
415
132/** 416/**
133 * Add the tab with the 'new' icon for starting a search. 417 * Add pseudonym data to tree store
418 *
419 * @param cls closure (the 'GtkListStore')
420 * @param pseudonym hash code of public key of pseudonym
421 * @param md meta data known about the pseudonym
422 * @param rating the local rating of the pseudonym
423 * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
134 */ 424 */
135static void 425static int
136add_new_tab () 426add_namespace_to_ts (void *cls, const GNUNET_HashCode * pseudonym,
427 const struct GNUNET_CONTAINER_MetaData *md, int rating)
137{ 428{
138 GtkNotebook *notebook; 429 GtkTreeStore *ts = cls;
139 GtkWindow *sf; 430 char *root;
140 gint pages; 431 char *ns_name;
141 GtkBuilder *builder; 432 GNUNET_HashCode *nsid;
142 GtkWidget *label; 433 char *description;
143 GtkWidget *frame; 434 char *uris;
144 435 char *emsg;
145 builder = 436 struct GNUNET_FS_Uri *uri;
146 GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_main_tab_new_frame.glade"); 437 GtkTreeIter iter;
147 438
148 /* load frame */ 439 ns_name =
149 sf = GTK_WINDOW (gtk_builder_get_object (builder, "_main_tab_new_frame")); 440 GNUNET_PSEUDONYM_id_to_name (GNUNET_FS_GTK_get_configuration (),
150 label = gtk_bin_get_child (GTK_BIN (sf)); 441 pseudonym);
151 g_object_ref (G_OBJECT (label)); 442 nsid = GNUNET_malloc (sizeof (GNUNET_HashCode));
152 gtk_container_remove (GTK_CONTAINER (sf), label); 443 *nsid = *pseudonym;
153 gtk_widget_destroy (GTK_WIDGET (sf)); 444 root = NULL;
154 g_object_unref (builder); 445 uris = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_URI);
155 g_signal_connect (G_OBJECT (label), "clicked", 446 if (uris != NULL)
156 G_CALLBACK (&GNUNET_GTK_main_menu_file_search_activate_cb), 447 {
157 NULL); 448 emsg = NULL;
158 449 uri = GNUNET_FS_uri_parse (uris, &emsg);
159 notebook = 450 if (uri == NULL)
160 GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object 451 GNUNET_free (emsg);
161 ("GNUNET_GTK_main_window_notebook")); 452 root = GNUNET_FS_uri_sks_get_content_id (uri);
162 pages = gtk_notebook_get_n_pages (notebook); 453 GNUNET_FS_uri_destroy (uri);
163 frame = gtk_label_new (""); 454 }
164 gtk_widget_show (frame); 455 description =
165 gtk_notebook_append_page (notebook, frame, label); 456 GNUNET_CONTAINER_meta_data_get_first_by_types (md,
166 gtk_notebook_set_current_page (notebook, pages); 457 EXTRACTOR_METATYPE_TITLE,
167 gtk_widget_show (GTK_WIDGET (notebook)); 458 EXTRACTOR_METATYPE_BOOK_TITLE,
459 EXTRACTOR_METATYPE_DESCRIPTION,
460 EXTRACTOR_METATYPE_SUMMARY,
461 EXTRACTOR_METATYPE_ALBUM,
462 EXTRACTOR_METATYPE_COMMENT,
463 EXTRACTOR_METATYPE_SUBJECT,
464 EXTRACTOR_METATYPE_KEYWORDS,
465 -1);
466 gtk_tree_store_insert_with_values (ts, &iter, NULL, G_MAXINT, 0, ns_name, 1,
467 nsid, 2, root, 3, description, -1);
468 GNUNET_free (ns_name);
469 GNUNET_free_non_null (root);
470 GNUNET_free_non_null (description);
471 return GNUNET_OK;
168} 472}
169 473
474void
475GNUNET_GTK_main_window_realize_cb (GtkWidget *widget, gpointer user_data)
476{
477 GtkTreeIter iter;
478 GtkTreeView *namespace_tree;
479 GtkTreeStore *namespace_treestore;
480 GtkBuilder *builder;
481 GtkWidget *namespace_selector_window;
482
483 builder = GTK_BUILDER (user_data);
484
485 namespace_treestore = GTK_TREE_STORE (GNUNET_FS_GTK_get_main_window_object
486 ("main_window_search_namespace_treestore"));
487 namespace_tree = GTK_TREE_VIEW (GNUNET_FS_GTK_get_main_window_object
488 ("namespace_selector_treeview"));
489
490 gtk_tree_store_insert_with_values (namespace_treestore, &iter, NULL,
491 G_MAXINT, 0, "Any", 1, NULL, 2, "", 3,
492 "Do not search in any particular namespace", -1);
493 GNUNET_PSEUDONYM_list_all (GNUNET_FS_GTK_get_configuration (),
494 &add_namespace_to_ts, namespace_treestore);
495
496 /* FIXME: read currently selected namespace from somewhere instead of selecting 0th item */
497 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (namespace_treestore), &iter))
498 {
499 gchar *value;
500 GtkLabel *sel_namespace_label;
501 GtkTreePath *treepath = gtk_tree_path_new_first ();
502 gtk_tree_selection_select_iter (gtk_tree_view_get_selection (
503 namespace_tree), &iter);
504 sel_namespace_label = GTK_LABEL (gtk_builder_get_object (builder, "main_window_search_selected_namespace_label"));
505 if (GNUNET_GTK_get_tree_string (namespace_tree, treepath, 0, &value))
506 gtk_label_set_text (sel_namespace_label, value);
507 gtk_tree_path_free (treepath);
508 }
509
510 /* How the window (to trigger certain events) and immediately hide it */
511 namespace_selector_window = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_window"));
512 gtk_widget_show (namespace_selector_window);
513 gtk_widget_hide (namespace_selector_window);
514
515}
170 516
171/** 517/**
172 * Actual main function run right after GNUnet's scheduler 518 * Actual main function run right after GNUnet's scheduler
@@ -201,7 +547,8 @@ run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
201 GNUNET_FS_OPTIONS_END); 547 GNUNET_FS_OPTIONS_END);
202 if (fs != NULL) 548 if (fs != NULL)
203 { 549 {
204 add_new_tab (); 550 /* Searches are now started from the search bar */
551 /* add_new_tab (); */
205 } 552 }
206 else 553 else
207 { 554 {