aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-12-16 19:03:56 +0000
committerChristian Grothoff <christian@grothoff.org>2011-12-16 19:03:56 +0000
commit99c1933f1e99aa7da550e65082f80e73c9787f43 (patch)
tree03279c0ee7404e0cebf1b70cf25e5f0db491cbc8
parent5dbb2088abda9734cea1cd9ffe817fdf901bc017 (diff)
downloadgnunet-gtk-99c1933f1e99aa7da550e65082f80e73c9787f43.tar.gz
gnunet-gtk-99c1933f1e99aa7da550e65082f80e73c9787f43.zip
LRN: Make metadata list items selectable, make metadata copyable and be more careful with strings (validation) - #1759
-rw-r--r--contrib/gnunet_fs_gtk_main_window.glade18
-rw-r--r--src/fs/gnunet-fs-gtk-common.c25
-rw-r--r--src/fs/gnunet-fs-gtk-event_handler.c176
-rw-r--r--src/fs/gnunet-fs-gtk.c6
4 files changed, 221 insertions, 4 deletions
diff --git a/contrib/gnunet_fs_gtk_main_window.glade b/contrib/gnunet_fs_gtk_main_window.glade
index 37dab80d..a47a445c 100644
--- a/contrib/gnunet_fs_gtk_main_window.glade
+++ b/contrib/gnunet_fs_gtk_main_window.glade
@@ -602,7 +602,10 @@
602 <property name="hadjustment">adjustment1</property> 602 <property name="hadjustment">adjustment1</property>
603 <property name="vadjustment">adjustment2</property> 603 <property name="vadjustment">adjustment2</property>
604 <property name="search_column">0</property> 604 <property name="search_column">0</property>
605 <property name="rubber_banding">True</property>
605 <property name="enable_grid_lines">both</property> 606 <property name="enable_grid_lines">both</property>
607 <signal name="button-press-event" handler="GNUNET_GTK_main_window_metadata_treeview_button_press_event_cb" swapped="no"/>
608 <signal name="popup-menu" handler="GNUNET_GTK_main_window_metadata_treeview_popup_menu_cb" swapped="no"/>
606 <child> 609 <child>
607 <object class="GtkTreeViewColumn" id="GNUNET_GTK_main_window_metadata_type_column"> 610 <object class="GtkTreeViewColumn" id="GNUNET_GTK_main_window_metadata_type_column">
608 <property name="sizing">autosize</property> 611 <property name="sizing">autosize</property>
@@ -628,7 +631,6 @@
628 <property name="sort_indicator">True</property> 631 <property name="sort_indicator">True</property>
629 <child> 632 <child>
630 <object class="GtkCellRendererText" id="GNUNET_GTK_main_window_metadata_value_renderer"> 633 <object class="GtkCellRendererText" id="GNUNET_GTK_main_window_metadata_value_renderer">
631 <property name="sensitive">False</property>
632 <property name="wrap_mode">word</property> 634 <property name="wrap_mode">word</property>
633 </object> 635 </object>
634 <attributes> 636 <attributes>
@@ -849,6 +851,20 @@
849 <column type="gchararray"/> 851 <column type="gchararray"/>
850 </columns> 852 </columns>
851 </object> 853 </object>
854 <object class="GtkMenu" id="metadata_popup_menu">
855 <property name="visible">True</property>
856 <property name="can_focus">False</property>
857 <child>
858 <object class="GtkMenuItem" id="Copy selection">
859 <property name="use_action_appearance">False</property>
860 <property name="visible">True</property>
861 <property name="can_focus">False</property>
862 <property name="label" translatable="yes">Copy selection</property>
863 <property name="use_underline">True</property>
864 <signal name="activate" handler="metadata_copy_selection_activated" swapped="no"/>
865 </object>
866 </child>
867 </object>
852 <object class="GtkWindow" id="namespace_selector_window"> 868 <object class="GtkWindow" id="namespace_selector_window">
853 <property name="can_focus">False</property> 869 <property name="can_focus">False</property>
854 <property name="events">GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property> 870 <property name="events">GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
diff --git a/src/fs/gnunet-fs-gtk-common.c b/src/fs/gnunet-fs-gtk-common.c
index e7cb07f1..1a250c62 100644
--- a/src/fs/gnunet-fs-gtk-common.c
+++ b/src/fs/gnunet-fs-gtk-common.c
@@ -48,13 +48,32 @@ GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls, const char *plugin_name,
48 const char *data_mime_type, 48 const char *data_mime_type,
49 const char *data, size_t data_len) 49 const char *data, size_t data_len)
50{ 50{
51 gchar *data_to_insert = NULL;
52 gboolean freedata = FALSE;
51 GtkListStore *ls = GTK_LIST_STORE (cls); 53 GtkListStore *ls = GTK_LIST_STORE (cls);
52 54
53 if ((format == EXTRACTOR_METAFORMAT_UTF8) || 55 if (format == EXTRACTOR_METAFORMAT_UTF8)
54 (format == EXTRACTOR_METAFORMAT_C_STRING)) 56 {
57 if (g_utf8_validate (data, data_len, NULL))
58 data_to_insert = data;
59 else
60 format = EXTRACTOR_METAFORMAT_C_STRING;
61 }
62 if (format == EXTRACTOR_METAFORMAT_C_STRING)
63 {
64 gsize rd, wr;
65 data_to_insert = g_locale_to_utf8 (data, data_len, &rd, &wr, NULL);
66 freedata = TRUE;
67 }
68
69 if (data_to_insert)
70 {
55 gtk_list_store_insert_with_values (ls, NULL, G_MAXINT, 0, type, 1, format, 71 gtk_list_store_insert_with_values (ls, NULL, G_MAXINT, 0, type, 1, format,
56 2, EXTRACTOR_metatype_to_string (type), 72 2, EXTRACTOR_metatype_to_string (type),
57 3, data, -1); 73 3, data_to_insert, -1);
74 if (freedata)
75 g_free (data_to_insert);
76 }
58 return 0; 77 return 0;
59} 78}
60 79
diff --git a/src/fs/gnunet-fs-gtk-event_handler.c b/src/fs/gnunet-fs-gtk-event_handler.c
index 74c3ab5d..8565bd05 100644
--- a/src/fs/gnunet-fs-gtk-event_handler.c
+++ b/src/fs/gnunet-fs-gtk-event_handler.c
@@ -1934,6 +1934,182 @@ GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy,
1934 gtk_list_store_clear (ms); 1934 gtk_list_store_clear (ms);
1935} 1935}
1936 1936
1937static void
1938copy_metadata_to_clipboard (GtkTreeModel *model, GtkTreePath *path,
1939 GtkTreeIter *iter, gpointer user_data)
1940{
1941 gchar *type, *value;
1942 GList **l = (GList **) user_data;
1943
1944 gtk_tree_model_get (model, iter, 2, &type, 3, &value, -1);
1945
1946 *l = g_list_prepend (*l, type);
1947 *l = g_list_prepend (*l, value);
1948}
1949
1950void
1951metadata_copy_selection_activated (GtkMenuItem *menuitem, gpointer user_data)
1952{
1953 GtkBuilder *builder;
1954 GtkTreeView *tree;
1955 GtkClipboard *cb;
1956 GList *pairs = NULL, *l, *next, *value, *type;
1957 guint total_len;
1958 gchar *s, *p;
1959
1960 builder = GTK_BUILDER (user_data);
1961 tree = GTK_TREE_VIEW (gtk_builder_get_object (builder,
1962 "GNUNET_GTK_main_window_metadata_treeview"));
1963
1964 gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (tree),
1965 copy_metadata_to_clipboard, &pairs);
1966
1967 total_len = 0;
1968 pairs = g_list_reverse (pairs);
1969 for (l = pairs; l; l = next)
1970 {
1971 type = l;
1972 value = l->next;
1973 if (!value)
1974 break;
1975 next = value->next;
1976 total_len += strlen ((gchar *) type->data)
1977 + strlen ((gchar *) value->data) + 2 /* ": " */ + (next ? 1 : 0) /* "\n" */;
1978 }
1979 if (total_len > 0)
1980 {
1981 total_len += 1; /* "\0" */
1982 s = g_new0 (gchar, total_len);
1983 p = s;
1984 for (l = pairs; l; l = next)
1985 {
1986 type = l;
1987 value = l->next;
1988 if (value)
1989 {
1990 next = value->next;
1991 p = g_stpcpy (p, (gchar *) type->data);
1992 p = g_stpcpy (p, ": ");
1993 p = g_stpcpy (p, (gchar *) value->data);
1994 if (next)
1995 p = g_stpcpy (p, "\n");
1996 }
1997 else
1998 next = NULL;
1999 }
2000 }
2001 g_list_foreach (pairs, (GFunc) g_free, NULL);
2002 g_list_free (pairs);
2003 pairs = NULL;
2004
2005 if (total_len > 0)
2006 {
2007 cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2008 gtk_clipboard_set_text (cb, s, -1);
2009 gtk_clipboard_store (cb);
2010 g_free (s);
2011 }
2012}
2013
2014void
2015metadata_menu_popup_position (GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
2016 gpointer user_data)
2017{
2018 GtkBuilder *builder;
2019 GtkTreeView *tree;
2020 GtkTreeSelection *sel;
2021 GList *rows;
2022 GtkTreePath *p;
2023 GtkAllocation tree_allocation;
2024 GdkWindow *main_window_gdk;
2025 gint mwg_x, mwg_y, t_x, t_y, popup_x, popup_y;
2026
2027 builder = GTK_BUILDER (user_data);
2028
2029 tree = GTK_TREE_VIEW (gtk_builder_get_object (builder,
2030 "GNUNET_GTK_main_window_metadata_treeview"));
2031
2032 gtk_widget_get_allocation (GTK_WIDGET (tree), &tree_allocation);
2033
2034 main_window_gdk = gtk_widget_get_window (GTK_WIDGET (tree));
2035
2036 gdk_window_get_origin (main_window_gdk, &mwg_x, &mwg_y);
2037
2038 t_x = mwg_x + tree_allocation.x;
2039 t_y = mwg_y + tree_allocation.y;
2040 popup_x = t_x;
2041 popup_y = t_y;
2042
2043 sel = gtk_tree_view_get_selection (tree);
2044
2045 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
2046
2047 if (rows->data)
2048 {
2049 GdkRectangle r;
2050 p = (GtkTreePath *) rows->data;
2051 gtk_tree_view_get_cell_area (tree, p, NULL, &r);
2052 popup_x += r.x;
2053 popup_y += r.y;
2054 }
2055
2056 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
2057 g_list_free (rows);
2058 *x = popup_x;
2059 *y = popup_y;
2060 *push_in = FALSE;
2061}
2062
2063static void
2064do_metadata_popup_menu (GtkWidget *widget, GdkEventButton *event,
2065 gpointer user_data)
2066{
2067 GtkMenu *menu;
2068 GtkBuilder *builder;
2069 int button, event_time;
2070 GtkMenuPositionFunc mpf = NULL;
2071
2072 builder = GTK_BUILDER (user_data);
2073
2074 menu = GTK_MENU (gtk_builder_get_object (builder, "metadata_popup_menu"));
2075
2076 if (event)
2077 {
2078 button = event->button;
2079 event_time = event->time;
2080 }
2081 else
2082 {
2083 button = 0;
2084 event_time = gtk_get_current_event_time ();
2085 }
2086
2087 gtk_menu_attach_to_widget (menu, widget, NULL);
2088 gtk_menu_popup (menu, NULL, NULL, mpf, user_data,
2089 button, event_time);
2090}
2091
2092gboolean
2093GNUNET_GTK_main_window_metadata_treeview_button_press_event_cb (GtkWidget *widget,
2094 GdkEventButton *event, gpointer user_data)
2095{
2096 /* Ignore double-clicks and triple-clicks */
2097 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
2098 {
2099 do_metadata_popup_menu (widget, event, user_data);
2100 return TRUE;
2101 }
2102
2103 return FALSE;
2104}
2105
2106gboolean
2107GNUNET_GTK_main_window_metadata_treeview_popup_menu_cb (GtkWidget *widget,
2108 gpointer user_data)
2109{
2110 do_metadata_popup_menu (widget, NULL, user_data);
2111 return TRUE;
2112}
1937 2113
1938 2114
1939/* end of gnunet-fs-gtk-event_handler.c */ 2115/* end of gnunet-fs-gtk-event_handler.c */
diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c
index e115395c..dd4c9512 100644
--- a/src/fs/gnunet-fs-gtk.c
+++ b/src/fs/gnunet-fs-gtk.c
@@ -572,6 +572,7 @@ GNUNET_GTK_main_window_realize_cb (GtkWidget *widget, gpointer user_data)
572 GtkTreeStore *namespace_treestore; 572 GtkTreeStore *namespace_treestore;
573 GtkBuilder *builder; 573 GtkBuilder *builder;
574 GtkWidget *namespace_selector_window; 574 GtkWidget *namespace_selector_window;
575 GtkTreeView *metadata_tree;
575 576
576 builder = GTK_BUILDER (user_data); 577 builder = GTK_BUILDER (user_data);
577 578
@@ -579,6 +580,11 @@ GNUNET_GTK_main_window_realize_cb (GtkWidget *widget, gpointer user_data)
579 ("main_window_search_namespace_treestore")); 580 ("main_window_search_namespace_treestore"));
580 namespace_tree = GTK_TREE_VIEW (GNUNET_FS_GTK_get_main_window_object 581 namespace_tree = GTK_TREE_VIEW (GNUNET_FS_GTK_get_main_window_object
581 ("namespace_selector_treeview")); 582 ("namespace_selector_treeview"));
583 metadata_tree = GTK_TREE_VIEW (GNUNET_FS_GTK_get_main_window_object
584 ("GNUNET_GTK_main_window_metadata_treeview"));
585
586 /* Allow multiple selection in metadata view */
587 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (metadata_tree), GTK_SELECTION_MULTIPLE);
582 588
583 /* FIXME: find a way to manage pseudonyms. 589 /* FIXME: find a way to manage pseudonyms.
584 * Right now the list will be filled with ALL and ANY pseudonyms that we 590 * Right now the list will be filled with ALL and ANY pseudonyms that we