[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r19629 - gnunet-gtk/src/fs
From: |
gnunet |
Subject: |
[GNUnet-SVN] r19629 - gnunet-gtk/src/fs |
Date: |
Thu, 2 Feb 2012 14:28:32 +0100 |
Author: grothoff
Date: 2012-02-02 14:28:32 +0100 (Thu, 02 Feb 2012)
New Revision: 19629
Added:
gnunet-gtk/src/fs/gnunet-fs-gtk_about.c
gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.c
gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.h
gnunet-gtk/src/fs/gnunet-fs-gtk_common.c
gnunet-gtk/src/fs/gnunet-fs-gtk_common.h
gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c
gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h
gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c
gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h
gnunet-gtk/src/fs/gnunet-fs-gtk_publish-dialog.c
gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.c
gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.h
Removed:
gnunet-gtk/src/fs/gnunet-fs-gtk-about.c
gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.c
gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.h
gnunet-gtk/src/fs/gnunet-fs-gtk-common.c
gnunet-gtk/src/fs/gnunet-fs-gtk-common.h
gnunet-gtk/src/fs/gnunet-fs-gtk-download.c
gnunet-gtk/src/fs/gnunet-fs-gtk-download.h
gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.c
gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.h
gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c
gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.h
gnunet-gtk/src/fs/gnunet-fs-gtk-main_window_file_publish.c
Modified:
gnunet-gtk/src/fs/Makefile.am
Log:
-rename fest
Modified: gnunet-gtk/src/fs/Makefile.am
===================================================================
--- gnunet-gtk/src/fs/Makefile.am 2012-02-02 12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/Makefile.am 2012-02-02 13:28:32 UTC (rev 19629)
@@ -10,18 +10,18 @@
bin_PROGRAMS = gnunet-fs-gtk
gnunet_fs_gtk_SOURCES = \
- gnunet-fs-gtk-about.c \
- gnunet-fs-gtk-common.c gnunet-fs-gtk-common.h \
- gnunet-fs-gtk-download.c gnunet-fs-gtk-download.h \
- gnunet-fs-gtk-edit_publish_dialog.c gnunet-fs-gtk-edit_publish_dialog.h \
- gnunet-fs-gtk-event_handler.c gnunet-fs-gtk-event_handler.h \
- gnunet-fs-gtk-anonymity_spin_buttons.c
gnunet-fs-gtk-anonymity_spin_buttons.h \
+ gnunet-fs-gtk.c gnunet-fs-gtk.h \
+ gnunet-fs-gtk_about.c \
+ gnunet-fs-gtk_anonymity-widgets.c gnunet-fs-gtk_anonymity-widgets.h \
+ gnunet-fs-gtk_common.c gnunet-fs-gtk_common.h \
+ gnunet-fs-gtk_download-save-as.c gnunet-fs-gtk_download-save-as.h \
+ gnunet-fs-gtk_event-handler.c gnunet-fs-gtk_event-handler.h \
+ gnunet-fs-gtk_publish-dialog.c \
+ gnunet-fs-gtk_publish-edit-dialog.c gnunet-fs-gtk_publish-edit-dialog.h \
gnunet-fs-gtk-main_window_meta_data_context_menu.c \
- gnunet-fs-gtk.c gnunet-fs-gtk.h \
gnunet-fs-gtk-main_window_adv_pseudonym.c \
gnunet-fs-gtk-main_window_create_pseudonym.c \
gnunet-fs-gtk-main_window_file_download.c \
- gnunet-fs-gtk-main_window_file_publish.c \
gnunet-fs-gtk-main_window_namespace.c \
gnunet-fs-gtk-main_window_search.c \
gnunet-fs-gtk-main_window_open_directory.c \
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-about.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-about.c 2012-02-02 12:57:54 UTC (rev
19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-about.c 2012-02-02 13:28:32 UTC (rev
19629)
@@ -1,44 +0,0 @@
-/*
- 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/gnunet-fs-gtk-about.c
- * @author Christian Grothoff
- * @author Igor Wronsky
- *
- * This file contains the about dialog.
- */
-#include "gnunet_gtk.h"
-
-
-/**
- * This displays an about window
- *
- * @param widget widget creating the event, unused
- * @param data global builder, unused
- */
-void
-GNUNET_GTK_main_menu_help_about_activate_cb (GtkWidget * dummy, gpointer data)
-{
- GNUNET_GTK_display_about ("gnunet_fs_gtk_about_window.glade");
-}
-
-
-/* end of gnunet-fs-gtk-about.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.c 2012-02-02
12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.c 2012-02-02
13:28:32 UTC (rev 19629)
@@ -1,177 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2005, 2006, 2010, 2012 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-anonymtiy_spin_buttons.c
- * @author Christian Grothoff
- * @brief operations to manage user's anonymity level selections
- */
-#include "gnunet-fs-gtk-common.h"
-#include "gnunet-fs-gtk-anonymity_spin_buttons.h"
-#include <gdk/gdk.h>
-
-/**
- * Spin button is changed, update its color. NOTE: This function will
eventually
- * become obsolete as we migrate to the drop-down style of anonymity-level
selection.
- *
- * @param w the spin button that changed
- * @param builder's closure, unused
- */
-void
-GNUNET_GTK_anonymity_spin_button_value_changed_cb (GtkWidget * w, gpointer
data)
-{
-#ifdef GdkRBGA
- GtkSpinButton *spin;
- gint val;
- GdkRGBA bcolor;
- GdkRGBA 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_rgba_parse (&bcolor, "red")) &&
- (TRUE == gdk_rgba_parse (&fcolor, "black")))
- {
- gtk_widget_override_background_color (w, GTK_STATE_NORMAL, &bcolor);
- gtk_widget_override_color (w, GTK_STATE_NORMAL, &fcolor);
- }
- else
- {
- GNUNET_break (0);
- }
- }
- else
- {
- gtk_widget_override_background_color (w, GTK_STATE_NORMAL, NULL);
- gtk_widget_override_color (w, GTK_STATE_NORMAL, NULL);
- }
-#endif
-}
-
-
-/**
- * Obtain the numeric anonymity level selected by a GtkComboBox.
- *
- * @param builder builder for looking up widgets
- * @param combo_name name of the GtkComboBox with the anonymity selection
- * @param p_level where to store the anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_get_selected_anonymity_level (GtkBuilder * builder,
- gchar * combo_name, guint * p_level)
-{
- GtkComboBox *combo;
-
- combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, combo_name));
- if (!combo)
- return FALSE;
- return GNUNET_GTK_get_selected_anonymity_combo_level (combo, p_level);
-}
-
-
-/**
- * Obtain the numeric anonymity level selected by a GtkComboBox.
- *
- * @param combo the GtkComboBox with the anonymity selection
- * @param p_level where to store the anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_get_selected_anonymity_combo_level (GtkComboBox *combo, guint
*p_level)
-{
- GtkTreeIter iter;
- GtkTreeModel *model;
- guint level;
-
- if (! gtk_combo_box_get_active_iter (combo, &iter))
- return FALSE;
- model = gtk_combo_box_get_model (combo);
- if (!model)
- return FALSE;
- gtk_tree_model_get (model, &iter, 1, &level, -1);
- if (p_level)
- *p_level = level;
- return TRUE;
-}
-
-
-/**
- * Set the anonymity level displayed by a combo box.
- *
- * @param builder the builder of the combo box
- * @param combo_name name of the combo box
- * @param sel_level desired anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_select_anonymity_level (GtkBuilder * builder, gchar * combo_name,
- guint sel_level)
-{
- GtkComboBox *combo;
-
- combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, combo_name));
- if (!combo)
- return FALSE;
- return GNUNET_GTK_select_anonymity_combo_level (combo, sel_level);
-}
-
-
-/**
- * Set the anonymity level displayed by a combo box.
- *
- * @param combo the combo box
- * @param sel_level desired anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_select_anonymity_combo_level (GtkComboBox *combo, guint sel_level)
-{
- GtkTreeIter iter;
- GtkTreeModel *model;
- guint level;
-
- model = gtk_combo_box_get_model (combo);
- if (!model)
- return FALSE;
- if (! gtk_tree_model_get_iter_first (model, &iter))
- return FALSE;
- do
- {
- gtk_tree_model_get (model, &iter, 1, &level, -1);
- if (level == sel_level)
- {
- gtk_combo_box_set_active_iter (combo, &iter);
- return TRUE;
- }
- }
- while (gtk_tree_model_iter_next (model, &iter));
- return FALSE;
-}
-
-
-
-/* end of gnunet-fs-gtk-anonymtiy_spin_buttons.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.h 2012-02-02
12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.h 2012-02-02
13:28:32 UTC (rev 19629)
@@ -1,80 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2005, 2006, 2010, 2012 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-anonymtiy_spin_buttons.h
- * @author Christian Grothoff
- * @brief operations to manage user's anonymity level selections
- */
-#ifndef GNUNET_FS_GTK_ANONYMITY_SPIN_BUTTONS_H
-#define GNUNET_FS_GTK_ANONYMITY_SPIN_BUTTONS_H
-
-#include "gnunet-fs-gtk-common.h"
-#include <gdk/gdk.h>
-
-
-/**
- * Obtain the numeric anonymity level selected by a GtkComboBox.
- *
- * @param builder builder for looking up widgets
- * @param combo_name name of the GtkComboBox with the anonymity selection
- * @param p_level where to store the anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_get_selected_anonymity_level (GtkBuilder * builder,
- gchar * combo_name, guint * p_level);
-
-
-/**
- * Obtain the numeric anonymity level selected by a GtkComboBox.
- *
- * @param combo the GtkComboBox with the anonymity selection
- * @param p_level where to store the anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_get_selected_anonymity_combo_level (GtkComboBox *combo, guint
*p_level);
-
-
-/**
- * Set the anonymity level displayed by a combo box.
- *
- * @param builder the builder of the combo box
- * @param combo_name name of the combo box
- * @param sel_level desired anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_select_anonymity_level (GtkBuilder * builder, gchar * combo_name,
- guint sel_level);
-
-
-/**
- * Set the anonymity level displayed by a combo box.
- *
- * @param combo the combo box
- * @param sel_level desired anonymity level
- * @return TRUE on success, FALSE on failure
- */
-gboolean
-GNUNET_GTK_select_anonymity_combo_level (GtkComboBox *combo, guint sel_level);
-
-#endif
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-common.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-common.c 2012-02-02 12:57:54 UTC (rev
19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-common.c 2012-02-02 13:28:32 UTC (rev
19629)
@@ -1,234 +0,0 @@
-/*
- 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-common.c
- * @brief Common functions used in various places
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk-common.h"
-
-/**
- * Converts metadata specified by @data of size @data_len
- * and saved in format @format to UTF-8 encoded string.
- * Works only for C-string and UTF8 metadata formats
- * (returns NULL for everything else).
- * Verifies UTF-8 strings.
- *
- * @param format format of the @data
- * @param data data to convert
- * @param data_len length of the data buffer (in bytes)
- * @return NULL if can't be converted, allocated string otherwise,
- * freeable with GNUNET_free* ().
- */
-char *
-GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format,
- const char *data, size_t data_len)
-{
- switch (format)
- {
- case EXTRACTOR_METAFORMAT_UTF8:
- /* data must not contain NULLs (hence the -1) */
- if (g_utf8_validate (data, data_len - 1, NULL))
- return GNUNET_strdup (data);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Failed to validate supposedly utf-8 string `%s' of length
%u, assuming it to be a C string\n"),
- data,
- (unsigned int) data_len);
- format = EXTRACTOR_METAFORMAT_C_STRING;
- /* fall-through */
- case EXTRACTOR_METAFORMAT_C_STRING:
- if (data_len > 0)
- {
- /* There are no guarantees that data is NULL-terminated, AFAIU,
- * so let's play it safe, shall we?
- */
- char data_copy[data_len + 1];
-
- memcpy (data_copy, data, data_len);
- data_copy[data_len] = '\0';
- return GNUNET_GTK_from_loc_to_utf8 (data_copy);
- }
- break;
- default:
- break;
- }
- return NULL;
-}
-
-
-/**
- * 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);
- char *data_to_insert;
-
- data_to_insert = GNUNET_FS_GTK_dubious_meta_to_utf8 (format, data, data_len);
- if (NULL == data_to_insert)
- return 0;
- gtk_list_store_insert_with_values (ls, NULL, G_MAXINT, 0, type, 1, format,
- 2, EXTRACTOR_metatype_to_string (type),
- 3, data_to_insert, -1);
- GNUNET_free (data_to_insert);
- return 0;
-}
-
-
-/**
- * Convert the year from the spin button to an expiration
- * time (on midnight, January 1st of that year).
- *
- * @param spin button with an expiration year
- * @return expiration time in the usual GNUnet format
- */
-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;
-}
-
-
-/**
- * Initialize the 'expiration_year_adjustment' of the given
- * builder to have a lower range of current-year+1 and a
- * default of current-year+2.
- *
- * @param builder builder object for which we should manipulate
- * the adjustment
- */
-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);
-}
-
-
-/**
- * Obtain pixbuf from thumbnail data in meta data.
- *
- * @param meta input meta data
- * @return NULL on error, otherwise the embedded thumbnail
- */
-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 (0 == ts)
- 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 (NULL != pixbuf)
- 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.
- *
- * @param filename name with the directory
- * @param dep function to call on each entry
- * @param dep_cls closure for 'dep'
- */
-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;
- }
- if (NULL == (fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
- GNUNET_DISK_PERM_NONE)))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
- return;
- }
- if (NULL == (ddata = GNUNET_DISK_file_map (fh, &mh,
GNUNET_DISK_MAP_TYPE_READ, (size_t) fsize)))
- {
- 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 gnunet-fs-gtk-common.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-common.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-common.h 2012-02-02 12:57:54 UTC (rev
19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-common.h 2012-02-02 13:28:32 UTC (rev
19629)
@@ -1,126 +0,0 @@
-/*
- 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-common.h
- * @brief Common includes for all gnunet-gtk source files
- * @author Christian Grothoff
- */
-#ifndef GNUNET_FS_GTK_COMMON_H
-#define GNUNET_FS_GTK_COMMON_H
-
-#include "gnunet_gtk.h"
-#include <gnunet/gnunet_fs_service.h>
-#include <extractor.h>
-
-
-/**
- * Obtain pixbuf from thumbnail data in meta data.
- *
- * @param meta input meta data
- * @return NULL on error, otherwise the embedded thumbnail
- */
-GdkPixbuf *
-GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct
- GNUNET_CONTAINER_MetaData *meta);
-
-
-/**
- * Initialize the 'expiration_year_adjustment' of the given
- * builder to have a lower range of current-year+1 and a
- * default of current-year+2.
- * FIXME: odd API...
- *
- * @param builder builder object for which we should manipulate
- * the adjustment
- */
-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).
- *
- * @param spin button with the year
- * @param time converted from the spin button
- */
-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.
- *
- * @param filename name with the directory
- * @param dep function to call on each entry
- * @param dep_cls closure for 'dep'
- */
-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);
-
-
-/**
- * Converts metadata specified by @data of size @data_len
- * and saved in format @format to UTF-8 encoded string.
- * Works only for C-string and UTF8 metadata formats
- * (returns NULL for everything else).
- * Verifies UTF-8 strings.
- *
- * @param format format of the @data
- * @param data data to convert
- * @param data_len length of the data buffer (in bytes)
- * @return NULL if can't be converted, allocated string otherwise,
- * freeable with GNUNET_free* ().
- */
-char *
-GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format,
- const char *data, size_t data_len);
-
-
-#endif
-/* end of gnunet-fs-gtk-common.h */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-download.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-download.c 2012-02-02 12:57:54 UTC (rev
19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-download.c 2012-02-02 13:28:32 UTC (rev
19629)
@@ -1,295 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2010, 2011, 2012 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-download.c
- * @brief functions for managing the 'save as' dialog
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk-download.h"
-#include "gnunet-fs-gtk.h"
-#include "gnunet-fs-gtk-event_handler.h"
-
-/**
- * State for a 'save as' dialog of a download.
- */
-struct DownloadAsDialogContext
-{
-
- /**
- * Download context for which this dialog determines the
- * filename (and other options).
- */
- struct DownloadContext *dc;
-
- /**
- * Builder for the dialog.
- */
- GtkBuilder *builder;
-
- /**
- * Main dialog object.
- */
- GtkWidget *dialog;
-
- /**
- * Final response code from the dialog.
- */
- gint response;
-};
-
-
-/**
- * Free resources associated with the given download context.
- *
- * @param dc context to free
- */
-static void
-save_as_dialog_free_download_context (struct DownloadContext *dc)
-{
- if (NULL != dc->rr)
- gtk_tree_row_reference_free (dc->rr);
- GNUNET_free_non_null (dc->mime);
- GNUNET_free_non_null (dc->filename);
- if (NULL != dc->meta)
- GNUNET_CONTAINER_meta_data_destroy (dc->meta);
- if (NULL != dc->uri)
- GNUNET_FS_uri_destroy (dc->uri);
- GNUNET_free (dc);
-}
-
-
-/**
- * The 'save_as' dialog is being deleted. Check which state we're in
- * and either simply clean up or start the download with the
- * respective options (by calling the respective continuation).
- *
- * @param widget the dialog object
- * @param event the deletion event
- * @param user_data the 'structDownloadAsDialogContext' of the dialog
- * @return always FALSE
- */
-gboolean
-GNUNET_GTK_save_as_dialog_delete_event_cb (GtkWidget * widget, GdkEvent *
event,
- gpointer user_data)
-{
- struct DownloadAsDialogContext *dlc = user_data;
- GtkBuilder *builder;
- struct DownloadContext *dc;
- GtkWidget *cb;
-
- builder = dlc->builder;
- dc = dlc->dc;
- cb = GTK_WIDGET (gtk_builder_get_object
- (builder, "GNUNET_GTK_save_as_recursive_check_button"));
- if (GTK_RESPONSE_OK != dlc->response)
- {
- save_as_dialog_free_download_context (dc);
- g_object_unref (G_OBJECT (dlc->builder));
- GNUNET_free (dlc);
- return FALSE;
- }
- GNUNET_free_non_null (dc->filename);
- dc->filename =
- GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(dlc->dialog));
- dc->is_recursive =
- (TRUE ==
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
- GNUNET_NO;
- dc->anonymity =
- gtk_spin_button_get_value (GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (builder,
-
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
- g_object_unref (G_OBJECT (builder));
- GNUNET_free (dlc);
- GNUNET_FS_GTK_download_context_start_download (dc);
- return FALSE;
-}
-
-
-/**
- * The user clicked on the 'save as' button of the dialog.
- * Delete the window and start the download.
- *
- * @param dialog the dialog object
- * @param response_id response_id associated with the button
- * @param user_data the 'structDownloadAsDialogContext' of the dialog
- */
-void
-GNUNET_GTK_save_as_dialog_response_cb (GtkDialog * dialog,
- gint response_id,
- gpointer user_data)
-{
- struct DownloadAsDialogContext *dlc = user_data;
-
- dlc->response = response_id;
- /* dialogs don't get delete-event the way normal windows do,
- call the handler manually */
- GNUNET_GTK_save_as_dialog_delete_event_cb (GTK_WIDGET (dialog), NULL,
- user_data);
- /* FIXME-BUG-MAYBE: isn't the dialog going to be destroyed with the builder?
- Is this legal and/or required? */
- gtk_widget_destroy (GTK_WIDGET (dialog));
-}
-
-
-/**
- * Open the 'save as' dialog for a download. Calls the 'dc->cb'
- * continutation when the dialog is complete. Will release the 'dc'
- * resources if the dialog is cancelled.
- *
- * @param dc download context for the file/directory
- */
-void
-GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc)
-{
- struct DownloadAsDialogContext *dlc;
- GtkWidget *cb;
-
- dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext));
- dlc->dc = dc;
- dlc->builder =
- GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade",
- dlc);
- if (NULL == dlc->builder)
- {
- GNUNET_break (0);
- save_as_dialog_free_download_context (dc);
- GNUNET_free (dlc);
- return;
- }
- dlc->dialog = GTK_WIDGET (gtk_builder_get_object
- (dlc->builder, "GNUNET_GTK_save_as_dialog"));
-
- /* Enable recursive button for directories and
- set recursive 'default' value based on what the 'dc' tells us */
- cb = GTK_WIDGET (gtk_builder_get_object
- (dlc->builder,
"GNUNET_GTK_save_as_recursive_check_button"));
- if (GNUNET_FS_meta_data_test_for_directory (dc->meta))
- gtk_widget_set_sensitive (cb, TRUE);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb),
- dc->is_recursive);
-
- /* initialize filename based on filename from 'dc' */
- if (NULL != dc->filename)
- {
- char *dirname;
- char *basename;
-
- dirname = GNUNET_strdup (dc->filename);
- basename = (char *) GNUNET_STRINGS_get_short_name (dirname);
- /* basename now points into 'dirname'; cut 'dirname' off at the '/' before
basename */
- if (basename > dirname)
- basename[-1] = '\0';
-
- /* FIXME: remove following lines after testing... */
- fprintf (stderr,
- "Splitting `%s' into `%s' + `%s' for file chooser dialog.\n",
- dc->filename,
- dirname,
- basename);
-
- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlc->dialog),
dirname);
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlc->dialog),
basename);
- GNUNET_free (dirname);
- }
- gtk_window_present (GTK_WINDOW (dlc->dialog));
-}
-
-
-/**
- * Actually start the download that is specified by the given download
- * context and its options. Will add a download entry to the
- * respective tree model and trigger a start of the download using the
- * FS-API.
- *
- * @param dc download context of the download to execute
- */
-void
-GNUNET_FS_GTK_download_context_start_download (struct DownloadContext *dc)
-{
- enum GNUNET_FS_DownloadOptions opt;
- struct GNUNET_FS_Handle *fs;
- struct DownloadEntry *de;
- uint64_t len;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- de = GNUNET_malloc (sizeof (struct DownloadEntry));
- de->uri = dc->uri;
- dc->uri = NULL;
- de->meta = dc->meta;
- dc->meta = NULL;
- if (NULL != dc->rr)
- {
- de->rr = gtk_tree_row_reference_copy (dc->rr);
- de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
- path = gtk_tree_row_reference_get_path (de->rr);
- if ( (NULL != path) &&
- (gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) )
- {
- /* Store filename and anonymity as specified by the user.
- * These will be re-used when this is a directory, and the user
- * downloads its children.
- */
- gtk_tree_store_set (de->ts, &iter, 15, dc->filename, 16, dc->anonymity,
-1);
- }
- else
- {
- /* We could not find the referenced row in the search tab; this is
- conceivable as the search tab might have been closed by the
- user while the 'save as' dialog was open. In this case, this
- is equivalent to having no search, so we drop the (now invalid)
- 'sr' reference */
- dc->sr = NULL;
- }
- if (NULL != path)
- gtk_tree_path_free (path);
- }
- fs = GNUNET_FS_GTK_get_fs_handle ();
- opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
- if (dc->is_recursive)
- opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
- len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
- if (NULL != dc->sr)
- {
- GNUNET_break (NULL !=
- GNUNET_FS_download_start_from_search (fs, dc->sr,
- dc->filename,
- NULL /* tempname */ ,
- 0 /* offset */ ,
- len, dc->anonymity,
opt,
- de));
- }
- else
- {
- GNUNET_break (NULL !=
- GNUNET_FS_download_start (fs, de->uri, NULL /* meta */ ,
- dc->filename, NULL /* tempname */ ,
- 0 /* offset */ ,
- len, dc->anonymity, opt, de,
- NULL /* parent download ctx */ ));
- }
- save_as_dialog_free_download_context (dc);
-}
-
-
-/* end of gnunet-fs-gtk-download.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-download.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-download.h 2012-02-02 12:57:54 UTC (rev
19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-download.h 2012-02-02 13:28:32 UTC (rev
19629)
@@ -1,117 +0,0 @@
-/*
- 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-download.h
- * @brief functions for downloading
- * @author Christian Grothoff
- */
-#ifndef GNUNET_FS_GTK_DOWNLOAD_H
-#define GNUNET_FS_GTK_DOWNLOAD_H
-
-#include "gnunet-fs-gtk-common.h"
-
-
-/**
- * Information we keep for a download.
- */
-struct DownloadContext;
-
-
-/**
- * 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;
-
- /**
- * Tab where this download is currently on display.
- * (this is the same as sr->tab, but sr is opaque here).
- */
- struct SearchTab *tab;
-
-};
-
-
-/**
- * Actually start the download that is specified by the given download
- * context and its options. Will add a download entry to the
- * respective tree model and trigger a start of the download using the
- * FS-API.
- *
- * @param dc download context of the download to execute
- */
-void
-GNUNET_FS_GTK_download_context_start_download (struct DownloadContext *dc);
-
-
-/**
- * Open the 'save as' dialog for a download. Calls
- * 'GNUNET_FS_GTK_download_context_start_download' when the dialog is
- * complete. Will release the 'dc' resources if the dialog is
- * cancelled.
- *
- * @param dc download context for the file/directory
- */
-void
-GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc);
-
-
-#endif
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.c 2012-02-02
12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.c 2012-02-02
13:28:32 UTC (rev 19629)
@@ -1,1163 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2005, 2006, 2010, 2012 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-edit_publish_dialog.c
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk-common.h"
-#include "gnunet-fs-gtk-edit_publish_dialog.h"
-#include "gnunet-fs-gtk.h"
-#include <gnunet/gnunet_util_lib.h>
-
-#include "metatypes.c"
-
-
-/**
- * Internal state kept for each "edit" dialog where the user can edit
- * publishing information for a file.
- */
-struct EditPublicationDialogContext
-{
- /**
- * Builder for the dialog.
- */
- GtkBuilder *builder;
-
- /**
- * The 'window' object for the dialog.
- */
- GtkWindow *edit_publication_window;
-
- /**
- * The confirmation button which closes the dialog (only sensitive
- * if the values entered are valid).
- */
- GtkWidget *confirm_button;
-
- /**
- * Tree view showing the meta data for the file.
- */
- GtkTreeView *meta_treeview;
-
- /**
- * Tree view showing the keywords for the file.
- */
- GtkTreeView *keywords_treeview;
-
- /**
- * Image showing the preview image for the file.
- */
- GtkImage *preview_image;
-
- /**
- * Combo box where the user can select the anonymity level.
- */
- GtkComboBox *anonymity_combo;
-
- /**
- * Liststore of possible publication types.
- */
- GtkListStore *pubtypes_liststore;
-
- /**
- * Liststore of all possible meta types the user can choose from.
- * (updated to based on the selected publication type).
- */
- GtkListStore *metatypes_liststore;
-
- /**
- * Liststore showing the meta data of the file (associated with
- * the 'meta_treeview'.
- */
- GtkListStore *meta_liststore;
-
- /**
- * Liststore with the keywords of the file (associated with the
- * 'keywords_treeview'.
- */
- GtkListStore *keywords_liststore;
-
- /**
- * Spin button to select content priority level for the file.
- */
- GtkSpinButton *priority_spin;
-
- /**
- * Spin button to select the expiration year.
- */
- GtkSpinButton *expiration_year_spin;
-
- /**
- * Spin button to select the replication level.
- */
- GtkSpinButton *replication_spin;
-
- /**
- * Entry line for adding additional keywords.
- */
- GtkEntry *keyword_entry;
-
- /**
- * Entry line for setting a namespace root (possibly invisible).
- */
- GtkEntry *root_entry;
-
- /**
- * Entry line to check indexing vs. inserting (possibly invisible)
- */
- GtkToggleButton *index_checkbutton;
-
- /**
- * Type ID of the last selected item in the GtkCellRendererCombo
- * of the meta data tree view.
- */
- gint meta_combo_selected_type_id;
-
- /**
- * Continuation to call once the dialog has been closed
- */
- GNUNET_FS_GTK_EditPublishDialogCallback cb;
-
- /**
- * Closure for 'cb'.
- */
- void *cb_cls;
-
- /**
- * Briefly used temporary meta data set.
- */
- struct GNUNET_CONTAINER_MetaData *md;
-
- /**
- * Information about the file being published as seen by the FS-API.
- * This is what we are primarily editing.
- */
- struct GNUNET_FS_FileInformation *fip;
-
- /**
- * Flag to track if we changed the preview and thus should keep/discard
- * certain metadata. (FIXME: yucky!)
- */
- int preview_changed;
-
- /**
- * Is this operation for a directory?
- */
- int is_directory;
-
- /**
- * Is it allowed for the user to supply keywords in this dialog?
- */
- int allow_no_keywords;
-
-};
-
-
-/**
- * Free resources associated with the edit publication dialog.
- *
- * @param ctx the context of the dialog to release resources of
- */
-static void
-free_edit_dialog_context (struct EditPublicationDialogContext *ctx)
-{
- gtk_widget_destroy (GTK_WIDGET (ctx->edit_publication_window));
- // FIXME-LEAK: destroy builder!
- GNUNET_free (ctx);
-}
-
-
-
-/* ****************** metadata editing ******************** */
-
-
-
-/**
- * Update the set of metatypes listed in the dialog based on the
- * given code.
- *
- * @param ctx main dialog context
- * @param code which set of metatypes is desired?
- */
-static void
-change_metatypes (struct EditPublicationDialogContext *ctx, gint code)
-{
- gint pubtype_count;
- gint max_type;
- gint i;
- GtkTreeIter iter;
-
- /* double-check that 'code' is valid */
- for (pubtype_count = 0; NULL != types[pubtype_count]; pubtype_count++) ;
- GNUNET_assert (code < pubtype_count);
-
- /* clear existing selection of metatypes */
- gtk_list_store_clear (ctx->metatypes_liststore);
- max_type = EXTRACTOR_metatype_get_max ();
- /* add new types based on selection */
- for (i = 0; types[code][i] != EXTRACTOR_METATYPE_RESERVED; i++)
- if ( (types[code][i] < max_type) && (types[code][i] > 0) )
- gtk_list_store_insert_with_values (ctx->metatypes_liststore,
- &iter, G_MAXINT,
- 0, types[code][i],
- 1, EXTRACTOR_METAFORMAT_UTF8,
- 2, EXTRACTOR_metatype_to_string (types
[code][i]),
- 3, EXTRACTOR_metatype_to_description
(types[code][i]),
- -1);
-}
-
-
-/**
- * The user has selected a different publication type.
- * Update the meta type selection.
- *
- * @param widget the publication type combo box widget
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_type_combo_changed_cb (GtkComboBox * widget,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
- gint code;
-
- if (! gtk_combo_box_get_active_iter (widget, &iter))
- return;
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->pubtypes_liststore), &iter, 0,
&code, -1);
- change_metatypes (ctx, code);
-}
-
-
-/**
- * The user has changed the selection in the meta data tree view.
- * Update the sensitivity of the 'delete' button.
- *
- * @param ts the tree selection object
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-/* FIXME: connect this signal via glade (modern versions of Glade support
this) */
-static void
-metadata_selection_changed_cb (GtkTreeSelection *ts,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_delete_button")),
- gtk_tree_selection_get_selected (ts, NULL, NULL));
-}
-
-
-/**
- * The user changed (and confirmed the change) the type of a
- * meta-data item in the meta data tree view. Update the type and
- * text in the list store accordingly.
- *
- * @param renderer widget where the change happened
- * @param path which item was changed in the tree view
- * @param new_text new value for the item
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_edited_cb
(GtkCellRendererText *renderer,
- gchar *
path,
- gchar *
new_text,
-
gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
- gint type_id;
-
- if (! gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL
(ctx->meta_liststore),
- &iter,
- path))
- {
- GNUNET_break (0);
- return;
- }
- if (-1 == ctx->meta_combo_selected_type_id)
- {
- GNUNET_break (0);
- return;
- }
- type_id = ctx->meta_combo_selected_type_id;
- ctx->meta_combo_selected_type_id = -1;
- gtk_list_store_set (ctx->meta_liststore, &iter,
- 0, type_id,
- 1, EXTRACTOR_METAFORMAT_UTF8,
- 2, EXTRACTOR_metatype_to_string (type_id),
- 4, EXTRACTOR_metatype_to_description (type_id),
- -1);
-}
-
-
-/**
- * The user changed the type of a meta-data item in the meta data
- * tree view. Obtain the selected type_id and store it in
- * the 'meta_combo_selected_type_id' field for use by
- * 'GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_edited_cb'.
- *
- * @param combo combo box that was dropped down
- * @param path which item was changed in the tree view
- * @param new_iter item that is now selected in the drop-down combo box
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_changed_cb
(GtkCellRendererCombo * combo,
- gchar
* path_string,
-
GtkTreeIter * new_iter,
-
gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeModel *combo_model;
- gint type_id;
-
- g_object_get (combo,
- "model", &combo_model, NULL);
- gtk_tree_model_get (combo_model, new_iter,
- 0, &type_id,
- -1);
- ctx->meta_combo_selected_type_id = type_id;
-}
-
-
-/**
- * The user changed (and confirmed the change) the value of a
- * meta-data item in the meta data tree view. Update the value
- * in the list store accordingly.
- *
- * @param renderer widget where the change happened
- * @param path which item was changed in the tree view
- * @param new_text new value for the item
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_metadata_tree_view_value_renderer_edited_cb
(GtkCellRendererText * renderer,
- gchar
* path,
- gchar
* new_text,
-
gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
- gint metatype;
- char *avalue;
- const char *ivalue;
- size_t slen;
- char *pos;
-
- if (! gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL
(ctx->meta_liststore),
- &iter,
- path))
- {
- GNUNET_break (0);
- return;
- }
-
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter,
- 0, &metatype, -1);
- if (metatype == EXTRACTOR_METATYPE_FILENAME)
- {
- /* apply filename rules */
- /* First, use UNIX-style separators */
- avalue = GNUNET_strdup (new_text);
- while (NULL != (pos = strstr (avalue, "\\")))
- *pos = '/';
-
- /* if user put '/' at the end, remove it' */
- slen = strlen (avalue);
- while ( (slen > 1) && (avalue[slen - 1] == '\\'))
- {
- avalue[slen - 1] = '\0';
- slen--;
- }
-
- /* However, directories must end with '/', so add it */
- if ( (new_text[strlen (new_text) - 1] != '/') &&
- ctx->is_directory )
- {
- char * tmp;
-
- GNUNET_asprintf (&tmp, "%s/", avalue);
- GNUNET_free (avalue);
- avalue = tmp;
- }
-
- /* Also, replace '../' everywhere with "___" */
- while (NULL != (pos = strstr (avalue, "../")))
- memset (pos, '_', 3);
-
- ivalue = avalue;
- }
- else
- {
- ivalue = new_text;
- avalue = NULL;
- }
- gtk_list_store_set (ctx->meta_liststore, &iter,
- 3, ivalue,
- -1);
- GNUNET_free_non_null (avalue);
-}
-
-
-/**
- * The user has pushed the 'add' button for metadata. Add a 'dummy' value
- * to our meta data store (to be edited by the user).
- *
- * @param button the 'add' button
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_add_button_clicked_cb (GtkButton * button,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
-
- gtk_list_store_insert_with_values (ctx->meta_liststore,
- &iter, 0,
- 0, 0,
- 1, EXTRACTOR_METAFORMAT_UTF8,
- 2, _("Select a type"),
- 3, _("Specify a value"),
- 4, NULL,
- -1);
-}
-
-
-/**
- * The user has pushed the 'del' button for metadata.
- * If there is a metadata selected, remove it from the list store.
- *
- * @param widget the button
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_delete_button_clicked_cb (GtkButton * button,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
- GtkTreeSelection *meta_selection;
-
- meta_selection = gtk_tree_view_get_selection (ctx->meta_treeview);
- if (! gtk_tree_selection_get_selected (meta_selection, NULL, &iter))
- {
- GNUNET_break (0);
- return;
- }
- if (gtk_list_store_remove (ctx->meta_liststore, &iter))
- gtk_tree_selection_select_iter (meta_selection, &iter);
-}
-
-
-/**
- * The user has selected another preview image file. Update the
- * preview image.
- *
- * @param widget the file chooser dialog that completed
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_metadata_preview_file_chooser_button_file_set_cb
(GtkFileChooserButton * widget,
-
gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- gchar *fn;
-
- fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
- gtk_image_set_from_file (ctx->preview_image, fn);
- g_free (fn);
- ctx->preview_changed = GNUNET_YES;
-}
-
-
-/* ****************** keyword list editing ******************** */
-
-
-
-/**
- * The user has changed the selection in the keyword tree view.
- * Update the sensitivity of the 'delete' button.
- *
- * @param ts the tree selection object
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-/* FIXME: connect this signal via glade (modern versions of Glade support
this) */
-static void
-keywords_selection_changed_cb (GtkTreeSelection *ts,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_keyword_list_del_button")),
- gtk_tree_selection_get_selected (ts, NULL, NULL));
-}
-
-
-/**
- * The user has edited the keyword entry line. Update the
- * sensitivity of the 'add' button.
- *
- * @param editable the entry line for keywords
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_keyword_entry_changed_cb (GtkEditable * editable,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- const char *keyword;
-
- keyword = gtk_entry_get_text (ctx->keyword_entry);
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (ctx->builder,
-
"GNUNET_GTK_edit_publication_keyword_list_add_button")),
- (strlen (keyword) > 0) ? TRUE : FALSE);
-}
-
-
-/**
- * The user has pushed the 'del' button for the keyword.
- * If there is a keyword selected, remove it from the list store.
- *
- * @param widget the button
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_keyword_list_del_button_clicked_cb (GtkButton *
- button,
- gpointer
user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- GtkTreeIter iter;
- GtkTreeSelection *keywords_selection;
-
- keywords_selection = gtk_tree_view_get_selection (ctx->keywords_treeview);
- if (! gtk_tree_selection_get_selected (keywords_selection, NULL, &iter))
- {
- GNUNET_break (0);
- return;
- }
- if (gtk_list_store_remove (GTK_LIST_STORE (ctx->keywords_liststore), &iter))
- gtk_tree_selection_select_iter (keywords_selection, &iter);
-
- /* disable confirm button if keywords are required and we have no more
keywords */
- if ( (! ctx->allow_no_keywords) &&
- (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL
(ctx->keywords_liststore),
- &iter)) )
- gtk_widget_set_sensitive (ctx->confirm_button, FALSE);
-}
-
-
-/**
- * The user has pushed the 'add' button for the keyword (or pressed RETURN).
- * If there is a keyword in the line, add it to the list store.
- *
- * @param widget the entry line, or NULL (if we are called from 'RETURN')
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_keyword_list_add_button_clicked_cb (GtkButton *
- button,
- gpointer
user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
- const char *keyword;
- GtkTreeIter iter;
-
- keyword = gtk_entry_get_text (ctx->keyword_entry);
- if (strlen (keyword) == 0)
- return;
- gtk_list_store_insert_with_values (ctx->keywords_liststore,
- &iter, G_MAXINT,
- 0, keyword,
- 1, TRUE,
- -1);
- gtk_widget_set_sensitive (ctx->confirm_button, TRUE);
- gtk_entry_set_text (ctx->keyword_entry, "");
-}
-
-
-/**
- * The user has pushed a button in the entry line. Check if it was 'RETURN'
- * and if so consider executing the 'add' action.
- *
- * @param widget the entry line
- * @param event the event information
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-gboolean
-GNUNET_GTK_edit_publication_keyword_entry_key_press_event_cb (GtkWidget *
- widget,
- GdkEventKey *
- event,
- gpointer
user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- if (event->keyval != GDK_KEY_Return)
- return FALSE;
- GNUNET_GTK_edit_publication_keyword_list_add_button_clicked_cb (NULL, ctx);
- return TRUE;
-}
-
-
-
-/* ****************** handlers for closing the dialog ******************** */
-
-
-/**
- * The user clicked the 'cancel' button. Abort the operation.
- *
- * @param button the cancel button
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_cancel_button_clicked_cb (GtkButton * button,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- ctx->cb (ctx->cb_cls, GTK_RESPONSE_CANCEL, NULL);
- free_edit_dialog_context (ctx);
-}
-
-
-/**
- * The user closed the window. Abort the operation.
- *
- * @param widget the window
- * @param event the event that caused the window to close
- * @param user_data the 'struct EditPublicationDialogContext'
- * @return TRUE (always)
- */
-gboolean
-GNUNET_GTK_edit_publication_window_delete_event_cb (GtkWidget * widget,
- GdkEvent * event,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- ctx->cb (ctx->cb_cls, GTK_RESPONSE_CANCEL, NULL);
- free_edit_dialog_context (ctx);
- return TRUE;
-}
-
-
-/**
- * Copy binary meta data from to the new container and also preserve
- * all entries that were not changed. In particular, all binary meta
- * data is removed if the preview was changed, otherwise it is all
- * kept. Similarly, if values are still in the liststore, they are
- * fully kept (including plugin name and original format). "Keeping"
- * a value means that it is added to the 'md' meta data in the dialog
- * context.
- *
- * @param cls closure, a 'struct FileInformationUpdateContext';
- * contains the 'new' meta data to construct in the 'md'
- * field and the liststore to check the current value
- * against in 'meta_liststore'.
- * @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 EditPublicationDialogContext *ctx = cls;
- GtkTreeIter iter;
- gchar *value;
- guint ntype;
- guint nformat;
- int keep;
-
- keep = GNUNET_NO;
- switch (format)
- {
- case EXTRACTOR_METAFORMAT_UTF8:
- case EXTRACTOR_METAFORMAT_C_STRING:
- if (TRUE == gtk_tree_model_get_iter_first (GTK_TREE_MODEL
(ctx->meta_liststore), &iter))
- {
- do
- {
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter, 0,
&ntype, 1, &nformat, 3, &value, -1);
- if ((ntype == type) && (nformat == format) &&
- (0 == strcmp (value, data)))
- {
- gtk_list_store_remove (ctx->meta_liststore, &iter);
- keep = GNUNET_YES;
- g_free (value);
- break;
- }
- g_free (value);
- }
- while (TRUE == gtk_tree_model_iter_next (GTK_TREE_MODEL
(ctx->meta_liststore), &iter));
- }
- break;
- case EXTRACTOR_METAFORMAT_UNKNOWN:
- break;
- case EXTRACTOR_METAFORMAT_BINARY:
- if (ctx->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 (ctx->md, plugin_name,
type,
- format, data_mime_type,
- data, data_len));
- return 0;
-}
-
-
-/**
- * Function called to update the information in FI based on the changes made in
- * the edit dialog.
- *
- * @param cls closure with a 'struct FileInformationUpdateContext *'
- * @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)
-{
- struct EditPublicationDialogContext *ctx = cls;
- GtkTreeIter iter;
- gint year;
-
- /* gather publishing options */
- *do_index = gtk_toggle_button_get_active (ctx->index_checkbutton);
- GNUNET_break (GNUNET_GTK_get_selected_anonymity_combo_level
(ctx->anonymity_combo,
-
&bo->anonymity_level));
- bo->content_priority = gtk_spin_button_get_value (ctx->priority_spin);
- bo->replication_level = gtk_spin_button_get_value (ctx->replication_spin);
- year = gtk_spin_button_get_value (ctx->expiration_year_spin);
- bo->expiration_time = GNUNET_FS_year_to_time (year);
-
- /* update keyword-URI */
- if (NULL != (*uri))
- GNUNET_FS_uri_destroy (*uri);
- *uri = NULL;
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ctx->keywords_liststore),
&iter))
- {
- do
- {
- gchar *value;
-
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->keywords_liststore), &iter, 0,
&value, -1);
- if (NULL == *uri)
- *uri = GNUNET_FS_uri_ksk_create_from_args (1, (const char **) &value);
- else
- GNUNET_FS_uri_ksk_add_keyword (*uri, value, GNUNET_NO);
- g_free (value);
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ctx->keywords_liststore),
&iter));
- }
-
- /* update meta data; first, we copy the unchanged values from the original
meta data */
- ctx->md = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_iterate (meta,
- &preserve_meta_items,
- ctx);
- /* clear original meta data */
- GNUNET_CONTAINER_meta_data_clear (meta);
- /* add all of the 'preserved' values */
- GNUNET_CONTAINER_meta_data_merge (meta, ctx->md);
- GNUNET_CONTAINER_meta_data_destroy (ctx->md);
- ctx->md = NULL;
- /* now add all of the values from the model; adding will simply do
- nothing for values that are already in the set because they were
preserved */
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ctx->meta_liststore),
&iter))
- {
- do
- {
- guint ntype;
- guint nformat;
- gchar *value;
-
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter, 0,
&ntype, 1, &nformat, 3, &value, -1);
- if (ntype > 0)
- GNUNET_CONTAINER_meta_data_insert (ctx->md, "<user>", ntype, nformat,
- "text/plain", value,
- strlen (value) + 1);
- g_free (value);
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ctx->meta_liststore),
&iter));
- }
-
- /* finally, if we got a new preview, add it as well */
- if (ctx->preview_changed == GNUNET_YES)
- {
- gchar *fn;
- char *data;
- gsize data_size;
- const char *mime;
- GFile *f;
- GFileInfo *finfo;
-
- fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
- (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_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 (! 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);
- g_free (fn);
- }
- return GNUNET_SYSERR; /* only visit top-level item */
-}
-
-
-/**
- * The user clicked the 'confirm' button. Push the edits back into the
- * FileInformation structure and given it and the options back to the
- * callback. Then clean up the dialog.
- *
- * @param button the cancel button
- * @param user_data the 'struct EditPublicationDialogContext'
- */
-void
-GNUNET_GTK_edit_publication_confirm_button_clicked_cb (GtkButton * button,
- gpointer user_data)
-{
- struct EditPublicationDialogContext *ctx = user_data;
-
- /* push back changes to file-information */
- GNUNET_FS_file_information_inspect (ctx->fip,
- &file_information_update,
- ctx);
- /* call our continuation */
- ctx->cb (ctx->cb_cls,
- GTK_RESPONSE_OK,
- gtk_entry_get_text (ctx->root_entry));
- /* free resources from the edit dialog */
- free_edit_dialog_context (ctx);
-}
-
-
-
-/* ****************** code for initialization of the dialog
******************** */
-
-
-
-/**
- * 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 (cls);
- gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
- 0, keyword,
- 1, FALSE,
- -1);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called to extract the information from FI to populate the edit
dialog.
- *
- * @param cls the 'struct EditPublicationDialogContext'
- * @param fi the entry in the publish-structure (unused)
- * @param length length of the file or directory (unused)
- * @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_import (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)
-{
- struct EditPublicationDialogContext *ctx = cls;
- GdkPixbuf *pixbuf;
- char *short_fn;
- int year;
-
- /* import options */
- year = (int) GNUNET_FS_time_to_year (bo->expiration_time);
- gtk_spin_button_set_value (ctx->expiration_year_spin, year);
- GNUNET_GTK_select_anonymity_combo_level (ctx->anonymity_combo,
- bo->anonymity_level);
- gtk_spin_button_set_value (ctx->priority_spin, bo->content_priority);
- gtk_spin_button_set_value (ctx->replication_spin, bo->replication_level);
- gtk_toggle_button_set_active (ctx->index_checkbutton, *do_index);
-
-
- /* import keywords */
- if (NULL != *uri)
- GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword,
ctx->keywords_liststore);
-
- /* import meta data */
- if (NULL != meta)
- {
- GNUNET_CONTAINER_meta_data_iterate (meta,
-
&GNUNET_FS_GTK_add_meta_data_to_list_store,
- ctx->meta_liststore);
- pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
- if (pixbuf != NULL)
- {
- gtk_image_set_from_pixbuf (ctx->preview_image, pixbuf);
- }
- }
-
- /* Also update window title based on filename */
- short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
-
EXTRACTOR_METATYPE_FILENAME,
- -1);
- if (NULL == short_fn)
- {
- gtk_window_set_title (ctx->edit_publication_window, _("<unnamed>"));
- }
- else
- {
- /* FIXME: ensure that short_fn is UTF-8 encoded */
- gtk_window_set_title (ctx->edit_publication_window, short_fn);
- GNUNET_free (short_fn);
- }
- return GNUNET_SYSERR; /* only visit top-level item */
-}
-
-
-/**
- * Open the dialog to edit file information data.
- *
- * @param parent parent window of the dialog
- * @param fip information about the file information that is to be edited
- * @param allow_no_keywords is it OK to close the dialog without any keywords?
- * also used to indicate that this is a namespace
operation
- * (FIXME: overloaded/badly-named argument)
- * @param anon_liststore liststore with anonymity options (FIXME: bad sharing)
- * @param cb function to call when the dialog is closed
- * @param cb_cls closure for 'cb'
- */
-void
-GNUNET_FS_GTK_edit_publish_dialog (GtkWindow * parent,
- struct GNUNET_FS_FileInformation *fip,
- int allow_no_keywords,
- GtkListStore *anon_liststore,
- GNUNET_FS_GTK_EditPublishDialogCallback cb,
- gpointer cb_cls)
-{
- GtkTreeIter iter;
- gint code;
- GtkComboBox *pubtypes_combo;
- GtkLabel *index_label;
- GtkLabel *root_label;
- struct EditPublicationDialogContext *ctx;
- GtkTreeSelection *meta_selection;
- GtkTreeSelection *keywords_selection;
-
- ctx = GNUNET_malloc (sizeof (struct EditPublicationDialogContext));
- ctx->fip = fip;
- ctx->preview_changed = GNUNET_NO;
- ctx->allow_no_keywords = allow_no_keywords;
- ctx->is_directory = GNUNET_FS_file_information_is_directory (fip);
- ctx->cb = cb;
- ctx->cb_cls = cb_cls;
- ctx->meta_combo_selected_type_id = -1;
- ctx->builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_edit_publication.glade", ctx);
-
- if (ctx->builder == NULL)
- {
- GNUNET_free (ctx);
- return;
- }
-
- /* obtain various widgets for use later */
- ctx->pubtypes_liststore =
- GTK_LIST_STORE (gtk_builder_get_object
- (ctx->builder,
"GNUNET_GTK_publication_types_liststore"));
- ctx->metatypes_liststore =
- GTK_LIST_STORE (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_publication_metadata_types_liststore"));
- ctx->meta_treeview = GTK_TREE_VIEW (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_edit_publication_metadata_tree_view"));
- ctx->keywords_treeview = GTK_TREE_VIEW (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_edit_publication_keyword_list_tree_view"));
- ctx->edit_publication_window =
- GTK_WINDOW (gtk_builder_get_object (ctx->builder,
- "GNUNET_GTK_edit_publication_window"));
- ctx->keywords_liststore = GTK_LIST_STORE (gtk_builder_get_object
- (ctx->builder,
"GNUNET_GTK_publication_keywords_liststore"));
- ctx->keyword_entry =
- GTK_ENTRY (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_edit_publication_keyword_entry"));
- ctx->confirm_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder,
"GNUNET_GTK_edit_publication_confirm_button"));
- ctx->preview_image =
- GTK_IMAGE (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_edit_publication_metadata_preview_image"));
- ctx->meta_liststore = GTK_LIST_STORE (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_publication_metadata_liststore"));
- ctx->root_entry = GTK_ENTRY (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_edit_publication_root_entry"));
- ctx->expiration_year_spin = GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_expiration_year_spin_button"));
- ctx->priority_spin = GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_priority_spin_button"));
- ctx->replication_spin = GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_replication_spin_button"));
- ctx->index_checkbutton = GTK_TOGGLE_BUTTON
- (gtk_builder_get_object
- (ctx->builder,
-
"GNUNET_GTK_edit_publication_index_checkbutton"));
- ctx->anonymity_combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->builder,
-
"GNUNET_GTK_edit_publication_anonymity_combobox"));
-
- /* Basic initialization of widgets models and visibility */
- gtk_combo_box_set_model (ctx->anonymity_combo,
- GTK_TREE_MODEL (anon_liststore));
- GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->builder);
-
- /* FIXME-UNCLEAN: are the following three even required anymore? */
- gtk_list_store_clear (ctx->keywords_liststore);
- gtk_list_store_clear (ctx->meta_liststore);
- gtk_entry_set_text (ctx->keyword_entry, "");
-
- pubtypes_combo =
- GTK_COMBO_BOX (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_edit_publication_type_combo"));
- if (gtk_combo_box_get_active_iter (pubtypes_combo, &iter))
- {
- gtk_tree_model_get (GTK_TREE_MODEL (ctx->pubtypes_liststore), &iter, 0,
&code, -1);
- change_metatypes (ctx, 0);
- }
- else
- gtk_combo_box_set_active (pubtypes_combo, 0);
-
- /* indexing does not apply to directories */
- gtk_widget_set_visible (GTK_WIDGET (ctx->index_checkbutton),
- ! ctx->is_directory);
- index_label = GTK_LABEL (gtk_builder_get_object
- (ctx->builder,
- "GNUNET_GTK_edit_publication_index_label"));
- gtk_widget_set_visible (GTK_WIDGET (index_label),
- ! ctx->is_directory);
-
- /* show root label only if we must have keywords, which is also only the
- case for namespaces (FIXME-UNCLEAN: overloaded use of the argument) */
- gtk_widget_set_visible (GTK_WIDGET (ctx->root_entry),
- !allow_no_keywords);
- root_label = GTK_LABEL (gtk_builder_get_object
- (ctx->builder,
"GNUNET_GTK_edit_publication_root_label"));
- gtk_widget_set_visible (GTK_WIDGET (root_label),
- !allow_no_keywords);
-
- /* FIXME-UNCLEAN: what if we already have keywords? Again, does not really
- apply to namespace-case, but this seems a bit ugly */
- gtk_widget_set_sensitive (ctx->confirm_button, allow_no_keywords ? TRUE :
FALSE);
-
-
- /* FIXME: these signal handlers can be set by (modern) versions of Glade */
- keywords_selection = gtk_tree_view_get_selection (ctx->keywords_treeview);
- g_signal_connect (G_OBJECT (keywords_selection), "changed",
- G_CALLBACK (keywords_selection_changed_cb), ctx);
- meta_selection = gtk_tree_view_get_selection (ctx->meta_treeview);
- g_signal_connect (G_OBJECT (meta_selection), "changed",
- G_CALLBACK (metadata_selection_changed_cb), ctx);
-
- /* import meta data and options */
- GNUNET_FS_file_information_inspect (fip, &file_information_import, ctx);
-
-
- /* Finally, display window */
- gtk_window_set_transient_for (ctx->edit_publication_window, parent);
- gtk_window_present (ctx->edit_publication_window);
-}
-
-
-/* end of gnunet-fs-gtk-edit_publish_dialog.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.h 2012-02-02
12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.h 2012-02-02
13:28:32 UTC (rev 19629)
@@ -1,66 +0,0 @@
-/*
- 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/gnunet-fs-gtk-edit_publish_dialog.h
- * @author Christian Grothoff
- */
-#ifndef GNUNET_FS_GTK_EDIT_PUBLISH_DIALOG_H
-#define GNUNET_FS_GTK_EDIT_PUBLISH_DIALOG_H
-
-#include "gnunet-fs-gtk-common.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_fs_service.h>
-
-
-/**
- * Function called when the edit publish dialog has been closed.
- *
- * @param cls closure
- * @param ret GTK_RESPONSE_OK if the dialog was closed with "OK"
- * @param root namespace root, NULL for file publishing
- */
-typedef void (*GNUNET_FS_GTK_EditPublishDialogCallback) (gpointer cls,
- int ret,
- const char *root);
-
-
-/**
- * Open the dialog to edit file information data.
- *
- * @param parent parent window of the dialog
- * @param fip information about the file information that is to be edited
- * @param allow_no_keywords is it OK to close the dialog without any keywords?
- * also used to indicate that this is a namespace
operation
- * (FIXME: overloaded/badly-named argument)
- * @param anon_liststore liststore with anonymity options (FIXME: bad sharing)
- * @param cb function to call when the dialog is closed
- * @param cb_cls closure for 'cb'
- */
-void
-GNUNET_FS_GTK_edit_publish_dialog (GtkWindow * parent,
- struct GNUNET_FS_FileInformation *fip,
- int allow_no_keywords,
- GtkListStore *anon_liststore,
- GNUNET_FS_GTK_EditPublishDialogCallback cb,
- gpointer cls);
-
-#endif
-/* end of gnunet-fs-gtk-edit_publish_dialog.h */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c 2012-02-02 12:57:54 UTC
(rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -1,2658 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2010, 2011, 2012 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-event_handler.c
- * @brief Main event handler for file-sharing
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk.h"
-#include "gnunet-fs-gtk-download.h"
-#include "gnunet-fs-gtk-event_handler.h"
-#include <string.h>
-
-
-/**
- * We have a single tab where we display publishing operations.
- * So there is only one instance of this struct.
- */
-struct PublishTab
-{
-
- /**
- * Frame for the tab.
- */
- GtkWidget *frame;
-
- /**
- * Associated builder.
- */
- GtkBuilder *builder;
-
- /**
- * Associated tree store.
- */
- GtkTreeStore *ts;
-};
-
-
-/**
- * Information we keep for each file or directory being published.
- * Used to quickly identify the tab and row of the operation; stored
- * in the user-context of the FS library for the publish operation.
- */
-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;
-
- /**
- * Is this the top-level entry for the publish operation
- * or sub-operation?
- */
- int is_top;
-};
-
-
-/**
- * Information we keep for each search result entry in any search tab.
- * An entry like this is also generated for downloads by-URI. Used to
- * quickly identify the tab and row of the result; stored in the
- * user-context of the FS library for the search result.
- */
-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;
-};
-
-
-
-/**
- * Head of linked list of tabs for searches.
- */
-static struct SearchTab *search_tab_head;
-
-/**
- * Tail of linked list of tabs for searches.
- */
-static struct SearchTab *search_tab_tail;
-
-/**
- * Special tab we use to for downloads-by-URIs and downloads
- * where the search tab has been closed ("parent lost").
- */
-static struct SearchTab *uri_tab;
-
-/**
- * Special tab we use to store publishing operations.
- */
-static struct PublishTab *publish_tab;
-
-/**
- * Row reference for the current search context menu.
- * FIXME-UNCLEAN: de-globalize?
- */
-static GtkTreeRowReference *current_context_row_reference;
-
-/**
- * Search tab used for the current search context menu.
- * FIXME-UNCLEAN: de-globalize?
- */
-static struct SearchTab *current_context_search_tab;
-
-
-
-/* ***************** Search event handling ****************** */
-
-/**
- * This should get the default download directory (so that GNUnet
- * won't offer the user to download files to the 'bin' subdirectory,
- * or whatever is the cwd). Returns NULL on failure (such as
- * non-existend directory). Should also preserve the last setting (so
- * if the user saves files somewhere else, next time we default to
- * somewhere else, at least until application restart, or maybe even
- * between application restarts).
- *
- * Fills the 'buffer' up to 'size' bytes, returns a pointer to it.
- */
-static char *
-get_default_download_directory (char *buffer, size_t size)
-{
- /* FIXME-FEATURE: implement... */
- return NULL;
-}
-
-
-/**
- * Called recursively to build a suggested filename by prepending
- * suggested names for its parent directories (if any).
- *
- * @param tm tree model this function gets the data from
- * @param iter current position in the tree, for which we want a suggested
filename
- * @param top GNUNET_YES for the original call to this function,
- * GNUNET_NO for recursive calls; used to decide if the
- * current call is eligible to set 'anonymity' and 'local_parents'
- * @param local_parents set to GNUNET_YES if all parents are directories, and
are downloaded.
- * @param anonymity set to the anonymity level of the closest ancestor
download (if any);
- * set to "-1" for uninitialized initially (will be left
at -1 if
- * no suitable parent download was found)
- * @param filename_is_absolute set to GNUNET_YES if the suggestion is an
absolute filename,
- * GNUNET_NO for relative filenames (gotten from
meta data)
- * @return suggested filename, possibly NULL
- */
-static char *
-get_suggested_filename_anonymity (GtkTreeModel *tm,
- GtkTreeIter *iter,
- int top,
- int *local_parents,
- int *anonymity,
- int *filename_is_absolute)
-{
- char *result;
- char *dirname;
- char *local_filename;
- char *filename;
- int downloaded_anonymity;
- int have_a_parent;
- struct GNUNET_CONTAINER_MetaData *meta;
- GtkTreeIter parent;
- const char *basename;
- char *dot;
-
- /* FIXME-BUG-MAYBE: this function is likely responsible for not always
- suggesting the best filename... To be investigated some more... */
- gtk_tree_model_get (tm, iter, 0, &meta,
- 15, &local_filename,
- 16, &downloaded_anonymity,
- -1);
- if ( (NULL == local_filename) && (GNUNET_NO == top) )
- *local_parents = GNUNET_NO;
- if ( (downloaded_anonymity != -1) && (*anonymity == -1) && (GNUNET_NO ==
top) )
- *anonymity = downloaded_anonymity;
- if (gtk_tree_model_iter_parent (tm, &parent, iter))
- {
- have_a_parent = GNUNET_YES;
- dirname = get_suggested_filename_anonymity (tm, &parent, GNUNET_NO,
- local_parents, anonymity,
- filename_is_absolute);
- }
- else
- {
- have_a_parent = GNUNET_NO;
- dirname = NULL;
- if (GNUNET_NO == top)
- *local_parents = GNUNET_NO;
- }
- if (local_filename == NULL)
- {
- filename = GNUNET_FS_meta_data_suggest_filename (meta);
- }
- else
- {
- /* This directory was downloaded as /foo/bar/baz/somedirname
- * Hopefully, "somedirname" is actually "somedir.gnd"
- * We need to strip the ".gnd" part to get "somedir", which is
- * what we're going to use instead of suggested original filename
- * Without the .gnd extension we're going to just use a copy
- * of the directory file name - and that would fail. Sad.
- */
- if ( (NULL == dirname) && (GNUNET_NO == have_a_parent))
- {
- /* This is the ealderlest parent directory. Use absolute path. */
- basename = (const char *) local_filename;
- *filename_is_absolute = GNUNET_YES;
- }
- else
- {
- basename = GNUNET_STRINGS_get_short_name (local_filename);
- }
- if ( (NULL != basename) && (strlen (basename) > 0) )
- {
- filename = GNUNET_strdup (basename);
- dot = strrchr (filename, '.');
- if (dot)
- *dot = '\0';
- }
- else
- {
- filename = GNUNET_FS_meta_data_suggest_filename (meta);
- }
- }
- if ( (NULL != dirname) && (NULL != filename) )
- {
- GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename);
- GNUNET_free (filename);
- GNUNET_free (dirname);
- return result;
- }
- if (NULL != filename)
- return filename;
- return NULL;
-}
-
-
-/**
- * This function is called when the user double-clicks on a search
- * result. Begins the download, if necessary by opening the "save as"
- * window.
- *
- * @param tree_view tree view with the details
- * @param path path selecting which entry we want to download
- * @param tab the search tab where the user triggered the download request
- * @param is_recursive was the request for a recursive download?
- */
-static void
-start_download (GtkTreeView *tree_view,
- GtkTreePath *path,
- struct SearchTab *tab,
- int is_recursive)
-{
- GtkTreeModel *tm;
- GtkTreeIter iter;
- struct GNUNET_FS_Uri *uri;
- struct GNUNET_CONTAINER_MetaData *meta;
- struct SearchResult *sr;
- gchar *mime;
- struct DownloadContext *dc;
- char *buf = NULL;
- char *tmp;
- size_t tmplen;
- char cwd[FILENAME_MAX];
- char *download_directory;
- char *filename;
- int local_parents;
- int have_a_suggestion;
- int anonymity;
- int filename_is_absolute;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Starting a %sdownload\n",
- is_recursive ? "recursive " : "");
-
- 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);
- if (NULL == uri)
- {
- /* user clicked on directory that was opened (not downloaded!), so we
- have no URI and downloading makes no sense. Ignore! */
- g_free (mime);
- return;
- }
- if (!(GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))
- {
- /* can only download chk/loc URIs, ignore */
- g_free (mime);
- return;
- }
-
- download_directory = get_default_download_directory (cwd, sizeof (cwd));
- /* If no download directory is known, try working directory */
- if (download_directory == NULL)
- download_directory = getcwd (cwd, sizeof (cwd));
- /* Calculate suggested filename */
- local_parents = GNUNET_YES;
- anonymity = -1;
- filename_is_absolute = GNUNET_NO;
- filename = get_suggested_filename_anonymity (tm, &iter, GNUNET_YES,
- &local_parents, &anonymity,
- &filename_is_absolute);
- have_a_suggestion = GNUNET_NO;
- if (NULL != download_directory)
- {
- if (NULL == filename)
- {
- buf = GNUNET_strdup (download_directory);
- }
- else
- {
- have_a_suggestion = GNUNET_YES;
- if (filename_is_absolute)
- GNUNET_asprintf (&tmp, "%s", filename);
- else
- GNUNET_asprintf (&tmp, "%s%s%s",
- download_directory,
- DIR_SEPARATOR_STR,
- filename);
- tmplen = strlen (tmp);
- /* now, if we have a directory, replace trailing '/' with ".gnd" */
- if (GNUNET_YES ==
- GNUNET_FS_meta_data_test_for_directory (meta))
- {
- if ( (tmp[tmplen-1] == '/') ||
- (tmp[tmplen-1] == '\\') )
- tmp[tmplen-1] = '\0';
- GNUNET_asprintf (&buf,
- "%s%s",
- tmp,
- GNUNET_FS_DIRECTORY_EXT);
- GNUNET_free (tmp);
- }
- else
- {
- buf = tmp;
- }
- }
- }
- GNUNET_free_non_null (filename);
-
- /* now setup everything for the save-as dialog */
- dc = GNUNET_malloc (sizeof (struct DownloadContext));
- dc->uri = GNUNET_FS_uri_dup (uri);
- dc->mime = mime;
- dc->filename = buf;
- dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
- dc->rr = gtk_tree_row_reference_new (tm, path);
- dc->sr = sr->result;
- dc->anonymity = anonymity;
- dc->is_recursive = is_recursive;
- dc->tab = tab;
- if ( (GNUNET_YES == local_parents) &&
- (GNUNET_YES == have_a_suggestion) )
- /* Skip the dialog, call directly */
- GNUNET_FS_GTK_download_context_start_download (dc);
- else
- GNUNET_FS_GTK_open_download_as_dialog (dc);
-}
-
-
-/**
- * An item was selected from the context menu; destroy the menu shell.
- *
- * @param menushell menu to destroy
- * @parma user_data the 'struct DownloadEntry' for the menu (unused)
- */
-static void
-search_list_popup_selection_done (GtkMenuShell *menushell,
- gpointer user_data)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Item selected in menu shell %p, destroying it.\n",
- menushell);
- gtk_widget_destroy (GTK_WIDGET (menushell));
-}
-
-
-/**
- * This function is called when the user double-clicks on a search
- * result. Begins the download, if necessary by opening the "save as"
- * window.
- *
- * @param tree_view tree view with the details
- * @param path path selecting which entry we want to download
- * @param column unused entry specifying which column the mouse was in
- * @param user_data the 'struct SearchTab' that was activated
- */
-static void
-start_download_row_activated (GtkTreeView * tree_view, GtkTreePath * path,
- GtkTreeViewColumn * column, gpointer user_data)
-{
- struct SearchTab *tab = user_data;
-
- start_download (tree_view, path, tab, GNUNET_NO);
-}
-
-
-/**
- * "Download" was selected in the current search context menu.
- *
- * @param item the 'download' menu item
- * @parma user_data the 'struct DownloadEntry' to download.
- */
-static void
-start_download_ctx_menu (GtkMenuItem *item, gpointer user_data)
-{
- 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, current_context_search_tab, GNUNET_NO);
- gtk_tree_path_free (path);
- current_context_search_tab = NULL;
-}
-
-
-/**
- * "Download recursively" was selected in the current search context menu.
- *
- * @param item the 'download recursively' menu item
- * @parma user_data the 'struct DownloadEntry' to download.
- */
-static void
-start_download_recursively_ctx_menu (GtkMenuItem *item, gpointer user_data)
-{
- 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, current_context_search_tab, GNUNET_YES);
- gtk_tree_path_free (path);
- current_context_search_tab = NULL;
-}
-
-
-/**
- * Download "abort" was selected in the current search context menu.
- *
- * @param item the 'abort' menu item
- * @parma user_data the 'struct DownloadEntry' to abort.
- */
-static void
-abort_download_ctx_menu (GtkMenuItem *item, gpointer user_data)
-{
- struct DownloadEntry *de = user_data;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Aborting download DE=%p\n",
- de);
- GNUNET_assert (de->dc != NULL);
- GNUNET_FS_download_stop (de->dc, GNUNET_YES);
- current_context_search_tab = NULL;
-}
-
-
-/**
- * Copy current URI to clipboard was selected in the current context menu.
- *
- * @param item the 'copy-to-clipboard' menu item
- * @parma user_data NULL
- */
-static void
-copy_uri_to_clipboard_ctx_menu (GtkMenuItem *item, gpointer user_data)
-{
- GtkTreePath *path;
- GtkTreeView *tv;
- GtkTreeModel *tm;
- GtkTreeIter iter;
- struct GNUNET_FS_Uri *uri;
- char *uris;
- GtkClipboard *cb;
-
- if (NULL == current_context_row_reference)
- {
- 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 (! 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);
-}
-
-
-/**
- * Context menu was requested for a search result list.
- * Compute which menu items are applicable and display
- * an appropriate menu.
- *
- * @param tm tree model underlying the tree view where the event happened
- * @param tab tab where the event happened
- * @param event_button the event
- * @return FALSE if no menu could be popped up,
- * TRUE if there is now a pop-up menu
- */
-static gboolean
-search_list_popup (GtkTreeModel *tm,
- struct SearchTab *tab,
- gint init_button,
- guint32 event_time,
- GtkTreeIter *iter)
-{
- GtkMenu *menu;
- GtkWidget *child;
- GtkTreePath *path;
- struct SearchResult *sr;
- struct GNUNET_FS_Uri *uri;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating a menu for SR=%p, DE=%p\n",
- sr,
- sr->download);
-
- /* FIXME-UNCLEAN: move these to some menu context struct
- (de-globalize) */
- 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 = gtk_tree_model_get_path (tm, iter);
- current_context_row_reference = gtk_tree_row_reference_new (tm, path);
- gtk_tree_path_free (path);
-
- gtk_tree_model_get (tm, iter, 1, &uri, 9, &sr, -1);
-
- menu = GTK_MENU (gtk_menu_new ());
- if ( (NULL == sr->download) &&
- (NULL != uri) )
- {
- /* only display download menus if there is a URI */
- 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);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
-
- child = gtk_menu_item_new_with_label (_("Download _recursively"));
- g_signal_connect (child, "activate",
- G_CALLBACK (start_download_recursively_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);
- }
- if (NULL != sr->download)
- {
- 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);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
- }
- if (NULL != uri)
- {
- 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);
- }
- g_signal_connect (menu, "selection-done",
- G_CALLBACK (search_list_popup_selection_done), NULL);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
- gtk_menu_popup (menu, NULL, NULL, NULL, NULL, init_button, event_time);
- return TRUE;
-}
-
-
-/**
- * We got a 'popup-menu' event, display the context menu.
- *
- * @param widget the tree view where the event happened
- * @param user_data the 'struct SearchTab' of the tree view
- * @return FALSE if no menu could be popped up,
- * TRUE if there is now a pop-up menu
- */
-static gboolean
-search_list_on_popup (GtkWidget *widget, gpointer user_data)
-{
- GtkTreeView *tv = GTK_TREE_VIEW (widget);
- struct SearchTab *tab = user_data;
- GtkTreeSelection *sel;
- GtkTreeIter iter;
- GtkTreeModel *tm;
-
- sel = gtk_tree_view_get_selection (tv);
- if (! gtk_tree_selection_get_selected (sel, &tm, &iter))
- return FALSE; /* nothing selected */
- return search_list_popup (tm, tab, 0, gtk_get_current_event_time (), &iter);
-}
-
-
-/**
- * We got a right-click on the search result list. Display the context
- * menu.
- *
- * @param widget the GtkTreeView with the search result list
- * @param event the event, we only care about button events
- * @param user_data the 'struct SearchTab' the widget is in
- * @return FALSE if no menu could be popped up,
- * TRUE if there is now a pop-up menu
- */
-static gboolean
-search_list_on_menu (GtkWidget * widget,
- GdkEvent * event,
- gpointer user_data)
-{
- GtkTreeView *tv = GTK_TREE_VIEW (widget);
- GdkEventButton *event_button = (GdkEventButton *) event;
- struct SearchTab *tab = user_data;
- GtkTreeModel *tm;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- if ( (event->type != GDK_BUTTON_PRESS) ||
- (event_button->button != 3) )
- return FALSE; /* not a right-click */
- if (! gtk_tree_view_get_path_at_pos (tv,
- event_button->x, event_button->y,
- &path, NULL, NULL, NULL))
- return FALSE; /* click outside of area with values, ignore */
- tm = gtk_tree_view_get_model (tv);
- if (! gtk_tree_model_get_iter (tm, &iter, path))
- return FALSE; /* not sure how we got a path but no iter... */
- gtk_tree_path_free (path);
- return search_list_popup (tm, tab,
- event_button->button,
- event_button->time,
- &iter);
-}
-
-
-/**
- * Recalculate and update the label for a search, as we have
- * received additional search results.
- *
- * @param tab search tab for which we should update the label
- */
-static void
-update_search_label (struct SearchTab *tab)
-{
- char *label_text;
-
- while (tab->parent != NULL)
- tab = tab->parent->tab;
- if (tab->num_results > 0)
- GNUNET_asprintf (&label_text, "%.*s%s (%u)", 20, tab->query_txt,
- strlen (tab->query_txt) > 20 ? "..." : "",
- tab->num_results);
- else
- GNUNET_asprintf (&label_text, "%.*s%s", 20, tab->query_txt,
- strlen (tab->query_txt) > 20 ? "..." : "");
- gtk_label_set_text (tab->label, label_text);
- gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), tab->query_txt);
- GNUNET_free (label_text);
-}
-
-
-/**
- * Close a search tab and free associated state. Assumes that the
- * respective tree model has already been cleaned up (this just
- * updates the notebook and frees the 'tab' itself).
- *
- * @param tab search tab to close
- */
-static void
-close_search_tab (struct SearchTab *tab)
-{
- GtkNotebook *notebook;
- int index;
- int i;
-
- if (tab->parent != NULL)
- {
- /* not a top-level search (namespace update 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);
- if (tab == uri_tab)
- uri_tab = NULL;
- GNUNET_free (tab);
-}
-
-
-/**
- * Free a particular search result and remove the respective
- * entries from the respective tree store. This function
- * is called when a search is stopped to clean up the state
- * of the tab.
- *
- * @param sr the search result to clean up
- */
-static void
-free_search_result (struct SearchResult *sr)
-{
- GtkTreePath *tp;
- GtkTreeModel *tm;
- GtkTreeIter iter;
- struct GNUNET_FS_Uri *uri;
- struct GNUNET_CONTAINER_MetaData *meta;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Freeing a search result SR=%p\n",
- sr);
- if ( (NULL == sr) ||
- (NULL == sr->rr) ||
- (NULL == (tm = gtk_tree_row_reference_get_model (sr->rr))) ||
- (NULL == (tp = gtk_tree_row_reference_get_path (sr->rr))) )
- {
- GNUNET_break (0);
- return;
- }
- if (! gtk_tree_model_get_iter (tm, &iter, tp))
- {
- GNUNET_break (0);
- gtk_tree_path_free (tp);
- return;
- }
- 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);
- (void) gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter);
- GNUNET_free (sr);
-}
-
-
-/**
- * Selected row has changed in search result tree view, update preview
- * and metadata areas.
- *
- * @param tv the tree view in a search tab where the selection changed
- * @param user_data the 'struct SearchTab' that contains the tree view
- */
-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 (! gtk_tree_selection_get_selected (sel, &model, &iter))
- {
- /* nothing selected, clear preview */
- gtk_image_clear (image);
- return;
- }
- meta = NULL;
- pixbuf = NULL;
- gtk_tree_model_get (model, &iter, 0, &meta, 3, &pixbuf, -1);
- if (NULL != pixbuf)
- {
- gtk_image_set_from_pixbuf (image, pixbuf);
- g_object_unref (G_OBJECT (pixbuf));
- }
- if (NULL != meta)
- GNUNET_CONTAINER_meta_data_iterate (meta,
-
&GNUNET_FS_GTK_add_meta_data_to_list_store,
- ms);
-}
-
-
-/**
- * Page switched in main notebook, update thumbnail and
- * metadata views.
- *
- * @param dummy widget emitting the event, unused
- * @param data master Gtk builder, unused
- */
-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);
- for (tab = search_tab_head; NULL != tab; tab = tab->next)
- {
- if (tab->frame != w)
- continue;
- tv = GTK_TREE_VIEW (gtk_builder_get_object
- (tab->builder, "_search_result_frame"));
- update_meta_data_views (tv, tab);
- return;
- }
- /* active tab is not a search tab (likely the 'publish' tab),
- clear meta data and preview widgets */
- 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);
-}
-
-
-/**
- * User clicked on the 'close' button for a search tab. Tell FS to stop the
search.
- *
- * @param button the 'close' button
- * @param user_data the 'struct SearchTab' of the tab to close
- */
-static void
-stop_search (GtkButton *button, gpointer user_data)
-{
- struct SearchTab *tab = user_data;
- struct GNUNET_FS_SearchContext *sc;
-
- sc = tab->sc;
- if (NULL == sc)
- {
- GNUNET_break (0);
- return;
- }
- tab->sc = NULL;
- GNUNET_FS_search_stop (sc);
- gtk_widget_hide (GTK_WIDGET (button));
- gtk_widget_hide (tab->pause_button);
- gtk_widget_hide (tab->play_button);
-}
-
-
-/**
- * The user clicked on the 'pause' button for a search tab. Tell FS to pause
the search.
- *
- * @param button the 'pause' button
- * @param user_data the 'struct SearchTab' of the tab to pause
- */
-static void
-pause_search (GtkButton *button, gpointer user_data)
-{
- struct SearchTab *tab = user_data;
-
- if (NULL == tab->sc)
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_FS_search_pause (tab->sc);
- gtk_widget_show (tab->play_button);
- gtk_widget_hide (tab->pause_button);
-}
-
-
-/**
- * The user clicked on the 'resume' button for a search tab. Tell FS to
resume the search.
- *
- * @param button the 'resume' button
- * @param user_data the 'struct SearchTab' of the tab to resume
- */
-static void
-continue_search (GtkButton * button, gpointer user_data)
-{
- struct SearchTab *tab = user_data;
-
- if (NULL == tab->sc)
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_FS_search_continue (tab->sc);
- gtk_widget_show (tab->pause_button);
- gtk_widget_hide (tab->play_button);
-}
-
-
-/**
- * User clicked on the 'clean' button of a search tab.
- * 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.
- *
- * @param button the button pressed by the user
- * @param user_data the 'struct SearchTab' of the respective tab to clean up
- */
-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;
- /* FIXME-BUG: this is a tree, what about cleaning up
- of the children? */
- do
- {
- gtk_tree_model_get (tm, &iter, 9, &sr, -1);
- if ( (sr->download != NULL) &&
- (sr->download->is_done == GNUNET_YES) )
- {
- /* got a finished download, stop it */
- GNUNET_FS_download_stop (sr->download->dc, GNUNET_YES);
- }
- if ( (NULL == sr->download) &&
- (NULL == sr->result) )
- {
- /* no active download and no associated FS-API search result;
- so this must be some left-over entry from an opened
- directory; clean it up */
- free_search_result (sr);
- }
- }
- while (TRUE == gtk_tree_model_iter_next (tm, &iter));
-}
-
-
-/**
- * We received a search error message from the FS library.
- * Present it to the user in an appropriate form.
- *
- * @param tab search tab affected by the error
- * @param emsg the error message
- */
-static void
-handle_search_error (struct SearchTab *tab,
- const char *emsg)
-{
- gtk_label_set_text (tab->label, _("Error!"));
- gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), emsg);
-}
-
-
-/**
- * Obtain the string we will use to describe a search result from
- * the respective meta data.
- *
- * @param meta meta data to inspect
- * @return description of the result in utf-8, never NULL
- */
-static char *
-get_description_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta)
-{
- char *desc;
- char *utf8_desc;
-
- 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)
- return GNUNET_strdup (_("no description supplied"));
- utf8_desc =
- GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc,
- strlen (desc) + 1);
- GNUNET_free (desc);
- if (utf8_desc == NULL)
- return GNUNET_strdup (_("no description supplied"));
- return utf8_desc;
-}
-
-
-/**
- * Obtain the mime type (or format description) will use to describe a search
result from
- * the respective meta data.
- *
- * @param meta meta data to inspect
- * @return mime type to use, possibly NULL
- */
-static char *
-get_mimetype_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta)
-{
- return GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
-
EXTRACTOR_METATYPE_MIMETYPE,
-
EXTRACTOR_METATYPE_FORMAT,
- -1);
-}
-
-
-/**
- * Some additional information about a search result has been
- * received. Update the view accordingly.
- *
- * @param sr search result that is being updated
- * @param meta updated meta data
- * @param availability_rank updated availability information
- * @param availability_certainty updated availability certainty
- * @param applicability_rank updated applicability information
- */
-static void
-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)
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Updating search result SR=%p with %d, %u, %u\n",
- sr, availability_rank,
- availability_certainty, applicability_rank);
- desc = get_description_from_metadata (meta);
- mime = get_mimetype_from_metadata (meta);
- 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 (NULL != ometa)
- 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);
- }
-}
-
-
-/**
- * Add a search result to the given search tab. This function is called
- * not only for 'normal' search results but also for directories that
- * are being opened and if the user manually enters a URI.
- *
- * @param tab search tab to extend, never NULL
- * @param iter set to position where search result is added (OUT only)
- * @param parent_rr reference to parent entry in search tab, NULL for normal
- * search results,
- * @param uri uri to add, can be NULL for top-level entry of a directory
opened from disk
- * (in this case, we don't know the URI and should
probably not
- * bother to calculate it)
- * @param meta metadata of the entry
- * @param result associated FS search result (can be NULL if this result
- * was part of a directory)
- * @param applicability_rank how relevant is the result
- * @return struct representing the search result (also stored in the tree
- * model at 'iter')
- */
-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 (NULL == uri)
- {
- /* opened directory file */
- fsize = 0;
- status_colour = "gray";
- mime = NULL; /* FIXME-FEATURE-MAYBE: should we set mime to directory? */
- uris = GNUNET_strdup (_("no URI"));
- }
- else
- {
- if ( (GNUNET_FS_uri_test_loc (uri)) ||
- (GNUNET_FS_uri_test_chk (uri)) )
- {
- fsize = GNUNET_FS_uri_chk_get_file_size (uri);
- mime = get_mimetype_from_metadata (meta);
- status_colour = "white";
- }
- else
- {
- /* FIXME-FEATURE-MAYBE: create mime type for namespaces? */
- /* FIXME-BUG-MAYBE: can we encounter ksk URIs here too? */
- fsize = 0;
- mime = GNUNET_strdup ("GNUnet namespace");
- status_colour = "lightgreen";
- }
- uris = GNUNET_FS_uri_to_string (uri);
- }
- desc = get_description_from_metadata (meta);
- pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
-
- sr = GNUNET_malloc (sizeof (struct SearchResult));
- sr->result = result;
- sr->tab = tab;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Allocated a search result SR=%p\n",
- sr);
- 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 (! 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, 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 */
- 14, (guint64) 0, /* completed */
- 15, NULL, /* downloaded_filename */
- 16, -1, /* downloaded_anonymity */
- -1);
- if (pixbuf != NULL)
- g_object_unref (pixbuf);
- GNUNET_free (uris);
- GNUNET_free (desc);
- GNUNET_free_non_null (mime);
-
- /* remember in 'sr' where we added the result */
- 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);
-
- /* move up to the outermost tab, in case this is an 'inner'
- search (namespace update case) */
- while (tab->parent != NULL)
- tab = tab->parent->tab;
- tab->num_results++;
-
- return sr;
-}
-
-
-/**
- * We have received a search result from the FS API. Add it to the
- * respective search tab. The search result can be an 'inner'
- * search result (updated result for a namespace search) or a
- * top-level search result. Update the tree view and the label
- * of the search tab accordingly.
- *
- * @param tab the search tab where the new result should be added
- * @param parent parent search result (if this is a namespace update result),
or NULL
- * @param uri URI of the search result
- * @param meta meta data for the result
- * @param result FS API handle to the result
- * @param applicability_rank how applicable is the result to the query
- * @return struct representing the search result (also stored in the tree
- * model at 'iter')
- */
-static struct SearchResult *
-process_search_result (struct SearchTab *tab,
- 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 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 search tab.
- *
- * @param sc context with FS for the search, NULL for none (open-URI/orphan
tab)
- * @param query the query, NULL for none (open-URI/orphan tab)
- * @return search tab handle
- */
-static struct SearchTab *
-setup_search_tab (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)
- {
- /* no real query, tab is for non-queries, use special label */
- tab->query_txt = GNUNET_strdup ("*");
- }
- else
- {
- /* FS_uri functions should produce UTF-8, so let them be */
- 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 ("gnunet_fs_gtk_search_tab.glade",
- tab);
- 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));
- g_object_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));
- g_object_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"));
-
- /* FIXME-UNCLEAN: connect these signals using glade!!! */
- 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; FIXME-UNCLEAN: again, connect these with glade... */
- 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_row_activated), 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);
- g_signal_connect (G_OBJECT (tv), "popup-menu",
- G_CALLBACK (search_list_on_popup), 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, that is a subtree representing namespace
- * 'update' results. We use a 'struct SearchTab' to represent this
- * sub-search. In the GUI, the presentation is similar to search
- * results in a directory, except that this is for a namespace search
- * result that gave pointers to an alternative keyword to use and this
- * is the set of the results found for this alternative keyword.
- *
- * All of the 'widget' elements of the returned 'search tab' reference
- * the parent search. The whole construction is essentially a trick
- * to allow us to store the FS-API's 'SearchContext' somewhere and to
- * find it when we get this kind of 'inner' search results (so that we
- * can then place them in the tree view in the right spot).
- *
- * FIXME-BUG-MAYBE: don't we need a bit more information then? Like exactly
where
- * this 'right spot' is? Not sure how just having 'sc' helps there,
- * as it is not a search result (!) to hang this up on! This might
- * essentially boil down to an issue with the FS API, not sure...
- *
- * @param sc context with FS for the search
- * @param parent parent search tab
- * @return struct representing the search result (also stored in the tree
- * model at 'iter')
- */
-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;
-}
-
-
-/**
- * Setup a new top-level entry in the URI/orphan tab. If necessary, create
- * the URI tab first.
- *
- * @param iter set to the new entry (OUT only)
- * @param srp set to search result (can be NULL)
- * @param meta metadata for the new entry
- * @param uri URI for the new entry
- * @return the 'uri_tab' the result was added to
- */
-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 SearchResult *sr;
- GtkNotebook *notebook;
- gint page;
-
- if (NULL == uri_tab)
- {
- uri_tab = setup_search_tab (NULL, NULL);
- gtk_widget_set_visible (uri_tab->close_button, FALSE);
- gtk_widget_set_visible (uri_tab->pause_button, FALSE);
- }
- /* make 'uri_tab' 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 (uri_tab->frame == gtk_notebook_get_nth_page (notebook, page))
- {
- gtk_notebook_set_current_page (notebook, page);
- break;
- }
- sr = GNUNET_GTK_add_search_result (uri_tab, iter, NULL, uri, meta, NULL, 0);
- if (NULL != srp)
- *srp = sr;
- return uri_tab;
-}
-
-
-
-/* ***************** Download event handling ****************** */
-
-
-
-/**
- * Change the (background) color of the given download entry.
- *
- * @param de entry to change
- * @param color name of the color to use
- */
-static void
-change_download_color (struct DownloadEntry *de,
- const char *color)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Changing download DE=%p color to %s\n",
- de, color);
- path = gtk_tree_row_reference_get_path (de->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_store_set (de->ts, &iter, 8, color, -1);
-}
-
-
-/**
- * A download operation was stopped. Remove all state associated with
- * it and reset the search result's background color to 'white'.
- *
- * @param de the download that was stopped
- */
-static void
-stop_download (struct DownloadEntry *de)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- GtkTreeModel *tm;
- struct SearchResult *search_result;
-
- tm = gtk_tree_row_reference_get_model (de->rr);
- path = gtk_tree_row_reference_get_path (de->rr);
- if (! gtk_tree_model_get_iter (tm, &iter, path))
- {
- gtk_tree_path_free (path);
- GNUNET_break (0);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_model_get (tm, &iter, 9, &search_result, -1);
- GNUNET_assert (search_result->download == de);
- search_result->download = NULL;
- change_download_color (de, "white");
- gtk_tree_row_reference_free (de->rr);
- GNUNET_FS_uri_destroy (de->uri);
- GNUNET_CONTAINER_meta_data_destroy (de->meta);
- GNUNET_free (de);
-}
-
-
-/**
- * Closure for 'add_directory_entry'.
- */
-struct AddDirectoryEntryContext
-{
-
- /**
- * Search tab where we need to expand the result list.
- */
- struct SearchTab *tab;
-
- /**
- * Row reference of parent (the directory).
- */
- GtkTreeRowReference *prr;
-
- /**
- * Do we need to check if the given entry already exists to
- * avoid adding it twice? Set to YES if 'add_directory_entry'
- * is called upon directory completion (so we might see all
- * entries again) and to NO if this is the initial download
- * and we're calling during a 'PROGRESS' event.
- */
- int check_duplicates;
-
-};
-
-
-/**
- * Function used to process entries in a directory. Whenever we
- * download a directory, this function is called on the entries in the
- * directory to add them to the search tab. Note that the function
- * maybe called twice for the same entry, once during incremental
- * processing and later once more when we have the complete directory.
- *
- * For the second round, the 'check_duplicates' flag will be set in
- * the closure. If called on an entry that already exists, the
- * function should simply do nothing.
- *
- * @param cls closure, our 'struct AddDirectoryEntryContext*'
- * @param filename name of the file in the directory
- * @param uri URI of the file, NULL for the directory itself
- * @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;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding directory entry `%s'\n",
- filename);
-
- if (NULL == uri)
- {
- /* directory meta data itself */
- /* FIXME-FEATURE-MAYBE: consider merging it with the meta data from
- the original search result... */
- return;
- }
- if (ade->check_duplicates == GNUNET_YES)
- {
- tm = gtk_tree_row_reference_get_model (ade->prr);
- path = gtk_tree_row_reference_get_path (ade->prr);
- if (! 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->tab, &iter, ade->prr, uri, meta, NULL,
- 0);
-}
-
-
-/**
- * We got an event that some download is progressing. Update the tree
- * model accordingly. If the download is a directory, try to display
- * the contents.
- *
- * @param de download entry that is progressing
- * @param size overall size of the download
- * @param completed number of bytes we have completed
- * @param block_data current block we've downloaded
- * @param offset offset of block_data in the overall file
- * @param block_size number of bytes in block_data
- * @param depth depth of the block in the ECRS tree
- */
-static void
-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)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Marking download progress for DE=%p, %llu/%llu, address@hidden
depth=%u\n",
- de, completed, size, block_size, offset, depth);
-
- path = gtk_tree_row_reference_get_path (de->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- /* FIXME-FEATURE: update availability-score here as well! */
- gtk_tree_store_set (de->ts, &iter,
- 4, (guint) ((size >
- 0) ? (100 * completed /
- size) : 100) /* progress */ ,
- 14, completed,
- -1);
- if ( (depth == 0) &&
- (block_size > 0) &&
- (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) )
- {
- /* got a data block of a directory, list its contents */
- struct AddDirectoryEntryContext ade;
-
- ade.tab = de->tab;
- 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))
- {
- /* Mime type was wrong, this is not a directory, update model! */
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_meta_data_delete (de->meta,
-
EXTRACTOR_METATYPE_MIMETYPE, NULL, 0));
- gtk_tree_store_set (de->ts, &iter,
- 10, "" /* unknown mime type */, -1);
- }
- }
-}
-
-
-/**
- * FS-API encountered an error downloading a file. Update the
- * view accordingly.
- *
- * @param de download that had an error
- * @param emsg error message to display
- */
-static void
-mark_download_error (struct DownloadEntry *de,
- const char *emsg)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- change_download_color (de, "red");
- de->is_done = GNUNET_YES;
- path = gtk_tree_row_reference_get_path (de->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_store_set (de->tab->ts, &iter, 4, 0, 7, emsg, -1);
-}
-
-
-/**
- * FS-API notified us that we're done with a download. Update the
- * view accordingly. If the download is a directory, try to display
- * the contents.
- *
- * @param de download that has finished
- * @param size overall size of the file
- * @param filename name of the downloaded file on disk (possibly a temporary
file)
- */
-static void
-mark_download_completed (struct DownloadEntry *de, uint64_t size,
- const char *filename)
-{
- struct AddDirectoryEntryContext ade;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Marking download completed for DE=%p, %llu-byte `%s'\n",
- de, size, filename);
-
- de->is_done = GNUNET_YES;
- mark_download_progress (de, size, size, NULL, 0, 0, 0);
- if ( (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) &&
- (filename != NULL) )
- {
- /* download was for a directory (and we have a temp file for scanning);
- add contents of the directory to the view */
- ade.tab = de->tab;
- ade.prr = de->rr;
- ade.check_duplicates = GNUNET_YES;
- GNUNET_FS_GTK_mmap_and_scan (filename, &add_directory_entry, &ade);
- }
- change_download_color (de, "green");
-}
-
-
-/**
- * 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.
- *
- * @param src_model source model
- * @param src_iter parent of the nodes to move
- * @param dst_model destination model
- * @param dst_iter new parent of the entries we are moving
- */
-static void
-copy_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, completed;
- 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;
- gchar *downloaded_filename;
- gint downloaded_anonymity;
-
- if (! gtk_tree_model_iter_children (src_model, &src_child, src_iter))
- return;
- 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, 14,
- &completed, 15, &downloaded_filename, 16,
- &downloaded_anonymity, -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, 14, completed, 15,
- downloaded_filename, 16,
- downloaded_anonymity, -1);
- g_free (filename);
- g_free (downloaded_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);
- search_result->result = NULL;
- 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);
- }
- copy_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).
- *
- * @param model model that contains the subtree to remove
- * @param iter root of the subtree to remove
- */
-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.
- *
- * @param de download where the parent (i.e. search) was lost
- */
-static void
-download_lost_parent (struct DownloadEntry *de)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- struct SearchTab *tab;
- GtkTreeRowReference *rr_old;
- GtkTreeModel *tm_old;
- GtkTreeIter iter_old;
- GtkTreeIter child;
- GtkTreeModel *model;
-
- /* first, move the root of the respective 'de'-tree */
- rr_old = de->rr;
- tab = GNUNET_GTK_add_to_uri_tab (&iter, &de->sr, de->meta, de->uri);
- de->sr->download = de;
- de->ts = tab->ts;
- model = GTK_TREE_MODEL (de->ts);
- path = gtk_tree_model_get_path (model, &iter);
- de->rr = gtk_tree_row_reference_new (model, path);
- gtk_tree_path_free (path);
- 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);
- if (! gtk_tree_model_get_iter (tm_old, &iter_old, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
-
- /* finally, move all children over as well */
- copy_children (tm_old, &iter_old, model, &iter);
- while (gtk_tree_model_iter_children (model, &child, &iter))
- delete_stale_subtree (model, &child);
-}
-
-
-/**
- * Setup a new download entry.
- *
- * @param de existing download entry for the download, or NULL (in which case
we create a fresh one)
- * @param pde parent download entry, or NULL
- * @param sr search result, or NULL
- * @param dc download context (for stopping)
- * @param uri the URI, must not be NULL
- * @param filename filename on disk
- * @param meta metadata
- * @param size total size
- * @param completed current progress
- * @return download entry struct for the download (equal to 'de' if 'de' was
not NULL)
- */
-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 char *filename,
- const struct GNUNET_CONTAINER_MetaData *meta, uint64_t size,
- uint64_t completed)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- struct SearchResult *srp;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Setting up download, initially DE=%p, PDE=%p for %p & %p into
%llu/%llu `%s'\n",
- de, pde, sr, dc, completed, size, filename);
- GNUNET_assert (NULL != uri);
- srp = NULL;
- if (NULL == de)
- {
- /* no existing download entry to build on, create a fresh one */
- de = GNUNET_malloc (sizeof (struct DownloadEntry));
- de->uri = GNUNET_FS_uri_dup (uri);
- }
- else
- {
- GNUNET_assert (GNUNET_YES == GNUNET_FS_uri_test_equal (de->uri, uri));
- }
- de->dc = dc;
- de->sr = sr;
- de->pde = pde;
- if ( (meta != NULL) && (de->meta == NULL) )
- de->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
- if (NULL != sr)
- {
- /* got a search result; display the download in the same location as the
search result */
- GNUNET_assert (sr->download == NULL);
- sr->download = de;
- de->rr = gtk_tree_row_reference_copy (sr->rr);
- de->ts = sr->tab->ts;
- de->tab = sr->tab;
- srp = sr;
- }
- if (NULL == de->rr)
- {
- /* Stand-alone download with no 'row'/search result affiliated
- with the download so far; create a fresh entry for this
- download in the URI tab */
- de->tab = GNUNET_GTK_add_to_uri_tab (&iter, &srp, 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);
- srp->download = de;
- }
- path = gtk_tree_row_reference_get_path (de->rr);
- if (! 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 */ ,
- 6, filename /* filename/description */ ,
- 8, "blue" /* status colour: pending */ ,
- 9, srp,
- 14, completed,
- -1);
- return de;
-}
-
-
-
-/* ***************** Publish event handling ****************** */
-
-
-
-/**
- * Change the (background) color of the given publish entry.
- *
- * @param pe entry to change
- * @param color name of the color to use
- */
-static void
-change_publish_color (struct PublishEntry *pe,
- const char *color)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Changing publish PE=%p color to %s\n",
- pe, color);
- path = gtk_tree_row_reference_get_path (pe->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_store_set (pe->tab->ts, &iter, 2, color, -1);
-}
-
-
-/**
- * We got an event that some publishing operation is progressing.
- * Update the tree model accordingly.
- *
- * @param pe publish entry that is progressing
- * @param size overall size of the file or directory
- * @param completed number of bytes we have completed
- */
-static void
-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 (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_store_set (pe->tab->ts, &iter, 3,
- (guint) ((size >
- 0) ? (100 * completed /
- size) : 100) /* progress */ ,
- -1);
-}
-
-
-/**
- * FS-API notified us that we're done with some publish operation.
- * Update the view accordingly.
- *
- * @param pe publish operation that has finished
- * @param uri resulting URI
- */
-static void
-handle_publish_completed (struct PublishEntry *pe,
- const struct GNUNET_FS_Uri *uri)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- char *uris;
-
- path = gtk_tree_row_reference_get_path (pe->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- pe->uri = GNUNET_FS_uri_dup (uri);
- uris = GNUNET_FS_uri_to_string (uri);
- gtk_tree_store_set (pe->tab->ts, &iter,
- 5, uris,
- -1);
- GNUNET_free (uris);
- change_publish_color (pe, "green");
-}
-
-
-/**
- * We received a publish error message from the FS library.
- * Present it to the user in an appropriate form.
- *
- * @param pe publishing operation affected by the error
- * @param emsg the error message
- */
-static void
-handle_publish_error (struct PublishEntry *pe,
- const char *emsg)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- path = gtk_tree_row_reference_get_path (pe->rr);
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- gtk_tree_path_free (path);
- return;
- }
- gtk_tree_path_free (path);
- gtk_tree_store_set (pe->tab->ts, &iter,
- 5, emsg,
- -1);
- change_publish_color (pe, "red");
-}
-
-
-/**
- * A publishing operation was stopped (in FS API). Free an entry in
- * the publish tab and its associated state.
- *
- * @param pe publishing operation that was stopped
- */
-static void
-handle_publish_stop (struct PublishEntry *pe)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- path = gtk_tree_row_reference_get_path (pe->rr);
- /* This is a child of a directory, and we've had that directory
- free'd already */
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
- {
- GNUNET_break (0);
- return;
- }
- (void) gtk_tree_store_remove (pe->tab->ts, &iter);
- gtk_tree_path_free (path);
- gtk_tree_row_reference_free (pe->rr);
- if (pe->uri != NULL)
- {
- GNUNET_FS_uri_destroy (pe->uri);
- pe->uri = NULL;
- }
- GNUNET_free (pe);
-}
-
-
-/**
- * The user clicked on the "close" button of the publishing tab.
- * Tell FS to stop all active publish operations. Then close the tab.
- *
- * @param button the stop button
- * @param user_data the 'struct PublishTab' that is being closed
- */
-static void
-stop_publishing (GtkButton * button, gpointer user_data)
-{
- struct PublishTab *tab = user_data;
- struct PublishEntry *ent;
- GtkTreeIter iter;
- GtkTreeModel *tm;
- GtkNotebook *notebook;
- int index;
- int i;
-
- GNUNET_assert (tab == publish_tab);
- /* stop all active operations */
- tm = GTK_TREE_MODEL (publish_tab->ts);
- if (gtk_tree_model_iter_children (tm, &iter, NULL))
- {
- do
- {
- gtk_tree_model_get (tm, &iter, 4, &ent, -1);
- GNUNET_FS_publish_stop (ent->pc);
- ent->pc = NULL;
- }
- while (TRUE == gtk_tree_model_iter_next (tm, &iter));
- }
-
- /* remove tab from notebook */
- 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 (publish_tab->frame == gtk_notebook_get_nth_page (notebook, i))
- index = i;
- gtk_notebook_remove_page (notebook, index);
-
- /* fully destroy tab */
- g_object_unref (publish_tab->builder);
- GNUNET_free (publish_tab);
- publish_tab = NULL;
-}
-
-
-/**
- * The user started a publishing operation. Add it to the publishing
- * tab. If needed, create the publishing tab.
- *
- * @param pc the FS-API's publishing context for the operation
- * @param fn the name of the file (or directory) that is being published
- * @param fsize size of the file
- * @param parent parent of this publishing operation (for recursive
operations), NULL for top-level operations
- * @return the publishing entry that will represent this operation
- */
-static struct PublishEntry *
-setup_publish (struct GNUNET_FS_PublishContext *pc, const char *fn,
- uint64_t fsize, struct PublishEntry *parent)
-{
- struct PublishEntry *ent;
- GtkTreeIter *pitrptr;
- GtkTreeIter iter;
- GtkTreeIter piter;
- GtkTreePath *path;
- GtkWindow *df;
- GtkWidget *tab_label;
- GtkWidget *close_button;
- GtkNotebook *notebook;
- char *size_fancy;
-
- if (NULL == publish_tab)
- {
- /* create new tab */
- publish_tab = GNUNET_malloc (sizeof (struct PublishTab));
- publish_tab->builder =
- GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_publish_tab.glade",
- publish_tab);
- df = GTK_WINDOW (gtk_builder_get_object
- (publish_tab->builder, "_publish_frame_window"));
- publish_tab->frame = gtk_bin_get_child (GTK_BIN (df));
- g_object_ref (publish_tab->frame);
- gtk_container_remove (GTK_CONTAINER (df), publish_tab->frame);
- gtk_widget_destroy (GTK_WIDGET (df));
-
- /* load tab_label */
- df = GTK_WINDOW (gtk_builder_get_object
- (publish_tab->builder, "_publish_label_window"));
- tab_label = gtk_bin_get_child (GTK_BIN (df));
- g_object_ref (tab_label);
- gtk_container_remove (GTK_CONTAINER (df), tab_label);
- gtk_widget_destroy (GTK_WIDGET (df));
-
- /* FIXME-UNCLEAN: connect these signals using GLADE!!! */
- /* get refs to widgets */
- close_button =
- GTK_WIDGET (gtk_builder_get_object
- (publish_tab->builder, "_publish_label_close_button"));
- g_signal_connect (G_OBJECT (close_button), "clicked",
- G_CALLBACK (stop_publishing), publish_tab);
- /* make visible */
- notebook =
- GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
- ("GNUNET_GTK_main_window_notebook"));
- gtk_notebook_insert_page (notebook, publish_tab->frame, tab_label, 0);
- gtk_widget_show (GTK_WIDGET (notebook));
- gtk_notebook_set_current_page (notebook, 0);
- publish_tab->ts =
- GTK_TREE_STORE (gtk_builder_get_object
- (publish_tab->builder, "_publish_frame_tree_store"));
- }
-
- /* decide where to insert in the tab */
- if (NULL == parent)
- {
- pitrptr = NULL;
- }
- else
- {
- /* create new iter from parent */
- path = gtk_tree_row_reference_get_path (parent->rr);
- if (TRUE !=
- gtk_tree_model_get_iter (GTK_TREE_MODEL (publish_tab->ts), &piter,
- path))
- {
- GNUNET_break (0);
- return NULL;
- }
- pitrptr = &piter;
- }
-
- /* create entry and perform insertion */
- ent = GNUNET_malloc (sizeof (struct PublishEntry));
- ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
- ent->tab = publish_tab;
- ent->pc = pc;
- size_fancy = GNUNET_STRINGS_byte_size_fancy (fsize);
- gtk_tree_store_insert_with_values (publish_tab->ts, &iter, pitrptr, G_MAXINT,
- 0, fn, 1, size_fancy, 2, "white", 3,
- (guint) 0 /* progress */ ,
- 4, ent, -1);
- GNUNET_free (size_fancy);
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (publish_tab->ts), &iter);
- ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (publish_tab->ts),
path);
- gtk_tree_path_free (path);
- return ent;
-}
-
-
-
-/* ***************** Master event handler ****************** */
-
-
-
-/**
- * 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)
- {
- handle_publish_error (ret,
- info->value.publish.specifics.resume.message);
- }
- else if (info->value.publish.specifics.resume.chk_uri != NULL)
- {
- handle_publish_completed (ret,
- info->value.publish.specifics.resume.chk_uri);
- }
- return ret;
- case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
- handle_publish_stop (info->value.publish.cctx);
- return NULL;
- case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
- mark_publish_progress (info->value.publish.cctx,
- info->value.publish.size,
- info->value.publish.completed);
- return info->value.publish.cctx;
- case GNUNET_FS_STATUS_PUBLISH_ERROR:
- handle_publish_error (info->value.publish.cctx,
- info->value.publish.specifics.error.message);
- return info->value.publish.cctx;
- case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
- handle_publish_completed (info->value.publish.cctx,
- info->value.publish.specifics.completed.chk_uri);
- return info->value.publish.cctx;
- case GNUNET_FS_STATUS_PUBLISH_STOPPED:
- handle_publish_stop (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.filename,
- 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.filename,
- info->value.download.specifics.resume.meta,
- info->value.download.size,
- info->value.download.completed);
- if (info->value.download.specifics.resume.message != NULL)
- mark_download_error (ret,
- info->value.download.specifics.resume.message);
- return ret;
- case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND:
- stop_download (info->value.download.cctx);
- return NULL;
- case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
- 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);
- return info->value.download.cctx;
- case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
- mark_download_error (info->value.download.cctx,
- info->value.download.specifics.error.message);
- return info->value.download.cctx;
- case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
- mark_download_completed (info->value.download.cctx,
- info->value.download.size,
- info->value.download.filename);
- return info->value.download.cctx;
- case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
- stop_download (info->value.download.cctx);
- return NULL;
- case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
- change_download_color (info->value.download.cctx, "yellow");
- return info->value.download.cctx;
- case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
- change_download_color (info->value.download.cctx, "blue");
- return info->value.download.cctx;
- case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT:
- download_lost_parent (info->value.download.cctx);
- return info->value.download.cctx;
- 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_tab (info->value.search.sc, info->value.search.query);
- case GNUNET_FS_STATUS_SEARCH_RESUME:
- ret = setup_search_tab (info->value.search.sc, info->value.search.query);
- if (info->value.search.specifics.resume.message)
- 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);
- 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);
- return ret;
- 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:
- 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);
- return info->value.search.specifics.update.cctx;
- case GNUNET_FS_STATUS_SEARCH_ERROR:
- handle_search_error (info->value.search.cctx,
- info->value.search.specifics.error.message);
- return info->value.search.cctx;
- 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_stopped.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;
-}
-
-
-/* end of gnunet-fs-gtk-event_handler.c */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.h
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.h 2012-02-02 12:57:54 UTC
(rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.h 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -1,241 +0,0 @@
-/*
- 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-event_handler.h
- * @brief Main event handler for file-sharing
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk-common.h"
-
-
-/**
- * State we keep for each (search) result entry in the
- * tree view of a search tab.
- */
-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;
-
- /**
- * Text of the search query.
- */
- char *query_txt;
-
- /**
- * GtkBuilder object for the search tab.
- */
- GtkBuilder *builder;
-
- /**
- * Frame instance of the search tab.
- */
- GtkWidget *frame;
-
- /**
- * The widget representing this search in the tab bar (not
- * a GtkLabel, contains the actual label and the buttons).
- */
- GtkWidget *tab_label;
-
- /**
- * Button to stop and close the search.
- */
- GtkWidget *close_button;
-
- /**
- * Button to clear all entries for downloads that have completed.
- */
- GtkWidget *clear_button;
-
- /**
- * Button to resume the search.
- */
- GtkWidget *play_button;
-
- /**
- * Button to pause the search.
- */
- GtkWidget *pause_button;
-
- /**
- * Textual label in the 'tab_label'
- */
- GtkLabel *label;
-
- /**
- * Tree store with the search results.
- */
- GtkTreeStore *ts;
-
- /**
- * Number of results we got for this search.
- */
- unsigned int num_results;
-
-};
-
-
-/**
- * Information we keep for each download.
- */
-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/orphan tab. If necessary, create
- * the URI tab first.
- *
- * @param iter set to the new entry (OUT only)
- * @param srp set to search result (can be NULL)
- * @param meta metadata for the new entry
- * @param uri URI for the new entry
- * @return the 'uri_tab' the result was added to
- */
-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, never NULL
- * @param iter set to position where search result is added (OUT only)
- * @param parent_rr reference to parent entry in search tab, NULL for normal
- * search results,
- * @param uri uri to add, can be NULL for top-level entry of a directory
opened from disk
- * (in this case, we don't know the URI and should
probably not
- * bother to calculate it)
- * @param meta metadata of the entry
- * @param result associated FS search result (can be NULL if this result
- * was part of a directory)
- * @param applicability_rank how relevant is the result
- * @return struct representing the search result (also stored in the tree
- * model at 'iter')
- */
-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 gnunet-fs-gtk-event_handler.h */
Deleted: gnunet-gtk/src/fs/gnunet-fs-gtk-main_window_file_publish.c
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk-main_window_file_publish.c 2012-02-02
12:57:54 UTC (rev 19628)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk-main_window_file_publish.c 2012-02-02
13:28:32 UTC (rev 19629)
@@ -1,1596 +0,0 @@
-/*
- 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/gnunet-fs-gtk-main_window_file_publish.c
- * @author Christian Grothoff
- */
-#include "gnunet-fs-gtk-common.h"
-#include "gnunet-fs-gtk.h"
-#include "gnunet-fs-gtk-edit_publish_dialog.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_fs_service.h>
-
-#define MARKER_DIR_FILE_SIZE "-"
-
-#define VERBOSE_PROGRESS GNUNET_NO
-
-struct AddDirClientContext;
-
-struct MainPublishingDialogContext
-{
- GtkBuilder *builder;
- GtkBuilder *main_window_builder;
- GtkTreeView *pseudonym_treeview;
- GtkTreeSelection *pseudonym_selection;
- GtkTreeModel *pseudonym_treemodel;
- GtkWidget *up_button;
- GtkWidget *down_button;
- GtkWidget *left_button;
- GtkWidget *right_button;
- GtkWidget *delete_button;
- GtkWidget *edit_button;
- GtkWidget *execute_button;
- GtkWidget *cancel_button;
- GtkTreeView *file_info_treeview;
- GtkTreeSelection *file_info_selection;
- GtkTreeModel *file_info_treemodel;
- GtkWindow *master_pubdialog;
-
- gulong open_directory_handler_id;
- GtkBuilder *open_directory_builder;
-
- gulong open_file_handler_id;
- GtkBuilder *open_file_builder;
-
- /* To keep multiple scanners running */
- struct AddDirClientContext *adddir_head;
- struct AddDirClientContext *adddir_tail;
-};
-
-/* One of these is kept for every directory being opened */
-struct AddDirClientContext
-{
- struct AddDirClientContext *prev;
- struct AddDirClientContext *next;
-
- struct GNUNET_FS_ProcessMetadataContext *pmc;
-
- struct MainPublishingDialogContext *ctx;
- struct GNUNET_FS_DirScanner *ds;
-
- struct GNUNET_FS_ShareTreeItem *directory_scan_result;
-
- struct GNUNET_FS_BlockOptions directory_scan_bo;
- int directory_scan_do_index;
-
- GtkBuilder *progress_dialog_builder;
- GtkWidget *progress_dialog;
- GtkProgressBar *progress_dialog_bar;
- GtkButton *progress_dialog_cancel;
- GtkTextView *progress_dialog_textview;
- GtkTextBuffer *progress_dialog_textbuffer;
- GtkTextMark *progress_dialog_textmark;
- GtkAdjustment *textview_vertial_adjustment;
-
- unsigned int done;
- unsigned int total;
-};
-
-
-static void
-selection_changed_cb (GtkTreeSelection * ts, struct
MainPublishingDialogContext *ctx);
-
-
-/**
- * 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;
-}
-
-/* Fill out the main publishing dialog context structure */
-static void
-init_ctx (struct MainPublishingDialogContext *ctx)
-{
- ctx->pseudonym_treeview = GTK_TREE_VIEW (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
-
- ctx->up_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_up_button"));
- ctx->down_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_down_button"));
- ctx->left_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_left_button"));
- ctx->right_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_right_button"));
- ctx->delete_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_delete_button"));
- ctx->edit_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_edit_button"));
- ctx->execute_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog_execute_button"));
- ctx->cancel_button = GTK_WIDGET (gtk_builder_get_object
- (ctx->builder , "GNUNET_GTK_master_publish_dialog_cancel_button"));
- ctx->file_info_treeview = GTK_TREE_VIEW (gtk_builder_get_object
- (ctx->builder,
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
-
- ctx->master_pubdialog =
- GTK_WINDOW (gtk_builder_get_object
- (ctx->builder, "GNUNET_GTK_master_publish_dialog"));
-
- ctx->file_info_selection = gtk_tree_view_get_selection
(ctx->file_info_treeview);
- ctx->file_info_treemodel = gtk_tree_view_get_model (ctx->file_info_treeview);
- ctx->pseudonym_selection = gtk_tree_view_get_selection
(ctx->pseudonym_treeview);
- ctx->pseudonym_treemodel = gtk_tree_view_get_model (ctx->pseudonym_treeview);
-
- g_signal_connect (G_OBJECT (ctx->file_info_selection), "changed",
- G_CALLBACK (selection_changed_cb), ctx);
- g_signal_connect (G_OBJECT (ctx->pseudonym_selection), "changed",
- G_CALLBACK (selection_changed_cb), ctx);
-}
-
-/**
- * Update selectivity in the master dialog.
- */
-static void
-update_selectivity (struct MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter parent;
- GtkTreeIter pred;
- int is_dir;
- struct GNUNET_FS_FileInformation *fip;
- int ns_ok;
- gchar *namespace_id;
-
- ns_ok = GNUNET_YES;
- if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection, NULL,
&iter))
- {
- gtk_tree_model_get (ctx->pseudonym_treemodel, &iter, 2, &namespace_id, -1);
- if (namespace_id == NULL)
- ns_ok = GNUNET_NO;
- else
- g_free (namespace_id);
- }
- /* Don't let the user close the dialog until all scanners are finished and
- * their windows are closed
- */
- if ((gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter))
- && (ns_ok == GNUNET_YES) && ctx->adddir_head == NULL)
- gtk_widget_set_sensitive (ctx->execute_button, TRUE);
- else
- gtk_widget_set_sensitive (ctx->execute_button, FALSE);
- if (ctx->adddir_head == NULL)
- gtk_widget_set_sensitive (ctx->cancel_button, TRUE);
- else
- gtk_widget_set_sensitive (ctx->cancel_button, FALSE);
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- gtk_widget_set_sensitive (ctx->up_button, FALSE);
- gtk_widget_set_sensitive (ctx->down_button, FALSE);
- gtk_widget_set_sensitive (ctx->left_button, FALSE);
- gtk_widget_set_sensitive (ctx->right_button, FALSE);
- gtk_widget_set_sensitive (ctx->delete_button, FALSE);
- gtk_widget_set_sensitive (ctx->edit_button, FALSE);
- return;
- }
- gtk_widget_set_sensitive (ctx->delete_button, TRUE);
- gtk_widget_set_sensitive (ctx->edit_button, TRUE);
-
- /* now figure out which move operations are currently legal */
- GNUNET_assert (TRUE == gtk_tree_selection_get_selected
(ctx->file_info_selection, NULL, &iter));
- if (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter))
- {
- gtk_widget_set_sensitive (ctx->down_button, TRUE);
- }
- else
- {
- gtk_widget_set_sensitive (ctx->down_button, FALSE);
- }
- GNUNET_assert (TRUE == gtk_tree_selection_get_selected
(ctx->file_info_selection, NULL, &iter));
- if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
- {
- gtk_widget_set_sensitive (ctx->left_button, TRUE);
- GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
- }
- else
- {
- gtk_widget_set_sensitive (ctx->left_button, FALSE);
- GNUNET_assert (TRUE == gtk_tree_model_get_iter_first
(ctx->file_info_treemodel, &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 (ctx->file_info_treemodel, &pred,
&iter))
- {
- gtk_tree_model_get (ctx->file_info_treemodel, &pred, 5, &fip, -1);
- is_dir = GNUNET_FS_file_information_is_directory (fip);
- GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
- }
- if (GNUNET_YES == is_dir)
- {
- gtk_widget_set_sensitive (ctx->right_button, TRUE);
- }
- else
- {
- gtk_widget_set_sensitive (ctx->right_button, FALSE);
- }
- if (GNUNET_SYSERR != is_dir)
- {
- gtk_widget_set_sensitive (ctx->up_button, TRUE);
- }
- else
- {
- gtk_widget_set_sensitive (ctx->up_button, FALSE);
- }
-}
-
-
-/**
- * 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 (struct MainPublishingDialogContext *ctx, 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;
-
- 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 (GTK_TREE_STORE (ctx->file_info_treemodel),
pos, iter, NULL);
- path = gtk_tree_model_get_path (ctx->file_info_treemodel, pos);
- row_reference = gtk_tree_row_reference_new (ctx->file_info_treemodel, 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, name);
- GNUNET_CONTAINER_meta_data_destroy (meta);
- gtk_tree_store_set (GTK_TREE_STORE (ctx->file_info_treemodel), pos, 0,
MARKER_DIR_FILE_SIZE, 1, (gboolean) GNUNET_NO,
- 2, name, 3, (guint) bo->anonymity_level, 4,
- (guint) bo->content_priority, 5, fi,
- 6, (guint64) bo->expiration_time.abs_value,
- 7, (guint) bo->replication_level,
- -1);
- update_selectivity (ctx);
-}
-
-static void
-selection_changed_cb (GtkTreeSelection * ts, struct
MainPublishingDialogContext *ctx)
-{
- update_selectivity (ctx);
-}
-
-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 (struct MainPublishingDialogContext *ctx, GtkTreeModel * tm,
GtkTreeIter * old,
- GtkTreeIter * newpos, int dsel)
-{
- struct GNUNET_FS_FileInformation *fip;
- gint do_index;
- gchar *short_fn;
- guint anonymity_level;
- guint priority;
- guint replication_level;
- guint64 expiration_time_abs;
- char *fsf;
- GtkTreePath *path;
- 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,
- 6, &expiration_time_abs, 7, &replication_level, -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,
- 6, expiration_time_abs,
- 7, replication_level, -1);
- if (dsel == GNUNET_YES)
- {
- 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 (ctx, 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 (ctx->file_info_treeview, path);
- GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, newpos, path));
- gtk_tree_path_free (path);
- gtk_tree_selection_select_iter (ctx->file_info_selection, newpos);
- }
- update_selectivity (ctx);
-}
-
-
-/**
- * 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,
- struct MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
-
- if (TRUE !=
- gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter,
cpath))
- {
- GNUNET_break (0);
- return;
- }
- gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 5,
new_text, -1);
- update_selectivity (ctx);
-}
-
-
-/**
- * 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,
- struct MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
-
- if (TRUE !=
- gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter,
cpath))
- {
- GNUNET_break (0);
- return;
- }
- gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 2,
new_text, -1);
- update_selectivity (ctx);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter parent;
- GtkTreeIter pred;
- GtkTreeIter prev;
- GtkTreeIter pos;
-
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
- {
- GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
- }
- else if (TRUE != gtk_tree_model_get_iter_first (ctx->file_info_treemodel,
&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 (ctx->file_info_treemodel, &pred,
&iter))
- {
- prev = pred;
- GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
- }
- gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, &prev, NULL);
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
- remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter parent;
- GtkTreeIter pos;
-
-
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- if (TRUE != gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, &parent);
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
- remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter parent;
- GtkTreeIter pred;
- GtkTreeIter prev;
- GtkTreeIter *pprev;
- GtkTreeIter pos;
-
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
- {
- GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
- pprev = &parent;
- }
- else if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel,
&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 (ctx->file_info_treemodel, &pred,
&iter))
- {
- prev = pred;
- pprev = &prev;
- GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
- }
- gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, pprev);
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
- remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter next;
- GtkTreeIter pos;
-
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&next))
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&next));
- gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, &next);
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
- remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- GtkTreeIter pos;
- struct GNUNET_FS_BlockOptions bo;
-
- /* FIXME: consider opening a dialog to get
- * anonymity, priority and expiration prior
- * to calling this function (currently we
- * use default values for those).
- * Or getting these values from the configuration.
- */
- 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 (ctx->file_info_selection, NULL,
&iter))
- {
- create_dir_at_iter (ctx, "unnamed/", &bo, NULL, &pos);
- return;
- }
- create_dir_at_iter (ctx, "unnamed/", &bo, &iter, &pos);
-}
-
-
-static void
-insert_progress_dialog_text (struct AddDirClientContext *adcc,
- const char *text)
-{
- gtk_text_buffer_insert_at_cursor (adcc->progress_dialog_textbuffer,
- text, -1);
- gtk_text_view_place_cursor_onscreen (adcc->progress_dialog_textview);
- gtk_adjustment_set_value (adcc->textview_vertial_adjustment,
- gtk_adjustment_get_upper
(adcc->textview_vertial_adjustment));
-}
-
-
-static void
-add_item (struct AddDirClientContext *adcc, GtkTreeStore *ts,
- struct GNUNET_FS_ShareTreeItem *item,
- GtkTreeIter *parent,
- GtkTreeIter *sibling,
- GtkTreeIter *item_iter)
-{
- char *file_size_fancy;
- struct GNUNET_FS_FileInformation *fi;
- GtkTreeRowReference *row_reference;
- GtkTreePath *path;
- struct stat sbuf;
-
- if (0 != stat (item->filename,
- &sbuf))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "stat", item->filename);
- return;
- }
-
- gtk_tree_store_insert_after (ts, item_iter, parent, sibling);
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), item_iter);
- row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), path);
- gtk_tree_path_free (path);
-
- if (item->is_directory)
- {
- if (NULL != item->meta)
- GNUNET_CONTAINER_meta_data_delete (item->meta,
- EXTRACTOR_METATYPE_MIMETYPE, NULL, 0);
- else
- item->meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_FS_meta_data_make_directory (item->meta);
- if (NULL == item->ksk_uri)
- item->ksk_uri = GNUNET_FS_uri_ksk_create (GNUNET_FS_DIRECTORY_MIME,
NULL);
- else
- GNUNET_FS_uri_ksk_add_keyword (item->ksk_uri, GNUNET_FS_DIRECTORY_MIME,
- GNUNET_NO);
- fi = GNUNET_FS_file_information_create_empty_directory (
- GNUNET_FS_GTK_get_fs_handle (), row_reference, item->ksk_uri,
- item->meta, &adcc->directory_scan_bo, item->filename);
- }
- else
- {
- fi = GNUNET_FS_file_information_create_from_file (
- GNUNET_FS_GTK_get_fs_handle (), row_reference, item->filename,
- item->ksk_uri, item->meta, adcc->directory_scan_do_index,
- &adcc->directory_scan_bo);
- }
- if (item->is_directory)
- file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
- else
- file_size_fancy = GNUNET_STRINGS_byte_size_fancy (sbuf.st_size);
-
- gtk_tree_store_set (ts, item_iter, 0, file_size_fancy,
- 1, (gboolean) adcc->directory_scan_do_index,
- 2, item->short_filename,
- 3, (guint) adcc->directory_scan_bo.anonymity_level,
- 4, (guint) adcc->directory_scan_bo.content_priority,
- 5, fi,
- 6, (guint64) adcc->directory_scan_bo.expiration_time.abs_value,
- 7, (guint) adcc->directory_scan_bo.replication_level, -1);
- GNUNET_free (file_size_fancy);
-}
-
-
-/**
- * Traverse the share tree and add it to the tree store
- *
- */
-static void
-add_share_items_to_treestore (struct AddDirClientContext *adcc,
- struct GNUNET_FS_ShareTreeItem *toplevel,
- GtkTreeIter *parent_iter)
-{
- struct MainPublishingDialogContext *ctx = adcc->ctx;
- GtkTreeStore *ts = GTK_TREE_STORE (ctx->file_info_treemodel);
- GtkTreeIter *sibling_iter;
- GtkTreeIter last_added;
- struct GNUNET_FS_ShareTreeItem *item;
-
- sibling_iter = NULL;
- for (item = toplevel; item != NULL; item = item->next)
- {
- add_item (adcc, ts, item, parent_iter, sibling_iter, &last_added);
- sibling_iter = &last_added;
- if (item->is_directory)
- add_share_items_to_treestore (adcc,
- item->children_head,
- sibling_iter);
- }
-}
-
-
-static void
-close_scan (struct AddDirClientContext *adcc)
-{
- gtk_widget_destroy (adcc->progress_dialog);
- g_object_unref (G_OBJECT (adcc->progress_dialog_builder));
- GNUNET_CONTAINER_DLL_remove (adcc->ctx->adddir_head,
- adcc->ctx->adddir_tail,
- adcc);
- update_selectivity (adcc->ctx);
- GNUNET_free (adcc);
-}
-
-
-static void
-directory_scan_cb (void *cls,
- const char *filename, int is_directory,
- enum GNUNET_FS_DirScannerProgressUpdateReason reason)
-{
- static struct GNUNET_TIME_Absolute last_pulse;
- struct AddDirClientContext *adcc = cls;
- char *s;
- gdouble fraction;
-
- switch (reason)
- {
- case GNUNET_FS_DIRSCANNER_FILE_START:
- GNUNET_assert (filename != NULL);
- if (GNUNET_TIME_absolute_get_duration (last_pulse).rel_value > 100)
- {
- gtk_progress_bar_pulse (adcc->progress_dialog_bar);
- last_pulse = GNUNET_TIME_absolute_get ();
- }
-#if VERBOSE_PROGRESS
- if (is_directory)
- {
- GNUNET_asprintf (&s, _("Scanning directory `%s'.\n"), filename);
- insert_progress_dialog_text (adcc, s);
- GNUNET_free (s);
- }
- else
- adcc->total++;
-#else
- if (! is_directory)
- adcc->total++;
-#endif
- break;
- case GNUNET_FS_DIRSCANNER_FILE_IGNORED:
- GNUNET_assert (filename != NULL);
- GNUNET_asprintf (&s,
- _("Failed to scan `%s' (access error). Skipping.\n"),
- filename);
-#if ! VERBOSE_PROGRESS
- gtk_widget_show (GTK_WIDGET (gtk_builder_get_object
(adcc->progress_dialog_builder,
-
"GNUNET_FS_GTK_progress_dialog_scrolled_window")));
-#endif
- insert_progress_dialog_text (adcc, s);
- GNUNET_free (s);
- break;
- case GNUNET_FS_DIRSCANNER_ALL_COUNTED:
- fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total;
- GNUNET_asprintf (&s, "%u/%u (%3f%%)",
- adcc->done,
- adcc->total,
- 100.0 * fraction);
- gtk_progress_bar_set_text (adcc->progress_dialog_bar,
- s);
- GNUNET_free (s);
- gtk_progress_bar_set_fraction (adcc->progress_dialog_bar,
- fraction);
- break;
- case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED:
-#if VERBOSE_PROGRESS
- GNUNET_asprintf (&s, _("Processed file `%s'.\n"), filename);
- insert_progress_dialog_text (adcc, s);
- GNUNET_free (s);
-#endif
- adcc->done++;
- GNUNET_assert (adcc->done <= adcc->total);
- fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total;
- GNUNET_asprintf (&s, "%u/%u (%3f%%)",
- adcc->done,
- adcc->total,
- 100.0 * fraction);
- gtk_progress_bar_set_text (adcc->progress_dialog_bar,
- s);
- GNUNET_free (s);
- gtk_progress_bar_set_fraction (adcc->progress_dialog_bar,
- fraction);
- break;
- case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR:
- insert_progress_dialog_text (adcc, _("Operation failed (press cancel)\n"));
- GNUNET_FS_directory_scan_abort (adcc->ds);
- adcc->ds = NULL;
- break;
- case GNUNET_FS_DIRSCANNER_FINISHED:
- insert_progress_dialog_text (adcc, _("Scanner has finished.\n"));
- adcc->directory_scan_result = GNUNET_FS_directory_scan_get_result
(adcc->ds);
- adcc->ds = NULL;
- GNUNET_FS_share_tree_trim (adcc->directory_scan_result);
- add_share_items_to_treestore (adcc,
- adcc->directory_scan_result,
- NULL);
- GNUNET_FS_share_tree_free (adcc->directory_scan_result);
- adcc->directory_scan_result = NULL;
- update_selectivity (adcc->ctx);
- close_scan (adcc);
- break;
- default:
- GNUNET_break (0);
- break;
- }
-}
-
-
-static void
-scan_file_or_directory (struct MainPublishingDialogContext *ctx,
- gchar *filename,
- struct GNUNET_FS_BlockOptions *bo,
- int do_index)
-{
- struct AddDirClientContext *adcc;
- GtkTextIter iter;
-
- adcc = GNUNET_malloc (sizeof (struct AddDirClientContext));
- adcc->ctx = ctx;
- GNUNET_CONTAINER_DLL_insert_tail (ctx->adddir_head, ctx->adddir_tail, adcc);
- adcc->ds = GNUNET_FS_directory_scan_start (filename,
- GNUNET_NO, NULL, &directory_scan_cb, adcc);
- adcc->directory_scan_bo = *bo;
- adcc->directory_scan_do_index = do_index;
-
- adcc->progress_dialog_builder = GNUNET_GTK_get_new_builder (
- "gnunet_fs_gtk_progress_dialog.glade", adcc);
- adcc->progress_dialog = GTK_WIDGET (gtk_builder_get_object (
- adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog"));
- adcc->progress_dialog_bar = GTK_PROGRESS_BAR (gtk_builder_get_object (
- adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog_progressbar"));
- adcc->progress_dialog_cancel = GTK_BUTTON (gtk_builder_get_object (
- adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog_cancel_button"));
- adcc->progress_dialog_textview = GTK_TEXT_VIEW (
- gtk_builder_get_object (adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog_textview"));
- adcc->textview_vertial_adjustment = GTK_ADJUSTMENT (
- gtk_builder_get_object (adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog_textview_vertical_adjustment"));
- adcc->progress_dialog_textbuffer = GTK_TEXT_BUFFER (
- gtk_builder_get_object (adcc->progress_dialog_builder,
- "GNUNET_FS_GTK_progress_dialog_textbuffer"));
- gtk_text_buffer_get_end_iter (adcc->progress_dialog_textbuffer,
- &iter);
- adcc->progress_dialog_textmark = gtk_text_buffer_create_mark (
- adcc->progress_dialog_textbuffer, "scroll",
- &iter, FALSE);
-#if VERBOSE_PROGRESS
- gtk_widget_show (GTK_WIDGET (gtk_builder_get_object
(adcc->progress_dialog_builder,
-
"GNUNET_FS_GTK_progress_dialog_scrolled_window")));
-#endif
-
- gtk_window_set_transient_for (GTK_WINDOW (adcc->progress_dialog),
adcc->ctx->master_pubdialog);
- gtk_window_set_title (GTK_WINDOW (adcc->progress_dialog), filename);
- gtk_window_present (GTK_WINDOW (adcc->progress_dialog));
-
- update_selectivity (ctx);
-}
-
-
-static void
-publish_directory_dialog_response_cb (GtkDialog * dialog,
- gint response_id,
- struct MainPublishingDialogContext *ctx)
-{
- char *filename;
- int do_index;
- GtkSpinButton *sb;
- struct GNUNET_FS_BlockOptions bo;
- GtkWidget *ad;
-
- if (g_signal_handler_is_connected (G_OBJECT (dialog),
ctx->open_directory_handler_id))
- g_signal_handler_disconnect (G_OBJECT (dialog),
ctx->open_directory_handler_id);
- ctx->open_directory_handler_id = 0;
-
- ad = GTK_WIDGET (gtk_builder_get_object
- (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog"));
- if (response_id == -5)
- {
- filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(ad));
- sb = GTK_SPIN_BUTTON (gtk_builder_get_object
- (ctx->open_directory_builder,
-
"GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
- if (!GNUNET_GTK_get_selected_anonymity_level
- (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog_anonymity_combobox",
- &bo.anonymity_level))
- bo.anonymity_level = 1;
- bo.content_priority =
- gtk_spin_button_get_value (GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->open_directory_builder,
-
"GNUNET_GTK_publish_directory_dialog_priority_spin_button")));
- bo.replication_level =
- gtk_spin_button_get_value (GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->open_directory_builder,
-
"GNUNET_GTK_publish_directory_dialog_replication_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
- (ctx->open_directory_builder,
-
"GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")));
-
- scan_file_or_directory (ctx, filename, &bo, do_index);
- g_free (filename);
- }
- gtk_widget_destroy (ad);
- g_object_unref (G_OBJECT (ctx->open_directory_builder));
-}
-
-
-static void
-publish_file_dialog_response_cb (GtkDialog * dialog,
- gint response_id,
- struct MainPublishingDialogContext *ctx)
-{
- char *filename;
- struct GNUNET_FS_BlockOptions bo;
- int do_index;
- GtkSpinButton *sb;
- GtkWidget *ad;
-
- if (g_signal_handler_is_connected (G_OBJECT (dialog),
ctx->open_file_handler_id))
- g_signal_handler_disconnect (G_OBJECT (dialog), ctx->open_file_handler_id);
- ctx->open_file_handler_id = 0;
-
- ad = GTK_WIDGET (gtk_builder_get_object
- (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog"));
-
- if (response_id == -5)
- {
- /* OK */
- sb = GTK_SPIN_BUTTON (gtk_builder_get_object
- (ctx->open_file_builder,
-
"GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
-
- if (!GNUNET_GTK_get_selected_anonymity_level
- (ctx->open_file_builder,
"GNUNET_GTK_publish_file_dialog_anonymity_combobox",
- &bo.anonymity_level))
- bo.anonymity_level = 1;
- bo.content_priority =
- gtk_spin_button_get_value (GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->open_file_builder,
-
"GNUNET_GTK_publish_file_dialog_priority_spin_button")));
- bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
- bo.replication_level =
- gtk_spin_button_get_value (GTK_SPIN_BUTTON
- (gtk_builder_get_object
- (ctx->open_file_builder,
-
"GNUNET_GTK_publish_file_dialog_replication_spin_button")));
- do_index =
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
- (gtk_builder_get_object
- (ctx->open_file_builder,
-
"GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
-
- filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(ad));
-
- scan_file_or_directory (ctx, filename, &bo, do_index);
-
- g_free (filename);
- }
- else
- {
- /* Cancel/Escape/close/etc */
- }
- gtk_widget_destroy (ad);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkWidget *ad;
-
- GtkComboBox *combo;
- GtkTreeModel *anon_treemodel;
-
- ctx->open_file_builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_file_dialog.glade", ctx);
- GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_file_builder);
- ad = GTK_WIDGET (gtk_builder_get_object
- (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog"));
-
- /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
- ctx->open_file_builder,
- "GNUNET_GTK_publish_file_dialog_priority_spin_button")), 1000);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
- ctx->open_file_builder,
- "GNUNET_GTK_publish_file_dialog_replication_spin_button")), 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (
- ctx->open_file_builder,
- "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")), TRUE);
-
- ctx->open_file_handler_id = g_signal_connect (G_OBJECT (ad), "response",
G_CALLBACK (publish_file_dialog_response_cb), ctx);
-
- anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object
(ctx->main_window_builder,
- "main_window_search_anonymity_liststore"));
- combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_file_builder,
- "GNUNET_GTK_publish_file_dialog_anonymity_combobox"));
- gtk_combo_box_set_model (combo, anon_treemodel);
-
- gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog);
-
- gtk_window_present (GTK_WINDOW (ad));
-}
-
-
-struct EditPublishContext
-{
- struct GNUNET_FS_FileInformation *fip;
-
- GtkTreeModel *tm;
-
- GtkTreeIter iter;
-};
-
-
-/**
- * Update tree view based on the information from the
- * GNUNET_FS_FileInformation publish-structure.
- *
- * @param cls closure, a 'struct EditPublishContext *'
- * @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_OK to continue, GNUNET_NO to remove
- * this entry from the directory, GNUNET_SYSERR
- * to abort the iteration
- */
-static int
-update_treeview_after_edit (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)
-{
- struct EditPublishContext *epc = cls;
-
- gtk_tree_store_set (GTK_TREE_STORE (epc->tm), &epc->iter,
- 1, *do_index,
- 3, (guint) bo->anonymity_level,
- 4, (guint) bo->content_priority,
- 6, (guint64) bo->expiration_time.abs_value,
- 7, (guint) bo->replication_level,
- -1);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Function called when the edit publish dialog has been closed.
- *
- * @param cls closure
- * @param ret GTK_RESPONSE_OK if the dialog was closed with "OK"
- * @param root unused (namespace root name)
- */
-static void
-master_publish_edit_publish_dialog_cb (gpointer cls,
- gint ret,
- const char *root)
-{
- struct EditPublishContext *cbargs = cls;
-
- if (ret == GTK_RESPONSE_OK)
- GNUNET_FS_file_information_inspect (cbargs->fip,
&update_treeview_after_edit, cbargs);
- GNUNET_free (cbargs);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- struct EditPublishContext *cbargs;
- GtkListStore *anon_liststore;
-
- anon_liststore = GTK_LIST_STORE (gtk_builder_get_object
(ctx->main_window_builder,
-
"main_window_search_anonymity_liststore"));
- cbargs = GNUNET_malloc (sizeof (struct EditPublishContext));
- cbargs->tm = ctx->file_info_treemodel;
- if (! gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&cbargs->iter))
- {
- GNUNET_break (0);
- GNUNET_free (cbargs);
- return;
- }
- gtk_tree_model_get (ctx->file_info_treemodel, &cbargs->iter,
- 5, &cbargs->fip,
- -1);
- /* FIXME: can we just give our anon_liststore out like this? What about
- (unintended) sharing of state? */
- GNUNET_FS_GTK_edit_publish_dialog (ctx->master_pubdialog,
- cbargs->fip,
- GNUNET_YES,
- anon_liststore,
- &master_publish_edit_publish_dialog_cb,
- cbargs);
-}
-
-
-/**
- * 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,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkTreeIter iter;
- struct GNUNET_FS_FileInformation *fip;
-
- if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
- {
- GNUNET_break (0);
- return;
- }
- gtk_tree_model_get (ctx->file_info_treemodel, &iter, 5, &fip, -1);
- GNUNET_FS_file_information_destroy (fip, &free_fi_row_reference, NULL);
- gtk_tree_store_remove (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
- update_selectivity (ctx);
-}
-
-
-void
-GNUNET_FS_GTK_progress_dialog_cancel_button_clicked_cb (GtkButton *button,
- void *cls)
-{
- struct AddDirClientContext *adcc = cls;
-
- if (adcc->ds != NULL)
- {
- /* Still scanning - signal the scanner to finish */
- GNUNET_FS_directory_scan_abort (adcc->ds);
- adcc->ds = NULL;
- }
- close_scan (adcc);
-}
-
-
-gboolean
-GNUNET_FS_GTK_progress_dialog_delete_event_cb (GtkWidget *widget,
- GdkEvent * event,
- void *cls)
-{
- /* Don't allow GTK to kill the window, until the scan is finished */
- return GNUNET_NO;
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy,
- struct
MainPublishingDialogContext *ctx)
-{
- GtkWidget *ad;
-
- GtkComboBox *combo;
- GtkTreeModel *anon_treemodel;
-
- ctx->open_directory_builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_directory_dialog.glade", ctx);
- GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_directory_builder);
-
- /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
- ctx->open_directory_builder,
- "GNUNET_GTK_publish_directory_dialog_priority_spin_button")), 1000);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
- ctx->open_directory_builder,
- "GNUNET_GTK_publish_directory_dialog_replication_spin_button")), 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (
- ctx->open_directory_builder,
- "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")), TRUE);
-
- ad = GTK_WIDGET (gtk_builder_get_object
- (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog"));
-
- ctx->open_directory_handler_id = g_signal_connect (G_OBJECT (ad),
"response", G_CALLBACK (publish_directory_dialog_response_cb), ctx);
-
- anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object
(ctx->main_window_builder,
- "main_window_search_anonymity_liststore"));
- combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_directory_builder,
- "GNUNET_GTK_publish_directory_dialog_anonymity_combobox"));
- gtk_combo_box_set_model (combo, anon_treemodel);
-
- gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog);
-
- gtk_window_present (GTK_WINDOW (ad));
-}
-
-
-/**
- * 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);
- /* FIXME: what if this put fails? Not convinced it cannot... */
- 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);
- if (desc == NULL)
- desc = GNUNET_strdup (_("no description supplied"));
- else
- {
- char *utf8_desc = NULL;
-
- utf8_desc =
- GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc,
- strlen (desc) + 1);
- GNUNET_free (desc);
- if (utf8_desc != NULL)
- desc = utf8_desc;
- else
- desc = NULL;
- }
- 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 (as string!) */ ,
- 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_CONTAINER_MetaData *meta;
- struct GNUNET_FS_Namespace *ns;
- GtkTreeIter child;
-
- gtk_tree_model_get (tm, iter, 1, &ns, 4, &meta, -1);
- 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));
- }
-}
-
-static int
-hide_master_publish_dialog (struct MainPublishingDialogContext *ctx, gint ret)
-{
- GtkTreeIter iter;
- gpointer namespace;
- gchar *namespace_id;
- gchar *namespace_uid;
- struct GNUNET_FS_FileInformation *fi;
-
- /* Don't close until all scanners are finished */
- if (ctx->adddir_head != NULL)
- return GNUNET_NO;
-
- if (ret == GTK_RESPONSE_OK)
- {
- if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection,
NULL, &iter))
- {
- gtk_tree_model_get (ctx->pseudonym_treemodel, &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 (ctx->file_info_treemodel, &iter))
- do
- {
- fi = get_file_information (ctx->file_info_treemodel, &iter);
- /* FIXME: should we convert namespace id and uid from UTF8? */
- 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 (ctx->file_info_treemodel, &iter));
- g_free (namespace_id);
- g_free (namespace_uid);
- }
-
- /* free state from 'ptm' */
- if (TRUE == gtk_tree_model_get_iter_first (ctx->pseudonym_treemodel, &iter))
- do
- {
- free_pseudonym_tree_store (ctx->pseudonym_treemodel, &iter);
- }
- while (TRUE == gtk_tree_model_iter_next (ctx->pseudonym_treemodel, &iter));
- gtk_tree_store_clear (GTK_TREE_STORE (ctx->pseudonym_treemodel));
-
- /* free state from 'tm' */
- if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter))
- do
- {
- free_file_information_tree_store (ctx->file_info_treemodel, &iter);
- }
- while (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter));
- gtk_tree_store_clear (GTK_TREE_STORE (ctx->file_info_treemodel));
- gtk_widget_destroy (GTK_WIDGET (ctx->master_pubdialog));
- g_object_unref (G_OBJECT (ctx->builder));
- GNUNET_free (ctx);
- return GNUNET_YES;
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_execute_button_clicked_cb (GtkButton * button,
- struct
MainPublishingDialogContext *ctx)
-{
- hide_master_publish_dialog (ctx, GTK_RESPONSE_OK);
-}
-
-
-void
-GNUNET_GTK_master_publish_dialog_cancel_button_clicked_cb (GtkButton * button,
- struct
MainPublishingDialogContext *ctx)
-{
- hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL);
-}
-
-
-gboolean
-GNUNET_GTK_master_publish_dialog_delete_event_cb (GtkWidget * widget,
- GdkEvent * event,
- struct
MainPublishingDialogContext *ctx)
-{
- if (GNUNET_NO == hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL))
- return TRUE;
- return FALSE;
-}
-
-
-/**
- */
-void
-GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy, gpointer
user_data)
-{
- struct MainPublishingDialogContext *ctx;
-
- ctx = GNUNET_malloc (sizeof (struct MainPublishingDialogContext));
- ctx->builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_dialog.glade", ctx);
-
- if (ctx->builder == NULL)
- {
- GNUNET_free (ctx);
- return;
- }
-
- init_ctx (ctx);
- ctx->main_window_builder = GTK_BUILDER (user_data);
- GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
- &add_namespace_to_ts, GTK_TREE_STORE
(ctx->pseudonym_treemodel));
- gtk_window_present (GTK_WINDOW (ctx->master_pubdialog));
-}
-
-
-/* end of gnunet-fs-gtk-main_window_file_publish.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_about.c (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-about.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_about.c (rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_about.c 2012-02-02 13:28:32 UTC (rev
19629)
@@ -0,0 +1,44 @@
+/*
+ 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/gnunet-fs-gtk_about.c
+ * @author Christian Grothoff
+ * @author Igor Wronsky
+ *
+ * This file contains the about dialog.
+ */
+#include "gnunet_gtk.h"
+
+
+/**
+ * This displays an about window
+ *
+ * @param widget widget creating the event, unused
+ * @param data global builder, unused
+ */
+void
+GNUNET_GTK_main_menu_help_about_activate_cb (GtkWidget * dummy, gpointer data)
+{
+ GNUNET_GTK_display_about ("gnunet_fs_gtk_about_window.glade");
+}
+
+
+/* end of gnunet-fs-gtk-about.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.c (from rev 19625,
gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.c
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.c 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,177 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010, 2012 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_anonymtiy-widgets.c
+ * @author Christian Grothoff
+ * @brief operations to manage user's anonymity level selections
+ */
+#include "gnunet-fs-gtk-common.h"
+#include "gnunet-fs-gtk-anonymity_spin_buttons.h"
+#include <gdk/gdk.h>
+
+/**
+ * Spin button is changed, update its color. NOTE: This function will
eventually
+ * become obsolete as we migrate to the drop-down style of anonymity-level
selection.
+ *
+ * @param w the spin button that changed
+ * @param builder's closure, unused
+ */
+void
+GNUNET_GTK_anonymity_spin_button_value_changed_cb (GtkWidget * w, gpointer
data)
+{
+#ifdef GdkRBGA
+ GtkSpinButton *spin;
+ gint val;
+ GdkRGBA bcolor;
+ GdkRGBA 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_rgba_parse (&bcolor, "red")) &&
+ (TRUE == gdk_rgba_parse (&fcolor, "black")))
+ {
+ gtk_widget_override_background_color (w, GTK_STATE_NORMAL, &bcolor);
+ gtk_widget_override_color (w, GTK_STATE_NORMAL, &fcolor);
+ }
+ else
+ {
+ GNUNET_break (0);
+ }
+ }
+ else
+ {
+ gtk_widget_override_background_color (w, GTK_STATE_NORMAL, NULL);
+ gtk_widget_override_color (w, GTK_STATE_NORMAL, NULL);
+ }
+#endif
+}
+
+
+/**
+ * Obtain the numeric anonymity level selected by a GtkComboBox.
+ *
+ * @param builder builder for looking up widgets
+ * @param combo_name name of the GtkComboBox with the anonymity selection
+ * @param p_level where to store the anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_get_selected_anonymity_level (GtkBuilder * builder,
+ gchar * combo_name, guint * p_level)
+{
+ GtkComboBox *combo;
+
+ combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, combo_name));
+ if (!combo)
+ return FALSE;
+ return GNUNET_GTK_get_selected_anonymity_combo_level (combo, p_level);
+}
+
+
+/**
+ * Obtain the numeric anonymity level selected by a GtkComboBox.
+ *
+ * @param combo the GtkComboBox with the anonymity selection
+ * @param p_level where to store the anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_get_selected_anonymity_combo_level (GtkComboBox *combo, guint
*p_level)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint level;
+
+ if (! gtk_combo_box_get_active_iter (combo, &iter))
+ return FALSE;
+ model = gtk_combo_box_get_model (combo);
+ if (!model)
+ return FALSE;
+ gtk_tree_model_get (model, &iter, 1, &level, -1);
+ if (p_level)
+ *p_level = level;
+ return TRUE;
+}
+
+
+/**
+ * Set the anonymity level displayed by a combo box.
+ *
+ * @param builder the builder of the combo box
+ * @param combo_name name of the combo box
+ * @param sel_level desired anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_select_anonymity_level (GtkBuilder * builder, gchar * combo_name,
+ guint sel_level)
+{
+ GtkComboBox *combo;
+
+ combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, combo_name));
+ if (!combo)
+ return FALSE;
+ return GNUNET_GTK_select_anonymity_combo_level (combo, sel_level);
+}
+
+
+/**
+ * Set the anonymity level displayed by a combo box.
+ *
+ * @param combo the combo box
+ * @param sel_level desired anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_select_anonymity_combo_level (GtkComboBox *combo, guint sel_level)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint level;
+
+ model = gtk_combo_box_get_model (combo);
+ if (!model)
+ return FALSE;
+ if (! gtk_tree_model_get_iter_first (model, &iter))
+ return FALSE;
+ do
+ {
+ gtk_tree_model_get (model, &iter, 1, &level, -1);
+ if (level == sel_level)
+ {
+ gtk_combo_box_set_active_iter (combo, &iter);
+ return TRUE;
+ }
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+ return FALSE;
+}
+
+
+
+/* end of gnunet-fs-gtk-anonymtiy_spin_buttons.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.h (from rev 19625,
gnunet-gtk/src/fs/gnunet-fs-gtk-anonymity_spin_buttons.h)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.h
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_anonymity-widgets.h 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,80 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010, 2012 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_anonymtiy-widgets.h
+ * @author Christian Grothoff
+ * @brief operations to manage user's anonymity level selections
+ */
+#ifndef GNUNET_FS_GTK_ANONYMITY_SPIN_BUTTONS_H
+#define GNUNET_FS_GTK_ANONYMITY_SPIN_BUTTONS_H
+
+#include "gnunet-fs-gtk-common.h"
+#include <gdk/gdk.h>
+
+
+/**
+ * Obtain the numeric anonymity level selected by a GtkComboBox.
+ *
+ * @param builder builder for looking up widgets
+ * @param combo_name name of the GtkComboBox with the anonymity selection
+ * @param p_level where to store the anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_get_selected_anonymity_level (GtkBuilder * builder,
+ gchar * combo_name, guint * p_level);
+
+
+/**
+ * Obtain the numeric anonymity level selected by a GtkComboBox.
+ *
+ * @param combo the GtkComboBox with the anonymity selection
+ * @param p_level where to store the anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_get_selected_anonymity_combo_level (GtkComboBox *combo, guint
*p_level);
+
+
+/**
+ * Set the anonymity level displayed by a combo box.
+ *
+ * @param builder the builder of the combo box
+ * @param combo_name name of the combo box
+ * @param sel_level desired anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_select_anonymity_level (GtkBuilder * builder, gchar * combo_name,
+ guint sel_level);
+
+
+/**
+ * Set the anonymity level displayed by a combo box.
+ *
+ * @param combo the combo box
+ * @param sel_level desired anonymity level
+ * @return TRUE on success, FALSE on failure
+ */
+gboolean
+GNUNET_GTK_select_anonymity_combo_level (GtkComboBox *combo, guint sel_level);
+
+#endif
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_common.c (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-common.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_common.c (rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_common.c 2012-02-02 13:28:32 UTC (rev
19629)
@@ -0,0 +1,234 @@
+/*
+ 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_common.c
+ * @brief Common functions used in various places
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk-common.h"
+
+/**
+ * Converts metadata specified by @data of size @data_len
+ * and saved in format @format to UTF-8 encoded string.
+ * Works only for C-string and UTF8 metadata formats
+ * (returns NULL for everything else).
+ * Verifies UTF-8 strings.
+ *
+ * @param format format of the @data
+ * @param data data to convert
+ * @param data_len length of the data buffer (in bytes)
+ * @return NULL if can't be converted, allocated string otherwise,
+ * freeable with GNUNET_free* ().
+ */
+char *
+GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format,
+ const char *data, size_t data_len)
+{
+ switch (format)
+ {
+ case EXTRACTOR_METAFORMAT_UTF8:
+ /* data must not contain NULLs (hence the -1) */
+ if (g_utf8_validate (data, data_len - 1, NULL))
+ return GNUNET_strdup (data);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Failed to validate supposedly utf-8 string `%s' of length
%u, assuming it to be a C string\n"),
+ data,
+ (unsigned int) data_len);
+ format = EXTRACTOR_METAFORMAT_C_STRING;
+ /* fall-through */
+ case EXTRACTOR_METAFORMAT_C_STRING:
+ if (data_len > 0)
+ {
+ /* There are no guarantees that data is NULL-terminated, AFAIU,
+ * so let's play it safe, shall we?
+ */
+ char data_copy[data_len + 1];
+
+ memcpy (data_copy, data, data_len);
+ data_copy[data_len] = '\0';
+ return GNUNET_GTK_from_loc_to_utf8 (data_copy);
+ }
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+
+/**
+ * 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);
+ char *data_to_insert;
+
+ data_to_insert = GNUNET_FS_GTK_dubious_meta_to_utf8 (format, data, data_len);
+ if (NULL == data_to_insert)
+ return 0;
+ gtk_list_store_insert_with_values (ls, NULL, G_MAXINT, 0, type, 1, format,
+ 2, EXTRACTOR_metatype_to_string (type),
+ 3, data_to_insert, -1);
+ GNUNET_free (data_to_insert);
+ return 0;
+}
+
+
+/**
+ * Convert the year from the spin button to an expiration
+ * time (on midnight, January 1st of that year).
+ *
+ * @param spin button with an expiration year
+ * @return expiration time in the usual GNUnet format
+ */
+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;
+}
+
+
+/**
+ * Initialize the 'expiration_year_adjustment' of the given
+ * builder to have a lower range of current-year+1 and a
+ * default of current-year+2.
+ *
+ * @param builder builder object for which we should manipulate
+ * the adjustment
+ */
+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);
+}
+
+
+/**
+ * Obtain pixbuf from thumbnail data in meta data.
+ *
+ * @param meta input meta data
+ * @return NULL on error, otherwise the embedded thumbnail
+ */
+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 (0 == ts)
+ 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 (NULL != pixbuf)
+ 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.
+ *
+ * @param filename name with the directory
+ * @param dep function to call on each entry
+ * @param dep_cls closure for 'dep'
+ */
+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;
+ }
+ if (NULL == (fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE)))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
+ return;
+ }
+ if (NULL == (ddata = GNUNET_DISK_file_map (fh, &mh,
GNUNET_DISK_MAP_TYPE_READ, (size_t) fsize)))
+ {
+ 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 gnunet-fs-gtk-common.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_common.h (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-common.h)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_common.h (rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_common.h 2012-02-02 13:28:32 UTC (rev
19629)
@@ -0,0 +1,126 @@
+/*
+ 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_common.h
+ * @brief Common includes for all gnunet-gtk source files
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_FS_GTK_COMMON_H
+#define GNUNET_FS_GTK_COMMON_H
+
+#include "gnunet_gtk.h"
+#include <gnunet/gnunet_fs_service.h>
+#include <extractor.h>
+
+
+/**
+ * Obtain pixbuf from thumbnail data in meta data.
+ *
+ * @param meta input meta data
+ * @return NULL on error, otherwise the embedded thumbnail
+ */
+GdkPixbuf *
+GNUNET_FS_GTK_get_thumbnail_from_meta_data (const struct
+ GNUNET_CONTAINER_MetaData *meta);
+
+
+/**
+ * Initialize the 'expiration_year_adjustment' of the given
+ * builder to have a lower range of current-year+1 and a
+ * default of current-year+2.
+ * FIXME: odd API...
+ *
+ * @param builder builder object for which we should manipulate
+ * the adjustment
+ */
+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).
+ *
+ * @param spin button with the year
+ * @param time converted from the spin button
+ */
+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.
+ *
+ * @param filename name with the directory
+ * @param dep function to call on each entry
+ * @param dep_cls closure for 'dep'
+ */
+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);
+
+
+/**
+ * Converts metadata specified by @data of size @data_len
+ * and saved in format @format to UTF-8 encoded string.
+ * Works only for C-string and UTF8 metadata formats
+ * (returns NULL for everything else).
+ * Verifies UTF-8 strings.
+ *
+ * @param format format of the @data
+ * @param data data to convert
+ * @param data_len length of the data buffer (in bytes)
+ * @return NULL if can't be converted, allocated string otherwise,
+ * freeable with GNUNET_free* ().
+ */
+char *
+GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format,
+ const char *data, size_t data_len);
+
+
+#endif
+/* end of gnunet-fs-gtk-common.h */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-download.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.c 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,295 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010, 2011, 2012 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_download-save-as.c
+ * @brief functions for managing the 'save as' dialog
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk-download.h"
+#include "gnunet-fs-gtk.h"
+#include "gnunet-fs-gtk-event_handler.h"
+
+/**
+ * State for a 'save as' dialog of a download.
+ */
+struct DownloadAsDialogContext
+{
+
+ /**
+ * Download context for which this dialog determines the
+ * filename (and other options).
+ */
+ struct DownloadContext *dc;
+
+ /**
+ * Builder for the dialog.
+ */
+ GtkBuilder *builder;
+
+ /**
+ * Main dialog object.
+ */
+ GtkWidget *dialog;
+
+ /**
+ * Final response code from the dialog.
+ */
+ gint response;
+};
+
+
+/**
+ * Free resources associated with the given download context.
+ *
+ * @param dc context to free
+ */
+static void
+save_as_dialog_free_download_context (struct DownloadContext *dc)
+{
+ if (NULL != dc->rr)
+ gtk_tree_row_reference_free (dc->rr);
+ GNUNET_free_non_null (dc->mime);
+ GNUNET_free_non_null (dc->filename);
+ if (NULL != dc->meta)
+ GNUNET_CONTAINER_meta_data_destroy (dc->meta);
+ if (NULL != dc->uri)
+ GNUNET_FS_uri_destroy (dc->uri);
+ GNUNET_free (dc);
+}
+
+
+/**
+ * The 'save_as' dialog is being deleted. Check which state we're in
+ * and either simply clean up or start the download with the
+ * respective options (by calling the respective continuation).
+ *
+ * @param widget the dialog object
+ * @param event the deletion event
+ * @param user_data the 'structDownloadAsDialogContext' of the dialog
+ * @return always FALSE
+ */
+gboolean
+GNUNET_GTK_save_as_dialog_delete_event_cb (GtkWidget * widget, GdkEvent *
event,
+ gpointer user_data)
+{
+ struct DownloadAsDialogContext *dlc = user_data;
+ GtkBuilder *builder;
+ struct DownloadContext *dc;
+ GtkWidget *cb;
+
+ builder = dlc->builder;
+ dc = dlc->dc;
+ cb = GTK_WIDGET (gtk_builder_get_object
+ (builder, "GNUNET_GTK_save_as_recursive_check_button"));
+ if (GTK_RESPONSE_OK != dlc->response)
+ {
+ save_as_dialog_free_download_context (dc);
+ g_object_unref (G_OBJECT (dlc->builder));
+ GNUNET_free (dlc);
+ return FALSE;
+ }
+ GNUNET_free_non_null (dc->filename);
+ dc->filename =
+ GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(dlc->dialog));
+ dc->is_recursive =
+ (TRUE ==
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
+ GNUNET_NO;
+ dc->anonymity =
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (builder,
+
"GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
+ g_object_unref (G_OBJECT (builder));
+ GNUNET_free (dlc);
+ GNUNET_FS_GTK_download_context_start_download (dc);
+ return FALSE;
+}
+
+
+/**
+ * The user clicked on the 'save as' button of the dialog.
+ * Delete the window and start the download.
+ *
+ * @param dialog the dialog object
+ * @param response_id response_id associated with the button
+ * @param user_data the 'structDownloadAsDialogContext' of the dialog
+ */
+void
+GNUNET_GTK_save_as_dialog_response_cb (GtkDialog * dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ struct DownloadAsDialogContext *dlc = user_data;
+
+ dlc->response = response_id;
+ /* dialogs don't get delete-event the way normal windows do,
+ call the handler manually */
+ GNUNET_GTK_save_as_dialog_delete_event_cb (GTK_WIDGET (dialog), NULL,
+ user_data);
+ /* FIXME-BUG-MAYBE: isn't the dialog going to be destroyed with the builder?
+ Is this legal and/or required? */
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+
+/**
+ * Open the 'save as' dialog for a download. Calls the 'dc->cb'
+ * continutation when the dialog is complete. Will release the 'dc'
+ * resources if the dialog is cancelled.
+ *
+ * @param dc download context for the file/directory
+ */
+void
+GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc)
+{
+ struct DownloadAsDialogContext *dlc;
+ GtkWidget *cb;
+
+ dlc = GNUNET_malloc (sizeof (struct DownloadAsDialogContext));
+ dlc->dc = dc;
+ dlc->builder =
+ GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_download_as_dialog.glade",
+ dlc);
+ if (NULL == dlc->builder)
+ {
+ GNUNET_break (0);
+ save_as_dialog_free_download_context (dc);
+ GNUNET_free (dlc);
+ return;
+ }
+ dlc->dialog = GTK_WIDGET (gtk_builder_get_object
+ (dlc->builder, "GNUNET_GTK_save_as_dialog"));
+
+ /* Enable recursive button for directories and
+ set recursive 'default' value based on what the 'dc' tells us */
+ cb = GTK_WIDGET (gtk_builder_get_object
+ (dlc->builder,
"GNUNET_GTK_save_as_recursive_check_button"));
+ if (GNUNET_FS_meta_data_test_for_directory (dc->meta))
+ gtk_widget_set_sensitive (cb, TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb),
+ dc->is_recursive);
+
+ /* initialize filename based on filename from 'dc' */
+ if (NULL != dc->filename)
+ {
+ char *dirname;
+ char *basename;
+
+ dirname = GNUNET_strdup (dc->filename);
+ basename = (char *) GNUNET_STRINGS_get_short_name (dirname);
+ /* basename now points into 'dirname'; cut 'dirname' off at the '/' before
basename */
+ if (basename > dirname)
+ basename[-1] = '\0';
+
+ /* FIXME: remove following lines after testing... */
+ fprintf (stderr,
+ "Splitting `%s' into `%s' + `%s' for file chooser dialog.\n",
+ dc->filename,
+ dirname,
+ basename);
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlc->dialog),
dirname);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlc->dialog),
basename);
+ GNUNET_free (dirname);
+ }
+ gtk_window_present (GTK_WINDOW (dlc->dialog));
+}
+
+
+/**
+ * Actually start the download that is specified by the given download
+ * context and its options. Will add a download entry to the
+ * respective tree model and trigger a start of the download using the
+ * FS-API.
+ *
+ * @param dc download context of the download to execute
+ */
+void
+GNUNET_FS_GTK_download_context_start_download (struct DownloadContext *dc)
+{
+ enum GNUNET_FS_DownloadOptions opt;
+ struct GNUNET_FS_Handle *fs;
+ struct DownloadEntry *de;
+ uint64_t len;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ de = GNUNET_malloc (sizeof (struct DownloadEntry));
+ de->uri = dc->uri;
+ dc->uri = NULL;
+ de->meta = dc->meta;
+ dc->meta = NULL;
+ if (NULL != dc->rr)
+ {
+ de->rr = gtk_tree_row_reference_copy (dc->rr);
+ de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if ( (NULL != path) &&
+ (gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path)) )
+ {
+ /* Store filename and anonymity as specified by the user.
+ * These will be re-used when this is a directory, and the user
+ * downloads its children.
+ */
+ gtk_tree_store_set (de->ts, &iter, 15, dc->filename, 16, dc->anonymity,
-1);
+ }
+ else
+ {
+ /* We could not find the referenced row in the search tab; this is
+ conceivable as the search tab might have been closed by the
+ user while the 'save as' dialog was open. In this case, this
+ is equivalent to having no search, so we drop the (now invalid)
+ 'sr' reference */
+ dc->sr = NULL;
+ }
+ if (NULL != path)
+ gtk_tree_path_free (path);
+ }
+ fs = GNUNET_FS_GTK_get_fs_handle ();
+ opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
+ if (dc->is_recursive)
+ opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
+ len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
+ if (NULL != dc->sr)
+ {
+ GNUNET_break (NULL !=
+ GNUNET_FS_download_start_from_search (fs, dc->sr,
+ dc->filename,
+ NULL /* tempname */ ,
+ 0 /* offset */ ,
+ len, dc->anonymity,
opt,
+ de));
+ }
+ else
+ {
+ GNUNET_break (NULL !=
+ GNUNET_FS_download_start (fs, de->uri, NULL /* meta */ ,
+ dc->filename, NULL /* tempname */ ,
+ 0 /* offset */ ,
+ len, dc->anonymity, opt, de,
+ NULL /* parent download ctx */ ));
+ }
+ save_as_dialog_free_download_context (dc);
+}
+
+
+/* end of gnunet-fs-gtk-download.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-download.h)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_download-save-as.h 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,117 @@
+/*
+ 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_download-save-as.h
+ * @brief functions for downloading
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_FS_GTK_DOWNLOAD_SAVE_AS_H
+#define GNUNET_FS_GTK_DOWNLOAD_SAVE_AS_H
+
+#include "gnunet-fs-gtk-common.h"
+
+
+/**
+ * Information we keep for a download.
+ */
+struct DownloadContext;
+
+
+/**
+ * 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;
+
+ /**
+ * Tab where this download is currently on display.
+ * (this is the same as sr->tab, but sr is opaque here).
+ */
+ struct SearchTab *tab;
+
+};
+
+
+/**
+ * Actually start the download that is specified by the given download
+ * context and its options. Will add a download entry to the
+ * respective tree model and trigger a start of the download using the
+ * FS-API.
+ *
+ * @param dc download context of the download to execute
+ */
+void
+GNUNET_FS_GTK_download_context_start_download (struct DownloadContext *dc);
+
+
+/**
+ * Open the 'save as' dialog for a download. Calls
+ * 'GNUNET_FS_GTK_download_context_start_download' when the dialog is
+ * complete. Will release the 'dc' resources if the dialog is
+ * cancelled.
+ *
+ * @param dc download context for the file/directory
+ */
+void
+GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc);
+
+
+#endif
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.c 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,2658 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010, 2011, 2012 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_event-handler.c
+ * @brief Main event handler for file-sharing
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk.h"
+#include "gnunet-fs-gtk-download.h"
+#include "gnunet-fs-gtk-event_handler.h"
+#include <string.h>
+
+
+/**
+ * We have a single tab where we display publishing operations.
+ * So there is only one instance of this struct.
+ */
+struct PublishTab
+{
+
+ /**
+ * Frame for the tab.
+ */
+ GtkWidget *frame;
+
+ /**
+ * Associated builder.
+ */
+ GtkBuilder *builder;
+
+ /**
+ * Associated tree store.
+ */
+ GtkTreeStore *ts;
+};
+
+
+/**
+ * Information we keep for each file or directory being published.
+ * Used to quickly identify the tab and row of the operation; stored
+ * in the user-context of the FS library for the publish operation.
+ */
+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;
+
+ /**
+ * Is this the top-level entry for the publish operation
+ * or sub-operation?
+ */
+ int is_top;
+};
+
+
+/**
+ * Information we keep for each search result entry in any search tab.
+ * An entry like this is also generated for downloads by-URI. Used to
+ * quickly identify the tab and row of the result; stored in the
+ * user-context of the FS library for the search result.
+ */
+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;
+};
+
+
+
+/**
+ * Head of linked list of tabs for searches.
+ */
+static struct SearchTab *search_tab_head;
+
+/**
+ * Tail of linked list of tabs for searches.
+ */
+static struct SearchTab *search_tab_tail;
+
+/**
+ * Special tab we use to for downloads-by-URIs and downloads
+ * where the search tab has been closed ("parent lost").
+ */
+static struct SearchTab *uri_tab;
+
+/**
+ * Special tab we use to store publishing operations.
+ */
+static struct PublishTab *publish_tab;
+
+/**
+ * Row reference for the current search context menu.
+ * FIXME-UNCLEAN: de-globalize?
+ */
+static GtkTreeRowReference *current_context_row_reference;
+
+/**
+ * Search tab used for the current search context menu.
+ * FIXME-UNCLEAN: de-globalize?
+ */
+static struct SearchTab *current_context_search_tab;
+
+
+
+/* ***************** Search event handling ****************** */
+
+/**
+ * This should get the default download directory (so that GNUnet
+ * won't offer the user to download files to the 'bin' subdirectory,
+ * or whatever is the cwd). Returns NULL on failure (such as
+ * non-existend directory). Should also preserve the last setting (so
+ * if the user saves files somewhere else, next time we default to
+ * somewhere else, at least until application restart, or maybe even
+ * between application restarts).
+ *
+ * Fills the 'buffer' up to 'size' bytes, returns a pointer to it.
+ */
+static char *
+get_default_download_directory (char *buffer, size_t size)
+{
+ /* FIXME-FEATURE: implement... */
+ return NULL;
+}
+
+
+/**
+ * Called recursively to build a suggested filename by prepending
+ * suggested names for its parent directories (if any).
+ *
+ * @param tm tree model this function gets the data from
+ * @param iter current position in the tree, for which we want a suggested
filename
+ * @param top GNUNET_YES for the original call to this function,
+ * GNUNET_NO for recursive calls; used to decide if the
+ * current call is eligible to set 'anonymity' and 'local_parents'
+ * @param local_parents set to GNUNET_YES if all parents are directories, and
are downloaded.
+ * @param anonymity set to the anonymity level of the closest ancestor
download (if any);
+ * set to "-1" for uninitialized initially (will be left
at -1 if
+ * no suitable parent download was found)
+ * @param filename_is_absolute set to GNUNET_YES if the suggestion is an
absolute filename,
+ * GNUNET_NO for relative filenames (gotten from
meta data)
+ * @return suggested filename, possibly NULL
+ */
+static char *
+get_suggested_filename_anonymity (GtkTreeModel *tm,
+ GtkTreeIter *iter,
+ int top,
+ int *local_parents,
+ int *anonymity,
+ int *filename_is_absolute)
+{
+ char *result;
+ char *dirname;
+ char *local_filename;
+ char *filename;
+ int downloaded_anonymity;
+ int have_a_parent;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ GtkTreeIter parent;
+ const char *basename;
+ char *dot;
+
+ /* FIXME-BUG-MAYBE: this function is likely responsible for not always
+ suggesting the best filename... To be investigated some more... */
+ gtk_tree_model_get (tm, iter, 0, &meta,
+ 15, &local_filename,
+ 16, &downloaded_anonymity,
+ -1);
+ if ( (NULL == local_filename) && (GNUNET_NO == top) )
+ *local_parents = GNUNET_NO;
+ if ( (downloaded_anonymity != -1) && (*anonymity == -1) && (GNUNET_NO ==
top) )
+ *anonymity = downloaded_anonymity;
+ if (gtk_tree_model_iter_parent (tm, &parent, iter))
+ {
+ have_a_parent = GNUNET_YES;
+ dirname = get_suggested_filename_anonymity (tm, &parent, GNUNET_NO,
+ local_parents, anonymity,
+ filename_is_absolute);
+ }
+ else
+ {
+ have_a_parent = GNUNET_NO;
+ dirname = NULL;
+ if (GNUNET_NO == top)
+ *local_parents = GNUNET_NO;
+ }
+ if (local_filename == NULL)
+ {
+ filename = GNUNET_FS_meta_data_suggest_filename (meta);
+ }
+ else
+ {
+ /* This directory was downloaded as /foo/bar/baz/somedirname
+ * Hopefully, "somedirname" is actually "somedir.gnd"
+ * We need to strip the ".gnd" part to get "somedir", which is
+ * what we're going to use instead of suggested original filename
+ * Without the .gnd extension we're going to just use a copy
+ * of the directory file name - and that would fail. Sad.
+ */
+ if ( (NULL == dirname) && (GNUNET_NO == have_a_parent))
+ {
+ /* This is the ealderlest parent directory. Use absolute path. */
+ basename = (const char *) local_filename;
+ *filename_is_absolute = GNUNET_YES;
+ }
+ else
+ {
+ basename = GNUNET_STRINGS_get_short_name (local_filename);
+ }
+ if ( (NULL != basename) && (strlen (basename) > 0) )
+ {
+ filename = GNUNET_strdup (basename);
+ dot = strrchr (filename, '.');
+ if (dot)
+ *dot = '\0';
+ }
+ else
+ {
+ filename = GNUNET_FS_meta_data_suggest_filename (meta);
+ }
+ }
+ if ( (NULL != dirname) && (NULL != filename) )
+ {
+ GNUNET_asprintf (&result, "%s%s%s", dirname, DIR_SEPARATOR_STR, filename);
+ GNUNET_free (filename);
+ GNUNET_free (dirname);
+ return result;
+ }
+ if (NULL != filename)
+ return filename;
+ return NULL;
+}
+
+
+/**
+ * This function is called when the user double-clicks on a search
+ * result. Begins the download, if necessary by opening the "save as"
+ * window.
+ *
+ * @param tree_view tree view with the details
+ * @param path path selecting which entry we want to download
+ * @param tab the search tab where the user triggered the download request
+ * @param is_recursive was the request for a recursive download?
+ */
+static void
+start_download (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ struct SearchTab *tab,
+ int is_recursive)
+{
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *meta;
+ struct SearchResult *sr;
+ gchar *mime;
+ struct DownloadContext *dc;
+ char *buf = NULL;
+ char *tmp;
+ size_t tmplen;
+ char cwd[FILENAME_MAX];
+ char *download_directory;
+ char *filename;
+ int local_parents;
+ int have_a_suggestion;
+ int anonymity;
+ int filename_is_absolute;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting a %sdownload\n",
+ is_recursive ? "recursive " : "");
+
+ 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);
+ if (NULL == uri)
+ {
+ /* user clicked on directory that was opened (not downloaded!), so we
+ have no URI and downloading makes no sense. Ignore! */
+ g_free (mime);
+ return;
+ }
+ if (!(GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)))
+ {
+ /* can only download chk/loc URIs, ignore */
+ g_free (mime);
+ return;
+ }
+
+ download_directory = get_default_download_directory (cwd, sizeof (cwd));
+ /* If no download directory is known, try working directory */
+ if (download_directory == NULL)
+ download_directory = getcwd (cwd, sizeof (cwd));
+ /* Calculate suggested filename */
+ local_parents = GNUNET_YES;
+ anonymity = -1;
+ filename_is_absolute = GNUNET_NO;
+ filename = get_suggested_filename_anonymity (tm, &iter, GNUNET_YES,
+ &local_parents, &anonymity,
+ &filename_is_absolute);
+ have_a_suggestion = GNUNET_NO;
+ if (NULL != download_directory)
+ {
+ if (NULL == filename)
+ {
+ buf = GNUNET_strdup (download_directory);
+ }
+ else
+ {
+ have_a_suggestion = GNUNET_YES;
+ if (filename_is_absolute)
+ GNUNET_asprintf (&tmp, "%s", filename);
+ else
+ GNUNET_asprintf (&tmp, "%s%s%s",
+ download_directory,
+ DIR_SEPARATOR_STR,
+ filename);
+ tmplen = strlen (tmp);
+ /* now, if we have a directory, replace trailing '/' with ".gnd" */
+ if (GNUNET_YES ==
+ GNUNET_FS_meta_data_test_for_directory (meta))
+ {
+ if ( (tmp[tmplen-1] == '/') ||
+ (tmp[tmplen-1] == '\\') )
+ tmp[tmplen-1] = '\0';
+ GNUNET_asprintf (&buf,
+ "%s%s",
+ tmp,
+ GNUNET_FS_DIRECTORY_EXT);
+ GNUNET_free (tmp);
+ }
+ else
+ {
+ buf = tmp;
+ }
+ }
+ }
+ GNUNET_free_non_null (filename);
+
+ /* now setup everything for the save-as dialog */
+ dc = GNUNET_malloc (sizeof (struct DownloadContext));
+ dc->uri = GNUNET_FS_uri_dup (uri);
+ dc->mime = mime;
+ dc->filename = buf;
+ dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ dc->rr = gtk_tree_row_reference_new (tm, path);
+ dc->sr = sr->result;
+ dc->anonymity = anonymity;
+ dc->is_recursive = is_recursive;
+ dc->tab = tab;
+ if ( (GNUNET_YES == local_parents) &&
+ (GNUNET_YES == have_a_suggestion) )
+ /* Skip the dialog, call directly */
+ GNUNET_FS_GTK_download_context_start_download (dc);
+ else
+ GNUNET_FS_GTK_open_download_as_dialog (dc);
+}
+
+
+/**
+ * An item was selected from the context menu; destroy the menu shell.
+ *
+ * @param menushell menu to destroy
+ * @parma user_data the 'struct DownloadEntry' for the menu (unused)
+ */
+static void
+search_list_popup_selection_done (GtkMenuShell *menushell,
+ gpointer user_data)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Item selected in menu shell %p, destroying it.\n",
+ menushell);
+ gtk_widget_destroy (GTK_WIDGET (menushell));
+}
+
+
+/**
+ * This function is called when the user double-clicks on a search
+ * result. Begins the download, if necessary by opening the "save as"
+ * window.
+ *
+ * @param tree_view tree view with the details
+ * @param path path selecting which entry we want to download
+ * @param column unused entry specifying which column the mouse was in
+ * @param user_data the 'struct SearchTab' that was activated
+ */
+static void
+start_download_row_activated (GtkTreeView * tree_view, GtkTreePath * path,
+ GtkTreeViewColumn * column, gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+
+ start_download (tree_view, path, tab, GNUNET_NO);
+}
+
+
+/**
+ * "Download" was selected in the current search context menu.
+ *
+ * @param item the 'download' menu item
+ * @parma user_data the 'struct DownloadEntry' to download.
+ */
+static void
+start_download_ctx_menu (GtkMenuItem *item, gpointer user_data)
+{
+ 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, current_context_search_tab, GNUNET_NO);
+ gtk_tree_path_free (path);
+ current_context_search_tab = NULL;
+}
+
+
+/**
+ * "Download recursively" was selected in the current search context menu.
+ *
+ * @param item the 'download recursively' menu item
+ * @parma user_data the 'struct DownloadEntry' to download.
+ */
+static void
+start_download_recursively_ctx_menu (GtkMenuItem *item, gpointer user_data)
+{
+ 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, current_context_search_tab, GNUNET_YES);
+ gtk_tree_path_free (path);
+ current_context_search_tab = NULL;
+}
+
+
+/**
+ * Download "abort" was selected in the current search context menu.
+ *
+ * @param item the 'abort' menu item
+ * @parma user_data the 'struct DownloadEntry' to abort.
+ */
+static void
+abort_download_ctx_menu (GtkMenuItem *item, gpointer user_data)
+{
+ struct DownloadEntry *de = user_data;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Aborting download DE=%p\n",
+ de);
+ GNUNET_assert (de->dc != NULL);
+ GNUNET_FS_download_stop (de->dc, GNUNET_YES);
+ current_context_search_tab = NULL;
+}
+
+
+/**
+ * Copy current URI to clipboard was selected in the current context menu.
+ *
+ * @param item the 'copy-to-clipboard' menu item
+ * @parma user_data NULL
+ */
+static void
+copy_uri_to_clipboard_ctx_menu (GtkMenuItem *item, gpointer user_data)
+{
+ GtkTreePath *path;
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ char *uris;
+ GtkClipboard *cb;
+
+ if (NULL == current_context_row_reference)
+ {
+ 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 (! 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);
+}
+
+
+/**
+ * Context menu was requested for a search result list.
+ * Compute which menu items are applicable and display
+ * an appropriate menu.
+ *
+ * @param tm tree model underlying the tree view where the event happened
+ * @param tab tab where the event happened
+ * @param event_button the event
+ * @return FALSE if no menu could be popped up,
+ * TRUE if there is now a pop-up menu
+ */
+static gboolean
+search_list_popup (GtkTreeModel *tm,
+ struct SearchTab *tab,
+ gint init_button,
+ guint32 event_time,
+ GtkTreeIter *iter)
+{
+ GtkMenu *menu;
+ GtkWidget *child;
+ GtkTreePath *path;
+ struct SearchResult *sr;
+ struct GNUNET_FS_Uri *uri;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating a menu for SR=%p, DE=%p\n",
+ sr,
+ sr->download);
+
+ /* FIXME-UNCLEAN: move these to some menu context struct
+ (de-globalize) */
+ 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 = gtk_tree_model_get_path (tm, iter);
+ current_context_row_reference = gtk_tree_row_reference_new (tm, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (tm, iter, 1, &uri, 9, &sr, -1);
+
+ menu = GTK_MENU (gtk_menu_new ());
+ if ( (NULL == sr->download) &&
+ (NULL != uri) )
+ {
+ /* only display download menus if there is a URI */
+ 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);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+
+ child = gtk_menu_item_new_with_label (_("Download _recursively"));
+ g_signal_connect (child, "activate",
+ G_CALLBACK (start_download_recursively_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);
+ }
+ if (NULL != sr->download)
+ {
+ 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);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+ }
+ if (NULL != uri)
+ {
+ 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);
+ }
+ g_signal_connect (menu, "selection-done",
+ G_CALLBACK (search_list_popup_selection_done), NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, init_button, event_time);
+ return TRUE;
+}
+
+
+/**
+ * We got a 'popup-menu' event, display the context menu.
+ *
+ * @param widget the tree view where the event happened
+ * @param user_data the 'struct SearchTab' of the tree view
+ * @return FALSE if no menu could be popped up,
+ * TRUE if there is now a pop-up menu
+ */
+static gboolean
+search_list_on_popup (GtkWidget *widget, gpointer user_data)
+{
+ GtkTreeView *tv = GTK_TREE_VIEW (widget);
+ struct SearchTab *tab = user_data;
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeModel *tm;
+
+ sel = gtk_tree_view_get_selection (tv);
+ if (! gtk_tree_selection_get_selected (sel, &tm, &iter))
+ return FALSE; /* nothing selected */
+ return search_list_popup (tm, tab, 0, gtk_get_current_event_time (), &iter);
+}
+
+
+/**
+ * We got a right-click on the search result list. Display the context
+ * menu.
+ *
+ * @param widget the GtkTreeView with the search result list
+ * @param event the event, we only care about button events
+ * @param user_data the 'struct SearchTab' the widget is in
+ * @return FALSE if no menu could be popped up,
+ * TRUE if there is now a pop-up menu
+ */
+static gboolean
+search_list_on_menu (GtkWidget * widget,
+ GdkEvent * event,
+ gpointer user_data)
+{
+ GtkTreeView *tv = GTK_TREE_VIEW (widget);
+ GdkEventButton *event_button = (GdkEventButton *) event;
+ struct SearchTab *tab = user_data;
+ GtkTreeModel *tm;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ if ( (event->type != GDK_BUTTON_PRESS) ||
+ (event_button->button != 3) )
+ return FALSE; /* not a right-click */
+ if (! gtk_tree_view_get_path_at_pos (tv,
+ event_button->x, event_button->y,
+ &path, NULL, NULL, NULL))
+ return FALSE; /* click outside of area with values, ignore */
+ tm = gtk_tree_view_get_model (tv);
+ if (! gtk_tree_model_get_iter (tm, &iter, path))
+ return FALSE; /* not sure how we got a path but no iter... */
+ gtk_tree_path_free (path);
+ return search_list_popup (tm, tab,
+ event_button->button,
+ event_button->time,
+ &iter);
+}
+
+
+/**
+ * Recalculate and update the label for a search, as we have
+ * received additional search results.
+ *
+ * @param tab search tab for which we should update the label
+ */
+static void
+update_search_label (struct SearchTab *tab)
+{
+ char *label_text;
+
+ while (tab->parent != NULL)
+ tab = tab->parent->tab;
+ if (tab->num_results > 0)
+ GNUNET_asprintf (&label_text, "%.*s%s (%u)", 20, tab->query_txt,
+ strlen (tab->query_txt) > 20 ? "..." : "",
+ tab->num_results);
+ else
+ GNUNET_asprintf (&label_text, "%.*s%s", 20, tab->query_txt,
+ strlen (tab->query_txt) > 20 ? "..." : "");
+ gtk_label_set_text (tab->label, label_text);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), tab->query_txt);
+ GNUNET_free (label_text);
+}
+
+
+/**
+ * Close a search tab and free associated state. Assumes that the
+ * respective tree model has already been cleaned up (this just
+ * updates the notebook and frees the 'tab' itself).
+ *
+ * @param tab search tab to close
+ */
+static void
+close_search_tab (struct SearchTab *tab)
+{
+ GtkNotebook *notebook;
+ int index;
+ int i;
+
+ if (tab->parent != NULL)
+ {
+ /* not a top-level search (namespace update 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);
+ if (tab == uri_tab)
+ uri_tab = NULL;
+ GNUNET_free (tab);
+}
+
+
+/**
+ * Free a particular search result and remove the respective
+ * entries from the respective tree store. This function
+ * is called when a search is stopped to clean up the state
+ * of the tab.
+ *
+ * @param sr the search result to clean up
+ */
+static void
+free_search_result (struct SearchResult *sr)
+{
+ GtkTreePath *tp;
+ GtkTreeModel *tm;
+ GtkTreeIter iter;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_CONTAINER_MetaData *meta;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Freeing a search result SR=%p\n",
+ sr);
+ if ( (NULL == sr) ||
+ (NULL == sr->rr) ||
+ (NULL == (tm = gtk_tree_row_reference_get_model (sr->rr))) ||
+ (NULL == (tp = gtk_tree_row_reference_get_path (sr->rr))) )
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (! gtk_tree_model_get_iter (tm, &iter, tp))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (tp);
+ return;
+ }
+ 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);
+ (void) gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter);
+ GNUNET_free (sr);
+}
+
+
+/**
+ * Selected row has changed in search result tree view, update preview
+ * and metadata areas.
+ *
+ * @param tv the tree view in a search tab where the selection changed
+ * @param user_data the 'struct SearchTab' that contains the tree view
+ */
+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 (! gtk_tree_selection_get_selected (sel, &model, &iter))
+ {
+ /* nothing selected, clear preview */
+ gtk_image_clear (image);
+ return;
+ }
+ meta = NULL;
+ pixbuf = NULL;
+ gtk_tree_model_get (model, &iter, 0, &meta, 3, &pixbuf, -1);
+ if (NULL != pixbuf)
+ {
+ gtk_image_set_from_pixbuf (image, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ if (NULL != meta)
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+
&GNUNET_FS_GTK_add_meta_data_to_list_store,
+ ms);
+}
+
+
+/**
+ * Page switched in main notebook, update thumbnail and
+ * metadata views.
+ *
+ * @param dummy widget emitting the event, unused
+ * @param data master Gtk builder, unused
+ */
+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);
+ for (tab = search_tab_head; NULL != tab; tab = tab->next)
+ {
+ if (tab->frame != w)
+ continue;
+ tv = GTK_TREE_VIEW (gtk_builder_get_object
+ (tab->builder, "_search_result_frame"));
+ update_meta_data_views (tv, tab);
+ return;
+ }
+ /* active tab is not a search tab (likely the 'publish' tab),
+ clear meta data and preview widgets */
+ 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);
+}
+
+
+/**
+ * User clicked on the 'close' button for a search tab. Tell FS to stop the
search.
+ *
+ * @param button the 'close' button
+ * @param user_data the 'struct SearchTab' of the tab to close
+ */
+static void
+stop_search (GtkButton *button, gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+ struct GNUNET_FS_SearchContext *sc;
+
+ sc = tab->sc;
+ if (NULL == sc)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ tab->sc = NULL;
+ GNUNET_FS_search_stop (sc);
+ gtk_widget_hide (GTK_WIDGET (button));
+ gtk_widget_hide (tab->pause_button);
+ gtk_widget_hide (tab->play_button);
+}
+
+
+/**
+ * The user clicked on the 'pause' button for a search tab. Tell FS to pause
the search.
+ *
+ * @param button the 'pause' button
+ * @param user_data the 'struct SearchTab' of the tab to pause
+ */
+static void
+pause_search (GtkButton *button, gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+
+ if (NULL == tab->sc)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_FS_search_pause (tab->sc);
+ gtk_widget_show (tab->play_button);
+ gtk_widget_hide (tab->pause_button);
+}
+
+
+/**
+ * The user clicked on the 'resume' button for a search tab. Tell FS to
resume the search.
+ *
+ * @param button the 'resume' button
+ * @param user_data the 'struct SearchTab' of the tab to resume
+ */
+static void
+continue_search (GtkButton * button, gpointer user_data)
+{
+ struct SearchTab *tab = user_data;
+
+ if (NULL == tab->sc)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_FS_search_continue (tab->sc);
+ gtk_widget_show (tab->pause_button);
+ gtk_widget_hide (tab->play_button);
+}
+
+
+/**
+ * User clicked on the 'clean' button of a search tab.
+ * 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.
+ *
+ * @param button the button pressed by the user
+ * @param user_data the 'struct SearchTab' of the respective tab to clean up
+ */
+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;
+ /* FIXME-BUG: this is a tree, what about cleaning up
+ of the children? */
+ do
+ {
+ gtk_tree_model_get (tm, &iter, 9, &sr, -1);
+ if ( (sr->download != NULL) &&
+ (sr->download->is_done == GNUNET_YES) )
+ {
+ /* got a finished download, stop it */
+ GNUNET_FS_download_stop (sr->download->dc, GNUNET_YES);
+ }
+ if ( (NULL == sr->download) &&
+ (NULL == sr->result) )
+ {
+ /* no active download and no associated FS-API search result;
+ so this must be some left-over entry from an opened
+ directory; clean it up */
+ free_search_result (sr);
+ }
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+}
+
+
+/**
+ * We received a search error message from the FS library.
+ * Present it to the user in an appropriate form.
+ *
+ * @param tab search tab affected by the error
+ * @param emsg the error message
+ */
+static void
+handle_search_error (struct SearchTab *tab,
+ const char *emsg)
+{
+ gtk_label_set_text (tab->label, _("Error!"));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (tab->label), emsg);
+}
+
+
+/**
+ * Obtain the string we will use to describe a search result from
+ * the respective meta data.
+ *
+ * @param meta meta data to inspect
+ * @return description of the result in utf-8, never NULL
+ */
+static char *
+get_description_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta)
+{
+ char *desc;
+ char *utf8_desc;
+
+ 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)
+ return GNUNET_strdup (_("no description supplied"));
+ utf8_desc =
+ GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc,
+ strlen (desc) + 1);
+ GNUNET_free (desc);
+ if (utf8_desc == NULL)
+ return GNUNET_strdup (_("no description supplied"));
+ return utf8_desc;
+}
+
+
+/**
+ * Obtain the mime type (or format description) will use to describe a search
result from
+ * the respective meta data.
+ *
+ * @param meta meta data to inspect
+ * @return mime type to use, possibly NULL
+ */
+static char *
+get_mimetype_from_metadata (const struct GNUNET_CONTAINER_MetaData *meta)
+{
+ return GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_MIMETYPE,
+
EXTRACTOR_METATYPE_FORMAT,
+ -1);
+}
+
+
+/**
+ * Some additional information about a search result has been
+ * received. Update the view accordingly.
+ *
+ * @param sr search result that is being updated
+ * @param meta updated meta data
+ * @param availability_rank updated availability information
+ * @param availability_certainty updated availability certainty
+ * @param applicability_rank updated applicability information
+ */
+static void
+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)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Updating search result SR=%p with %d, %u, %u\n",
+ sr, availability_rank,
+ availability_certainty, applicability_rank);
+ desc = get_description_from_metadata (meta);
+ mime = get_mimetype_from_metadata (meta);
+ 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 (NULL != ometa)
+ 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);
+ }
+}
+
+
+/**
+ * Add a search result to the given search tab. This function is called
+ * not only for 'normal' search results but also for directories that
+ * are being opened and if the user manually enters a URI.
+ *
+ * @param tab search tab to extend, never NULL
+ * @param iter set to position where search result is added (OUT only)
+ * @param parent_rr reference to parent entry in search tab, NULL for normal
+ * search results,
+ * @param uri uri to add, can be NULL for top-level entry of a directory
opened from disk
+ * (in this case, we don't know the URI and should
probably not
+ * bother to calculate it)
+ * @param meta metadata of the entry
+ * @param result associated FS search result (can be NULL if this result
+ * was part of a directory)
+ * @param applicability_rank how relevant is the result
+ * @return struct representing the search result (also stored in the tree
+ * model at 'iter')
+ */
+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 (NULL == uri)
+ {
+ /* opened directory file */
+ fsize = 0;
+ status_colour = "gray";
+ mime = NULL; /* FIXME-FEATURE-MAYBE: should we set mime to directory? */
+ uris = GNUNET_strdup (_("no URI"));
+ }
+ else
+ {
+ if ( (GNUNET_FS_uri_test_loc (uri)) ||
+ (GNUNET_FS_uri_test_chk (uri)) )
+ {
+ fsize = GNUNET_FS_uri_chk_get_file_size (uri);
+ mime = get_mimetype_from_metadata (meta);
+ status_colour = "white";
+ }
+ else
+ {
+ /* FIXME-FEATURE-MAYBE: create mime type for namespaces? */
+ /* FIXME-BUG-MAYBE: can we encounter ksk URIs here too? */
+ fsize = 0;
+ mime = GNUNET_strdup ("GNUnet namespace");
+ status_colour = "lightgreen";
+ }
+ uris = GNUNET_FS_uri_to_string (uri);
+ }
+ desc = get_description_from_metadata (meta);
+ pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
+
+ sr = GNUNET_malloc (sizeof (struct SearchResult));
+ sr->result = result;
+ sr->tab = tab;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Allocated a search result SR=%p\n",
+ sr);
+ 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 (! 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, 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 */
+ 14, (guint64) 0, /* completed */
+ 15, NULL, /* downloaded_filename */
+ 16, -1, /* downloaded_anonymity */
+ -1);
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+ GNUNET_free (uris);
+ GNUNET_free (desc);
+ GNUNET_free_non_null (mime);
+
+ /* remember in 'sr' where we added the result */
+ 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);
+
+ /* move up to the outermost tab, in case this is an 'inner'
+ search (namespace update case) */
+ while (tab->parent != NULL)
+ tab = tab->parent->tab;
+ tab->num_results++;
+
+ return sr;
+}
+
+
+/**
+ * We have received a search result from the FS API. Add it to the
+ * respective search tab. The search result can be an 'inner'
+ * search result (updated result for a namespace search) or a
+ * top-level search result. Update the tree view and the label
+ * of the search tab accordingly.
+ *
+ * @param tab the search tab where the new result should be added
+ * @param parent parent search result (if this is a namespace update result),
or NULL
+ * @param uri URI of the search result
+ * @param meta meta data for the result
+ * @param result FS API handle to the result
+ * @param applicability_rank how applicable is the result to the query
+ * @return struct representing the search result (also stored in the tree
+ * model at 'iter')
+ */
+static struct SearchResult *
+process_search_result (struct SearchTab *tab,
+ 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 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 search tab.
+ *
+ * @param sc context with FS for the search, NULL for none (open-URI/orphan
tab)
+ * @param query the query, NULL for none (open-URI/orphan tab)
+ * @return search tab handle
+ */
+static struct SearchTab *
+setup_search_tab (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)
+ {
+ /* no real query, tab is for non-queries, use special label */
+ tab->query_txt = GNUNET_strdup ("*");
+ }
+ else
+ {
+ /* FS_uri functions should produce UTF-8, so let them be */
+ 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 ("gnunet_fs_gtk_search_tab.glade",
+ tab);
+ 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));
+ g_object_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));
+ g_object_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"));
+
+ /* FIXME-UNCLEAN: connect these signals using glade!!! */
+ 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; FIXME-UNCLEAN: again, connect these with glade... */
+ 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_row_activated), 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);
+ g_signal_connect (G_OBJECT (tv), "popup-menu",
+ G_CALLBACK (search_list_on_popup), 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, that is a subtree representing namespace
+ * 'update' results. We use a 'struct SearchTab' to represent this
+ * sub-search. In the GUI, the presentation is similar to search
+ * results in a directory, except that this is for a namespace search
+ * result that gave pointers to an alternative keyword to use and this
+ * is the set of the results found for this alternative keyword.
+ *
+ * All of the 'widget' elements of the returned 'search tab' reference
+ * the parent search. The whole construction is essentially a trick
+ * to allow us to store the FS-API's 'SearchContext' somewhere and to
+ * find it when we get this kind of 'inner' search results (so that we
+ * can then place them in the tree view in the right spot).
+ *
+ * FIXME-BUG-MAYBE: don't we need a bit more information then? Like exactly
where
+ * this 'right spot' is? Not sure how just having 'sc' helps there,
+ * as it is not a search result (!) to hang this up on! This might
+ * essentially boil down to an issue with the FS API, not sure...
+ *
+ * @param sc context with FS for the search
+ * @param parent parent search tab
+ * @return struct representing the search result (also stored in the tree
+ * model at 'iter')
+ */
+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;
+}
+
+
+/**
+ * Setup a new top-level entry in the URI/orphan tab. If necessary, create
+ * the URI tab first.
+ *
+ * @param iter set to the new entry (OUT only)
+ * @param srp set to search result (can be NULL)
+ * @param meta metadata for the new entry
+ * @param uri URI for the new entry
+ * @return the 'uri_tab' the result was added to
+ */
+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 SearchResult *sr;
+ GtkNotebook *notebook;
+ gint page;
+
+ if (NULL == uri_tab)
+ {
+ uri_tab = setup_search_tab (NULL, NULL);
+ gtk_widget_set_visible (uri_tab->close_button, FALSE);
+ gtk_widget_set_visible (uri_tab->pause_button, FALSE);
+ }
+ /* make 'uri_tab' 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 (uri_tab->frame == gtk_notebook_get_nth_page (notebook, page))
+ {
+ gtk_notebook_set_current_page (notebook, page);
+ break;
+ }
+ sr = GNUNET_GTK_add_search_result (uri_tab, iter, NULL, uri, meta, NULL, 0);
+ if (NULL != srp)
+ *srp = sr;
+ return uri_tab;
+}
+
+
+
+/* ***************** Download event handling ****************** */
+
+
+
+/**
+ * Change the (background) color of the given download entry.
+ *
+ * @param de entry to change
+ * @param color name of the color to use
+ */
+static void
+change_download_color (struct DownloadEntry *de,
+ const char *color)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Changing download DE=%p color to %s\n",
+ de, color);
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->ts, &iter, 8, color, -1);
+}
+
+
+/**
+ * A download operation was stopped. Remove all state associated with
+ * it and reset the search result's background color to 'white'.
+ *
+ * @param de the download that was stopped
+ */
+static void
+stop_download (struct DownloadEntry *de)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeModel *tm;
+ struct SearchResult *search_result;
+
+ tm = gtk_tree_row_reference_get_model (de->rr);
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (! gtk_tree_model_get_iter (tm, &iter, path))
+ {
+ gtk_tree_path_free (path);
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_model_get (tm, &iter, 9, &search_result, -1);
+ GNUNET_assert (search_result->download == de);
+ search_result->download = NULL;
+ change_download_color (de, "white");
+ gtk_tree_row_reference_free (de->rr);
+ GNUNET_FS_uri_destroy (de->uri);
+ GNUNET_CONTAINER_meta_data_destroy (de->meta);
+ GNUNET_free (de);
+}
+
+
+/**
+ * Closure for 'add_directory_entry'.
+ */
+struct AddDirectoryEntryContext
+{
+
+ /**
+ * Search tab where we need to expand the result list.
+ */
+ struct SearchTab *tab;
+
+ /**
+ * Row reference of parent (the directory).
+ */
+ GtkTreeRowReference *prr;
+
+ /**
+ * Do we need to check if the given entry already exists to
+ * avoid adding it twice? Set to YES if 'add_directory_entry'
+ * is called upon directory completion (so we might see all
+ * entries again) and to NO if this is the initial download
+ * and we're calling during a 'PROGRESS' event.
+ */
+ int check_duplicates;
+
+};
+
+
+/**
+ * Function used to process entries in a directory. Whenever we
+ * download a directory, this function is called on the entries in the
+ * directory to add them to the search tab. Note that the function
+ * maybe called twice for the same entry, once during incremental
+ * processing and later once more when we have the complete directory.
+ *
+ * For the second round, the 'check_duplicates' flag will be set in
+ * the closure. If called on an entry that already exists, the
+ * function should simply do nothing.
+ *
+ * @param cls closure, our 'struct AddDirectoryEntryContext*'
+ * @param filename name of the file in the directory
+ * @param uri URI of the file, NULL for the directory itself
+ * @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;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding directory entry `%s'\n",
+ filename);
+
+ if (NULL == uri)
+ {
+ /* directory meta data itself */
+ /* FIXME-FEATURE-MAYBE: consider merging it with the meta data from
+ the original search result... */
+ return;
+ }
+ if (ade->check_duplicates == GNUNET_YES)
+ {
+ tm = gtk_tree_row_reference_get_model (ade->prr);
+ path = gtk_tree_row_reference_get_path (ade->prr);
+ if (! 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->tab, &iter, ade->prr, uri, meta, NULL,
+ 0);
+}
+
+
+/**
+ * We got an event that some download is progressing. Update the tree
+ * model accordingly. If the download is a directory, try to display
+ * the contents.
+ *
+ * @param de download entry that is progressing
+ * @param size overall size of the download
+ * @param completed number of bytes we have completed
+ * @param block_data current block we've downloaded
+ * @param offset offset of block_data in the overall file
+ * @param block_size number of bytes in block_data
+ * @param depth depth of the block in the ECRS tree
+ */
+static void
+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)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Marking download progress for DE=%p, %llu/%llu, address@hidden
depth=%u\n",
+ de, completed, size, block_size, offset, depth);
+
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ /* FIXME-FEATURE: update availability-score here as well! */
+ gtk_tree_store_set (de->ts, &iter,
+ 4, (guint) ((size >
+ 0) ? (100 * completed /
+ size) : 100) /* progress */ ,
+ 14, completed,
+ -1);
+ if ( (depth == 0) &&
+ (block_size > 0) &&
+ (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) )
+ {
+ /* got a data block of a directory, list its contents */
+ struct AddDirectoryEntryContext ade;
+
+ ade.tab = de->tab;
+ 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))
+ {
+ /* Mime type was wrong, this is not a directory, update model! */
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_meta_data_delete (de->meta,
+
EXTRACTOR_METATYPE_MIMETYPE, NULL, 0));
+ gtk_tree_store_set (de->ts, &iter,
+ 10, "" /* unknown mime type */, -1);
+ }
+ }
+}
+
+
+/**
+ * FS-API encountered an error downloading a file. Update the
+ * view accordingly.
+ *
+ * @param de download that had an error
+ * @param emsg error message to display
+ */
+static void
+mark_download_error (struct DownloadEntry *de,
+ const char *emsg)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ change_download_color (de, "red");
+ de->is_done = GNUNET_YES;
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (de->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (de->tab->ts, &iter, 4, 0, 7, emsg, -1);
+}
+
+
+/**
+ * FS-API notified us that we're done with a download. Update the
+ * view accordingly. If the download is a directory, try to display
+ * the contents.
+ *
+ * @param de download that has finished
+ * @param size overall size of the file
+ * @param filename name of the downloaded file on disk (possibly a temporary
file)
+ */
+static void
+mark_download_completed (struct DownloadEntry *de, uint64_t size,
+ const char *filename)
+{
+ struct AddDirectoryEntryContext ade;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Marking download completed for DE=%p, %llu-byte `%s'\n",
+ de, size, filename);
+
+ de->is_done = GNUNET_YES;
+ mark_download_progress (de, size, size, NULL, 0, 0, 0);
+ if ( (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) &&
+ (filename != NULL) )
+ {
+ /* download was for a directory (and we have a temp file for scanning);
+ add contents of the directory to the view */
+ ade.tab = de->tab;
+ ade.prr = de->rr;
+ ade.check_duplicates = GNUNET_YES;
+ GNUNET_FS_GTK_mmap_and_scan (filename, &add_directory_entry, &ade);
+ }
+ change_download_color (de, "green");
+}
+
+
+/**
+ * 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.
+ *
+ * @param src_model source model
+ * @param src_iter parent of the nodes to move
+ * @param dst_model destination model
+ * @param dst_iter new parent of the entries we are moving
+ */
+static void
+copy_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, completed;
+ 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;
+ gchar *downloaded_filename;
+ gint downloaded_anonymity;
+
+ if (! gtk_tree_model_iter_children (src_model, &src_child, src_iter))
+ return;
+ 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, 14,
+ &completed, 15, &downloaded_filename, 16,
+ &downloaded_anonymity, -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, 14, completed, 15,
+ downloaded_filename, 16,
+ downloaded_anonymity, -1);
+ g_free (filename);
+ g_free (downloaded_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);
+ search_result->result = NULL;
+ 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);
+ }
+ copy_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).
+ *
+ * @param model model that contains the subtree to remove
+ * @param iter root of the subtree to remove
+ */
+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.
+ *
+ * @param de download where the parent (i.e. search) was lost
+ */
+static void
+download_lost_parent (struct DownloadEntry *de)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ struct SearchTab *tab;
+ GtkTreeRowReference *rr_old;
+ GtkTreeModel *tm_old;
+ GtkTreeIter iter_old;
+ GtkTreeIter child;
+ GtkTreeModel *model;
+
+ /* first, move the root of the respective 'de'-tree */
+ rr_old = de->rr;
+ tab = GNUNET_GTK_add_to_uri_tab (&iter, &de->sr, de->meta, de->uri);
+ de->sr->download = de;
+ de->ts = tab->ts;
+ model = GTK_TREE_MODEL (de->ts);
+ path = gtk_tree_model_get_path (model, &iter);
+ de->rr = gtk_tree_row_reference_new (model, path);
+ gtk_tree_path_free (path);
+ 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);
+ if (! gtk_tree_model_get_iter (tm_old, &iter_old, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+
+ /* finally, move all children over as well */
+ copy_children (tm_old, &iter_old, model, &iter);
+ while (gtk_tree_model_iter_children (model, &child, &iter))
+ delete_stale_subtree (model, &child);
+}
+
+
+/**
+ * Setup a new download entry.
+ *
+ * @param de existing download entry for the download, or NULL (in which case
we create a fresh one)
+ * @param pde parent download entry, or NULL
+ * @param sr search result, or NULL
+ * @param dc download context (for stopping)
+ * @param uri the URI, must not be NULL
+ * @param filename filename on disk
+ * @param meta metadata
+ * @param size total size
+ * @param completed current progress
+ * @return download entry struct for the download (equal to 'de' if 'de' was
not NULL)
+ */
+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 char *filename,
+ const struct GNUNET_CONTAINER_MetaData *meta, uint64_t size,
+ uint64_t completed)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ struct SearchResult *srp;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Setting up download, initially DE=%p, PDE=%p for %p & %p into
%llu/%llu `%s'\n",
+ de, pde, sr, dc, completed, size, filename);
+ GNUNET_assert (NULL != uri);
+ srp = NULL;
+ if (NULL == de)
+ {
+ /* no existing download entry to build on, create a fresh one */
+ de = GNUNET_malloc (sizeof (struct DownloadEntry));
+ de->uri = GNUNET_FS_uri_dup (uri);
+ }
+ else
+ {
+ GNUNET_assert (GNUNET_YES == GNUNET_FS_uri_test_equal (de->uri, uri));
+ }
+ de->dc = dc;
+ de->sr = sr;
+ de->pde = pde;
+ if ( (meta != NULL) && (de->meta == NULL) )
+ de->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ if (NULL != sr)
+ {
+ /* got a search result; display the download in the same location as the
search result */
+ GNUNET_assert (sr->download == NULL);
+ sr->download = de;
+ de->rr = gtk_tree_row_reference_copy (sr->rr);
+ de->ts = sr->tab->ts;
+ de->tab = sr->tab;
+ srp = sr;
+ }
+ if (NULL == de->rr)
+ {
+ /* Stand-alone download with no 'row'/search result affiliated
+ with the download so far; create a fresh entry for this
+ download in the URI tab */
+ de->tab = GNUNET_GTK_add_to_uri_tab (&iter, &srp, 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);
+ srp->download = de;
+ }
+ path = gtk_tree_row_reference_get_path (de->rr);
+ if (! 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 */ ,
+ 6, filename /* filename/description */ ,
+ 8, "blue" /* status colour: pending */ ,
+ 9, srp,
+ 14, completed,
+ -1);
+ return de;
+}
+
+
+
+/* ***************** Publish event handling ****************** */
+
+
+
+/**
+ * Change the (background) color of the given publish entry.
+ *
+ * @param pe entry to change
+ * @param color name of the color to use
+ */
+static void
+change_publish_color (struct PublishEntry *pe,
+ const char *color)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Changing publish PE=%p color to %s\n",
+ pe, color);
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (pe->tab->ts, &iter, 2, color, -1);
+}
+
+
+/**
+ * We got an event that some publishing operation is progressing.
+ * Update the tree model accordingly.
+ *
+ * @param pe publish entry that is progressing
+ * @param size overall size of the file or directory
+ * @param completed number of bytes we have completed
+ */
+static void
+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 (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (pe->tab->ts, &iter, 3,
+ (guint) ((size >
+ 0) ? (100 * completed /
+ size) : 100) /* progress */ ,
+ -1);
+}
+
+
+/**
+ * FS-API notified us that we're done with some publish operation.
+ * Update the view accordingly.
+ *
+ * @param pe publish operation that has finished
+ * @param uri resulting URI
+ */
+static void
+handle_publish_completed (struct PublishEntry *pe,
+ const struct GNUNET_FS_Uri *uri)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ char *uris;
+
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ pe->uri = GNUNET_FS_uri_dup (uri);
+ uris = GNUNET_FS_uri_to_string (uri);
+ gtk_tree_store_set (pe->tab->ts, &iter,
+ 5, uris,
+ -1);
+ GNUNET_free (uris);
+ change_publish_color (pe, "green");
+}
+
+
+/**
+ * We received a publish error message from the FS library.
+ * Present it to the user in an appropriate form.
+ *
+ * @param pe publishing operation affected by the error
+ * @param emsg the error message
+ */
+static void
+handle_publish_error (struct PublishEntry *pe,
+ const char *emsg)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_store_set (pe->tab->ts, &iter,
+ 5, emsg,
+ -1);
+ change_publish_color (pe, "red");
+}
+
+
+/**
+ * A publishing operation was stopped (in FS API). Free an entry in
+ * the publish tab and its associated state.
+ *
+ * @param pe publishing operation that was stopped
+ */
+static void
+handle_publish_stop (struct PublishEntry *pe)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_row_reference_get_path (pe->rr);
+ /* This is a child of a directory, and we've had that directory
+ free'd already */
+ if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts), &iter, path))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ (void) gtk_tree_store_remove (pe->tab->ts, &iter);
+ gtk_tree_path_free (path);
+ gtk_tree_row_reference_free (pe->rr);
+ if (pe->uri != NULL)
+ {
+ GNUNET_FS_uri_destroy (pe->uri);
+ pe->uri = NULL;
+ }
+ GNUNET_free (pe);
+}
+
+
+/**
+ * The user clicked on the "close" button of the publishing tab.
+ * Tell FS to stop all active publish operations. Then close the tab.
+ *
+ * @param button the stop button
+ * @param user_data the 'struct PublishTab' that is being closed
+ */
+static void
+stop_publishing (GtkButton * button, gpointer user_data)
+{
+ struct PublishTab *tab = user_data;
+ struct PublishEntry *ent;
+ GtkTreeIter iter;
+ GtkTreeModel *tm;
+ GtkNotebook *notebook;
+ int index;
+ int i;
+
+ GNUNET_assert (tab == publish_tab);
+ /* stop all active operations */
+ tm = GTK_TREE_MODEL (publish_tab->ts);
+ if (gtk_tree_model_iter_children (tm, &iter, NULL))
+ {
+ do
+ {
+ gtk_tree_model_get (tm, &iter, 4, &ent, -1);
+ GNUNET_FS_publish_stop (ent->pc);
+ ent->pc = NULL;
+ }
+ while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+ }
+
+ /* remove tab from notebook */
+ 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 (publish_tab->frame == gtk_notebook_get_nth_page (notebook, i))
+ index = i;
+ gtk_notebook_remove_page (notebook, index);
+
+ /* fully destroy tab */
+ g_object_unref (publish_tab->builder);
+ GNUNET_free (publish_tab);
+ publish_tab = NULL;
+}
+
+
+/**
+ * The user started a publishing operation. Add it to the publishing
+ * tab. If needed, create the publishing tab.
+ *
+ * @param pc the FS-API's publishing context for the operation
+ * @param fn the name of the file (or directory) that is being published
+ * @param fsize size of the file
+ * @param parent parent of this publishing operation (for recursive
operations), NULL for top-level operations
+ * @return the publishing entry that will represent this operation
+ */
+static struct PublishEntry *
+setup_publish (struct GNUNET_FS_PublishContext *pc, const char *fn,
+ uint64_t fsize, struct PublishEntry *parent)
+{
+ struct PublishEntry *ent;
+ GtkTreeIter *pitrptr;
+ GtkTreeIter iter;
+ GtkTreeIter piter;
+ GtkTreePath *path;
+ GtkWindow *df;
+ GtkWidget *tab_label;
+ GtkWidget *close_button;
+ GtkNotebook *notebook;
+ char *size_fancy;
+
+ if (NULL == publish_tab)
+ {
+ /* create new tab */
+ publish_tab = GNUNET_malloc (sizeof (struct PublishTab));
+ publish_tab->builder =
+ GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_publish_tab.glade",
+ publish_tab);
+ df = GTK_WINDOW (gtk_builder_get_object
+ (publish_tab->builder, "_publish_frame_window"));
+ publish_tab->frame = gtk_bin_get_child (GTK_BIN (df));
+ g_object_ref (publish_tab->frame);
+ gtk_container_remove (GTK_CONTAINER (df), publish_tab->frame);
+ gtk_widget_destroy (GTK_WIDGET (df));
+
+ /* load tab_label */
+ df = GTK_WINDOW (gtk_builder_get_object
+ (publish_tab->builder, "_publish_label_window"));
+ tab_label = gtk_bin_get_child (GTK_BIN (df));
+ g_object_ref (tab_label);
+ gtk_container_remove (GTK_CONTAINER (df), tab_label);
+ gtk_widget_destroy (GTK_WIDGET (df));
+
+ /* FIXME-UNCLEAN: connect these signals using GLADE!!! */
+ /* get refs to widgets */
+ close_button =
+ GTK_WIDGET (gtk_builder_get_object
+ (publish_tab->builder, "_publish_label_close_button"));
+ g_signal_connect (G_OBJECT (close_button), "clicked",
+ G_CALLBACK (stop_publishing), publish_tab);
+ /* make visible */
+ notebook =
+ GTK_NOTEBOOK (GNUNET_FS_GTK_get_main_window_object
+ ("GNUNET_GTK_main_window_notebook"));
+ gtk_notebook_insert_page (notebook, publish_tab->frame, tab_label, 0);
+ gtk_widget_show (GTK_WIDGET (notebook));
+ gtk_notebook_set_current_page (notebook, 0);
+ publish_tab->ts =
+ GTK_TREE_STORE (gtk_builder_get_object
+ (publish_tab->builder, "_publish_frame_tree_store"));
+ }
+
+ /* decide where to insert in the tab */
+ if (NULL == parent)
+ {
+ pitrptr = NULL;
+ }
+ else
+ {
+ /* create new iter from parent */
+ path = gtk_tree_row_reference_get_path (parent->rr);
+ if (TRUE !=
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (publish_tab->ts), &piter,
+ path))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ pitrptr = &piter;
+ }
+
+ /* create entry and perform insertion */
+ ent = GNUNET_malloc (sizeof (struct PublishEntry));
+ ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
+ ent->tab = publish_tab;
+ ent->pc = pc;
+ size_fancy = GNUNET_STRINGS_byte_size_fancy (fsize);
+ gtk_tree_store_insert_with_values (publish_tab->ts, &iter, pitrptr, G_MAXINT,
+ 0, fn, 1, size_fancy, 2, "white", 3,
+ (guint) 0 /* progress */ ,
+ 4, ent, -1);
+ GNUNET_free (size_fancy);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (publish_tab->ts), &iter);
+ ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (publish_tab->ts),
path);
+ gtk_tree_path_free (path);
+ return ent;
+}
+
+
+
+/* ***************** Master event handler ****************** */
+
+
+
+/**
+ * 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)
+ {
+ handle_publish_error (ret,
+ info->value.publish.specifics.resume.message);
+ }
+ else if (info->value.publish.specifics.resume.chk_uri != NULL)
+ {
+ handle_publish_completed (ret,
+ info->value.publish.specifics.resume.chk_uri);
+ }
+ return ret;
+ case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
+ handle_publish_stop (info->value.publish.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
+ mark_publish_progress (info->value.publish.cctx,
+ info->value.publish.size,
+ info->value.publish.completed);
+ return info->value.publish.cctx;
+ case GNUNET_FS_STATUS_PUBLISH_ERROR:
+ handle_publish_error (info->value.publish.cctx,
+ info->value.publish.specifics.error.message);
+ return info->value.publish.cctx;
+ case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
+ handle_publish_completed (info->value.publish.cctx,
+ info->value.publish.specifics.completed.chk_uri);
+ return info->value.publish.cctx;
+ case GNUNET_FS_STATUS_PUBLISH_STOPPED:
+ handle_publish_stop (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.filename,
+ 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.filename,
+ info->value.download.specifics.resume.meta,
+ info->value.download.size,
+ info->value.download.completed);
+ if (info->value.download.specifics.resume.message != NULL)
+ mark_download_error (ret,
+ info->value.download.specifics.resume.message);
+ return ret;
+ case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND:
+ stop_download (info->value.download.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
+ 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);
+ return info->value.download.cctx;
+ case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
+ mark_download_error (info->value.download.cctx,
+ info->value.download.specifics.error.message);
+ return info->value.download.cctx;
+ case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
+ mark_download_completed (info->value.download.cctx,
+ info->value.download.size,
+ info->value.download.filename);
+ return info->value.download.cctx;
+ case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
+ stop_download (info->value.download.cctx);
+ return NULL;
+ case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
+ change_download_color (info->value.download.cctx, "yellow");
+ return info->value.download.cctx;
+ case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
+ change_download_color (info->value.download.cctx, "blue");
+ return info->value.download.cctx;
+ case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT:
+ download_lost_parent (info->value.download.cctx);
+ return info->value.download.cctx;
+ 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_tab (info->value.search.sc, info->value.search.query);
+ case GNUNET_FS_STATUS_SEARCH_RESUME:
+ ret = setup_search_tab (info->value.search.sc, info->value.search.query);
+ if (info->value.search.specifics.resume.message)
+ 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);
+ 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);
+ return ret;
+ 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:
+ 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);
+ return info->value.search.specifics.update.cctx;
+ case GNUNET_FS_STATUS_SEARCH_ERROR:
+ handle_search_error (info->value.search.cctx,
+ info->value.search.specifics.error.message);
+ return info->value.search.cctx;
+ 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_stopped.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;
+}
+
+
+/* end of gnunet-fs-gtk-event_handler.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h (from rev 19624,
gnunet-gtk/src/fs/gnunet-fs-gtk-event_handler.h)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_event-handler.h 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,241 @@
+/*
+ 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_event-handler.h
+ * @brief Main event handler for file-sharing
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk-common.h"
+
+
+/**
+ * State we keep for each (search) result entry in the
+ * tree view of a search tab.
+ */
+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;
+
+ /**
+ * Text of the search query.
+ */
+ char *query_txt;
+
+ /**
+ * GtkBuilder object for the search tab.
+ */
+ GtkBuilder *builder;
+
+ /**
+ * Frame instance of the search tab.
+ */
+ GtkWidget *frame;
+
+ /**
+ * The widget representing this search in the tab bar (not
+ * a GtkLabel, contains the actual label and the buttons).
+ */
+ GtkWidget *tab_label;
+
+ /**
+ * Button to stop and close the search.
+ */
+ GtkWidget *close_button;
+
+ /**
+ * Button to clear all entries for downloads that have completed.
+ */
+ GtkWidget *clear_button;
+
+ /**
+ * Button to resume the search.
+ */
+ GtkWidget *play_button;
+
+ /**
+ * Button to pause the search.
+ */
+ GtkWidget *pause_button;
+
+ /**
+ * Textual label in the 'tab_label'
+ */
+ GtkLabel *label;
+
+ /**
+ * Tree store with the search results.
+ */
+ GtkTreeStore *ts;
+
+ /**
+ * Number of results we got for this search.
+ */
+ unsigned int num_results;
+
+};
+
+
+/**
+ * Information we keep for each download.
+ */
+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/orphan tab. If necessary, create
+ * the URI tab first.
+ *
+ * @param iter set to the new entry (OUT only)
+ * @param srp set to search result (can be NULL)
+ * @param meta metadata for the new entry
+ * @param uri URI for the new entry
+ * @return the 'uri_tab' the result was added to
+ */
+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, never NULL
+ * @param iter set to position where search result is added (OUT only)
+ * @param parent_rr reference to parent entry in search tab, NULL for normal
+ * search results,
+ * @param uri uri to add, can be NULL for top-level entry of a directory
opened from disk
+ * (in this case, we don't know the URI and should
probably not
+ * bother to calculate it)
+ * @param meta metadata of the entry
+ * @param result associated FS search result (can be NULL if this result
+ * was part of a directory)
+ * @param applicability_rank how relevant is the result
+ * @return struct representing the search result (also stored in the tree
+ * model at 'iter')
+ */
+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 gnunet-fs-gtk-event_handler.h */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_publish-dialog.c (from rev 19628,
gnunet-gtk/src/fs/gnunet-fs-gtk-main_window_file_publish.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_publish-dialog.c
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_publish-dialog.c 2012-02-02 13:28:32 UTC
(rev 19629)
@@ -0,0 +1,1596 @@
+/*
+ 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/gnunet-fs-gtk_publish-dialog.c
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk-common.h"
+#include "gnunet-fs-gtk.h"
+#include "gnunet-fs-gtk-edit_publish_dialog.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_fs_service.h>
+
+#define MARKER_DIR_FILE_SIZE "-"
+
+#define VERBOSE_PROGRESS GNUNET_NO
+
+struct AddDirClientContext;
+
+struct MainPublishingDialogContext
+{
+ GtkBuilder *builder;
+ GtkBuilder *main_window_builder;
+ GtkTreeView *pseudonym_treeview;
+ GtkTreeSelection *pseudonym_selection;
+ GtkTreeModel *pseudonym_treemodel;
+ GtkWidget *up_button;
+ GtkWidget *down_button;
+ GtkWidget *left_button;
+ GtkWidget *right_button;
+ GtkWidget *delete_button;
+ GtkWidget *edit_button;
+ GtkWidget *execute_button;
+ GtkWidget *cancel_button;
+ GtkTreeView *file_info_treeview;
+ GtkTreeSelection *file_info_selection;
+ GtkTreeModel *file_info_treemodel;
+ GtkWindow *master_pubdialog;
+
+ gulong open_directory_handler_id;
+ GtkBuilder *open_directory_builder;
+
+ gulong open_file_handler_id;
+ GtkBuilder *open_file_builder;
+
+ /* To keep multiple scanners running */
+ struct AddDirClientContext *adddir_head;
+ struct AddDirClientContext *adddir_tail;
+};
+
+/* One of these is kept for every directory being opened */
+struct AddDirClientContext
+{
+ struct AddDirClientContext *prev;
+ struct AddDirClientContext *next;
+
+ struct GNUNET_FS_ProcessMetadataContext *pmc;
+
+ struct MainPublishingDialogContext *ctx;
+ struct GNUNET_FS_DirScanner *ds;
+
+ struct GNUNET_FS_ShareTreeItem *directory_scan_result;
+
+ struct GNUNET_FS_BlockOptions directory_scan_bo;
+ int directory_scan_do_index;
+
+ GtkBuilder *progress_dialog_builder;
+ GtkWidget *progress_dialog;
+ GtkProgressBar *progress_dialog_bar;
+ GtkButton *progress_dialog_cancel;
+ GtkTextView *progress_dialog_textview;
+ GtkTextBuffer *progress_dialog_textbuffer;
+ GtkTextMark *progress_dialog_textmark;
+ GtkAdjustment *textview_vertial_adjustment;
+
+ unsigned int done;
+ unsigned int total;
+};
+
+
+static void
+selection_changed_cb (GtkTreeSelection * ts, struct
MainPublishingDialogContext *ctx);
+
+
+/**
+ * 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;
+}
+
+/* Fill out the main publishing dialog context structure */
+static void
+init_ctx (struct MainPublishingDialogContext *ctx)
+{
+ ctx->pseudonym_treeview = GTK_TREE_VIEW (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
+
+ ctx->up_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_up_button"));
+ ctx->down_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_down_button"));
+ ctx->left_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_left_button"));
+ ctx->right_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_right_button"));
+ ctx->delete_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_delete_button"));
+ ctx->edit_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_edit_button"));
+ ctx->execute_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog_execute_button"));
+ ctx->cancel_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder , "GNUNET_GTK_master_publish_dialog_cancel_button"));
+ ctx->file_info_treeview = GTK_TREE_VIEW (gtk_builder_get_object
+ (ctx->builder,
"GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
+
+ ctx->master_pubdialog =
+ GTK_WINDOW (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_master_publish_dialog"));
+
+ ctx->file_info_selection = gtk_tree_view_get_selection
(ctx->file_info_treeview);
+ ctx->file_info_treemodel = gtk_tree_view_get_model (ctx->file_info_treeview);
+ ctx->pseudonym_selection = gtk_tree_view_get_selection
(ctx->pseudonym_treeview);
+ ctx->pseudonym_treemodel = gtk_tree_view_get_model (ctx->pseudonym_treeview);
+
+ g_signal_connect (G_OBJECT (ctx->file_info_selection), "changed",
+ G_CALLBACK (selection_changed_cb), ctx);
+ g_signal_connect (G_OBJECT (ctx->pseudonym_selection), "changed",
+ G_CALLBACK (selection_changed_cb), ctx);
+}
+
+/**
+ * Update selectivity in the master dialog.
+ */
+static void
+update_selectivity (struct MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ int is_dir;
+ struct GNUNET_FS_FileInformation *fip;
+ int ns_ok;
+ gchar *namespace_id;
+
+ ns_ok = GNUNET_YES;
+ if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection, NULL,
&iter))
+ {
+ gtk_tree_model_get (ctx->pseudonym_treemodel, &iter, 2, &namespace_id, -1);
+ if (namespace_id == NULL)
+ ns_ok = GNUNET_NO;
+ else
+ g_free (namespace_id);
+ }
+ /* Don't let the user close the dialog until all scanners are finished and
+ * their windows are closed
+ */
+ if ((gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter))
+ && (ns_ok == GNUNET_YES) && ctx->adddir_head == NULL)
+ gtk_widget_set_sensitive (ctx->execute_button, TRUE);
+ else
+ gtk_widget_set_sensitive (ctx->execute_button, FALSE);
+ if (ctx->adddir_head == NULL)
+ gtk_widget_set_sensitive (ctx->cancel_button, TRUE);
+ else
+ gtk_widget_set_sensitive (ctx->cancel_button, FALSE);
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ gtk_widget_set_sensitive (ctx->up_button, FALSE);
+ gtk_widget_set_sensitive (ctx->down_button, FALSE);
+ gtk_widget_set_sensitive (ctx->left_button, FALSE);
+ gtk_widget_set_sensitive (ctx->right_button, FALSE);
+ gtk_widget_set_sensitive (ctx->delete_button, FALSE);
+ gtk_widget_set_sensitive (ctx->edit_button, FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive (ctx->delete_button, TRUE);
+ gtk_widget_set_sensitive (ctx->edit_button, TRUE);
+
+ /* now figure out which move operations are currently legal */
+ GNUNET_assert (TRUE == gtk_tree_selection_get_selected
(ctx->file_info_selection, NULL, &iter));
+ if (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter))
+ {
+ gtk_widget_set_sensitive (ctx->down_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (ctx->down_button, FALSE);
+ }
+ GNUNET_assert (TRUE == gtk_tree_selection_get_selected
(ctx->file_info_selection, NULL, &iter));
+ if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
+ {
+ gtk_widget_set_sensitive (ctx->left_button, TRUE);
+ GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
+ }
+ else
+ {
+ gtk_widget_set_sensitive (ctx->left_button, FALSE);
+ GNUNET_assert (TRUE == gtk_tree_model_get_iter_first
(ctx->file_info_treemodel, &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 (ctx->file_info_treemodel, &pred,
&iter))
+ {
+ gtk_tree_model_get (ctx->file_info_treemodel, &pred, 5, &fip, -1);
+ is_dir = GNUNET_FS_file_information_is_directory (fip);
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
+ }
+ if (GNUNET_YES == is_dir)
+ {
+ gtk_widget_set_sensitive (ctx->right_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (ctx->right_button, FALSE);
+ }
+ if (GNUNET_SYSERR != is_dir)
+ {
+ gtk_widget_set_sensitive (ctx->up_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (ctx->up_button, FALSE);
+ }
+}
+
+
+/**
+ * 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 (struct MainPublishingDialogContext *ctx, 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;
+
+ 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 (GTK_TREE_STORE (ctx->file_info_treemodel),
pos, iter, NULL);
+ path = gtk_tree_model_get_path (ctx->file_info_treemodel, pos);
+ row_reference = gtk_tree_row_reference_new (ctx->file_info_treemodel, 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, name);
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ gtk_tree_store_set (GTK_TREE_STORE (ctx->file_info_treemodel), pos, 0,
MARKER_DIR_FILE_SIZE, 1, (gboolean) GNUNET_NO,
+ 2, name, 3, (guint) bo->anonymity_level, 4,
+ (guint) bo->content_priority, 5, fi,
+ 6, (guint64) bo->expiration_time.abs_value,
+ 7, (guint) bo->replication_level,
+ -1);
+ update_selectivity (ctx);
+}
+
+static void
+selection_changed_cb (GtkTreeSelection * ts, struct
MainPublishingDialogContext *ctx)
+{
+ update_selectivity (ctx);
+}
+
+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 (struct MainPublishingDialogContext *ctx, GtkTreeModel * tm,
GtkTreeIter * old,
+ GtkTreeIter * newpos, int dsel)
+{
+ struct GNUNET_FS_FileInformation *fip;
+ gint do_index;
+ gchar *short_fn;
+ guint anonymity_level;
+ guint priority;
+ guint replication_level;
+ guint64 expiration_time_abs;
+ char *fsf;
+ GtkTreePath *path;
+ 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,
+ 6, &expiration_time_abs, 7, &replication_level, -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,
+ 6, expiration_time_abs,
+ 7, replication_level, -1);
+ if (dsel == GNUNET_YES)
+ {
+ 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 (ctx, 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 (ctx->file_info_treeview, path);
+ GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, newpos, path));
+ gtk_tree_path_free (path);
+ gtk_tree_selection_select_iter (ctx->file_info_selection, newpos);
+ }
+ update_selectivity (ctx);
+}
+
+
+/**
+ * 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,
+ struct MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+
+ if (TRUE !=
+ gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter,
cpath))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 5,
new_text, -1);
+ update_selectivity (ctx);
+}
+
+
+/**
+ * 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,
+ struct MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+
+ if (TRUE !=
+ gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter,
cpath))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 2,
new_text, -1);
+ update_selectivity (ctx);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ GtkTreeIter prev;
+ GtkTreeIter pos;
+
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
+ {
+ GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
+ }
+ else if (TRUE != gtk_tree_model_get_iter_first (ctx->file_info_treemodel,
&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 (ctx->file_info_treemodel, &pred,
&iter))
+ {
+ prev = pred;
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
+ }
+ gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, &prev, NULL);
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pos;
+
+
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE != gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, &parent);
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ GtkTreeIter pred;
+ GtkTreeIter prev;
+ GtkTreeIter *pprev;
+ GtkTreeIter pos;
+
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent,
&iter))
+ {
+ GNUNET_assert (TRUE == gtk_tree_model_iter_children
(ctx->file_info_treemodel, &pred, &parent));
+ pprev = &parent;
+ }
+ else if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel,
&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 (ctx->file_info_treemodel, &pred,
&iter))
+ {
+ prev = pred;
+ pprev = &prev;
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&pred));
+ }
+ gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, pprev);
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter next;
+ GtkTreeIter pos;
+
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&next))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel,
&next));
+ gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel),
&pos, NULL, &next);
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES);
+ remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ GtkTreeIter pos;
+ struct GNUNET_FS_BlockOptions bo;
+
+ /* FIXME: consider opening a dialog to get
+ * anonymity, priority and expiration prior
+ * to calling this function (currently we
+ * use default values for those).
+ * Or getting these values from the configuration.
+ */
+ 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 (ctx->file_info_selection, NULL,
&iter))
+ {
+ create_dir_at_iter (ctx, "unnamed/", &bo, NULL, &pos);
+ return;
+ }
+ create_dir_at_iter (ctx, "unnamed/", &bo, &iter, &pos);
+}
+
+
+static void
+insert_progress_dialog_text (struct AddDirClientContext *adcc,
+ const char *text)
+{
+ gtk_text_buffer_insert_at_cursor (adcc->progress_dialog_textbuffer,
+ text, -1);
+ gtk_text_view_place_cursor_onscreen (adcc->progress_dialog_textview);
+ gtk_adjustment_set_value (adcc->textview_vertial_adjustment,
+ gtk_adjustment_get_upper
(adcc->textview_vertial_adjustment));
+}
+
+
+static void
+add_item (struct AddDirClientContext *adcc, GtkTreeStore *ts,
+ struct GNUNET_FS_ShareTreeItem *item,
+ GtkTreeIter *parent,
+ GtkTreeIter *sibling,
+ GtkTreeIter *item_iter)
+{
+ char *file_size_fancy;
+ struct GNUNET_FS_FileInformation *fi;
+ GtkTreeRowReference *row_reference;
+ GtkTreePath *path;
+ struct stat sbuf;
+
+ if (0 != stat (item->filename,
+ &sbuf))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "stat", item->filename);
+ return;
+ }
+
+ gtk_tree_store_insert_after (ts, item_iter, parent, sibling);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), item_iter);
+ row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), path);
+ gtk_tree_path_free (path);
+
+ if (item->is_directory)
+ {
+ if (NULL != item->meta)
+ GNUNET_CONTAINER_meta_data_delete (item->meta,
+ EXTRACTOR_METATYPE_MIMETYPE, NULL, 0);
+ else
+ item->meta = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_FS_meta_data_make_directory (item->meta);
+ if (NULL == item->ksk_uri)
+ item->ksk_uri = GNUNET_FS_uri_ksk_create (GNUNET_FS_DIRECTORY_MIME,
NULL);
+ else
+ GNUNET_FS_uri_ksk_add_keyword (item->ksk_uri, GNUNET_FS_DIRECTORY_MIME,
+ GNUNET_NO);
+ fi = GNUNET_FS_file_information_create_empty_directory (
+ GNUNET_FS_GTK_get_fs_handle (), row_reference, item->ksk_uri,
+ item->meta, &adcc->directory_scan_bo, item->filename);
+ }
+ else
+ {
+ fi = GNUNET_FS_file_information_create_from_file (
+ GNUNET_FS_GTK_get_fs_handle (), row_reference, item->filename,
+ item->ksk_uri, item->meta, adcc->directory_scan_do_index,
+ &adcc->directory_scan_bo);
+ }
+ if (item->is_directory)
+ file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
+ else
+ file_size_fancy = GNUNET_STRINGS_byte_size_fancy (sbuf.st_size);
+
+ gtk_tree_store_set (ts, item_iter, 0, file_size_fancy,
+ 1, (gboolean) adcc->directory_scan_do_index,
+ 2, item->short_filename,
+ 3, (guint) adcc->directory_scan_bo.anonymity_level,
+ 4, (guint) adcc->directory_scan_bo.content_priority,
+ 5, fi,
+ 6, (guint64) adcc->directory_scan_bo.expiration_time.abs_value,
+ 7, (guint) adcc->directory_scan_bo.replication_level, -1);
+ GNUNET_free (file_size_fancy);
+}
+
+
+/**
+ * Traverse the share tree and add it to the tree store
+ *
+ */
+static void
+add_share_items_to_treestore (struct AddDirClientContext *adcc,
+ struct GNUNET_FS_ShareTreeItem *toplevel,
+ GtkTreeIter *parent_iter)
+{
+ struct MainPublishingDialogContext *ctx = adcc->ctx;
+ GtkTreeStore *ts = GTK_TREE_STORE (ctx->file_info_treemodel);
+ GtkTreeIter *sibling_iter;
+ GtkTreeIter last_added;
+ struct GNUNET_FS_ShareTreeItem *item;
+
+ sibling_iter = NULL;
+ for (item = toplevel; item != NULL; item = item->next)
+ {
+ add_item (adcc, ts, item, parent_iter, sibling_iter, &last_added);
+ sibling_iter = &last_added;
+ if (item->is_directory)
+ add_share_items_to_treestore (adcc,
+ item->children_head,
+ sibling_iter);
+ }
+}
+
+
+static void
+close_scan (struct AddDirClientContext *adcc)
+{
+ gtk_widget_destroy (adcc->progress_dialog);
+ g_object_unref (G_OBJECT (adcc->progress_dialog_builder));
+ GNUNET_CONTAINER_DLL_remove (adcc->ctx->adddir_head,
+ adcc->ctx->adddir_tail,
+ adcc);
+ update_selectivity (adcc->ctx);
+ GNUNET_free (adcc);
+}
+
+
+static void
+directory_scan_cb (void *cls,
+ const char *filename, int is_directory,
+ enum GNUNET_FS_DirScannerProgressUpdateReason reason)
+{
+ static struct GNUNET_TIME_Absolute last_pulse;
+ struct AddDirClientContext *adcc = cls;
+ char *s;
+ gdouble fraction;
+
+ switch (reason)
+ {
+ case GNUNET_FS_DIRSCANNER_FILE_START:
+ GNUNET_assert (filename != NULL);
+ if (GNUNET_TIME_absolute_get_duration (last_pulse).rel_value > 100)
+ {
+ gtk_progress_bar_pulse (adcc->progress_dialog_bar);
+ last_pulse = GNUNET_TIME_absolute_get ();
+ }
+#if VERBOSE_PROGRESS
+ if (is_directory)
+ {
+ GNUNET_asprintf (&s, _("Scanning directory `%s'.\n"), filename);
+ insert_progress_dialog_text (adcc, s);
+ GNUNET_free (s);
+ }
+ else
+ adcc->total++;
+#else
+ if (! is_directory)
+ adcc->total++;
+#endif
+ break;
+ case GNUNET_FS_DIRSCANNER_FILE_IGNORED:
+ GNUNET_assert (filename != NULL);
+ GNUNET_asprintf (&s,
+ _("Failed to scan `%s' (access error). Skipping.\n"),
+ filename);
+#if ! VERBOSE_PROGRESS
+ gtk_widget_show (GTK_WIDGET (gtk_builder_get_object
(adcc->progress_dialog_builder,
+
"GNUNET_FS_GTK_progress_dialog_scrolled_window")));
+#endif
+ insert_progress_dialog_text (adcc, s);
+ GNUNET_free (s);
+ break;
+ case GNUNET_FS_DIRSCANNER_ALL_COUNTED:
+ fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total;
+ GNUNET_asprintf (&s, "%u/%u (%3f%%)",
+ adcc->done,
+ adcc->total,
+ 100.0 * fraction);
+ gtk_progress_bar_set_text (adcc->progress_dialog_bar,
+ s);
+ GNUNET_free (s);
+ gtk_progress_bar_set_fraction (adcc->progress_dialog_bar,
+ fraction);
+ break;
+ case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED:
+#if VERBOSE_PROGRESS
+ GNUNET_asprintf (&s, _("Processed file `%s'.\n"), filename);
+ insert_progress_dialog_text (adcc, s);
+ GNUNET_free (s);
+#endif
+ adcc->done++;
+ GNUNET_assert (adcc->done <= adcc->total);
+ fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total;
+ GNUNET_asprintf (&s, "%u/%u (%3f%%)",
+ adcc->done,
+ adcc->total,
+ 100.0 * fraction);
+ gtk_progress_bar_set_text (adcc->progress_dialog_bar,
+ s);
+ GNUNET_free (s);
+ gtk_progress_bar_set_fraction (adcc->progress_dialog_bar,
+ fraction);
+ break;
+ case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR:
+ insert_progress_dialog_text (adcc, _("Operation failed (press cancel)\n"));
+ GNUNET_FS_directory_scan_abort (adcc->ds);
+ adcc->ds = NULL;
+ break;
+ case GNUNET_FS_DIRSCANNER_FINISHED:
+ insert_progress_dialog_text (adcc, _("Scanner has finished.\n"));
+ adcc->directory_scan_result = GNUNET_FS_directory_scan_get_result
(adcc->ds);
+ adcc->ds = NULL;
+ GNUNET_FS_share_tree_trim (adcc->directory_scan_result);
+ add_share_items_to_treestore (adcc,
+ adcc->directory_scan_result,
+ NULL);
+ GNUNET_FS_share_tree_free (adcc->directory_scan_result);
+ adcc->directory_scan_result = NULL;
+ update_selectivity (adcc->ctx);
+ close_scan (adcc);
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+}
+
+
+static void
+scan_file_or_directory (struct MainPublishingDialogContext *ctx,
+ gchar *filename,
+ struct GNUNET_FS_BlockOptions *bo,
+ int do_index)
+{
+ struct AddDirClientContext *adcc;
+ GtkTextIter iter;
+
+ adcc = GNUNET_malloc (sizeof (struct AddDirClientContext));
+ adcc->ctx = ctx;
+ GNUNET_CONTAINER_DLL_insert_tail (ctx->adddir_head, ctx->adddir_tail, adcc);
+ adcc->ds = GNUNET_FS_directory_scan_start (filename,
+ GNUNET_NO, NULL, &directory_scan_cb, adcc);
+ adcc->directory_scan_bo = *bo;
+ adcc->directory_scan_do_index = do_index;
+
+ adcc->progress_dialog_builder = GNUNET_GTK_get_new_builder (
+ "gnunet_fs_gtk_progress_dialog.glade", adcc);
+ adcc->progress_dialog = GTK_WIDGET (gtk_builder_get_object (
+ adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog"));
+ adcc->progress_dialog_bar = GTK_PROGRESS_BAR (gtk_builder_get_object (
+ adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog_progressbar"));
+ adcc->progress_dialog_cancel = GTK_BUTTON (gtk_builder_get_object (
+ adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog_cancel_button"));
+ adcc->progress_dialog_textview = GTK_TEXT_VIEW (
+ gtk_builder_get_object (adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog_textview"));
+ adcc->textview_vertial_adjustment = GTK_ADJUSTMENT (
+ gtk_builder_get_object (adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog_textview_vertical_adjustment"));
+ adcc->progress_dialog_textbuffer = GTK_TEXT_BUFFER (
+ gtk_builder_get_object (adcc->progress_dialog_builder,
+ "GNUNET_FS_GTK_progress_dialog_textbuffer"));
+ gtk_text_buffer_get_end_iter (adcc->progress_dialog_textbuffer,
+ &iter);
+ adcc->progress_dialog_textmark = gtk_text_buffer_create_mark (
+ adcc->progress_dialog_textbuffer, "scroll",
+ &iter, FALSE);
+#if VERBOSE_PROGRESS
+ gtk_widget_show (GTK_WIDGET (gtk_builder_get_object
(adcc->progress_dialog_builder,
+
"GNUNET_FS_GTK_progress_dialog_scrolled_window")));
+#endif
+
+ gtk_window_set_transient_for (GTK_WINDOW (adcc->progress_dialog),
adcc->ctx->master_pubdialog);
+ gtk_window_set_title (GTK_WINDOW (adcc->progress_dialog), filename);
+ gtk_window_present (GTK_WINDOW (adcc->progress_dialog));
+
+ update_selectivity (ctx);
+}
+
+
+static void
+publish_directory_dialog_response_cb (GtkDialog * dialog,
+ gint response_id,
+ struct MainPublishingDialogContext *ctx)
+{
+ char *filename;
+ int do_index;
+ GtkSpinButton *sb;
+ struct GNUNET_FS_BlockOptions bo;
+ GtkWidget *ad;
+
+ if (g_signal_handler_is_connected (G_OBJECT (dialog),
ctx->open_directory_handler_id))
+ g_signal_handler_disconnect (G_OBJECT (dialog),
ctx->open_directory_handler_id);
+ ctx->open_directory_handler_id = 0;
+
+ ad = GTK_WIDGET (gtk_builder_get_object
+ (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog"));
+ if (response_id == -5)
+ {
+ filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(ad));
+ sb = GTK_SPIN_BUTTON (gtk_builder_get_object
+ (ctx->open_directory_builder,
+
"GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
+ if (!GNUNET_GTK_get_selected_anonymity_level
+ (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog_anonymity_combobox",
+ &bo.anonymity_level))
+ bo.anonymity_level = 1;
+ bo.content_priority =
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->open_directory_builder,
+
"GNUNET_GTK_publish_directory_dialog_priority_spin_button")));
+ bo.replication_level =
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->open_directory_builder,
+
"GNUNET_GTK_publish_directory_dialog_replication_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
+ (ctx->open_directory_builder,
+
"GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")));
+
+ scan_file_or_directory (ctx, filename, &bo, do_index);
+ g_free (filename);
+ }
+ gtk_widget_destroy (ad);
+ g_object_unref (G_OBJECT (ctx->open_directory_builder));
+}
+
+
+static void
+publish_file_dialog_response_cb (GtkDialog * dialog,
+ gint response_id,
+ struct MainPublishingDialogContext *ctx)
+{
+ char *filename;
+ struct GNUNET_FS_BlockOptions bo;
+ int do_index;
+ GtkSpinButton *sb;
+ GtkWidget *ad;
+
+ if (g_signal_handler_is_connected (G_OBJECT (dialog),
ctx->open_file_handler_id))
+ g_signal_handler_disconnect (G_OBJECT (dialog), ctx->open_file_handler_id);
+ ctx->open_file_handler_id = 0;
+
+ ad = GTK_WIDGET (gtk_builder_get_object
+ (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog"));
+
+ if (response_id == -5)
+ {
+ /* OK */
+ sb = GTK_SPIN_BUTTON (gtk_builder_get_object
+ (ctx->open_file_builder,
+
"GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
+
+ if (!GNUNET_GTK_get_selected_anonymity_level
+ (ctx->open_file_builder,
"GNUNET_GTK_publish_file_dialog_anonymity_combobox",
+ &bo.anonymity_level))
+ bo.anonymity_level = 1;
+ bo.content_priority =
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->open_file_builder,
+
"GNUNET_GTK_publish_file_dialog_priority_spin_button")));
+ bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb);
+ bo.replication_level =
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->open_file_builder,
+
"GNUNET_GTK_publish_file_dialog_replication_spin_button")));
+ do_index =
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
+ (gtk_builder_get_object
+ (ctx->open_file_builder,
+
"GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
+
+ filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER
(ad));
+
+ scan_file_or_directory (ctx, filename, &bo, do_index);
+
+ g_free (filename);
+ }
+ else
+ {
+ /* Cancel/Escape/close/etc */
+ }
+ gtk_widget_destroy (ad);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkWidget *ad;
+
+ GtkComboBox *combo;
+ GtkTreeModel *anon_treemodel;
+
+ ctx->open_file_builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_file_dialog.glade", ctx);
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_file_builder);
+ ad = GTK_WIDGET (gtk_builder_get_object
+ (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog"));
+
+ /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
+ ctx->open_file_builder,
+ "GNUNET_GTK_publish_file_dialog_priority_spin_button")), 1000);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
+ ctx->open_file_builder,
+ "GNUNET_GTK_publish_file_dialog_replication_spin_button")), 0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (
+ ctx->open_file_builder,
+ "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")), TRUE);
+
+ ctx->open_file_handler_id = g_signal_connect (G_OBJECT (ad), "response",
G_CALLBACK (publish_file_dialog_response_cb), ctx);
+
+ anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object
(ctx->main_window_builder,
+ "main_window_search_anonymity_liststore"));
+ combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_file_builder,
+ "GNUNET_GTK_publish_file_dialog_anonymity_combobox"));
+ gtk_combo_box_set_model (combo, anon_treemodel);
+
+ gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog);
+
+ gtk_window_present (GTK_WINDOW (ad));
+}
+
+
+struct EditPublishContext
+{
+ struct GNUNET_FS_FileInformation *fip;
+
+ GtkTreeModel *tm;
+
+ GtkTreeIter iter;
+};
+
+
+/**
+ * Update tree view based on the information from the
+ * GNUNET_FS_FileInformation publish-structure.
+ *
+ * @param cls closure, a 'struct EditPublishContext *'
+ * @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_OK to continue, GNUNET_NO to remove
+ * this entry from the directory, GNUNET_SYSERR
+ * to abort the iteration
+ */
+static int
+update_treeview_after_edit (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)
+{
+ struct EditPublishContext *epc = cls;
+
+ gtk_tree_store_set (GTK_TREE_STORE (epc->tm), &epc->iter,
+ 1, *do_index,
+ 3, (guint) bo->anonymity_level,
+ 4, (guint) bo->content_priority,
+ 6, (guint64) bo->expiration_time.abs_value,
+ 7, (guint) bo->replication_level,
+ -1);
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called when the edit publish dialog has been closed.
+ *
+ * @param cls closure
+ * @param ret GTK_RESPONSE_OK if the dialog was closed with "OK"
+ * @param root unused (namespace root name)
+ */
+static void
+master_publish_edit_publish_dialog_cb (gpointer cls,
+ gint ret,
+ const char *root)
+{
+ struct EditPublishContext *cbargs = cls;
+
+ if (ret == GTK_RESPONSE_OK)
+ GNUNET_FS_file_information_inspect (cbargs->fip,
&update_treeview_after_edit, cbargs);
+ GNUNET_free (cbargs);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ struct EditPublishContext *cbargs;
+ GtkListStore *anon_liststore;
+
+ anon_liststore = GTK_LIST_STORE (gtk_builder_get_object
(ctx->main_window_builder,
+
"main_window_search_anonymity_liststore"));
+ cbargs = GNUNET_malloc (sizeof (struct EditPublishContext));
+ cbargs->tm = ctx->file_info_treemodel;
+ if (! gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&cbargs->iter))
+ {
+ GNUNET_break (0);
+ GNUNET_free (cbargs);
+ return;
+ }
+ gtk_tree_model_get (ctx->file_info_treemodel, &cbargs->iter,
+ 5, &cbargs->fip,
+ -1);
+ /* FIXME: can we just give our anon_liststore out like this? What about
+ (unintended) sharing of state? */
+ GNUNET_FS_GTK_edit_publish_dialog (ctx->master_pubdialog,
+ cbargs->fip,
+ GNUNET_YES,
+ anon_liststore,
+ &master_publish_edit_publish_dialog_cb,
+ cbargs);
+}
+
+
+/**
+ * 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,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkTreeIter iter;
+ struct GNUNET_FS_FileInformation *fip;
+
+ if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL,
&iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ gtk_tree_model_get (ctx->file_info_treemodel, &iter, 5, &fip, -1);
+ GNUNET_FS_file_information_destroy (fip, &free_fi_row_reference, NULL);
+ gtk_tree_store_remove (GTK_TREE_STORE (ctx->file_info_treemodel), &iter);
+ update_selectivity (ctx);
+}
+
+
+void
+GNUNET_FS_GTK_progress_dialog_cancel_button_clicked_cb (GtkButton *button,
+ void *cls)
+{
+ struct AddDirClientContext *adcc = cls;
+
+ if (adcc->ds != NULL)
+ {
+ /* Still scanning - signal the scanner to finish */
+ GNUNET_FS_directory_scan_abort (adcc->ds);
+ adcc->ds = NULL;
+ }
+ close_scan (adcc);
+}
+
+
+gboolean
+GNUNET_FS_GTK_progress_dialog_delete_event_cb (GtkWidget *widget,
+ GdkEvent * event,
+ void *cls)
+{
+ /* Don't allow GTK to kill the window, until the scan is finished */
+ return GNUNET_NO;
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy,
+ struct
MainPublishingDialogContext *ctx)
+{
+ GtkWidget *ad;
+
+ GtkComboBox *combo;
+ GtkTreeModel *anon_treemodel;
+
+ ctx->open_directory_builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_directory_dialog.glade", ctx);
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_directory_builder);
+
+ /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
+ ctx->open_directory_builder,
+ "GNUNET_GTK_publish_directory_dialog_priority_spin_button")), 1000);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (
+ ctx->open_directory_builder,
+ "GNUNET_GTK_publish_directory_dialog_replication_spin_button")), 0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (
+ ctx->open_directory_builder,
+ "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")), TRUE);
+
+ ad = GTK_WIDGET (gtk_builder_get_object
+ (ctx->open_directory_builder,
"GNUNET_GTK_publish_directory_dialog"));
+
+ ctx->open_directory_handler_id = g_signal_connect (G_OBJECT (ad),
"response", G_CALLBACK (publish_directory_dialog_response_cb), ctx);
+
+ anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object
(ctx->main_window_builder,
+ "main_window_search_anonymity_liststore"));
+ combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_directory_builder,
+ "GNUNET_GTK_publish_directory_dialog_anonymity_combobox"));
+ gtk_combo_box_set_model (combo, anon_treemodel);
+
+ gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog);
+
+ gtk_window_present (GTK_WINDOW (ad));
+}
+
+
+/**
+ * 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);
+ /* FIXME: what if this put fails? Not convinced it cannot... */
+ 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);
+ if (desc == NULL)
+ desc = GNUNET_strdup (_("no description supplied"));
+ else
+ {
+ char *utf8_desc = NULL;
+
+ utf8_desc =
+ GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc,
+ strlen (desc) + 1);
+ GNUNET_free (desc);
+ if (utf8_desc != NULL)
+ desc = utf8_desc;
+ else
+ desc = NULL;
+ }
+ 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 (as string!) */ ,
+ 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_CONTAINER_MetaData *meta;
+ struct GNUNET_FS_Namespace *ns;
+ GtkTreeIter child;
+
+ gtk_tree_model_get (tm, iter, 1, &ns, 4, &meta, -1);
+ 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));
+ }
+}
+
+static int
+hide_master_publish_dialog (struct MainPublishingDialogContext *ctx, gint ret)
+{
+ GtkTreeIter iter;
+ gpointer namespace;
+ gchar *namespace_id;
+ gchar *namespace_uid;
+ struct GNUNET_FS_FileInformation *fi;
+
+ /* Don't close until all scanners are finished */
+ if (ctx->adddir_head != NULL)
+ return GNUNET_NO;
+
+ if (ret == GTK_RESPONSE_OK)
+ {
+ if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection,
NULL, &iter))
+ {
+ gtk_tree_model_get (ctx->pseudonym_treemodel, &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 (ctx->file_info_treemodel, &iter))
+ do
+ {
+ fi = get_file_information (ctx->file_info_treemodel, &iter);
+ /* FIXME: should we convert namespace id and uid from UTF8? */
+ 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 (ctx->file_info_treemodel, &iter));
+ g_free (namespace_id);
+ g_free (namespace_uid);
+ }
+
+ /* free state from 'ptm' */
+ if (TRUE == gtk_tree_model_get_iter_first (ctx->pseudonym_treemodel, &iter))
+ do
+ {
+ free_pseudonym_tree_store (ctx->pseudonym_treemodel, &iter);
+ }
+ while (TRUE == gtk_tree_model_iter_next (ctx->pseudonym_treemodel, &iter));
+ gtk_tree_store_clear (GTK_TREE_STORE (ctx->pseudonym_treemodel));
+
+ /* free state from 'tm' */
+ if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter))
+ do
+ {
+ free_file_information_tree_store (ctx->file_info_treemodel, &iter);
+ }
+ while (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter));
+ gtk_tree_store_clear (GTK_TREE_STORE (ctx->file_info_treemodel));
+ gtk_widget_destroy (GTK_WIDGET (ctx->master_pubdialog));
+ g_object_unref (G_OBJECT (ctx->builder));
+ GNUNET_free (ctx);
+ return GNUNET_YES;
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_execute_button_clicked_cb (GtkButton * button,
+ struct
MainPublishingDialogContext *ctx)
+{
+ hide_master_publish_dialog (ctx, GTK_RESPONSE_OK);
+}
+
+
+void
+GNUNET_GTK_master_publish_dialog_cancel_button_clicked_cb (GtkButton * button,
+ struct
MainPublishingDialogContext *ctx)
+{
+ hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL);
+}
+
+
+gboolean
+GNUNET_GTK_master_publish_dialog_delete_event_cb (GtkWidget * widget,
+ GdkEvent * event,
+ struct
MainPublishingDialogContext *ctx)
+{
+ if (GNUNET_NO == hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL))
+ return TRUE;
+ return FALSE;
+}
+
+
+/**
+ */
+void
+GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy, gpointer
user_data)
+{
+ struct MainPublishingDialogContext *ctx;
+
+ ctx = GNUNET_malloc (sizeof (struct MainPublishingDialogContext));
+ ctx->builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_publish_dialog.glade", ctx);
+
+ if (ctx->builder == NULL)
+ {
+ GNUNET_free (ctx);
+ return;
+ }
+
+ init_ctx (ctx);
+ ctx->main_window_builder = GTK_BUILDER (user_data);
+ GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
+ &add_namespace_to_ts, GTK_TREE_STORE
(ctx->pseudonym_treemodel));
+ gtk_window_present (GTK_WINDOW (ctx->master_pubdialog));
+}
+
+
+/* end of gnunet-fs-gtk-main_window_file_publish.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.c (from rev 19628,
gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.c)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.c
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.c 2012-02-02
13:28:32 UTC (rev 19629)
@@ -0,0 +1,1163 @@
+/*
+ This file is part of GNUnet
+ (C) 2005, 2006, 2010, 2012 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_publish-edit-dialog.c
+ * @author Christian Grothoff
+ */
+#include "gnunet-fs-gtk-common.h"
+#include "gnunet-fs-gtk-edit_publish_dialog.h"
+#include "gnunet-fs-gtk.h"
+#include <gnunet/gnunet_util_lib.h>
+
+#include "metatypes.c"
+
+
+/**
+ * Internal state kept for each "edit" dialog where the user can edit
+ * publishing information for a file.
+ */
+struct EditPublicationDialogContext
+{
+ /**
+ * Builder for the dialog.
+ */
+ GtkBuilder *builder;
+
+ /**
+ * The 'window' object for the dialog.
+ */
+ GtkWindow *edit_publication_window;
+
+ /**
+ * The confirmation button which closes the dialog (only sensitive
+ * if the values entered are valid).
+ */
+ GtkWidget *confirm_button;
+
+ /**
+ * Tree view showing the meta data for the file.
+ */
+ GtkTreeView *meta_treeview;
+
+ /**
+ * Tree view showing the keywords for the file.
+ */
+ GtkTreeView *keywords_treeview;
+
+ /**
+ * Image showing the preview image for the file.
+ */
+ GtkImage *preview_image;
+
+ /**
+ * Combo box where the user can select the anonymity level.
+ */
+ GtkComboBox *anonymity_combo;
+
+ /**
+ * Liststore of possible publication types.
+ */
+ GtkListStore *pubtypes_liststore;
+
+ /**
+ * Liststore of all possible meta types the user can choose from.
+ * (updated to based on the selected publication type).
+ */
+ GtkListStore *metatypes_liststore;
+
+ /**
+ * Liststore showing the meta data of the file (associated with
+ * the 'meta_treeview'.
+ */
+ GtkListStore *meta_liststore;
+
+ /**
+ * Liststore with the keywords of the file (associated with the
+ * 'keywords_treeview'.
+ */
+ GtkListStore *keywords_liststore;
+
+ /**
+ * Spin button to select content priority level for the file.
+ */
+ GtkSpinButton *priority_spin;
+
+ /**
+ * Spin button to select the expiration year.
+ */
+ GtkSpinButton *expiration_year_spin;
+
+ /**
+ * Spin button to select the replication level.
+ */
+ GtkSpinButton *replication_spin;
+
+ /**
+ * Entry line for adding additional keywords.
+ */
+ GtkEntry *keyword_entry;
+
+ /**
+ * Entry line for setting a namespace root (possibly invisible).
+ */
+ GtkEntry *root_entry;
+
+ /**
+ * Entry line to check indexing vs. inserting (possibly invisible)
+ */
+ GtkToggleButton *index_checkbutton;
+
+ /**
+ * Type ID of the last selected item in the GtkCellRendererCombo
+ * of the meta data tree view.
+ */
+ gint meta_combo_selected_type_id;
+
+ /**
+ * Continuation to call once the dialog has been closed
+ */
+ GNUNET_FS_GTK_EditPublishDialogCallback cb;
+
+ /**
+ * Closure for 'cb'.
+ */
+ void *cb_cls;
+
+ /**
+ * Briefly used temporary meta data set.
+ */
+ struct GNUNET_CONTAINER_MetaData *md;
+
+ /**
+ * Information about the file being published as seen by the FS-API.
+ * This is what we are primarily editing.
+ */
+ struct GNUNET_FS_FileInformation *fip;
+
+ /**
+ * Flag to track if we changed the preview and thus should keep/discard
+ * binary metadata.
+ */
+ int preview_changed;
+
+ /**
+ * Is this operation for a directory?
+ */
+ int is_directory;
+
+ /**
+ * Is it allowed for the user to supply keywords in this dialog?
+ */
+ int allow_no_keywords;
+
+};
+
+
+/**
+ * Free resources associated with the edit publication dialog.
+ *
+ * @param ctx the context of the dialog to release resources of
+ */
+static void
+free_edit_dialog_context (struct EditPublicationDialogContext *ctx)
+{
+ gtk_widget_destroy (GTK_WIDGET (ctx->edit_publication_window));
+ // FIXME-LEAK: destroy builder!
+ GNUNET_free (ctx);
+}
+
+
+
+/* ****************** metadata editing ******************** */
+
+
+
+/**
+ * Update the set of metatypes listed in the dialog based on the
+ * given code.
+ *
+ * @param ctx main dialog context
+ * @param code which set of metatypes is desired?
+ */
+static void
+change_metatypes (struct EditPublicationDialogContext *ctx, gint code)
+{
+ gint pubtype_count;
+ gint max_type;
+ gint i;
+ GtkTreeIter iter;
+
+ /* double-check that 'code' is valid */
+ for (pubtype_count = 0; NULL != types[pubtype_count]; pubtype_count++) ;
+ GNUNET_assert (code < pubtype_count);
+
+ /* clear existing selection of metatypes */
+ gtk_list_store_clear (ctx->metatypes_liststore);
+ max_type = EXTRACTOR_metatype_get_max ();
+ /* add new types based on selection */
+ for (i = 0; types[code][i] != EXTRACTOR_METATYPE_RESERVED; i++)
+ if ( (types[code][i] < max_type) && (types[code][i] > 0) )
+ gtk_list_store_insert_with_values (ctx->metatypes_liststore,
+ &iter, G_MAXINT,
+ 0, types[code][i],
+ 1, EXTRACTOR_METAFORMAT_UTF8,
+ 2, EXTRACTOR_metatype_to_string (types
[code][i]),
+ 3, EXTRACTOR_metatype_to_description
(types[code][i]),
+ -1);
+}
+
+
+/**
+ * The user has selected a different publication type.
+ * Update the meta type selection.
+ *
+ * @param widget the publication type combo box widget
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_type_combo_changed_cb (GtkComboBox * widget,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+ gint code;
+
+ if (! gtk_combo_box_get_active_iter (widget, &iter))
+ return;
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->pubtypes_liststore), &iter, 0,
&code, -1);
+ change_metatypes (ctx, code);
+}
+
+
+/**
+ * The user has changed the selection in the meta data tree view.
+ * Update the sensitivity of the 'delete' button.
+ *
+ * @param ts the tree selection object
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+/* FIXME-UNCLEAN: connect this signal via glade (modern versions of Glade
support this) */
+static void
+metadata_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_delete_button")),
+ gtk_tree_selection_get_selected (ts, NULL, NULL));
+}
+
+
+/**
+ * The user changed (and confirmed the change) the type of a
+ * meta-data item in the meta data tree view. Update the type and
+ * text in the list store accordingly.
+ *
+ * @param renderer widget where the change happened
+ * @param path which item was changed in the tree view
+ * @param new_text new value for the item
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_edited_cb
(GtkCellRendererText *renderer,
+ gchar *
path,
+ gchar *
new_text,
+
gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+ gint type_id;
+
+ if (! gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL
(ctx->meta_liststore),
+ &iter,
+ path))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (-1 == ctx->meta_combo_selected_type_id)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ type_id = ctx->meta_combo_selected_type_id;
+ ctx->meta_combo_selected_type_id = -1;
+ gtk_list_store_set (ctx->meta_liststore, &iter,
+ 0, type_id,
+ 1, EXTRACTOR_METAFORMAT_UTF8,
+ 2, EXTRACTOR_metatype_to_string (type_id),
+ 4, EXTRACTOR_metatype_to_description (type_id),
+ -1);
+}
+
+
+/**
+ * The user changed the type of a meta-data item in the meta data
+ * tree view. Obtain the selected type_id and store it in
+ * the 'meta_combo_selected_type_id' field for use by
+ * 'GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_edited_cb'.
+ *
+ * @param combo combo box that was dropped down
+ * @param path which item was changed in the tree view
+ * @param new_iter item that is now selected in the drop-down combo box
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_metadata_tree_view_type_renderer_changed_cb
(GtkCellRendererCombo * combo,
+ gchar
* path_string,
+
GtkTreeIter * new_iter,
+
gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeModel *combo_model;
+ gint type_id;
+
+ g_object_get (combo,
+ "model", &combo_model, NULL);
+ gtk_tree_model_get (combo_model, new_iter,
+ 0, &type_id,
+ -1);
+ ctx->meta_combo_selected_type_id = type_id;
+}
+
+
+/**
+ * The user changed (and confirmed the change) the value of a
+ * meta-data item in the meta data tree view. Update the value
+ * in the list store accordingly.
+ *
+ * @param renderer widget where the change happened
+ * @param path which item was changed in the tree view
+ * @param new_text new value for the item
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_metadata_tree_view_value_renderer_edited_cb
(GtkCellRendererText * renderer,
+ gchar
* path,
+ gchar
* new_text,
+
gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+ gint metatype;
+ char *avalue;
+ const char *ivalue;
+ size_t slen;
+ char *pos;
+
+ if (! gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL
(ctx->meta_liststore),
+ &iter,
+ path))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter,
+ 0, &metatype, -1);
+ if (metatype == EXTRACTOR_METATYPE_FILENAME)
+ {
+ /* apply filename rules */
+ /* First, use UNIX-style separators */
+ avalue = GNUNET_strdup (new_text);
+ while (NULL != (pos = strstr (avalue, "\\")))
+ *pos = '/';
+
+ /* if user put '/' at the end, remove it' */
+ slen = strlen (avalue);
+ while ( (slen > 1) && (avalue[slen - 1] == '\\'))
+ {
+ avalue[slen - 1] = '\0';
+ slen--;
+ }
+
+ /* However, directories must end with '/', so add it */
+ if ( (new_text[strlen (new_text) - 1] != '/') &&
+ ctx->is_directory )
+ {
+ char * tmp;
+
+ GNUNET_asprintf (&tmp, "%s/", avalue);
+ GNUNET_free (avalue);
+ avalue = tmp;
+ }
+
+ /* Also, replace '../' everywhere with "___" */
+ while (NULL != (pos = strstr (avalue, "../")))
+ memset (pos, '_', 3);
+
+ ivalue = avalue;
+ }
+ else
+ {
+ ivalue = new_text;
+ avalue = NULL;
+ }
+ gtk_list_store_set (ctx->meta_liststore, &iter,
+ 3, ivalue,
+ -1);
+ GNUNET_free_non_null (avalue);
+}
+
+
+/**
+ * The user has pushed the 'add' button for metadata. Add a 'dummy' value
+ * to our meta data store (to be edited by the user).
+ *
+ * @param button the 'add' button
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_add_button_clicked_cb (GtkButton * button,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+
+ gtk_list_store_insert_with_values (ctx->meta_liststore,
+ &iter, 0,
+ 0, 0,
+ 1, EXTRACTOR_METAFORMAT_UTF8,
+ 2, _("Select a type"),
+ 3, _("Specify a value"),
+ 4, NULL,
+ -1);
+}
+
+
+/**
+ * The user has pushed the 'del' button for metadata.
+ * If there is a metadata selected, remove it from the list store.
+ *
+ * @param widget the button
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_delete_button_clicked_cb (GtkButton * button,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+ GtkTreeSelection *meta_selection;
+
+ meta_selection = gtk_tree_view_get_selection (ctx->meta_treeview);
+ if (! gtk_tree_selection_get_selected (meta_selection, NULL, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (gtk_list_store_remove (ctx->meta_liststore, &iter))
+ gtk_tree_selection_select_iter (meta_selection, &iter);
+}
+
+
+/**
+ * The user has selected another preview image file. Update the
+ * preview image.
+ *
+ * @param widget the file chooser dialog that completed
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_metadata_preview_file_chooser_button_file_set_cb
(GtkFileChooserButton * widget,
+
gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ gchar *fn;
+
+ fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ gtk_image_set_from_file (ctx->preview_image, fn);
+ g_free (fn);
+ ctx->preview_changed = GNUNET_YES;
+}
+
+
+/* ****************** keyword list editing ******************** */
+
+
+
+/**
+ * The user has changed the selection in the keyword tree view.
+ * Update the sensitivity of the 'delete' button.
+ *
+ * @param ts the tree selection object
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+/* FIXME-UNCLEAN: connect this signal via glade (modern versions of Glade
support this) */
+static void
+keywords_selection_changed_cb (GtkTreeSelection *ts,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_keyword_list_del_button")),
+ gtk_tree_selection_get_selected (ts, NULL, NULL));
+}
+
+
+/**
+ * The user has edited the keyword entry line. Update the
+ * sensitivity of the 'add' button.
+ *
+ * @param editable the entry line for keywords
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_keyword_entry_changed_cb (GtkEditable * editable,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ const char *keyword;
+
+ keyword = gtk_entry_get_text (ctx->keyword_entry);
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (ctx->builder,
+
"GNUNET_GTK_edit_publication_keyword_list_add_button")),
+ (strlen (keyword) > 0) ? TRUE : FALSE);
+}
+
+
+/**
+ * The user has pushed the 'del' button for the keyword.
+ * If there is a keyword selected, remove it from the list store.
+ *
+ * @param widget the button
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_keyword_list_del_button_clicked_cb (GtkButton *
+ button,
+ gpointer
user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ GtkTreeIter iter;
+ GtkTreeSelection *keywords_selection;
+
+ keywords_selection = gtk_tree_view_get_selection (ctx->keywords_treeview);
+ if (! gtk_tree_selection_get_selected (keywords_selection, NULL, &iter))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (gtk_list_store_remove (GTK_LIST_STORE (ctx->keywords_liststore), &iter))
+ gtk_tree_selection_select_iter (keywords_selection, &iter);
+
+ /* disable confirm button if keywords are required and we have no more
keywords */
+ if ( (! ctx->allow_no_keywords) &&
+ (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL
(ctx->keywords_liststore),
+ &iter)) )
+ gtk_widget_set_sensitive (ctx->confirm_button, FALSE);
+}
+
+
+/**
+ * The user has pushed the 'add' button for the keyword (or pressed RETURN).
+ * If there is a keyword in the line, add it to the list store.
+ *
+ * @param widget the entry line, or NULL (if we are called from 'RETURN')
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_keyword_list_add_button_clicked_cb (GtkButton *
+ button,
+ gpointer
user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+ const char *keyword;
+ GtkTreeIter iter;
+
+ keyword = gtk_entry_get_text (ctx->keyword_entry);
+ if (strlen (keyword) == 0)
+ return;
+ gtk_list_store_insert_with_values (ctx->keywords_liststore,
+ &iter, G_MAXINT,
+ 0, keyword,
+ 1, TRUE,
+ -1);
+ gtk_widget_set_sensitive (ctx->confirm_button, TRUE);
+ gtk_entry_set_text (ctx->keyword_entry, "");
+}
+
+
+/**
+ * The user has pushed a button in the entry line. Check if it was 'RETURN'
+ * and if so consider executing the 'add' action.
+ *
+ * @param widget the entry line
+ * @param event the event information
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+gboolean
+GNUNET_GTK_edit_publication_keyword_entry_key_press_event_cb (GtkWidget *
+ widget,
+ GdkEventKey *
+ event,
+ gpointer
user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ if (event->keyval != GDK_KEY_Return)
+ return FALSE;
+ GNUNET_GTK_edit_publication_keyword_list_add_button_clicked_cb (NULL, ctx);
+ return TRUE;
+}
+
+
+
+/* ****************** handlers for closing the dialog ******************** */
+
+
+/**
+ * The user clicked the 'cancel' button. Abort the operation.
+ *
+ * @param button the cancel button
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_cancel_button_clicked_cb (GtkButton * button,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ ctx->cb (ctx->cb_cls, GTK_RESPONSE_CANCEL, NULL);
+ free_edit_dialog_context (ctx);
+}
+
+
+/**
+ * The user closed the window. Abort the operation.
+ *
+ * @param widget the window
+ * @param event the event that caused the window to close
+ * @param user_data the 'struct EditPublicationDialogContext'
+ * @return TRUE (always)
+ */
+gboolean
+GNUNET_GTK_edit_publication_window_delete_event_cb (GtkWidget * widget,
+ GdkEvent * event,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ ctx->cb (ctx->cb_cls, GTK_RESPONSE_CANCEL, NULL);
+ free_edit_dialog_context (ctx);
+ return TRUE;
+}
+
+
+/**
+ * Copy binary meta data from to the new container and also preserve
+ * all entries that were not changed. In particular, all binary meta
+ * data is removed if the preview was changed, otherwise it is all
+ * kept. Similarly, if values are still in the liststore, they are
+ * fully kept (including plugin name and original format). "Keeping"
+ * a value means that it is added to the 'md' meta data in the dialog
+ * context.
+ *
+ * @param cls closure, a 'struct FileInformationUpdateContext';
+ * contains the 'new' meta data to construct in the 'md'
+ * field and the liststore to check the current value
+ * against in 'meta_liststore'.
+ * @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 EditPublicationDialogContext *ctx = cls;
+ GtkTreeIter iter;
+ gchar *value;
+ guint ntype;
+ guint nformat;
+ int keep;
+
+ keep = GNUNET_NO;
+ switch (format)
+ {
+ case EXTRACTOR_METAFORMAT_UTF8:
+ case EXTRACTOR_METAFORMAT_C_STRING:
+ if (TRUE == gtk_tree_model_get_iter_first (GTK_TREE_MODEL
(ctx->meta_liststore), &iter))
+ {
+ do
+ {
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter, 0,
&ntype, 1, &nformat, 3, &value, -1);
+ if ((ntype == type) && (nformat == format) &&
+ (0 == strcmp (value, data)))
+ {
+ gtk_list_store_remove (ctx->meta_liststore, &iter);
+ keep = GNUNET_YES;
+ g_free (value);
+ break;
+ }
+ g_free (value);
+ }
+ while (TRUE == gtk_tree_model_iter_next (GTK_TREE_MODEL
(ctx->meta_liststore), &iter));
+ }
+ break;
+ case EXTRACTOR_METAFORMAT_UNKNOWN:
+ break;
+ case EXTRACTOR_METAFORMAT_BINARY:
+ if (ctx->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 (ctx->md, plugin_name,
type,
+ format, data_mime_type,
+ data, data_len));
+ return 0;
+}
+
+
+/**
+ * Function called to update the information in FI based on the changes made in
+ * the edit dialog.
+ *
+ * @param cls closure with a 'struct FileInformationUpdateContext *'
+ * @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)
+{
+ struct EditPublicationDialogContext *ctx = cls;
+ GtkTreeIter iter;
+ gint year;
+
+ /* gather publishing options */
+ *do_index = gtk_toggle_button_get_active (ctx->index_checkbutton);
+ GNUNET_break (GNUNET_GTK_get_selected_anonymity_combo_level
(ctx->anonymity_combo,
+
&bo->anonymity_level));
+ bo->content_priority = gtk_spin_button_get_value (ctx->priority_spin);
+ bo->replication_level = gtk_spin_button_get_value (ctx->replication_spin);
+ year = gtk_spin_button_get_value (ctx->expiration_year_spin);
+ bo->expiration_time = GNUNET_FS_year_to_time (year);
+
+ /* update keyword-URI */
+ if (NULL != (*uri))
+ GNUNET_FS_uri_destroy (*uri);
+ *uri = NULL;
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ctx->keywords_liststore),
&iter))
+ {
+ do
+ {
+ gchar *value;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->keywords_liststore), &iter, 0,
&value, -1);
+ if (NULL == *uri)
+ *uri = GNUNET_FS_uri_ksk_create_from_args (1, (const char **) &value);
+ else
+ GNUNET_FS_uri_ksk_add_keyword (*uri, value, GNUNET_NO);
+ g_free (value);
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ctx->keywords_liststore),
&iter));
+ }
+
+ /* update meta data; first, we copy the unchanged values from the original
meta data */
+ ctx->md = GNUNET_CONTAINER_meta_data_create ();
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+ &preserve_meta_items,
+ ctx);
+ /* clear original meta data */
+ GNUNET_CONTAINER_meta_data_clear (meta);
+ /* add all of the 'preserved' values */
+ GNUNET_CONTAINER_meta_data_merge (meta, ctx->md);
+ GNUNET_CONTAINER_meta_data_destroy (ctx->md);
+ ctx->md = NULL;
+ /* now add all of the values from the model; adding will simply do
+ nothing for values that are already in the set because they were
preserved */
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ctx->meta_liststore),
&iter))
+ {
+ do
+ {
+ guint ntype;
+ guint nformat;
+ gchar *value;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->meta_liststore), &iter, 0,
&ntype, 1, &nformat, 3, &value, -1);
+ if (ntype > 0)
+ GNUNET_CONTAINER_meta_data_insert (ctx->md, "<user>", ntype, nformat,
+ "text/plain", value,
+ strlen (value) + 1);
+ g_free (value);
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ctx->meta_liststore),
&iter));
+ }
+
+ /* finally, if we got a new preview, add it as well */
+ if (ctx->preview_changed == GNUNET_YES)
+ {
+ gchar *fn;
+ char *data;
+ gsize data_size;
+ const char *mime;
+ GFile *f;
+ GFileInfo *finfo;
+
+ fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
+ (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_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 (! 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);
+ g_free (fn);
+ }
+ return GNUNET_SYSERR; /* only visit top-level item */
+}
+
+
+/**
+ * The user clicked the 'confirm' button. Push the edits back into the
+ * FileInformation structure and given it and the options back to the
+ * callback. Then clean up the dialog.
+ *
+ * @param button the cancel button
+ * @param user_data the 'struct EditPublicationDialogContext'
+ */
+void
+GNUNET_GTK_edit_publication_confirm_button_clicked_cb (GtkButton * button,
+ gpointer user_data)
+{
+ struct EditPublicationDialogContext *ctx = user_data;
+
+ /* push back changes to file-information */
+ GNUNET_FS_file_information_inspect (ctx->fip,
+ &file_information_update,
+ ctx);
+ /* call our continuation */
+ ctx->cb (ctx->cb_cls,
+ GTK_RESPONSE_OK,
+ gtk_entry_get_text (ctx->root_entry));
+ /* free resources from the edit dialog */
+ free_edit_dialog_context (ctx);
+}
+
+
+
+/* ****************** code for initialization of the dialog
******************** */
+
+
+
+/**
+ * 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 (cls);
+ gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
+ 0, keyword,
+ 1, FALSE,
+ -1);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called to extract the information from FI to populate the edit
dialog.
+ *
+ * @param cls the 'struct EditPublicationDialogContext'
+ * @param fi the entry in the publish-structure (unused)
+ * @param length length of the file or directory (unused)
+ * @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_import (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)
+{
+ struct EditPublicationDialogContext *ctx = cls;
+ GdkPixbuf *pixbuf;
+ char *short_fn;
+ int year;
+
+ /* import options */
+ year = (int) GNUNET_FS_time_to_year (bo->expiration_time);
+ gtk_spin_button_set_value (ctx->expiration_year_spin, year);
+ GNUNET_GTK_select_anonymity_combo_level (ctx->anonymity_combo,
+ bo->anonymity_level);
+ gtk_spin_button_set_value (ctx->priority_spin, bo->content_priority);
+ gtk_spin_button_set_value (ctx->replication_spin, bo->replication_level);
+ gtk_toggle_button_set_active (ctx->index_checkbutton, *do_index);
+
+
+ /* import keywords */
+ if (NULL != *uri)
+ GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword,
ctx->keywords_liststore);
+
+ /* import meta data */
+ if (NULL != meta)
+ {
+ GNUNET_CONTAINER_meta_data_iterate (meta,
+
&GNUNET_FS_GTK_add_meta_data_to_list_store,
+ ctx->meta_liststore);
+ pixbuf = GNUNET_FS_GTK_get_thumbnail_from_meta_data (meta);
+ if (pixbuf != NULL)
+ {
+ gtk_image_set_from_pixbuf (ctx->preview_image, pixbuf);
+ }
+ }
+
+ /* Also update window title based on filename */
+ short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+
EXTRACTOR_METATYPE_FILENAME,
+ -1);
+ if (NULL == short_fn)
+ {
+ gtk_window_set_title (ctx->edit_publication_window, _("<unnamed>"));
+ }
+ else
+ {
+ /* FIXME-BUG-MAYBE: ensure that short_fn is UTF-8 encoded */
+ gtk_window_set_title (ctx->edit_publication_window, short_fn);
+ GNUNET_free (short_fn);
+ }
+ return GNUNET_SYSERR; /* only visit top-level item */
+}
+
+
+/**
+ * Open the dialog to edit file information data.
+ *
+ * @param parent parent window of the dialog
+ * @param fip information about the file information that is to be edited
+ * @param allow_no_keywords is it OK to close the dialog without any keywords?
+ * also used to indicate that this is a namespace
operation
+ * (FIXME-UNCLEAN: overloaded/badly-named argument)
+ * @param anon_liststore liststore with anonymity options (FIXME-UNCLEAN: bad
sharing)
+ * @param cb function to call when the dialog is closed
+ * @param cb_cls closure for 'cb'
+ */
+void
+GNUNET_FS_GTK_edit_publish_dialog (GtkWindow * parent,
+ struct GNUNET_FS_FileInformation *fip,
+ int allow_no_keywords,
+ GtkListStore *anon_liststore,
+ GNUNET_FS_GTK_EditPublishDialogCallback cb,
+ gpointer cb_cls)
+{
+ GtkTreeIter iter;
+ gint code;
+ GtkComboBox *pubtypes_combo;
+ GtkLabel *index_label;
+ GtkLabel *root_label;
+ struct EditPublicationDialogContext *ctx;
+ GtkTreeSelection *meta_selection;
+ GtkTreeSelection *keywords_selection;
+
+ ctx = GNUNET_malloc (sizeof (struct EditPublicationDialogContext));
+ ctx->fip = fip;
+ ctx->preview_changed = GNUNET_NO;
+ ctx->allow_no_keywords = allow_no_keywords;
+ ctx->is_directory = GNUNET_FS_file_information_is_directory (fip);
+ ctx->cb = cb;
+ ctx->cb_cls = cb_cls;
+ ctx->meta_combo_selected_type_id = -1;
+ ctx->builder = GNUNET_GTK_get_new_builder
("gnunet_fs_gtk_edit_publication.glade", ctx);
+
+ if (ctx->builder == NULL)
+ {
+ GNUNET_free (ctx);
+ return;
+ }
+
+ /* obtain various widgets for use later */
+ ctx->pubtypes_liststore =
+ GTK_LIST_STORE (gtk_builder_get_object
+ (ctx->builder,
"GNUNET_GTK_publication_types_liststore"));
+ ctx->metatypes_liststore =
+ GTK_LIST_STORE (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_publication_metadata_types_liststore"));
+ ctx->meta_treeview = GTK_TREE_VIEW (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_edit_publication_metadata_tree_view"));
+ ctx->keywords_treeview = GTK_TREE_VIEW (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_edit_publication_keyword_list_tree_view"));
+ ctx->edit_publication_window =
+ GTK_WINDOW (gtk_builder_get_object (ctx->builder,
+ "GNUNET_GTK_edit_publication_window"));
+ ctx->keywords_liststore = GTK_LIST_STORE (gtk_builder_get_object
+ (ctx->builder,
"GNUNET_GTK_publication_keywords_liststore"));
+ ctx->keyword_entry =
+ GTK_ENTRY (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_edit_publication_keyword_entry"));
+ ctx->confirm_button = GTK_WIDGET (gtk_builder_get_object
+ (ctx->builder,
"GNUNET_GTK_edit_publication_confirm_button"));
+ ctx->preview_image =
+ GTK_IMAGE (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_edit_publication_metadata_preview_image"));
+ ctx->meta_liststore = GTK_LIST_STORE (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_publication_metadata_liststore"));
+ ctx->root_entry = GTK_ENTRY (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_edit_publication_root_entry"));
+ ctx->expiration_year_spin = GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_expiration_year_spin_button"));
+ ctx->priority_spin = GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_priority_spin_button"));
+ ctx->replication_spin = GTK_SPIN_BUTTON
+ (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_replication_spin_button"));
+ ctx->index_checkbutton = GTK_TOGGLE_BUTTON
+ (gtk_builder_get_object
+ (ctx->builder,
+
"GNUNET_GTK_edit_publication_index_checkbutton"));
+ ctx->anonymity_combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->builder,
+
"GNUNET_GTK_edit_publication_anonymity_combobox"));
+
+ /* Basic initialization of widgets models and visibility */
+ gtk_combo_box_set_model (ctx->anonymity_combo,
+ GTK_TREE_MODEL (anon_liststore));
+ GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->builder);
+
+ /* FIXME-UNCLEAN: are the following three even required anymore? */
+ gtk_list_store_clear (ctx->keywords_liststore);
+ gtk_list_store_clear (ctx->meta_liststore);
+ gtk_entry_set_text (ctx->keyword_entry, "");
+
+ pubtypes_combo =
+ GTK_COMBO_BOX (gtk_builder_get_object
+ (ctx->builder, "GNUNET_GTK_edit_publication_type_combo"));
+ if (gtk_combo_box_get_active_iter (pubtypes_combo, &iter))
+ {
+ gtk_tree_model_get (GTK_TREE_MODEL (ctx->pubtypes_liststore), &iter, 0,
&code, -1);
+ change_metatypes (ctx, 0);
+ }
+ else
+ gtk_combo_box_set_active (pubtypes_combo, 0);
+
+ /* indexing does not apply to directories */
+ gtk_widget_set_visible (GTK_WIDGET (ctx->index_checkbutton),
+ ! ctx->is_directory);
+ index_label = GTK_LABEL (gtk_builder_get_object
+ (ctx->builder,
+ "GNUNET_GTK_edit_publication_index_label"));
+ gtk_widget_set_visible (GTK_WIDGET (index_label),
+ ! ctx->is_directory);
+
+ /* show root label only if we must have keywords, which is also only the
+ case for namespaces (FIXME-UNCLEAN: overloaded use of the argument) */
+ gtk_widget_set_visible (GTK_WIDGET (ctx->root_entry),
+ !allow_no_keywords);
+ root_label = GTK_LABEL (gtk_builder_get_object
+ (ctx->builder,
"GNUNET_GTK_edit_publication_root_label"));
+ gtk_widget_set_visible (GTK_WIDGET (root_label),
+ !allow_no_keywords);
+
+ /* FIXME-UNCLEAN: what if we already have keywords? Again, does not really
+ apply to namespace-case, but this seems a bit ugly */
+ gtk_widget_set_sensitive (ctx->confirm_button, allow_no_keywords ? TRUE :
FALSE);
+
+
+ /* FIXME-UNCLEAN: these signal handlers can be set by (modern) versions of
Glade */
+ keywords_selection = gtk_tree_view_get_selection (ctx->keywords_treeview);
+ g_signal_connect (G_OBJECT (keywords_selection), "changed",
+ G_CALLBACK (keywords_selection_changed_cb), ctx);
+ meta_selection = gtk_tree_view_get_selection (ctx->meta_treeview);
+ g_signal_connect (G_OBJECT (meta_selection), "changed",
+ G_CALLBACK (metadata_selection_changed_cb), ctx);
+
+ /* import meta data and options */
+ GNUNET_FS_file_information_inspect (fip, &file_information_import, ctx);
+
+
+ /* Finally, display window */
+ gtk_window_set_transient_for (ctx->edit_publication_window, parent);
+ gtk_window_present (ctx->edit_publication_window);
+}
+
+
+/* end of gnunet-fs-gtk-edit_publish_dialog.c */
Copied: gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.h (from rev 19628,
gnunet-gtk/src/fs/gnunet-fs-gtk-edit_publish_dialog.h)
===================================================================
--- gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.h
(rev 0)
+++ gnunet-gtk/src/fs/gnunet-fs-gtk_publish-edit-dialog.h 2012-02-02
13:28:32 UTC (rev 19629)
@@ -0,0 +1,66 @@
+/*
+ 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/gnunet-fs-gtk_publish-edit-dialog.h
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_FS_GTK_PUBLISH_EDIT_DIALOG_H
+#define GNUNET_FS_GTK_PUBLISH_EDIT_DIALOG_H
+
+#include "gnunet-fs-gtk-common.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_fs_service.h>
+
+
+/**
+ * Function called when the edit publish dialog has been closed.
+ *
+ * @param cls closure
+ * @param ret GTK_RESPONSE_OK if the dialog was closed with "OK"
+ * @param root namespace root, NULL for file publishing
+ */
+typedef void (*GNUNET_FS_GTK_EditPublishDialogCallback) (gpointer cls,
+ int ret,
+ const char *root);
+
+
+/**
+ * Open the dialog to edit file information data.
+ *
+ * @param parent parent window of the dialog
+ * @param fip information about the file information that is to be edited
+ * @param allow_no_keywords is it OK to close the dialog without any keywords?
+ * also used to indicate that this is a namespace
operation
+ * (FIXME: overloaded/badly-named argument)
+ * @param anon_liststore liststore with anonymity options (FIXME: bad sharing)
+ * @param cb function to call when the dialog is closed
+ * @param cb_cls closure for 'cb'
+ */
+void
+GNUNET_FS_GTK_edit_publish_dialog (GtkWindow * parent,
+ struct GNUNET_FS_FileInformation *fip,
+ int allow_no_keywords,
+ GtkListStore *anon_liststore,
+ GNUNET_FS_GTK_EditPublishDialogCallback cb,
+ gpointer cls);
+
+#endif
+/* end of gnunet-fs-gtk-edit_publish_dialog.h */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r19629 - gnunet-gtk/src/fs,
gnunet <=