[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r16543 - in gnunet-gtk/src: . fs
From: |
gnunet |
Subject: |
[GNUnet-SVN] r16543 - in gnunet-gtk/src: . fs |
Date: |
Mon, 15 Aug 2011 16:11:40 +0200 |
Author: grothoff
Date: 2011-08-15 16:11:40 +0200 (Mon, 15 Aug 2011)
New Revision: 16543
Added:
gnunet-gtk/src/fs/
gnunet-gtk/src/fs/Makefile.am
gnunet-gtk/src/fs/about.c
gnunet-gtk/src/fs/common.c
gnunet-gtk/src/fs/common.h
gnunet-gtk/src/fs/download.c
gnunet-gtk/src/fs/download.h
gnunet-gtk/src/fs/edit_publish_dialog.c
gnunet-gtk/src/fs/edit_publish_dialog.h
gnunet-gtk/src/fs/fs_anonymity_spin_buttons.c
gnunet-gtk/src/fs/fs_event_handler.c
gnunet-gtk/src/fs/fs_event_handler.h
gnunet-gtk/src/fs/gnunet-fs-gtk.c
gnunet-gtk/src/fs/gnunet-fs-gtk.h
gnunet-gtk/src/fs/main_window_adv_pseudonym.c
gnunet-gtk/src/fs/main_window_create_pseudonym.c
gnunet-gtk/src/fs/main_window_file_download.c
gnunet-gtk/src/fs/main_window_file_publish.c
gnunet-gtk/src/fs/main_window_file_search.c
gnunet-gtk/src/fs/main_window_open_directory.c
gnunet-gtk/src/fs/main_window_view_toggles.c
Log:
gnunet-fs-gtk against new libgnunetgtk library
Added: gnunet-gtk/src/fs/Makefile.am
===================================================================
--- gnunet-gtk/src/fs/Makefile.am (rev 0)
+++ gnunet-gtk/src/fs/Makefile.am 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,36 @@
+SUBDIRS = .
+
+INCLUDES = \
+ -I$(top_srcdir)/ \
+ -I$(top_srcdir)/src/include \
+ @GTK_CFLAGS@ \
+ @GNUNET_CFLAGS@ \
+ @GLADE_CFLAGS@
+
+bin_PROGRAMS = gnunet-fs-gtk
+
+gnunet_fs_gtk_SOURCES = \
+ about.c \
+ common.c common.h \
+ download.c download.h \
+ edit_publish_dialog.c edit_publish_dialog.h \
+ fs_event_handler.c fs_event_handler.h \
+ fs_anonymity_spin_buttons.c \
+ gnunet-fs-gtk.c gnunet-fs-gtk.h \
+ main_window_create_pseudonym.c \
+ main_window_file_download.c \
+ main_window_file_publish.c \
+ main_window_file_search.c \
+ main_window_open_directory.c \
+ main_window_adv_pseudonym.c \
+ main_window_view_toggles.c
+gnunet_fs_gtk_LDADD = \
+ $(top_builddir)/src/lib/libgnunetgtk.la \
+ @GTK_LIBS@ \
+ @GLADE_LIBS@ \
+ -lextractor \
+ -lgnunetutil \
+ -lgnunetfs \
+ $(INTLLIBS)
+gnunet_fs_gtk_LDFLAGS = \
+ -export-dynamic
Copied: gnunet-gtk/src/fs/about.c (from rev 16478, gnunet-gtk/src/about.c)
===================================================================
--- gnunet-gtk/src/fs/about.c (rev 0)
+++ gnunet-gtk/src/fs/about.c 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,42 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs/about.c
+ * @author Christian Grothoff
+ * @author Igor Wronsky
+ *
+ * This file contains the about dialog.
+ */
+#include "gnunet_gtk.h"
+
+
+/**
+ * This displays an about window
+ */
+void
+GNUNET_GTK_main_menu_help_about_activate_cb (GtkWidget * dummy, gpointer data)
+{
+ GNUNET_GTK_display_about ("gnunet_fs_gtk_about_dialog.glade",
+ "GNUNET_GKT_about_dialog");
+}
+
+
+/* end of about.c */
Copied: gnunet-gtk/src/fs/common.c (from rev 16478, gnunet-gtk/src/common.c)
===================================================================
--- gnunet-gtk/src/fs/common.c (rev 0)
+++ gnunet-gtk/src/fs/common.c 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,183 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs/common.c
+ * @brief Common functions used in various places
+ * @author Christian Grothoff
+ */
+#include "common.h"
+
+/**
+ * Add meta data to list store.
+ *
+ * @param cls closure (the GtkListStore)
+ * @param plugin_name name of the plugin that produced this value;
+ * special values can be used (i.e. '<zlib>' for zlib being
+ * used in the main libextractor library and yielding
+ * meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data
+ * @param data_mime_type mime-type of data (not of the original file);
+ * can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue (always)
+ */
+int
+GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len)
+{
+ GtkListStore *ls = GTK_LIST_STORE (cls);
+
+ if ( (format == EXTRACTOR_METAFORMAT_UTF8) ||
+ (format == EXTRACTOR_METAFORMAT_C_STRING) )
+ gtk_list_store_insert_with_values (ls,
+ NULL,
+ G_MAXINT,
+ 0, type,
+ 1, format,
+ 2, EXTRACTOR_metatype_to_string (type),
+ 3, data,
+ -1);
+ return 0;
+}
+
+
+/**
+ * Convert the year from the spin button to an expiration
+ * time (on midnight, January 1st of that year).
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_FS_GTK_get_expiration_time (GtkSpinButton *spin)
+{
+ struct GNUNET_TIME_Absolute ret;
+ int year;
+
+ year = gtk_spin_button_get_value_as_int (spin);
+ GNUNET_assert (year >= 0);
+ ret = GNUNET_FS_year_to_time ( (unsigned int) year);
+ GNUNET_break (GNUNET_TIME_absolute_get ().abs_value < ret.abs_value);
+ return ret;
+}
+
+
+void
+GNUNET_FS_GTK_setup_expiration_year_adjustment (GtkBuilder *builder)
+{
+ GtkAdjustment *aj;
+ unsigned int year;
+
+ year = GNUNET_FS_get_current_year ();
+ aj = GTK_ADJUSTMENT (gtk_builder_get_object (builder,
+ "expiration_year_adjustment"));
+ gtk_adjustment_set_value (aj, year + 2);
+ gtk_adjustment_set_lower (aj, year + 1);
+}
+
+
+GdkPixbuf *
+GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct
GNUNET_CONTAINER_MetaData *meta)
+{
+ GdkPixbuf *pixbuf;
+ GdkPixbufLoader *loader;
+ size_t ts;
+ unsigned char *thumb;
+
+ thumb = NULL;
+ ts = GNUNET_CONTAINER_meta_data_get_thumbnail (meta, &thumb);
+ if (ts == 0)
+ return NULL;
+ loader = gdk_pixbuf_loader_new ();
+ gdk_pixbuf_loader_write (loader, (const guchar *) thumb, ts, NULL);
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ gdk_pixbuf_loader_close (loader, NULL);
+ if (pixbuf != NULL)
+ g_object_ref (pixbuf);
+ g_object_unref (loader);
+ GNUNET_free (thumb);
+ return pixbuf;
+}
+
+
+/**
+ * mmap the given file and run the GNUNET_FS_directory_list_contents
+ * function on it.
+ */
+void
+GNUNET_FS_GTK_mmap_and_scan (const char *filename,
+ GNUNET_FS_DirectoryEntryProcessor dep,
+ void *dep_cls)
+{
+ struct GNUNET_DISK_FileHandle *fh;
+ struct GNUNET_DISK_MapHandle *mh;
+ uint64_t fsize;
+ void * ddata;
+
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename,
+ &fsize,
+ GNUNET_YES))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ fh = GNUNET_DISK_file_open (filename,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (fh == NULL)
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
+ return;
+ }
+ ddata = GNUNET_DISK_file_map (fh,
+ &mh,
+ GNUNET_DISK_MAP_TYPE_READ,
+ (size_t) fsize);
+ if (ddata == NULL)
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mmap", filename);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (fh));
+ return;
+ }
+ if (GNUNET_SYSERR ==
+ GNUNET_FS_directory_list_contents ((size_t) fsize,
+ ddata,
+ 0,
+ dep, dep_cls))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Selected file `%s' is not a GNUnet directory!\n"),
+ filename);
+ }
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_unmap (mh));
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (fh));
+}
+
+
+/* end of common.c */
Copied: gnunet-gtk/src/fs/common.h (from rev 16478, gnunet-gtk/src/common.h)
===================================================================
--- gnunet-gtk/src/fs/common.h (rev 0)
+++ gnunet-gtk/src/fs/common.h 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,89 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs/common.h
+ * @brief Common includes for all gnunet-gtk source files
+ * @author Christian Grothoff
+ */
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "gnunet_gtk.h"
+#include <gnunet/gnunet_fs_service.h>
+#include <extractor.h>
+
+
+
+GdkPixbuf *
+GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct
GNUNET_CONTAINER_MetaData *meta);
+
+/**
+ * Setup the expiration year adjustment to start with the
+ * next year and default to next year plus one.
+ */
+void
+GNUNET_FS_GTK_setup_expiration_year_adjustment (GtkBuilder *builder);
+
+/**
+ * Convert the year from the spin button to an expiration
+ * time (on midnight, January 1st of that year).
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_FS_GTK_get_expiration_time (GtkSpinButton *spin);
+
+
+/**
+ * mmap the given file and run the GNUNET_FS_directory_list_contents
+ * function on it.
+ */
+void
+GNUNET_FS_GTK_mmap_and_scan (const char *filename,
+ GNUNET_FS_DirectoryEntryProcessor dep,
+ void *dep_cls);
+
+
+/**
+ * Add meta data to list store.
+ *
+ * @param cls closure (the GtkListStore)
+ * @param plugin_name name of the plugin that produced this value;
+ * special values can be used (i.e. '<zlib>' for zlib being
+ * used in the main libextractor library and yielding
+ * meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data
+ * @param data_mime_type mime-type of data (not of the original file);
+ * can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue (always)
+ */
+int
+GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len);
+
+#endif
+/* end of common.h */
Copied: gnunet-gtk/src/fs/download.c (from rev 16478, gnunet-gtk/src/download.c)
===================================================================
--- gnunet-gtk/src/fs/download.c (rev 0)
+++ gnunet-gtk/src/fs/download.c 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,136 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/download.c
+ * @brief functions for downloading
+ * @author Christian Grothoff
+ */
+#include "download.h"
+#include "gnunet-fs-gtk.h"
+#include "fs_event_handler.h"
+
+void
+GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc)
+{
+ GtkWidget *ad;
+ GtkBuilder *builder;
+ struct GNUNET_FS_Handle *fs;
+ uint64_t len;
+ enum GNUNET_FS_DownloadOptions opt;
+ uint32_t anonymity;
+ struct DownloadEntry *de;
+ GtkWidget *cb;
+
+ builder = GNUNET_GTK_get_new_builder ("download_as.glade");
+ if (builder == NULL)
+ {
+ if (dc->rr != NULL)
+ gtk_tree_row_reference_free (dc->rr);
+ GNUNET_free_non_null (dc->mime);
+ GNUNET_free_non_null (dc->filename);
+ GNUNET_FS_uri_destroy (dc->uri);
+ GNUNET_free (dc);
+ return;
+ }
+ cb = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_save_as_recursive_check_button"));
+ if (GNUNET_FS_meta_data_test_for_directory (dc->meta))
+ gtk_widget_set_sensitive (cb, TRUE);
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+ "GNUNET_GTK_save_as_dialog"));
+ if (dc->filename != NULL)
+ {
+ char buf[1024];
+ if (NULL != getcwd (buf, sizeof(buf)))
+ {
+ if (strlen (buf) + strlen (dc->filename) + 2 < sizeof(buf))
+ {
+ strcat (buf, DIR_SEPARATOR_STR);
+ strcat (buf, dc->filename);
+ }
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad),
+ buf);
+ }
+ }
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ if (dc->rr != NULL)
+ gtk_tree_row_reference_free (dc->rr);
+ GNUNET_free_non_null (dc->mime);
+ GNUNET_free_non_null (dc->filename);
+ GNUNET_FS_uri_destroy (dc->uri);
+ GNUNET_free (dc);
+ return;
+ }
+ GNUNET_free_non_null (dc->filename);
+ dc->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
+ dc->is_recursive = (TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(cb))) ? GNUNET_YES : GNUNET_NO;
+ fs = GNUNET_FS_GTK_get_fs_handle ();
+ opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
+ if (dc->is_recursive)
+ opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
+ anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
+ len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ de = GNUNET_malloc (sizeof (struct DownloadEntry));
+ de->uri = dc->uri;
+ de->meta = dc->meta;
+ if (dc->rr != NULL)
+ {
+ de->rr = dc->rr;
+ de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
+ }
+ if (dc->sr != NULL)
+ {
+ GNUNET_break (NULL !=
+ GNUNET_FS_download_start_from_search (fs,
+ dc->sr,
+ dc->filename,
+ NULL /* tempname */,
+ 0 /* offset */,
+ len,
+ anonymity,
+ opt,
+ de));
+ }
+ else
+ {
+ GNUNET_break (NULL !=
+ GNUNET_FS_download_start (fs,
+ dc->uri,
+ NULL /* meta */,
+ dc->filename,
+ NULL /* tempname */,
+ 0 /* offset */,
+ len,
+ anonymity,
+ opt,
+ de,
+ NULL /* parent download ctx */));
+ }
+ GNUNET_free (dc);
+}
+
+/* end of download.c */
Copied: gnunet-gtk/src/fs/download.h (from rev 16478, gnunet-gtk/src/download.h)
===================================================================
--- gnunet-gtk/src/fs/download.h (rev 0)
+++ gnunet-gtk/src/fs/download.h 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,83 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/download.h
+ * @brief functions for downloading
+ * @author Christian Grothoff
+ */
+
+#ifndef DOWNLOAD_H
+#define DOWNLOAD_H
+#include "common.h"
+
+/**
+ * Information we keep for a download.
+ */
+struct DownloadContext
+{
+ /**
+ * URI for the download.
+ */
+ struct GNUNET_FS_Uri *uri;
+
+ /**
+ * Meta data.
+ */
+ struct GNUNET_CONTAINER_MetaData *meta;
+
+ /**
+ * Mime type.
+ */
+ char *mime;
+
+ /**
+ * Suggested filename, or NULL.
+ */
+ char *filename;
+
+ /**
+ * Row reference (if URI was found by search, or
+ * part of directory, etc.); otherwise NULL (download by URI).
+ */
+ GtkTreeRowReference *rr;
+
+ /**
+ * Associated search result, or NULL.
+ */
+ struct GNUNET_FS_SearchResult *sr;
+
+ /**
+ * Is this a recursive download?
+ */
+ int is_recursive;
+
+ /**
+ * Desired (default) anonymity level.
+ */
+ int anonymity;
+};
+
+
+
+void
+GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc);
+
+#endif
Added: gnunet-gtk/src/fs/edit_publish_dialog.c
===================================================================
--- gnunet-gtk/src/fs/edit_publish_dialog.c (rev 0)
+++ gnunet-gtk/src/fs/edit_publish_dialog.c 2011-08-15 14:11:40 UTC (rev
16543)
@@ -0,0 +1,771 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/edit_publish_dialog.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "edit_publish_dialog.h"
+#include <gnunet/gnunet_util_lib.h>
+
+/**
+ * Builder for the current dialog.
+ */
+static GtkBuilder *builder;
+
+/**
+ * Are we editing metadata for a directory?
+ */
+static int is_directory;
+
+/**
+ * Set to YES if the preview was changed.
+ */
+static int preview_changed;
+
+void
+GNUNET_GTK_edit_file_information_keyword_list_normalize_button_clicked_cb ()
+{
+ GNUNET_break (0);
+}
+
+void
+GNUNET_GTK_edit_file_information_keyword_list_del_button_clicked_cb ()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_list_store_remove (GTK_LIST_STORE (tm),
+ &iter);
+}
+
+void
+GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ()
+{
+ const char *keyword;
+ GtkEntry *entry;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_keyword_list_store"));
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_entry"));
+ keyword = gtk_entry_get_text (entry);
+ if (strlen (keyword) > 0)
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
+ gtk_entry_set_text (entry, "");
+}
+
+
+void
+GNUNET_GTK_edit_file_information_keyword_entry_changed_cb ()
+{
+ const char *keyword;
+ GtkEntry *entry;
+ GtkWidget *button;
+
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_add_button"));
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_entry"));
+ keyword = gtk_entry_get_text (entry);
+ gtk_widget_set_sensitive (button,
+ (strlen (keyword) > 0) ? TRUE : FALSE);
+}
+
+
+static void
+metadata_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkWidget *button;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_delete_button"));
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+}
+
+
+static void
+keyword_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkWidget *button;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_del_button"));
+
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_normalize_button"));
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+}
+
+
+void
+GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb ()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ const char *value;
+ GtkEntry *entry;
+ GtkWidget *button;
+
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_value_entry"));
+ value = gtk_entry_get_text (entry);
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_add_button"));
+ gtk_widget_set_sensitive (button,
+ (strlen (value) > 0)
+ ? gtk_tree_selection_get_selected (sel, NULL, NULL)
+ : FALSE);
+}
+
+
+void
+GNUNET_GTK_edit_file_information_keyword_entry_activate_cb ()
+{
+ GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ();
+}
+
+
+void
+GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button_file_set_cb
(GtkFileChooserButton *widget,
+
gpointer user_data)
+{
+ gchar *fn;
+ GtkImage *image;
+
+ fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ image = GTK_IMAGE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_preview_image"));
+ gtk_image_set_from_file (image, fn);
+ preview_changed = GNUNET_YES;
+}
+
+
+void
+GNUNET_GTK_edit_file_information_metadata_delete_button_clicked_cb()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_list_store_remove (GTK_LIST_STORE (tm),
+ &iter);
+}
+
+
+void
+GNUNET_GTK_edit_file_information_metadata_add_button_clicked_cb ()
+{
+ const char *value;
+ char *avalue;
+ const char *ivalue;
+ GtkEntry *entry;
+ GtkListStore *ls;
+ GtkTreeModel *tm;
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ guint type;
+ size_t slen;
+ char *pos;
+
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_value_entry"));
+ value = gtk_entry_get_text (entry);
+ if ((value == NULL) || (strlen (value) == 0))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
+ tm = gtk_tree_view_get_model (tv);
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm,
+ &iter,
+ 1, &type, -1);
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
+ (value[strlen(value)-1] != '/') &&
+ (is_directory) )
+ {
+ GNUNET_asprintf (&avalue,
+ "%s/",
+ value);
+ /* if user typed '\' instead of '/', change it! */
+ slen = strlen (avalue);
+ while ( (slen > 1) &&
+ (avalue[slen-2] == '\\') )
+ {
+ avalue[slen-2] = '/';
+ avalue[slen-1] = '\0';
+ slen--;
+ }
+ while (NULL != (pos = strstr (avalue, "\\")))
+ *pos = '/';
+ /* remove '../' everywhere */
+ while (NULL != (pos = strstr (avalue, "../")))
+ {
+ pos[0] = '_';
+ pos[1] = '_';
+ pos[2] = '_';
+ }
+ ivalue = avalue;
+ }
+ else
+ {
+ ivalue = value;
+ avalue = NULL;
+ }
+
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
+ 0, type,
+ 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
+ 2, EXTRACTOR_metatype_to_string (type),
+ 3, ivalue,
+ -1);
+ GNUNET_free_non_null (avalue);
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+}
+
+
+/**
+ * Add each of the keywords to the keyword list store.
+ *
+ * @param cls closure
+ * @param keyword the keyword
+ * @param is_mandatory is the keyword mandatory (in a search)
+ * @return GNUNET_OK to continue to iterate
+ */
+static int
+add_keyword (void *cls,
+ const char *keyword,
+ int is_mandatory)
+{
+ GtkListStore *ls;
+ GtkTreeIter iter;
+
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_keyword_list_store"));
+ gtk_list_store_insert_with_values (ls, &iter,
+ G_MAXINT,
+ 0, keyword,
+ -1);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Add the given meta data to the model (or make it the preview
+ * image if it is an image).
+ *
+ * @param cls closure, NULL
+ * @param plugin_name name of the plugin that produced this value;
+ * special values can be used (i.e. '<zlib>' for zlib being
+ * used in the main libextractor library and yielding
+ * meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data
+ * @param data_mime_type mime-type of data (not of the original file);
+ * can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue extracting
+ */
+static int
+add_meta_item (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len)
+{
+ GtkListStore *ls;
+ GtkTreeIter iter;
+
+ switch (format)
+ {
+ case EXTRACTOR_METAFORMAT_UTF8:
+ case EXTRACTOR_METAFORMAT_C_STRING:
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ gtk_list_store_insert_with_values (ls, &iter,
+ G_MAXINT,
+ 0, (guint) type,
+ 1, (guint) format,
+ 2, EXTRACTOR_metatype_to_string (type),
+ 3, data,
+ -1);
+ break;
+ case EXTRACTOR_METAFORMAT_UNKNOWN:
+ break;
+ case EXTRACTOR_METAFORMAT_BINARY:
+ break;
+ default:
+ GNUNET_break (0);
+ }
+ return 0;
+}
+
+
+/**
+ * Function called to extract the information from FI.
+ *
+ * @param cls closure
+ * @param fi the entry in the publish-structure
+ * @param length length of the file or directory
+ * @param meta metadata for the file or directory (can be modified)
+ * @param uri pointer to the keywords that will be used for this entry (can be
modified)
+ * @param bo block options
+ * @param do_index should we index (can be modified)
+ * @param client_info pointer to client context set upon creation (can be
modified)
+ * @return GNUNET_SYSERR (aborts after first call)
+ */
+static int
+file_information_extract (void *cls,
+ struct GNUNET_FS_FileInformation *fi,
+ uint64_t length,
+ struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_Uri **uri,
+ struct GNUNET_FS_BlockOptions *bo,
+ int *do_index,
+ void **client_info)
+{
+ GtkImage *img;
+ GdkPixbuf *pixbuf;
+ struct tm *t;
+ int year;
+ time_t tp;
+
+ if (NULL != *uri)
+ GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword, NULL);
+ if (NULL != meta)
+ {
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+ &add_meta_item,
+ NULL);
+ pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
+ if (pixbuf != NULL)
+ {
+ img = GTK_IMAGE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_preview_image"));
+ gtk_image_set_from_pixbuf (img,
+ pixbuf);
+ }
+ }
+ tp = bo->expiration_time.abs_value / 1000; /* ms to seconds */
+ t = gmtime (&tp);
+ if (t == NULL)
+ year = 0;
+ else
+ year = t->tm_year + 1900;
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_expiration_year_spin_button")),
+ year);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_anonymity_spin_button")),
+ bo->anonymity_level);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_priority_spin_button")),
+ bo->content_priority);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object
(builder,
+
"GNUNET_GTK_edit_file_information_index_check_button")),
+ *do_index);
+ return GNUNET_SYSERR; /* only visit top-level item */
+}
+
+
+/**
+ * Copy binary meta data from to the new container and also
+ * preserve all entries that were not changed.
+ *
+ * @param cls closure, new meta data container
+ * @param plugin_name name of the plugin that produced this value;
+ * special values can be used (i.e. '<zlib>' for zlib being
+ * used in the main libextractor library and yielding
+ * meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data
+ * @param data_mime_type mime-type of data (not of the original file);
+ * can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue extracting
+ */
+static int
+preserve_meta_items (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len)
+{
+ struct GNUNET_CONTAINER_MetaData *md = cls;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ gchar *value;
+ guint ntype;
+ guint nformat;
+ int keep;
+
+ keep = GNUNET_NO;
+ switch (format)
+ {
+ case EXTRACTOR_METAFORMAT_UTF8:
+ case EXTRACTOR_METAFORMAT_C_STRING:
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 0, &ntype,
+ 1, &nformat,
+ 3, &value,
+ -1);
+ if ( (ntype == type) &&
+ (nformat == format) &&
+ (0 == strcmp (value, data)) )
+ {
+ gtk_list_store_remove (GTK_LIST_STORE (tm), &iter);
+ keep = GNUNET_YES;
+ g_free (value);
+ break;
+ }
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ break;
+ case EXTRACTOR_METAFORMAT_UNKNOWN:
+ break;
+ case EXTRACTOR_METAFORMAT_BINARY:
+ if (preview_changed == GNUNET_NO)
+ keep = GNUNET_YES;
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+ if (GNUNET_YES == keep)
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_meta_data_insert (md,
+ plugin_name, type, format,
+ data_mime_type, data,
data_len));
+ return 0;
+}
+
+
+/**
+ * Function called to update the information in FI.
+ *
+ * @param cls closure (short_fn to update)
+ * @param fi the entry in the publish-structure
+ * @param length length of the file or directory
+ * @param meta metadata for the file or directory (can be modified)
+ * @param uri pointer to the keywords that will be used for this entry (can be
modified)
+ * @param bo block options (can be modified)
+ * @param do_index should we index (can be modified)
+ * @param client_info pointer to client context set upon creation (can be
modified)
+ * @return GNUNET_SYSERR (aborts after first call)
+ */
+static int
+file_information_update (void *cls,
+ struct GNUNET_FS_FileInformation *fi,
+ uint64_t length,
+ struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_Uri **uri,
+ struct GNUNET_FS_BlockOptions *bo,
+ int *do_index,
+ void **client_info)
+{
+ char **short_fn = cls;
+ struct GNUNET_CONTAINER_MetaData *nm;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *nxt;
+ struct GNUNET_FS_Uri *mrg;
+ gchar *value;
+ guint ntype;
+ guint nformat;
+ GtkSpinButton *sb;
+ gchar *fn;
+ char *data;
+ gsize data_size;
+ const char *mime;
+ GFile *f;
+ GFileInfo *finfo;
+
+ bo->anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_anonymity_spin_button")));
+ bo->content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_priority_spin_button")));
+ *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_index_check_button")));
+ sb =GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_expiration_year_spin_button"));
+ bo->expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
+ /* update URI */
+ if (NULL != (*uri))
+ GNUNET_FS_uri_destroy (*uri);
+ *uri = NULL;
+ nxt = NULL;
+ mrg = NULL;
+
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
+
"GNUNET_GTK_keyword_list_store"));
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 0, &value,
+ -1);
+ nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
+ mrg = GNUNET_FS_uri_ksk_merge (nxt, *uri);
+ GNUNET_FS_uri_destroy (nxt);
+ if (NULL != *uri)
+ GNUNET_FS_uri_destroy (*uri);
+ *uri = mrg;
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+
+ /* update meta */
+ nm = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+ &preserve_meta_items,
+ nm);
+
+ GNUNET_CONTAINER_meta_data_clear (meta);
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 0, &ntype,
+ 1, &nformat,
+ 3, &value,
+ -1);
+ GNUNET_CONTAINER_meta_data_insert (nm,
+ "<user>",
+ ntype,
+ nformat,
+ "text/plain",
+ value,
+ strlen (value)+1);
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ GNUNET_CONTAINER_meta_data_merge (meta, nm);
+ if (preview_changed == GNUNET_YES)
+ {
+ fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button")));
+ f = g_file_new_for_path (fn);
+ finfo = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0,
NULL, NULL);
+ if (FALSE == g_file_load_contents (f, NULL, &data, &data_size, NULL,
NULL))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Could not load preview `%s' into memory\n"),
+ fn);
+ }
+ else
+ {
+ mime = g_file_info_get_attribute_string (finfo,
+
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
+ GNUNET_CONTAINER_meta_data_insert (meta,
+ "<user>",
+ EXTRACTOR_METATYPE_THUMBNAIL,
+ EXTRACTOR_METAFORMAT_BINARY,
+ mime,
+ data,
+ data_size);
+ }
+ g_object_unref (finfo);
+ g_object_unref (f);
+ }
+ GNUNET_CONTAINER_meta_data_destroy (nm);
+
+ /* update short_fn */
+ GNUNET_free_non_null (*short_fn);
+ *short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_FILENAME,
+ -1);
+ /* FIXME: update expiration time? (not yet in dialog!) */
+ return GNUNET_SYSERR; /* only visit top-level item */
+}
+
+
+/**
+ * Open the dialog to edit file information data.
+ */
+void
+GNUNET_GTK_edit_publish_dialog (int *do_index,
+ char **short_fn,
+ guint *anonymity_level,
+ guint *priority,
+ struct GNUNET_FS_FileInformation *fip)
+{
+ GtkWidget *ad;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+ guint type;
+ guint max_type;
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+
+ GNUNET_assert (builder == NULL);
+ builder = GNUNET_GTK_get_new_builder ("publish_edit_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ preview_changed = GNUNET_NO;
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
+ if (GNUNET_FS_file_information_is_directory (fip))
+ {
+ /* indexing does not apply to directories */
+ gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_index_check_button")));
+ gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_index_label")));
+
+ }
+
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_dialog"));
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_metatype_list_store"));
+ max_type = EXTRACTOR_metatype_get_max ();
+ type = 1;
+ while (type < max_type - 1)
+ {
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
+ 0, EXTRACTOR_metatype_to_string (type),
+ 1, type,
+ 2, EXTRACTOR_metatype_to_description
(type),
+ -1);
+ type++;
+ }
+
+ GNUNET_FS_file_information_inspect (fip,
+ &file_information_extract,
+ NULL);
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+
G_CALLBACK(GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb),
NULL);
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(metadata_selection_changed_cb), NULL);
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(keyword_selection_changed_cb), NULL);
+ gtk_window_set_title (GTK_WINDOW (ad), *short_fn);
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+ return;
+ }
+ GNUNET_FS_file_information_inspect (fip,
+ &file_information_update,
+ short_fn);
+ *anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_anonymity_spin_button")));
+ *priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_priority_spin_button")));
+ *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_edit_file_information_index_check_button")));
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+}
+
+/* end of edit_publish_dialog.c */
Added: gnunet-gtk/src/fs/edit_publish_dialog.h
===================================================================
--- gnunet-gtk/src/fs/edit_publish_dialog.h (rev 0)
+++ gnunet-gtk/src/fs/edit_publish_dialog.h 2011-08-15 14:11:40 UTC (rev
16543)
@@ -0,0 +1,41 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/edit_publish_dialog.h
+ * @author Christian Grothoff
+ */
+#ifndef EDIT_PUBLISH_DIALOG_H
+#define EDIT_PUBLISH_DIALOG_H
+
+#include "common.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_fs_service.h>
+
+
+void
+GNUNET_GTK_edit_publish_dialog (int *do_index,
+ char **short_fn,
+ guint *anonymity_level,
+ guint *priority,
+ struct GNUNET_FS_FileInformation *fip);
+
+#endif
+/* end of edit_publish_dialog.h */
Added: gnunet-gtk/src/fs/fs_anonymity_spin_buttons.c
===================================================================
--- gnunet-gtk/src/fs/fs_anonymity_spin_buttons.c
(rev 0)
+++ gnunet-gtk/src/fs/fs_anonymity_spin_buttons.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,73 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs_anonymtiy_spin_buttons.c
+ * @author Christian Grothoff
+ *
+ * This file contains callbacks to turn spin buttons red when the
+ * value reaches zero.
+ */
+#include "common.h"
+
+
+/**
+ * Spin button is changed, update its colour.
+ */
+void
+GNUNET_GTK_anonymity_spin_button_value_changed_cb (GtkWidget *w,
+ gpointer data)
+{
+ GtkSpinButton *spin;
+ gint val;
+ GdkColor bcolor;
+ GdkColor fcolor;
+
+ spin = GTK_SPIN_BUTTON (w);
+ if (spin == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ val = gtk_spin_button_get_value_as_int (spin);
+ if (val == 0)
+ {
+ if ((TRUE == gdk_color_parse ("red",
+ &bcolor)) &&
+ (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
+ &bcolor, FALSE, TRUE)) &&
+ (TRUE == gdk_color_parse ("black",
+ &fcolor)) &&
+ (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
+ &fcolor, FALSE, TRUE)))
+ {
+ gtk_widget_modify_base (w, GTK_STATE_NORMAL, &bcolor);
+ gtk_widget_modify_text (w, GTK_STATE_NORMAL, &fcolor);
+ }
+ }
+ else
+ {
+ gtk_widget_modify_base (w, GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_text (w, GTK_STATE_NORMAL, NULL);
+ }
+}
+
+
+/* end of fs_anonymtiy_spin_buttons.c */
Copied: gnunet-gtk/src/fs/fs_event_handler.c (from rev 16478,
gnunet-gtk/src/fs_event_handler.c)
===================================================================
--- gnunet-gtk/src/fs/fs_event_handler.c (rev 0)
+++ gnunet-gtk/src/fs/fs_event_handler.c 2011-08-15 14:11:40 UTC (rev
16543)
@@ -0,0 +1,2028 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs_event_handler.c
+ * @brief Main event handler for file-sharing
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+#include "download.h"
+#include "fs_event_handler.h"
+#include <string.h>
+
+static struct SearchTab *search_tab_head;
+
+static struct SearchTab *search_tab_tail;
+
+struct PublishTab
+{
+ /**
+ * This is a doubly-linked list.
+ */
+ struct PublishTab *next;
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct PublishTab *prev;
+
+ GtkWidget *frame;
+
+ GtkBuilder *builder;
+
+ /**
+ * Associated (top-level) FS publish operation.
+ */
+ struct GNUNET_FS_PublishContext *pc;
+
+ GtkTreeStore *ts;
+};
+
+
+struct PublishEntry
+{
+ /**
+ * Associated FS publish operation.
+ */
+ struct GNUNET_FS_PublishContext *pc;
+
+ /**
+ * Tab storing this entry.
+ */
+ struct PublishTab *tab;
+
+ /**
+ * Where in the tab is this entry?
+ */
+ GtkTreeRowReference *rr;
+
+ /**
+ * URI of the file (set after completion).
+ */
+ struct GNUNET_FS_Uri *uri;
+
+ int is_top;
+};
+
+
+struct SearchResult
+{
+ /**
+ * Where in the tab is this result?
+ */
+ GtkTreeRowReference *rr;
+
+ /**
+ * Tab storing this result.
+ */
+ struct SearchTab *tab;
+
+ /**
+ * Search result for top-level results and
+ * namespace-update results.
+ */
+ struct GNUNET_FS_SearchResult *result;
+
+ /**
+ * Associated download, or NULL for none.
+ */
+ struct DownloadEntry *download;
+};
+
+
+
+static struct PublishTab *publish_tab_head;
+
+static struct PublishTab *publish_tab_tail;
+
+
+static struct DownloadEntry *
+change_download_colour (struct DownloadEntry *de,
+ const char *colour)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return de;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->ts, &iter,
+ 8, colour,
+ -1);
+ return de;
+}
+
+
+static struct PublishEntry *
+change_publish_colour (struct PublishEntry *pe,
+ const char *colour)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ if (pe == NULL)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return pe;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (pe->tab->ts, &iter,
+ 2, colour,
+ -1);
+ return pe;
+}
+
+
+static void
+stop_download (struct DownloadEntry *de,
+ int is_suspend)
+{
+ change_download_colour (de, "white");
+ gtk_tree_row_reference_free (de->rr);
+ if (is_suspend == GNUNET_NO)
+ GNUNET_FS_download_stop (de->dc, GNUNET_YES);
+ GNUNET_FS_uri_destroy (de->uri);
+ GNUNET_CONTAINER_meta_data_destroy (de->meta);
+ GNUNET_free (de);
+}
+
+
+
+struct AddDirectoryEntryContext
+{
+
+ struct DownloadEntry *de;
+
+ /**
+ * Row reference of parent (the directory).
+ */
+ GtkTreeRowReference *prr;
+
+ int check_duplicates;
+
+};
+
+
+/**
+ * Function used to process entries in a directory.
+ *
+ * @param cls closure, our 'struct AddDirectoryEntryContext*'
+ * @param filename name of the file in the directory
+ * @param uri URI of the file
+ * @param metadata metadata for the file; metadata for
+ * the directory if everything else is NULL/zero
+ * @param length length of the available data for the file
+ * (of type size_t since data must certainly fit
+ * into memory; if files are larger than size_t
+ * permits, then they will certainly not be
+ * embedded with the directory itself).
+ * @param data data available for the file (length bytes)
+ */
+static void
+add_directory_entry (void *cls,
+ const char *filename,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ size_t length,
+ const void *data)
+{
+ struct AddDirectoryEntryContext *ade = cls;
+ GtkTreeIter iter;
+ GtkTreeIter piter;
+ GtkTreePath *path;
+ GtkTreeModel *tm;
+ struct GNUNET_FS_Uri *xuri;
+
+ if (uri == NULL)
+ {
+ /* directory meta data itself */
+ /* FIXME: consider merging it in... */
+ return;
+ }
+ if (ade->check_duplicates == GNUNET_YES)
+ {
+ path = gtk_tree_row_reference_get_path (ade->prr);
+ tm = gtk_tree_row_reference_get_model (ade->prr);
+ if (TRUE != gtk_tree_model_get_iter (tm,
+ &piter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ if (TRUE == gtk_tree_model_iter_children (tm,
+ &iter,
+ &piter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm,
+ &iter,
+ 1, &xuri,
+ -1);
+ if (GNUNET_YES ==
+ GNUNET_FS_uri_test_equal (xuri, uri))
+ return; /* already present */
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ }
+ GNUNET_GTK_add_search_result (ade->de->tab,
+ &iter,
+ ade->prr,
+ uri,
+ meta,
+ NULL,
+ 0);
+}
+
+
+static struct DownloadEntry *
+mark_download_progress (struct DownloadEntry *de,
+ uint64_t size,
+ uint64_t completed,
+ const void *block_data,
+ uint64_t offset,
+ uint64_t block_size,
+ unsigned int depth)
+{
+ struct AddDirectoryEntryContext ade;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return de;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->ts, &iter,
+ 4, (guint) ((size > 0) ? (100 * completed / size) : 100)
/* progress */,
+ -1);
+ if ( (depth == 0) &&
+ (block_size > 0) &&
+ (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) )
+ {
+ ade.de = de;
+ ade.prr = de->rr;
+ ade.check_duplicates = GNUNET_NO;
+ if (GNUNET_SYSERR ==
+ GNUNET_FS_directory_list_contents ((size_t) block_size,
+ block_data,
+ offset,
+ &add_directory_entry,
+ &ade))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Metadata wrongly claims that this is a GNUnet
directory!\n"));
+ }
+ }
+ return de;
+}
+
+
+static struct DownloadEntry *
+mark_download_error (struct DownloadEntry *de,
+ const char *emsg)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ de = change_download_colour (de,
+ "red");
+ de->is_done = GNUNET_YES;
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->tab->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return de;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->tab->ts, &iter,
+ 4, 0,
+ 7, emsg,
+ -1);
+ return de;
+}
+
+
+static struct DownloadEntry *
+mark_download_completed (struct DownloadEntry *de,
+ uint64_t size,
+ const char *filename)
+{
+ struct AddDirectoryEntryContext ade;
+
+ de->is_done = GNUNET_YES;
+ (void) mark_download_progress (de, size, size, NULL, 0, 0, 0);
+ if ( (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) &&
+ (filename != NULL) )
+ {
+ ade.de = de;
+ ade.prr = de->rr;
+ ade.check_duplicates = GNUNET_NO;
+ GNUNET_FS_GTK_mmap_and_scan (filename,
+ &add_directory_entry,
+ &ade);
+ }
+ (void) change_download_colour (de, "green");
+ return de;
+}
+
+
+static struct PublishEntry *
+mark_publish_progress (struct PublishEntry *pe,
+ uint64_t size,
+ uint64_t completed)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return pe;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (pe->tab->ts, &iter,
+ 3, (guint) ((size > 0) ? (100 * completed / size) : 100)
/* progress */,
+ -1);
+ return pe;
+}
+
+
+/**
+ * Move (aka copy) all of the children of 'src_iter' from the 'src_model'
+ * to become children of 'dst_iter' in the 'dst_model'.
+ *
+ * The models are both 'GNUNET_GTK_file_sharing_result_tree_store' models.
+ *
+ * Note that we also need to update the 'struct SearchResult'
+ * and (if it exists) the respective 'struct DownloadEntry'
+ * to refer to the new model.
+ */
+static void
+move_children (GtkTreeModel *src_model,
+ GtkTreeIter *src_iter,
+ GtkTreeModel *dst_model,
+ GtkTreeIter *dst_iter)
+{
+ GtkTreeIter src_child;
+ GtkTreeIter dst_child;
+ GtkTreePath *path;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ struct GNUNET_FS_Uri *uri;
+ guint64 filesize;
+ GdkPixbuf *preview;
+ guint percent_progress;
+ guint percent_availability;
+ gchar *filename;
+ gchar *uri_as_string;
+ gchar *status_colour;
+ struct SearchResult *search_result;
+ gchar *mimetype;
+ guint applicability_rank;
+ guint availability_certainty;
+ gint availability_rank;
+
+ if (TRUE == gtk_tree_model_iter_children (src_model,
+ &src_child,
+ src_iter))
+ {
+ do
+ {
+ gtk_tree_model_get (src_model,
+ &src_child,
+ 0, &meta,
+ 1, &uri,
+ 2, &filesize,
+ 3, &preview,
+ 4, &percent_progress,
+ 5, &percent_availability,
+ 6, &filename,
+ 7, &uri_as_string,
+ 8, &status_colour,
+ 9, &search_result,
+ 10, &mimetype,
+ 11, &applicability_rank,
+ 12, &availability_certainty,
+ 13, &availability_rank,
+ -1);
+ gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model),
+ &dst_child,
+ dst_iter,
+ G_MAXINT,
+ 0, meta,
+ 1, uri,
+ 2, filesize,
+ 3, preview,
+ 4, percent_progress,
+ 5, percent_availability,
+ 6, filename,
+ 7, uri_as_string,
+ 8, status_colour,
+ 9, search_result,
+ 10, mimetype,
+ 11, applicability_rank,
+ 12, availability_certainty,
+ 13, availability_rank,
+ -1);
+ g_free (filename);
+ g_free (uri_as_string);
+ g_free (status_colour);
+ g_free (mimetype);
+ if (preview != NULL)
+ g_object_unref (preview);
+ gtk_tree_row_reference_free (search_result->rr);
+ path = gtk_tree_model_get_path (dst_model,
+ &dst_child);
+ search_result->rr = gtk_tree_row_reference_new (dst_model,
+ path);
+ gtk_tree_path_free (path);
+ if (search_result->download != NULL)
+ {
+ search_result->download->ts = GTK_TREE_STORE (dst_model);
+ gtk_tree_row_reference_free (search_result->download->rr);
+ search_result->download->rr = gtk_tree_row_reference_copy
(search_result->rr);
+ }
+ move_children (src_model,
+ &src_child,
+ dst_model,
+ &dst_child);
+ }
+ while (TRUE == gtk_tree_model_iter_next (src_model,
+ &src_child));
+ }
+}
+
+
+/**
+ * Delete the entire given subtree from the model.
+ * Does not free anything inside of the respective
+ * model's fields (since they have been moved).
+ */
+static void
+delete_stale_subtree (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GtkTreeIter child;
+
+ while (TRUE == gtk_tree_model_iter_children (model,
+ &child,
+ iter))
+ delete_stale_subtree (model, &child);
+ gtk_tree_store_remove (GTK_TREE_STORE (model),
+ iter);
+}
+
+
+/**
+ * Handle the case where an active download lost its
+ * search parent by moving it to the URI tab.
+ */
+static struct DownloadEntry *
+download_lost_parent (struct DownloadEntry *de,
+ uint64_t size,
+ uint64_t completed,
+ int is_active)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ struct SearchTab *tab;
+ GtkTreeRowReference *rr_old;
+ GtkTreeModel *tm_old;
+ GtkTreeIter iter_old;
+
+ rr_old = de->rr;
+ de->sr = NULL;
+ tab = GNUNET_GTK_add_to_uri_tab (&iter,
+ NULL,
+ de->meta,
+ de->uri);
+ de->ts = tab->ts;
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
+ &iter);
+ de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
+ path);
+ gtk_tree_path_free (path);
+ mark_download_progress (de, size, completed,
+ NULL, 0, 0, 0);
+ tm_old = gtk_tree_row_reference_get_model (rr_old);
+ path = gtk_tree_row_reference_get_path (rr_old);
+ gtk_tree_row_reference_free (rr_old);
+ gtk_tree_model_get_iter (tm_old,
+ &iter_old,
+ path);
+ gtk_tree_path_free (path);
+ move_children (tm_old,
+ &iter_old,
+ GTK_TREE_MODEL (de->ts),
+ &iter);
+ delete_stale_subtree (tm_old,
+ &iter_old);
+ if (size > completed)
+ {
+ if (is_active)
+ change_download_colour (de, "yellow");
+ else
+ change_download_colour (de, "blue");
+ }
+ else
+ {
+ change_download_colour (de, "green");
+ }
+ return de;
+}
+
+
+/**
+ * Setup a new download entry.
+ *
+ * @param de existing download entry for the download, or NULL
+ * @param pde parent download entry, or NULL
+ * @param sr search result, or NULL
+ * @param dc download context (for stopping)
+ * @param uri the URI
+ * @param meta metadata
+ * @param size total size
+ * @param completed current progress
+ */
+static struct DownloadEntry *
+setup_download (struct DownloadEntry *de,
+ struct DownloadEntry *pde,
+ struct SearchResult *sr,
+ struct GNUNET_FS_DownloadContext *dc,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ uint64_t size,
+ uint64_t completed)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ if (de == NULL)
+ {
+ de = GNUNET_malloc (sizeof (struct DownloadEntry));
+ GNUNET_assert (sr->download == NULL);
+ sr->download = de;
+ de->sr = sr;
+ de->dc = dc;
+ de->uri = GNUNET_FS_uri_dup (uri);
+ }
+ de->pde = pde;
+ if ( (meta != NULL) &&
+ (de->meta == NULL) )
+ de->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ if (sr != NULL)
+ {
+ de->rr = gtk_tree_row_reference_copy (sr->rr);
+ de->ts = sr->tab->ts;
+ de->tab = sr->tab;
+ }
+ else if (de->rr == NULL)
+ {
+ de->tab = GNUNET_GTK_add_to_uri_tab (&iter,
+ NULL,
+ meta,
+ uri);
+ de->ts = de->tab->ts;
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
+ &iter);
+ de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
+ path);
+ gtk_tree_path_free (path);
+ }
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
+ &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return de;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->ts, &iter,
+ 4, (guint) ((size > 0) ? (100 * completed / size) : 100)
/* progress */,
+ 8, "blue" /* status colour: pending */,
+ -1);
+ return de;
+}
+
+
+/**
+ * Tell FS to start a download. Begins by opening the
+ * "save as" window.
+ */
+static void
+start_download (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ struct SearchResult *sr;
+ gchar *mime;
+ struct DownloadContext *dlc;
+
+ GNUNET_assert (tab != NULL);
+ tm = gtk_tree_view_get_model (tree_view);
+ if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm, &iter,
+ 0, &meta,
+ 1, &uri,
+ 9, &sr,
+ 10, &mime,
+ -1);
+ dlc = GNUNET_malloc (sizeof (struct DownloadContext));
+ dlc->uri = GNUNET_FS_uri_dup (uri);
+ dlc->mime = (NULL != mime) ? GNUNET_strdup (mime) : NULL;
+ dlc->filename = GNUNET_FS_meta_data_suggest_filename (meta);
+ dlc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ dlc->rr = gtk_tree_row_reference_new (tm, path);
+ dlc->sr = sr->result;
+ dlc->anonymity = -1;
+ GNUNET_GTK_open_download_as_dialog (dlc);
+ g_free (mime);
+}
+
+
+
+/**
+ * Row reference for the current search context menu.
+ */
+static GtkTreeRowReference *current_context_row_reference;
+
+/**
+ * Search tab used for the current search context menu.
+ */
+static struct SearchTab *current_context_search_tab;
+
+/**
+ * Download was selected in the current search context menu.
+ */
+static void
+start_download_ctx_menu (gpointer user_data,
+ guint unused,
+ GtkWidget *widget)
+{
+ GtkTreePath *path;
+ GtkTreeView *tv;
+
+ if (current_context_row_reference == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ path = gtk_tree_row_reference_get_path (current_context_row_reference);
+ gtk_tree_row_reference_free (current_context_row_reference);
+ current_context_row_reference = NULL;
+ tv = GTK_TREE_VIEW (gtk_builder_get_object
(current_context_search_tab->builder,
+ "_search_result_frame"));
+ start_download (tv, path, NULL, current_context_search_tab);
+ gtk_tree_path_free (path);
+ current_context_search_tab = NULL;
+}
+
+
+/**
+ * Download was selected in the current search context menu.
+ */
+static void
+abort_download_ctx_menu (gpointer user_data,
+ guint unused,
+ GtkWidget *widget)
+{
+ struct DownloadEntry *de = user_data;
+
+ GNUNET_assert (de->dc != NULL);
+ GNUNET_FS_download_stop (de->dc,
+ GNUNET_YES);
+ current_context_search_tab = NULL;
+}
+
+
+/**
+ * Copy current URI to clipboard.
+ */
+static void
+copy_uri_to_clipboard_ctx_menu (gpointer user_data,
+ guint unused,
+ GtkWidget *widget)
+{
+ GtkTreePath *path;
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ char *uris;
+ GtkClipboard *cb;
+
+ if (current_context_row_reference == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ path = gtk_tree_row_reference_get_path (current_context_row_reference);
+ gtk_tree_row_reference_free (current_context_row_reference);
+ current_context_row_reference = NULL;
+ tv = GTK_TREE_VIEW (gtk_builder_get_object
(current_context_search_tab->builder,
+ "_search_result_frame"));
+ tm = gtk_tree_view_get_model (tv);
+ if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_model_get (tm, &iter,
+ 1, &uri, -1);
+ gtk_tree_path_free (path);
+ current_context_search_tab = NULL;
+ if (uri == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ uris = GNUNET_FS_uri_to_string (uri);
+ cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (cb,
+ uris,
+ -1);
+ gtk_clipboard_store (cb);
+ GNUNET_free (uris);
+}
+
+
+/**
+ * We got a right-click on the search result list. Display the context
+ * menu.
+ */
+static int
+search_list_on_menu(GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ GdkEventButton *event_button;
+ struct SearchTab *tab = user_data;
+ GtkTreeView *tv;
+ GtkMenu *menu;
+ GtkWidget *child;
+ GtkTreePath *path;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct SearchResult *sr;
+
+ tv = GTK_TREE_VIEW (widget);
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ event_button = (GdkEventButton *) event;
+ if (event_button->button == 3)
+ {
+ current_context_search_tab = tab;
+ if (current_context_row_reference != NULL)
+ {
+ gtk_tree_row_reference_free (current_context_row_reference);
+ current_context_row_reference = NULL;
+ }
+ path = NULL;
+ if (FALSE == gtk_tree_view_get_path_at_pos (tv,
+ event_button->x,
+ event_button->y,
+ &path, NULL, NULL, NULL))
+ {
+ /* nothing selected */
+ current_context_search_tab = NULL;
+ return FALSE;
+ }
+ tm = gtk_tree_view_get_model (tv);
+ gtk_tree_model_get_iter (tm, &iter, path);
+ gtk_tree_model_get (tm, &iter,
+ 9, &sr,
+ -1);
+ current_context_row_reference = gtk_tree_row_reference_new (tm,
+ path);
+ gtk_tree_path_free (path);
+
+ /*
+ FIXME: have additional options, depending on status:
+ - view full meta data (in new window)
+ - copy URI to clipboard
+ - start recursive download
+ - abort active download (!)
+ => need to know download status before creating menu!
+ */
+ menu = GTK_MENU (gtk_menu_new ());
+ if (sr->download == NULL)
+ {
+ child = gtk_menu_item_new_with_label (_("_Download"));
+ g_signal_connect (child,
+ "activate",
+ G_CALLBACK (start_download_ctx_menu),
+ NULL);
+ gtk_label_set_use_underline (GTK_LABEL
+ (gtk_bin_get_child (GTK_BIN
(child))),
+ TRUE);
+ gtk_widget_show (child);
+ }
+ else
+ {
+ child = gtk_menu_item_new_with_label (_("_Abort download"));
+ g_signal_connect (child,
+ "activate",
+ G_CALLBACK (abort_download_ctx_menu),
+ sr->download);
+ gtk_label_set_use_underline (GTK_LABEL
+ (gtk_bin_get_child (GTK_BIN
(child))),
+ TRUE);
+ gtk_widget_show (child);
+
+ }
+
+ child = gtk_menu_item_new_with_label (_("_Copy URI to Clipboard"));
+ g_signal_connect (child,
+ "activate",
+ G_CALLBACK (copy_uri_to_clipboard_ctx_menu),
+ NULL);
+ gtk_label_set_use_underline (GTK_LABEL
+ (gtk_bin_get_child (GTK_BIN (child))),
+ TRUE);
+ gtk_widget_show (child);
+
+
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
+ event_button->button,
+ event_button->time);
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ * Selected row has changed, update preview and metadata
+ * areas.
+ */
+static void
+update_meta_data_views (GtkTreeView *tv,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ GtkImage *image;
+ GtkListStore *ms;
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ GdkPixbuf *pixbuf;
+
+ GNUNET_assert (tab->query_txt != NULL);
+ image = GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_preview_image"));
+ ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_meta_data_list_store"));
+
+ sel = gtk_tree_view_get_selection (tv);
+ gtk_list_store_clear (ms);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &model,
+ &iter))
+ {
+ gtk_image_clear (image);
+ return;
+ }
+ meta = NULL;
+ pixbuf = NULL;
+ gtk_tree_model_get (model,
+ &iter,
+ 0, &meta,
+ 3, &pixbuf,
+ -1);
+ if (pixbuf != NULL)
+ {
+ gtk_image_set_from_pixbuf (image, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ if (meta != NULL)
+ {
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+
&GNUNET_FS_GTK_add_meta_data_to_list_store,
+ ms);
+ }
+}
+
+
+/**
+ * Update the label for a search
+ */
+static void
+update_search_label (struct SearchTab *tab)
+{
+ char *name;
+
+ while (tab->parent != NULL)
+ tab = tab->parent->tab;
+ if (tab->num_results > 0)
+ GNUNET_asprintf (&name,
+ "%.*s%s (%u)",
+ 20,
+ tab->query_txt,
+ strlen (tab->query_txt) > 20 ? "..." : "",
+ tab->num_results);
+ else
+ GNUNET_asprintf (&name,
+ "%.*s%s",
+ 20,
+ tab->query_txt,
+ strlen (tab->query_txt) > 20 ? "..." : "");
+ gtk_label_set_text (tab->label, name);
+ GNUNET_free (name);
+}
+
+
+/**
+ * Close a search tab and free associated state.
+ */
+static void
+close_search_tab (struct SearchTab *tab)
+{
+ GtkNotebook *notebook;
+ int index;
+ int i;
+
+ if (tab->parent != NULL)
+ {
+ /* not a top-level search, do not close tab here! */
+ GNUNET_free (tab);
+ return;
+ }
+
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ index = -1;
+ for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
+ if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
+ index = i;
+ gtk_notebook_remove_page (notebook, index);
+ g_object_unref (tab->builder);
+ GNUNET_free (tab->query_txt);
+ GNUNET_CONTAINER_DLL_remove (search_tab_head,
+ search_tab_tail,
+ tab);
+ GNUNET_free (tab);
+}
+
+
+/**
+ * Close a publish tab and free associated state.
+ */
+static struct PublishEntry *
+handle_publish_completed (struct PublishEntry *ent,
+ const struct GNUNET_FS_Uri *uri)
+{
+ ent->uri = GNUNET_FS_uri_dup (uri);
+ return change_publish_colour (ent,
+ "green");
+}
+
+
+
+/**
+ * Handle error.
+ */
+static struct PublishEntry *
+handle_publish_error (struct PublishEntry *ent,
+ const char *emsg)
+{
+ GNUNET_break (0);
+ return change_publish_colour (ent,
+ "red");
+}
+
+
+/**
+ * Close a publish tab and free associated state.
+ */
+static void
+close_publish_tab (struct PublishEntry *ent)
+{
+ struct PublishTab *tab;
+ GtkNotebook *notebook;
+ int index;
+ int i;
+
+ if (ent == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_row_reference_free (ent->rr);
+ if (GNUNET_YES != ent->is_top)
+ {
+ GNUNET_free (ent);
+ return;
+ }
+ tab = ent->tab;
+ if (ent->uri != NULL)
+ GNUNET_FS_uri_destroy (ent->uri);
+ GNUNET_free (ent);
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ index = -1;
+ for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
+ if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
+ index = i;
+ gtk_notebook_remove_page (notebook, index);
+ g_object_unref (tab->builder);
+ GNUNET_CONTAINER_DLL_remove (publish_tab_head,
+ publish_tab_tail,
+ tab);
+ GNUNET_free (tab);
+}
+
+
+/**
+ * Tell FS to stop a search.
+ */
+static void
+stop_search (GtkButton *button,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ if (tab->sc != NULL)
+ {
+ GNUNET_FS_search_stop (tab->sc);
+ tab->sc = NULL;
+ }
+}
+
+
+/**
+ * Stop completed downloads (or those that failed). Should
+ * iterate over the underlying tree store and stop all
+ * completed entries. Furthermore, if the resulting tree
+ * store is empty and has no search associated with it,
+ * the tab should be closed.
+ */
+static void
+clear_downloads (GtkButton *button,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ struct SearchResult *sr;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+
+ tm = GTK_TREE_MODEL (tab->ts);
+ if (TRUE != gtk_tree_model_get_iter_first (tm, &iter))
+ return;
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 9, &sr,
+ -1);
+ if ( (sr->download != NULL) &&
+ (sr->download->is_done == GNUNET_YES) )
+ GNUNET_FS_download_stop (sr->download->dc,
+ GNUNET_YES);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+}
+
+
+
+/**
+ * Tell FS to pause a search.
+ */
+static void
+pause_search (GtkButton *button,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ if (tab->sc != NULL)
+ {
+ GNUNET_FS_search_pause (tab->sc);
+ gtk_widget_show (tab->play_button);
+ gtk_widget_hide (tab->pause_button);
+ }
+}
+
+
+/**
+ * Tell FS to resume a search.
+ */
+static void
+continue_search (GtkButton *button,
+ gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ if (tab->sc != NULL)
+ {
+ GNUNET_FS_search_continue (tab->sc);
+ gtk_widget_show (tab->pause_button);
+ gtk_widget_hide (tab->play_button);
+ }
+}
+
+
+/**
+ * Setup a new search tab.
+ *
+ * @param sc context with FS for the search
+ * @param query the query
+ * @param anonymity anonymity level
+ */
+static struct SearchTab *
+setup_search (struct GNUNET_FS_SearchContext *sc,
+ const struct GNUNET_FS_Uri *query)
+{
+ struct SearchTab *tab;
+ GtkTreeView *tv;
+ GtkNotebook *notebook;
+ GtkWindow *sf;
+ gint pages;
+
+ tab = GNUNET_malloc (sizeof (struct SearchTab));
+ GNUNET_CONTAINER_DLL_insert (search_tab_head,
+ search_tab_tail,
+ tab);
+ tab->sc = sc;
+ if (query == NULL)
+ {
+ tab->query_txt = GNUNET_strdup ("*");
+ }
+ else
+ {
+ if (GNUNET_FS_uri_test_ksk (query))
+ tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query);
+ else
+ tab->query_txt = GNUNET_FS_uri_to_string (query);
+ }
+ tab->builder = GNUNET_GTK_get_new_builder ("search_tab.glade");
+ tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
+
"GNUNET_GTK_file_sharing_result_tree_store"));
+ /* load frame */
+ sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
+ "_search_result_frame_window"));
+ tab->frame = gtk_bin_get_child (GTK_BIN (sf));
+ gtk_widget_ref (tab->frame);
+ gtk_container_remove (GTK_CONTAINER (sf), tab->frame);
+ gtk_widget_destroy (GTK_WIDGET (sf));
+
+ /* load tab_label */
+ sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
+ "_search_result_label_window"));
+ tab->tab_label = gtk_bin_get_child (GTK_BIN (sf));
+ gtk_widget_ref (tab->tab_label);
+ gtk_container_remove (GTK_CONTAINER (sf), tab->tab_label);
+ gtk_widget_destroy (GTK_WIDGET (sf));
+
+ /* get refs to widgets */
+ tab->label = GTK_LABEL (gtk_builder_get_object (tab->builder,
+
"_search_result_label_window_label"));
+
+ tab->close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
+
"_search_result_label_close_button"));
+ g_signal_connect(G_OBJECT(tab->close_button), "clicked",
+ G_CALLBACK(stop_search), tab);
+ tab->clear_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
+
"_search_result_label_clear_button"));
+ g_signal_connect(G_OBJECT(tab->clear_button), "clicked",
+ G_CALLBACK(clear_downloads), tab);
+ tab->play_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
+
"_search_result_label_play_button"));
+ g_signal_connect(G_OBJECT(tab->play_button), "clicked",
+ G_CALLBACK(continue_search), tab);
+ tab->pause_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
+
"_search_result_label_pause_button"));
+ g_signal_connect(G_OBJECT(tab->pause_button), "clicked",
+ G_CALLBACK(pause_search), tab);
+ /* patch text */
+ update_search_label (tab);
+
+ /* add signal handlers */
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
+ "_search_result_frame"));
+ g_signal_connect(G_OBJECT(tv), "row-activated",
+ G_CALLBACK(start_download), tab);
+ g_signal_connect(G_OBJECT(tv), "cursor-changed",
+ G_CALLBACK(update_meta_data_views), tab);
+ g_signal_connect (G_OBJECT(tv),
+ "button_press_event",
+ G_CALLBACK(search_list_on_menu),
+ tab);
+
+
+ /* make visible */
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ pages = gtk_notebook_get_n_pages (notebook);
+ gtk_notebook_insert_page (notebook,
+ tab->frame,
+ tab->tab_label,
+ pages - 1);
+ gtk_notebook_set_current_page (notebook,
+ pages - 1);
+ gtk_widget_show (GTK_WIDGET (notebook));
+ return tab;
+}
+
+
+/**
+ * Setup an inner search.
+ *
+ * @param sc context with FS for the search
+ * @param parent parent search tab
+ * @param anonymity anonymity level
+ */
+static struct SearchTab *
+setup_inner_search (struct GNUNET_FS_SearchContext *sc,
+ struct SearchResult *parent)
+{
+ struct SearchTab *ret;
+
+ ret = GNUNET_malloc (sizeof (struct SearchTab));
+ ret->parent = parent;
+ ret->sc = sc;
+ ret->query_txt = parent->tab->query_txt;
+ ret->builder = parent->tab->builder;
+ ret->frame = parent->tab->frame;
+ ret->tab_label = parent->tab->tab_label;
+ ret->close_button = parent->tab->close_button;
+ ret->clear_button = parent->tab->clear_button;
+ ret->play_button = parent->tab->play_button;
+ ret->label = parent->tab->label;
+
+ return ret;
+}
+
+
+
+/**
+ * Add a search result to the given search tab.
+ *
+ * @param tab search tab to extend
+ * @param iter set to position where search result is added
+ * @param parent_rr reference to parent entry in search tab
+ * @param uri uri to add
+ * @param meta metadata of the entry
+ * @param result associated FS search result (can be NULL)
+ * @param applicability_rank how relevant is the result
+ * @return entry for the search result
+ */
+struct SearchResult *
+GNUNET_GTK_add_search_result (struct SearchTab *tab,
+ GtkTreeIter *iter,
+ GtkTreeRowReference *parent_rr,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_SearchResult *result,
+ uint32_t applicability_rank)
+{
+ struct SearchResult *sr;
+ GtkTreePath *tp;
+ const char *status_colour;
+ char *desc;
+ char *mime;
+ char *uris;
+ GdkPixbuf *pixbuf;
+ GtkTreeIter *pitr;
+ GtkTreeIter pmem;
+ GtkTreePath *path;
+ GtkTreeModel *tm;
+ GtkTreeStore *ts;
+ uint64_t fsize;
+
+ if ( (uri != NULL) &&
+ (!GNUNET_FS_uri_test_loc (uri)) &&
+ (!GNUNET_FS_uri_test_chk (uri)) )
+ {
+ fsize = 0;
+ mime = GNUNET_strdup ("GNUnet namespace");
+ status_colour = "lightgreen";
+ }
+ else if (uri != NULL)
+ {
+ fsize = GNUNET_FS_uri_chk_get_file_size (uri);
+ mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_MIMETYPE,
+
EXTRACTOR_METATYPE_FORMAT,
+ -1);
+ status_colour = "white";
+ }
+ else
+ {
+ fsize = 0;
+ status_colour = "gray";
+ mime = NULL;
+ }
+ desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_PACKAGE_NAME,
+
EXTRACTOR_METATYPE_TITLE,
+
EXTRACTOR_METATYPE_BOOK_TITLE,
+
EXTRACTOR_METATYPE_FILENAME,
+
EXTRACTOR_METATYPE_DESCRIPTION,
+
EXTRACTOR_METATYPE_SUMMARY,
+
EXTRACTOR_METATYPE_ALBUM,
+
EXTRACTOR_METATYPE_COMMENT,
+
EXTRACTOR_METATYPE_SUBJECT,
+
EXTRACTOR_METATYPE_KEYWORDS,
+ -1);
+ if (desc == NULL)
+ desc = GNUNET_strdup (_("no description supplied"));
+ if (uri == NULL)
+ uris = GNUNET_strdup (_("no URI"));
+ else
+ uris = GNUNET_FS_uri_to_string (uri);
+
+ pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
+ sr = GNUNET_malloc (sizeof (struct SearchResult));
+ sr->result = result;
+ sr->tab = tab;
+ if (parent_rr != NULL)
+ {
+ /* get piter from parent */
+ path = gtk_tree_row_reference_get_path (parent_rr);
+ tm = gtk_tree_row_reference_get_model (parent_rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tm),
+ &pmem, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ /* desperate measure: make top-level entry */
+ pitr = NULL;
+ }
+ else
+ {
+ pitr = &pmem;
+ }
+ ts = GTK_TREE_STORE (tm);
+ }
+ else
+ {
+ /* top-level result */
+ pitr = NULL;
+ ts = tab->ts;
+ }
+ gtk_tree_store_insert_with_values (ts,
+ iter,
+ pitr,
+ G_MAXINT,
+ 0, GNUNET_CONTAINER_meta_data_duplicate
(meta),
+ 1, (uri == NULL) ? NULL :
GNUNET_FS_uri_dup (uri),
+ 2, (uri == NULL) ? 0 : fsize,
+ 3, pixbuf /* preview */,
+ 4, 0 /* percent progress */,
+ 5, 0 /* percent availability */,
+ 6, desc /* filename/description */,
+ 7, uris,
+ 8, status_colour,
+ 9, sr,
+ 10, mime,
+ 11, applicability_rank,
+ 12, 0 /* avail-cert */,
+ 13, 0 /* avail-rank */,
+ -1);
+ if (tab != NULL)
+ {
+ while (tab->parent != NULL)
+ tab = tab->parent->tab;
+ tab->num_results++;
+ }
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+ GNUNET_free (uris);
+ GNUNET_free (desc);
+ GNUNET_free_non_null (mime);
+ tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
+ iter);
+ sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
+ tp);
+ gtk_tree_path_free (tp);
+ return sr;
+}
+
+
+static struct SearchResult *
+process_search_result (void *cls,
+ struct SearchResult *parent,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_SearchResult *result,
+ uint32_t applicability_rank)
+{
+ struct SearchTab *tab = cls;
+ struct SearchResult *sr;
+ GtkTreeIter iter;
+
+ sr = GNUNET_GTK_add_search_result (tab, &iter,
+ (parent != NULL) ? parent->rr : NULL,
+ uri,
+ meta, result, applicability_rank);
+ update_search_label (tab);
+ return sr;
+}
+
+
+/**
+ * Setup a new top-level entry in the URI tab. If necessary, create
+ * the URI tab first.
+ *
+ * @param iter set to the new entry
+ * @param srp set to search result
+ * @param meta metadata for the new entry
+ * @param uri URI for the new entry
+ * @return NULL on error, otherwise tree store matching iter
+ */
+struct SearchTab *
+GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
+ struct SearchResult **srp,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ const struct GNUNET_FS_Uri *uri)
+{
+ struct SearchTab *utab;
+ struct SearchResult *sr;
+ GtkNotebook *notebook;
+ gint page;
+
+ utab = search_tab_head;
+ while (utab != NULL)
+ {
+ if (utab->sc == NULL)
+ break;
+ utab = utab->next;
+ }
+ if (utab == NULL)
+ {
+ utab = setup_search (NULL, NULL);
+ gtk_widget_set_visible (utab->close_button,
+ FALSE);
+ gtk_widget_set_visible (utab->pause_button,
+ FALSE);
+ }
+ else
+ {
+ /* make 'utab' the current page */
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ for (page=0;page<gtk_notebook_get_n_pages (notebook);page++)
+ if (utab->frame ==
+ gtk_notebook_get_nth_page (notebook,
+ page))
+ {
+ gtk_notebook_set_current_page (notebook,
+ page);
+ break;
+ }
+ }
+ sr = GNUNET_GTK_add_search_result (utab, iter,
+ NULL, uri, meta,
+ NULL, 0);
+
+ if (NULL != srp)
+ *srp = sr;
+ return utab;
+}
+
+
+static struct SearchTab *
+handle_search_error (struct SearchTab *sr,
+ const char *emsg)
+{
+ /* FIXME: implement error handler */
+ GNUNET_break (0);
+ return sr;
+}
+
+
+static struct SearchResult *
+update_search_result (struct SearchResult *sr,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ int32_t availability_rank,
+ uint32_t availability_certainty,
+ uint32_t applicability_rank)
+{
+ GtkTreeIter iter;
+ struct GNUNET_CONTAINER_MetaData *ometa;
+ GtkTreeView *tv;
+ GtkTreePath *tp;
+ GtkTreeStore *ts;
+ GtkTreeModel *tm;
+ char *desc;
+ char *mime;
+ GdkPixbuf *pixbuf;
+ guint percent_avail;
+ GtkNotebook *notebook;
+ gint page;
+
+ if (sr == NULL)
+ return NULL;
+ desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_PACKAGE_NAME,
+
EXTRACTOR_METATYPE_TITLE,
+
EXTRACTOR_METATYPE_BOOK_TITLE,
+
EXTRACTOR_METATYPE_FILENAME,
+
EXTRACTOR_METATYPE_DESCRIPTION,
+
EXTRACTOR_METATYPE_SUMMARY,
+
EXTRACTOR_METATYPE_ALBUM,
+
EXTRACTOR_METATYPE_COMMENT,
+
EXTRACTOR_METATYPE_SUBJECT,
+
EXTRACTOR_METATYPE_KEYWORDS,
+ -1);
+ if (desc == NULL)
+ desc = GNUNET_strdup (_("no description supplied"));
+ mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_MIMETYPE,
+
EXTRACTOR_METATYPE_FORMAT,
+ -1);
+ pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
+ tp = gtk_tree_row_reference_get_path (sr->rr);
+ tm = gtk_tree_row_reference_get_model (sr->rr);
+ ts = GTK_TREE_STORE (tm);
+ gtk_tree_model_get_iter (tm, &iter, tp);
+ gtk_tree_path_free (tp);
+ gtk_tree_model_get (tm,
+ &iter,
+ 0, &ometa,
+ -1);
+ if (meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (ometa);
+ if (availability_certainty > 0)
+ percent_avail = (availability_certainty + availability_rank) * 50 /
availability_certainty;
+ else
+ percent_avail = 0;
+ gtk_tree_store_set (ts,
+ &iter,
+ 0, GNUNET_CONTAINER_meta_data_duplicate (meta),
+ 3, pixbuf /* preview */,
+ 5, (guint) percent_avail /* percent availability */,
+ 6, desc /* filename/description */,
+ 10, mime,
+ 11, (guint) applicability_rank,
+ 12, (guint) availability_certainty,
+ 13, (gint) availability_rank,
+ -1);
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+ GNUNET_free (desc);
+ GNUNET_free_non_null (mime);
+
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ page = gtk_notebook_get_current_page (notebook);
+ if (gtk_notebook_get_nth_page (notebook,
+ page) == sr->tab->frame)
+ {
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (sr->tab->builder,
+ "_search_result_frame"));
+
+ update_meta_data_views (tv,
+ sr->tab);
+ }
+ return sr;
+}
+
+
+static void
+free_search_result (struct SearchResult *sr)
+{
+ GtkTreePath *tp;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *meta;
+
+ if (sr == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ tp = gtk_tree_row_reference_get_path (sr->rr);
+ tm = gtk_tree_row_reference_get_model (sr->rr);
+ gtk_tree_model_get_iter (tm, &iter, tp);
+ gtk_tree_path_free (tp);
+ gtk_tree_model_get (tm,
+ &iter,
+ 0, &meta,
+ 1, &uri,
+ -1);
+ if (uri != NULL)
+ GNUNET_FS_uri_destroy (uri);
+ if (meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ gtk_tree_row_reference_free (sr->rr);
+ gtk_tree_store_remove (GTK_TREE_STORE (tm),
+ &iter);
+ GNUNET_free (sr);
+}
+
+
+/**
+ * Tell FS to stop publishing.
+ */
+static void
+stop_publishing (GtkButton *button,
+ gpointer user_data)
+{
+ struct PublishTab *tab = user_data;
+ struct GNUNET_FS_PublishContext *pc;
+
+ if (NULL != (pc = tab->pc))
+ {
+ tab->pc = NULL;
+ GNUNET_FS_publish_stop (pc);
+ }
+}
+
+
+static struct PublishEntry *
+setup_publish (struct GNUNET_FS_PublishContext *pc,
+ const char *fn,
+ uint64_t fsize,
+ struct PublishEntry *parent)
+{
+ struct PublishTab *tab;
+ struct PublishEntry *ent;
+ GtkTreeIter *pitrptr;
+ GtkTreeIter iter;
+ GtkTreeIter piter;
+ GtkTreePath *path;
+ GtkWindow *df;
+ GtkWidget *tab_label;
+ GtkLabel *fn_label;
+ GtkWidget *close_button;
+ GtkNotebook *notebook;
+ gint pages;
+ char *size_fancy;
+
+ if (NULL == parent)
+ {
+ /* create new tab */
+ tab = GNUNET_malloc (sizeof (struct PublishTab));
+ tab->pc = pc;
+ GNUNET_CONTAINER_DLL_insert (publish_tab_head,
+ publish_tab_tail,
+ tab);
+ tab->builder = GNUNET_GTK_get_new_builder ("publish_tab.glade");
+ df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
+ "_publish_frame_window"));
+ tab->frame = gtk_bin_get_child (GTK_BIN (df));
+ gtk_widget_ref (tab->frame);
+ gtk_container_remove (GTK_CONTAINER (df), tab->frame);
+ gtk_widget_destroy (GTK_WIDGET (df));
+
+ /* load tab_label */
+ df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
+ "_publish_label_window"));
+ tab_label = gtk_bin_get_child (GTK_BIN (df));
+ gtk_widget_ref (tab_label);
+ gtk_container_remove (GTK_CONTAINER (df), tab_label);
+ gtk_widget_destroy (GTK_WIDGET (df));
+
+ /* get refs to widgets */
+ fn_label = GTK_LABEL (gtk_builder_get_object (tab->builder,
+
"_publish_label_window_label"));
+ gtk_label_set_text (fn_label, fn);
+ close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
+
"_publish_label_close_button"));
+ g_signal_connect(G_OBJECT(close_button), "clicked",
+ G_CALLBACK(stop_publishing), tab);
+ /* make visible */
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ pages = gtk_notebook_get_n_pages (notebook);
+ gtk_notebook_insert_page (notebook,
+ tab->frame,
+ tab_label,
+ pages - 1);
+ gtk_widget_show (GTK_WIDGET (notebook));
+ tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
+
"_publish_frame_tree_store"));
+ pitrptr = NULL;
+ }
+ else
+ {
+ /* create new iter from parent */
+ tab = parent->tab;
+ path = gtk_tree_row_reference_get_path (parent->rr);
+ if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tab->ts),
+ &piter, path))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ pitrptr = &piter;
+ }
+ size_fancy = GNUNET_STRINGS_byte_size_fancy (fsize);
+ gtk_tree_store_insert_with_values (tab->ts,
+ &iter,
+ pitrptr,
+ G_MAXINT,
+ 0, fn,
+ 1, size_fancy,
+ 2, "white",
+ 3, (guint) 0 /* progress */,
+ -1);
+ GNUNET_free (size_fancy);
+ ent = GNUNET_malloc (sizeof (struct PublishEntry));
+ ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
+ ent->tab = tab;
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (tab->ts), &iter);
+ ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (tab->ts),
+ path);
+ gtk_tree_path_free (path);
+ ent->pc = pc;
+ return ent;
+}
+
+
+/**
+ * Notification of FS to a client about the progress of an
+ * operation. Callbacks of this type will be used for uploads,
+ * downloads and searches. Some of the arguments depend a bit
+ * in their meaning on the context in which the callback is used.
+ *
+ * @param cls closure
+ * @param info details about the event, specifying the event type
+ * and various bits about the event
+ * @return client-context (for the next progress call
+ * for this operation; should be set to NULL for
+ * SUSPEND and STOPPED events). The value returned
+ * will be passed to future callbacks in the respective
+ * field in the GNUNET_FS_ProgressInfo struct.
+ */
+void*
+GNUNET_GTK_fs_event_handler (void *cls,
+ const struct GNUNET_FS_ProgressInfo *info)
+{
+ void *ret;
+
+ switch (info->status)
+ {
+ case GNUNET_FS_STATUS_PUBLISH_START:
+ return setup_publish (info->value.publish.pc,
+ info->value.publish.filename,
+ info->value.publish.size,
+ info->value.publish.pctx);
+ case GNUNET_FS_STATUS_PUBLISH_RESUME:
+ ret = setup_publish (info->value.publish.pc,
+ info->value.publish.filename,
+ info->value.publish.size,
+ info->value.publish.pctx);
+ if (ret == NULL)
+ return ret;
+ if (info->value.publish.specifics.resume.message != NULL)
+ {
+ ret = handle_publish_error (ret,
+
info->value.publish.specifics.resume.message);
+ }
+ else if (info->value.publish.specifics.resume.chk_uri != NULL)
+ {
+ ret = handle_publish_completed (ret,
+
info->value.publish.specifics.resume.chk_uri);
+ }
+ return ret;
+ case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
+ close_publish_tab (info->value.publish.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
+ return mark_publish_progress (info->value.publish.cctx,
+ info->value.publish.size,
+ info->value.publish.completed);
+ case GNUNET_FS_STATUS_PUBLISH_ERROR:
+ return handle_publish_error (info->value.publish.cctx,
+ info->value.publish.specifics.error.message);
+ case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
+ return handle_publish_completed (info->value.publish.cctx,
+
info->value.publish.specifics.completed.chk_uri);
+ case GNUNET_FS_STATUS_PUBLISH_STOPPED:
+ close_publish_tab (info->value.publish.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_DOWNLOAD_START:
+ return setup_download (info->value.download.cctx,
+ info->value.download.pctx,
+ info->value.download.sctx,
+ info->value.download.dc,
+ info->value.download.uri,
+ info->value.download.specifics.start.meta,
+ info->value.download.size,
+ info->value.download.completed);
+ case GNUNET_FS_STATUS_DOWNLOAD_RESUME:
+ ret = setup_download (info->value.download.cctx,
+ info->value.download.pctx,
+ info->value.download.sctx,
+ info->value.download.dc,
+ info->value.download.uri,
+ info->value.download.specifics.resume.meta,
+ info->value.download.size,
+ info->value.download.completed);
+ if (info->value.download.specifics.resume.message != NULL)
+ {
+ ret = mark_download_error (ret,
+
info->value.download.specifics.resume.message);
+ }
+ return ret;
+ case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND:
+ stop_download (info->value.download.cctx, GNUNET_YES);
+ return NULL;
+ case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
+ return mark_download_progress (info->value.download.cctx,
+ info->value.download.size,
+ info->value.download.completed,
+
info->value.download.specifics.progress.data,
+
info->value.download.specifics.progress.offset,
+
info->value.download.specifics.progress.data_len,
+
info->value.download.specifics.progress.depth);
+ case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
+ return mark_download_error (info->value.download.cctx,
+ info->value.download.specifics.error.message);
+ case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
+ return mark_download_completed (info->value.download.cctx,
+ info->value.download.size,
+ info->value.download.filename);
+ case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
+ stop_download (info->value.download.cctx, GNUNET_NO);
+ return NULL;
+ case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
+ return change_download_colour (info->value.download.cctx,
+ "yellow");
+ case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
+ return change_download_colour (info->value.download.cctx,
+ "blue");
+ case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT:
+ return download_lost_parent (info->value.download.cctx,
+ info->value.download.size,
+ info->value.download.completed,
+ info->value.download.is_active);
+ case GNUNET_FS_STATUS_SEARCH_START:
+ if (info->value.search.pctx != NULL)
+ return setup_inner_search (info->value.search.sc,
+ info->value.search.pctx);
+ return setup_search (info->value.search.sc,
+ info->value.search.query);
+ case GNUNET_FS_STATUS_SEARCH_RESUME:
+ ret = setup_search (info->value.search.sc,
+ info->value.search.query);
+ if (info->value.search.specifics.resume.message)
+ ret = handle_search_error (ret,
+ info->value.search.specifics.resume.message);
+ return ret;
+ case GNUNET_FS_STATUS_SEARCH_RESUME_RESULT:
+ ret = process_search_result (info->value.search.cctx,
+ info->value.search.pctx,
+
info->value.search.specifics.resume_result.uri,
+
info->value.search.specifics.resume_result.meta,
+
info->value.search.specifics.resume_result.result,
+
info->value.search.specifics.resume_result.applicability_rank);
+ return update_search_result (ret,
+
info->value.search.specifics.resume_result.meta,
+
info->value.search.specifics.resume_result.applicability_rank,
+
info->value.search.specifics.resume_result.availability_certainty,
+
info->value.search.specifics.resume_result.availability_rank);
+ case GNUNET_FS_STATUS_SEARCH_SUSPEND:
+ close_search_tab (info->value.search.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_SEARCH_RESULT:
+ return process_search_result (info->value.search.cctx,
+ info->value.search.pctx,
+ info->value.search.specifics.result.uri,
+ info->value.search.specifics.result.meta,
+ info->value.search.specifics.result.result,
+
info->value.search.specifics.result.applicability_rank);
+ case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_SEARCH_UPDATE:
+ return update_search_result (info->value.search.specifics.update.cctx,
+ info->value.search.specifics.update.meta,
+
info->value.search.specifics.update.applicability_rank,
+
info->value.search.specifics.update.availability_certainty,
+
info->value.search.specifics.update.availability_rank);
+ case GNUNET_FS_STATUS_SEARCH_ERROR:
+ return handle_search_error (info->value.search.cctx,
+ info->value.search.specifics.error.message);
+ case GNUNET_FS_STATUS_SEARCH_PAUSED:
+ return info->value.search.cctx;
+ case GNUNET_FS_STATUS_SEARCH_CONTINUED:
+ return info->value.search.cctx;
+ case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
+ free_search_result (info->value.search.specifics.result_suspend.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND:
+ free_search_result (info->value.search.specifics.result_suspend.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_SEARCH_STOPPED:
+ close_search_tab (info->value.search.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_UNINDEX_START:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_RESUME:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_SUSPEND:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_PROGRESS:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_ERROR:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_COMPLETED:
+ GNUNET_break (0);
+ break;
+ case GNUNET_FS_STATUS_UNINDEX_STOPPED:
+ GNUNET_break (0);
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+ return NULL;
+}
+
+
+/**
+ * Page switched in main notebook, update thumbnail and
+ * metadata views.
+ */
+void
+GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkNotebook *notebook;
+ gint page;
+ GtkWidget *w;
+ struct SearchTab *tab;
+ GtkImage *image;
+ GtkListStore *ms;
+ GtkTreeView *tv;
+
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ page = gtk_notebook_get_current_page (notebook);
+ w = gtk_notebook_get_nth_page (notebook, page);
+ tab = search_tab_head;
+ while (tab != NULL)
+ {
+ if (tab->frame == w)
+ {
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
+ "_search_result_frame"));
+ update_meta_data_views (tv, tab);
+ return;
+ }
+ tab = tab->next;
+ }
+ image = GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_preview_image"));
+ gtk_image_clear (image);
+ ms = GTK_LIST_STORE (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_meta_data_list_store"));
+ gtk_list_store_clear (ms);
+}
+
+
+
+/* end of fs_event_handler.c */
Copied: gnunet-gtk/src/fs/fs_event_handler.h (from rev 16478,
gnunet-gtk/src/fs_event_handler.h)
===================================================================
--- gnunet-gtk/src/fs/fs_event_handler.h (rev 0)
+++ gnunet-gtk/src/fs/fs_event_handler.h 2011-08-15 14:11:40 UTC (rev
16543)
@@ -0,0 +1,198 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs_event_handler.h
+ * @brief Main event handler for file-sharing
+ * @author Christian Grothoff
+ */
+#include "common.h"
+
+
+struct SearchResult;
+
+
+/**
+ * Context we keep for a search tab.
+ */
+struct SearchTab
+{
+ /**
+ * This is a doubly-linked list.
+ */
+ struct SearchTab *next;
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct SearchTab *prev;
+
+ /**
+ * Set in case this is an inner search, otherwise NULL.
+ */
+ struct SearchResult *parent;
+
+ /**
+ * Handle for this search with FS library.
+ */
+ struct GNUNET_FS_SearchContext *sc;
+
+ char *query_txt;
+
+ GtkBuilder *builder;
+
+ GtkWidget *frame;
+
+ GtkWidget *tab_label;
+
+ GtkWidget *close_button;
+
+ GtkWidget *clear_button;
+
+ GtkWidget *play_button;
+
+ GtkWidget *pause_button;
+
+ GtkLabel *label;
+
+ GtkTreeStore *ts;
+
+ unsigned int num_results;
+
+};
+
+
+struct DownloadEntry
+{
+
+ /**
+ * Download entry of the parent (for recursive downloads),
+ * NULL if we are either a top-level download (from URI,
+ * from opened directory, orphaned from search or direct
+ * search result).
+ */
+ struct DownloadEntry *pde;
+
+ /**
+ * Associated search result, or NULL if we don't belong
+ * to a search directly (download entry).
+ */
+ struct SearchResult *sr;
+
+ /**
+ * FS handle to control the download.
+ */
+ struct GNUNET_FS_DownloadContext *dc;
+
+ /**
+ * URI for the download.
+ */
+ struct GNUNET_FS_Uri *uri;
+
+ /**
+ * Meta data for the download.
+ */
+ struct GNUNET_CONTAINER_MetaData *meta;
+
+ /**
+ * Where in the tree view is this download being displayed.
+ */
+ GtkTreeRowReference *rr;
+
+ /**
+ * Tree store where we are stored.
+ */
+ GtkTreeStore *ts;
+
+ /**
+ * Tab where this download is currently on display.
+ */
+ struct SearchTab *tab;
+
+ /**
+ * Has the download completed (or errored)?
+ */
+ int is_done;
+
+};
+
+
+
+
+/**
+ * Setup a new top-level entry in the URI tab. If necessary, create
+ * the URI tab first.
+ *
+ * @param iter set to the new entry
+ * @param srp set to search result
+ * @param meta metadata for the new entry
+ * @param uri URI for the new entry
+ * @return NULL on error, otherwise search tab with the new entry
+ */
+struct SearchTab *
+GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
+ struct SearchResult **sr,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ const struct GNUNET_FS_Uri *uri);
+
+
+
+/**
+ * Add a search result to the given search tab.
+ *
+ * @param tab search tab to extend
+ * @param iter set to position where search result is added
+ * @param parent_rr reference to parent entry in search tab
+ * @param uri uri to add
+ * @param meta metadata of the entry
+ * @param result associated FS search result (can be NULL)
+ * @param applicability_rank how relevant is the result
+ * @return entry for the search result
+ */
+struct SearchResult *
+GNUNET_GTK_add_search_result (struct SearchTab *tab,
+ GtkTreeIter *iter,
+ GtkTreeRowReference *parent_rr,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_SearchResult *result,
+ uint32_t applicability_rank);
+
+
+/**
+ * Notification of FS to a client about the progress of an
+ * operation. Callbacks of this type will be used for uploads,
+ * downloads and searches. Some of the arguments depend a bit
+ * in their meaning on the context in which the callback is used.
+ *
+ * @param cls closure
+ * @param info details about the event, specifying the event type
+ * and various bits about the event
+ * @return client-context (for the next progress call
+ * for this operation; should be set to NULL for
+ * SUSPEND and STOPPED events). The value returned
+ * will be passed to future callbacks in the respective
+ * field in the GNUNET_FS_ProgressInfo struct.
+ */
+void* GNUNET_GTK_fs_event_handler (void *cls,
+ const struct GNUNET_FS_ProgressInfo *info);
+
+
+/* end of fs_event_handler.h */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk.c (from rev 16519,
gnunet-gtk/src/gnunet-gtk.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk.c (rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk.c 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,249 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-gtk.c
+ * @brief Main function of gnunet-gtk
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "fs_event_handler.h"
+
+/**
+ * Should gnunet-gtk start in tray mode?
+ */
+static int tray_only;
+
+/**
+ * Handle to our main loop.
+ */
+static struct GNUNET_GTK_MainLoop *ml;
+
+/**
+ * Handle for file-sharing operations.
+ */
+static struct GNUNET_FS_Handle *fs;
+
+/**
+ * List of plugins for meta data extraction.
+ */
+static struct EXTRACTOR_PluginList *plugins;
+
+
+/**
+ * Return handle for file-sharing operations.
+ *
+ * @return NULL on error
+ */
+struct GNUNET_FS_Handle *
+GNUNET_FS_GTK_get_fs_handle ()
+{
+ return fs;
+}
+
+
+/**
+ * Get LE plugin list.
+ */
+struct EXTRACTOR_PluginList *
+GNUNET_FS_GTK_get_le_plugins ()
+{
+ return plugins;
+}
+
+
+/**
+ * Get cfg.
+ */
+const struct GNUNET_CONFIGURATION_Handle *
+GNUNET_FS_GTK_get_configuration (void)
+{
+ return GNUNET_GTK_main_loop_get_configuration (ml);
+}
+
+
+/**
+ * Get an object from the main window.
+ *
+ * @param name name of the object
+ * @return NULL on error
+ */
+GObject *
+GNUNET_FS_GTK_get_main_window_object (const char *name)
+{
+ return GNUNET_GTK_main_loop_get_object (ml, name);
+}
+
+
+/**
+ * Task run on shutdown.
+ * FIXME: does this need to be a separate task!?
+ */
+static void
+shutdown_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if (fs != NULL)
+ {
+ GNUNET_FS_stop (fs);
+ fs = NULL;
+ }
+ EXTRACTOR_plugin_remove_all (plugins);
+ plugins = NULL;
+}
+
+
+/**
+ * Callback invoked if the application is supposed to exit.
+ */
+void
+GNUNET_GTK_quit_cb (GtkObject *object,
+ gpointer user_data)
+{
+ GNUNET_GTK_tray_icon_destroy ();
+ GNUNET_GTK_main_loop_quit (ml);
+ GNUNET_SCHEDULER_add_now (&shutdown_task,
+ NULL);
+}
+
+
+/**
+ * Search selected in 'file' menu. (from main_window_file_search.c)
+ */
+void
+GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
+ gpointer data);
+
+
+/**
+ * Add the tab with the 'new' icon for starting a search.
+ */
+static void
+add_new_tab ()
+{
+ GtkNotebook *notebook;
+ GtkWindow *sf;
+ gint pages;
+ GtkBuilder *builder;
+ GtkWidget *label;
+ GtkWidget *frame;
+
+ builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_main_tab_new_frame.glade");
+
+ /* load frame */
+ sf = GTK_WINDOW (gtk_builder_get_object (builder,
+ "_main_tab_new_frame"));
+ label = gtk_bin_get_child (GTK_BIN (sf));
+ gtk_widget_ref (label);
+ gtk_container_remove (GTK_CONTAINER (sf), label);
+ gtk_widget_destroy (GTK_WIDGET (sf));
+ g_object_unref (builder);
+ g_signal_connect(G_OBJECT(label), "clicked",
+ G_CALLBACK(&GNUNET_GTK_main_menu_file_search_activate_cb),
NULL);
+
+ notebook = GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window_notebook"));
+ pages = gtk_notebook_get_n_pages (notebook);
+ frame = gtk_label_new ("");
+ gtk_widget_show (frame);
+ gtk_notebook_append_page (notebook,
+ frame,
+ label);
+ gtk_notebook_set_current_page (notebook,
+ pages);
+ gtk_widget_show (GTK_WIDGET (notebook));
+}
+
+
+/**
+ * Actual main function run right after GNUnet's scheduler
+ * is initialized. Initializes up GTK and Glade.
+ */
+static void
+run (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GtkWidget *main_window;
+ ml = cls;
+
+ GNUNET_GTK_set_icon_search_path ();
+ GNUNET_GTK_setup_nls ();
+
+ /* setup main window */
+ main_window = GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_window"));
+ gtk_window_maximize (GTK_WINDOW (main_window));
+ GNUNET_GTK_tray_icon_create (GTK_WINDOW (main_window),
+ "gnunet-gtk" /* FIXME: rename icon? */,
+ "gnunet-fs-gtk");
+
+ /* initialize file-sharing */
+ plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
+ fs = GNUNET_FS_start (GNUNET_GTK_main_loop_get_configuration (ml),
+ "gnunet-gtk",
+ &GNUNET_GTK_fs_event_handler,
+ NULL,
+ GNUNET_FS_FLAGS_NONE /* fixme later for
persistence/probes */,
+ /* set other options here later! */
+ GNUNET_FS_OPTIONS_END);
+ if (fs != NULL)
+ {
+ add_new_tab ();
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_create_pseudonym")));
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_advertise_pseudonym")));
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_publish")));
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_search")));
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_download_uri")));
+ gtk_widget_hide (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object
("GNUNET_GTK_main_menu_file_open_gnunet_directory")));
+ /* FIXME: set warning in status bar... */
+ }
+ /* make GUI visible */
+ if (!tray_only)
+ {
+ gtk_widget_show (main_window);
+ gtk_window_present (GTK_WINDOW (main_window));
+ }
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+ static struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'t', "tray", NULL,
+ gettext_noop ("start in tray mode"), 0,
+ &GNUNET_GETOPT_set_one, &tray_only},
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_GTK_main_loop_start ("gnunet-gtk",
+ "GTK GUI for GNUnet",
+ argc, argv,
+ options,
+ "gnunet_fs_gtk_main_window.glade",
+ &run))
+ return 1;
+ return 0;
+}
+
+
+/* end of gnunet-fs-gtk.c */
Added: gnunet-gtk/src/fs/gnunet-fs-gtk.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk.h (rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk.h 2011-08-15 14:11:40 UTC (rev 16543)
@@ -0,0 +1,68 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/fs/gnunet-fs-gtk.h
+ * @brief Globals for gnunet-fs-gtk
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_FS_GTK_H
+#define GNUNET_FS_GTK_H
+
+#include "gnunet_gtk.h"
+#include <gnunet/gnunet_fs_service.h>
+#include <extractor.h>
+
+
+/**
+ * Get GNU libextractor plugin list.
+ */
+struct EXTRACTOR_PluginList *
+GNUNET_FS_GTK_get_le_plugins (void);
+
+
+/**
+ * Get our configuration.
+ */
+const struct GNUNET_CONFIGURATION_Handle *
+GNUNET_FS_GTK_get_configuration (void);
+
+
+/**
+ * Return our handle for file-sharing operations.
+ *
+ * @return NULL on error
+ */
+struct GNUNET_FS_Handle *
+GNUNET_FS_GTK_get_fs_handle (void);
+
+/**
+ * Get an object from the main window.
+ *
+ * @param name name of the object
+ * @return NULL on error
+ */
+GObject *
+GNUNET_FS_GTK_get_main_window_object (const char *name);
+
+
+
+#endif
+/* end of gnunet-fs-gtk.h */
Copied: gnunet-gtk/src/fs/main_window_adv_pseudonym.c (from rev 16478,
gnunet-gtk/src/main_window_adv_pseudonym.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_adv_pseudonym.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_adv_pseudonym.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,588 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_adv_pseudonym.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+
+static GtkBuilder *builder;
+
+
+/**
+ * Canonicalize spelling of currently selected keyword.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button_clicked_cb ()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ gchar *value;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_FS_Uri *nuri;
+ char *nvalue;
+ char *emsg;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm, &iter,
+ 0, &value,
+ -1);
+ emsg = NULL;
+ uri = GNUNET_FS_uri_ksk_create (value, &emsg);
+ if (uri == NULL)
+ {
+ GNUNET_break (0);
+ GNUNET_free (emsg);
+ g_free (value);
+ return;
+ }
+ nuri = GNUNET_FS_uri_ksk_canonicalize (uri);
+ nvalue = GNUNET_FS_uri_ksk_to_string_fancy (nuri);
+ gtk_list_store_set (GTK_LIST_STORE (tm), &iter,
+ 0, nvalue,
+ -1);
+ GNUNET_FS_uri_destroy (nuri);
+ GNUNET_FS_uri_destroy (uri);
+ GNUNET_free (nvalue);
+ g_free (value);
+}
+
+
+/**
+ * Remove the currently selected keyword from the list.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_keyword_list_del_button_clicked_cb ()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_list_store_remove (GTK_LIST_STORE (tm),
+ &iter);
+}
+
+
+/**
+ * Add keyword from entry line to keyword list.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ()
+{
+ const char *keyword;
+ GtkEntry *entry;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_keyword_list_store"));
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_entry"));
+ keyword = gtk_entry_get_text (entry);
+ if (strlen (keyword) > 0)
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
+ gtk_entry_set_text (entry, "");
+}
+
+
+/**
+ * Update sensitivity of keyword add button.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_keyword_entry_changed_cb ()
+{
+ const char *keyword;
+ GtkEntry *entry;
+ GtkWidget *button;
+
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_add_button"));
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_entry"));
+ keyword = gtk_entry_get_text (entry);
+ gtk_widget_set_sensitive (button,
+ (strlen (keyword) > 0) ? TRUE : FALSE);
+}
+
+/**
+ * Update sensitivity of metadata delete button.
+ */
+static void
+metadata_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkWidget *button;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_delete_button"));
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+}
+
+
+/**
+ * Update sensitivity of keyword delete and normalize button.
+ */
+static void
+keyword_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkWidget *button;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_del_button"));
+
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button"));
+ gtk_widget_set_sensitive (button,
+ gtk_tree_selection_get_selected (sel, NULL, NULL));
+}
+
+
+/**
+ * Update sensitivity of metadata add button.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb ()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ const char *value;
+ GtkEntry *entry;
+ GtkWidget *button;
+
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
+ value = gtk_entry_get_text (entry);
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_add_button"));
+ gtk_widget_set_sensitive (button,
+ (strlen (value) > 0)
+ ? gtk_tree_selection_get_selected (sel, NULL, NULL)
+ : FALSE);
+}
+
+
+/**
+ * Add keyword to keyword list.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_keyword_entry_activate_cb ()
+{
+ GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ();
+}
+
+
+void
+GNUNET_GTK_advertise_pseudonym_metadata_preview_file_chooser_button_file_set_cb
()
+{
+ GNUNET_break (0);
+}
+
+/**
+ * Delete currently selected item from meta data list.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_metadata_delete_button_clicked_cb()
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_list_store_remove (GTK_LIST_STORE (tm),
+ &iter);
+}
+
+
+/**
+ * Add metadata to metadata list.
+ */
+void
+GNUNET_GTK_advertise_pseudonym_metadata_add_button_clicked_cb ()
+{
+ const char *value;
+ char *avalue;
+ const char *ivalue;
+ GtkEntry *entry;
+ GtkListStore *ls;
+ GtkTreeModel *tm;
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ guint type;
+ size_t slen;
+ char *pos;
+
+ entry = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
+ value = gtk_entry_get_text (entry);
+ if ((value == NULL) || (strlen (value) == 0))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
+ tm = gtk_tree_view_get_model (tv);
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm,
+ &iter,
+ 1, &type, -1);
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
+ (value[strlen(value)-1] != '/') )
+ {
+ GNUNET_asprintf (&avalue,
+ "%s/",
+ value);
+ /* if user typed '\' instead of '/', change it! */
+ slen = strlen (avalue);
+ while ( (slen > 1) &&
+ (avalue[slen-2] == '\\') )
+ {
+ avalue[slen-2] = '/';
+ avalue[slen-1] = '\0';
+ slen--;
+ }
+ while (NULL != (pos = strstr (avalue, "\\")))
+ *pos = '/';
+ /* remove '../' everywhere */
+ while (NULL != (pos = strstr (avalue, "../")))
+ {
+ pos[0] = '_';
+ pos[1] = '_';
+ pos[2] = '_';
+ }
+ ivalue = avalue;
+ }
+ else
+ {
+ ivalue = value;
+ avalue = NULL;
+ }
+
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
+ 0, type,
+ 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
+ 2, EXTRACTOR_metatype_to_string (type),
+ 3, ivalue,
+ -1);
+ GNUNET_free_non_null (avalue);
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+}
+
+
+/**
+ * Callback with information about local (!) namespaces.
+ * Contains the names of the local namespace and the global
+ * ID. Adds the to the list store.
+ *
+ * @param cls closure, the list store.
+ * @param name human-readable identifier of the namespace
+ * @param id hash identifier for the namespace
+ */
+static void
+add_to_list (void *cls,
+ const char *name,
+ const GNUNET_HashCode *id)
+{
+ GtkListStore *ls = cls;
+ GtkTreeIter iter;
+
+ gtk_list_store_insert_with_values (ls,
+ &iter,
+ -1,
+ 0, name,
+ 1, GNUNET_FS_namespace_create
(GNUNET_FS_GTK_get_fs_handle (),
+ name),
+ -1);
+
+}
+
+
+static void
+selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ GtkTreeIter iter;
+ GtkWidget *ok_button;
+
+ ok_button = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_select_pseudonym_ok_button"));
+ if (TRUE == gtk_tree_selection_get_selected (ts, NULL, &iter))
+ gtk_widget_set_sensitive (ok_button, TRUE);
+ else
+ gtk_widget_set_sensitive (ok_button, FALSE);
+}
+
+
+/**
+ * Advertise pseudonym selected.
+ */
+void
+GNUNET_GTK_main_menu_file_advertise_pseudonym_activate_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ struct GNUNET_FS_Namespace *ns;
+ struct GNUNET_FS_Namespace *nso;
+ GtkListStore *ls;
+ GtkTreeView *tv;
+ GtkTreeIter iter;
+ GtkTreeSelection *sel;
+ GtkTreeModel *tm;
+ GtkSpinButton *sb;
+ struct GNUNET_FS_BlockOptions bo;
+ struct GNUNET_FS_Uri *nxt;
+ struct GNUNET_FS_Uri *mrg;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *nm;
+ const char *root;
+ char *value;
+ guint ntype;
+ guint nformat;
+ guint type;
+ guint max_type;
+
+ builder = GNUNET_GTK_get_new_builder ("select_pseudonym_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_select_pseudonym_dialog"));
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_select_pseudonym_liststore"));
+ GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
+ &add_to_list,
+ ls);
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_select_pseudonym_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(selection_changed_cb), NULL);
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+ return;
+ }
+ GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter));
+ gtk_tree_model_get (tm,
+ &iter,
+ 1, &ns,
+ -1);
+ /* free all namespaces from list store except "ns" */
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 1, &nso,
+ -1);
+ if (ns != nso)
+ GNUNET_FS_namespace_delete (nso, GNUNET_NO);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+
+
+ builder = GNUNET_GTK_get_new_builder ("advertise_pseudonym_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_dialog"));
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_metatype_list_store"));
+ max_type = EXTRACTOR_metatype_get_max ();
+ type = 1;
+ while (type < max_type - 1)
+ {
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
+ 0, EXTRACTOR_metatype_to_string (type),
+ 1, type,
+ 2, EXTRACTOR_metatype_to_description
(type),
+ -1);
+ type++;
+ }
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+
G_CALLBACK(GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb),
NULL);
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(metadata_selection_changed_cb), NULL);
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(keyword_selection_changed_cb), NULL);
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+ return;
+ }
+ /* get keywords from list store */
+ nxt = NULL;
+ mrg = NULL;
+ uri = NULL;
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
+
"GNUNET_GTK_keyword_list_store"));
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 0, &value,
+ -1);
+ nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
+ mrg = GNUNET_FS_uri_ksk_merge (nxt, uri);
+ GNUNET_FS_uri_destroy (nxt);
+ if (NULL != uri)
+ GNUNET_FS_uri_destroy (uri);
+ uri = mrg;
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ /* get meta */
+ nm = GNUNET_CONTAINER_meta_data_create ();
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
+
"GNUNET_GTK_meta_data_list_store"));
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter,
+ 0, &ntype,
+ 1, &nformat,
+ 3, &value,
+ -1);
+ GNUNET_CONTAINER_meta_data_insert (nm,
+ "<user>",
+ ntype,
+ nformat,
+ "text/plain",
+ value,
+ strlen (value)+1);
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+ bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_anonymity_spin_button")));
+ bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_priority_spin_button")));
+ sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_expiration_year_spin_button"));
+ bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
+ root = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_advertise_pseudonym_root_entry")));
+ GNUNET_FS_namespace_advertise (GNUNET_FS_GTK_get_fs_handle (),
+ uri,
+ ns,
+ nm,
+ &bo,
+ root,
+ NULL, NULL);
+ GNUNET_FS_namespace_delete (ns, GNUNET_NO);
+ GNUNET_CONTAINER_meta_data_destroy (nm);
+ if (NULL != uri)
+ GNUNET_FS_uri_destroy (uri);
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+}
+
+
+/* end of main_window_adv_pseudonym.c */
Copied: gnunet-gtk/src/fs/main_window_create_pseudonym.c (from rev 16478,
gnunet-gtk/src/main_window_create_pseudonym.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_create_pseudonym.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_create_pseudonym.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_create_pseudonym.c
+ * @author Christian Grothoff
+ *
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+
+/**
+ */
+void
+GNUNET_GTK_main_menu_create_pseudonym_activate_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ GtkBuilder *builder;
+ const char *name;
+ struct GNUNET_FS_Namespace *ns;
+
+ builder = GNUNET_GTK_get_new_builder ("create_namespace_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_create_namespace_dialog"));
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ return;
+ }
+ name = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_create_namespace_name_entry")));
+ /* FIXME: show busy dialog while doing key creation */
+ ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (),
+ name);
+ GNUNET_FS_namespace_delete (ns, GNUNET_NO);
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+}
+
+
+/* end of main_window_create_pseudonym.c */
Copied: gnunet-gtk/src/fs/main_window_file_download.c (from rev 16478,
gnunet-gtk/src/main_window_file_download.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_file_download.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_file_download.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,130 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_file_download.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "download.h"
+#include "gnunet-fs-gtk.h"
+
+static GtkBuilder *builder;
+
+void
+GNUNET_GTK_open_url_dialog_url_entry_changed_cb (GtkEditable *editable,
+ gpointer user_data)
+{
+ struct GNUNET_FS_Uri *uri;
+ char *perr;
+ const char *uris;
+
+ perr = NULL;
+ uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_open_url_dialog_url_entry")));
+ if (uris != NULL)
+ uri = GNUNET_FS_uri_parse (uris, &perr);
+ else
+ uri = NULL;
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_open_url_dialog_execute_button")),
+ (uri == NULL) ? FALSE : TRUE);
+ if (uri != NULL)
+ GNUNET_FS_uri_destroy (uri);
+ else
+ GNUNET_free_non_null (perr);
+}
+
+
+/**
+ * User selected "Open URI" in main window.
+ */
+void
+GNUNET_GTK_main_menu_file_download_uri_activate_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ const char *uris;
+ uint32_t anonymity;
+ struct GNUNET_FS_Uri *uri;
+ char *perr;
+ struct DownloadContext *dc;
+
+ GNUNET_assert (builder == NULL);
+ builder = GNUNET_GTK_get_new_builder ("open_url_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+ "GNUNET_GTK_open_url_dialog"));
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+ fprintf (stderr,
+ "Dialog closed!\n");
+ return;
+ }
+ uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_open_url_dialog_url_entry")));
+ anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_open_url_dialog_anonymity_spin_button")));
+ uri = GNUNET_FS_uri_parse (uris, &perr);
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+ if (uri == NULL)
+ {
+ GNUNET_free (perr);
+ /* Why was "execute" button sensitive!? */
+ GNUNET_break (0);
+ return;
+ }
+ if (GNUNET_FS_uri_test_sks (uri) ||
+ GNUNET_FS_uri_test_ksk (uri))
+ {
+ fprintf (stderr,
+ "Starting search!\n");
+ GNUNET_break (NULL !=
+ GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (),
+ uri,
+ anonymity,
+ GNUNET_FS_SEARCH_OPTION_NONE,
+ NULL));
+ GNUNET_FS_uri_destroy (uri);
+ return;
+ }
+ if (GNUNET_FS_uri_test_chk (uri) ||
+ GNUNET_FS_uri_test_loc (uri))
+ {
+ dc = GNUNET_malloc (sizeof (struct DownloadContext));
+ dc->uri = uri;
+ dc->anonymity = anonymity;
+ GNUNET_GTK_open_download_as_dialog (dc);
+ return;
+ }
+ GNUNET_break (0);
+ GNUNET_FS_uri_destroy (uri);
+}
+
+/* end of main_window_file_download.c */
Copied: gnunet-gtk/src/fs/main_window_file_publish.c (from rev 16478,
gnunet-gtk/src/main_window_file_publish.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_file_publish.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_file_publish.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,1933 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_file_publish.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+#include "edit_publish_dialog.h"
+#include <gnunet/gnunet_util_lib.h>
+
+#define MARKER_DIR_FILE_SIZE "-"
+
+/**
+ * Builder used for the master publish dialog.
+ */
+static GtkBuilder *master_builder;
+
+
+/**
+ * Check if two GtkTreeIters refer to the same element.
+ *
+ * @param tm tree model of the iterators
+ * @param i1 first iterator
+ * @param i2 second iterator
+ * @return GNUNET_YES if they are equal
+ */
+static int
+gtk_tree_iter_equals (GtkTreeModel *tm,
+ GtkTreeIter *i1,
+ GtkTreeIter *i2)
+{
+ GtkTreePath *p1;
+ GtkTreePath *p2;
+ int ret;
+
+ p1 = gtk_tree_model_get_path (tm, i1);
+ p2 = gtk_tree_model_get_path (tm, i2);
+ ret = gtk_tree_path_compare (p1, p2);
+ gtk_tree_path_free (p1);
+ gtk_tree_path_free (p2);
+ return (0 == ret) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Update selectivity in the master dialog.
+ */
+static void
+update_selectivity ()
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeModel *ptm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ GtkWidget *up_button;
+ GtkWidget *down_button;
+ GtkWidget *left_button;
+ GtkWidget *right_button;
+ GtkWidget *delete_button;
+ GtkWidget *edit_button;
+ GtkWidget *execute_button;
+ int is_dir;
+ struct GNUNET_FS_FileInformation *fip;
+ int ns_ok;
+ gchar *namespace_id;
+
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_file_sharing_publishing_tree_store"));
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ ns_ok = GNUNET_YES;
+ if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
+ {
+ gtk_tree_model_get (ptm,
+ &iter,
+ 2, &namespace_id,
+ -1);
+ if (namespace_id == NULL)
+ ns_ok = GNUNET_NO;
+ else
+ g_free (namespace_id);
+ }
+ up_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_up_button"));
+ down_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_down_button"));
+ left_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_left_button"));
+ right_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_right_button"));
+ delete_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_delete_button"));
+ edit_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_edit_button"));
+ execute_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_execute_button"));
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ tm = gtk_tree_view_get_model (tv);
+ if ( (gtk_tree_model_get_iter_first (tm, &iter)) &&
+ (ns_ok == GNUNET_YES) )
+ gtk_widget_set_sensitive (execute_button, TRUE);
+ else
+ gtk_widget_set_sensitive (execute_button, FALSE);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ gtk_widget_set_sensitive (up_button, FALSE);
+ gtk_widget_set_sensitive (down_button, FALSE);
+ gtk_widget_set_sensitive (left_button, FALSE);
+ gtk_widget_set_sensitive (right_button, FALSE);
+ gtk_widget_set_sensitive (delete_button, FALSE);
+ gtk_widget_set_sensitive (edit_button, FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive (delete_button, TRUE);
+ gtk_widget_set_sensitive (edit_button, TRUE);
+
+ /* now figure out which move operations are currently legal */
+ GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
+ if (TRUE == gtk_tree_model_iter_next (tm, &iter))
+ {
+ gtk_widget_set_sensitive (down_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (down_button, FALSE);
+ }
+ GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
+ if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
+ {
+ gtk_widget_set_sensitive (left_button, TRUE);
+ GNUNET_assert (TRUE ==
+ gtk_tree_model_iter_children (tm, &pred, &parent));
+ }
+ else
+ {
+ gtk_widget_set_sensitive (left_button, FALSE);
+ GNUNET_assert (TRUE ==
+ gtk_tree_model_get_iter_first (tm, &pred));
+ }
+ /* iterate over 'next' of pred to find out if our
+ predecessor is a directory! */
+ is_dir = GNUNET_SYSERR;
+ while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
+ {
+ gtk_tree_model_get (tm, &pred,
+ 5, &fip, -1);
+ is_dir = GNUNET_FS_file_information_is_directory (fip);
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
+ }
+ if (GNUNET_YES == is_dir)
+ {
+ gtk_widget_set_sensitive (right_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (right_button, FALSE);
+ }
+ if (GNUNET_SYSERR != is_dir)
+ {
+ gtk_widget_set_sensitive (up_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (up_button, FALSE);
+ }
+}
+
+
+/**
+ * Add a file to the tree model.
+ *
+ * @param filename file to add
+ * @param bo block options to use
+ * @param do_index should we index or insert?
+ * @param iter parent entry, or NULL for top-level addition
+ */
+static void
+add_file_at_iter (const char *filename,
+ const struct GNUNET_FS_BlockOptions *bo,
+ int do_index,
+ GtkTreeIter *iter)
+{
+ struct GNUNET_FS_FileInformation *fi;
+ GtkTreeRowReference *row_reference;
+ GtkTreePath *path;
+ uint64_t file_size;
+ const char *short_fn;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ struct GNUNET_FS_Uri *ksk_uri;
+ GtkTreeStore *ts;
+ GtkTreeIter pos;
+ char *file_size_fancy;
+ const char *ss;
+ struct stat sbuf;
+
+ if (0 != STAT (filename, &sbuf))
+ return;
+ if (S_ISDIR (sbuf.st_mode))
+ {
+ file_size = 0;
+ }
+ else
+ {
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename,
+ &file_size,
+ GNUNET_YES))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ }
+ ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_file_sharing_publishing_tree_store"));
+
+ meta = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_FS_meta_data_extract_from_file (meta,
+ filename,
+ GNUNET_FS_GTK_get_le_plugins());
+ GNUNET_CONTAINER_meta_data_delete (meta,
+ EXTRACTOR_METATYPE_FILENAME,
+ NULL, 0);
+ short_fn = filename;
+ while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
+ short_fn = 1 + ss;
+ GNUNET_CONTAINER_meta_data_insert (meta,
+ "<gnunet-gtk>",
+ EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METAFORMAT_UTF8,
+ "text/plain",
+ short_fn,
+ strlen(short_fn)+1);
+ ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
+ gtk_tree_store_insert_before (ts,
+ &pos,
+ iter,
+ NULL);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
+ &pos);
+ row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
+ path);
+ gtk_tree_path_free (path);
+ fi = GNUNET_FS_file_information_create_from_file
(GNUNET_FS_GTK_get_fs_handle (),
+ row_reference,
+ filename,
+ ksk_uri,
+ meta,
+ do_index,
+ bo);
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ GNUNET_FS_uri_destroy (ksk_uri);
+ if (S_ISDIR (sbuf.st_mode))
+ file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
+ else
+ file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
+ gtk_tree_store_set (ts, &pos,
+ 0, file_size_fancy,
+ 1, (gboolean) do_index,
+ 2, short_fn,
+ 3, (guint) bo->anonymity_level,
+ 4, (guint) bo->content_priority,
+ 5, fi,
+ -1);
+ GNUNET_free (file_size_fancy);
+ update_selectivity ();
+}
+
+
+
+/**
+ * Add an empty directory to the tree model.
+ *
+ * @param name name for the directory
+ * @param bo block options
+ * @param iter parent entry, or NULL for top-level addition
+ * @param pos iterator to set to the location of the new element
+ */
+static void
+create_dir_at_iter (const char *name,
+ const struct GNUNET_FS_BlockOptions *bo,
+ GtkTreeIter *iter,
+ GtkTreeIter *pos)
+{
+ struct GNUNET_FS_FileInformation *fi;
+ GtkTreeRowReference *row_reference;
+ GtkTreePath *path;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ GtkTreeStore *ts;
+
+ ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_file_sharing_publishing_tree_store"));
+ meta = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_FS_meta_data_make_directory (meta);
+ GNUNET_CONTAINER_meta_data_insert (meta,
+ "<gnunet-gtk>",
+ EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METAFORMAT_UTF8,
+ "text/plain",
+ name,
+ strlen(name)+1);
+ gtk_tree_store_insert_before (ts,
+ pos,
+ iter,
+ NULL);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
+ pos);
+ row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
+ path);
+ gtk_tree_path_free (path);
+ fi = GNUNET_FS_file_information_create_empty_directory
(GNUNET_FS_GTK_get_fs_handle (),
+ row_reference,
+ NULL,
+ meta,
+ bo);
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ gtk_tree_store_set (ts, pos,
+ 0, MARKER_DIR_FILE_SIZE,
+ 1, (gboolean) GNUNET_NO,
+ 2, name,
+ 3, (guint) bo->anonymity_level,
+ 4, (guint) bo->content_priority,
+ 5, fi,
+ -1);
+ update_selectivity ();
+}
+
+
+/* ************ code for adding directories starts ************* */
+
+
+/**
+ * Data we keep when calculating the publication details for a file.
+ */
+struct PublishData
+{
+ /**
+ * Metadata for the file.
+ */
+ struct GNUNET_CONTAINER_MetaData *meta;
+
+ /**
+ * Iterator for the entry.
+ */
+ GtkTreeIter iter;
+};
+
+
+/**
+ * Entry for each unique meta data entry to track how often
+ * it occured. Contains the keyword and the counter.
+ */
+struct MetaCounter
+{
+
+ /**
+ * Keyword that was found.
+ */
+ const char *value;
+
+ /**
+ * Mimetype of the value.
+ */
+ const char *value_mimetype;
+
+ /**
+ * Type of the value.
+ */
+ enum EXTRACTOR_MetaType type;
+
+ /**
+ * Format of the value.
+ */
+ enum EXTRACTOR_MetaFormat format;
+
+ /**
+ * How many files have meta entries matching this value?
+ * (type and format do not have to match).
+ */
+ unsigned int count;
+
+};
+
+
+/**
+ * Execution context for 'add_dir'
+ */
+struct AddDirContext
+{
+ /**
+ * While scanning, 'parent' is the iter entry for the
+ * parent, or NULL for top-level.
+ */
+ GtkTreeIter *parent;
+
+ /**
+ * Tree store to manipulate.
+ */
+ GtkTreeStore *ts;
+
+ /**
+ * Map from the hash over the meta value to an 'struct MetaCounter'
+ * counter that says how often this value was
+ * encountered in the current directory.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *metacounter;
+
+ /**
+ * Map from the hash of a filename in the current directory
+ * to the 'struct PublishData*' for the file.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *metamap;
+
+ /**
+ * Metadata to exclude from using for KSK since it'll be associated
+ * with the parent as well. NULL for nothing blocked.
+ */
+ struct GNUNET_CONTAINER_MetaData *no_ksk;
+
+ /**
+ * Block options to use.
+ */
+ struct GNUNET_FS_BlockOptions bo;
+
+ /**
+ * Index or insert?
+ */
+ int do_index;
+
+ /**
+ * Number of files in the current directory.
+ */
+ unsigned int dir_entry_count;
+};
+
+
+/**
+ * Add the given meta data item to the
+ * meta data statistics tracker.
+ *
+ * @param cls closure (user-defined)
+ * @param plugin_name name of the plugin that produced this value;
+ * special values can be used (i.e. '<zlib>' for zlib being
+ * used in the main libextractor library and yielding
+ * meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data
+ * @param data_mime_type mime-type of data (not of the original file);
+ * can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue extracting, 1 to abort
+ */
+static int
+add_to_meta_counter (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len)
+{
+ struct GNUNET_CONTAINER_MultiHashMap *mcm = cls;
+ struct MetaCounter *cnt;
+ GNUNET_HashCode hc;
+ size_t mlen;
+ size_t dlen;
+
+ if ( (format != EXTRACTOR_METAFORMAT_UTF8) &&
+ (format != EXTRACTOR_METAFORMAT_C_STRING) )
+ return 0;
+ dlen = strlen (data) + 1;
+ GNUNET_CRYPTO_hash (data,
+ dlen - 1,
+ &hc);
+ cnt = GNUNET_CONTAINER_multihashmap_get (mcm, &hc);
+ if (cnt == NULL)
+ {
+ mlen = strlen (data_mime_type) + 1;
+ cnt = GNUNET_malloc (sizeof (struct MetaCounter) +
+ dlen + mlen);
+ cnt->count = 1;
+ cnt->value = (const char *) &cnt[1];
+ cnt->value_mimetype = &cnt->value[dlen];
+ memcpy (&cnt[1],
+ data,
+ dlen);
+ memcpy ((char*) cnt->value_mimetype,
+ data_mime_type,
+ mlen);
+ cnt->type = type;
+ cnt->format = format;
+ GNUNET_CONTAINER_multihashmap_put (mcm,
+ &hc,
+ cnt,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+
+ }
+ else
+ {
+ cnt->count++;
+ if (cnt->format == EXTRACTOR_METAFORMAT_C_STRING)
+ cnt->format = format; /* possibly improve to UTF8 */
+ if (cnt->type == EXTRACTOR_METATYPE_UNKNOWN)
+ cnt->type = type;
+ }
+ return 0;
+}
+
+
+/**
+ * Extract metadata from a file and add it to the metamap and
+ * the metacounter.
+ *
+ * @param adc context to modify
+ * @param filename name of the file to process
+ */
+static void
+extract_file (struct AddDirContext *adc,
+ const char *filename)
+{
+ struct PublishData *pd;
+ GNUNET_HashCode hc;
+ const char *short_fn;
+ const char *ss;
+
+ adc->dir_entry_count++;
+ pd = GNUNET_malloc (sizeof (struct PublishData));
+ pd->meta = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_FS_meta_data_extract_from_file (pd->meta,
+ filename,
+ GNUNET_FS_GTK_get_le_plugins());
+ GNUNET_CONTAINER_meta_data_delete (pd->meta,
+ EXTRACTOR_METATYPE_FILENAME,
+ NULL, 0);
+ short_fn = filename;
+ while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
+ short_fn = 1 + ss;
+ GNUNET_CONTAINER_meta_data_insert (pd->meta,
+ "<gnunet-gtk>",
+ EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METAFORMAT_UTF8,
+ "text/plain",
+ short_fn,
+ strlen(short_fn)+1);
+
+
+ gtk_tree_store_insert_before (adc->ts,
+ &pd->iter,
+ adc->parent,
+ NULL);
+ GNUNET_CRYPTO_hash (filename,
+ strlen (filename),
+ &hc);
+ GNUNET_CONTAINER_multihashmap_put (adc->metamap,
+ &hc,
+ pd,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ GNUNET_CONTAINER_meta_data_iterate (pd->meta,
+ &add_to_meta_counter,
+ adc->metacounter);
+}
+
+
+/**
+ * Remove the keyword from the ksk URI.
+ *
+ * @param cls the ksk uri
+ * @param keyword the word to remove
+ * @param is_mandatory ignored
+ * @return always GNUNET_OK
+ */
+static int
+remove_keyword (void *cls,
+ const char *keyword,
+ int is_mandatory)
+{
+ struct GNUNET_FS_Uri *ksk = cls;
+
+ GNUNET_FS_uri_ksk_remove_keyword (ksk, keyword);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Add the specifics of the given entry to the tree store.
+ * Derive KSK from the given meta data, but exclude meta
+ * data given in "md_no_ksk" for keyword generation.
+ *
+ * @param ts tree store to modify
+ * @param iter position in the tree store for this file
+ * @param filename file to add
+ * @param bo block options
+ * @param do_index should we index or insert?
+ * @param md_no_ksk metadata with keywords NOT to add
+ * @param meta metadata for the file
+ */
+static void
+add_entry_to_ts (GtkTreeStore *ts,
+ GtkTreeIter *iter,
+ const char *filename,
+ const struct GNUNET_FS_BlockOptions *bo,
+ int do_index,
+ struct GNUNET_CONTAINER_MetaData *md_no_ksk,
+ struct GNUNET_CONTAINER_MetaData *meta)
+{
+ char *file_size_fancy;
+ struct GNUNET_FS_FileInformation *fi;
+ GtkTreeRowReference *row_reference;
+ GtkTreePath *path;
+ uint64_t file_size;
+ struct GNUNET_FS_Uri *ksk_uri;
+ struct GNUNET_FS_Uri *kill_ksk;
+ const char *ss;
+ const char *short_fn;
+ struct stat sbuf;
+
+ if (0 != STAT (filename, &sbuf))
+ return;
+ if (S_ISDIR (sbuf.st_mode))
+ {
+ file_size = 0;
+ }
+ else
+ {
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename,
+ &file_size,
+ GNUNET_YES))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ }
+ ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
+ kill_ksk = GNUNET_FS_uri_ksk_create_from_meta_data (md_no_ksk);
+ if (kill_ksk != NULL)
+ {
+ GNUNET_FS_uri_ksk_get_keywords (kill_ksk,
+ &remove_keyword,
+ ksk_uri);
+ GNUNET_FS_uri_destroy (kill_ksk);
+ }
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
+ iter);
+ row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
+ path);
+ gtk_tree_path_free (path);
+ if (S_ISDIR (sbuf.st_mode))
+ {
+ GNUNET_CONTAINER_meta_data_delete (meta,
+ EXTRACTOR_METATYPE_MIMETYPE,
+ NULL, 0);
+ GNUNET_FS_meta_data_make_directory (meta);
+ GNUNET_FS_uri_ksk_add_keyword (ksk_uri,
+ GNUNET_FS_DIRECTORY_MIME,
+ GNUNET_NO);
+ fi = GNUNET_FS_file_information_create_empty_directory
(GNUNET_FS_GTK_get_fs_handle (),
+ row_reference,
+ ksk_uri,
+ meta,
+ bo);
+ }
+ else
+ {
+ fi = GNUNET_FS_file_information_create_from_file
(GNUNET_FS_GTK_get_fs_handle (),
+ row_reference,
+ filename,
+ ksk_uri,
+ meta,
+ do_index,
+ bo);
+ }
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ GNUNET_FS_uri_destroy (ksk_uri);
+ if (S_ISDIR (sbuf.st_mode))
+ file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
+ else
+ file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
+ short_fn = filename;
+ while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
+ short_fn = 1 + ss;
+ gtk_tree_store_set (ts, iter,
+ 0, file_size_fancy,
+ 1, (gboolean) do_index,
+ 2, short_fn,
+ 3, (guint) bo->anonymity_level,
+ 4, (guint) bo->content_priority,
+ 5, fi,
+ -1);
+ GNUNET_free (file_size_fancy);
+}
+
+
+/**
+ * Function called by the directory iterator to
+ * (recursively) add all of the files in the
+ * directory to the tree.
+ *
+ * @param cls the 'struct AddDirContext*' we're in
+ * @param filename file or directory to scan
+ */
+static int
+publish_entry (void *cls,
+ const char *filename)
+{
+ struct AddDirContext *adc = cls;
+ struct PublishData *pd;
+ GNUNET_HashCode hc;
+
+ GNUNET_CRYPTO_hash (filename,
+ strlen (filename),
+ &hc);
+ pd = GNUNET_CONTAINER_multihashmap_get (adc->metamap,
+ &hc);
+ add_entry_to_ts (adc->ts,
+ &pd->iter,
+ filename,
+ &adc->bo,
+ adc->do_index,
+ adc->no_ksk,
+ pd->meta);
+ GNUNET_CONTAINER_multihashmap_remove (adc->metamap,
+ &hc,
+ pd);
+ GNUNET_free (pd);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Context passed to 'migrate_and_drop'.
+ */
+struct MetaProcessContext
+{
+ /**
+ * Metadata with all the keywords we migrated to the parent.
+ */
+ struct GNUNET_CONTAINER_MetaData *md;
+
+ /**
+ * How often does a keyword have to occur to be
+ * migrated to the parent?
+ */
+ unsigned int threshold;
+};
+
+
+/**
+ * Copy "frequent" meta data entries over to the
+ * target meta data struct, free the counters.
+ *
+ */
+static int
+migrate_and_drop (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct MetaProcessContext *mpc = cls;
+ struct MetaCounter *counter = value;
+
+ if (counter->count >= mpc->threshold)
+ {
+ GNUNET_CONTAINER_meta_data_insert (mpc->md,
+ "<gnunet-gtk>",
+ counter->type,
+ counter->format,
+ counter->value_mimetype,
+ counter->value,
+ strlen (counter->value)+1);
+ }
+ GNUNET_free (counter);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Go over the collected meta data from all entries in the
+ * directory and push common meta data up one level (by
+ * adding it to the returned struct).
+ *
+ * @param adc collection of child meta data
+ * @return meta data to moved to parent
+ */
+static struct GNUNET_CONTAINER_MetaData *
+process_metadata (struct AddDirContext *adc)
+{
+ struct MetaProcessContext mpc;
+
+ mpc.md = GNUNET_CONTAINER_meta_data_create ();
+ mpc.threshold = (adc->dir_entry_count + 1) / 2; /* 50% */
+ GNUNET_CONTAINER_multihashmap_iterate (adc->metacounter,
+ &migrate_and_drop,
+ &mpc);
+ GNUNET_CONTAINER_multihashmap_destroy (adc->metacounter);
+ return mpc.md;
+}
+
+
+/**
+ * Function called by the directory iterator to
+ * (recursively) add all of the files in the
+ * directory to the tree.
+ *
+ * @param cls the 'struct AddDirContext*' we're in
+ * @param filename file or directory to scan
+ */
+static int
+scan_directory (void *cls,
+ const char *filename)
+
+{
+ struct AddDirContext *adc = cls;
+ struct stat sbuf;
+ GtkTreeIter *parent;
+ struct PublishData *pd;
+ GNUNET_HashCode hc;
+ struct GNUNET_CONTAINER_MultiHashMap *mhm;
+ struct GNUNET_CONTAINER_MultiHashMap *mcm;
+ unsigned int pc;
+
+ if (0 != STAT (filename, &sbuf))
+ return GNUNET_OK;
+ if (S_ISDIR (sbuf.st_mode))
+ {
+ parent = adc->parent;
+ mhm = adc->metamap;
+ mcm = adc->metacounter;
+ pc = adc->dir_entry_count;
+ adc->metamap = GNUNET_CONTAINER_multihashmap_create (1024);
+ adc->metacounter = GNUNET_CONTAINER_multihashmap_create (1024);
+ adc->dir_entry_count = 0;
+ pd = GNUNET_malloc (sizeof (struct PublishData));
+ gtk_tree_store_insert_before (adc->ts,
+ &pd->iter,
+ parent,
+ NULL);
+ adc->parent = &pd->iter;
+ GNUNET_DISK_directory_scan (filename,
+ &scan_directory,
+ adc);
+ pd->meta = process_metadata (adc);
+ adc->no_ksk = pd->meta;
+ GNUNET_DISK_directory_scan (filename,
+ &publish_entry,
+ adc);
+ GNUNET_CONTAINER_multihashmap_destroy (adc->metamap);
+ adc->metamap = mhm;
+ adc->metacounter = mcm;
+ adc->parent = parent;
+ adc->dir_entry_count = pc + 1;
+ if (adc->metamap != NULL)
+ {
+ GNUNET_CRYPTO_hash (filename,
+ strlen (filename),
+ &hc);
+ GNUNET_CONTAINER_multihashmap_put (adc->metamap,
+ &hc,
+ pd,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ GNUNET_CONTAINER_meta_data_iterate (pd->meta,
+ &add_to_meta_counter,
+ mcm);
+ }
+ else
+ {
+ GNUNET_assert (mcm == NULL);
+ /* we're top-level */
+ add_entry_to_ts (adc->ts,
+ &pd->iter,
+ filename,
+ &adc->bo,
+ adc->do_index,
+ NULL,
+ pd->meta);
+ }
+ }
+ else
+ {
+ GNUNET_assert (adc->metamap != NULL);
+ extract_file (adc, filename);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Add a directory to the tree model.
+ *
+ * @param filename directory name to add
+ * @param bo block options
+ * @param do_index should we index?
+ */
+static void
+add_dir (const char *filename,
+ const struct GNUNET_FS_BlockOptions *bo,
+ int do_index)
+{
+ struct stat sbuf;
+ struct AddDirContext scan_ctx;
+
+ if (0 != STAT (filename, &sbuf))
+ return;
+ if (! S_ISDIR (sbuf.st_mode))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ memset (&scan_ctx, 0, sizeof (scan_ctx));
+ scan_ctx.bo = *bo;
+ scan_ctx.do_index = do_index;
+ scan_ctx.ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_file_sharing_publishing_tree_store"));
+ scan_directory (&scan_ctx, filename);
+}
+
+
+/* ************ code for adding directories ends here ************* */
+
+
+static void
+selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ update_selectivity ();
+}
+
+
+static void
+remove_old_entry (GtkTreeStore *ts,
+ GtkTreeIter *root)
+{
+ GtkTreeIter child;
+
+ while (TRUE == gtk_tree_model_iter_children (GTK_TREE_MODEL (ts),
+ &child, root))
+ remove_old_entry (ts, &child);
+ gtk_tree_store_remove (ts, root);
+}
+
+
+/**
+ * Move an entry in the tree.
+ */
+static void
+move_entry (GtkTreeModel *tm,
+ GtkTreeIter *old,
+ GtkTreeIter *newpos,
+ int dsel)
+{
+ struct GNUNET_FS_FileInformation *fip;
+ GtkTreeView *tv;
+ gint do_index;
+ gchar *short_fn;
+ guint anonymity_level;
+ guint priority;
+ char *fsf;
+ GtkTreePath *path;
+ GtkTreeSelection *sel;
+ GtkTreeIter child;
+ GtkTreeIter cnewpos;
+ GtkTreeRowReference *rr;
+ GtkTreeRowReference *rr2;
+
+ gtk_tree_model_get (tm,
+ old,
+ 0, &fsf,
+ 1, &do_index,
+ 2, &short_fn,
+ 3, &anonymity_level,
+ 4, &priority,
+ 5, &fip,
+ -1);
+ gtk_tree_store_set (GTK_TREE_STORE (tm), newpos,
+ 0, fsf,
+ 1, do_index,
+ 2, short_fn,
+ 3, (guint)anonymity_level,
+ 4, (guint) priority,
+ 5, fip,
+ -1);
+ sel = NULL;
+ tv = NULL;
+ if (dsel == GNUNET_YES)
+ {
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ path = gtk_tree_model_get_path (tm, newpos);
+ rr = gtk_tree_row_reference_new (tm, path);
+ gtk_tree_path_free (path);
+ }
+ else
+ {
+ rr = NULL;
+ }
+ if (TRUE == gtk_tree_model_iter_children (tm, &child, old))
+ {
+ do
+ {
+ path = gtk_tree_model_get_path (tm, &child);
+ rr2 = gtk_tree_row_reference_new (tm, path);
+ gtk_tree_path_free (path);
+ gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
+ &cnewpos, newpos, NULL);
+ move_entry (tm, &child, &cnewpos, GNUNET_NO);
+ path = gtk_tree_row_reference_get_path (rr2);
+ gtk_tree_row_reference_free (rr2);
+ GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
+ &child,
+ path));
+ gtk_tree_path_free (path);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &child));
+ }
+ g_free (short_fn);
+ g_free (fsf);
+ if (dsel == GNUNET_YES)
+ {
+ path = gtk_tree_row_reference_get_path (rr);
+ gtk_tree_row_reference_free (rr);
+ gtk_tree_view_expand_to_path (tv, path);
+ GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
+ newpos,
+ path));
+ gtk_tree_path_free (path);
+ gtk_tree_selection_select_iter (sel,
+ newpos);
+ }
+ update_selectivity ();
+}
+
+/**
+ * User has changed the "current" identifier for the content in
+ * the GtkTreeView. Update the model.
+ */
+void
+GNUNET_GTK_master_publish_dialog_pseudonym_updates_renderer_edited_cb
(GtkCellRendererText *renderer,
+ gchar
*cpath,
+ gchar
*new_text,
+ gpointer
user_data)
+{
+ GtkTreeIter iter;
+ GtkTreeStore *ts;
+
+ ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_pseudonym_tree_store"));
+
+ if (TRUE !=
+ gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_set (ts, &iter, 5, new_text, -1);
+ update_selectivity ();
+}
+
+
+/**
+ * User has changed the "current" identifier for the content in
+ * the GtkTreeView. Update the model.
+ */
+void
+GNUNET_GTK_master_publish_dialog_pseudonym_identifier_renderer_edited_cb
(GtkCellRendererText *renderer,
+ gchar
*cpath,
+ gchar
*new_text,
+
gpointer user_data)
+{
+ GtkTreeIter iter;
+ GtkTreeStore *ts;
+
+ ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_pseudonym_tree_store"));
+
+ if (TRUE !=
+ gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_set (ts, &iter, 2, new_text, -1);
+ update_selectivity ();
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ GtkTreeIter prev;
+ GtkTreeIter pos;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
+ {
+ GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred,
&parent));
+ }
+ else if (TRUE != gtk_tree_model_get_iter_first (tm, &pred))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ /* iterate over 'next' of pred to find out who our predecessor is! */
+ memset (&prev, 0, sizeof (GtkTreeIter));
+ while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
+ {
+ prev = pred;
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
+ }
+ gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
+ &pos, &prev, NULL);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (tm, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (tm), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pos;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE != gtk_tree_model_iter_parent (tm, &parent, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
+ &pos, NULL, &parent);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (tm, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (tm), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ GtkTreeIter prev;
+ GtkTreeIter *pprev;
+ GtkTreeIter pos;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
+ {
+ GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred,
&parent));
+ pprev = &parent;
+ }
+ else if (TRUE == gtk_tree_model_get_iter_first (tm, &pred))
+ {
+ pprev = NULL;
+ }
+ else
+ {
+ GNUNET_break (0);
+ return;
+ }
+ /* iterate over 'next' of pred to find out who our predecessor is! */
+ while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
+ {
+ prev = pred;
+ pprev = &prev;
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
+ }
+ gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
+ &pos, NULL, pprev);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (tm, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (tm), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter next;
+ GtkTreeIter pos;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &next))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &next));
+ gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
+ &pos, NULL, &next);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (tm, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (tm), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeIter pos;
+ struct GNUNET_FS_BlockOptions bo;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ /* FIXME: consider opening a dialog to get
+ * anonymity, priority and expiration prior
+ * to calling this function (currently we
+ * use default values for those).
+ */
+ bo.anonymity_level = 1;
+ bo.content_priority = 1000;
+ bo.expiration_time = GNUNET_TIME_relative_to_absolute
(GNUNET_TIME_UNIT_YEARS);
+ bo.replication_level = 1;
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ NULL,
+ &iter))
+ {
+ create_dir_at_iter ("unnamed/",
+ &bo,
+ NULL, &pos);
+ return;
+ }
+ create_dir_at_iter ("unnamed/",
+ &bo,
+ &iter, &pos);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ GtkBuilder *builder;
+ char *filename;
+ struct GNUNET_FS_BlockOptions bo;
+ int do_index;
+ GtkSpinButton *sb;
+
+ builder = GNUNET_GTK_get_new_builder ("publish-file-dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+ "GNUNET_GTK_publish_file_dialog"));
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ return;
+ }
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
+ sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
+ bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_file_dialog_anonymity_spin_button")));
+ bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_file_dialog_priority_spin_button")));
+ bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
+ bo.replication_level = 1; /* FIXME... */
+ do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
+ add_file_at_iter (filename,
+ &bo, do_index,
+ NULL);
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ g_free (filename);
+ update_selectivity ();
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ int do_index;
+ guint anonymity_level;
+ guint priority;
+ gchar *short_fn;
+ struct GNUNET_FS_FileInformation *fip;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm,
+ &iter,
+ 1, &do_index,
+ 2, &short_fn,
+ 3, &anonymity_level,
+ 4, &priority,
+ 5, &fip,
+ -1);
+ GNUNET_GTK_edit_publish_dialog (&do_index,
+ &short_fn,
+ &anonymity_level,
+ &priority,
+ fip);
+ gtk_tree_store_set (GTK_TREE_STORE (tm),
+ &iter,
+ 1, do_index,
+ 2, short_fn,
+ 3, anonymity_level,
+ 4, priority,
+ -1);
+ g_free (short_fn);
+}
+
+
+/**
+ * Free row reference stored in the file information's
+ * client-info pointer.
+ */
+static int
+free_fi_row_reference (void *cls,
+ struct GNUNET_FS_FileInformation *fi,
+ uint64_t length,
+ struct GNUNET_CONTAINER_MetaData *meta,
+ struct GNUNET_FS_Uri **uri,
+ struct GNUNET_FS_BlockOptions *bo,
+ int *do_index,
+ void **client_info)
+{
+ GtkTreeRowReference *row = *client_info;
+
+ if (row == NULL)
+ {
+ GNUNET_break (0);
+ return GNUNET_OK;
+ }
+ gtk_tree_row_reference_free (row);
+ return GNUNET_OK;
+}
+
+
+
+void
+GNUNET_GTK_master_publish_dialog_delete_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ struct GNUNET_FS_FileInformation *fip;
+
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ if (TRUE != gtk_tree_selection_get_selected (sel,
+ &tm,
+ &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (tm,
+ &iter,
+ 5, &fip,
+ -1);
+ GNUNET_FS_file_information_destroy (fip,
+ &free_fi_row_reference,
+ NULL);
+ gtk_tree_store_remove (GTK_TREE_STORE (tm),
+ &iter);
+ update_selectivity ();
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ GtkBuilder *builder;
+ char *filename;
+ int do_index;
+ GtkSpinButton *sb;
+ struct GNUNET_FS_BlockOptions bo;
+
+ builder = GNUNET_GTK_get_new_builder ("publish-directory-dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (builder);
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_directory_dialog"));
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ return;
+ }
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
+ sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
+ bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_directory_dialog_anonymity_spin_button")));
+ bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_directory_dialog_priority_spin_button")));
+ bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
+ do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(gtk_builder_get_object (builder,
+
"GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")));
+
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ /* FIXME: open progress dialog here... */
+ add_dir (filename, &bo, do_index);
+ g_free (filename);
+ update_selectivity ();
+}
+
+
+/**
+ * Get the file information struct corresponding to the
+ * given iter in the publish dialog tree model. Recursively
+ * builds the file information struct from the subtree.
+ *
+ * @param tm model to grab fi from
+ * @param iter position to grab fi from
+ * @return file information from the given position (never NULL)
+ */
+static struct GNUNET_FS_FileInformation *
+get_file_information (GtkTreeModel *tm,
+ GtkTreeIter *iter)
+{
+ struct GNUNET_FS_FileInformation *fi;
+ struct GNUNET_FS_FileInformation *fic;
+ GtkTreeIter child;
+
+ gtk_tree_model_get (tm, iter,
+ 5, &fi,
+ -1);
+ gtk_tree_store_set (GTK_TREE_STORE (tm), iter,
+ 5, NULL,
+ -1);
+ GNUNET_assert (fi != NULL);
+ if (gtk_tree_model_iter_children (tm, &child, iter))
+ {
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_FS_file_information_is_directory (fi));
+ do
+ {
+ fic = get_file_information (tm, &child);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_FS_file_information_add (fi, fic));
+ }
+ while (gtk_tree_model_iter_next (tm, &child));
+ }
+ return fi;
+}
+
+
+/**
+ * Closure for 'add_updateable_to_ts'.
+ */
+struct UpdateableContext
+{
+ /**
+ * Parent of current insertion.
+ */
+ GtkTreeIter *parent;
+
+ /**
+ * Tree store we are modifying.
+ */
+ GtkTreeStore *ts;
+
+ /**
+ * Name of the namespace.
+ */
+ const char *namespace_name;
+
+ /**
+ * Handle to the namespace.
+ */
+ struct GNUNET_FS_Namespace *ns;
+
+ /**
+ * Hash codes of identifiers already added to tree store.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *seen;
+
+ /**
+ * Did the iterator get called?
+ */
+ int update_called;
+};
+
+
+/**
+ * Add updateable entries to the tree view.
+ *
+ * @param cls closure
+ * @param last_id ID to add
+ * @param last_uri associated URI
+ * @param last_meta associate meta data
+ * @param next_id ID for future updates
+ */
+static void
+add_updateable_to_ts (void *cls,
+ const char *last_id,
+ const struct GNUNET_FS_Uri *last_uri,
+ const struct GNUNET_CONTAINER_MetaData *last_meta,
+ const char *next_id)
+{
+ struct UpdateableContext *uc = cls;
+ struct UpdateableContext sc;
+ GtkTreeIter iter;
+ GtkTreeIter titer;
+ char *desc;
+ GNUNET_HashCode hc;
+
+ uc->update_called = GNUNET_YES;
+ GNUNET_CRYPTO_hash (last_id,
+ strlen (last_id),
+ &hc);
+ if (NULL !=
+ GNUNET_CONTAINER_multihashmap_get (uc->seen,
+ &hc))
+ return;
+ GNUNET_CONTAINER_multihashmap_put (uc->seen,
+ &hc,
+ "dummy",
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ desc = GNUNET_CONTAINER_meta_data_get_first_by_types (last_meta,
+
EXTRACTOR_METATYPE_DESCRIPTION,
+
EXTRACTOR_METATYPE_TITLE,
+
EXTRACTOR_METATYPE_BOOK_TITLE,
+
EXTRACTOR_METATYPE_FILENAME,
+
EXTRACTOR_METATYPE_SUMMARY,
+
EXTRACTOR_METATYPE_ALBUM,
+
EXTRACTOR_METATYPE_COMMENT,
+
EXTRACTOR_METATYPE_SUBJECT,
+ -1);
+ gtk_tree_store_insert_with_values (uc->ts,
+ &iter,
+ uc->parent,
+ G_MAXINT,
+ 0, uc->namespace_name,
+ 1, uc->ns,
+ 2, last_id,
+ 3, GNUNET_FS_uri_dup (last_uri),
+ 4, GNUNET_CONTAINER_meta_data_duplicate
(last_meta),
+ 5, "",
+ 6, desc,
+ 7, TRUE /* update editable (always) */,
+ 8, FALSE /* current not editable (only for
top-level) */,
+ -1);
+ GNUNET_free_non_null (desc);
+ sc.parent = &iter;
+ sc.ts = uc->ts;
+ sc.namespace_name = uc->namespace_name;
+ sc.ns = uc->ns;
+ sc.seen = uc->seen;
+ sc.update_called = GNUNET_NO;
+ GNUNET_FS_namespace_list_updateable (uc->ns,
+ next_id,
+ &add_updateable_to_ts,
+ &sc);
+ if ( (sc.update_called == GNUNET_NO) &&
+ (next_id != NULL) &&
+ (strlen (next_id) > 0) )
+ {
+ /* add leaf */
+ gtk_tree_store_insert_with_values (uc->ts,
+ &titer,
+ &iter,
+ G_MAXINT,
+ 0, uc->namespace_name,
+ 1, uc->ns,
+ 2, next_id,
+ 3, NULL,
+ 4, NULL,
+ 5, "",
+ 6, "",
+ 7, TRUE /* update editable (always) */,
+ 8, FALSE /* current not editable (only
for top-level) */,
+ -1);
+ }
+}
+
+
+/**
+ * Add all updateable entries of the current namespace to the
+ * tree store.
+ *
+ * @param cls the 'GtkTreeStore' to update
+ * @param name name of the namespace to add
+ * @param id identity of the namespace to add
+ */
+static void
+add_namespace_to_ts (void *cls,
+ const char *name,
+ const GNUNET_HashCode *id)
+{
+ GtkTreeStore *ts = cls;
+ struct UpdateableContext uc;
+ GtkTreeIter iter;
+
+ uc.parent = &iter;
+ uc.namespace_name = name;
+ uc.ts = ts;
+ uc.ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (),
+ name);
+ uc.update_called = GNUNET_NO;
+ gtk_tree_store_insert_with_values (ts, &iter,
+ NULL,
+ G_MAXINT,
+ 0, name,
+ 1, uc.ns,
+ 2, NULL /* last-id */,
+ 3, NULL /* last-uri */,
+ 4, NULL /* meta */,
+ 5, NULL /* next-ID */,
+ 6, NULL /* last-description */,
+ 7, TRUE /* update editable */,
+ 8, TRUE /* current editable */,
+ -1);
+ uc.seen = GNUNET_CONTAINER_multihashmap_create (128);
+ GNUNET_FS_namespace_list_updateable (uc.ns, NULL,
+ &add_updateable_to_ts, &uc);
+ GNUNET_CONTAINER_multihashmap_destroy (uc.seen);
+}
+
+
+static void
+free_pseudonym_tree_store (GtkTreeModel *tm,
+ GtkTreeIter *iter)
+{
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ struct GNUNET_FS_Namespace *ns;
+ GtkTreeIter child;
+
+ gtk_tree_model_get (tm,
+ iter,
+ 1, &ns,
+ 3, &uri,
+ 4, &meta,
+ -1);
+ if (uri != NULL)
+ GNUNET_FS_uri_destroy (uri);
+ if (meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ if (ns != NULL)
+ {
+ // FIXME: delete ns?
+ // GNUNET_FS_namespace_delete (nso, GNUNET_NO);
+ }
+ if (TRUE ==
+ gtk_tree_model_iter_children (tm, &child, iter))
+ {
+ do
+ {
+ free_pseudonym_tree_store (tm,
+ &child);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm,
+ &child));
+ }
+}
+
+
+static void
+free_file_information_tree_store (GtkTreeModel *tm,
+ GtkTreeIter *iter)
+{
+ GtkTreeIter child;
+ struct GNUNET_FS_FileInformation *fip;
+
+ gtk_tree_model_get (tm,
+ iter,
+ 5, &fip,
+ -1);
+ if (fip != NULL)
+ GNUNET_FS_file_information_destroy (fip, NULL, NULL);
+ if (TRUE ==
+ gtk_tree_model_iter_children (tm, &child, iter))
+ {
+ do
+ {
+ free_file_information_tree_store (tm,
+ &child);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm,
+ &child));
+ }
+}
+
+
+/**
+ */
+void
+GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ GtkTreeStore *ts;
+ gint ret;
+ GtkTreeView *tv;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ struct GNUNET_FS_FileInformation *fi;
+ GtkTreeModel *tm;
+ GtkTreeModel *ptm;
+ struct GNUNET_FS_Namespace *namespace;
+ gchar *namespace_id;
+ gchar *namespace_uid;
+
+ GNUNET_assert (master_builder == NULL);
+ master_builder = GNUNET_GTK_get_new_builder ("publish_dialog.glade");
+ if (master_builder == NULL)
+ return;
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(selection_changed_cb), NULL);
+ ad = GTK_WIDGET (gtk_builder_get_object (master_builder,
+ "GNUNET_GTK_master_publish_dialog"));
+ ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_pseudonym_tree_store"));
+ GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
+ &add_namespace_to_ts,
+ ts);
+ tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_file_sharing_publishing_tree_store"));
+ tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
+ sel = gtk_tree_view_get_selection (tv);
+ g_signal_connect(G_OBJECT(sel), "changed",
+ G_CALLBACK(selection_changed_cb), NULL);
+ ret = gtk_dialog_run (GTK_DIALOG (ad));
+ if (ret == GTK_RESPONSE_OK)
+ {
+ if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
+ {
+ gtk_tree_model_get (ptm,
+ &iter,
+ 1, &namespace,
+ 2, &namespace_id,
+ 5, &namespace_uid,
+ -1);
+ }
+ else
+ {
+ namespace = NULL;
+ namespace_id = NULL;
+ namespace_uid = NULL;
+ }
+ if (gtk_tree_model_get_iter_first (tm, &iter))
+ do
+ {
+ fi = get_file_information (tm, &iter);
+ GNUNET_FS_publish_start (GNUNET_FS_GTK_get_fs_handle (),
+ fi,
+ namespace,
+ namespace_id,
+ namespace_uid,
+ GNUNET_FS_PUBLISH_OPTION_NONE);
+ }
+ while (gtk_tree_model_iter_next (tm, &iter));
+ if (namespace_id != NULL)
+ g_free (namespace_id);
+ if (namespace_uid != NULL)
+ g_free (namespace_uid);
+ }
+ ptm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
+
"GNUNET_GTK_pseudonym_tree_store"));
+ /* free state from 'ptm' */
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (ptm,
+ &iter))
+ do
+ {
+ free_pseudonym_tree_store (ptm,
+ &iter);
+ }
+ while (TRUE == gtk_tree_model_iter_next (ptm,
+ &iter));
+
+ /* free state from 'tm' */
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (tm,
+ &iter))
+ do
+ {
+ free_file_information_tree_store (tm,
+ &iter);
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm,
+ &iter));
+
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (master_builder));
+ master_builder = NULL;
+}
+
+
+/* end of main_window_file_publish.c */
Copied: gnunet-gtk/src/fs/main_window_file_search.c (from rev 16478,
gnunet-gtk/src/main_window_file_search.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_file_search.c (rev 0)
+++ gnunet-gtk/src/fs/main_window_file_search.c 2011-08-15 14:11:40 UTC (rev
16543)
@@ -0,0 +1,243 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_file_search.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+
+/**
+ * Builder used for the search dialog.
+ */
+static GtkBuilder *builder;
+
+
+/**
+ * User double-clicked on namespace or pressed enter;
+ * move namespace root to the 'keywords' line.
+ */
+void
+GNUNET_GTK_search_dialog_namespace_tree_view_row_activated_cb (GtkTreeView
*tree_view,
+ GtkTreePath
*path,
+
GtkTreeViewColumn *column,
+ gpointer
user_data)
+{
+ GtkTreeModel *ls;
+ GtkTreeSelection *sel;
+ GtkEntry *query;
+ GtkTreeIter iter;
+ char *root;
+
+ query = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_search_dialog_keyword_entry"));
+ sel = gtk_tree_view_get_selection (tree_view);
+ if (TRUE ==
+ gtk_tree_selection_get_selected (sel,
+ &ls,
+ &iter))
+ {
+ gtk_tree_model_get (ls, &iter,
+ 1, &root,
+ -1);
+ gtk_entry_set_text (query,
+ root);
+ GNUNET_free (root);
+ }
+}
+
+
+void
+GNUNET_GTK_search_dialog_search_button_clicked_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkEntry *query;
+ GtkSpinButton *anonymity;
+ GtkTreeView *namespace;
+ const char *keywords;
+ char *emsg;
+ struct GNUNET_FS_Uri *uri;
+ GNUNET_HashCode *nsid;
+ GtkTreeModel *ls;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+
+ query = GTK_ENTRY (gtk_builder_get_object (builder,
+
"GNUNET_GTK_search_dialog_keyword_entry"));
+ anonymity = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
+
"GNUNET_GTK_search_dialog_anonymity_spin_button"));
+ namespace = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+
"GNUNET_GTK_search_dialog_namespace_tree_view"));
+ keywords = gtk_entry_get_text (query);
+ nsid = NULL;
+ sel = gtk_tree_view_get_selection (namespace);
+ if (TRUE ==
+ gtk_tree_selection_get_selected (sel,
+ &ls,
+ &iter))
+ gtk_tree_model_get (ls, &iter,
+ 2, &nsid,
+ -1);
+ if (nsid != NULL)
+ {
+ uri = GNUNET_FS_uri_sks_create_from_nsid (nsid,
+ keywords);
+ GNUNET_assert (uri != NULL);
+ }
+ else
+ {
+ emsg = NULL;
+ uri = GNUNET_FS_uri_ksk_create (keywords, &emsg);
+ if (uri == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid keyword string `%s': %s"),
+ keywords,
+ emsg);
+ GNUNET_free_non_null (emsg);
+ return;
+ }
+ }
+ GNUNET_FS_search_start (GNUNET_FS_GTK_get_fs_handle (),
+ uri,
+ gtk_spin_button_get_value_as_int (anonymity),
+ GNUNET_FS_SEARCH_OPTION_NONE,
+ NULL);
+ GNUNET_FS_uri_destroy (uri);
+}
+
+
+
+/**
+ * Add pseudonym data to list store
+ *
+ * @param cls closure (the 'GtkListStore')
+ * @param pseudonym hash code of public key of pseudonym
+ * @param md meta data known about the pseudonym
+ * @param rating the local rating of the pseudonym
+ * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
+ */
+static int
+add_namespace_to_ls (void *cls,
+ const GNUNET_HashCode *
+ pseudonym,
+ const struct
+ GNUNET_CONTAINER_MetaData * md,
+ int rating)
+{
+ GtkListStore *ls = cls;
+ char *root;
+ char *ns_name;
+ GNUNET_HashCode *nsid;
+ char *description;
+ char *uris;
+ char *emsg;
+ struct GNUNET_FS_Uri *uri;
+ GtkTreeIter iter;
+
+ ns_name = GNUNET_PSEUDONYM_id_to_name (GNUNET_FS_GTK_get_configuration (),
+ pseudonym);
+ nsid = GNUNET_malloc (sizeof (GNUNET_HashCode));
+ *nsid = *pseudonym;
+ root = NULL;
+ uris = GNUNET_CONTAINER_meta_data_get_by_type (md,
+ EXTRACTOR_METATYPE_URI);
+ if (uris != NULL)
+ {
+ emsg = NULL;
+ uri = GNUNET_FS_uri_parse (uris, &emsg);
+ if (uri == NULL)
+ GNUNET_free (emsg);
+ root = GNUNET_FS_uri_sks_get_content_id (uri);
+ GNUNET_FS_uri_destroy (uri);
+ }
+ description = GNUNET_CONTAINER_meta_data_get_first_by_types (md,
+
EXTRACTOR_METATYPE_TITLE,
+
EXTRACTOR_METATYPE_BOOK_TITLE,
+
EXTRACTOR_METATYPE_DESCRIPTION,
+
EXTRACTOR_METATYPE_SUMMARY,
+
EXTRACTOR_METATYPE_ALBUM,
+
EXTRACTOR_METATYPE_COMMENT,
+
EXTRACTOR_METATYPE_SUBJECT,
+
EXTRACTOR_METATYPE_KEYWORDS,
+ -1);
+ gtk_list_store_insert_with_values (ls,
+ &iter,
+ G_MAXINT,
+ 0, ns_name,
+ 1, root,
+ 2, nsid,
+ 3, description,
+ -1);
+ GNUNET_free (ns_name);
+ GNUNET_free_non_null (root);
+ GNUNET_free_non_null (description);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Search selected in 'file' menu.
+ */
+void
+GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ GtkWidget *ad;
+ GtkListStore *ls;
+ GtkTreeIter iter;
+ GNUNET_HashCode *nsid;
+
+ GNUNET_assert (builder == NULL);
+ builder = GNUNET_GTK_get_new_builder ("search_dialog.glade");
+ if (builder == NULL)
+ return;
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+ "GNUNET_GTK_search_dialog"));
+ ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
+
"GNUNET_GTK_namespace_list_store"));
+ GNUNET_PSEUDONYM_list_all (GNUNET_FS_GTK_get_configuration (),
+ &add_namespace_to_ls,
+ ls);
+ gtk_dialog_run (GTK_DIALOG (ad));
+
+ /* free nsids from 'ls' */
+ if (TRUE ==
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls),
+ &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (GTK_TREE_MODEL (ls),
+ &iter,
+ 2, &nsid,
+ -1);
+ GNUNET_free (nsid);
+ }
+ while (TRUE == gtk_tree_model_iter_next (GTK_TREE_MODEL (ls),
+ &iter));
+ }
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ builder = NULL;
+}
+
+/* end of main_window_file_search.c */
Copied: gnunet-gtk/src/fs/main_window_open_directory.c (from rev 16478,
gnunet-gtk/src/main_window_open_directory.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_open_directory.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_open_directory.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,147 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_open_directory.c
+ * @author Christian Grothoff
+ */
+#include "common.h"
+#include "fs_event_handler.h"
+
+struct AddChildContext
+{
+ const char *filename;
+ GtkTreeStore *ts;
+ struct SearchTab *tab;
+ struct SearchResult *par;
+ GtkTreeRowReference *prr;
+ GtkTreeIter iter;
+};
+
+
+/**
+ * Function used to process entries in a directory.
+ *
+ * @param cls closure, our 'struct AddChildContext*'
+ * @param filename name of the file in the directory
+ * @param uri URI of the file
+ * @param metadata metadata for the file; metadata for
+ * the directory if everything else is NULL/zero
+ * @param length length of the available data for the file
+ * (of type size_t since data must certainly fit
+ * into memory; if files are larger than size_t
+ * permits, then they will certainly not be
+ * embedded with the directory itself).
+ * @param data data available for the file (length bytes)
+ */
+static void
+add_child (void *cls,
+ const char *filename,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ size_t length,
+ const void *data)
+{
+ struct AddChildContext *acc = cls;
+ struct GNUNET_CONTAINER_MetaData *dmeta;
+ GtkTreePath *tp;
+ GtkTreeIter iter;
+
+ if (uri == NULL)
+ {
+ /* directory meta data itself */
+ dmeta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ GNUNET_CONTAINER_meta_data_insert (dmeta,
+ "<user>",
+ EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METAFORMAT_C_STRING,
+ "text/plain",
+ acc->filename,
+ strlen (acc->filename) + 1);
+ acc->tab = GNUNET_GTK_add_to_uri_tab (&acc->iter,
+ &acc->par,
+ dmeta,
+ NULL);
+ tp = gtk_tree_model_get_path (GTK_TREE_MODEL (acc->tab->ts),
+ &acc->iter);
+ acc->prr = gtk_tree_row_reference_new (GTK_TREE_MODEL (acc->tab->ts),
+ tp);
+ gtk_tree_path_free (tp);
+ acc->ts = acc->tab->ts;
+ GNUNET_CONTAINER_meta_data_destroy (dmeta);
+ return;
+ }
+ if (acc->ts == NULL)
+ return;
+ GNUNET_assert (NULL !=
+ GNUNET_GTK_add_search_result (acc->tab,
+ &iter,
+ acc->prr,
+ uri,
+ meta,
+ NULL,
+ 0));
+}
+
+
+/**
+ * User selected "Open directory" in menu. Display dialog, open
+ * file and then display a new tab with its contents.
+ */
+void
+GNUNET_GTK_main_menu_file_open_gnunet_directory_activate_cb (GtkWidget *
dummy,
+ gpointer data)
+{
+ struct AddChildContext acc;
+ GtkWidget *ad;
+ GtkBuilder *builder;
+ char *filename;
+ GtkFileFilter *ff;
+
+ builder = GNUNET_GTK_get_new_builder ("open_directory_dialog.glade");
+ if (builder == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ad = GTK_WIDGET (gtk_builder_get_object (builder,
+ "GNUNET_GTK_open_directory_dialog"));
+ ff = GTK_FILE_FILTER (gtk_builder_get_object (builder,
+ "gnunet_directory_filter"));
+ /* FIXME: some day, write a custom file filter for gnunet-directories... */
+ gtk_file_filter_add_pattern (ff, "*" GNUNET_FS_DIRECTORY_EXT);
+ if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
+ {
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ return;
+ }
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (builder));
+ acc.filename = filename;
+ acc.ts = NULL;
+ GNUNET_FS_GTK_mmap_and_scan (filename,
+ &add_child,
+ &acc);
+ g_free (filename);
+}
+
+/* end of main_window_open_directory.c */
Copied: gnunet-gtk/src/fs/main_window_view_toggles.c (from rev 16478,
gnunet-gtk/src/main_window_view_toggles.c)
===================================================================
--- gnunet-gtk/src/fs/main_window_view_toggles.c
(rev 0)
+++ gnunet-gtk/src/fs/main_window_view_toggles.c 2011-08-15 14:11:40 UTC
(rev 16543)
@@ -0,0 +1,90 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/main_window_view_toggles.c
+ * @author Christian Grothoff
+ *
+ * This file contains callbacks for the 'view' menu that toggle views.
+ */
+#include "common.h"
+#include "gnunet-fs-gtk.h"
+
+
+/**
+ * Toggle the visibility of a widget based on the checkeness
+ * of a menu item.
+ *
+ * @param toggled_widget name of widget to toggle
+ * @param toggle_menu name of menu entry
+ */
+static void
+toggle_view (const char *toggled_widget,
+ const char *toggle_menu)
+{
+ GtkCheckMenuItem *mi;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object (toggled_widget));
+ mi = GTK_CHECK_MENU_ITEM (GNUNET_FS_GTK_get_main_window_object
(toggle_menu));
+ if (gtk_check_menu_item_get_active (mi))
+ gtk_widget_show (widget);
+ else
+ gtk_widget_hide (widget);
+}
+
+
+/**
+ * Preview view is toggled.
+ */
+void
+GNUNET_GTK_main_menu_view_preview_toggled_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ toggle_view ("GNUNET_GTK_main_window_preview_image",
+ "GNUNET_GTK_main_menu_view_preview");
+}
+
+
+/**
+ * Neighbour view is toggled.
+ */
+void
+GNUNET_GTK_main_menu_view_neighbours_toggled_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ toggle_view ("GNUNET_GTK_main_window_peerinfo_treeview",
+ "GNUNET_GTK_main_menu_view_neighbours");
+}
+
+
+/**
+ * Metadata view is toggled.
+ */
+void
+GNUNET_GTK_main_menu_view_metadata_toggled_cb (GtkWidget * dummy,
+ gpointer data)
+{
+ toggle_view ("GNUNET_GTK_main_window_metadata_treeview",
+ "GNUNET_GTK_main_menu_view_metadata");
+}
+
+
+/* end of main_window_view_toggles.c */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r16543 - in gnunet-gtk/src: . fs,
gnunet <=