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 */