aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-15 14:11:40 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-15 14:11:40 +0000
commitb32c41fda944780a18bc886a3171cb5cde46d77f (patch)
treecc473697c7b9bd9f2546335b6659ae66e8f79cf5
parentd4d1ddd29caf14f7bb502abc133288b50b9d0ce1 (diff)
downloadgnunet-gtk-b32c41fda944780a18bc886a3171cb5cde46d77f.tar.gz
gnunet-gtk-b32c41fda944780a18bc886a3171cb5cde46d77f.zip
gnunet-fs-gtk against new libgnunetgtk library
-rw-r--r--src/fs/Makefile.am36
-rw-r--r--src/fs/about.c42
-rw-r--r--src/fs/common.c183
-rw-r--r--src/fs/common.h89
-rw-r--r--src/fs/download.c136
-rw-r--r--src/fs/download.h83
-rw-r--r--src/fs/edit_publish_dialog.c771
-rw-r--r--src/fs/edit_publish_dialog.h41
-rw-r--r--src/fs/fs_anonymity_spin_buttons.c73
-rw-r--r--src/fs/fs_event_handler.c2028
-rw-r--r--src/fs/fs_event_handler.h198
-rw-r--r--src/fs/gnunet-fs-gtk.c249
-rw-r--r--src/fs/gnunet-fs-gtk.h68
-rw-r--r--src/fs/main_window_adv_pseudonym.c588
-rw-r--r--src/fs/main_window_create_pseudonym.c65
-rw-r--r--src/fs/main_window_file_download.c130
-rw-r--r--src/fs/main_window_file_publish.c1933
-rw-r--r--src/fs/main_window_file_search.c243
-rw-r--r--src/fs/main_window_open_directory.c147
-rw-r--r--src/fs/main_window_view_toggles.c90
20 files changed, 7193 insertions, 0 deletions
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am
new file mode 100644
index 00000000..1bca5573
--- /dev/null
+++ b/src/fs/Makefile.am
@@ -0,0 +1,36 @@
1SUBDIRS = .
2
3INCLUDES = \
4 -I$(top_srcdir)/ \
5 -I$(top_srcdir)/src/include \
6 @GTK_CFLAGS@ \
7 @GNUNET_CFLAGS@ \
8 @GLADE_CFLAGS@
9
10bin_PROGRAMS = gnunet-fs-gtk
11
12gnunet_fs_gtk_SOURCES = \
13 about.c \
14 common.c common.h \
15 download.c download.h \
16 edit_publish_dialog.c edit_publish_dialog.h \
17 fs_event_handler.c fs_event_handler.h \
18 fs_anonymity_spin_buttons.c \
19 gnunet-fs-gtk.c gnunet-fs-gtk.h \
20 main_window_create_pseudonym.c \
21 main_window_file_download.c \
22 main_window_file_publish.c \
23 main_window_file_search.c \
24 main_window_open_directory.c \
25 main_window_adv_pseudonym.c \
26 main_window_view_toggles.c
27gnunet_fs_gtk_LDADD = \
28 $(top_builddir)/src/lib/libgnunetgtk.la \
29 @GTK_LIBS@ \
30 @GLADE_LIBS@ \
31 -lextractor \
32 -lgnunetutil \
33 -lgnunetfs \
34 $(INTLLIBS)
35gnunet_fs_gtk_LDFLAGS = \
36 -export-dynamic
diff --git a/src/fs/about.c b/src/fs/about.c
new file mode 100644
index 00000000..9e1bad52
--- /dev/null
+++ b/src/fs/about.c
@@ -0,0 +1,42 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs/about.c
23 * @author Christian Grothoff
24 * @author Igor Wronsky
25 *
26 * This file contains the about dialog.
27 */
28#include "gnunet_gtk.h"
29
30
31/**
32 * This displays an about window
33 */
34void
35GNUNET_GTK_main_menu_help_about_activate_cb (GtkWidget * dummy, gpointer data)
36{
37 GNUNET_GTK_display_about ("gnunet_fs_gtk_about_dialog.glade",
38 "GNUNET_GKT_about_dialog");
39}
40
41
42/* end of about.c */
diff --git a/src/fs/common.c b/src/fs/common.c
new file mode 100644
index 00000000..f586a3d4
--- /dev/null
+++ b/src/fs/common.c
@@ -0,0 +1,183 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs/common.c
23 * @brief Common functions used in various places
24 * @author Christian Grothoff
25 */
26#include "common.h"
27
28/**
29 * Add meta data to list store.
30 *
31 * @param cls closure (the GtkListStore)
32 * @param plugin_name name of the plugin that produced this value;
33 * special values can be used (i.e. '<zlib>' for zlib being
34 * used in the main libextractor library and yielding
35 * meta data).
36 * @param type libextractor-type describing the meta data
37 * @param format basic format information about data
38 * @param data_mime_type mime-type of data (not of the original file);
39 * can be NULL (if mime-type is not known)
40 * @param data actual meta-data found
41 * @param data_len number of bytes in data
42 * @return 0 to continue (always)
43 */
44int
45GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls,
46 const char *plugin_name,
47 enum EXTRACTOR_MetaType type,
48 enum EXTRACTOR_MetaFormat format,
49 const char *data_mime_type,
50 const char *data,
51 size_t data_len)
52{
53 GtkListStore *ls = GTK_LIST_STORE (cls);
54
55 if ( (format == EXTRACTOR_METAFORMAT_UTF8) ||
56 (format == EXTRACTOR_METAFORMAT_C_STRING) )
57 gtk_list_store_insert_with_values (ls,
58 NULL,
59 G_MAXINT,
60 0, type,
61 1, format,
62 2, EXTRACTOR_metatype_to_string (type),
63 3, data,
64 -1);
65 return 0;
66}
67
68
69/**
70 * Convert the year from the spin button to an expiration
71 * time (on midnight, January 1st of that year).
72 */
73struct GNUNET_TIME_Absolute
74GNUNET_FS_GTK_get_expiration_time (GtkSpinButton *spin)
75{
76 struct GNUNET_TIME_Absolute ret;
77 int year;
78
79 year = gtk_spin_button_get_value_as_int (spin);
80 GNUNET_assert (year >= 0);
81 ret = GNUNET_FS_year_to_time ( (unsigned int) year);
82 GNUNET_break (GNUNET_TIME_absolute_get ().abs_value < ret.abs_value);
83 return ret;
84}
85
86
87void
88GNUNET_FS_GTK_setup_expiration_year_adjustment (GtkBuilder *builder)
89{
90 GtkAdjustment *aj;
91 unsigned int year;
92
93 year = GNUNET_FS_get_current_year ();
94 aj = GTK_ADJUSTMENT (gtk_builder_get_object (builder,
95 "expiration_year_adjustment"));
96 gtk_adjustment_set_value (aj, year + 2);
97 gtk_adjustment_set_lower (aj, year + 1);
98}
99
100
101GdkPixbuf *
102GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct GNUNET_CONTAINER_MetaData *meta)
103{
104 GdkPixbuf *pixbuf;
105 GdkPixbufLoader *loader;
106 size_t ts;
107 unsigned char *thumb;
108
109 thumb = NULL;
110 ts = GNUNET_CONTAINER_meta_data_get_thumbnail (meta, &thumb);
111 if (ts == 0)
112 return NULL;
113 loader = gdk_pixbuf_loader_new ();
114 gdk_pixbuf_loader_write (loader, (const guchar *) thumb, ts, NULL);
115 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
116 gdk_pixbuf_loader_close (loader, NULL);
117 if (pixbuf != NULL)
118 g_object_ref (pixbuf);
119 g_object_unref (loader);
120 GNUNET_free (thumb);
121 return pixbuf;
122}
123
124
125/**
126 * mmap the given file and run the GNUNET_FS_directory_list_contents
127 * function on it.
128 */
129void
130GNUNET_FS_GTK_mmap_and_scan (const char *filename,
131 GNUNET_FS_DirectoryEntryProcessor dep,
132 void *dep_cls)
133{
134 struct GNUNET_DISK_FileHandle *fh;
135 struct GNUNET_DISK_MapHandle *mh;
136 uint64_t fsize;
137 void * ddata;
138
139 if (GNUNET_OK !=
140 GNUNET_DISK_file_size (filename,
141 &fsize,
142 GNUNET_YES))
143 {
144 GNUNET_break (0);
145 return;
146 }
147 fh = GNUNET_DISK_file_open (filename,
148 GNUNET_DISK_OPEN_READ,
149 GNUNET_DISK_PERM_NONE);
150 if (fh == NULL)
151 {
152 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
153 return;
154 }
155 ddata = GNUNET_DISK_file_map (fh,
156 &mh,
157 GNUNET_DISK_MAP_TYPE_READ,
158 (size_t) fsize);
159 if (ddata == NULL)
160 {
161 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mmap", filename);
162 GNUNET_break (GNUNET_OK ==
163 GNUNET_DISK_file_close (fh));
164 return;
165 }
166 if (GNUNET_SYSERR ==
167 GNUNET_FS_directory_list_contents ((size_t) fsize,
168 ddata,
169 0,
170 dep, dep_cls))
171 {
172 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
173 _("Selected file `%s' is not a GNUnet directory!\n"),
174 filename);
175 }
176 GNUNET_break (GNUNET_OK ==
177 GNUNET_DISK_file_unmap (mh));
178 GNUNET_break (GNUNET_OK ==
179 GNUNET_DISK_file_close (fh));
180}
181
182
183/* end of common.c */
diff --git a/src/fs/common.h b/src/fs/common.h
new file mode 100644
index 00000000..e316768b
--- /dev/null
+++ b/src/fs/common.h
@@ -0,0 +1,89 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs/common.h
23 * @brief Common includes for all gnunet-gtk source files
24 * @author Christian Grothoff
25 */
26#ifndef COMMON_H
27#define COMMON_H
28
29#include "gnunet_gtk.h"
30#include <gnunet/gnunet_fs_service.h>
31#include <extractor.h>
32
33
34
35GdkPixbuf *
36GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct GNUNET_CONTAINER_MetaData *meta);
37
38/**
39 * Setup the expiration year adjustment to start with the
40 * next year and default to next year plus one.
41 */
42void
43GNUNET_FS_GTK_setup_expiration_year_adjustment (GtkBuilder *builder);
44
45/**
46 * Convert the year from the spin button to an expiration
47 * time (on midnight, January 1st of that year).
48 */
49struct GNUNET_TIME_Absolute
50GNUNET_FS_GTK_get_expiration_time (GtkSpinButton *spin);
51
52
53/**
54 * mmap the given file and run the GNUNET_FS_directory_list_contents
55 * function on it.
56 */
57void
58GNUNET_FS_GTK_mmap_and_scan (const char *filename,
59 GNUNET_FS_DirectoryEntryProcessor dep,
60 void *dep_cls);
61
62
63/**
64 * Add meta data to list store.
65 *
66 * @param cls closure (the GtkListStore)
67 * @param plugin_name name of the plugin that produced this value;
68 * special values can be used (i.e. '<zlib>' for zlib being
69 * used in the main libextractor library and yielding
70 * meta data).
71 * @param type libextractor-type describing the meta data
72 * @param format basic format information about data
73 * @param data_mime_type mime-type of data (not of the original file);
74 * can be NULL (if mime-type is not known)
75 * @param data actual meta-data found
76 * @param data_len number of bytes in data
77 * @return 0 to continue (always)
78 */
79int
80GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls,
81 const char *plugin_name,
82 enum EXTRACTOR_MetaType type,
83 enum EXTRACTOR_MetaFormat format,
84 const char *data_mime_type,
85 const char *data,
86 size_t data_len);
87
88#endif
89/* end of common.h */
diff --git a/src/fs/download.c b/src/fs/download.c
new file mode 100644
index 00000000..6a0e172c
--- /dev/null
+++ b/src/fs/download.c
@@ -0,0 +1,136 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/download.c
23 * @brief functions for downloading
24 * @author Christian Grothoff
25 */
26#include "download.h"
27#include "gnunet-fs-gtk.h"
28#include "fs_event_handler.h"
29
30void
31GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc)
32{
33 GtkWidget *ad;
34 GtkBuilder *builder;
35 struct GNUNET_FS_Handle *fs;
36 uint64_t len;
37 enum GNUNET_FS_DownloadOptions opt;
38 uint32_t anonymity;
39 struct DownloadEntry *de;
40 GtkWidget *cb;
41
42 builder = GNUNET_GTK_get_new_builder ("download_as.glade");
43 if (builder == NULL)
44 {
45 if (dc->rr != NULL)
46 gtk_tree_row_reference_free (dc->rr);
47 GNUNET_free_non_null (dc->mime);
48 GNUNET_free_non_null (dc->filename);
49 GNUNET_FS_uri_destroy (dc->uri);
50 GNUNET_free (dc);
51 return;
52 }
53 cb = GTK_WIDGET (gtk_builder_get_object (builder,
54 "GNUNET_GTK_save_as_recursive_check_button"));
55 if (GNUNET_FS_meta_data_test_for_directory (dc->meta))
56 gtk_widget_set_sensitive (cb, TRUE);
57 ad = GTK_WIDGET (gtk_builder_get_object (builder,
58 "GNUNET_GTK_save_as_dialog"));
59 if (dc->filename != NULL)
60 {
61 char buf[1024];
62 if (NULL != getcwd (buf, sizeof(buf)))
63 {
64 if (strlen (buf) + strlen (dc->filename) + 2 < sizeof(buf))
65 {
66 strcat (buf, DIR_SEPARATOR_STR);
67 strcat (buf, dc->filename);
68 }
69 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad),
70 buf);
71 }
72 }
73 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
74 {
75 gtk_widget_destroy (ad);
76 g_object_unref (G_OBJECT (builder));
77 if (dc->rr != NULL)
78 gtk_tree_row_reference_free (dc->rr);
79 GNUNET_free_non_null (dc->mime);
80 GNUNET_free_non_null (dc->filename);
81 GNUNET_FS_uri_destroy (dc->uri);
82 GNUNET_free (dc);
83 return;
84 }
85 GNUNET_free_non_null (dc->filename);
86 dc->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
87 dc->is_recursive = (TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES : GNUNET_NO;
88 fs = GNUNET_FS_GTK_get_fs_handle ();
89 opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
90 if (dc->is_recursive)
91 opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
92 anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
93 "GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
94 len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
95 gtk_widget_destroy (ad);
96 g_object_unref (G_OBJECT (builder));
97 de = GNUNET_malloc (sizeof (struct DownloadEntry));
98 de->uri = dc->uri;
99 de->meta = dc->meta;
100 if (dc->rr != NULL)
101 {
102 de->rr = dc->rr;
103 de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
104 }
105 if (dc->sr != NULL)
106 {
107 GNUNET_break (NULL !=
108 GNUNET_FS_download_start_from_search (fs,
109 dc->sr,
110 dc->filename,
111 NULL /* tempname */,
112 0 /* offset */,
113 len,
114 anonymity,
115 opt,
116 de));
117 }
118 else
119 {
120 GNUNET_break (NULL !=
121 GNUNET_FS_download_start (fs,
122 dc->uri,
123 NULL /* meta */,
124 dc->filename,
125 NULL /* tempname */,
126 0 /* offset */,
127 len,
128 anonymity,
129 opt,
130 de,
131 NULL /* parent download ctx */));
132 }
133 GNUNET_free (dc);
134}
135
136/* end of download.c */
diff --git a/src/fs/download.h b/src/fs/download.h
new file mode 100644
index 00000000..e2c8767b
--- /dev/null
+++ b/src/fs/download.h
@@ -0,0 +1,83 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/download.h
23 * @brief functions for downloading
24 * @author Christian Grothoff
25 */
26
27#ifndef DOWNLOAD_H
28#define DOWNLOAD_H
29#include "common.h"
30
31/**
32 * Information we keep for a download.
33 */
34struct DownloadContext
35{
36 /**
37 * URI for the download.
38 */
39 struct GNUNET_FS_Uri *uri;
40
41 /**
42 * Meta data.
43 */
44 struct GNUNET_CONTAINER_MetaData *meta;
45
46 /**
47 * Mime type.
48 */
49 char *mime;
50
51 /**
52 * Suggested filename, or NULL.
53 */
54 char *filename;
55
56 /**
57 * Row reference (if URI was found by search, or
58 * part of directory, etc.); otherwise NULL (download by URI).
59 */
60 GtkTreeRowReference *rr;
61
62 /**
63 * Associated search result, or NULL.
64 */
65 struct GNUNET_FS_SearchResult *sr;
66
67 /**
68 * Is this a recursive download?
69 */
70 int is_recursive;
71
72 /**
73 * Desired (default) anonymity level.
74 */
75 int anonymity;
76};
77
78
79
80void
81GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc);
82
83#endif
diff --git a/src/fs/edit_publish_dialog.c b/src/fs/edit_publish_dialog.c
new file mode 100644
index 00000000..ab7b968d
--- /dev/null
+++ b/src/fs/edit_publish_dialog.c
@@ -0,0 +1,771 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/edit_publish_dialog.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "edit_publish_dialog.h"
27#include <gnunet/gnunet_util_lib.h>
28
29/**
30 * Builder for the current dialog.
31 */
32static GtkBuilder *builder;
33
34/**
35 * Are we editing metadata for a directory?
36 */
37static int is_directory;
38
39/**
40 * Set to YES if the preview was changed.
41 */
42static int preview_changed;
43
44void
45GNUNET_GTK_edit_file_information_keyword_list_normalize_button_clicked_cb ()
46{
47 GNUNET_break (0);
48}
49
50void
51GNUNET_GTK_edit_file_information_keyword_list_del_button_clicked_cb ()
52{
53 GtkTreeView *tv;
54 GtkTreeSelection *sel;
55 GtkTreeModel *tm;
56 GtkTreeIter iter;
57
58 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
59 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
60 sel = gtk_tree_view_get_selection (tv);
61 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
62 {
63 GNUNET_break (0);
64 return;
65 }
66 gtk_list_store_remove (GTK_LIST_STORE (tm),
67 &iter);
68}
69
70void
71GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ()
72{
73 const char *keyword;
74 GtkEntry *entry;
75 GtkListStore *ls;
76 GtkTreeIter iter;
77
78 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
79 "GNUNET_GTK_keyword_list_store"));
80 entry = GTK_ENTRY (gtk_builder_get_object (builder,
81 "GNUNET_GTK_edit_file_information_keyword_entry"));
82 keyword = gtk_entry_get_text (entry);
83 if (strlen (keyword) > 0)
84 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
85 gtk_entry_set_text (entry, "");
86}
87
88
89void
90GNUNET_GTK_edit_file_information_keyword_entry_changed_cb ()
91{
92 const char *keyword;
93 GtkEntry *entry;
94 GtkWidget *button;
95
96 button = GTK_WIDGET (gtk_builder_get_object (builder,
97 "GNUNET_GTK_edit_file_information_keyword_list_add_button"));
98 entry = GTK_ENTRY (gtk_builder_get_object (builder,
99 "GNUNET_GTK_edit_file_information_keyword_entry"));
100 keyword = gtk_entry_get_text (entry);
101 gtk_widget_set_sensitive (button,
102 (strlen (keyword) > 0) ? TRUE : FALSE);
103}
104
105
106static void
107metadata_selection_changed_cb (GtkTreeSelection *ts,
108 gpointer user_data)
109{
110 GtkTreeView *tv;
111 GtkTreeSelection *sel;
112 GtkWidget *button;
113
114 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
115 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
116 sel = gtk_tree_view_get_selection (tv);
117 button = GTK_WIDGET (gtk_builder_get_object (builder,
118 "GNUNET_GTK_edit_file_information_metadata_delete_button"));
119 gtk_widget_set_sensitive (button,
120 gtk_tree_selection_get_selected (sel, NULL, NULL));
121}
122
123
124static void
125keyword_selection_changed_cb (GtkTreeSelection *ts,
126 gpointer user_data)
127{
128 GtkTreeView *tv;
129 GtkTreeSelection *sel;
130 GtkWidget *button;
131
132 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
133 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
134 sel = gtk_tree_view_get_selection (tv);
135 button = GTK_WIDGET (gtk_builder_get_object (builder,
136 "GNUNET_GTK_edit_file_information_keyword_list_del_button"));
137
138 gtk_widget_set_sensitive (button,
139 gtk_tree_selection_get_selected (sel, NULL, NULL));
140 button = GTK_WIDGET (gtk_builder_get_object (builder,
141 "GNUNET_GTK_edit_file_information_keyword_list_normalize_button"));
142 gtk_widget_set_sensitive (button,
143 gtk_tree_selection_get_selected (sel, NULL, NULL));
144}
145
146
147void
148GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb ()
149{
150 GtkTreeView *tv;
151 GtkTreeSelection *sel;
152 const char *value;
153 GtkEntry *entry;
154 GtkWidget *button;
155
156 entry = GTK_ENTRY (gtk_builder_get_object (builder,
157 "GNUNET_GTK_edit_file_information_metadata_value_entry"));
158 value = gtk_entry_get_text (entry);
159 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
160 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
161 sel = gtk_tree_view_get_selection (tv);
162 button = GTK_WIDGET (gtk_builder_get_object (builder,
163 "GNUNET_GTK_edit_file_information_metadata_add_button"));
164 gtk_widget_set_sensitive (button,
165 (strlen (value) > 0)
166 ? gtk_tree_selection_get_selected (sel, NULL, NULL)
167 : FALSE);
168}
169
170
171void
172GNUNET_GTK_edit_file_information_keyword_entry_activate_cb ()
173{
174 GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ();
175}
176
177
178void
179GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button_file_set_cb (GtkFileChooserButton *widget,
180 gpointer user_data)
181{
182 gchar *fn;
183 GtkImage *image;
184
185 fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
186 image = GTK_IMAGE (gtk_builder_get_object (builder,
187 "GNUNET_GTK_edit_file_information_metadata_preview_image"));
188 gtk_image_set_from_file (image, fn);
189 preview_changed = GNUNET_YES;
190}
191
192
193void
194GNUNET_GTK_edit_file_information_metadata_delete_button_clicked_cb()
195{
196 GtkTreeView *tv;
197 GtkTreeSelection *sel;
198 GtkTreeModel *tm;
199 GtkTreeIter iter;
200
201 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
202 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
203 sel = gtk_tree_view_get_selection (tv);
204 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
205 {
206 GNUNET_break (0);
207 return;
208 }
209 gtk_list_store_remove (GTK_LIST_STORE (tm),
210 &iter);
211}
212
213
214void
215GNUNET_GTK_edit_file_information_metadata_add_button_clicked_cb ()
216{
217 const char *value;
218 char *avalue;
219 const char *ivalue;
220 GtkEntry *entry;
221 GtkListStore *ls;
222 GtkTreeModel *tm;
223 GtkTreeView *tv;
224 GtkTreeSelection *sel;
225 GtkTreeIter iter;
226 guint type;
227 size_t slen;
228 char *pos;
229
230 entry = GTK_ENTRY (gtk_builder_get_object (builder,
231 "GNUNET_GTK_edit_file_information_metadata_value_entry"));
232 value = gtk_entry_get_text (entry);
233 if ((value == NULL) || (strlen (value) == 0))
234 {
235 GNUNET_break (0);
236 return;
237 }
238 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
239 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
240 tm = gtk_tree_view_get_model (tv);
241 sel = gtk_tree_view_get_selection (tv);
242 if (TRUE != gtk_tree_selection_get_selected (sel,
243 &tm,
244 &iter))
245 {
246 GNUNET_break (0);
247 return;
248 }
249 gtk_tree_model_get (tm,
250 &iter,
251 1, &type, -1);
252 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
253 "GNUNET_GTK_meta_data_list_store"));
254 if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
255 (value[strlen(value)-1] != '/') &&
256 (is_directory) )
257 {
258 GNUNET_asprintf (&avalue,
259 "%s/",
260 value);
261 /* if user typed '\' instead of '/', change it! */
262 slen = strlen (avalue);
263 while ( (slen > 1) &&
264 (avalue[slen-2] == '\\') )
265 {
266 avalue[slen-2] = '/';
267 avalue[slen-1] = '\0';
268 slen--;
269 }
270 while (NULL != (pos = strstr (avalue, "\\")))
271 *pos = '/';
272 /* remove '../' everywhere */
273 while (NULL != (pos = strstr (avalue, "../")))
274 {
275 pos[0] = '_';
276 pos[1] = '_';
277 pos[2] = '_';
278 }
279 ivalue = avalue;
280 }
281 else
282 {
283 ivalue = value;
284 avalue = NULL;
285 }
286
287 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
288 0, type,
289 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
290 2, EXTRACTOR_metatype_to_string (type),
291 3, ivalue,
292 -1);
293 GNUNET_free_non_null (avalue);
294 gtk_entry_set_text (GTK_ENTRY (entry), "");
295}
296
297
298/**
299 * Add each of the keywords to the keyword list store.
300 *
301 * @param cls closure
302 * @param keyword the keyword
303 * @param is_mandatory is the keyword mandatory (in a search)
304 * @return GNUNET_OK to continue to iterate
305 */
306static int
307add_keyword (void *cls,
308 const char *keyword,
309 int is_mandatory)
310{
311 GtkListStore *ls;
312 GtkTreeIter iter;
313
314 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
315 "GNUNET_GTK_keyword_list_store"));
316 gtk_list_store_insert_with_values (ls, &iter,
317 G_MAXINT,
318 0, keyword,
319 -1);
320 return GNUNET_OK;
321}
322
323
324/**
325 * Add the given meta data to the model (or make it the preview
326 * image if it is an image).
327 *
328 * @param cls closure, NULL
329 * @param plugin_name name of the plugin that produced this value;
330 * special values can be used (i.e. '<zlib>' for zlib being
331 * used in the main libextractor library and yielding
332 * meta data).
333 * @param type libextractor-type describing the meta data
334 * @param format basic format information about data
335 * @param data_mime_type mime-type of data (not of the original file);
336 * can be NULL (if mime-type is not known)
337 * @param data actual meta-data found
338 * @param data_len number of bytes in data
339 * @return 0 to continue extracting
340 */
341static int
342add_meta_item (void *cls,
343 const char *plugin_name,
344 enum EXTRACTOR_MetaType type,
345 enum EXTRACTOR_MetaFormat format,
346 const char *data_mime_type,
347 const char *data,
348 size_t data_len)
349{
350 GtkListStore *ls;
351 GtkTreeIter iter;
352
353 switch (format)
354 {
355 case EXTRACTOR_METAFORMAT_UTF8:
356 case EXTRACTOR_METAFORMAT_C_STRING:
357 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
358 "GNUNET_GTK_meta_data_list_store"));
359 gtk_list_store_insert_with_values (ls, &iter,
360 G_MAXINT,
361 0, (guint) type,
362 1, (guint) format,
363 2, EXTRACTOR_metatype_to_string (type),
364 3, data,
365 -1);
366 break;
367 case EXTRACTOR_METAFORMAT_UNKNOWN:
368 break;
369 case EXTRACTOR_METAFORMAT_BINARY:
370 break;
371 default:
372 GNUNET_break (0);
373 }
374 return 0;
375}
376
377
378/**
379 * Function called to extract the information from FI.
380 *
381 * @param cls closure
382 * @param fi the entry in the publish-structure
383 * @param length length of the file or directory
384 * @param meta metadata for the file or directory (can be modified)
385 * @param uri pointer to the keywords that will be used for this entry (can be modified)
386 * @param bo block options
387 * @param do_index should we index (can be modified)
388 * @param client_info pointer to client context set upon creation (can be modified)
389 * @return GNUNET_SYSERR (aborts after first call)
390 */
391static int
392file_information_extract (void *cls,
393 struct GNUNET_FS_FileInformation *fi,
394 uint64_t length,
395 struct GNUNET_CONTAINER_MetaData *meta,
396 struct GNUNET_FS_Uri **uri,
397 struct GNUNET_FS_BlockOptions *bo,
398 int *do_index,
399 void **client_info)
400{
401 GtkImage *img;
402 GdkPixbuf *pixbuf;
403 struct tm *t;
404 int year;
405 time_t tp;
406
407 if (NULL != *uri)
408 GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword, NULL);
409 if (NULL != meta)
410 {
411 GNUNET_CONTAINER_meta_data_iterate (meta,
412 &add_meta_item,
413 NULL);
414 pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
415 if (pixbuf != NULL)
416 {
417 img = GTK_IMAGE (gtk_builder_get_object (builder,
418 "GNUNET_GTK_edit_file_information_metadata_preview_image"));
419 gtk_image_set_from_pixbuf (img,
420 pixbuf);
421 }
422 }
423 tp = bo->expiration_time.abs_value / 1000; /* ms to seconds */
424 t = gmtime (&tp);
425 if (t == NULL)
426 year = 0;
427 else
428 year = t->tm_year + 1900;
429 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
430 "GNUNET_GTK_edit_file_information_expiration_year_spin_button")),
431 year);
432 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
433 "GNUNET_GTK_edit_file_information_anonymity_spin_button")),
434 bo->anonymity_level);
435 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
436 "GNUNET_GTK_edit_file_information_priority_spin_button")),
437 bo->content_priority);
438 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
439 "GNUNET_GTK_edit_file_information_index_check_button")),
440 *do_index);
441 return GNUNET_SYSERR; /* only visit top-level item */
442}
443
444
445/**
446 * Copy binary meta data from to the new container and also
447 * preserve all entries that were not changed.
448 *
449 * @param cls closure, new meta data container
450 * @param plugin_name name of the plugin that produced this value;
451 * special values can be used (i.e. '<zlib>' for zlib being
452 * used in the main libextractor library and yielding
453 * meta data).
454 * @param type libextractor-type describing the meta data
455 * @param format basic format information about data
456 * @param data_mime_type mime-type of data (not of the original file);
457 * can be NULL (if mime-type is not known)
458 * @param data actual meta-data found
459 * @param data_len number of bytes in data
460 * @return 0 to continue extracting
461 */
462static int
463preserve_meta_items (void *cls,
464 const char *plugin_name,
465 enum EXTRACTOR_MetaType type,
466 enum EXTRACTOR_MetaFormat format,
467 const char *data_mime_type,
468 const char *data,
469 size_t data_len)
470{
471 struct GNUNET_CONTAINER_MetaData *md = cls;
472 GtkTreeModel *tm;
473 GtkTreeIter iter;
474 gchar *value;
475 guint ntype;
476 guint nformat;
477 int keep;
478
479 keep = GNUNET_NO;
480 switch (format)
481 {
482 case EXTRACTOR_METAFORMAT_UTF8:
483 case EXTRACTOR_METAFORMAT_C_STRING:
484 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
485 "GNUNET_GTK_meta_data_list_store"));
486 if (TRUE ==
487 gtk_tree_model_get_iter_first (tm, &iter))
488 {
489 do
490 {
491 gtk_tree_model_get (tm, &iter,
492 0, &ntype,
493 1, &nformat,
494 3, &value,
495 -1);
496 if ( (ntype == type) &&
497 (nformat == format) &&
498 (0 == strcmp (value, data)) )
499 {
500 gtk_list_store_remove (GTK_LIST_STORE (tm), &iter);
501 keep = GNUNET_YES;
502 g_free (value);
503 break;
504 }
505 g_free (value);
506 }
507 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
508 }
509 break;
510 case EXTRACTOR_METAFORMAT_UNKNOWN:
511 break;
512 case EXTRACTOR_METAFORMAT_BINARY:
513 if (preview_changed == GNUNET_NO)
514 keep = GNUNET_YES;
515 break;
516 default:
517 GNUNET_break (0);
518 break;
519 }
520 if (GNUNET_YES == keep)
521 GNUNET_break (GNUNET_OK ==
522 GNUNET_CONTAINER_meta_data_insert (md,
523 plugin_name, type, format,
524 data_mime_type, data, data_len));
525 return 0;
526}
527
528
529/**
530 * Function called to update the information in FI.
531 *
532 * @param cls closure (short_fn to update)
533 * @param fi the entry in the publish-structure
534 * @param length length of the file or directory
535 * @param meta metadata for the file or directory (can be modified)
536 * @param uri pointer to the keywords that will be used for this entry (can be modified)
537 * @param bo block options (can be modified)
538 * @param do_index should we index (can be modified)
539 * @param client_info pointer to client context set upon creation (can be modified)
540 * @return GNUNET_SYSERR (aborts after first call)
541 */
542static int
543file_information_update (void *cls,
544 struct GNUNET_FS_FileInformation *fi,
545 uint64_t length,
546 struct GNUNET_CONTAINER_MetaData *meta,
547 struct GNUNET_FS_Uri **uri,
548 struct GNUNET_FS_BlockOptions *bo,
549 int *do_index,
550 void **client_info)
551{
552 char **short_fn = cls;
553 struct GNUNET_CONTAINER_MetaData *nm;
554 GtkTreeModel *tm;
555 GtkTreeIter iter;
556 struct GNUNET_FS_Uri *nxt;
557 struct GNUNET_FS_Uri *mrg;
558 gchar *value;
559 guint ntype;
560 guint nformat;
561 GtkSpinButton *sb;
562 gchar *fn;
563 char *data;
564 gsize data_size;
565 const char *mime;
566 GFile *f;
567 GFileInfo *finfo;
568
569 bo->anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
570 "GNUNET_GTK_edit_file_information_anonymity_spin_button")));
571 bo->content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
572 "GNUNET_GTK_edit_file_information_priority_spin_button")));
573 *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
574 "GNUNET_GTK_edit_file_information_index_check_button")));
575 sb =GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
576 "GNUNET_GTK_edit_file_information_expiration_year_spin_button"));
577 bo->expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
578 /* update URI */
579 if (NULL != (*uri))
580 GNUNET_FS_uri_destroy (*uri);
581 *uri = NULL;
582 nxt = NULL;
583 mrg = NULL;
584
585 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
586 "GNUNET_GTK_keyword_list_store"));
587 if (TRUE ==
588 gtk_tree_model_get_iter_first (tm, &iter))
589 {
590 do
591 {
592 gtk_tree_model_get (tm, &iter,
593 0, &value,
594 -1);
595 nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
596 mrg = GNUNET_FS_uri_ksk_merge (nxt, *uri);
597 GNUNET_FS_uri_destroy (nxt);
598 if (NULL != *uri)
599 GNUNET_FS_uri_destroy (*uri);
600 *uri = mrg;
601 g_free (value);
602 }
603 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
604 }
605
606 /* update meta */
607 nm = GNUNET_CONTAINER_meta_data_create ();
608 GNUNET_CONTAINER_meta_data_iterate (meta,
609 &preserve_meta_items,
610 nm);
611
612 GNUNET_CONTAINER_meta_data_clear (meta);
613 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
614 "GNUNET_GTK_meta_data_list_store"));
615 if (TRUE ==
616 gtk_tree_model_get_iter_first (tm, &iter))
617 {
618 do
619 {
620 gtk_tree_model_get (tm, &iter,
621 0, &ntype,
622 1, &nformat,
623 3, &value,
624 -1);
625 GNUNET_CONTAINER_meta_data_insert (nm,
626 "<user>",
627 ntype,
628 nformat,
629 "text/plain",
630 value,
631 strlen (value)+1);
632 g_free (value);
633 }
634 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
635 }
636 GNUNET_CONTAINER_meta_data_merge (meta, nm);
637 if (preview_changed == GNUNET_YES)
638 {
639 fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gtk_builder_get_object (builder,
640 "GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button")));
641 f = g_file_new_for_path (fn);
642 finfo = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, NULL, NULL);
643 if (FALSE == g_file_load_contents (f, NULL, &data, &data_size, NULL, NULL))
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
646 _("Could not load preview `%s' into memory\n"),
647 fn);
648 }
649 else
650 {
651 mime = g_file_info_get_attribute_string (finfo,
652 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
653 GNUNET_CONTAINER_meta_data_insert (meta,
654 "<user>",
655 EXTRACTOR_METATYPE_THUMBNAIL,
656 EXTRACTOR_METAFORMAT_BINARY,
657 mime,
658 data,
659 data_size);
660 }
661 g_object_unref (finfo);
662 g_object_unref (f);
663 }
664 GNUNET_CONTAINER_meta_data_destroy (nm);
665
666 /* update short_fn */
667 GNUNET_free_non_null (*short_fn);
668 *short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
669 EXTRACTOR_METATYPE_FILENAME,
670 -1);
671 /* FIXME: update expiration time? (not yet in dialog!) */
672 return GNUNET_SYSERR; /* only visit top-level item */
673}
674
675
676/**
677 * Open the dialog to edit file information data.
678 */
679void
680GNUNET_GTK_edit_publish_dialog (int *do_index,
681 char **short_fn,
682 guint *anonymity_level,
683 guint *priority,
684 struct GNUNET_FS_FileInformation *fip)
685{
686 GtkWidget *ad;
687 GtkListStore *ls;
688 GtkTreeIter iter;
689 guint type;
690 guint max_type;
691 GtkTreeView *tv;
692 GtkTreeSelection *sel;
693
694 GNUNET_assert (builder == NULL);
695 builder = GNUNET_GTK_get_new_builder ("publish_edit_dialog.glade");
696 if (builder == NULL)
697 {
698 GNUNET_break (0);
699 return;
700 }
701 preview_changed = GNUNET_NO;
702 GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
703 if (GNUNET_FS_file_information_is_directory (fip))
704 {
705 /* indexing does not apply to directories */
706 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
707 "GNUNET_GTK_edit_file_information_index_check_button")));
708 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
709 "GNUNET_GTK_edit_file_information_index_label")));
710
711 }
712
713 ad = GTK_WIDGET (gtk_builder_get_object (builder,
714 "GNUNET_GTK_edit_file_information_dialog"));
715 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
716 "GNUNET_GTK_metatype_list_store"));
717 max_type = EXTRACTOR_metatype_get_max ();
718 type = 1;
719 while (type < max_type - 1)
720 {
721 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
722 0, EXTRACTOR_metatype_to_string (type),
723 1, type,
724 2, EXTRACTOR_metatype_to_description (type),
725 -1);
726 type++;
727 }
728
729 GNUNET_FS_file_information_inspect (fip,
730 &file_information_extract,
731 NULL);
732 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
733 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
734 sel = gtk_tree_view_get_selection (tv);
735 g_signal_connect(G_OBJECT(sel), "changed",
736 G_CALLBACK(GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb), NULL);
737
738 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
739 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
740 sel = gtk_tree_view_get_selection (tv);
741 g_signal_connect(G_OBJECT(sel), "changed",
742 G_CALLBACK(metadata_selection_changed_cb), NULL);
743
744 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
745 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
746 sel = gtk_tree_view_get_selection (tv);
747 g_signal_connect(G_OBJECT(sel), "changed",
748 G_CALLBACK(keyword_selection_changed_cb), NULL);
749 gtk_window_set_title (GTK_WINDOW (ad), *short_fn);
750 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
751 {
752 gtk_widget_destroy (ad);
753 g_object_unref (G_OBJECT (builder));
754 builder = NULL;
755 return;
756 }
757 GNUNET_FS_file_information_inspect (fip,
758 &file_information_update,
759 short_fn);
760 *anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
761 "GNUNET_GTK_edit_file_information_anonymity_spin_button")));
762 *priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
763 "GNUNET_GTK_edit_file_information_priority_spin_button")));
764 *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
765 "GNUNET_GTK_edit_file_information_index_check_button")));
766 gtk_widget_destroy (ad);
767 g_object_unref (G_OBJECT (builder));
768 builder = NULL;
769}
770
771/* end of edit_publish_dialog.c */
diff --git a/src/fs/edit_publish_dialog.h b/src/fs/edit_publish_dialog.h
new file mode 100644
index 00000000..c13f6abe
--- /dev/null
+++ b/src/fs/edit_publish_dialog.h
@@ -0,0 +1,41 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/edit_publish_dialog.h
23 * @author Christian Grothoff
24 */
25#ifndef EDIT_PUBLISH_DIALOG_H
26#define EDIT_PUBLISH_DIALOG_H
27
28#include "common.h"
29#include <gnunet/gnunet_util_lib.h>
30#include <gnunet/gnunet_fs_service.h>
31
32
33void
34GNUNET_GTK_edit_publish_dialog (int *do_index,
35 char **short_fn,
36 guint *anonymity_level,
37 guint *priority,
38 struct GNUNET_FS_FileInformation *fip);
39
40#endif
41/* end of edit_publish_dialog.h */
diff --git a/src/fs/fs_anonymity_spin_buttons.c b/src/fs/fs_anonymity_spin_buttons.c
new file mode 100644
index 00000000..fa4b4eeb
--- /dev/null
+++ b/src/fs/fs_anonymity_spin_buttons.c
@@ -0,0 +1,73 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs_anonymtiy_spin_buttons.c
23 * @author Christian Grothoff
24 *
25 * This file contains callbacks to turn spin buttons red when the
26 * value reaches zero.
27 */
28#include "common.h"
29
30
31/**
32 * Spin button is changed, update its colour.
33 */
34void
35GNUNET_GTK_anonymity_spin_button_value_changed_cb (GtkWidget *w,
36 gpointer data)
37{
38 GtkSpinButton *spin;
39 gint val;
40 GdkColor bcolor;
41 GdkColor fcolor;
42
43 spin = GTK_SPIN_BUTTON (w);
44 if (spin == NULL)
45 {
46 GNUNET_break (0);
47 return;
48 }
49 val = gtk_spin_button_get_value_as_int (spin);
50 if (val == 0)
51 {
52 if ((TRUE == gdk_color_parse ("red",
53 &bcolor)) &&
54 (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
55 &bcolor, FALSE, TRUE)) &&
56 (TRUE == gdk_color_parse ("black",
57 &fcolor)) &&
58 (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
59 &fcolor, FALSE, TRUE)))
60 {
61 gtk_widget_modify_base (w, GTK_STATE_NORMAL, &bcolor);
62 gtk_widget_modify_text (w, GTK_STATE_NORMAL, &fcolor);
63 }
64 }
65 else
66 {
67 gtk_widget_modify_base (w, GTK_STATE_NORMAL, NULL);
68 gtk_widget_modify_text (w, GTK_STATE_NORMAL, NULL);
69 }
70}
71
72
73/* end of fs_anonymtiy_spin_buttons.c */
diff --git a/src/fs/fs_event_handler.c b/src/fs/fs_event_handler.c
new file mode 100644
index 00000000..05463f34
--- /dev/null
+++ b/src/fs/fs_event_handler.c
@@ -0,0 +1,2028 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs_event_handler.c
23 * @brief Main event handler for file-sharing
24 * @author Christian Grothoff
25 */
26#include "common.h"
27#include "gnunet-fs-gtk.h"
28#include "download.h"
29#include "fs_event_handler.h"
30#include <string.h>
31
32static struct SearchTab *search_tab_head;
33
34static struct SearchTab *search_tab_tail;
35
36struct PublishTab
37{
38 /**
39 * This is a doubly-linked list.
40 */
41 struct PublishTab *next;
42
43 /**
44 * This is a doubly-linked list.
45 */
46 struct PublishTab *prev;
47
48 GtkWidget *frame;
49
50 GtkBuilder *builder;
51
52 /**
53 * Associated (top-level) FS publish operation.
54 */
55 struct GNUNET_FS_PublishContext *pc;
56
57 GtkTreeStore *ts;
58};
59
60
61struct PublishEntry
62{
63 /**
64 * Associated FS publish operation.
65 */
66 struct GNUNET_FS_PublishContext *pc;
67
68 /**
69 * Tab storing this entry.
70 */
71 struct PublishTab *tab;
72
73 /**
74 * Where in the tab is this entry?
75 */
76 GtkTreeRowReference *rr;
77
78 /**
79 * URI of the file (set after completion).
80 */
81 struct GNUNET_FS_Uri *uri;
82
83 int is_top;
84};
85
86
87struct SearchResult
88{
89 /**
90 * Where in the tab is this result?
91 */
92 GtkTreeRowReference *rr;
93
94 /**
95 * Tab storing this result.
96 */
97 struct SearchTab *tab;
98
99 /**
100 * Search result for top-level results and
101 * namespace-update results.
102 */
103 struct GNUNET_FS_SearchResult *result;
104
105 /**
106 * Associated download, or NULL for none.
107 */
108 struct DownloadEntry *download;
109};
110
111
112
113static struct PublishTab *publish_tab_head;
114
115static struct PublishTab *publish_tab_tail;
116
117
118static struct DownloadEntry *
119change_download_colour (struct DownloadEntry *de,
120 const char *colour)
121{
122 GtkTreeIter iter;
123 GtkTreePath *path;
124
125 path = gtk_tree_row_reference_get_path (de->rr);
126 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
127 &iter, path))
128 {
129 GNUNET_break (0);
130 gtk_tree_path_free (path);
131 return de;
132 }
133 gtk_tree_path_free (path);
134 gtk_tree_store_set (de->ts, &iter,
135 8, colour,
136 -1);
137 return de;
138}
139
140
141static struct PublishEntry *
142change_publish_colour (struct PublishEntry *pe,
143 const char *colour)
144{
145 GtkTreeIter iter;
146 GtkTreePath *path;
147
148 if (pe == NULL)
149 {
150 GNUNET_break (0);
151 return NULL;
152 }
153 path = gtk_tree_row_reference_get_path (pe->rr);
154 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
155 &iter, path))
156 {
157 GNUNET_break (0);
158 gtk_tree_path_free (path);
159 return pe;
160 }
161 gtk_tree_path_free (path);
162 gtk_tree_store_set (pe->tab->ts, &iter,
163 2, colour,
164 -1);
165 return pe;
166}
167
168
169static void
170stop_download (struct DownloadEntry *de,
171 int is_suspend)
172{
173 change_download_colour (de, "white");
174 gtk_tree_row_reference_free (de->rr);
175 if (is_suspend == GNUNET_NO)
176 GNUNET_FS_download_stop (de->dc, GNUNET_YES);
177 GNUNET_FS_uri_destroy (de->uri);
178 GNUNET_CONTAINER_meta_data_destroy (de->meta);
179 GNUNET_free (de);
180}
181
182
183
184struct AddDirectoryEntryContext
185{
186
187 struct DownloadEntry *de;
188
189 /**
190 * Row reference of parent (the directory).
191 */
192 GtkTreeRowReference *prr;
193
194 int check_duplicates;
195
196};
197
198
199/**
200 * Function used to process entries in a directory.
201 *
202 * @param cls closure, our 'struct AddDirectoryEntryContext*'
203 * @param filename name of the file in the directory
204 * @param uri URI of the file
205 * @param metadata metadata for the file; metadata for
206 * the directory if everything else is NULL/zero
207 * @param length length of the available data for the file
208 * (of type size_t since data must certainly fit
209 * into memory; if files are larger than size_t
210 * permits, then they will certainly not be
211 * embedded with the directory itself).
212 * @param data data available for the file (length bytes)
213 */
214static void
215add_directory_entry (void *cls,
216 const char *filename,
217 const struct GNUNET_FS_Uri *uri,
218 const struct GNUNET_CONTAINER_MetaData *meta,
219 size_t length,
220 const void *data)
221{
222 struct AddDirectoryEntryContext *ade = cls;
223 GtkTreeIter iter;
224 GtkTreeIter piter;
225 GtkTreePath *path;
226 GtkTreeModel *tm;
227 struct GNUNET_FS_Uri *xuri;
228
229 if (uri == NULL)
230 {
231 /* directory meta data itself */
232 /* FIXME: consider merging it in... */
233 return;
234 }
235 if (ade->check_duplicates == GNUNET_YES)
236 {
237 path = gtk_tree_row_reference_get_path (ade->prr);
238 tm = gtk_tree_row_reference_get_model (ade->prr);
239 if (TRUE != gtk_tree_model_get_iter (tm,
240 &piter, path))
241 {
242 GNUNET_break (0);
243 gtk_tree_path_free (path);
244 return;
245 }
246 gtk_tree_path_free (path);
247 if (TRUE == gtk_tree_model_iter_children (tm,
248 &iter,
249 &piter))
250 {
251 do
252 {
253 gtk_tree_model_get (tm,
254 &iter,
255 1, &xuri,
256 -1);
257 if (GNUNET_YES ==
258 GNUNET_FS_uri_test_equal (xuri, uri))
259 return; /* already present */
260 }
261 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
262 }
263 }
264 GNUNET_GTK_add_search_result (ade->de->tab,
265 &iter,
266 ade->prr,
267 uri,
268 meta,
269 NULL,
270 0);
271}
272
273
274static struct DownloadEntry *
275mark_download_progress (struct DownloadEntry *de,
276 uint64_t size,
277 uint64_t completed,
278 const void *block_data,
279 uint64_t offset,
280 uint64_t block_size,
281 unsigned int depth)
282{
283 struct AddDirectoryEntryContext ade;
284 GtkTreeIter iter;
285 GtkTreePath *path;
286
287 path = gtk_tree_row_reference_get_path (de->rr);
288 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
289 &iter, path))
290 {
291 GNUNET_break (0);
292 gtk_tree_path_free (path);
293 return de;
294 }
295 gtk_tree_path_free (path);
296 gtk_tree_store_set (de->ts, &iter,
297 4, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
298 -1);
299 if ( (depth == 0) &&
300 (block_size > 0) &&
301 (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) )
302 {
303 ade.de = de;
304 ade.prr = de->rr;
305 ade.check_duplicates = GNUNET_NO;
306 if (GNUNET_SYSERR ==
307 GNUNET_FS_directory_list_contents ((size_t) block_size,
308 block_data,
309 offset,
310 &add_directory_entry,
311 &ade))
312 {
313 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
314 _("Metadata wrongly claims that this is a GNUnet directory!\n"));
315 }
316 }
317 return de;
318}
319
320
321static struct DownloadEntry *
322mark_download_error (struct DownloadEntry *de,
323 const char *emsg)
324{
325 GtkTreeIter iter;
326 GtkTreePath *path;
327
328 de = change_download_colour (de,
329 "red");
330 de->is_done = GNUNET_YES;
331 path = gtk_tree_row_reference_get_path (de->rr);
332 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->tab->ts),
333 &iter, path))
334 {
335 GNUNET_break (0);
336 gtk_tree_path_free (path);
337 return de;
338 }
339 gtk_tree_path_free (path);
340 gtk_tree_store_set (de->tab->ts, &iter,
341 4, 0,
342 7, emsg,
343 -1);
344 return de;
345}
346
347
348static struct DownloadEntry *
349mark_download_completed (struct DownloadEntry *de,
350 uint64_t size,
351 const char *filename)
352{
353 struct AddDirectoryEntryContext ade;
354
355 de->is_done = GNUNET_YES;
356 (void) mark_download_progress (de, size, size, NULL, 0, 0, 0);
357 if ( (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) &&
358 (filename != NULL) )
359 {
360 ade.de = de;
361 ade.prr = de->rr;
362 ade.check_duplicates = GNUNET_NO;
363 GNUNET_FS_GTK_mmap_and_scan (filename,
364 &add_directory_entry,
365 &ade);
366 }
367 (void) change_download_colour (de, "green");
368 return de;
369}
370
371
372static struct PublishEntry *
373mark_publish_progress (struct PublishEntry *pe,
374 uint64_t size,
375 uint64_t completed)
376{
377 GtkTreeIter iter;
378 GtkTreePath *path;
379
380 path = gtk_tree_row_reference_get_path (pe->rr);
381 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
382 &iter, path))
383 {
384 GNUNET_break (0);
385 gtk_tree_path_free (path);
386 return pe;
387 }
388 gtk_tree_path_free (path);
389 gtk_tree_store_set (pe->tab->ts, &iter,
390 3, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
391 -1);
392 return pe;
393}
394
395
396/**
397 * Move (aka copy) all of the children of 'src_iter' from the 'src_model'
398 * to become children of 'dst_iter' in the 'dst_model'.
399 *
400 * The models are both 'GNUNET_GTK_file_sharing_result_tree_store' models.
401 *
402 * Note that we also need to update the 'struct SearchResult'
403 * and (if it exists) the respective 'struct DownloadEntry'
404 * to refer to the new model.
405 */
406static void
407move_children (GtkTreeModel *src_model,
408 GtkTreeIter *src_iter,
409 GtkTreeModel *dst_model,
410 GtkTreeIter *dst_iter)
411{
412 GtkTreeIter src_child;
413 GtkTreeIter dst_child;
414 GtkTreePath *path;
415 struct GNUNET_CONTAINER_MetaData *meta;
416 struct GNUNET_FS_Uri *uri;
417 guint64 filesize;
418 GdkPixbuf *preview;
419 guint percent_progress;
420 guint percent_availability;
421 gchar *filename;
422 gchar *uri_as_string;
423 gchar *status_colour;
424 struct SearchResult *search_result;
425 gchar *mimetype;
426 guint applicability_rank;
427 guint availability_certainty;
428 gint availability_rank;
429
430 if (TRUE == gtk_tree_model_iter_children (src_model,
431 &src_child,
432 src_iter))
433 {
434 do
435 {
436 gtk_tree_model_get (src_model,
437 &src_child,
438 0, &meta,
439 1, &uri,
440 2, &filesize,
441 3, &preview,
442 4, &percent_progress,
443 5, &percent_availability,
444 6, &filename,
445 7, &uri_as_string,
446 8, &status_colour,
447 9, &search_result,
448 10, &mimetype,
449 11, &applicability_rank,
450 12, &availability_certainty,
451 13, &availability_rank,
452 -1);
453 gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model),
454 &dst_child,
455 dst_iter,
456 G_MAXINT,
457 0, meta,
458 1, uri,
459 2, filesize,
460 3, preview,
461 4, percent_progress,
462 5, percent_availability,
463 6, filename,
464 7, uri_as_string,
465 8, status_colour,
466 9, search_result,
467 10, mimetype,
468 11, applicability_rank,
469 12, availability_certainty,
470 13, availability_rank,
471 -1);
472 g_free (filename);
473 g_free (uri_as_string);
474 g_free (status_colour);
475 g_free (mimetype);
476 if (preview != NULL)
477 g_object_unref (preview);
478 gtk_tree_row_reference_free (search_result->rr);
479 path = gtk_tree_model_get_path (dst_model,
480 &dst_child);
481 search_result->rr = gtk_tree_row_reference_new (dst_model,
482 path);
483 gtk_tree_path_free (path);
484 if (search_result->download != NULL)
485 {
486 search_result->download->ts = GTK_TREE_STORE (dst_model);
487 gtk_tree_row_reference_free (search_result->download->rr);
488 search_result->download->rr = gtk_tree_row_reference_copy (search_result->rr);
489 }
490 move_children (src_model,
491 &src_child,
492 dst_model,
493 &dst_child);
494 }
495 while (TRUE == gtk_tree_model_iter_next (src_model,
496 &src_child));
497 }
498}
499
500
501/**
502 * Delete the entire given subtree from the model.
503 * Does not free anything inside of the respective
504 * model's fields (since they have been moved).
505 */
506static void
507delete_stale_subtree (GtkTreeModel *model,
508 GtkTreeIter *iter)
509{
510 GtkTreeIter child;
511
512 while (TRUE == gtk_tree_model_iter_children (model,
513 &child,
514 iter))
515 delete_stale_subtree (model, &child);
516 gtk_tree_store_remove (GTK_TREE_STORE (model),
517 iter);
518}
519
520
521/**
522 * Handle the case where an active download lost its
523 * search parent by moving it to the URI tab.
524 */
525static struct DownloadEntry *
526download_lost_parent (struct DownloadEntry *de,
527 uint64_t size,
528 uint64_t completed,
529 int is_active)
530{
531 GtkTreeIter iter;
532 GtkTreePath *path;
533 struct SearchTab *tab;
534 GtkTreeRowReference *rr_old;
535 GtkTreeModel *tm_old;
536 GtkTreeIter iter_old;
537
538 rr_old = de->rr;
539 de->sr = NULL;
540 tab = GNUNET_GTK_add_to_uri_tab (&iter,
541 NULL,
542 de->meta,
543 de->uri);
544 de->ts = tab->ts;
545 path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
546 &iter);
547 de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
548 path);
549 gtk_tree_path_free (path);
550 mark_download_progress (de, size, completed,
551 NULL, 0, 0, 0);
552 tm_old = gtk_tree_row_reference_get_model (rr_old);
553 path = gtk_tree_row_reference_get_path (rr_old);
554 gtk_tree_row_reference_free (rr_old);
555 gtk_tree_model_get_iter (tm_old,
556 &iter_old,
557 path);
558 gtk_tree_path_free (path);
559 move_children (tm_old,
560 &iter_old,
561 GTK_TREE_MODEL (de->ts),
562 &iter);
563 delete_stale_subtree (tm_old,
564 &iter_old);
565 if (size > completed)
566 {
567 if (is_active)
568 change_download_colour (de, "yellow");
569 else
570 change_download_colour (de, "blue");
571 }
572 else
573 {
574 change_download_colour (de, "green");
575 }
576 return de;
577}
578
579
580/**
581 * Setup a new download entry.
582 *
583 * @param de existing download entry for the download, or NULL
584 * @param pde parent download entry, or NULL
585 * @param sr search result, or NULL
586 * @param dc download context (for stopping)
587 * @param uri the URI
588 * @param meta metadata
589 * @param size total size
590 * @param completed current progress
591 */
592static struct DownloadEntry *
593setup_download (struct DownloadEntry *de,
594 struct DownloadEntry *pde,
595 struct SearchResult *sr,
596 struct GNUNET_FS_DownloadContext *dc,
597 const struct GNUNET_FS_Uri *uri,
598 const struct GNUNET_CONTAINER_MetaData *meta,
599 uint64_t size,
600 uint64_t completed)
601{
602 GtkTreeIter iter;
603 GtkTreePath *path;
604
605 if (de == NULL)
606 {
607 de = GNUNET_malloc (sizeof (struct DownloadEntry));
608 GNUNET_assert (sr->download == NULL);
609 sr->download = de;
610 de->sr = sr;
611 de->dc = dc;
612 de->uri = GNUNET_FS_uri_dup (uri);
613 }
614 de->pde = pde;
615 if ( (meta != NULL) &&
616 (de->meta == NULL) )
617 de->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
618 if (sr != NULL)
619 {
620 de->rr = gtk_tree_row_reference_copy (sr->rr);
621 de->ts = sr->tab->ts;
622 de->tab = sr->tab;
623 }
624 else if (de->rr == NULL)
625 {
626 de->tab = GNUNET_GTK_add_to_uri_tab (&iter,
627 NULL,
628 meta,
629 uri);
630 de->ts = de->tab->ts;
631 path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
632 &iter);
633 de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
634 path);
635 gtk_tree_path_free (path);
636 }
637 path = gtk_tree_row_reference_get_path (de->rr);
638 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
639 &iter, path))
640 {
641 GNUNET_break (0);
642 gtk_tree_path_free (path);
643 return de;
644 }
645 gtk_tree_path_free (path);
646 gtk_tree_store_set (de->ts, &iter,
647 4, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
648 8, "blue" /* status colour: pending */,
649 -1);
650 return de;
651}
652
653
654/**
655 * Tell FS to start a download. Begins by opening the
656 * "save as" window.
657 */
658static void
659start_download (GtkTreeView *tree_view,
660 GtkTreePath *path,
661 GtkTreeViewColumn *column,
662 gpointer user_data)
663{
664 struct SearchTab *tab = user_data;
665 GtkTreeModel *tm;
666 GtkTreeIter iter;
667 struct GNUNET_FS_Uri *uri;
668 struct GNUNET_CONTAINER_MetaData *meta;
669 struct SearchResult *sr;
670 gchar *mime;
671 struct DownloadContext *dlc;
672
673 GNUNET_assert (tab != NULL);
674 tm = gtk_tree_view_get_model (tree_view);
675 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
676 {
677 GNUNET_break (0);
678 return;
679 }
680 gtk_tree_model_get (tm, &iter,
681 0, &meta,
682 1, &uri,
683 9, &sr,
684 10, &mime,
685 -1);
686 dlc = GNUNET_malloc (sizeof (struct DownloadContext));
687 dlc->uri = GNUNET_FS_uri_dup (uri);
688 dlc->mime = (NULL != mime) ? GNUNET_strdup (mime) : NULL;
689 dlc->filename = GNUNET_FS_meta_data_suggest_filename (meta);
690 dlc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
691 dlc->rr = gtk_tree_row_reference_new (tm, path);
692 dlc->sr = sr->result;
693 dlc->anonymity = -1;
694 GNUNET_GTK_open_download_as_dialog (dlc);
695 g_free (mime);
696}
697
698
699
700/**
701 * Row reference for the current search context menu.
702 */
703static GtkTreeRowReference *current_context_row_reference;
704
705/**
706 * Search tab used for the current search context menu.
707 */
708static struct SearchTab *current_context_search_tab;
709
710/**
711 * Download was selected in the current search context menu.
712 */
713static void
714start_download_ctx_menu (gpointer user_data,
715 guint unused,
716 GtkWidget *widget)
717{
718 GtkTreePath *path;
719 GtkTreeView *tv;
720
721 if (current_context_row_reference == NULL)
722 {
723 GNUNET_break (0);
724 return;
725 }
726 path = gtk_tree_row_reference_get_path (current_context_row_reference);
727 gtk_tree_row_reference_free (current_context_row_reference);
728 current_context_row_reference = NULL;
729 tv = GTK_TREE_VIEW (gtk_builder_get_object (current_context_search_tab->builder,
730 "_search_result_frame"));
731 start_download (tv, path, NULL, current_context_search_tab);
732 gtk_tree_path_free (path);
733 current_context_search_tab = NULL;
734}
735
736
737/**
738 * Download was selected in the current search context menu.
739 */
740static void
741abort_download_ctx_menu (gpointer user_data,
742 guint unused,
743 GtkWidget *widget)
744{
745 struct DownloadEntry *de = user_data;
746
747 GNUNET_assert (de->dc != NULL);
748 GNUNET_FS_download_stop (de->dc,
749 GNUNET_YES);
750 current_context_search_tab = NULL;
751}
752
753
754/**
755 * Copy current URI to clipboard.
756 */
757static void
758copy_uri_to_clipboard_ctx_menu (gpointer user_data,
759 guint unused,
760 GtkWidget *widget)
761{
762 GtkTreePath *path;
763 GtkTreeView *tv;
764 GtkTreeModel *tm;
765 GtkTreeIter iter;
766 struct GNUNET_FS_Uri *uri;
767 char *uris;
768 GtkClipboard *cb;
769
770 if (current_context_row_reference == NULL)
771 {
772 GNUNET_break (0);
773 return;
774 }
775 path = gtk_tree_row_reference_get_path (current_context_row_reference);
776 gtk_tree_row_reference_free (current_context_row_reference);
777 current_context_row_reference = NULL;
778 tv = GTK_TREE_VIEW (gtk_builder_get_object (current_context_search_tab->builder,
779 "_search_result_frame"));
780 tm = gtk_tree_view_get_model (tv);
781 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
782 {
783 GNUNET_break (0);
784 gtk_tree_path_free (path);
785 return;
786 }
787 gtk_tree_model_get (tm, &iter,
788 1, &uri, -1);
789 gtk_tree_path_free (path);
790 current_context_search_tab = NULL;
791 if (uri == NULL)
792 {
793 GNUNET_break (0);
794 return;
795 }
796 uris = GNUNET_FS_uri_to_string (uri);
797 cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
798 gtk_clipboard_set_text (cb,
799 uris,
800 -1);
801 gtk_clipboard_store (cb);
802 GNUNET_free (uris);
803}
804
805
806/**
807 * We got a right-click on the search result list. Display the context
808 * menu.
809 */
810static int
811search_list_on_menu(GtkWidget *widget,
812 GdkEvent *event,
813 gpointer user_data)
814{
815 GdkEventButton *event_button;
816 struct SearchTab *tab = user_data;
817 GtkTreeView *tv;
818 GtkMenu *menu;
819 GtkWidget *child;
820 GtkTreePath *path;
821 GtkTreeModel *tm;
822 GtkTreeIter iter;
823 struct SearchResult *sr;
824
825 tv = GTK_TREE_VIEW (widget);
826 if (event->type == GDK_BUTTON_PRESS)
827 {
828 event_button = (GdkEventButton *) event;
829 if (event_button->button == 3)
830 {
831 current_context_search_tab = tab;
832 if (current_context_row_reference != NULL)
833 {
834 gtk_tree_row_reference_free (current_context_row_reference);
835 current_context_row_reference = NULL;
836 }
837 path = NULL;
838 if (FALSE == gtk_tree_view_get_path_at_pos (tv,
839 event_button->x,
840 event_button->y,
841 &path, NULL, NULL, NULL))
842 {
843 /* nothing selected */
844 current_context_search_tab = NULL;
845 return FALSE;
846 }
847 tm = gtk_tree_view_get_model (tv);
848 gtk_tree_model_get_iter (tm, &iter, path);
849 gtk_tree_model_get (tm, &iter,
850 9, &sr,
851 -1);
852 current_context_row_reference = gtk_tree_row_reference_new (tm,
853 path);
854 gtk_tree_path_free (path);
855
856 /*
857 FIXME: have additional options, depending on status:
858 - view full meta data (in new window)
859 - copy URI to clipboard
860 - start recursive download
861 - abort active download (!)
862 => need to know download status before creating menu!
863 */
864 menu = GTK_MENU (gtk_menu_new ());
865 if (sr->download == NULL)
866 {
867 child = gtk_menu_item_new_with_label (_("_Download"));
868 g_signal_connect (child,
869 "activate",
870 G_CALLBACK (start_download_ctx_menu),
871 NULL);
872 gtk_label_set_use_underline (GTK_LABEL
873 (gtk_bin_get_child (GTK_BIN (child))),
874 TRUE);
875 gtk_widget_show (child);
876 }
877 else
878 {
879 child = gtk_menu_item_new_with_label (_("_Abort download"));
880 g_signal_connect (child,
881 "activate",
882 G_CALLBACK (abort_download_ctx_menu),
883 sr->download);
884 gtk_label_set_use_underline (GTK_LABEL
885 (gtk_bin_get_child (GTK_BIN (child))),
886 TRUE);
887 gtk_widget_show (child);
888
889 }
890
891 child = gtk_menu_item_new_with_label (_("_Copy URI to Clipboard"));
892 g_signal_connect (child,
893 "activate",
894 G_CALLBACK (copy_uri_to_clipboard_ctx_menu),
895 NULL);
896 gtk_label_set_use_underline (GTK_LABEL
897 (gtk_bin_get_child (GTK_BIN (child))),
898 TRUE);
899 gtk_widget_show (child);
900
901
902
903 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
904 gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
905 event_button->button,
906 event_button->time);
907 }
908 }
909 return FALSE;
910}
911
912
913/**
914 * Selected row has changed, update preview and metadata
915 * areas.
916 */
917static void
918update_meta_data_views (GtkTreeView *tv,
919 gpointer user_data)
920{
921 struct SearchTab *tab = user_data;
922 GtkImage *image;
923 GtkListStore *ms;
924 GtkTreeSelection *sel;
925 GtkTreeModel *model;
926 GtkTreeIter iter;
927 struct GNUNET_CONTAINER_MetaData *meta;
928 GdkPixbuf *pixbuf;
929
930 GNUNET_assert (tab->query_txt != NULL);
931 image = GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_preview_image"));
932 ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_meta_data_list_store"));
933
934 sel = gtk_tree_view_get_selection (tv);
935 gtk_list_store_clear (ms);
936 if (TRUE != gtk_tree_selection_get_selected (sel,
937 &model,
938 &iter))
939 {
940 gtk_image_clear (image);
941 return;
942 }
943 meta = NULL;
944 pixbuf = NULL;
945 gtk_tree_model_get (model,
946 &iter,
947 0, &meta,
948 3, &pixbuf,
949 -1);
950 if (pixbuf != NULL)
951 {
952 gtk_image_set_from_pixbuf (image, pixbuf);
953 g_object_unref (G_OBJECT (pixbuf));
954 }
955 if (meta != NULL)
956 {
957 GNUNET_CONTAINER_meta_data_iterate (meta,
958 &GNUNET_FS_GTK_add_meta_data_to_list_store,
959 ms);
960 }
961}
962
963
964/**
965 * Update the label for a search
966 */
967static void
968update_search_label (struct SearchTab *tab)
969{
970 char *name;
971
972 while (tab->parent != NULL)
973 tab = tab->parent->tab;
974 if (tab->num_results > 0)
975 GNUNET_asprintf (&name,
976 "%.*s%s (%u)",
977 20,
978 tab->query_txt,
979 strlen (tab->query_txt) > 20 ? "..." : "",
980 tab->num_results);
981 else
982 GNUNET_asprintf (&name,
983 "%.*s%s",
984 20,
985 tab->query_txt,
986 strlen (tab->query_txt) > 20 ? "..." : "");
987 gtk_label_set_text (tab->label, name);
988 GNUNET_free (name);
989}
990
991
992/**
993 * Close a search tab and free associated state.
994 */
995static void
996close_search_tab (struct SearchTab *tab)
997{
998 GtkNotebook *notebook;
999 int index;
1000 int i;
1001
1002 if (tab->parent != NULL)
1003 {
1004 /* not a top-level search, do not close tab here! */
1005 GNUNET_free (tab);
1006 return;
1007 }
1008
1009 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1010 index = -1;
1011 for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
1012 if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
1013 index = i;
1014 gtk_notebook_remove_page (notebook, index);
1015 g_object_unref (tab->builder);
1016 GNUNET_free (tab->query_txt);
1017 GNUNET_CONTAINER_DLL_remove (search_tab_head,
1018 search_tab_tail,
1019 tab);
1020 GNUNET_free (tab);
1021}
1022
1023
1024/**
1025 * Close a publish tab and free associated state.
1026 */
1027static struct PublishEntry *
1028handle_publish_completed (struct PublishEntry *ent,
1029 const struct GNUNET_FS_Uri *uri)
1030{
1031 ent->uri = GNUNET_FS_uri_dup (uri);
1032 return change_publish_colour (ent,
1033 "green");
1034}
1035
1036
1037
1038/**
1039 * Handle error.
1040 */
1041static struct PublishEntry *
1042handle_publish_error (struct PublishEntry *ent,
1043 const char *emsg)
1044{
1045 GNUNET_break (0);
1046 return change_publish_colour (ent,
1047 "red");
1048}
1049
1050
1051/**
1052 * Close a publish tab and free associated state.
1053 */
1054static void
1055close_publish_tab (struct PublishEntry *ent)
1056{
1057 struct PublishTab *tab;
1058 GtkNotebook *notebook;
1059 int index;
1060 int i;
1061
1062 if (ent == NULL)
1063 {
1064 GNUNET_break (0);
1065 return;
1066 }
1067 gtk_tree_row_reference_free (ent->rr);
1068 if (GNUNET_YES != ent->is_top)
1069 {
1070 GNUNET_free (ent);
1071 return;
1072 }
1073 tab = ent->tab;
1074 if (ent->uri != NULL)
1075 GNUNET_FS_uri_destroy (ent->uri);
1076 GNUNET_free (ent);
1077 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1078 index = -1;
1079 for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
1080 if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
1081 index = i;
1082 gtk_notebook_remove_page (notebook, index);
1083 g_object_unref (tab->builder);
1084 GNUNET_CONTAINER_DLL_remove (publish_tab_head,
1085 publish_tab_tail,
1086 tab);
1087 GNUNET_free (tab);
1088}
1089
1090
1091/**
1092 * Tell FS to stop a search.
1093 */
1094static void
1095stop_search (GtkButton *button,
1096 gpointer user_data)
1097{
1098 struct SearchTab *tab = user_data;
1099 if (tab->sc != NULL)
1100 {
1101 GNUNET_FS_search_stop (tab->sc);
1102 tab->sc = NULL;
1103 }
1104}
1105
1106
1107/**
1108 * Stop completed downloads (or those that failed). Should
1109 * iterate over the underlying tree store and stop all
1110 * completed entries. Furthermore, if the resulting tree
1111 * store is empty and has no search associated with it,
1112 * the tab should be closed.
1113 */
1114static void
1115clear_downloads (GtkButton *button,
1116 gpointer user_data)
1117{
1118 struct SearchTab *tab = user_data;
1119 struct SearchResult *sr;
1120 GtkTreeModel *tm;
1121 GtkTreeIter iter;
1122
1123 tm = GTK_TREE_MODEL (tab->ts);
1124 if (TRUE != gtk_tree_model_get_iter_first (tm, &iter))
1125 return;
1126 do
1127 {
1128 gtk_tree_model_get (tm, &iter,
1129 9, &sr,
1130 -1);
1131 if ( (sr->download != NULL) &&
1132 (sr->download->is_done == GNUNET_YES) )
1133 GNUNET_FS_download_stop (sr->download->dc,
1134 GNUNET_YES);
1135 }
1136 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
1137}
1138
1139
1140
1141/**
1142 * Tell FS to pause a search.
1143 */
1144static void
1145pause_search (GtkButton *button,
1146 gpointer user_data)
1147{
1148 struct SearchTab *tab = user_data;
1149 if (tab->sc != NULL)
1150 {
1151 GNUNET_FS_search_pause (tab->sc);
1152 gtk_widget_show (tab->play_button);
1153 gtk_widget_hide (tab->pause_button);
1154 }
1155}
1156
1157
1158/**
1159 * Tell FS to resume a search.
1160 */
1161static void
1162continue_search (GtkButton *button,
1163 gpointer user_data)
1164{
1165 struct SearchTab *tab = user_data;
1166 if (tab->sc != NULL)
1167 {
1168 GNUNET_FS_search_continue (tab->sc);
1169 gtk_widget_show (tab->pause_button);
1170 gtk_widget_hide (tab->play_button);
1171 }
1172}
1173
1174
1175/**
1176 * Setup a new search tab.
1177 *
1178 * @param sc context with FS for the search
1179 * @param query the query
1180 * @param anonymity anonymity level
1181 */
1182static struct SearchTab *
1183setup_search (struct GNUNET_FS_SearchContext *sc,
1184 const struct GNUNET_FS_Uri *query)
1185{
1186 struct SearchTab *tab;
1187 GtkTreeView *tv;
1188 GtkNotebook *notebook;
1189 GtkWindow *sf;
1190 gint pages;
1191
1192 tab = GNUNET_malloc (sizeof (struct SearchTab));
1193 GNUNET_CONTAINER_DLL_insert (search_tab_head,
1194 search_tab_tail,
1195 tab);
1196 tab->sc = sc;
1197 if (query == NULL)
1198 {
1199 tab->query_txt = GNUNET_strdup ("*");
1200 }
1201 else
1202 {
1203 if (GNUNET_FS_uri_test_ksk (query))
1204 tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query);
1205 else
1206 tab->query_txt = GNUNET_FS_uri_to_string (query);
1207 }
1208 tab->builder = GNUNET_GTK_get_new_builder ("search_tab.glade");
1209 tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
1210 "GNUNET_GTK_file_sharing_result_tree_store"));
1211 /* load frame */
1212 sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1213 "_search_result_frame_window"));
1214 tab->frame = gtk_bin_get_child (GTK_BIN (sf));
1215 gtk_widget_ref (tab->frame);
1216 gtk_container_remove (GTK_CONTAINER (sf), tab->frame);
1217 gtk_widget_destroy (GTK_WIDGET (sf));
1218
1219 /* load tab_label */
1220 sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1221 "_search_result_label_window"));
1222 tab->tab_label = gtk_bin_get_child (GTK_BIN (sf));
1223 gtk_widget_ref (tab->tab_label);
1224 gtk_container_remove (GTK_CONTAINER (sf), tab->tab_label);
1225 gtk_widget_destroy (GTK_WIDGET (sf));
1226
1227 /* get refs to widgets */
1228 tab->label = GTK_LABEL (gtk_builder_get_object (tab->builder,
1229 "_search_result_label_window_label"));
1230
1231 tab->close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1232 "_search_result_label_close_button"));
1233 g_signal_connect(G_OBJECT(tab->close_button), "clicked",
1234 G_CALLBACK(stop_search), tab);
1235 tab->clear_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1236 "_search_result_label_clear_button"));
1237 g_signal_connect(G_OBJECT(tab->clear_button), "clicked",
1238 G_CALLBACK(clear_downloads), tab);
1239 tab->play_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1240 "_search_result_label_play_button"));
1241 g_signal_connect(G_OBJECT(tab->play_button), "clicked",
1242 G_CALLBACK(continue_search), tab);
1243 tab->pause_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1244 "_search_result_label_pause_button"));
1245 g_signal_connect(G_OBJECT(tab->pause_button), "clicked",
1246 G_CALLBACK(pause_search), tab);
1247 /* patch text */
1248 update_search_label (tab);
1249
1250 /* add signal handlers */
1251 tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
1252 "_search_result_frame"));
1253 g_signal_connect(G_OBJECT(tv), "row-activated",
1254 G_CALLBACK(start_download), tab);
1255 g_signal_connect(G_OBJECT(tv), "cursor-changed",
1256 G_CALLBACK(update_meta_data_views), tab);
1257 g_signal_connect (G_OBJECT(tv),
1258 "button_press_event",
1259 G_CALLBACK(search_list_on_menu),
1260 tab);
1261
1262
1263 /* make visible */
1264 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1265 pages = gtk_notebook_get_n_pages (notebook);
1266 gtk_notebook_insert_page (notebook,
1267 tab->frame,
1268 tab->tab_label,
1269 pages - 1);
1270 gtk_notebook_set_current_page (notebook,
1271 pages - 1);
1272 gtk_widget_show (GTK_WIDGET (notebook));
1273 return tab;
1274}
1275
1276
1277/**
1278 * Setup an inner search.
1279 *
1280 * @param sc context with FS for the search
1281 * @param parent parent search tab
1282 * @param anonymity anonymity level
1283 */
1284static struct SearchTab *
1285setup_inner_search (struct GNUNET_FS_SearchContext *sc,
1286 struct SearchResult *parent)
1287{
1288 struct SearchTab *ret;
1289
1290 ret = GNUNET_malloc (sizeof (struct SearchTab));
1291 ret->parent = parent;
1292 ret->sc = sc;
1293 ret->query_txt = parent->tab->query_txt;
1294 ret->builder = parent->tab->builder;
1295 ret->frame = parent->tab->frame;
1296 ret->tab_label = parent->tab->tab_label;
1297 ret->close_button = parent->tab->close_button;
1298 ret->clear_button = parent->tab->clear_button;
1299 ret->play_button = parent->tab->play_button;
1300 ret->label = parent->tab->label;
1301
1302 return ret;
1303}
1304
1305
1306
1307/**
1308 * Add a search result to the given search tab.
1309 *
1310 * @param tab search tab to extend
1311 * @param iter set to position where search result is added
1312 * @param parent_rr reference to parent entry in search tab
1313 * @param uri uri to add
1314 * @param meta metadata of the entry
1315 * @param result associated FS search result (can be NULL)
1316 * @param applicability_rank how relevant is the result
1317 * @return entry for the search result
1318 */
1319struct SearchResult *
1320GNUNET_GTK_add_search_result (struct SearchTab *tab,
1321 GtkTreeIter *iter,
1322 GtkTreeRowReference *parent_rr,
1323 const struct GNUNET_FS_Uri *uri,
1324 const struct GNUNET_CONTAINER_MetaData *meta,
1325 struct GNUNET_FS_SearchResult *result,
1326 uint32_t applicability_rank)
1327{
1328 struct SearchResult *sr;
1329 GtkTreePath *tp;
1330 const char *status_colour;
1331 char *desc;
1332 char *mime;
1333 char *uris;
1334 GdkPixbuf *pixbuf;
1335 GtkTreeIter *pitr;
1336 GtkTreeIter pmem;
1337 GtkTreePath *path;
1338 GtkTreeModel *tm;
1339 GtkTreeStore *ts;
1340 uint64_t fsize;
1341
1342 if ( (uri != NULL) &&
1343 (!GNUNET_FS_uri_test_loc (uri)) &&
1344 (!GNUNET_FS_uri_test_chk (uri)) )
1345 {
1346 fsize = 0;
1347 mime = GNUNET_strdup ("GNUnet namespace");
1348 status_colour = "lightgreen";
1349 }
1350 else if (uri != NULL)
1351 {
1352 fsize = GNUNET_FS_uri_chk_get_file_size (uri);
1353 mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1354 EXTRACTOR_METATYPE_MIMETYPE,
1355 EXTRACTOR_METATYPE_FORMAT,
1356 -1);
1357 status_colour = "white";
1358 }
1359 else
1360 {
1361 fsize = 0;
1362 status_colour = "gray";
1363 mime = NULL;
1364 }
1365 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1366 EXTRACTOR_METATYPE_PACKAGE_NAME,
1367 EXTRACTOR_METATYPE_TITLE,
1368 EXTRACTOR_METATYPE_BOOK_TITLE,
1369 EXTRACTOR_METATYPE_FILENAME,
1370 EXTRACTOR_METATYPE_DESCRIPTION,
1371 EXTRACTOR_METATYPE_SUMMARY,
1372 EXTRACTOR_METATYPE_ALBUM,
1373 EXTRACTOR_METATYPE_COMMENT,
1374 EXTRACTOR_METATYPE_SUBJECT,
1375 EXTRACTOR_METATYPE_KEYWORDS,
1376 -1);
1377 if (desc == NULL)
1378 desc = GNUNET_strdup (_("no description supplied"));
1379 if (uri == NULL)
1380 uris = GNUNET_strdup (_("no URI"));
1381 else
1382 uris = GNUNET_FS_uri_to_string (uri);
1383
1384 pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
1385 sr = GNUNET_malloc (sizeof (struct SearchResult));
1386 sr->result = result;
1387 sr->tab = tab;
1388 if (parent_rr != NULL)
1389 {
1390 /* get piter from parent */
1391 path = gtk_tree_row_reference_get_path (parent_rr);
1392 tm = gtk_tree_row_reference_get_model (parent_rr);
1393 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tm),
1394 &pmem, path))
1395 {
1396 GNUNET_break (0);
1397 gtk_tree_path_free (path);
1398 /* desperate measure: make top-level entry */
1399 pitr = NULL;
1400 }
1401 else
1402 {
1403 pitr = &pmem;
1404 }
1405 ts = GTK_TREE_STORE (tm);
1406 }
1407 else
1408 {
1409 /* top-level result */
1410 pitr = NULL;
1411 ts = tab->ts;
1412 }
1413 gtk_tree_store_insert_with_values (ts,
1414 iter,
1415 pitr,
1416 G_MAXINT,
1417 0, GNUNET_CONTAINER_meta_data_duplicate (meta),
1418 1, (uri == NULL) ? NULL : GNUNET_FS_uri_dup (uri),
1419 2, (uri == NULL) ? 0 : fsize,
1420 3, pixbuf /* preview */,
1421 4, 0 /* percent progress */,
1422 5, 0 /* percent availability */,
1423 6, desc /* filename/description */,
1424 7, uris,
1425 8, status_colour,
1426 9, sr,
1427 10, mime,
1428 11, applicability_rank,
1429 12, 0 /* avail-cert */,
1430 13, 0 /* avail-rank */,
1431 -1);
1432 if (tab != NULL)
1433 {
1434 while (tab->parent != NULL)
1435 tab = tab->parent->tab;
1436 tab->num_results++;
1437 }
1438 if (pixbuf != NULL)
1439 g_object_unref (pixbuf);
1440 GNUNET_free (uris);
1441 GNUNET_free (desc);
1442 GNUNET_free_non_null (mime);
1443 tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
1444 iter);
1445 sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
1446 tp);
1447 gtk_tree_path_free (tp);
1448 return sr;
1449}
1450
1451
1452static struct SearchResult *
1453process_search_result (void *cls,
1454 struct SearchResult *parent,
1455 const struct GNUNET_FS_Uri *uri,
1456 const struct GNUNET_CONTAINER_MetaData *meta,
1457 struct GNUNET_FS_SearchResult *result,
1458 uint32_t applicability_rank)
1459{
1460 struct SearchTab *tab = cls;
1461 struct SearchResult *sr;
1462 GtkTreeIter iter;
1463
1464 sr = GNUNET_GTK_add_search_result (tab, &iter,
1465 (parent != NULL) ? parent->rr : NULL,
1466 uri,
1467 meta, result, applicability_rank);
1468 update_search_label (tab);
1469 return sr;
1470}
1471
1472
1473/**
1474 * Setup a new top-level entry in the URI tab. If necessary, create
1475 * the URI tab first.
1476 *
1477 * @param iter set to the new entry
1478 * @param srp set to search result
1479 * @param meta metadata for the new entry
1480 * @param uri URI for the new entry
1481 * @return NULL on error, otherwise tree store matching iter
1482 */
1483struct SearchTab *
1484GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
1485 struct SearchResult **srp,
1486 const struct GNUNET_CONTAINER_MetaData *meta,
1487 const struct GNUNET_FS_Uri *uri)
1488{
1489 struct SearchTab *utab;
1490 struct SearchResult *sr;
1491 GtkNotebook *notebook;
1492 gint page;
1493
1494 utab = search_tab_head;
1495 while (utab != NULL)
1496 {
1497 if (utab->sc == NULL)
1498 break;
1499 utab = utab->next;
1500 }
1501 if (utab == NULL)
1502 {
1503 utab = setup_search (NULL, NULL);
1504 gtk_widget_set_visible (utab->close_button,
1505 FALSE);
1506 gtk_widget_set_visible (utab->pause_button,
1507 FALSE);
1508 }
1509 else
1510 {
1511 /* make 'utab' the current page */
1512 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1513 for (page=0;page<gtk_notebook_get_n_pages (notebook);page++)
1514 if (utab->frame ==
1515 gtk_notebook_get_nth_page (notebook,
1516 page))
1517 {
1518 gtk_notebook_set_current_page (notebook,
1519 page);
1520 break;
1521 }
1522 }
1523 sr = GNUNET_GTK_add_search_result (utab, iter,
1524 NULL, uri, meta,
1525 NULL, 0);
1526
1527 if (NULL != srp)
1528 *srp = sr;
1529 return utab;
1530}
1531
1532
1533static struct SearchTab *
1534handle_search_error (struct SearchTab *sr,
1535 const char *emsg)
1536{
1537 /* FIXME: implement error handler */
1538 GNUNET_break (0);
1539 return sr;
1540}
1541
1542
1543static struct SearchResult *
1544update_search_result (struct SearchResult *sr,
1545 const struct GNUNET_CONTAINER_MetaData *meta,
1546 int32_t availability_rank,
1547 uint32_t availability_certainty,
1548 uint32_t applicability_rank)
1549{
1550 GtkTreeIter iter;
1551 struct GNUNET_CONTAINER_MetaData *ometa;
1552 GtkTreeView *tv;
1553 GtkTreePath *tp;
1554 GtkTreeStore *ts;
1555 GtkTreeModel *tm;
1556 char *desc;
1557 char *mime;
1558 GdkPixbuf *pixbuf;
1559 guint percent_avail;
1560 GtkNotebook *notebook;
1561 gint page;
1562
1563 if (sr == NULL)
1564 return NULL;
1565 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1566 EXTRACTOR_METATYPE_PACKAGE_NAME,
1567 EXTRACTOR_METATYPE_TITLE,
1568 EXTRACTOR_METATYPE_BOOK_TITLE,
1569 EXTRACTOR_METATYPE_FILENAME,
1570 EXTRACTOR_METATYPE_DESCRIPTION,
1571 EXTRACTOR_METATYPE_SUMMARY,
1572 EXTRACTOR_METATYPE_ALBUM,
1573 EXTRACTOR_METATYPE_COMMENT,
1574 EXTRACTOR_METATYPE_SUBJECT,
1575 EXTRACTOR_METATYPE_KEYWORDS,
1576 -1);
1577 if (desc == NULL)
1578 desc = GNUNET_strdup (_("no description supplied"));
1579 mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1580 EXTRACTOR_METATYPE_MIMETYPE,
1581 EXTRACTOR_METATYPE_FORMAT,
1582 -1);
1583 pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
1584 tp = gtk_tree_row_reference_get_path (sr->rr);
1585 tm = gtk_tree_row_reference_get_model (sr->rr);
1586 ts = GTK_TREE_STORE (tm);
1587 gtk_tree_model_get_iter (tm, &iter, tp);
1588 gtk_tree_path_free (tp);
1589 gtk_tree_model_get (tm,
1590 &iter,
1591 0, &ometa,
1592 -1);
1593 if (meta != NULL)
1594 GNUNET_CONTAINER_meta_data_destroy (ometa);
1595 if (availability_certainty > 0)
1596 percent_avail = (availability_certainty + availability_rank) * 50 / availability_certainty;
1597 else
1598 percent_avail = 0;
1599 gtk_tree_store_set (ts,
1600 &iter,
1601 0, GNUNET_CONTAINER_meta_data_duplicate (meta),
1602 3, pixbuf /* preview */,
1603 5, (guint) percent_avail /* percent availability */,
1604 6, desc /* filename/description */,
1605 10, mime,
1606 11, (guint) applicability_rank,
1607 12, (guint) availability_certainty,
1608 13, (gint) availability_rank,
1609 -1);
1610 if (pixbuf != NULL)
1611 g_object_unref (pixbuf);
1612 GNUNET_free (desc);
1613 GNUNET_free_non_null (mime);
1614
1615 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1616 page = gtk_notebook_get_current_page (notebook);
1617 if (gtk_notebook_get_nth_page (notebook,
1618 page) == sr->tab->frame)
1619 {
1620 tv = GTK_TREE_VIEW (gtk_builder_get_object (sr->tab->builder,
1621 "_search_result_frame"));
1622
1623 update_meta_data_views (tv,
1624 sr->tab);
1625 }
1626 return sr;
1627}
1628
1629
1630static void
1631free_search_result (struct SearchResult *sr)
1632{
1633 GtkTreePath *tp;
1634 GtkTreeModel *tm;
1635 GtkTreeIter iter;
1636 struct GNUNET_FS_Uri *uri;
1637 struct GNUNET_CONTAINER_MetaData *meta;
1638
1639 if (sr == NULL)
1640 {
1641 GNUNET_break (0);
1642 return;
1643 }
1644 tp = gtk_tree_row_reference_get_path (sr->rr);
1645 tm = gtk_tree_row_reference_get_model (sr->rr);
1646 gtk_tree_model_get_iter (tm, &iter, tp);
1647 gtk_tree_path_free (tp);
1648 gtk_tree_model_get (tm,
1649 &iter,
1650 0, &meta,
1651 1, &uri,
1652 -1);
1653 if (uri != NULL)
1654 GNUNET_FS_uri_destroy (uri);
1655 if (meta != NULL)
1656 GNUNET_CONTAINER_meta_data_destroy (meta);
1657 gtk_tree_row_reference_free (sr->rr);
1658 gtk_tree_store_remove (GTK_TREE_STORE (tm),
1659 &iter);
1660 GNUNET_free (sr);
1661}
1662
1663
1664/**
1665 * Tell FS to stop publishing.
1666 */
1667static void
1668stop_publishing (GtkButton *button,
1669 gpointer user_data)
1670{
1671 struct PublishTab *tab = user_data;
1672 struct GNUNET_FS_PublishContext *pc;
1673
1674 if (NULL != (pc = tab->pc))
1675 {
1676 tab->pc = NULL;
1677 GNUNET_FS_publish_stop (pc);
1678 }
1679}
1680
1681
1682static struct PublishEntry *
1683setup_publish (struct GNUNET_FS_PublishContext *pc,
1684 const char *fn,
1685 uint64_t fsize,
1686 struct PublishEntry *parent)
1687{
1688 struct PublishTab *tab;
1689 struct PublishEntry *ent;
1690 GtkTreeIter *pitrptr;
1691 GtkTreeIter iter;
1692 GtkTreeIter piter;
1693 GtkTreePath *path;
1694 GtkWindow *df;
1695 GtkWidget *tab_label;
1696 GtkLabel *fn_label;
1697 GtkWidget *close_button;
1698 GtkNotebook *notebook;
1699 gint pages;
1700 char *size_fancy;
1701
1702 if (NULL == parent)
1703 {
1704 /* create new tab */
1705 tab = GNUNET_malloc (sizeof (struct PublishTab));
1706 tab->pc = pc;
1707 GNUNET_CONTAINER_DLL_insert (publish_tab_head,
1708 publish_tab_tail,
1709 tab);
1710 tab->builder = GNUNET_GTK_get_new_builder ("publish_tab.glade");
1711 df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1712 "_publish_frame_window"));
1713 tab->frame = gtk_bin_get_child (GTK_BIN (df));
1714 gtk_widget_ref (tab->frame);
1715 gtk_container_remove (GTK_CONTAINER (df), tab->frame);
1716 gtk_widget_destroy (GTK_WIDGET (df));
1717
1718 /* load tab_label */
1719 df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1720 "_publish_label_window"));
1721 tab_label = gtk_bin_get_child (GTK_BIN (df));
1722 gtk_widget_ref (tab_label);
1723 gtk_container_remove (GTK_CONTAINER (df), tab_label);
1724 gtk_widget_destroy (GTK_WIDGET (df));
1725
1726 /* get refs to widgets */
1727 fn_label = GTK_LABEL (gtk_builder_get_object (tab->builder,
1728 "_publish_label_window_label"));
1729 gtk_label_set_text (fn_label, fn);
1730 close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1731 "_publish_label_close_button"));
1732 g_signal_connect(G_OBJECT(close_button), "clicked",
1733 G_CALLBACK(stop_publishing), tab);
1734 /* make visible */
1735 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1736 pages = gtk_notebook_get_n_pages (notebook);
1737 gtk_notebook_insert_page (notebook,
1738 tab->frame,
1739 tab_label,
1740 pages - 1);
1741 gtk_widget_show (GTK_WIDGET (notebook));
1742 tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
1743 "_publish_frame_tree_store"));
1744 pitrptr = NULL;
1745 }
1746 else
1747 {
1748 /* create new iter from parent */
1749 tab = parent->tab;
1750 path = gtk_tree_row_reference_get_path (parent->rr);
1751 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tab->ts),
1752 &piter, path))
1753 {
1754 GNUNET_break (0);
1755 return NULL;
1756 }
1757 pitrptr = &piter;
1758 }
1759 size_fancy = GNUNET_STRINGS_byte_size_fancy (fsize);
1760 gtk_tree_store_insert_with_values (tab->ts,
1761 &iter,
1762 pitrptr,
1763 G_MAXINT,
1764 0, fn,
1765 1, size_fancy,
1766 2, "white",
1767 3, (guint) 0 /* progress */,
1768 -1);
1769 GNUNET_free (size_fancy);
1770 ent = GNUNET_malloc (sizeof (struct PublishEntry));
1771 ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
1772 ent->tab = tab;
1773 path = gtk_tree_model_get_path (GTK_TREE_MODEL (tab->ts), &iter);
1774 ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (tab->ts),
1775 path);
1776 gtk_tree_path_free (path);
1777 ent->pc = pc;
1778 return ent;
1779}
1780
1781
1782/**
1783 * Notification of FS to a client about the progress of an
1784 * operation. Callbacks of this type will be used for uploads,
1785 * downloads and searches. Some of the arguments depend a bit
1786 * in their meaning on the context in which the callback is used.
1787 *
1788 * @param cls closure
1789 * @param info details about the event, specifying the event type
1790 * and various bits about the event
1791 * @return client-context (for the next progress call
1792 * for this operation; should be set to NULL for
1793 * SUSPEND and STOPPED events). The value returned
1794 * will be passed to future callbacks in the respective
1795 * field in the GNUNET_FS_ProgressInfo struct.
1796 */
1797void*
1798GNUNET_GTK_fs_event_handler (void *cls,
1799 const struct GNUNET_FS_ProgressInfo *info)
1800{
1801 void *ret;
1802
1803 switch (info->status)
1804 {
1805 case GNUNET_FS_STATUS_PUBLISH_START:
1806 return setup_publish (info->value.publish.pc,
1807 info->value.publish.filename,
1808 info->value.publish.size,
1809 info->value.publish.pctx);
1810 case GNUNET_FS_STATUS_PUBLISH_RESUME:
1811 ret = setup_publish (info->value.publish.pc,
1812 info->value.publish.filename,
1813 info->value.publish.size,
1814 info->value.publish.pctx);
1815 if (ret == NULL)
1816 return ret;
1817 if (info->value.publish.specifics.resume.message != NULL)
1818 {
1819 ret = handle_publish_error (ret,
1820 info->value.publish.specifics.resume.message);
1821 }
1822 else if (info->value.publish.specifics.resume.chk_uri != NULL)
1823 {
1824 ret = handle_publish_completed (ret,
1825 info->value.publish.specifics.resume.chk_uri);
1826 }
1827 return ret;
1828 case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
1829 close_publish_tab (info->value.publish.cctx);
1830 return NULL;
1831 case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
1832 return mark_publish_progress (info->value.publish.cctx,
1833 info->value.publish.size,
1834 info->value.publish.completed);
1835 case GNUNET_FS_STATUS_PUBLISH_ERROR:
1836 return handle_publish_error (info->value.publish.cctx,
1837 info->value.publish.specifics.error.message);
1838 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
1839 return handle_publish_completed (info->value.publish.cctx,
1840 info->value.publish.specifics.completed.chk_uri);
1841 case GNUNET_FS_STATUS_PUBLISH_STOPPED:
1842 close_publish_tab (info->value.publish.cctx);
1843 return NULL;
1844 case GNUNET_FS_STATUS_DOWNLOAD_START:
1845 return setup_download (info->value.download.cctx,
1846 info->value.download.pctx,
1847 info->value.download.sctx,
1848 info->value.download.dc,
1849 info->value.download.uri,
1850 info->value.download.specifics.start.meta,
1851 info->value.download.size,
1852 info->value.download.completed);
1853 case GNUNET_FS_STATUS_DOWNLOAD_RESUME:
1854 ret = setup_download (info->value.download.cctx,
1855 info->value.download.pctx,
1856 info->value.download.sctx,
1857 info->value.download.dc,
1858 info->value.download.uri,
1859 info->value.download.specifics.resume.meta,
1860 info->value.download.size,
1861 info->value.download.completed);
1862 if (info->value.download.specifics.resume.message != NULL)
1863 {
1864 ret = mark_download_error (ret,
1865 info->value.download.specifics.resume.message);
1866 }
1867 return ret;
1868 case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND:
1869 stop_download (info->value.download.cctx, GNUNET_YES);
1870 return NULL;
1871 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
1872 return mark_download_progress (info->value.download.cctx,
1873 info->value.download.size,
1874 info->value.download.completed,
1875 info->value.download.specifics.progress.data,
1876 info->value.download.specifics.progress.offset,
1877 info->value.download.specifics.progress.data_len,
1878 info->value.download.specifics.progress.depth);
1879 case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
1880 return mark_download_error (info->value.download.cctx,
1881 info->value.download.specifics.error.message);
1882 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
1883 return mark_download_completed (info->value.download.cctx,
1884 info->value.download.size,
1885 info->value.download.filename);
1886 case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
1887 stop_download (info->value.download.cctx, GNUNET_NO);
1888 return NULL;
1889 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
1890 return change_download_colour (info->value.download.cctx,
1891 "yellow");
1892 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
1893 return change_download_colour (info->value.download.cctx,
1894 "blue");
1895 case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT:
1896 return download_lost_parent (info->value.download.cctx,
1897 info->value.download.size,
1898 info->value.download.completed,
1899 info->value.download.is_active);
1900 case GNUNET_FS_STATUS_SEARCH_START:
1901 if (info->value.search.pctx != NULL)
1902 return setup_inner_search (info->value.search.sc,
1903 info->value.search.pctx);
1904 return setup_search (info->value.search.sc,
1905 info->value.search.query);
1906 case GNUNET_FS_STATUS_SEARCH_RESUME:
1907 ret = setup_search (info->value.search.sc,
1908 info->value.search.query);
1909 if (info->value.search.specifics.resume.message)
1910 ret = handle_search_error (ret,
1911 info->value.search.specifics.resume.message);
1912 return ret;
1913 case GNUNET_FS_STATUS_SEARCH_RESUME_RESULT:
1914 ret = process_search_result (info->value.search.cctx,
1915 info->value.search.pctx,
1916 info->value.search.specifics.resume_result.uri,
1917 info->value.search.specifics.resume_result.meta,
1918 info->value.search.specifics.resume_result.result,
1919 info->value.search.specifics.resume_result.applicability_rank);
1920 return update_search_result (ret,
1921 info->value.search.specifics.resume_result.meta,
1922 info->value.search.specifics.resume_result.applicability_rank,
1923 info->value.search.specifics.resume_result.availability_certainty,
1924 info->value.search.specifics.resume_result.availability_rank);
1925 case GNUNET_FS_STATUS_SEARCH_SUSPEND:
1926 close_search_tab (info->value.search.cctx);
1927 return NULL;
1928 case GNUNET_FS_STATUS_SEARCH_RESULT:
1929 return process_search_result (info->value.search.cctx,
1930 info->value.search.pctx,
1931 info->value.search.specifics.result.uri,
1932 info->value.search.specifics.result.meta,
1933 info->value.search.specifics.result.result,
1934 info->value.search.specifics.result.applicability_rank);
1935 case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE:
1936 GNUNET_break (0);
1937 break;
1938 case GNUNET_FS_STATUS_SEARCH_UPDATE:
1939 return update_search_result (info->value.search.specifics.update.cctx,
1940 info->value.search.specifics.update.meta,
1941 info->value.search.specifics.update.applicability_rank,
1942 info->value.search.specifics.update.availability_certainty,
1943 info->value.search.specifics.update.availability_rank);
1944 case GNUNET_FS_STATUS_SEARCH_ERROR:
1945 return handle_search_error (info->value.search.cctx,
1946 info->value.search.specifics.error.message);
1947 case GNUNET_FS_STATUS_SEARCH_PAUSED:
1948 return info->value.search.cctx;
1949 case GNUNET_FS_STATUS_SEARCH_CONTINUED:
1950 return info->value.search.cctx;
1951 case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
1952 free_search_result (info->value.search.specifics.result_suspend.cctx);
1953 return NULL;
1954 case GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND:
1955 free_search_result (info->value.search.specifics.result_suspend.cctx);
1956 return NULL;
1957 case GNUNET_FS_STATUS_SEARCH_STOPPED:
1958 close_search_tab (info->value.search.cctx);
1959 return NULL;
1960 case GNUNET_FS_STATUS_UNINDEX_START:
1961 GNUNET_break (0);
1962 break;
1963 case GNUNET_FS_STATUS_UNINDEX_RESUME:
1964 GNUNET_break (0);
1965 break;
1966 case GNUNET_FS_STATUS_UNINDEX_SUSPEND:
1967 GNUNET_break (0);
1968 break;
1969 case GNUNET_FS_STATUS_UNINDEX_PROGRESS:
1970 GNUNET_break (0);
1971 break;
1972 case GNUNET_FS_STATUS_UNINDEX_ERROR:
1973 GNUNET_break (0);
1974 break;
1975 case GNUNET_FS_STATUS_UNINDEX_COMPLETED:
1976 GNUNET_break (0);
1977 break;
1978 case GNUNET_FS_STATUS_UNINDEX_STOPPED:
1979 GNUNET_break (0);
1980 break;
1981 default:
1982 GNUNET_break (0);
1983 break;
1984 }
1985 return NULL;
1986}
1987
1988
1989/**
1990 * Page switched in main notebook, update thumbnail and
1991 * metadata views.
1992 */
1993void
1994GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy,
1995 gpointer data)
1996{
1997 GtkNotebook *notebook;
1998 gint page;
1999 GtkWidget *w;
2000 struct SearchTab *tab;
2001 GtkImage *image;
2002 GtkListStore *ms;
2003 GtkTreeView *tv;
2004
2005 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
2006 page = gtk_notebook_get_current_page (notebook);
2007 w = gtk_notebook_get_nth_page (notebook, page);
2008 tab = search_tab_head;
2009 while (tab != NULL)
2010 {
2011 if (tab->frame == w)
2012 {
2013 tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
2014 "_search_result_frame"));
2015 update_meta_data_views (tv, tab);
2016 return;
2017 }
2018 tab = tab->next;
2019 }
2020 image = GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_preview_image"));
2021 gtk_image_clear (image);
2022 ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_meta_data_list_store"));
2023 gtk_list_store_clear (ms);
2024}
2025
2026
2027
2028/* end of fs_event_handler.c */
diff --git a/src/fs/fs_event_handler.h b/src/fs/fs_event_handler.h
new file mode 100644
index 00000000..a86ff339
--- /dev/null
+++ b/src/fs/fs_event_handler.h
@@ -0,0 +1,198 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs_event_handler.h
23 * @brief Main event handler for file-sharing
24 * @author Christian Grothoff
25 */
26#include "common.h"
27
28
29struct SearchResult;
30
31
32/**
33 * Context we keep for a search tab.
34 */
35struct SearchTab
36{
37 /**
38 * This is a doubly-linked list.
39 */
40 struct SearchTab *next;
41
42 /**
43 * This is a doubly-linked list.
44 */
45 struct SearchTab *prev;
46
47 /**
48 * Set in case this is an inner search, otherwise NULL.
49 */
50 struct SearchResult *parent;
51
52 /**
53 * Handle for this search with FS library.
54 */
55 struct GNUNET_FS_SearchContext *sc;
56
57 char *query_txt;
58
59 GtkBuilder *builder;
60
61 GtkWidget *frame;
62
63 GtkWidget *tab_label;
64
65 GtkWidget *close_button;
66
67 GtkWidget *clear_button;
68
69 GtkWidget *play_button;
70
71 GtkWidget *pause_button;
72
73 GtkLabel *label;
74
75 GtkTreeStore *ts;
76
77 unsigned int num_results;
78
79};
80
81
82struct DownloadEntry
83{
84
85 /**
86 * Download entry of the parent (for recursive downloads),
87 * NULL if we are either a top-level download (from URI,
88 * from opened directory, orphaned from search or direct
89 * search result).
90 */
91 struct DownloadEntry *pde;
92
93 /**
94 * Associated search result, or NULL if we don't belong
95 * to a search directly (download entry).
96 */
97 struct SearchResult *sr;
98
99 /**
100 * FS handle to control the download.
101 */
102 struct GNUNET_FS_DownloadContext *dc;
103
104 /**
105 * URI for the download.
106 */
107 struct GNUNET_FS_Uri *uri;
108
109 /**
110 * Meta data for the download.
111 */
112 struct GNUNET_CONTAINER_MetaData *meta;
113
114 /**
115 * Where in the tree view is this download being displayed.
116 */
117 GtkTreeRowReference *rr;
118
119 /**
120 * Tree store where we are stored.
121 */
122 GtkTreeStore *ts;
123
124 /**
125 * Tab where this download is currently on display.
126 */
127 struct SearchTab *tab;
128
129 /**
130 * Has the download completed (or errored)?
131 */
132 int is_done;
133
134};
135
136
137
138
139/**
140 * Setup a new top-level entry in the URI tab. If necessary, create
141 * the URI tab first.
142 *
143 * @param iter set to the new entry
144 * @param srp set to search result
145 * @param meta metadata for the new entry
146 * @param uri URI for the new entry
147 * @return NULL on error, otherwise search tab with the new entry
148 */
149struct SearchTab *
150GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
151 struct SearchResult **sr,
152 const struct GNUNET_CONTAINER_MetaData *meta,
153 const struct GNUNET_FS_Uri *uri);
154
155
156
157/**
158 * Add a search result to the given search tab.
159 *
160 * @param tab search tab to extend
161 * @param iter set to position where search result is added
162 * @param parent_rr reference to parent entry in search tab
163 * @param uri uri to add
164 * @param meta metadata of the entry
165 * @param result associated FS search result (can be NULL)
166 * @param applicability_rank how relevant is the result
167 * @return entry for the search result
168 */
169struct SearchResult *
170GNUNET_GTK_add_search_result (struct SearchTab *tab,
171 GtkTreeIter *iter,
172 GtkTreeRowReference *parent_rr,
173 const struct GNUNET_FS_Uri *uri,
174 const struct GNUNET_CONTAINER_MetaData *meta,
175 struct GNUNET_FS_SearchResult *result,
176 uint32_t applicability_rank);
177
178
179/**
180 * Notification of FS to a client about the progress of an
181 * operation. Callbacks of this type will be used for uploads,
182 * downloads and searches. Some of the arguments depend a bit
183 * in their meaning on the context in which the callback is used.
184 *
185 * @param cls closure
186 * @param info details about the event, specifying the event type
187 * and various bits about the event
188 * @return client-context (for the next progress call
189 * for this operation; should be set to NULL for
190 * SUSPEND and STOPPED events). The value returned
191 * will be passed to future callbacks in the respective
192 * field in the GNUNET_FS_ProgressInfo struct.
193 */
194void* GNUNET_GTK_fs_event_handler (void *cls,
195 const struct GNUNET_FS_ProgressInfo *info);
196
197
198/* end of fs_event_handler.h */
diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c
new file mode 100644
index 00000000..2fe466e4
--- /dev/null
+++ b/src/fs/gnunet-fs-gtk.c
@@ -0,0 +1,249 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/gnunet-gtk.c
23 * @brief Main function of gnunet-gtk
24 * @author Christian Grothoff
25 */
26#include "common.h"
27#include "fs_event_handler.h"
28
29/**
30 * Should gnunet-gtk start in tray mode?
31 */
32static int tray_only;
33
34/**
35 * Handle to our main loop.
36 */
37static struct GNUNET_GTK_MainLoop *ml;
38
39/**
40 * Handle for file-sharing operations.
41 */
42static struct GNUNET_FS_Handle *fs;
43
44/**
45 * List of plugins for meta data extraction.
46 */
47static struct EXTRACTOR_PluginList *plugins;
48
49
50/**
51 * Return handle for file-sharing operations.
52 *
53 * @return NULL on error
54 */
55struct GNUNET_FS_Handle *
56GNUNET_FS_GTK_get_fs_handle ()
57{
58 return fs;
59}
60
61
62/**
63 * Get LE plugin list.
64 */
65struct EXTRACTOR_PluginList *
66GNUNET_FS_GTK_get_le_plugins ()
67{
68 return plugins;
69}
70
71
72/**
73 * Get cfg.
74 */
75const struct GNUNET_CONFIGURATION_Handle *
76GNUNET_FS_GTK_get_configuration (void)
77{
78 return GNUNET_GTK_main_loop_get_configuration (ml);
79}
80
81
82/**
83 * Get an object from the main window.
84 *
85 * @param name name of the object
86 * @return NULL on error
87 */
88GObject *
89GNUNET_FS_GTK_get_main_window_object (const char *name)
90{
91 return GNUNET_GTK_main_loop_get_object (ml, name);
92}
93
94
95/**
96 * Task run on shutdown.
97 * FIXME: does this need to be a separate task!?
98 */
99static void
100shutdown_task (void *cls,
101 const struct GNUNET_SCHEDULER_TaskContext *tc)
102{
103 if (fs != NULL)
104 {
105 GNUNET_FS_stop (fs);
106 fs = NULL;
107 }
108 EXTRACTOR_plugin_remove_all (plugins);
109 plugins = NULL;
110}
111
112
113/**
114 * Callback invoked if the application is supposed to exit.
115 */
116void
117GNUNET_GTK_quit_cb (GtkObject *object,
118 gpointer user_data)
119{
120 GNUNET_GTK_tray_icon_destroy ();
121 GNUNET_GTK_main_loop_quit (ml);
122 GNUNET_SCHEDULER_add_now (&shutdown_task,
123 NULL);
124}
125
126
127/**
128 * Search selected in 'file' menu. (from main_window_file_search.c)
129 */
130void
131GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
132 gpointer data);
133
134
135/**
136 * Add the tab with the 'new' icon for starting a search.
137 */
138static void
139add_new_tab ()
140{
141 GtkNotebook *notebook;
142 GtkWindow *sf;
143 gint pages;
144 GtkBuilder *builder;
145 GtkWidget *label;
146 GtkWidget *frame;
147
148 builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_main_tab_new_frame.glade");
149
150 /* load frame */
151 sf = GTK_WINDOW (gtk_builder_get_object (builder,
152 "_main_tab_new_frame"));
153 label = gtk_bin_get_child (GTK_BIN (sf));
154 gtk_widget_ref (label);
155 gtk_container_remove (GTK_CONTAINER (sf), label);
156 gtk_widget_destroy (GTK_WIDGET (sf));
157 g_object_unref (builder);
158 g_signal_connect(G_OBJECT(label), "clicked",
159 G_CALLBACK(&GNUNET_GTK_main_menu_file_search_activate_cb), NULL);
160
161 notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
162 pages = gtk_notebook_get_n_pages (notebook);
163 frame = gtk_label_new ("");
164 gtk_widget_show (frame);
165 gtk_notebook_append_page (notebook,
166 frame,
167 label);
168 gtk_notebook_set_current_page (notebook,
169 pages);
170 gtk_widget_show (GTK_WIDGET (notebook));
171}
172
173
174/**
175 * Actual main function run right after GNUnet's scheduler
176 * is initialized. Initializes up GTK and Glade.
177 */
178static void
179run (void *cls,
180 const struct GNUNET_SCHEDULER_TaskContext *tc)
181{
182 GtkWidget *main_window;
183 ml = cls;
184
185 GNUNET_GTK_set_icon_search_path ();
186 GNUNET_GTK_setup_nls ();
187
188 /* setup main window */
189 main_window = GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_window"));
190 gtk_window_maximize (GTK_WINDOW (main_window));
191 GNUNET_GTK_tray_icon_create (GTK_WINDOW (main_window),
192 "gnunet-gtk" /* FIXME: rename icon? */,
193 "gnunet-fs-gtk");
194
195 /* initialize file-sharing */
196 plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
197 fs = GNUNET_FS_start (GNUNET_GTK_main_loop_get_configuration (ml),
198 "gnunet-gtk",
199 &GNUNET_GTK_fs_event_handler,
200 NULL,
201 GNUNET_FS_FLAGS_NONE /* fixme later for persistence/probes */,
202 /* set other options here later! */
203 GNUNET_FS_OPTIONS_END);
204 if (fs != NULL)
205 {
206 add_new_tab ();
207 }
208 else
209 {
210 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_create_pseudonym")));
211 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_advertise_pseudonym")));
212 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_publish")));
213 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_search")));
214 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_download_uri")));
215 gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ("GNUNET_GTK_main_menu_file_open_gnunet_directory")));
216 /* FIXME: set warning in status bar... */
217 }
218 /* make GUI visible */
219 if (!tray_only)
220 {
221 gtk_widget_show (main_window);
222 gtk_window_present (GTK_WINDOW (main_window));
223 }
224}
225
226
227int
228main (int argc, char *const *argv)
229{
230 static struct GNUNET_GETOPT_CommandLineOption options[] = {
231 {'t', "tray", NULL,
232 gettext_noop ("start in tray mode"), 0,
233 &GNUNET_GETOPT_set_one, &tray_only},
234 GNUNET_GETOPT_OPTION_END
235 };
236
237 if (GNUNET_OK !=
238 GNUNET_GTK_main_loop_start ("gnunet-gtk",
239 "GTK GUI for GNUnet",
240 argc, argv,
241 options,
242 "gnunet_fs_gtk_main_window.glade",
243 &run))
244 return 1;
245 return 0;
246}
247
248
249/* end of gnunet-fs-gtk.c */
diff --git a/src/fs/gnunet-fs-gtk.h b/src/fs/gnunet-fs-gtk.h
new file mode 100644
index 00000000..3b3228f2
--- /dev/null
+++ b/src/fs/gnunet-fs-gtk.h
@@ -0,0 +1,68 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs/gnunet-fs-gtk.h
23 * @brief Globals for gnunet-fs-gtk
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_FS_GTK_H
27#define GNUNET_FS_GTK_H
28
29#include "gnunet_gtk.h"
30#include <gnunet/gnunet_fs_service.h>
31#include <extractor.h>
32
33
34/**
35 * Get GNU libextractor plugin list.
36 */
37struct EXTRACTOR_PluginList *
38GNUNET_FS_GTK_get_le_plugins (void);
39
40
41/**
42 * Get our configuration.
43 */
44const struct GNUNET_CONFIGURATION_Handle *
45GNUNET_FS_GTK_get_configuration (void);
46
47
48/**
49 * Return our handle for file-sharing operations.
50 *
51 * @return NULL on error
52 */
53struct GNUNET_FS_Handle *
54GNUNET_FS_GTK_get_fs_handle (void);
55
56/**
57 * Get an object from the main window.
58 *
59 * @param name name of the object
60 * @return NULL on error
61 */
62GObject *
63GNUNET_FS_GTK_get_main_window_object (const char *name);
64
65
66
67#endif
68/* end of gnunet-fs-gtk.h */
diff --git a/src/fs/main_window_adv_pseudonym.c b/src/fs/main_window_adv_pseudonym.c
new file mode 100644
index 00000000..88a8f2b3
--- /dev/null
+++ b/src/fs/main_window_adv_pseudonym.c
@@ -0,0 +1,588 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_adv_pseudonym.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "gnunet-fs-gtk.h"
27
28static GtkBuilder *builder;
29
30
31/**
32 * Canonicalize spelling of currently selected keyword.
33 */
34void
35GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button_clicked_cb ()
36{
37 GtkTreeView *tv;
38 GtkTreeSelection *sel;
39 GtkTreeModel *tm;
40 GtkTreeIter iter;
41 gchar *value;
42 struct GNUNET_FS_Uri *uri;
43 struct GNUNET_FS_Uri *nuri;
44 char *nvalue;
45 char *emsg;
46
47 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
48 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
49 sel = gtk_tree_view_get_selection (tv);
50 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
51 {
52 GNUNET_break (0);
53 return;
54 }
55 gtk_tree_model_get (tm, &iter,
56 0, &value,
57 -1);
58 emsg = NULL;
59 uri = GNUNET_FS_uri_ksk_create (value, &emsg);
60 if (uri == NULL)
61 {
62 GNUNET_break (0);
63 GNUNET_free (emsg);
64 g_free (value);
65 return;
66 }
67 nuri = GNUNET_FS_uri_ksk_canonicalize (uri);
68 nvalue = GNUNET_FS_uri_ksk_to_string_fancy (nuri);
69 gtk_list_store_set (GTK_LIST_STORE (tm), &iter,
70 0, nvalue,
71 -1);
72 GNUNET_FS_uri_destroy (nuri);
73 GNUNET_FS_uri_destroy (uri);
74 GNUNET_free (nvalue);
75 g_free (value);
76}
77
78
79/**
80 * Remove the currently selected keyword from the list.
81 */
82void
83GNUNET_GTK_advertise_pseudonym_keyword_list_del_button_clicked_cb ()
84{
85 GtkTreeView *tv;
86 GtkTreeSelection *sel;
87 GtkTreeModel *tm;
88 GtkTreeIter iter;
89
90 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
91 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
92 sel = gtk_tree_view_get_selection (tv);
93 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
94 {
95 GNUNET_break (0);
96 return;
97 }
98 gtk_list_store_remove (GTK_LIST_STORE (tm),
99 &iter);
100}
101
102
103/**
104 * Add keyword from entry line to keyword list.
105 */
106void
107GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ()
108{
109 const char *keyword;
110 GtkEntry *entry;
111 GtkListStore *ls;
112 GtkTreeIter iter;
113
114 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
115 "GNUNET_GTK_keyword_list_store"));
116 entry = GTK_ENTRY (gtk_builder_get_object (builder,
117 "GNUNET_GTK_advertise_pseudonym_keyword_entry"));
118 keyword = gtk_entry_get_text (entry);
119 if (strlen (keyword) > 0)
120 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
121 gtk_entry_set_text (entry, "");
122}
123
124
125/**
126 * Update sensitivity of keyword add button.
127 */
128void
129GNUNET_GTK_advertise_pseudonym_keyword_entry_changed_cb ()
130{
131 const char *keyword;
132 GtkEntry *entry;
133 GtkWidget *button;
134
135 button = GTK_WIDGET (gtk_builder_get_object (builder,
136 "GNUNET_GTK_advertise_pseudonym_keyword_list_add_button"));
137 entry = GTK_ENTRY (gtk_builder_get_object (builder,
138 "GNUNET_GTK_advertise_pseudonym_keyword_entry"));
139 keyword = gtk_entry_get_text (entry);
140 gtk_widget_set_sensitive (button,
141 (strlen (keyword) > 0) ? TRUE : FALSE);
142}
143
144/**
145 * Update sensitivity of metadata delete button.
146 */
147static void
148metadata_selection_changed_cb (GtkTreeSelection *ts,
149 gpointer user_data)
150{
151 GtkTreeView *tv;
152 GtkTreeSelection *sel;
153 GtkWidget *button;
154
155 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
156 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
157 sel = gtk_tree_view_get_selection (tv);
158 button = GTK_WIDGET (gtk_builder_get_object (builder,
159 "GNUNET_GTK_advertise_pseudonym_metadata_delete_button"));
160 gtk_widget_set_sensitive (button,
161 gtk_tree_selection_get_selected (sel, NULL, NULL));
162}
163
164
165/**
166 * Update sensitivity of keyword delete and normalize button.
167 */
168static void
169keyword_selection_changed_cb (GtkTreeSelection *ts,
170 gpointer user_data)
171{
172 GtkTreeView *tv;
173 GtkTreeSelection *sel;
174 GtkWidget *button;
175
176 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
177 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
178 sel = gtk_tree_view_get_selection (tv);
179 button = GTK_WIDGET (gtk_builder_get_object (builder,
180 "GNUNET_GTK_advertise_pseudonym_keyword_list_del_button"));
181
182 gtk_widget_set_sensitive (button,
183 gtk_tree_selection_get_selected (sel, NULL, NULL));
184 button = GTK_WIDGET (gtk_builder_get_object (builder,
185 "GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button"));
186 gtk_widget_set_sensitive (button,
187 gtk_tree_selection_get_selected (sel, NULL, NULL));
188}
189
190
191/**
192 * Update sensitivity of metadata add button.
193 */
194void
195GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb ()
196{
197 GtkTreeView *tv;
198 GtkTreeSelection *sel;
199 const char *value;
200 GtkEntry *entry;
201 GtkWidget *button;
202
203 entry = GTK_ENTRY (gtk_builder_get_object (builder,
204 "GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
205 value = gtk_entry_get_text (entry);
206 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
207 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
208 sel = gtk_tree_view_get_selection (tv);
209 button = GTK_WIDGET (gtk_builder_get_object (builder,
210 "GNUNET_GTK_advertise_pseudonym_metadata_add_button"));
211 gtk_widget_set_sensitive (button,
212 (strlen (value) > 0)
213 ? gtk_tree_selection_get_selected (sel, NULL, NULL)
214 : FALSE);
215}
216
217
218/**
219 * Add keyword to keyword list.
220 */
221void
222GNUNET_GTK_advertise_pseudonym_keyword_entry_activate_cb ()
223{
224 GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ();
225}
226
227
228void
229GNUNET_GTK_advertise_pseudonym_metadata_preview_file_chooser_button_file_set_cb ()
230{
231 GNUNET_break (0);
232}
233
234/**
235 * Delete currently selected item from meta data list.
236 */
237void
238GNUNET_GTK_advertise_pseudonym_metadata_delete_button_clicked_cb()
239{
240 GtkTreeView *tv;
241 GtkTreeSelection *sel;
242 GtkTreeModel *tm;
243 GtkTreeIter iter;
244
245 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
246 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
247 sel = gtk_tree_view_get_selection (tv);
248 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
249 {
250 GNUNET_break (0);
251 return;
252 }
253 gtk_list_store_remove (GTK_LIST_STORE (tm),
254 &iter);
255}
256
257
258/**
259 * Add metadata to metadata list.
260 */
261void
262GNUNET_GTK_advertise_pseudonym_metadata_add_button_clicked_cb ()
263{
264 const char *value;
265 char *avalue;
266 const char *ivalue;
267 GtkEntry *entry;
268 GtkListStore *ls;
269 GtkTreeModel *tm;
270 GtkTreeView *tv;
271 GtkTreeSelection *sel;
272 GtkTreeIter iter;
273 guint type;
274 size_t slen;
275 char *pos;
276
277 entry = GTK_ENTRY (gtk_builder_get_object (builder,
278 "GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
279 value = gtk_entry_get_text (entry);
280 if ((value == NULL) || (strlen (value) == 0))
281 {
282 GNUNET_break (0);
283 return;
284 }
285 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
286 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
287 tm = gtk_tree_view_get_model (tv);
288 sel = gtk_tree_view_get_selection (tv);
289 if (TRUE != gtk_tree_selection_get_selected (sel,
290 &tm,
291 &iter))
292 {
293 GNUNET_break (0);
294 return;
295 }
296 gtk_tree_model_get (tm,
297 &iter,
298 1, &type, -1);
299 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
300 "GNUNET_GTK_meta_data_list_store"));
301 if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
302 (value[strlen(value)-1] != '/') )
303 {
304 GNUNET_asprintf (&avalue,
305 "%s/",
306 value);
307 /* if user typed '\' instead of '/', change it! */
308 slen = strlen (avalue);
309 while ( (slen > 1) &&
310 (avalue[slen-2] == '\\') )
311 {
312 avalue[slen-2] = '/';
313 avalue[slen-1] = '\0';
314 slen--;
315 }
316 while (NULL != (pos = strstr (avalue, "\\")))
317 *pos = '/';
318 /* remove '../' everywhere */
319 while (NULL != (pos = strstr (avalue, "../")))
320 {
321 pos[0] = '_';
322 pos[1] = '_';
323 pos[2] = '_';
324 }
325 ivalue = avalue;
326 }
327 else
328 {
329 ivalue = value;
330 avalue = NULL;
331 }
332
333 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
334 0, type,
335 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
336 2, EXTRACTOR_metatype_to_string (type),
337 3, ivalue,
338 -1);
339 GNUNET_free_non_null (avalue);
340 gtk_entry_set_text (GTK_ENTRY (entry), "");
341}
342
343
344/**
345 * Callback with information about local (!) namespaces.
346 * Contains the names of the local namespace and the global
347 * ID. Adds the to the list store.
348 *
349 * @param cls closure, the list store.
350 * @param name human-readable identifier of the namespace
351 * @param id hash identifier for the namespace
352 */
353static void
354add_to_list (void *cls,
355 const char *name,
356 const GNUNET_HashCode *id)
357{
358 GtkListStore *ls = cls;
359 GtkTreeIter iter;
360
361 gtk_list_store_insert_with_values (ls,
362 &iter,
363 -1,
364 0, name,
365 1, GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (),
366 name),
367 -1);
368
369}
370
371
372static void
373selection_changed_cb (GtkTreeSelection *ts,
374 gpointer user_data)
375{
376 GtkTreeIter iter;
377 GtkWidget *ok_button;
378
379 ok_button = GTK_WIDGET (gtk_builder_get_object (builder,
380 "GNUNET_GTK_select_pseudonym_ok_button"));
381 if (TRUE == gtk_tree_selection_get_selected (ts, NULL, &iter))
382 gtk_widget_set_sensitive (ok_button, TRUE);
383 else
384 gtk_widget_set_sensitive (ok_button, FALSE);
385}
386
387
388/**
389 * Advertise pseudonym selected.
390 */
391void
392GNUNET_GTK_main_menu_file_advertise_pseudonym_activate_cb (GtkWidget * dummy,
393 gpointer data)
394{
395 GtkWidget *ad;
396 struct GNUNET_FS_Namespace *ns;
397 struct GNUNET_FS_Namespace *nso;
398 GtkListStore *ls;
399 GtkTreeView *tv;
400 GtkTreeIter iter;
401 GtkTreeSelection *sel;
402 GtkTreeModel *tm;
403 GtkSpinButton *sb;
404 struct GNUNET_FS_BlockOptions bo;
405 struct GNUNET_FS_Uri *nxt;
406 struct GNUNET_FS_Uri *mrg;
407 struct GNUNET_FS_Uri *uri;
408 struct GNUNET_CONTAINER_MetaData *nm;
409 const char *root;
410 char *value;
411 guint ntype;
412 guint nformat;
413 guint type;
414 guint max_type;
415
416 builder = GNUNET_GTK_get_new_builder ("select_pseudonym_dialog.glade");
417 if (builder == NULL)
418 {
419 GNUNET_break (0);
420 return;
421 }
422 ad = GTK_WIDGET (gtk_builder_get_object (builder,
423 "GNUNET_GTK_select_pseudonym_dialog"));
424 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
425 "GNUNET_GTK_select_pseudonym_liststore"));
426 GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
427 &add_to_list,
428 ls);
429 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
430 "GNUNET_GTK_select_pseudonym_tree_view"));
431 sel = gtk_tree_view_get_selection (tv);
432 g_signal_connect(G_OBJECT(sel), "changed",
433 G_CALLBACK(selection_changed_cb), NULL);
434 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
435 {
436 gtk_widget_destroy (ad);
437 g_object_unref (G_OBJECT (builder));
438 builder = NULL;
439 return;
440 }
441 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel,
442 &tm,
443 &iter));
444 gtk_tree_model_get (tm,
445 &iter,
446 1, &ns,
447 -1);
448 /* free all namespaces from list store except "ns" */
449 if (TRUE ==
450 gtk_tree_model_get_iter_first (tm, &iter))
451 {
452 do
453 {
454 gtk_tree_model_get (tm, &iter,
455 1, &nso,
456 -1);
457 if (ns != nso)
458 GNUNET_FS_namespace_delete (nso, GNUNET_NO);
459 }
460 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
461 }
462 gtk_widget_destroy (ad);
463 g_object_unref (G_OBJECT (builder));
464 builder = NULL;
465
466
467 builder = GNUNET_GTK_get_new_builder ("advertise_pseudonym_dialog.glade");
468 if (builder == NULL)
469 {
470 GNUNET_break (0);
471 return;
472 }
473 GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
474 ad = GTK_WIDGET (gtk_builder_get_object (builder,
475 "GNUNET_GTK_advertise_pseudonym_dialog"));
476 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
477 "GNUNET_GTK_metatype_list_store"));
478 max_type = EXTRACTOR_metatype_get_max ();
479 type = 1;
480 while (type < max_type - 1)
481 {
482 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
483 0, EXTRACTOR_metatype_to_string (type),
484 1, type,
485 2, EXTRACTOR_metatype_to_description (type),
486 -1);
487 type++;
488 }
489 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
490 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
491 sel = gtk_tree_view_get_selection (tv);
492 g_signal_connect(G_OBJECT(sel), "changed",
493 G_CALLBACK(GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb), NULL);
494
495 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
496 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
497 sel = gtk_tree_view_get_selection (tv);
498 g_signal_connect(G_OBJECT(sel), "changed",
499 G_CALLBACK(metadata_selection_changed_cb), NULL);
500
501 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
502 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
503 sel = gtk_tree_view_get_selection (tv);
504 g_signal_connect(G_OBJECT(sel), "changed",
505 G_CALLBACK(keyword_selection_changed_cb), NULL);
506 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
507 {
508 gtk_widget_destroy (ad);
509 g_object_unref (G_OBJECT (builder));
510 builder = NULL;
511 return;
512 }
513 /* get keywords from list store */
514 nxt = NULL;
515 mrg = NULL;
516 uri = NULL;
517 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
518 "GNUNET_GTK_keyword_list_store"));
519 if (TRUE ==
520 gtk_tree_model_get_iter_first (tm, &iter))
521 {
522 do
523 {
524 gtk_tree_model_get (tm, &iter,
525 0, &value,
526 -1);
527 nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
528 mrg = GNUNET_FS_uri_ksk_merge (nxt, uri);
529 GNUNET_FS_uri_destroy (nxt);
530 if (NULL != uri)
531 GNUNET_FS_uri_destroy (uri);
532 uri = mrg;
533 g_free (value);
534 }
535 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
536 }
537 /* get meta */
538 nm = GNUNET_CONTAINER_meta_data_create ();
539 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
540 "GNUNET_GTK_meta_data_list_store"));
541 if (TRUE ==
542 gtk_tree_model_get_iter_first (tm, &iter))
543 {
544 do
545 {
546 gtk_tree_model_get (tm, &iter,
547 0, &ntype,
548 1, &nformat,
549 3, &value,
550 -1);
551 GNUNET_CONTAINER_meta_data_insert (nm,
552 "<user>",
553 ntype,
554 nformat,
555 "text/plain",
556 value,
557 strlen (value)+1);
558 g_free (value);
559 }
560 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
561 }
562 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
563 "GNUNET_GTK_advertise_pseudonym_anonymity_spin_button")));
564 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
565 "GNUNET_GTK_advertise_pseudonym_priority_spin_button")));
566 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
567 "GNUNET_GTK_advertise_pseudonym_expiration_year_spin_button"));
568 bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
569 root = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
570 "GNUNET_GTK_advertise_pseudonym_root_entry")));
571 GNUNET_FS_namespace_advertise (GNUNET_FS_GTK_get_fs_handle (),
572 uri,
573 ns,
574 nm,
575 &bo,
576 root,
577 NULL, NULL);
578 GNUNET_FS_namespace_delete (ns, GNUNET_NO);
579 GNUNET_CONTAINER_meta_data_destroy (nm);
580 if (NULL != uri)
581 GNUNET_FS_uri_destroy (uri);
582 gtk_widget_destroy (ad);
583 g_object_unref (G_OBJECT (builder));
584 builder = NULL;
585}
586
587
588/* end of main_window_adv_pseudonym.c */
diff --git a/src/fs/main_window_create_pseudonym.c b/src/fs/main_window_create_pseudonym.c
new file mode 100644
index 00000000..9faf0bae
--- /dev/null
+++ b/src/fs/main_window_create_pseudonym.c
@@ -0,0 +1,65 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_create_pseudonym.c
23 * @author Christian Grothoff
24 *
25 */
26#include "common.h"
27#include "gnunet-fs-gtk.h"
28
29/**
30 */
31void
32GNUNET_GTK_main_menu_create_pseudonym_activate_cb (GtkWidget * dummy,
33 gpointer data)
34{
35 GtkWidget *ad;
36 GtkBuilder *builder;
37 const char *name;
38 struct GNUNET_FS_Namespace *ns;
39
40 builder = GNUNET_GTK_get_new_builder ("create_namespace_dialog.glade");
41 if (builder == NULL)
42 {
43 GNUNET_break (0);
44 return;
45 }
46 ad = GTK_WIDGET (gtk_builder_get_object (builder,
47 "GNUNET_GTK_create_namespace_dialog"));
48 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
49 {
50 gtk_widget_destroy (ad);
51 g_object_unref (G_OBJECT (builder));
52 return;
53 }
54 name = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
55 "GNUNET_GTK_create_namespace_name_entry")));
56 /* FIXME: show busy dialog while doing key creation */
57 ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (),
58 name);
59 GNUNET_FS_namespace_delete (ns, GNUNET_NO);
60 gtk_widget_destroy (ad);
61 g_object_unref (G_OBJECT (builder));
62}
63
64
65/* end of main_window_create_pseudonym.c */
diff --git a/src/fs/main_window_file_download.c b/src/fs/main_window_file_download.c
new file mode 100644
index 00000000..0a41bfba
--- /dev/null
+++ b/src/fs/main_window_file_download.c
@@ -0,0 +1,130 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_file_download.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "download.h"
27#include "gnunet-fs-gtk.h"
28
29static GtkBuilder *builder;
30
31void
32GNUNET_GTK_open_url_dialog_url_entry_changed_cb (GtkEditable *editable,
33 gpointer user_data)
34{
35 struct GNUNET_FS_Uri *uri;
36 char *perr;
37 const char *uris;
38
39 perr = NULL;
40 uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
41 "GNUNET_GTK_open_url_dialog_url_entry")));
42 if (uris != NULL)
43 uri = GNUNET_FS_uri_parse (uris, &perr);
44 else
45 uri = NULL;
46 gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder,
47 "GNUNET_GTK_open_url_dialog_execute_button")),
48 (uri == NULL) ? FALSE : TRUE);
49 if (uri != NULL)
50 GNUNET_FS_uri_destroy (uri);
51 else
52 GNUNET_free_non_null (perr);
53}
54
55
56/**
57 * User selected "Open URI" in main window.
58 */
59void
60GNUNET_GTK_main_menu_file_download_uri_activate_cb (GtkWidget * dummy,
61 gpointer data)
62{
63 GtkWidget *ad;
64 const char *uris;
65 uint32_t anonymity;
66 struct GNUNET_FS_Uri *uri;
67 char *perr;
68 struct DownloadContext *dc;
69
70 GNUNET_assert (builder == NULL);
71 builder = GNUNET_GTK_get_new_builder ("open_url_dialog.glade");
72 if (builder == NULL)
73 {
74 GNUNET_break (0);
75 return;
76 }
77 ad = GTK_WIDGET (gtk_builder_get_object (builder,
78 "GNUNET_GTK_open_url_dialog"));
79 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
80 {
81 gtk_widget_destroy (ad);
82 g_object_unref (G_OBJECT (builder));
83 builder = NULL;
84 fprintf (stderr,
85 "Dialog closed!\n");
86 return;
87 }
88 uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
89 "GNUNET_GTK_open_url_dialog_url_entry")));
90 anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
91 "GNUNET_GTK_open_url_dialog_anonymity_spin_button")));
92 uri = GNUNET_FS_uri_parse (uris, &perr);
93 gtk_widget_destroy (ad);
94 g_object_unref (G_OBJECT (builder));
95 builder = NULL;
96 if (uri == NULL)
97 {
98 GNUNET_free (perr);
99 /* Why was "execute" button sensitive!? */
100 GNUNET_break (0);
101 return;
102 }
103 if (GNUNET_FS_uri_test_sks (uri) ||
104 GNUNET_FS_uri_test_ksk (uri))
105 {
106 fprintf (stderr,
107 "Starting search!\n");
108 GNUNET_break (NULL !=
109 GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (),
110 uri,
111 anonymity,
112 GNUNET_FS_SEARCH_OPTION_NONE,
113 NULL));
114 GNUNET_FS_uri_destroy (uri);
115 return;
116 }
117 if (GNUNET_FS_uri_test_chk (uri) ||
118 GNUNET_FS_uri_test_loc (uri))
119 {
120 dc = GNUNET_malloc (sizeof (struct DownloadContext));
121 dc->uri = uri;
122 dc->anonymity = anonymity;
123 GNUNET_GTK_open_download_as_dialog (dc);
124 return;
125 }
126 GNUNET_break (0);
127 GNUNET_FS_uri_destroy (uri);
128}
129
130/* end of main_window_file_download.c */
diff --git a/src/fs/main_window_file_publish.c b/src/fs/main_window_file_publish.c
new file mode 100644
index 00000000..2fa46ec5
--- /dev/null
+++ b/src/fs/main_window_file_publish.c
@@ -0,0 +1,1933 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_file_publish.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "gnunet-fs-gtk.h"
27#include "edit_publish_dialog.h"
28#include <gnunet/gnunet_util_lib.h>
29
30#define MARKER_DIR_FILE_SIZE "-"
31
32/**
33 * Builder used for the master publish dialog.
34 */
35static GtkBuilder *master_builder;
36
37
38/**
39 * Check if two GtkTreeIters refer to the same element.
40 *
41 * @param tm tree model of the iterators
42 * @param i1 first iterator
43 * @param i2 second iterator
44 * @return GNUNET_YES if they are equal
45 */
46static int
47gtk_tree_iter_equals (GtkTreeModel *tm,
48 GtkTreeIter *i1,
49 GtkTreeIter *i2)
50{
51 GtkTreePath *p1;
52 GtkTreePath *p2;
53 int ret;
54
55 p1 = gtk_tree_model_get_path (tm, i1);
56 p2 = gtk_tree_model_get_path (tm, i2);
57 ret = gtk_tree_path_compare (p1, p2);
58 gtk_tree_path_free (p1);
59 gtk_tree_path_free (p2);
60 return (0 == ret) ? GNUNET_YES : GNUNET_NO;
61}
62
63
64/**
65 * Update selectivity in the master dialog.
66 */
67static void
68update_selectivity ()
69{
70 GtkTreeView *tv;
71 GtkTreeModel *tm;
72 GtkTreeModel *ptm;
73 GtkTreeSelection *sel;
74 GtkTreeIter iter;
75 GtkTreeIter parent;
76 GtkTreeIter pred;
77 GtkWidget *up_button;
78 GtkWidget *down_button;
79 GtkWidget *left_button;
80 GtkWidget *right_button;
81 GtkWidget *delete_button;
82 GtkWidget *edit_button;
83 GtkWidget *execute_button;
84 int is_dir;
85 struct GNUNET_FS_FileInformation *fip;
86 int ns_ok;
87 gchar *namespace_id;
88
89 tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
90 "GNUNET_GTK_file_sharing_publishing_tree_store"));
91 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
92 "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
93 sel = gtk_tree_view_get_selection (tv);
94 ns_ok = GNUNET_YES;
95 if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
96 {
97 gtk_tree_model_get (ptm,
98 &iter,
99 2, &namespace_id,
100 -1);
101 if (namespace_id == NULL)
102 ns_ok = GNUNET_NO;
103 else
104 g_free (namespace_id);
105 }
106 up_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
107 "GNUNET_GTK_master_publish_dialog_up_button"));
108 down_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
109 "GNUNET_GTK_master_publish_dialog_down_button"));
110 left_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
111 "GNUNET_GTK_master_publish_dialog_left_button"));
112 right_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
113 "GNUNET_GTK_master_publish_dialog_right_button"));
114 delete_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
115 "GNUNET_GTK_master_publish_dialog_delete_button"));
116 edit_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
117 "GNUNET_GTK_master_publish_dialog_edit_button"));
118 execute_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
119 "GNUNET_GTK_master_publish_dialog_execute_button"));
120 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
121 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
122 sel = gtk_tree_view_get_selection (tv);
123 tm = gtk_tree_view_get_model (tv);
124 if ( (gtk_tree_model_get_iter_first (tm, &iter)) &&
125 (ns_ok == GNUNET_YES) )
126 gtk_widget_set_sensitive (execute_button, TRUE);
127 else
128 gtk_widget_set_sensitive (execute_button, FALSE);
129 if (TRUE != gtk_tree_selection_get_selected (sel,
130 &tm,
131 &iter))
132 {
133 gtk_widget_set_sensitive (up_button, FALSE);
134 gtk_widget_set_sensitive (down_button, FALSE);
135 gtk_widget_set_sensitive (left_button, FALSE);
136 gtk_widget_set_sensitive (right_button, FALSE);
137 gtk_widget_set_sensitive (delete_button, FALSE);
138 gtk_widget_set_sensitive (edit_button, FALSE);
139 return;
140 }
141 gtk_widget_set_sensitive (delete_button, TRUE);
142 gtk_widget_set_sensitive (edit_button, TRUE);
143
144 /* now figure out which move operations are currently legal */
145 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
146 if (TRUE == gtk_tree_model_iter_next (tm, &iter))
147 {
148 gtk_widget_set_sensitive (down_button, TRUE);
149 }
150 else
151 {
152 gtk_widget_set_sensitive (down_button, FALSE);
153 }
154 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
155 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
156 {
157 gtk_widget_set_sensitive (left_button, TRUE);
158 GNUNET_assert (TRUE ==
159 gtk_tree_model_iter_children (tm, &pred, &parent));
160 }
161 else
162 {
163 gtk_widget_set_sensitive (left_button, FALSE);
164 GNUNET_assert (TRUE ==
165 gtk_tree_model_get_iter_first (tm, &pred));
166 }
167 /* iterate over 'next' of pred to find out if our
168 predecessor is a directory! */
169 is_dir = GNUNET_SYSERR;
170 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
171 {
172 gtk_tree_model_get (tm, &pred,
173 5, &fip, -1);
174 is_dir = GNUNET_FS_file_information_is_directory (fip);
175 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
176 }
177 if (GNUNET_YES == is_dir)
178 {
179 gtk_widget_set_sensitive (right_button, TRUE);
180 }
181 else
182 {
183 gtk_widget_set_sensitive (right_button, FALSE);
184 }
185 if (GNUNET_SYSERR != is_dir)
186 {
187 gtk_widget_set_sensitive (up_button, TRUE);
188 }
189 else
190 {
191 gtk_widget_set_sensitive (up_button, FALSE);
192 }
193}
194
195
196/**
197 * Add a file to the tree model.
198 *
199 * @param filename file to add
200 * @param bo block options to use
201 * @param do_index should we index or insert?
202 * @param iter parent entry, or NULL for top-level addition
203 */
204static void
205add_file_at_iter (const char *filename,
206 const struct GNUNET_FS_BlockOptions *bo,
207 int do_index,
208 GtkTreeIter *iter)
209{
210 struct GNUNET_FS_FileInformation *fi;
211 GtkTreeRowReference *row_reference;
212 GtkTreePath *path;
213 uint64_t file_size;
214 const char *short_fn;
215 struct GNUNET_CONTAINER_MetaData *meta;
216 struct GNUNET_FS_Uri *ksk_uri;
217 GtkTreeStore *ts;
218 GtkTreeIter pos;
219 char *file_size_fancy;
220 const char *ss;
221 struct stat sbuf;
222
223 if (0 != STAT (filename, &sbuf))
224 return;
225 if (S_ISDIR (sbuf.st_mode))
226 {
227 file_size = 0;
228 }
229 else
230 {
231 if (GNUNET_OK !=
232 GNUNET_DISK_file_size (filename,
233 &file_size,
234 GNUNET_YES))
235 {
236 GNUNET_break (0);
237 return;
238 }
239 }
240 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
241 "GNUNET_GTK_file_sharing_publishing_tree_store"));
242
243 meta = GNUNET_CONTAINER_meta_data_create ();
244 GNUNET_FS_meta_data_extract_from_file (meta,
245 filename,
246 GNUNET_FS_GTK_get_le_plugins());
247 GNUNET_CONTAINER_meta_data_delete (meta,
248 EXTRACTOR_METATYPE_FILENAME,
249 NULL, 0);
250 short_fn = filename;
251 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
252 short_fn = 1 + ss;
253 GNUNET_CONTAINER_meta_data_insert (meta,
254 "<gnunet-gtk>",
255 EXTRACTOR_METATYPE_FILENAME,
256 EXTRACTOR_METAFORMAT_UTF8,
257 "text/plain",
258 short_fn,
259 strlen(short_fn)+1);
260 ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
261 gtk_tree_store_insert_before (ts,
262 &pos,
263 iter,
264 NULL);
265 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
266 &pos);
267 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
268 path);
269 gtk_tree_path_free (path);
270 fi = GNUNET_FS_file_information_create_from_file (GNUNET_FS_GTK_get_fs_handle (),
271 row_reference,
272 filename,
273 ksk_uri,
274 meta,
275 do_index,
276 bo);
277 GNUNET_CONTAINER_meta_data_destroy (meta);
278 GNUNET_FS_uri_destroy (ksk_uri);
279 if (S_ISDIR (sbuf.st_mode))
280 file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
281 else
282 file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
283 gtk_tree_store_set (ts, &pos,
284 0, file_size_fancy,
285 1, (gboolean) do_index,
286 2, short_fn,
287 3, (guint) bo->anonymity_level,
288 4, (guint) bo->content_priority,
289 5, fi,
290 -1);
291 GNUNET_free (file_size_fancy);
292 update_selectivity ();
293}
294
295
296
297/**
298 * Add an empty directory to the tree model.
299 *
300 * @param name name for the directory
301 * @param bo block options
302 * @param iter parent entry, or NULL for top-level addition
303 * @param pos iterator to set to the location of the new element
304 */
305static void
306create_dir_at_iter (const char *name,
307 const struct GNUNET_FS_BlockOptions *bo,
308 GtkTreeIter *iter,
309 GtkTreeIter *pos)
310{
311 struct GNUNET_FS_FileInformation *fi;
312 GtkTreeRowReference *row_reference;
313 GtkTreePath *path;
314 struct GNUNET_CONTAINER_MetaData *meta;
315 GtkTreeStore *ts;
316
317 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
318 "GNUNET_GTK_file_sharing_publishing_tree_store"));
319 meta = GNUNET_CONTAINER_meta_data_create ();
320 GNUNET_FS_meta_data_make_directory (meta);
321 GNUNET_CONTAINER_meta_data_insert (meta,
322 "<gnunet-gtk>",
323 EXTRACTOR_METATYPE_FILENAME,
324 EXTRACTOR_METAFORMAT_UTF8,
325 "text/plain",
326 name,
327 strlen(name)+1);
328 gtk_tree_store_insert_before (ts,
329 pos,
330 iter,
331 NULL);
332 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
333 pos);
334 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
335 path);
336 gtk_tree_path_free (path);
337 fi = GNUNET_FS_file_information_create_empty_directory (GNUNET_FS_GTK_get_fs_handle (),
338 row_reference,
339 NULL,
340 meta,
341 bo);
342 GNUNET_CONTAINER_meta_data_destroy (meta);
343 gtk_tree_store_set (ts, pos,
344 0, MARKER_DIR_FILE_SIZE,
345 1, (gboolean) GNUNET_NO,
346 2, name,
347 3, (guint) bo->anonymity_level,
348 4, (guint) bo->content_priority,
349 5, fi,
350 -1);
351 update_selectivity ();
352}
353
354
355/* ************ code for adding directories starts ************* */
356
357
358/**
359 * Data we keep when calculating the publication details for a file.
360 */
361struct PublishData
362{
363 /**
364 * Metadata for the file.
365 */
366 struct GNUNET_CONTAINER_MetaData *meta;
367
368 /**
369 * Iterator for the entry.
370 */
371 GtkTreeIter iter;
372};
373
374
375/**
376 * Entry for each unique meta data entry to track how often
377 * it occured. Contains the keyword and the counter.
378 */
379struct MetaCounter
380{
381
382 /**
383 * Keyword that was found.
384 */
385 const char *value;
386
387 /**
388 * Mimetype of the value.
389 */
390 const char *value_mimetype;
391
392 /**
393 * Type of the value.
394 */
395 enum EXTRACTOR_MetaType type;
396
397 /**
398 * Format of the value.
399 */
400 enum EXTRACTOR_MetaFormat format;
401
402 /**
403 * How many files have meta entries matching this value?
404 * (type and format do not have to match).
405 */
406 unsigned int count;
407
408};
409
410
411/**
412 * Execution context for 'add_dir'
413 */
414struct AddDirContext
415{
416 /**
417 * While scanning, 'parent' is the iter entry for the
418 * parent, or NULL for top-level.
419 */
420 GtkTreeIter *parent;
421
422 /**
423 * Tree store to manipulate.
424 */
425 GtkTreeStore *ts;
426
427 /**
428 * Map from the hash over the meta value to an 'struct MetaCounter'
429 * counter that says how often this value was
430 * encountered in the current directory.
431 */
432 struct GNUNET_CONTAINER_MultiHashMap *metacounter;
433
434 /**
435 * Map from the hash of a filename in the current directory
436 * to the 'struct PublishData*' for the file.
437 */
438 struct GNUNET_CONTAINER_MultiHashMap *metamap;
439
440 /**
441 * Metadata to exclude from using for KSK since it'll be associated
442 * with the parent as well. NULL for nothing blocked.
443 */
444 struct GNUNET_CONTAINER_MetaData *no_ksk;
445
446 /**
447 * Block options to use.
448 */
449 struct GNUNET_FS_BlockOptions bo;
450
451 /**
452 * Index or insert?
453 */
454 int do_index;
455
456 /**
457 * Number of files in the current directory.
458 */
459 unsigned int dir_entry_count;
460};
461
462
463/**
464 * Add the given meta data item to the
465 * meta data statistics tracker.
466 *
467 * @param cls closure (user-defined)
468 * @param plugin_name name of the plugin that produced this value;
469 * special values can be used (i.e. '<zlib>' for zlib being
470 * used in the main libextractor library and yielding
471 * meta data).
472 * @param type libextractor-type describing the meta data
473 * @param format basic format information about data
474 * @param data_mime_type mime-type of data (not of the original file);
475 * can be NULL (if mime-type is not known)
476 * @param data actual meta-data found
477 * @param data_len number of bytes in data
478 * @return 0 to continue extracting, 1 to abort
479 */
480static int
481add_to_meta_counter (void *cls,
482 const char *plugin_name,
483 enum EXTRACTOR_MetaType type,
484 enum EXTRACTOR_MetaFormat format,
485 const char *data_mime_type,
486 const char *data,
487 size_t data_len)
488{
489 struct GNUNET_CONTAINER_MultiHashMap *mcm = cls;
490 struct MetaCounter *cnt;
491 GNUNET_HashCode hc;
492 size_t mlen;
493 size_t dlen;
494
495 if ( (format != EXTRACTOR_METAFORMAT_UTF8) &&
496 (format != EXTRACTOR_METAFORMAT_C_STRING) )
497 return 0;
498 dlen = strlen (data) + 1;
499 GNUNET_CRYPTO_hash (data,
500 dlen - 1,
501 &hc);
502 cnt = GNUNET_CONTAINER_multihashmap_get (mcm, &hc);
503 if (cnt == NULL)
504 {
505 mlen = strlen (data_mime_type) + 1;
506 cnt = GNUNET_malloc (sizeof (struct MetaCounter) +
507 dlen + mlen);
508 cnt->count = 1;
509 cnt->value = (const char *) &cnt[1];
510 cnt->value_mimetype = &cnt->value[dlen];
511 memcpy (&cnt[1],
512 data,
513 dlen);
514 memcpy ((char*) cnt->value_mimetype,
515 data_mime_type,
516 mlen);
517 cnt->type = type;
518 cnt->format = format;
519 GNUNET_CONTAINER_multihashmap_put (mcm,
520 &hc,
521 cnt,
522 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
523
524 }
525 else
526 {
527 cnt->count++;
528 if (cnt->format == EXTRACTOR_METAFORMAT_C_STRING)
529 cnt->format = format; /* possibly improve to UTF8 */
530 if (cnt->type == EXTRACTOR_METATYPE_UNKNOWN)
531 cnt->type = type;
532 }
533 return 0;
534}
535
536
537/**
538 * Extract metadata from a file and add it to the metamap and
539 * the metacounter.
540 *
541 * @param adc context to modify
542 * @param filename name of the file to process
543 */
544static void
545extract_file (struct AddDirContext *adc,
546 const char *filename)
547{
548 struct PublishData *pd;
549 GNUNET_HashCode hc;
550 const char *short_fn;
551 const char *ss;
552
553 adc->dir_entry_count++;
554 pd = GNUNET_malloc (sizeof (struct PublishData));
555 pd->meta = GNUNET_CONTAINER_meta_data_create ();
556 GNUNET_FS_meta_data_extract_from_file (pd->meta,
557 filename,
558 GNUNET_FS_GTK_get_le_plugins());
559 GNUNET_CONTAINER_meta_data_delete (pd->meta,
560 EXTRACTOR_METATYPE_FILENAME,
561 NULL, 0);
562 short_fn = filename;
563 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
564 short_fn = 1 + ss;
565 GNUNET_CONTAINER_meta_data_insert (pd->meta,
566 "<gnunet-gtk>",
567 EXTRACTOR_METATYPE_FILENAME,
568 EXTRACTOR_METAFORMAT_UTF8,
569 "text/plain",
570 short_fn,
571 strlen(short_fn)+1);
572
573
574 gtk_tree_store_insert_before (adc->ts,
575 &pd->iter,
576 adc->parent,
577 NULL);
578 GNUNET_CRYPTO_hash (filename,
579 strlen (filename),
580 &hc);
581 GNUNET_CONTAINER_multihashmap_put (adc->metamap,
582 &hc,
583 pd,
584 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
585 GNUNET_CONTAINER_meta_data_iterate (pd->meta,
586 &add_to_meta_counter,
587 adc->metacounter);
588}
589
590
591/**
592 * Remove the keyword from the ksk URI.
593 *
594 * @param cls the ksk uri
595 * @param keyword the word to remove
596 * @param is_mandatory ignored
597 * @return always GNUNET_OK
598 */
599static int
600remove_keyword (void *cls,
601 const char *keyword,
602 int is_mandatory)
603{
604 struct GNUNET_FS_Uri *ksk = cls;
605
606 GNUNET_FS_uri_ksk_remove_keyword (ksk, keyword);
607 return GNUNET_OK;
608}
609
610
611/**
612 * Add the specifics of the given entry to the tree store.
613 * Derive KSK from the given meta data, but exclude meta
614 * data given in "md_no_ksk" for keyword generation.
615 *
616 * @param ts tree store to modify
617 * @param iter position in the tree store for this file
618 * @param filename file to add
619 * @param bo block options
620 * @param do_index should we index or insert?
621 * @param md_no_ksk metadata with keywords NOT to add
622 * @param meta metadata for the file
623 */
624static void
625add_entry_to_ts (GtkTreeStore *ts,
626 GtkTreeIter *iter,
627 const char *filename,
628 const struct GNUNET_FS_BlockOptions *bo,
629 int do_index,
630 struct GNUNET_CONTAINER_MetaData *md_no_ksk,
631 struct GNUNET_CONTAINER_MetaData *meta)
632{
633 char *file_size_fancy;
634 struct GNUNET_FS_FileInformation *fi;
635 GtkTreeRowReference *row_reference;
636 GtkTreePath *path;
637 uint64_t file_size;
638 struct GNUNET_FS_Uri *ksk_uri;
639 struct GNUNET_FS_Uri *kill_ksk;
640 const char *ss;
641 const char *short_fn;
642 struct stat sbuf;
643
644 if (0 != STAT (filename, &sbuf))
645 return;
646 if (S_ISDIR (sbuf.st_mode))
647 {
648 file_size = 0;
649 }
650 else
651 {
652 if (GNUNET_OK !=
653 GNUNET_DISK_file_size (filename,
654 &file_size,
655 GNUNET_YES))
656 {
657 GNUNET_break (0);
658 return;
659 }
660 }
661 ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
662 kill_ksk = GNUNET_FS_uri_ksk_create_from_meta_data (md_no_ksk);
663 if (kill_ksk != NULL)
664 {
665 GNUNET_FS_uri_ksk_get_keywords (kill_ksk,
666 &remove_keyword,
667 ksk_uri);
668 GNUNET_FS_uri_destroy (kill_ksk);
669 }
670 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
671 iter);
672 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
673 path);
674 gtk_tree_path_free (path);
675 if (S_ISDIR (sbuf.st_mode))
676 {
677 GNUNET_CONTAINER_meta_data_delete (meta,
678 EXTRACTOR_METATYPE_MIMETYPE,
679 NULL, 0);
680 GNUNET_FS_meta_data_make_directory (meta);
681 GNUNET_FS_uri_ksk_add_keyword (ksk_uri,
682 GNUNET_FS_DIRECTORY_MIME,
683 GNUNET_NO);
684 fi = GNUNET_FS_file_information_create_empty_directory (GNUNET_FS_GTK_get_fs_handle (),
685 row_reference,
686 ksk_uri,
687 meta,
688 bo);
689 }
690 else
691 {
692 fi = GNUNET_FS_file_information_create_from_file (GNUNET_FS_GTK_get_fs_handle (),
693 row_reference,
694 filename,
695 ksk_uri,
696 meta,
697 do_index,
698 bo);
699 }
700 GNUNET_CONTAINER_meta_data_destroy (meta);
701 GNUNET_FS_uri_destroy (ksk_uri);
702 if (S_ISDIR (sbuf.st_mode))
703 file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
704 else
705 file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
706 short_fn = filename;
707 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
708 short_fn = 1 + ss;
709 gtk_tree_store_set (ts, iter,
710 0, file_size_fancy,
711 1, (gboolean) do_index,
712 2, short_fn,
713 3, (guint) bo->anonymity_level,
714 4, (guint) bo->content_priority,
715 5, fi,
716 -1);
717 GNUNET_free (file_size_fancy);
718}
719
720
721/**
722 * Function called by the directory iterator to
723 * (recursively) add all of the files in the
724 * directory to the tree.
725 *
726 * @param cls the 'struct AddDirContext*' we're in
727 * @param filename file or directory to scan
728 */
729static int
730publish_entry (void *cls,
731 const char *filename)
732{
733 struct AddDirContext *adc = cls;
734 struct PublishData *pd;
735 GNUNET_HashCode hc;
736
737 GNUNET_CRYPTO_hash (filename,
738 strlen (filename),
739 &hc);
740 pd = GNUNET_CONTAINER_multihashmap_get (adc->metamap,
741 &hc);
742 add_entry_to_ts (adc->ts,
743 &pd->iter,
744 filename,
745 &adc->bo,
746 adc->do_index,
747 adc->no_ksk,
748 pd->meta);
749 GNUNET_CONTAINER_multihashmap_remove (adc->metamap,
750 &hc,
751 pd);
752 GNUNET_free (pd);
753 return GNUNET_OK;
754}
755
756
757/**
758 * Context passed to 'migrate_and_drop'.
759 */
760struct MetaProcessContext
761{
762 /**
763 * Metadata with all the keywords we migrated to the parent.
764 */
765 struct GNUNET_CONTAINER_MetaData *md;
766
767 /**
768 * How often does a keyword have to occur to be
769 * migrated to the parent?
770 */
771 unsigned int threshold;
772};
773
774
775/**
776 * Copy "frequent" meta data entries over to the
777 * target meta data struct, free the counters.
778 *
779 */
780static int
781migrate_and_drop (void *cls,
782 const GNUNET_HashCode *key,
783 void *value)
784{
785 struct MetaProcessContext *mpc = cls;
786 struct MetaCounter *counter = value;
787
788 if (counter->count >= mpc->threshold)
789 {
790 GNUNET_CONTAINER_meta_data_insert (mpc->md,
791 "<gnunet-gtk>",
792 counter->type,
793 counter->format,
794 counter->value_mimetype,
795 counter->value,
796 strlen (counter->value)+1);
797 }
798 GNUNET_free (counter);
799 return GNUNET_YES;
800}
801
802
803/**
804 * Go over the collected meta data from all entries in the
805 * directory and push common meta data up one level (by
806 * adding it to the returned struct).
807 *
808 * @param adc collection of child meta data
809 * @return meta data to moved to parent
810 */
811static struct GNUNET_CONTAINER_MetaData *
812process_metadata (struct AddDirContext *adc)
813{
814 struct MetaProcessContext mpc;
815
816 mpc.md = GNUNET_CONTAINER_meta_data_create ();
817 mpc.threshold = (adc->dir_entry_count + 1) / 2; /* 50% */
818 GNUNET_CONTAINER_multihashmap_iterate (adc->metacounter,
819 &migrate_and_drop,
820 &mpc);
821 GNUNET_CONTAINER_multihashmap_destroy (adc->metacounter);
822 return mpc.md;
823}
824
825
826/**
827 * Function called by the directory iterator to
828 * (recursively) add all of the files in the
829 * directory to the tree.
830 *
831 * @param cls the 'struct AddDirContext*' we're in
832 * @param filename file or directory to scan
833 */
834static int
835scan_directory (void *cls,
836 const char *filename)
837
838{
839 struct AddDirContext *adc = cls;
840 struct stat sbuf;
841 GtkTreeIter *parent;
842 struct PublishData *pd;
843 GNUNET_HashCode hc;
844 struct GNUNET_CONTAINER_MultiHashMap *mhm;
845 struct GNUNET_CONTAINER_MultiHashMap *mcm;
846 unsigned int pc;
847
848 if (0 != STAT (filename, &sbuf))
849 return GNUNET_OK;
850 if (S_ISDIR (sbuf.st_mode))
851 {
852 parent = adc->parent;
853 mhm = adc->metamap;
854 mcm = adc->metacounter;
855 pc = adc->dir_entry_count;
856 adc->metamap = GNUNET_CONTAINER_multihashmap_create (1024);
857 adc->metacounter = GNUNET_CONTAINER_multihashmap_create (1024);
858 adc->dir_entry_count = 0;
859 pd = GNUNET_malloc (sizeof (struct PublishData));
860 gtk_tree_store_insert_before (adc->ts,
861 &pd->iter,
862 parent,
863 NULL);
864 adc->parent = &pd->iter;
865 GNUNET_DISK_directory_scan (filename,
866 &scan_directory,
867 adc);
868 pd->meta = process_metadata (adc);
869 adc->no_ksk = pd->meta;
870 GNUNET_DISK_directory_scan (filename,
871 &publish_entry,
872 adc);
873 GNUNET_CONTAINER_multihashmap_destroy (adc->metamap);
874 adc->metamap = mhm;
875 adc->metacounter = mcm;
876 adc->parent = parent;
877 adc->dir_entry_count = pc + 1;
878 if (adc->metamap != NULL)
879 {
880 GNUNET_CRYPTO_hash (filename,
881 strlen (filename),
882 &hc);
883 GNUNET_CONTAINER_multihashmap_put (adc->metamap,
884 &hc,
885 pd,
886 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
887 GNUNET_CONTAINER_meta_data_iterate (pd->meta,
888 &add_to_meta_counter,
889 mcm);
890 }
891 else
892 {
893 GNUNET_assert (mcm == NULL);
894 /* we're top-level */
895 add_entry_to_ts (adc->ts,
896 &pd->iter,
897 filename,
898 &adc->bo,
899 adc->do_index,
900 NULL,
901 pd->meta);
902 }
903 }
904 else
905 {
906 GNUNET_assert (adc->metamap != NULL);
907 extract_file (adc, filename);
908 }
909 return GNUNET_OK;
910}
911
912
913/**
914 * Add a directory to the tree model.
915 *
916 * @param filename directory name to add
917 * @param bo block options
918 * @param do_index should we index?
919 */
920static void
921add_dir (const char *filename,
922 const struct GNUNET_FS_BlockOptions *bo,
923 int do_index)
924{
925 struct stat sbuf;
926 struct AddDirContext scan_ctx;
927
928 if (0 != STAT (filename, &sbuf))
929 return;
930 if (! S_ISDIR (sbuf.st_mode))
931 {
932 GNUNET_break (0);
933 return;
934 }
935 memset (&scan_ctx, 0, sizeof (scan_ctx));
936 scan_ctx.bo = *bo;
937 scan_ctx.do_index = do_index;
938 scan_ctx.ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
939 "GNUNET_GTK_file_sharing_publishing_tree_store"));
940 scan_directory (&scan_ctx, filename);
941}
942
943
944/* ************ code for adding directories ends here ************* */
945
946
947static void
948selection_changed_cb (GtkTreeSelection *ts,
949 gpointer user_data)
950{
951 update_selectivity ();
952}
953
954
955static void
956remove_old_entry (GtkTreeStore *ts,
957 GtkTreeIter *root)
958{
959 GtkTreeIter child;
960
961 while (TRUE == gtk_tree_model_iter_children (GTK_TREE_MODEL (ts),
962 &child, root))
963 remove_old_entry (ts, &child);
964 gtk_tree_store_remove (ts, root);
965}
966
967
968/**
969 * Move an entry in the tree.
970 */
971static void
972move_entry (GtkTreeModel *tm,
973 GtkTreeIter *old,
974 GtkTreeIter *newpos,
975 int dsel)
976{
977 struct GNUNET_FS_FileInformation *fip;
978 GtkTreeView *tv;
979 gint do_index;
980 gchar *short_fn;
981 guint anonymity_level;
982 guint priority;
983 char *fsf;
984 GtkTreePath *path;
985 GtkTreeSelection *sel;
986 GtkTreeIter child;
987 GtkTreeIter cnewpos;
988 GtkTreeRowReference *rr;
989 GtkTreeRowReference *rr2;
990
991 gtk_tree_model_get (tm,
992 old,
993 0, &fsf,
994 1, &do_index,
995 2, &short_fn,
996 3, &anonymity_level,
997 4, &priority,
998 5, &fip,
999 -1);
1000 gtk_tree_store_set (GTK_TREE_STORE (tm), newpos,
1001 0, fsf,
1002 1, do_index,
1003 2, short_fn,
1004 3, (guint)anonymity_level,
1005 4, (guint) priority,
1006 5, fip,
1007 -1);
1008 sel = NULL;
1009 tv = NULL;
1010 if (dsel == GNUNET_YES)
1011 {
1012 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1013 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1014 sel = gtk_tree_view_get_selection (tv);
1015 path = gtk_tree_model_get_path (tm, newpos);
1016 rr = gtk_tree_row_reference_new (tm, path);
1017 gtk_tree_path_free (path);
1018 }
1019 else
1020 {
1021 rr = NULL;
1022 }
1023 if (TRUE == gtk_tree_model_iter_children (tm, &child, old))
1024 {
1025 do
1026 {
1027 path = gtk_tree_model_get_path (tm, &child);
1028 rr2 = gtk_tree_row_reference_new (tm, path);
1029 gtk_tree_path_free (path);
1030 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1031 &cnewpos, newpos, NULL);
1032 move_entry (tm, &child, &cnewpos, GNUNET_NO);
1033 path = gtk_tree_row_reference_get_path (rr2);
1034 gtk_tree_row_reference_free (rr2);
1035 GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
1036 &child,
1037 path));
1038 gtk_tree_path_free (path);
1039 }
1040 while (TRUE == gtk_tree_model_iter_next (tm, &child));
1041 }
1042 g_free (short_fn);
1043 g_free (fsf);
1044 if (dsel == GNUNET_YES)
1045 {
1046 path = gtk_tree_row_reference_get_path (rr);
1047 gtk_tree_row_reference_free (rr);
1048 gtk_tree_view_expand_to_path (tv, path);
1049 GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
1050 newpos,
1051 path));
1052 gtk_tree_path_free (path);
1053 gtk_tree_selection_select_iter (sel,
1054 newpos);
1055 }
1056 update_selectivity ();
1057}
1058
1059/**
1060 * User has changed the "current" identifier for the content in
1061 * the GtkTreeView. Update the model.
1062 */
1063void
1064GNUNET_GTK_master_publish_dialog_pseudonym_updates_renderer_edited_cb (GtkCellRendererText *renderer,
1065 gchar *cpath,
1066 gchar *new_text,
1067 gpointer user_data)
1068{
1069 GtkTreeIter iter;
1070 GtkTreeStore *ts;
1071
1072 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1073 "GNUNET_GTK_pseudonym_tree_store"));
1074
1075 if (TRUE !=
1076 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
1077 {
1078 GNUNET_break (0);
1079 return;
1080 }
1081 gtk_tree_store_set (ts, &iter, 5, new_text, -1);
1082 update_selectivity ();
1083}
1084
1085
1086/**
1087 * User has changed the "current" identifier for the content in
1088 * the GtkTreeView. Update the model.
1089 */
1090void
1091GNUNET_GTK_master_publish_dialog_pseudonym_identifier_renderer_edited_cb (GtkCellRendererText *renderer,
1092 gchar *cpath,
1093 gchar *new_text,
1094 gpointer user_data)
1095{
1096 GtkTreeIter iter;
1097 GtkTreeStore *ts;
1098
1099 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1100 "GNUNET_GTK_pseudonym_tree_store"));
1101
1102 if (TRUE !=
1103 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
1104 {
1105 GNUNET_break (0);
1106 return;
1107 }
1108 gtk_tree_store_set (ts, &iter, 2, new_text, -1);
1109 update_selectivity ();
1110}
1111
1112
1113void
1114GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy,
1115 gpointer data)
1116{
1117 GtkTreeView *tv;
1118 GtkTreeModel *tm;
1119 GtkTreeSelection *sel;
1120 GtkTreeIter iter;
1121 GtkTreeIter parent;
1122 GtkTreeIter pred;
1123 GtkTreeIter prev;
1124 GtkTreeIter pos;
1125
1126 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1127 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1128 sel = gtk_tree_view_get_selection (tv);
1129 if (TRUE != gtk_tree_selection_get_selected (sel,
1130 &tm,
1131 &iter))
1132 {
1133 GNUNET_break (0);
1134 return;
1135 }
1136 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
1137 {
1138 GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent));
1139 }
1140 else if (TRUE != gtk_tree_model_get_iter_first (tm, &pred))
1141 {
1142 GNUNET_break (0);
1143 return;
1144 }
1145 /* iterate over 'next' of pred to find out who our predecessor is! */
1146 memset (&prev, 0, sizeof (GtkTreeIter));
1147 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
1148 {
1149 prev = pred;
1150 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
1151 }
1152 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1153 &pos, &prev, NULL);
1154 if (TRUE != gtk_tree_selection_get_selected (sel,
1155 &tm,
1156 &iter))
1157 {
1158 GNUNET_break (0);
1159 return;
1160 }
1161 move_entry (tm, &iter, &pos, GNUNET_YES);
1162 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1163}
1164
1165
1166void
1167GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy,
1168 gpointer data)
1169{
1170 GtkTreeView *tv;
1171 GtkTreeModel *tm;
1172 GtkTreeSelection *sel;
1173 GtkTreeIter iter;
1174 GtkTreeIter parent;
1175 GtkTreeIter pos;
1176
1177 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1178 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1179 sel = gtk_tree_view_get_selection (tv);
1180 if (TRUE != gtk_tree_selection_get_selected (sel,
1181 &tm,
1182 &iter))
1183 {
1184 GNUNET_break (0);
1185 return;
1186 }
1187 if (TRUE != gtk_tree_model_iter_parent (tm, &parent, &iter))
1188 {
1189 GNUNET_break (0);
1190 return;
1191 }
1192 gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
1193 &pos, NULL, &parent);
1194 if (TRUE != gtk_tree_selection_get_selected (sel,
1195 &tm,
1196 &iter))
1197 {
1198 GNUNET_break (0);
1199 return;
1200 }
1201 move_entry (tm, &iter, &pos, GNUNET_YES);
1202 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1203}
1204
1205
1206void
1207GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy,
1208 gpointer data)
1209{
1210 GtkTreeView *tv;
1211 GtkTreeModel *tm;
1212 GtkTreeSelection *sel;
1213 GtkTreeIter iter;
1214 GtkTreeIter parent;
1215 GtkTreeIter pred;
1216 GtkTreeIter prev;
1217 GtkTreeIter *pprev;
1218 GtkTreeIter pos;
1219
1220 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1221 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1222 sel = gtk_tree_view_get_selection (tv);
1223 if (TRUE != gtk_tree_selection_get_selected (sel,
1224 &tm,
1225 &iter))
1226 {
1227 GNUNET_break (0);
1228 return;
1229 }
1230 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
1231 {
1232 GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent));
1233 pprev = &parent;
1234 }
1235 else if (TRUE == gtk_tree_model_get_iter_first (tm, &pred))
1236 {
1237 pprev = NULL;
1238 }
1239 else
1240 {
1241 GNUNET_break (0);
1242 return;
1243 }
1244 /* iterate over 'next' of pred to find out who our predecessor is! */
1245 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
1246 {
1247 prev = pred;
1248 pprev = &prev;
1249 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
1250 }
1251 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1252 &pos, NULL, pprev);
1253 if (TRUE != gtk_tree_selection_get_selected (sel,
1254 &tm,
1255 &iter))
1256 {
1257 GNUNET_break (0);
1258 return;
1259 }
1260 move_entry (tm, &iter, &pos, GNUNET_YES);
1261 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1262}
1263
1264
1265void
1266GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy,
1267 gpointer data)
1268{
1269 GtkTreeView *tv;
1270 GtkTreeModel *tm;
1271 GtkTreeSelection *sel;
1272 GtkTreeIter iter;
1273 GtkTreeIter next;
1274 GtkTreeIter pos;
1275
1276 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1277 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1278 sel = gtk_tree_view_get_selection (tv);
1279 if (TRUE != gtk_tree_selection_get_selected (sel,
1280 &tm,
1281 &iter))
1282 {
1283 GNUNET_break (0);
1284 return;
1285 }
1286 if (TRUE != gtk_tree_selection_get_selected (sel,
1287 &tm,
1288 &next))
1289 {
1290 GNUNET_break (0);
1291 return;
1292 }
1293 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &next));
1294 gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
1295 &pos, NULL, &next);
1296 if (TRUE != gtk_tree_selection_get_selected (sel,
1297 &tm,
1298 &iter))
1299 {
1300 GNUNET_break (0);
1301 return;
1302 }
1303 move_entry (tm, &iter, &pos, GNUNET_YES);
1304 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1305}
1306
1307
1308void
1309GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy,
1310 gpointer data)
1311{
1312 GtkTreeView *tv;
1313 GtkTreeSelection *sel;
1314 GtkTreeIter iter;
1315 GtkTreeIter pos;
1316 struct GNUNET_FS_BlockOptions bo;
1317
1318 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1319 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1320 sel = gtk_tree_view_get_selection (tv);
1321 /* FIXME: consider opening a dialog to get
1322 * anonymity, priority and expiration prior
1323 * to calling this function (currently we
1324 * use default values for those).
1325 */
1326 bo.anonymity_level = 1;
1327 bo.content_priority = 1000;
1328 bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS);
1329 bo.replication_level = 1;
1330 if (TRUE != gtk_tree_selection_get_selected (sel,
1331 NULL,
1332 &iter))
1333 {
1334 create_dir_at_iter ("unnamed/",
1335 &bo,
1336 NULL, &pos);
1337 return;
1338 }
1339 create_dir_at_iter ("unnamed/",
1340 &bo,
1341 &iter, &pos);
1342}
1343
1344
1345void
1346GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy,
1347 gpointer data)
1348{
1349 GtkWidget *ad;
1350 GtkBuilder *builder;
1351 char *filename;
1352 struct GNUNET_FS_BlockOptions bo;
1353 int do_index;
1354 GtkSpinButton *sb;
1355
1356 builder = GNUNET_GTK_get_new_builder ("publish-file-dialog.glade");
1357 if (builder == NULL)
1358 {
1359 GNUNET_break (0);
1360 return;
1361 }
1362 ad = GTK_WIDGET (gtk_builder_get_object (builder,
1363 "GNUNET_GTK_publish_file_dialog"));
1364 GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
1365 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
1366 {
1367 gtk_widget_destroy (ad);
1368 g_object_unref (G_OBJECT (builder));
1369 return;
1370 }
1371 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
1372 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1373 "GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
1374 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1375 "GNUNET_GTK_publish_file_dialog_anonymity_spin_button")));
1376 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1377 "GNUNET_GTK_publish_file_dialog_priority_spin_button")));
1378 bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
1379 bo.replication_level = 1; /* FIXME... */
1380 do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
1381 "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
1382 add_file_at_iter (filename,
1383 &bo, do_index,
1384 NULL);
1385 gtk_widget_destroy (ad);
1386 g_object_unref (G_OBJECT (builder));
1387 g_free (filename);
1388 update_selectivity ();
1389}
1390
1391
1392void
1393GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy,
1394 gpointer data)
1395{
1396 GtkTreeView *tv;
1397 GtkTreeModel *tm;
1398 GtkTreeSelection *sel;
1399 GtkTreeIter iter;
1400 int do_index;
1401 guint anonymity_level;
1402 guint priority;
1403 gchar *short_fn;
1404 struct GNUNET_FS_FileInformation *fip;
1405
1406 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1407 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1408 sel = gtk_tree_view_get_selection (tv);
1409 if (TRUE != gtk_tree_selection_get_selected (sel,
1410 &tm,
1411 &iter))
1412 {
1413 GNUNET_break (0);
1414 return;
1415 }
1416 gtk_tree_model_get (tm,
1417 &iter,
1418 1, &do_index,
1419 2, &short_fn,
1420 3, &anonymity_level,
1421 4, &priority,
1422 5, &fip,
1423 -1);
1424 GNUNET_GTK_edit_publish_dialog (&do_index,
1425 &short_fn,
1426 &anonymity_level,
1427 &priority,
1428 fip);
1429 gtk_tree_store_set (GTK_TREE_STORE (tm),
1430 &iter,
1431 1, do_index,
1432 2, short_fn,
1433 3, anonymity_level,
1434 4, priority,
1435 -1);
1436 g_free (short_fn);
1437}
1438
1439
1440/**
1441 * Free row reference stored in the file information's
1442 * client-info pointer.
1443 */
1444static int
1445free_fi_row_reference (void *cls,
1446 struct GNUNET_FS_FileInformation *fi,
1447 uint64_t length,
1448 struct GNUNET_CONTAINER_MetaData *meta,
1449 struct GNUNET_FS_Uri **uri,
1450 struct GNUNET_FS_BlockOptions *bo,
1451 int *do_index,
1452 void **client_info)
1453{
1454 GtkTreeRowReference *row = *client_info;
1455
1456 if (row == NULL)
1457 {
1458 GNUNET_break (0);
1459 return GNUNET_OK;
1460 }
1461 gtk_tree_row_reference_free (row);
1462 return GNUNET_OK;
1463}
1464
1465
1466
1467void
1468GNUNET_GTK_master_publish_dialog_delete_button_clicked_cb (GtkWidget * dummy,
1469 gpointer data)
1470{
1471 GtkTreeView *tv;
1472 GtkTreeModel *tm;
1473 GtkTreeSelection *sel;
1474 GtkTreeIter iter;
1475 struct GNUNET_FS_FileInformation *fip;
1476
1477 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1478 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1479 sel = gtk_tree_view_get_selection (tv);
1480 if (TRUE != gtk_tree_selection_get_selected (sel,
1481 &tm,
1482 &iter))
1483 {
1484 GNUNET_break (0);
1485 return;
1486 }
1487 gtk_tree_model_get (tm,
1488 &iter,
1489 5, &fip,
1490 -1);
1491 GNUNET_FS_file_information_destroy (fip,
1492 &free_fi_row_reference,
1493 NULL);
1494 gtk_tree_store_remove (GTK_TREE_STORE (tm),
1495 &iter);
1496 update_selectivity ();
1497}
1498
1499
1500void
1501GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy,
1502 gpointer data)
1503{
1504 GtkWidget *ad;
1505 GtkBuilder *builder;
1506 char *filename;
1507 int do_index;
1508 GtkSpinButton *sb;
1509 struct GNUNET_FS_BlockOptions bo;
1510
1511 builder = GNUNET_GTK_get_new_builder ("publish-directory-dialog.glade");
1512 if (builder == NULL)
1513 {
1514 GNUNET_break (0);
1515 return;
1516 }
1517 GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
1518 ad = GTK_WIDGET (gtk_builder_get_object (builder,
1519 "GNUNET_GTK_publish_directory_dialog"));
1520 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
1521 {
1522 gtk_widget_destroy (ad);
1523 g_object_unref (G_OBJECT (builder));
1524 return;
1525 }
1526 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
1527 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1528 "GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
1529 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1530 "GNUNET_GTK_publish_directory_dialog_anonymity_spin_button")));
1531 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1532 "GNUNET_GTK_publish_directory_dialog_priority_spin_button")));
1533 bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
1534 do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
1535 "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")));
1536
1537 gtk_widget_destroy (ad);
1538 g_object_unref (G_OBJECT (builder));
1539 /* FIXME: open progress dialog here... */
1540 add_dir (filename, &bo, do_index);
1541 g_free (filename);
1542 update_selectivity ();
1543}
1544
1545
1546/**
1547 * Get the file information struct corresponding to the
1548 * given iter in the publish dialog tree model. Recursively
1549 * builds the file information struct from the subtree.
1550 *
1551 * @param tm model to grab fi from
1552 * @param iter position to grab fi from
1553 * @return file information from the given position (never NULL)
1554 */
1555static struct GNUNET_FS_FileInformation *
1556get_file_information (GtkTreeModel *tm,
1557 GtkTreeIter *iter)
1558{
1559 struct GNUNET_FS_FileInformation *fi;
1560 struct GNUNET_FS_FileInformation *fic;
1561 GtkTreeIter child;
1562
1563 gtk_tree_model_get (tm, iter,
1564 5, &fi,
1565 -1);
1566 gtk_tree_store_set (GTK_TREE_STORE (tm), iter,
1567 5, NULL,
1568 -1);
1569 GNUNET_assert (fi != NULL);
1570 if (gtk_tree_model_iter_children (tm, &child, iter))
1571 {
1572 GNUNET_break (GNUNET_YES ==
1573 GNUNET_FS_file_information_is_directory (fi));
1574 do
1575 {
1576 fic = get_file_information (tm, &child);
1577 GNUNET_break (GNUNET_OK ==
1578 GNUNET_FS_file_information_add (fi, fic));
1579 }
1580 while (gtk_tree_model_iter_next (tm, &child));
1581 }
1582 return fi;
1583}
1584
1585
1586/**
1587 * Closure for 'add_updateable_to_ts'.
1588 */
1589struct UpdateableContext
1590{
1591 /**
1592 * Parent of current insertion.
1593 */
1594 GtkTreeIter *parent;
1595
1596 /**
1597 * Tree store we are modifying.
1598 */
1599 GtkTreeStore *ts;
1600
1601 /**
1602 * Name of the namespace.
1603 */
1604 const char *namespace_name;
1605
1606 /**
1607 * Handle to the namespace.
1608 */
1609 struct GNUNET_FS_Namespace *ns;
1610
1611 /**
1612 * Hash codes of identifiers already added to tree store.
1613 */
1614 struct GNUNET_CONTAINER_MultiHashMap *seen;
1615
1616 /**
1617 * Did the iterator get called?
1618 */
1619 int update_called;
1620};
1621
1622
1623/**
1624 * Add updateable entries to the tree view.
1625 *
1626 * @param cls closure
1627 * @param last_id ID to add
1628 * @param last_uri associated URI
1629 * @param last_meta associate meta data
1630 * @param next_id ID for future updates
1631 */
1632static void
1633add_updateable_to_ts (void *cls,
1634 const char *last_id,
1635 const struct GNUNET_FS_Uri *last_uri,
1636 const struct GNUNET_CONTAINER_MetaData *last_meta,
1637 const char *next_id)
1638{
1639 struct UpdateableContext *uc = cls;
1640 struct UpdateableContext sc;
1641 GtkTreeIter iter;
1642 GtkTreeIter titer;
1643 char *desc;
1644 GNUNET_HashCode hc;
1645
1646 uc->update_called = GNUNET_YES;
1647 GNUNET_CRYPTO_hash (last_id,
1648 strlen (last_id),
1649 &hc);
1650 if (NULL !=
1651 GNUNET_CONTAINER_multihashmap_get (uc->seen,
1652 &hc))
1653 return;
1654 GNUNET_CONTAINER_multihashmap_put (uc->seen,
1655 &hc,
1656 "dummy",
1657 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1658 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (last_meta,
1659 EXTRACTOR_METATYPE_DESCRIPTION,
1660 EXTRACTOR_METATYPE_TITLE,
1661 EXTRACTOR_METATYPE_BOOK_TITLE,
1662 EXTRACTOR_METATYPE_FILENAME,
1663 EXTRACTOR_METATYPE_SUMMARY,
1664 EXTRACTOR_METATYPE_ALBUM,
1665 EXTRACTOR_METATYPE_COMMENT,
1666 EXTRACTOR_METATYPE_SUBJECT,
1667 -1);
1668 gtk_tree_store_insert_with_values (uc->ts,
1669 &iter,
1670 uc->parent,
1671 G_MAXINT,
1672 0, uc->namespace_name,
1673 1, uc->ns,
1674 2, last_id,
1675 3, GNUNET_FS_uri_dup (last_uri),
1676 4, GNUNET_CONTAINER_meta_data_duplicate (last_meta),
1677 5, "",
1678 6, desc,
1679 7, TRUE /* update editable (always) */,
1680 8, FALSE /* current not editable (only for top-level) */,
1681 -1);
1682 GNUNET_free_non_null (desc);
1683 sc.parent = &iter;
1684 sc.ts = uc->ts;
1685 sc.namespace_name = uc->namespace_name;
1686 sc.ns = uc->ns;
1687 sc.seen = uc->seen;
1688 sc.update_called = GNUNET_NO;
1689 GNUNET_FS_namespace_list_updateable (uc->ns,
1690 next_id,
1691 &add_updateable_to_ts,
1692 &sc);
1693 if ( (sc.update_called == GNUNET_NO) &&
1694 (next_id != NULL) &&
1695 (strlen (next_id) > 0) )
1696 {
1697 /* add leaf */
1698 gtk_tree_store_insert_with_values (uc->ts,
1699 &titer,
1700 &iter,
1701 G_MAXINT,
1702 0, uc->namespace_name,
1703 1, uc->ns,
1704 2, next_id,
1705 3, NULL,
1706 4, NULL,
1707 5, "",
1708 6, "",
1709 7, TRUE /* update editable (always) */,
1710 8, FALSE /* current not editable (only for top-level) */,
1711 -1);
1712 }
1713}
1714
1715
1716/**
1717 * Add all updateable entries of the current namespace to the
1718 * tree store.
1719 *
1720 * @param cls the 'GtkTreeStore' to update
1721 * @param name name of the namespace to add
1722 * @param id identity of the namespace to add
1723 */
1724static void
1725add_namespace_to_ts (void *cls,
1726 const char *name,
1727 const GNUNET_HashCode *id)
1728{
1729 GtkTreeStore *ts = cls;
1730 struct UpdateableContext uc;
1731 GtkTreeIter iter;
1732
1733 uc.parent = &iter;
1734 uc.namespace_name = name;
1735 uc.ts = ts;
1736 uc.ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (),
1737 name);
1738 uc.update_called = GNUNET_NO;
1739 gtk_tree_store_insert_with_values (ts, &iter,
1740 NULL,
1741 G_MAXINT,
1742 0, name,
1743 1, uc.ns,
1744 2, NULL /* last-id */,
1745 3, NULL /* last-uri */,
1746 4, NULL /* meta */,
1747 5, NULL /* next-ID */,
1748 6, NULL /* last-description */,
1749 7, TRUE /* update editable */,
1750 8, TRUE /* current editable */,
1751 -1);
1752 uc.seen = GNUNET_CONTAINER_multihashmap_create (128);
1753 GNUNET_FS_namespace_list_updateable (uc.ns, NULL,
1754 &add_updateable_to_ts, &uc);
1755 GNUNET_CONTAINER_multihashmap_destroy (uc.seen);
1756}
1757
1758
1759static void
1760free_pseudonym_tree_store (GtkTreeModel *tm,
1761 GtkTreeIter *iter)
1762{
1763 struct GNUNET_FS_Uri *uri;
1764 struct GNUNET_CONTAINER_MetaData *meta;
1765 struct GNUNET_FS_Namespace *ns;
1766 GtkTreeIter child;
1767
1768 gtk_tree_model_get (tm,
1769 iter,
1770 1, &ns,
1771 3, &uri,
1772 4, &meta,
1773 -1);
1774 if (uri != NULL)
1775 GNUNET_FS_uri_destroy (uri);
1776 if (meta != NULL)
1777 GNUNET_CONTAINER_meta_data_destroy (meta);
1778 if (ns != NULL)
1779 {
1780 // FIXME: delete ns?
1781 // GNUNET_FS_namespace_delete (nso, GNUNET_NO);
1782 }
1783 if (TRUE ==
1784 gtk_tree_model_iter_children (tm, &child, iter))
1785 {
1786 do
1787 {
1788 free_pseudonym_tree_store (tm,
1789 &child);
1790 }
1791 while (TRUE == gtk_tree_model_iter_next (tm,
1792 &child));
1793 }
1794}
1795
1796
1797static void
1798free_file_information_tree_store (GtkTreeModel *tm,
1799 GtkTreeIter *iter)
1800{
1801 GtkTreeIter child;
1802 struct GNUNET_FS_FileInformation *fip;
1803
1804 gtk_tree_model_get (tm,
1805 iter,
1806 5, &fip,
1807 -1);
1808 if (fip != NULL)
1809 GNUNET_FS_file_information_destroy (fip, NULL, NULL);
1810 if (TRUE ==
1811 gtk_tree_model_iter_children (tm, &child, iter))
1812 {
1813 do
1814 {
1815 free_file_information_tree_store (tm,
1816 &child);
1817 }
1818 while (TRUE == gtk_tree_model_iter_next (tm,
1819 &child));
1820 }
1821}
1822
1823
1824/**
1825 */
1826void
1827GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy,
1828 gpointer data)
1829{
1830 GtkWidget *ad;
1831 GtkTreeStore *ts;
1832 gint ret;
1833 GtkTreeView *tv;
1834 GtkTreeSelection *sel;
1835 GtkTreeIter iter;
1836 struct GNUNET_FS_FileInformation *fi;
1837 GtkTreeModel *tm;
1838 GtkTreeModel *ptm;
1839 struct GNUNET_FS_Namespace *namespace;
1840 gchar *namespace_id;
1841 gchar *namespace_uid;
1842
1843 GNUNET_assert (master_builder == NULL);
1844 master_builder = GNUNET_GTK_get_new_builder ("publish_dialog.glade");
1845 if (master_builder == NULL)
1846 return;
1847 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1848 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1849 sel = gtk_tree_view_get_selection (tv);
1850 g_signal_connect(G_OBJECT(sel), "changed",
1851 G_CALLBACK(selection_changed_cb), NULL);
1852 ad = GTK_WIDGET (gtk_builder_get_object (master_builder,
1853 "GNUNET_GTK_master_publish_dialog"));
1854 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1855 "GNUNET_GTK_pseudonym_tree_store"));
1856 GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
1857 &add_namespace_to_ts,
1858 ts);
1859 tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
1860 "GNUNET_GTK_file_sharing_publishing_tree_store"));
1861 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1862 "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
1863 sel = gtk_tree_view_get_selection (tv);
1864 g_signal_connect(G_OBJECT(sel), "changed",
1865 G_CALLBACK(selection_changed_cb), NULL);
1866 ret = gtk_dialog_run (GTK_DIALOG (ad));
1867 if (ret == GTK_RESPONSE_OK)
1868 {
1869 if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
1870 {
1871 gtk_tree_model_get (ptm,
1872 &iter,
1873 1, &namespace,
1874 2, &namespace_id,
1875 5, &namespace_uid,
1876 -1);
1877 }
1878 else
1879 {
1880 namespace = NULL;
1881 namespace_id = NULL;
1882 namespace_uid = NULL;
1883 }
1884 if (gtk_tree_model_get_iter_first (tm, &iter))
1885 do
1886 {
1887 fi = get_file_information (tm, &iter);
1888 GNUNET_FS_publish_start (GNUNET_FS_GTK_get_fs_handle (),
1889 fi,
1890 namespace,
1891 namespace_id,
1892 namespace_uid,
1893 GNUNET_FS_PUBLISH_OPTION_NONE);
1894 }
1895 while (gtk_tree_model_iter_next (tm, &iter));
1896 if (namespace_id != NULL)
1897 g_free (namespace_id);
1898 if (namespace_uid != NULL)
1899 g_free (namespace_uid);
1900 }
1901 ptm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
1902 "GNUNET_GTK_pseudonym_tree_store"));
1903 /* free state from 'ptm' */
1904 if (TRUE ==
1905 gtk_tree_model_get_iter_first (ptm,
1906 &iter))
1907 do
1908 {
1909 free_pseudonym_tree_store (ptm,
1910 &iter);
1911 }
1912 while (TRUE == gtk_tree_model_iter_next (ptm,
1913 &iter));
1914
1915 /* free state from 'tm' */
1916 if (TRUE ==
1917 gtk_tree_model_get_iter_first (tm,
1918 &iter))
1919 do
1920 {
1921 free_file_information_tree_store (tm,
1922 &iter);
1923 }
1924 while (TRUE == gtk_tree_model_iter_next (tm,
1925 &iter));
1926
1927 gtk_widget_destroy (ad);
1928 g_object_unref (G_OBJECT (master_builder));
1929 master_builder = NULL;
1930}
1931
1932
1933/* end of main_window_file_publish.c */
diff --git a/src/fs/main_window_file_search.c b/src/fs/main_window_file_search.c
new file mode 100644
index 00000000..bef1d2b7
--- /dev/null
+++ b/src/fs/main_window_file_search.c
@@ -0,0 +1,243 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_file_search.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "gnunet-fs-gtk.h"
27
28/**
29 * Builder used for the search dialog.
30 */
31static GtkBuilder *builder;
32
33
34/**
35 * User double-clicked on namespace or pressed enter;
36 * move namespace root to the 'keywords' line.
37 */
38void
39GNUNET_GTK_search_dialog_namespace_tree_view_row_activated_cb (GtkTreeView *tree_view,
40 GtkTreePath *path,
41 GtkTreeViewColumn *column,
42 gpointer user_data)
43{
44 GtkTreeModel *ls;
45 GtkTreeSelection *sel;
46 GtkEntry *query;
47 GtkTreeIter iter;
48 char *root;
49
50 query = GTK_ENTRY (gtk_builder_get_object (builder,
51 "GNUNET_GTK_search_dialog_keyword_entry"));
52 sel = gtk_tree_view_get_selection (tree_view);
53 if (TRUE ==
54 gtk_tree_selection_get_selected (sel,
55 &ls,
56 &iter))
57 {
58 gtk_tree_model_get (ls, &iter,
59 1, &root,
60 -1);
61 gtk_entry_set_text (query,
62 root);
63 GNUNET_free (root);
64 }
65}
66
67
68void
69GNUNET_GTK_search_dialog_search_button_clicked_cb (GtkWidget * dummy,
70 gpointer data)
71{
72 GtkEntry *query;
73 GtkSpinButton *anonymity;
74 GtkTreeView *namespace;
75 const char *keywords;
76 char *emsg;
77 struct GNUNET_FS_Uri *uri;
78 GNUNET_HashCode *nsid;
79 GtkTreeModel *ls;
80 GtkTreeSelection *sel;
81 GtkTreeIter iter;
82
83 query = GTK_ENTRY (gtk_builder_get_object (builder,
84 "GNUNET_GTK_search_dialog_keyword_entry"));
85 anonymity = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
86 "GNUNET_GTK_search_dialog_anonymity_spin_button"));
87 namespace = GTK_TREE_VIEW (gtk_builder_get_object (builder,
88 "GNUNET_GTK_search_dialog_namespace_tree_view"));
89 keywords = gtk_entry_get_text (query);
90 nsid = NULL;
91 sel = gtk_tree_view_get_selection (namespace);
92 if (TRUE ==
93 gtk_tree_selection_get_selected (sel,
94 &ls,
95 &iter))
96 gtk_tree_model_get (ls, &iter,
97 2, &nsid,
98 -1);
99 if (nsid != NULL)
100 {
101 uri = GNUNET_FS_uri_sks_create_from_nsid (nsid,
102 keywords);
103 GNUNET_assert (uri != NULL);
104 }
105 else
106 {
107 emsg = NULL;
108 uri = GNUNET_FS_uri_ksk_create (keywords, &emsg);
109 if (uri == NULL)
110 {
111 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
112 _("Invalid keyword string `%s': %s"),
113 keywords,
114 emsg);
115 GNUNET_free_non_null (emsg);
116 return;
117 }
118 }
119 GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (),
120 uri,
121 gtk_spin_button_get_value_as_int (anonymity),
122 GNUNET_FS_SEARCH_OPTION_NONE,
123 NULL);
124 GNUNET_FS_uri_destroy (uri);
125}
126
127
128
129/**
130 * Add pseudonym data to list store
131 *
132 * @param cls closure (the 'GtkListStore')
133 * @param pseudonym hash code of public key of pseudonym
134 * @param md meta data known about the pseudonym
135 * @param rating the local rating of the pseudonym
136 * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
137 */
138static int
139add_namespace_to_ls (void *cls,
140 const GNUNET_HashCode *
141 pseudonym,
142 const struct
143 GNUNET_CONTAINER_MetaData * md,
144 int rating)
145{
146 GtkListStore *ls = cls;
147 char *root;
148 char *ns_name;
149 GNUNET_HashCode *nsid;
150 char *description;
151 char *uris;
152 char *emsg;
153 struct GNUNET_FS_Uri *uri;
154 GtkTreeIter iter;
155
156 ns_name = GNUNET_PSEUDONYM_id_to_name (GNUNET_FS_GTK_get_configuration (),
157 pseudonym);
158 nsid = GNUNET_malloc (sizeof (GNUNET_HashCode));
159 *nsid = *pseudonym;
160 root = NULL;
161 uris = GNUNET_CONTAINER_meta_data_get_by_type (md,
162 EXTRACTOR_METATYPE_URI);
163 if (uris != NULL)
164 {
165 emsg = NULL;
166 uri = GNUNET_FS_uri_parse (uris, &emsg);
167 if (uri == NULL)
168 GNUNET_free (emsg);
169 root = GNUNET_FS_uri_sks_get_content_id (uri);
170 GNUNET_FS_uri_destroy (uri);
171 }
172 description = GNUNET_CONTAINER_meta_data_get_first_by_types (md,
173 EXTRACTOR_METATYPE_TITLE,
174 EXTRACTOR_METATYPE_BOOK_TITLE,
175 EXTRACTOR_METATYPE_DESCRIPTION,
176 EXTRACTOR_METATYPE_SUMMARY,
177 EXTRACTOR_METATYPE_ALBUM,
178 EXTRACTOR_METATYPE_COMMENT,
179 EXTRACTOR_METATYPE_SUBJECT,
180 EXTRACTOR_METATYPE_KEYWORDS,
181 -1);
182 gtk_list_store_insert_with_values (ls,
183 &iter,
184 G_MAXINT,
185 0, ns_name,
186 1, root,
187 2, nsid,
188 3, description,
189 -1);
190 GNUNET_free (ns_name);
191 GNUNET_free_non_null (root);
192 GNUNET_free_non_null (description);
193 return GNUNET_OK;
194}
195
196
197/**
198 * Search selected in 'file' menu.
199 */
200void
201GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
202 gpointer data)
203{
204 GtkWidget *ad;
205 GtkListStore *ls;
206 GtkTreeIter iter;
207 GNUNET_HashCode *nsid;
208
209 GNUNET_assert (builder == NULL);
210 builder = GNUNET_GTK_get_new_builder ("search_dialog.glade");
211 if (builder == NULL)
212 return;
213 ad = GTK_WIDGET (gtk_builder_get_object (builder,
214 "GNUNET_GTK_search_dialog"));
215 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
216 "GNUNET_GTK_namespace_list_store"));
217 GNUNET_PSEUDONYM_list_all (GNUNET_FS_GTK_get_configuration (),
218 &add_namespace_to_ls,
219 ls);
220 gtk_dialog_run (GTK_DIALOG (ad));
221
222 /* free nsids from 'ls' */
223 if (TRUE ==
224 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls),
225 &iter))
226 {
227 do
228 {
229 gtk_tree_model_get (GTK_TREE_MODEL (ls),
230 &iter,
231 2, &nsid,
232 -1);
233 GNUNET_free (nsid);
234 }
235 while (TRUE == gtk_tree_model_iter_next (GTK_TREE_MODEL (ls),
236 &iter));
237 }
238 gtk_widget_destroy (ad);
239 g_object_unref (G_OBJECT (builder));
240 builder = NULL;
241}
242
243/* end of main_window_file_search.c */
diff --git a/src/fs/main_window_open_directory.c b/src/fs/main_window_open_directory.c
new file mode 100644
index 00000000..9419ef17
--- /dev/null
+++ b/src/fs/main_window_open_directory.c
@@ -0,0 +1,147 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_open_directory.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "fs_event_handler.h"
27
28struct AddChildContext
29{
30 const char *filename;
31 GtkTreeStore *ts;
32 struct SearchTab *tab;
33 struct SearchResult *par;
34 GtkTreeRowReference *prr;
35 GtkTreeIter iter;
36};
37
38
39/**
40 * Function used to process entries in a directory.
41 *
42 * @param cls closure, our 'struct AddChildContext*'
43 * @param filename name of the file in the directory
44 * @param uri URI of the file
45 * @param metadata metadata for the file; metadata for
46 * the directory if everything else is NULL/zero
47 * @param length length of the available data for the file
48 * (of type size_t since data must certainly fit
49 * into memory; if files are larger than size_t
50 * permits, then they will certainly not be
51 * embedded with the directory itself).
52 * @param data data available for the file (length bytes)
53 */
54static void
55add_child (void *cls,
56 const char *filename,
57 const struct GNUNET_FS_Uri *uri,
58 const struct GNUNET_CONTAINER_MetaData *meta,
59 size_t length,
60 const void *data)
61{
62 struct AddChildContext *acc = cls;
63 struct GNUNET_CONTAINER_MetaData *dmeta;
64 GtkTreePath *tp;
65 GtkTreeIter iter;
66
67 if (uri == NULL)
68 {
69 /* directory meta data itself */
70 dmeta = GNUNET_CONTAINER_meta_data_duplicate (meta);
71 GNUNET_CONTAINER_meta_data_insert (dmeta,
72 "<user>",
73 EXTRACTOR_METATYPE_FILENAME,
74 EXTRACTOR_METAFORMAT_C_STRING,
75 "text/plain",
76 acc->filename,
77 strlen (acc->filename) + 1);
78 acc->tab = GNUNET_GTK_add_to_uri_tab (&acc->iter,
79 &acc->par,
80 dmeta,
81 NULL);
82 tp = gtk_tree_model_get_path (GTK_TREE_MODEL (acc->tab->ts),
83 &acc->iter);
84 acc->prr = gtk_tree_row_reference_new (GTK_TREE_MODEL (acc->tab->ts),
85 tp);
86 gtk_tree_path_free (tp);
87 acc->ts = acc->tab->ts;
88 GNUNET_CONTAINER_meta_data_destroy (dmeta);
89 return;
90 }
91 if (acc->ts == NULL)
92 return;
93 GNUNET_assert (NULL !=
94 GNUNET_GTK_add_search_result (acc->tab,
95 &iter,
96 acc->prr,
97 uri,
98 meta,
99 NULL,
100 0));
101}
102
103
104/**
105 * User selected "Open directory" in menu. Display dialog, open
106 * file and then display a new tab with its contents.
107 */
108void
109GNUNET_GTK_main_menu_file_open_gnunet_directory_activate_cb (GtkWidget * dummy,
110 gpointer data)
111{
112 struct AddChildContext acc;
113 GtkWidget *ad;
114 GtkBuilder *builder;
115 char *filename;
116 GtkFileFilter *ff;
117
118 builder = GNUNET_GTK_get_new_builder ("open_directory_dialog.glade");
119 if (builder == NULL)
120 {
121 GNUNET_break (0);
122 return;
123 }
124 ad = GTK_WIDGET (gtk_builder_get_object (builder,
125 "GNUNET_GTK_open_directory_dialog"));
126 ff = GTK_FILE_FILTER (gtk_builder_get_object (builder,
127 "gnunet_directory_filter"));
128 /* FIXME: some day, write a custom file filter for gnunet-directories... */
129 gtk_file_filter_add_pattern (ff, "*" GNUNET_FS_DIRECTORY_EXT);
130 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
131 {
132 gtk_widget_destroy (ad);
133 g_object_unref (G_OBJECT (builder));
134 return;
135 }
136 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
137 gtk_widget_destroy (ad);
138 g_object_unref (G_OBJECT (builder));
139 acc.filename = filename;
140 acc.ts = NULL;
141 GNUNET_FS_GTK_mmap_and_scan (filename,
142 &add_child,
143 &acc);
144 g_free (filename);
145}
146
147/* end of main_window_open_directory.c */
diff --git a/src/fs/main_window_view_toggles.c b/src/fs/main_window_view_toggles.c
new file mode 100644
index 00000000..0cdea23a
--- /dev/null
+++ b/src/fs/main_window_view_toggles.c
@@ -0,0 +1,90 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/main_window_view_toggles.c
23 * @author Christian Grothoff
24 *
25 * This file contains callbacks for the 'view' menu that toggle views.
26 */
27#include "common.h"
28#include "gnunet-fs-gtk.h"
29
30
31/**
32 * Toggle the visibility of a widget based on the checkeness
33 * of a menu item.
34 *
35 * @param toggled_widget name of widget to toggle
36 * @param toggle_menu name of menu entry
37 */
38static void
39toggle_view (const char *toggled_widget,
40 const char *toggle_menu)
41{
42 GtkCheckMenuItem *mi;
43 GtkWidget *widget;
44
45 widget = GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object (toggled_widget));
46 mi = GTK_CHECK_MENU_ITEM (GNUNET_FS_GTK_get_main_window_object (toggle_menu));
47 if (gtk_check_menu_item_get_active (mi))
48 gtk_widget_show (widget);
49 else
50 gtk_widget_hide (widget);
51}
52
53
54/**
55 * Preview view is toggled.
56 */
57void
58GNUNET_GTK_main_menu_view_preview_toggled_cb (GtkWidget * dummy,
59 gpointer data)
60{
61 toggle_view ("GNUNET_GTK_main_window_preview_image",
62 "GNUNET_GTK_main_menu_view_preview");
63}
64
65
66/**
67 * Neighbour view is toggled.
68 */
69void
70GNUNET_GTK_main_menu_view_neighbours_toggled_cb (GtkWidget * dummy,
71 gpointer data)
72{
73 toggle_view ("GNUNET_GTK_main_window_peerinfo_treeview",
74 "GNUNET_GTK_main_menu_view_neighbours");
75}
76
77
78/**
79 * Metadata view is toggled.
80 */
81void
82GNUNET_GTK_main_menu_view_metadata_toggled_cb (GtkWidget * dummy,
83 gpointer data)
84{
85 toggle_view ("GNUNET_GTK_main_window_metadata_treeview",
86 "GNUNET_GTK_main_menu_view_metadata");
87}
88
89
90/* end of main_window_view_toggles.c */