/* This file is part of GNUnet (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/main_window_file_publish.c * @author Christian Grothoff */ #include "common.h" #include "edit_publish_dialog.h" #include /** * Builder used for the master publish dialog. */ static GtkBuilder *master_builder; /** * Check if two GtkTreeIters refer to the same element. * * @param tm tree model of the iterators * @param i1 first iterator * @param i2 second iterator * @return GNUNET_YES if they are equal */ static int gtk_tree_iter_equals (GtkTreeModel *tm, GtkTreeIter *i1, GtkTreeIter *i2) { GtkTreePath *p1; GtkTreePath *p2; int ret; p1 = gtk_tree_model_get_path (tm, i1); p2 = gtk_tree_model_get_path (tm, i2); ret = gtk_tree_path_compare (p1, p2); gtk_tree_path_free (p1); gtk_tree_path_free (p2); return (0 == ret) ? GNUNET_YES : GNUNET_NO; } /** * Update selectivity in the master dialog. */ static void update_selectivity () { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeModel *ptm; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter parent; GtkTreeIter pred; GtkWidget *up_button; GtkWidget *down_button; GtkWidget *left_button; GtkWidget *right_button; GtkWidget *delete_button; GtkWidget *edit_button; GtkWidget *execute_button; int is_dir; struct GNUNET_FS_FileInformation *fip; int ns_ok; char *namespace_id; tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder, "GNUNET_GTK_file_sharing_publishing_tree_store")); tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view")); sel = gtk_tree_view_get_selection (tv); ns_ok = GNUNET_YES; if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter)) { gtk_tree_model_get (ptm, &iter, 2, &namespace_id, -1); if (namespace_id == NULL) { ns_ok = GNUNET_NO; GNUNET_free (namespace_id); } } up_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_up_button")); down_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_down_button")); left_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_left_button")); right_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_right_button")); delete_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_delete_button")); edit_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_edit_button")); execute_button = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_execute_button")); tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); tm = gtk_tree_view_get_model (tv); if ( (gtk_tree_model_get_iter_first (tm, &iter)) && (ns_ok == GNUNET_YES) ) gtk_widget_set_sensitive (execute_button, TRUE); else gtk_widget_set_sensitive (execute_button, FALSE); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { gtk_widget_set_sensitive (up_button, FALSE); gtk_widget_set_sensitive (down_button, FALSE); gtk_widget_set_sensitive (left_button, FALSE); gtk_widget_set_sensitive (right_button, FALSE); gtk_widget_set_sensitive (delete_button, FALSE); gtk_widget_set_sensitive (edit_button, FALSE); return; } gtk_widget_set_sensitive (delete_button, TRUE); gtk_widget_set_sensitive (edit_button, TRUE); /* now figure out which move operations are currently legal */ GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter)); if (TRUE == gtk_tree_model_iter_next (tm, &iter)) { gtk_widget_set_sensitive (down_button, TRUE); } else { gtk_widget_set_sensitive (down_button, FALSE); } GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter)); if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter)) { gtk_widget_set_sensitive (left_button, TRUE); GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent)); } else { gtk_widget_set_sensitive (left_button, FALSE); GNUNET_assert (TRUE == gtk_tree_model_get_iter_first (tm, &pred)); } /* iterate over 'next' of pred to find out if our predecessor is a directory! */ is_dir = GNUNET_SYSERR; while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter)) { gtk_tree_model_get (tm, &pred, 5, &fip, -1); is_dir = GNUNET_FS_file_information_is_directory (fip); GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred)); } if (GNUNET_YES == is_dir) { gtk_widget_set_sensitive (right_button, TRUE); } else { gtk_widget_set_sensitive (right_button, FALSE); } if (GNUNET_SYSERR != is_dir) { gtk_widget_set_sensitive (up_button, TRUE); } else { gtk_widget_set_sensitive (up_button, FALSE); } } /** * Add a file to the tree model. * * @param filename file to add * @param iter parent entry, or NULL for top-level addition */ static void add_file_at_iter (const char *filename, uint32_t anonymity_level, uint32_t priority, struct GNUNET_TIME_Absolute expiration, int do_index, GtkTreeIter *iter) { struct GNUNET_FS_FileInformation *fi; GtkTreeRowReference *row_reference; GtkTreePath *path; uint64_t file_size; const char *short_fn; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; GtkTreeStore *ts; GtkTreeIter pos; char *file_size_fancy; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &file_size, GNUNET_YES)) { GNUNET_break (0); return; } ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder, "GNUNET_GTK_file_sharing_publishing_tree_store")); meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_FS_meta_data_extract_from_file (meta, filename, GNUNET_GTK_get_le_plugins()); GNUNET_CONTAINER_meta_data_delete (meta, EXTRACTOR_METATYPE_FILENAME, NULL, 0); short_fn = filename; while (NULL != strstr (short_fn, DIR_SEPARATOR_STR)) short_fn = 1 + strstr (short_fn, DIR_SEPARATOR_STR); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", short_fn, strlen(short_fn)+1); ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta); gtk_tree_store_insert_before (ts, &pos, iter, NULL); path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), &pos); row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), path); gtk_tree_path_free (path); fi = GNUNET_FS_file_information_create_from_file (GNUNET_GTK_get_fs_handle (), row_reference, filename, ksk_uri, meta, do_index, anonymity_level, priority, expiration); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_FS_uri_destroy (ksk_uri); file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size); gtk_tree_store_set (ts, &pos, 0, file_size_fancy, 1, (gboolean) do_index, 2, short_fn, 3, (guint)anonymity_level, 4, (guint) priority, 5, fi, -1); GNUNET_free (file_size_fancy); update_selectivity (); } /** * Add an empty directory to the tree model. * * @param name name for the directory * @param iter parent entry, or NULL for top-level addition * @param pos iterator to set to the location of the new element */ static void create_dir_at_iter (const char *name, uint32_t anonymity, uint32_t priority, struct GNUNET_TIME_Absolute expiration, GtkTreeIter *iter, GtkTreeIter *pos) { struct GNUNET_FS_FileInformation *fi; GtkTreeRowReference *row_reference; GtkTreePath *path; struct GNUNET_CONTAINER_MetaData *meta; GtkTreeStore *ts; ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder, "GNUNET_GTK_file_sharing_publishing_tree_store")); meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_FS_meta_data_make_directory (meta); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", name, strlen(name)+1); gtk_tree_store_insert_before (ts, pos, iter, NULL); path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), pos); row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), path); gtk_tree_path_free (path); fi = GNUNET_FS_file_information_create_empty_directory (GNUNET_GTK_get_fs_handle (), row_reference, NULL, meta, anonymity, priority, expiration); GNUNET_CONTAINER_meta_data_destroy (meta); gtk_tree_store_set (ts, pos, 0, "0", 1, (gboolean) GNUNET_NO, 2, name, 3, (guint) anonymity, 4, (guint) priority, 5, fi, -1); update_selectivity (); } struct AddDirContext { GtkTreeIter *parent; uint32_t anonymity_level; uint32_t priority; struct GNUNET_TIME_Absolute expiration; int do_index; }; /** * Add a directory to the tree model. * * @param filename directory name to add * @param iter parent entry, or NULL for top-level addition */ static void add_dir_at_iter (const char *filename, uint32_t anonymity_level, uint32_t priority, struct GNUNET_TIME_Absolute expiration, int do_index, GtkTreeIter *iter); /** * Function called by the directory iterator to * (recursively) add all of the files in the * directory to the tree. */ static int scan_cb (void *cls, const char *filename) { struct AddDirContext *adc = cls; add_dir_at_iter (filename, adc->anonymity_level, adc->priority, adc->expiration, adc->do_index, adc->parent); return GNUNET_OK; } /** * Add a directory to the tree model. * * @param filename directory name to add * @param iter parent entry, or NULL for top-level addition */ static void add_dir_at_iter (const char *filename, uint32_t anonymity_level, uint32_t priority, struct GNUNET_TIME_Absolute expiration, int do_index, GtkTreeIter *iter) { struct stat sbuf; struct AddDirContext scan_ctx; GtkTreeIter pos; fprintf (stderr, "Adding %s\n", filename); if (0 != STAT (filename, &sbuf)) return; if (S_ISDIR (sbuf.st_mode)) { create_dir_at_iter (filename, anonymity_level, priority, expiration, iter, &pos); scan_ctx.parent = &pos; scan_ctx.anonymity_level = anonymity_level; scan_ctx.priority = priority; scan_ctx.expiration = expiration; scan_ctx.do_index = do_index; GNUNET_DISK_directory_scan (filename, &scan_cb, &scan_ctx); } else { add_file_at_iter (filename, anonymity_level, priority, expiration, do_index, iter); } } static void selection_changed_cb (GtkTreeSelection *ts, gpointer user_data) { update_selectivity (); } static void remove_old_entry (GtkTreeStore *ts, GtkTreeIter *root) { GtkTreeIter child; while (TRUE == gtk_tree_model_iter_children (GTK_TREE_MODEL (ts), &child, root)) remove_old_entry (ts, &child); gtk_tree_store_remove (ts, root); } /** * Move an entry in the tree. */ static void move_entry (GtkTreeModel *tm, GtkTreeIter *old, GtkTreeIter *newpos, int dsel) { struct GNUNET_FS_FileInformation *fip; GtkTreeView *tv; gint do_index; char *short_fn; guint anonymity_level; guint priority; char *fsf; GtkTreePath *path; GtkTreeSelection *sel; GtkTreeIter child; GtkTreeIter cnewpos; GtkTreeRowReference *rr; GtkTreeRowReference *rr2; gtk_tree_model_get (tm, old, 0, &fsf, 1, &do_index, 2, &short_fn, 3, &anonymity_level, 4, &priority, 5, &fip, -1); gtk_tree_store_set (GTK_TREE_STORE (tm), newpos, 0, fsf, 1, do_index, 2, short_fn, 3, (guint)anonymity_level, 4, (guint) priority, 5, fip, -1); sel = NULL; tv = NULL; if (dsel == GNUNET_YES) { tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); path = gtk_tree_model_get_path (tm, newpos); rr = gtk_tree_row_reference_new (tm, path); gtk_tree_path_free (path); } else { rr = NULL; } if (TRUE == gtk_tree_model_iter_children (tm, &child, old)) { do { path = gtk_tree_model_get_path (tm, &child); rr2 = gtk_tree_row_reference_new (tm, path); gtk_tree_path_free (path); gtk_tree_store_insert_before (GTK_TREE_STORE (tm), &cnewpos, newpos, NULL); move_entry (tm, &child, &cnewpos, GNUNET_NO); path = gtk_tree_row_reference_get_path (rr2); gtk_tree_row_reference_free (rr2); GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, &child, path)); gtk_tree_path_free (path); } while (TRUE == gtk_tree_model_iter_next (tm, &child)); } g_free (short_fn); g_free (fsf); if (dsel == GNUNET_YES) { path = gtk_tree_row_reference_get_path (rr); gtk_tree_row_reference_free (rr); gtk_tree_view_expand_to_path (tv, path); GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, newpos, path)); gtk_tree_path_free (path); gtk_tree_selection_select_iter (sel, newpos); } update_selectivity (); } /** * User has changed the "current" identifier for the content in * the GtkTreeView. Update the model. */ void GNUNET_GTK_master_publish_dialog_pseudonym_updates_renderer_edited_cb (GtkCellRendererText *renderer, gchar *cpath, gchar *new_text, gpointer user_data) { GtkTreeIter iter; GtkTreeStore *ts; ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder, "GNUNET_GTK_pseudonym_tree_store")); if (TRUE != gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath)) { GNUNET_break (0); return; } gtk_tree_store_set (ts, &iter, 5, new_text, -1); update_selectivity (); } /** * User has changed the "current" identifier for the content in * the GtkTreeView. Update the model. */ void GNUNET_GTK_master_publish_dialog_pseudonym_identifier_renderer_edited_cb (GtkCellRendererText *renderer, gchar *cpath, gchar *new_text, gpointer user_data) { GtkTreeIter iter; GtkTreeStore *ts; ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder, "GNUNET_GTK_pseudonym_tree_store")); if (TRUE != gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath)) { GNUNET_break (0); return; } gtk_tree_store_set (ts, &iter, 2, new_text, -1); update_selectivity (); } void GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter parent; GtkTreeIter pred; GtkTreeIter prev; GtkTreeIter pos; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter)) { GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent)); } else if (TRUE != gtk_tree_model_get_iter_first (tm, &pred)) { GNUNET_break (0); return; } /* iterate over 'next' of pred to find out who our predecessor is! */ memset (&prev, 0, sizeof (GtkTreeIter)); while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter)) { prev = pred; GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred)); } gtk_tree_store_insert_before (GTK_TREE_STORE (tm), &pos, &prev, NULL); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } move_entry (tm, &iter, &pos, GNUNET_YES); remove_old_entry (GTK_TREE_STORE (tm), &iter); } void GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter parent; GtkTreeIter pos; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } if (TRUE != gtk_tree_model_iter_parent (tm, &parent, &iter)) { GNUNET_break (0); return; } gtk_tree_store_insert_after (GTK_TREE_STORE (tm), &pos, NULL, &parent); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } move_entry (tm, &iter, &pos, GNUNET_YES); remove_old_entry (GTK_TREE_STORE (tm), &iter); } void GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter parent; GtkTreeIter pred; GtkTreeIter prev; GtkTreeIter *pprev; GtkTreeIter pos; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter)) { GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent)); pprev = &parent; } else if (TRUE == gtk_tree_model_get_iter_first (tm, &pred)) { pprev = NULL; } else { GNUNET_break (0); return; } /* iterate over 'next' of pred to find out who our predecessor is! */ while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter)) { prev = pred; pprev = &prev; GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred)); } gtk_tree_store_insert_before (GTK_TREE_STORE (tm), &pos, NULL, pprev); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } move_entry (tm, &iter, &pos, GNUNET_YES); remove_old_entry (GTK_TREE_STORE (tm), &iter); } void GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter next; GtkTreeIter pos; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &next)) { GNUNET_break (0); return; } GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &next)); gtk_tree_store_insert_after (GTK_TREE_STORE (tm), &pos, NULL, &next); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } move_entry (tm, &iter, &pos, GNUNET_YES); remove_old_entry (GTK_TREE_STORE (tm), &iter); } void GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeIter pos; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); /* FIXME: consider opening a dialog to get * anonymity, priority and expiration prior * to calling this function (currently we * use default values for those). */ if (TRUE != gtk_tree_selection_get_selected (sel, NULL, &iter)) { create_dir_at_iter ("unnamed/", 1 /* anonymity */, 1000 /* priority */, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS) /* expiration */, NULL, &pos); return; } create_dir_at_iter ("unnamed/", 1 /* anonymity */, 1000 /* priority */, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS) /* expiration */, &iter, &pos); } struct ListValue { const char *text; uint64_t value; }; static struct ListValue list_values[] = { { gettext_noop ("1 year"), 1000LL * 60 * 60 * 24 * 365 }, { gettext_noop ("1 month"), 1000LL * 60 * 60 * 24 * 30 }, { gettext_noop ("1 day"), 1000LL * 60 * 60 * 24 }, { gettext_noop ("1 hour"), 1000LL * 60 * 60 }, { gettext_noop ("1 minute"), 1000LL * 60 }, { NULL, 0} }; void GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkWidget *ad; GtkBuilder *builder; char *filename; uint32_t anonymity; uint32_t priority; struct GNUNET_TIME_Relative exp; int do_index; GtkComboBox *cb; GtkListStore *ls; GtkTreeIter iter; int i; builder = GNUNET_GTK_get_new_builder ("publish-file-dialog.glade"); if (builder == NULL) { GNUNET_break (0); return; } ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog")); cb = GTK_COMBO_BOX (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog_expiration_combo_box")); ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog_expiration_list_store")); i = 0; while (list_values[i].text != NULL) { gtk_list_store_insert_before (ls, &iter, NULL); gtk_list_store_set (ls, &iter, 0, gettext (list_values[i].text), 1, list_values[i].value, -1); i++; } if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad))) { gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); return; } filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad)); anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog_anonymity_spin_button"))); priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog_priority_spin_button"))); do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_file_dialog_do_index_checkbutton"))); gtk_combo_box_get_active_iter (cb, &iter); gtk_tree_model_get (GTK_TREE_MODEL (ls), &iter, 1, &exp.value, -1); add_file_at_iter (filename, anonymity, priority, GNUNET_TIME_relative_to_absolute (exp), do_index, NULL); gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); g_free (filename); update_selectivity (); } void GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; int do_index; guint anonymity_level; guint priority; char *short_fn; struct GNUNET_FS_FileInformation *fip; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } gtk_tree_model_get (tm, &iter, 1, &do_index, 2, &short_fn, 3, &anonymity_level, 4, &priority, 5, &fip, -1); GNUNET_GTK_edit_publish_dialog (&do_index, &short_fn, &anonymity_level, &priority, fip); gtk_tree_store_set (GTK_TREE_STORE (tm), &iter, 1, do_index, 2, short_fn, 3, anonymity_level, 4, priority, -1); g_free (short_fn); } /** * Free row reference stored in the file information's * client-info pointer. */ static int free_fi_row_reference (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, uint32_t *anonymity, uint32_t *priority, int *do_index, struct GNUNET_TIME_Absolute *expirationTime, void **client_info) { GtkTreeRowReference *row = *client_info; if (row == NULL) { GNUNET_break (0); return GNUNET_OK; } gtk_tree_row_reference_free (row); return GNUNET_OK; } void GNUNET_GTK_master_publish_dialog_delete_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; struct GNUNET_FS_FileInformation *fip; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } gtk_tree_model_get (tm, &iter, 5, &fip, -1); GNUNET_FS_file_information_destroy (fip, &free_fi_row_reference, NULL); gtk_tree_store_remove (GTK_TREE_STORE (tm), &iter); update_selectivity (); } void GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy, gpointer data) { GtkWidget *ad; GtkBuilder *builder; char *filename; uint32_t anonymity; uint32_t priority; struct GNUNET_TIME_Relative exp; int do_index; GtkComboBox *cb; GtkListStore *ls; GtkTreeIter iter; int i; builder = GNUNET_GTK_get_new_builder ("publish-directory-dialog.glade"); if (builder == NULL) { GNUNET_break (0); return; } ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog")); cb = GTK_COMBO_BOX (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog_expiration_combo_box")); ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog_expiration_list_store")); i = 0; while (list_values[i].text != NULL) { gtk_list_store_insert_before (ls, &iter, NULL); gtk_list_store_set (ls, &iter, 0, gettext (list_values[i].text), 1, list_values[i].value, -1); i++; } if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad))) { gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); return; } filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad)); anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog_anonymity_spin_button"))); priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog_priority_spin_button"))); do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton"))); gtk_combo_box_get_active_iter (cb, &iter); gtk_tree_model_get (GTK_TREE_MODEL (ls), &iter, 1, &exp.value, -1); gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); /* FIXME: open progress dialog here... */ add_dir_at_iter (filename, anonymity, priority, GNUNET_TIME_relative_to_absolute (exp), do_index, NULL); g_free (filename); update_selectivity (); } /** * Get the file information struct corresponding to the * given iter in the publish dialog tree model. Recursively * builds the file information struct from the subtree. * * @param tm model to grab fi from * @param iter position to grab fi from * @return file information from the given position (never NULL) */ static struct GNUNET_FS_FileInformation * get_file_information (GtkTreeModel *tm, GtkTreeIter *iter) { struct GNUNET_FS_FileInformation *fi; struct GNUNET_FS_FileInformation *fic; GtkTreeIter child; gtk_tree_model_get (tm, iter, 5, &fi, -1); 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; } struct UpdateableContext { GtkTreeIter parent; GtkTreeStore *ts; const char *namespace_name; struct GNUNET_FS_Namespace *ns; }; 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; GtkTreeIter iter; char *desc; desc = GNUNET_CONTAINER_meta_data_get_by_type (last_meta, EXTRACTOR_METATYPE_DESCRIPTION); 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, next_id, 6, desc, 7, FALSE /* current not editable (only for top-level) */, 8, TRUE /* update editable (always) */, -1); GNUNET_free_non_null (desc); } static void add_namespace_to_ts (void *cls, const char *name, const GNUNET_HashCode *id) { GtkTreeStore *ts = cls; struct UpdateableContext uc; uc.namespace_name = name; uc.ts = ts; uc.ns = GNUNET_FS_namespace_create (GNUNET_GTK_get_fs_handle (), name); gtk_tree_store_insert_with_values (ts, &uc.parent, NULL, G_MAXINT, 0, name, 1, uc.ns, 2, NULL /* last-id */, 3, NULL /* last-uri */, 4, NULL /* meta */, 5, NULL /* next-ID */, 6, NULL /* last-description */, 7, TRUE /* current editable */, 8, TRUE /* update editable */, -1); /* FIXME: maybe we want to build the real tree here? => FS API should be different... */ GNUNET_FS_namespace_list_updateable (uc.ns, &add_updateable_to_ts, &uc); } /** */ void GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy, gpointer data) { GtkWidget *ad; GtkTreeStore *ts; gint ret; GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeIter iter; struct GNUNET_FS_FileInformation *fi; GtkTreeModel *tm; GtkTreeModel *ptm; struct GNUNET_FS_Namespace *namespace; char *namespace_id; char *namespace_uid; GNUNET_assert (master_builder == NULL); master_builder = GNUNET_GTK_get_new_builder ("publish_dialog.glade"); if (master_builder == NULL) return; tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); sel = gtk_tree_view_get_selection (tv); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(selection_changed_cb), NULL); ad = GTK_WIDGET (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog")); ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder, "GNUNET_GTK_pseudonym_tree_store")); GNUNET_FS_namespace_list (GNUNET_GTK_get_fs_handle (), &add_namespace_to_ts, ts); ret = gtk_dialog_run (GTK_DIALOG (ad)); if (ret == GTK_RESPONSE_OK) { tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder, "GNUNET_GTK_file_sharing_publishing_tree_store")); tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder, "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter)) { gtk_tree_model_get (ptm, &iter, 1, &namespace, 2, &namespace_id, 5, &namespace_uid, -1); } else { namespace = NULL; namespace_id = NULL; namespace_uid = NULL; } if (gtk_tree_model_get_iter_first (tm, &iter)) do { fi = get_file_information (tm, &iter); GNUNET_FS_publish_start (GNUNET_GTK_get_fs_handle (), fi, namespace, namespace_id, namespace_uid, GNUNET_FS_PUBLISH_OPTION_NONE); } while (gtk_tree_model_iter_next (tm, &iter)); GNUNET_free_non_null (namespace_uid); GNUNET_free_non_null (namespace_id); } /* FIXME: free state from 'ls' */ /* FIXME: free state from 'tm' */ gtk_widget_destroy (ad); g_object_unref (G_OBJECT (master_builder)); master_builder = NULL; } /* end of main_window_file_publish.c */