/* 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_advertise-pseudonym.c * @author Christian Grothoff * @brief allow the user to select a pseudonym to advertise and * then run the advertising dialog (using the edit-publish * dialog functions) and finally do the advertising */ #include "gnunet-fs-gtk_common.h" #include "gnunet-fs-gtk.h" #include "gnunet-fs-gtk_publish-edit-dialog.h" /* *************************** handlers run on closing of the dialog ********************** */ /** * Closure for 'advertise_namespace' and the callback from the editing dialog. */ struct NamespaceAdvertisementContext { /** * Handle to the namespace to advertise. */ struct GNUNET_FS_Namespace *ns; /** * Root of the namespace is stored here temporarily. */ const char *root; /** * File information structure (fake) which we use to run the 'edit' dialog. */ struct GNUNET_FS_FileInformation *fip; }; /** * Actually perform the advertising with the information collected. * * @param cls closure, a 'struct NamespaceAdvertisementContext *' * @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 advertise_namespace (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 NamespaceAdvertisementContext *nds = cls; GNUNET_FS_namespace_advertise (GNUNET_FS_GTK_get_fs_handle (), *uri, nds->ns, meta, bo, nds->root, NULL, NULL); return GNUNET_SYSERR; } /** * Callback invoked from the editing dialog upon completion of the * meta data editing for the advertisement. * * @param cls the 'struct NamespaceAdvertisementContext' * @param ret return value from the dialog * @param root namespace root to use */ static void adv_pseudonym_edit_publish_dialog_cb (gpointer cls, gint ret, const char *root) { struct NamespaceAdvertisementContext *nds = cls; if (ret == GTK_RESPONSE_OK) { nds->root = root; GNUNET_FS_file_information_inspect (nds->fip, &advertise_namespace, nds); nds->root = NULL; } GNUNET_FS_namespace_delete (nds->ns, GNUNET_NO); GNUNET_FS_file_information_destroy (nds->fip, NULL, NULL); GNUNET_free (nds); } /** * Function called from the pseudonym selection dialog upon completion. * * @param dialog the pseudonym selection dialog * @param response_id response code from the dialog * @param user_data the builder of the dialog */ void GNUNET_GTK_select_pseudonym_dialog_response_cb (GtkDialog * dialog, gint response_id, gpointer user_data) { GtkBuilder *builder = GTK_BUILDER (user_data); GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeModel *tm; GtkTreeIter iter; struct GNUNET_FS_Namespace *ns; struct GNUNET_FS_Namespace *nso; GtkWindow *transient; struct NamespaceAdvertisementContext *nds; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_BlockOptions bo; if (-5 != response_id) { gtk_widget_destroy (GTK_WIDGET (dialog)); g_object_unref (G_OBJECT (builder)); return; } tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_tree_view")); sel = gtk_tree_view_get_selection (tv); if (! gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); gtk_widget_destroy (GTK_WIDGET (dialog)); g_object_unref (G_OBJECT (builder)); return; } gtk_tree_model_get (tm, &iter, 1, &ns, -1); /* free all namespaces from list store except "ns" */ if (gtk_tree_model_get_iter_first (tm, &iter)) { do { gtk_tree_model_get (tm, &iter, 1, &nso, -1); if (ns != nso) GNUNET_FS_namespace_delete (nso, GNUNET_NO); } while (gtk_tree_model_iter_next (tm, &iter)); } transient = gtk_window_get_transient_for (GTK_WINDOW (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog)); g_object_unref (G_OBJECT (builder)); nds = GNUNET_malloc (sizeof (struct NamespaceAdvertisementContext)); nds->ns = ns; memset (&bo, 0, sizeof (struct GNUNET_FS_BlockOptions)); bo.expiration_time = GNUNET_FS_year_to_time (GNUNET_FS_get_current_year () + 2); bo.anonymity_level = 1; bo.content_priority = 1000; /* create fake file information to run the 'edit' dialog with */ meta = GNUNET_CONTAINER_meta_data_create (); nds->fip = GNUNET_FS_file_information_create_empty_directory (NULL, NULL, NULL, meta, &bo, NULL); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_FS_GTK_edit_publish_dialog (transient, nds->fip, GNUNET_NO, &adv_pseudonym_edit_publish_dialog_cb, nds); } /** * User deleted 'select pseudonym' dialog. Clean up. * * @param widget the dialog * @param event the destroying event * @param user_data the builder of the dialog * @return TRUE (allow destruction) */ gboolean GNUNET_GTK_select_pseudonym_dialog_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { GtkBuilder *builder = GTK_BUILDER (user_data); GtkTreeModel *tm; GtkTreeIter iter; tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_liststore")); if (gtk_tree_model_get_iter_first (tm, &iter)) { do { struct GNUNET_FS_Namespace *nso; gtk_tree_model_get (tm, &iter, 1, &nso, -1); GNUNET_FS_namespace_delete (nso, GNUNET_NO); } while (gtk_tree_model_iter_next (tm, &iter)); } g_object_unref (G_OBJECT (builder)); return TRUE; } /* *************************** code to create the dialog ********************** */ /** * Callback with information about local (!) namespaces. * Contains the names of the local namespace and the global * ID. Adds the to the list store. * * @param cls closure, the list store. * @param name human-readable identifier of the namespace * @param id hash identifier for the namespace */ static void add_to_list (void *cls, const char *name, const GNUNET_HashCode * id) { GtkListStore *ls = cls; GtkTreeIter iter; gtk_list_store_insert_with_values (ls, &iter, -1, 0, name, 1, GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (), name), -1); } /** * Selection of the pseudonym changed, update the sensitivity * of the buttons. * * @param ts the selection instance * @param user_data the builder of the selection dialog */ static void selection_changed_cb (GtkTreeSelection * ts, gpointer user_data) { GtkBuilder *builder = GTK_BUILDER (user_data); GtkTreeIter iter; GtkWidget *ok_button; ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_ok_button")); if (gtk_tree_selection_get_selected (ts, NULL, &iter)) gtk_widget_set_sensitive (ok_button, TRUE); else gtk_widget_set_sensitive (ok_button, FALSE); } /** * Advertise pseudonym selected in the menu. * * @param dummy the menu item * @param user_data the builder of the main window, unused */ void GNUNET_GTK_main_menu_file_advertise_pseudonym_activate_cb (GtkWidget * dummy, gpointer user_data) { GtkWidget *ad; GtkListStore *ls; GtkWidget *toplevel; GtkTreeView *tv; GtkTreeSelection *sel; GtkBuilder *builder; builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_select_pseudonym_dialog.glade", NULL); if (NULL == builder) { GNUNET_break (0); return; } ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_dialog")); ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_liststore")); GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (), &add_to_list, ls); /* FIXME-UNCLEAN: this signal can be connected by (modern) Glade automatically */ tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_select_pseudonym_tree_view")); sel = gtk_tree_view_get_selection (tv); g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (selection_changed_cb), builder); toplevel = gtk_widget_get_toplevel (dummy); if (GTK_IS_WINDOW (toplevel)) gtk_window_set_transient_for (GTK_WINDOW (ad), GTK_WINDOW (toplevel)); gtk_window_present (GTK_WINDOW (ad)); } /* end of gnunet-fs-gtk_advertise-pseudonym.c */