From d044af68ba86eb0df8b8279242cc80a02d5f5e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?= =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Sun, 11 Dec 2011 05:52:19 +0400 Subject: [PATCH 4/6] New search bar in the main window --- contrib/gnunet_fs_gtk_main_window.glade | 496 ++++++++++++++++++++--- contrib/gnunet_fs_gtk_search_tab.glade | 202 +++++---- src/fs/gnunet-fs-gtk-main_window_view_toggles.c | 9 + src/fs/gnunet-fs-gtk.c | 323 +++++++++++++++ 4 files changed, 883 insertions(+), 147 deletions(-) diff --git a/contrib/gnunet_fs_gtk_main_window.glade b/contrib/gnunet_fs_gtk_main_window.glade index cb0b276..799c1b1 100644 --- a/contrib/gnunet_fs_gtk_main_window.glade +++ b/contrib/gnunet_fs_gtk_main_window.glade @@ -1,55 +1,119 @@ - + - + + + + + + + + + + + + + True - gtk-go-down + False + gtk-go-up + + + True + False + gtk-new True + False gtk-find - + True - gtk-open + False + gtk-go-down - + True - gtk-new + False + gtk-index - - True - gtk-go-up + + + + + + + + + + + + None + 0 + #AAAA00000000 + + + Normal + 1 + #000000000000 + + + Paranoid + 10 + #0000AAAA0000 + + + False gnunet-fs-gtk center 700 500 gnunet-gtk + True + False + + + True + False + 2 + + + False + True + end + 0 + + True + False - True False + True + False _File sharing True True + False _Create pseudonym + False True + False Create a pseudonym for publishing content. Note that you can also publish content anonymously (without using a pseudonym). - False <gnunet-fs-gtk>/File sharing/Create pseudonym True image3 @@ -61,8 +125,9 @@ _Advertise Pseudonym - True False + True + False True image6 False @@ -72,9 +137,10 @@ _Publish + False True + False Publish files or directories on GNUnet - False <gnunet-fs-gtk>/File sharing/Publish True image2 @@ -85,16 +151,18 @@ - True False + True + False _Search + False True + False Search GNUnet for files - False <gnunet-fs-gtk>/File sharing/Search True image4 @@ -105,16 +173,18 @@ - True False + True + False _Download + False True + False Download a file or directory with a known URI. - False <gnunet-fs-gtk>/File sharing/Download True image5 @@ -126,9 +196,10 @@ _Open GNUnet directory + False True + False Use this option to browse a GNUnet directory file that has been previously downloaded. - False <gnunet-fs-gtk>/File sharing/Open directory True image1 @@ -139,16 +210,18 @@ - True False + True + False gtk-quit + False True + False Exit gnunet-fs-gtk. Active file-sharing operations will resume upon restart. - False <gnunet-fs-gtk>/Quit True True @@ -163,17 +236,20 @@ False + False _Edit True True + False gtk-preferences + False True + False Edit the system configuration. - False <gnunet-fs-gtk>/Edit/Preferences True True @@ -185,18 +261,21 @@ - True False + True + False _View True True + False + False True + False Show meta data in main window - False Metadata True True @@ -205,34 +284,50 @@ + False True + False Show preview (when available) - False Preview True True + + + False + True + False + Show search box in main window + Search + True + True + + + - True False + True + False _Help True True + False gtk-about + False True + False Display information about this version of gnunet-fs-gtk - False <gnunet-fs-gtk>/Help/About True True @@ -252,11 +347,13 @@ + False icons - True False + True + False _Search True gtk-find @@ -274,8 +371,203 @@ + + True + False + 3 + 4 + + + True + False + Namespace: + + + False + False + 0 + + + + + True + False + 0 + + + <none> + False + True + True + True + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK + image10 + right + + + + + + + + False + False + 1 + + + + + True + False + Query: + + + False + False + 2 + + + + + True + True + + True + gtk-find + True + False + True + True + + + True + True + 3 + + + + + True + False + Anonymity: + + + False + False + 4 + + + + + True + False + 0 + + + True + False + main_window_search_anonymity_liststore + 1 + + + + 2 + 0 + + + + + + 1 + + + + + + + False + False + 5 + + + + + True + False + Type: + + + False + False + 6 + + + + + True + False + 0 + 0 + + + True + False + main_window_search_mime_liststore + 0 + + + + 0 + + + + + + 1 + + + + + + + False + False + 7 + + + + + True + False + 0 + + + Find! + False + True + True + True + + + + + + False + False + 8 + + + + + False + False + 3 + + + True + False True @@ -292,6 +584,7 @@ True + False False @@ -302,12 +595,14 @@ True + False 128 128 True False + False True Thumbnail associated with the currently selected content 256 @@ -389,36 +684,12 @@ True True - 3 - - - - - True - 2 - - - False - True - end - 0 + 4 - - - - - - - - - - - - @@ -433,10 +704,6 @@ - - True - gtk-index - 100 1 @@ -461,4 +728,119 @@ 10 10 + + True + False + gtk-open + + + True + False + gtk-index + + + True + False + gtk-index + + + True + False + gtk-index + + + True + False + gtk-index + + + + + + + + + + + + Any + + + plain/text + Text + + + application/zip + Zip + + + audio/mpeg + MPEG audio + + + + + + + + + + + + + + + + + False + GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK + popup + False + dropdown-menu + True + True + True + False + False + GNUNET_GTK_main_window + False + + + + + True + True + main_window_search_namespace_treestore + False + 0 + True + 3 + + + + autosize + Name + + + + 0 + + + + + + + autosize + Key + + + + 2 + + + + + + + diff --git a/contrib/gnunet_fs_gtk_search_tab.glade b/contrib/gnunet_fs_gtk_search_tab.glade index 38c0c38..9a8fa61 100644 --- a/contrib/gnunet_fs_gtk_search_tab.glade +++ b/contrib/gnunet_fs_gtk_search_tab.glade @@ -35,125 +35,143 @@ + False + popup You should never see this - - - 100 - True - True - automatic - automatic - + True + True + False + False + False - + + 100 True True - GNUNET_GTK_file_sharing_result_tree_store - True - horizontal - True + automatic + automatic - - True - autosize - Description - True - True + + True + True + GNUNET_GTK_file_sharing_result_tree_store True - True - 6 + horizontal + True - - - 8 - 6 - 5 - + + True + autosize + Description + True + True + True + True + 6 + + + + 8 + 6 + 5 + + + - - - - - autosize - Format - True - True - True - 10 - - - 8 - 10 - + + autosize + Format + True + True + True + 10 + + + + 8 + 10 + + + - - - - - autosize - Size - True - True - 2 - - - 8 - 2 - 4 - + + autosize + Size + True + True + 2 + + + + 8 + 2 + 4 + + + - - - - - autosize - # - True - True - descending - 11 - - - 8 - 11 - + + autosize + # + True + True + descending + 11 + + + + 8 + 11 + + + - - - - - 128 - 128 - Preview - True - - - 3 - + + 128 + 128 + Preview + True + + + + 3 + + + - - + False + popup + You shouldn't see this also + dock + True + True + False + False + False True + False 5 30 True + False query + True False 5 0 @@ -161,12 +179,13 @@ + False True True - False True + False gtk-media-play 2 @@ -180,13 +199,14 @@ + False True True True - False True + False gtk-media-pause 2 @@ -200,13 +220,14 @@ + False True True True - False True + False gtk-clear @@ -220,14 +241,15 @@ + False True True True - False half True + False gtk-close 2 diff --git a/src/fs/gnunet-fs-gtk-main_window_view_toggles.c b/src/fs/gnunet-fs-gtk-main_window_view_toggles.c index 975a1be..9b73cac 100644 --- a/src/fs/gnunet-fs-gtk-main_window_view_toggles.c +++ b/src/fs/gnunet-fs-gtk-main_window_view_toggles.c @@ -71,5 +71,14 @@ GNUNET_GTK_main_menu_view_metadata_toggled_cb (GtkWidget * dummy, gpointer data) "GNUNET_GTK_main_menu_view_metadata"); } +/** + * Preview view is toggled. + */ +void +GNUNET_GTK_main_menu_view_search_toggled_cb (GtkWidget * dummy, gpointer data) +{ + toggle_view ("main_window_search_hbox", + "GNUNET_GTK_main_menu_search_preview"); +} /* end of gnunet-fs-gtk-main_window_view_toggles.c */ diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c index 67a7059..68c6be6 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; */ static struct EXTRACTOR_PluginList *plugins; +guint namespace_selector_window_leave_timeout_source = 0; /** * Return handle for file-sharing operations. @@ -167,6 +168,328 @@ add_new_tab () gtk_widget_show (GTK_WIDGET (notebook)); } +void +main_window_search_namespace_dropdown_button_toggled_cb (GtkToggleButton *togglebutton, + gpointer user_data) +{ + gboolean active; + GtkBuilder *builder = GTK_BUILDER (user_data); + GtkWidget *namespace_selector_window; + namespace_selector_window = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_window")); + g_object_get (G_OBJECT (togglebutton), "active", &active, NULL); + if (active) + { + GtkAllocation togglebutton_allocation; + GdkWindow *main_window_gdk; + gint mwg_x, mwg_y, tgb_x, tgb_y, popup_x, popup_y; + + gtk_widget_get_allocation (GTK_WIDGET (togglebutton), &togglebutton_allocation); + + main_window_gdk = gtk_widget_get_window (GTK_WIDGET (togglebutton)); + + gdk_window_get_origin (main_window_gdk, &mwg_x, &mwg_y); + + /* FIXME: this might become a problem in other window managers, + * where reference point is not in the top-left corner. + * We want to show the window below the button. + */ + tgb_x = mwg_x + togglebutton_allocation.x; + tgb_y = mwg_y + togglebutton_allocation.y; + popup_x = tgb_x; + popup_y = tgb_y + togglebutton_allocation.height; + + gtk_window_move (GTK_WINDOW (namespace_selector_window), popup_x, popup_y); + + gtk_widget_show (namespace_selector_window); + } + else + gtk_widget_hide (namespace_selector_window); +} + +gboolean +namespace_selector_window_leave_timeout_cb (gpointer user_data) +{ + GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (user_data); + /* This will eventually hide the namespace selector */ + gtk_toggle_button_set_active (toggle_button, FALSE); + return FALSE; +} + +gboolean +main_window_search_namespace_dropdown_button_enter_notify_event_cb ( + GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + if (namespace_selector_window_leave_timeout_source > 0) + g_source_remove (namespace_selector_window_leave_timeout_source); + return FALSE; +} + + +gboolean +namespace_selector_window_leave_notify_event_cb (GtkWidget *widget, + GdkEvent *event, gpointer user_data) +{ + GtkBuilder *builder; + GtkToggleButton *toggle_button; + guint timeout_id; + + builder = GTK_BUILDER (user_data); + + toggle_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "main_window_search_namespace_dropdown_button")); + + /* Place a timeout to hide the window. It will be cancelled if the cursor + * enters the namespace selector window or the toggle button within 100ms. + */ + timeout_id = g_timeout_add (100, &namespace_selector_window_leave_timeout_cb, toggle_button); + if (namespace_selector_window_leave_timeout_source > 0) + g_source_remove (namespace_selector_window_leave_timeout_source); + namespace_selector_window_leave_timeout_source = timeout_id; + + return FALSE; +} + +gboolean +GNUNET_GTK_get_tree_string (GtkTreeView *treeview, GtkTreePath *treepath, + guint column, gchar **value) +{ + gboolean ok; + GtkTreeModel *model; + + model = gtk_tree_view_get_model (treeview); + if (!model) + return FALSE; + + GtkTreeIter iter; + ok = gtk_tree_model_get_iter (model, &iter, treepath); + if (!ok) + return FALSE; + + *value = NULL; + gtk_tree_model_get (model, &iter, column, value, -1); + if (*value == NULL) + return FALSE; + return TRUE; +} + +gboolean +get_selected_anonymity_level (GtkBuilder *builder, guint *p_level) +{ + GtkComboBox *combo; + GtkTreeIter iter; + GtkTreeModel *model; + guint level; + + combo = GTK_COMBO_BOX(gtk_builder_get_object (builder, + "main_window_search_anonymity_combobox")); + if (!combo) + return FALSE; + + if (!gtk_combo_box_get_active_iter (combo, &iter)) + return FALSE; + + model = gtk_combo_box_get_model (combo); + if (!model) + return FALSE; + + gtk_tree_model_get (model, &iter, 1, &level, -1); + if (p_level) + *p_level = level; + return TRUE; +} + +gboolean +get_selected_namespace_treepath_iter_model_widget (GtkBuilder *builder, + GtkTreePath **p_treepath, GtkTreeIter *p_iter, GtkTreeModel **p_model, + GtkWidget **p_widget) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GList *selected; + GtkTreePath *treepath; + GtkWidget *widget; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_treeview")); + if (!widget) + return FALSE; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + if (!selection || !model) + return FALSE; + + selected = gtk_tree_selection_get_selected_rows (selection, NULL); + if (!selected) + return FALSE; + if (selected->data == NULL) + { + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); + return FALSE; + } + /* Free everything except the first path, keep it */ + treepath = (GtkTreePath *) selected->data; + selected = g_list_remove (selected, selected->data); + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); + + if (p_iter && !gtk_tree_model_get_iter (model, p_iter, treepath)) + { + gtk_tree_path_free (treepath); + return FALSE; + } + *p_treepath = treepath; + if (p_model) + *p_model = model; + if (p_widget) + *p_widget = widget; + return TRUE; +} + +void +namespace_selector_treeview_cursor_changed_cb (GtkWidget *widget, + gpointer user_data) +{ + GtkBuilder *builder; + GtkToggleButton *toggle_button; + gchar *value; + GtkTreePath *treepath; + + builder = GTK_BUILDER (user_data); + + if (!get_selected_namespace_treepath_iter_model_widget (builder, &treepath, NULL, NULL, NULL)) + return; + + toggle_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "main_window_search_namespace_dropdown_button")); + if (!toggle_button) + return; + + if (GNUNET_GTK_get_tree_string (GTK_TREE_VIEW (widget), treepath, 0, + &value)) + gtk_button_set_label (GTK_BUTTON (toggle_button), value); + + gtk_tree_path_free (treepath); + + /* This will eventually hide the namespace selector */ + gtk_toggle_button_set_active (toggle_button, FALSE); +} + +void +main_window_search_button_clicked_cb (GtkButton *button, gpointer user_data) +{ + GtkBuilder *builder; + GtkTreePath *namespace_treepath = NULL; + GtkTreeModel *namespace_model = NULL; + GtkComboBox *mime_combo; + GtkTreeModel *mime_model; + GtkEntry *query_entry; + guint anonymity_level; + GtkTreeIter iter; + const char *entry_keywords; + gchar *keywords; + gchar *mime_keyword; + + GNUNET_HashCode *nsid = NULL; + struct GNUNET_FS_Uri *uri; + char *emsg; + + builder = GTK_BUILDER (user_data); + + if (!get_selected_anonymity_level (builder, &anonymity_level)) + return; + + mime_combo = GTK_COMBO_BOX (GNUNET_FS_GTK_get_main_window_object + ("main_window_search_mime_combobox")); + mime_model = gtk_combo_box_get_model (mime_combo); + if (mime_model && gtk_combo_box_get_active_iter (mime_combo, &iter)) + { + mime_keyword = NULL; + gtk_tree_model_get (mime_model, &iter, 0, &mime_keyword, -1); + } + + get_selected_namespace_treepath_iter_model_widget (builder, + &namespace_treepath, &iter, &namespace_model, NULL); + + query_entry = GTK_ENTRY (gtk_builder_get_object (builder, + "main_window_search_entry")); + + entry_keywords = gtk_entry_get_text (query_entry); + if (mime_keyword != NULL) + { + keywords = g_strdup_printf ("%s %s", entry_keywords, mime_keyword); + g_free (mime_keyword); + } + else + keywords = g_strdup (entry_keywords); + if (namespace_treepath != NULL) + gtk_tree_model_get (namespace_model, &iter, 1, &nsid, -1); + if (nsid != NULL) + { + uri = GNUNET_FS_uri_sks_create_from_nsid (nsid, keywords); + GNUNET_assert (uri != NULL); + } + else + { + emsg = NULL; + uri = GNUNET_FS_uri_ksk_create (keywords, &emsg); + if (uri == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Invalid keyword string `%s': %s"), keywords, emsg); + GNUNET_free_non_null (emsg); + return; + } + } + GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (), uri, + anonymity_level, GNUNET_FS_SEARCH_OPTION_NONE, NULL); + + g_free (keywords); + GNUNET_FS_uri_destroy (uri); +} + +void +GNUNET_GTK_main_window_realize_cb (GtkWidget *widget, gpointer user_data) +{ + GtkTreeIter iter; + GtkTreeView *namespace_tree; + GtkTreeStore *namespace_treestore; + GtkBuilder *builder; + GtkToggleButton *toggle_button; + GtkWidget *namespace_selector_window; + + builder = GTK_BUILDER (user_data); + + namespace_treestore = GTK_TREE_STORE (GNUNET_FS_GTK_get_main_window_object + ("main_window_search_namespace_treestore")); + namespace_tree = GTK_TREE_VIEW (GNUNET_FS_GTK_get_main_window_object + ("namespace_selector_treeview")); + + /* TODO: fetch real values from somewhere instead of filling the store with dummies */ + gtk_tree_store_insert_with_values (namespace_treestore, &iter, NULL, 0, 0, "Any", 1, NULL, 2, "", 3, "Do not search in any particular namespace", -1); + gtk_tree_store_insert_with_values (namespace_treestore, &iter, NULL, 1, 0, "foo", 1, NULL, 2, "IAMTHEBESTOBEYMENOCARRIER", 3, "Tooltip1", -1); + gtk_tree_store_insert_with_values (namespace_treestore, &iter, NULL, 2, 0, "bar", 1, NULL, 2, "NOONEWILLKNOWTHISIDBECAUSEITSSECRET", 3, "Tooltip2", -1); + gtk_tree_store_insert_with_values (namespace_treestore, &iter, NULL, 3, 0, "baz", 1, NULL, 2, "SSLOPENSSHGNUGTKGNUNETFTWYAYA", 3, "Tooltip3", -1); + + /* FIXME: read currently selected namespace from somewhere instead of selecting 0th item */ + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (namespace_treestore), &iter)) + { + gchar *value; + GtkTreePath *treepath = gtk_tree_path_new_first (); + gtk_tree_selection_select_iter (gtk_tree_view_get_selection ( + namespace_tree), &iter); + toggle_button = GTK_TOGGLE_BUTTON (GNUNET_FS_GTK_get_main_window_object + ("main_window_search_namespace_dropdown_button")); + if (GNUNET_GTK_get_tree_string (namespace_tree, + treepath, 0, &value)) + gtk_button_set_label (GTK_BUTTON (toggle_button), value); + gtk_tree_path_free (treepath); + } + + /* How the window (to trigger certain events) and immediately hide it */ + namespace_selector_window = GTK_WIDGET (gtk_builder_get_object (builder, "namespace_selector_window")); + gtk_widget_show (namespace_selector_window); + gtk_widget_hide (namespace_selector_window); + +} /** * Actual main function run right after GNUnet's scheduler -- 1.7.4