/* 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_namespace_manager.c * @author LRN */ #include "gnunet-fs-gtk_common.h" #include "gnunet-fs-gtk.h" #include #include struct GNUNET_GTK_NamespaceManagerContext { GtkBuilder *builder; GtkWidget *known_ns; GtkWidget *ns_order; GtkWidget *ns_details; GtkTreeSelection *known_ns_sel; GtkTreeSelection *ns_order_sel; GtkTreeSelection *ns_details_sel; GtkListStore *ns_order_store; GtkListStore *known_ns_store; GtkListStore *ns_details_store; GtkWindow *namespace_manager; GtkTreeViewColumn *order_rank; GtkTreeViewColumn *order_name; GtkTreeViewColumn *order_id; GtkWidget *details_apply_button; GtkWidget *details_delete_button; int sort_direction; struct GNUNET_CONTAINER_MetaData *uneditable_md; }; /** * THIS IS EVIL! Used to avoid opening more than one ns manager * at once. Could be fixed by saving a pointer to the ns manager window * somewhere in the main gnunet-fs-gtk window, but main window does * not have a context structure for such things at the moment, hence * this VERY EVIL GLOBAL VARIABLE! */ static struct GNUNET_GTK_NamespaceManagerContext *ns_manager = NULL; #define GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN 0 #define GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN 1 #define GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN 2 #define GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN 3 #define GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN 4 #define GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN 5 #define GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN 6 #define GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN 7 #define GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN 0 #define GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN 1 #define GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN 2 #define GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN 3 #define GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN 4 #define GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN 0 #define GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN 1 #define GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN 2 #define GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN 3 #define GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN 4 #define GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN 5 static void sort_order_list (struct GNUNET_GTK_NamespaceManagerContext *ctx, int sort_column) { int sorted = GNUNET_NO; GtkTreeIter iter; gint i; gint row_count; gint *row_indices, *row_ints; gchar **row_strings; ctx->sort_direction = ctx->sort_direction <= 0 ? 1 : 0; row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL ( ctx->ns_order_store), NULL); if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL ( ctx->ns_order_store), &iter)) return; row_indices = g_new0 (gint, row_count); row_ints = g_new0 (gint, row_count); row_strings = g_new0 (gchar *, row_count); for (i = 0; i < row_count; i++) { int an_int; char *a_string; row_indices[i] = i; switch (sort_column) { case GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN: gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter, sort_column, &an_int, -1); row_ints[i] = an_int; row_strings[i] = NULL; break; case GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN: case GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN: gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter, sort_column, &a_string, -1); row_strings[i] = a_string; break; default: row_strings[i] = NULL; break; } if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL ( ctx->ns_order_store), &iter)) break; } while (sorted != GNUNET_YES) { sorted = GNUNET_YES; for (i = 0; i < row_count - 1; i++) { int cmp_result; switch (sort_column) { case GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN: cmp_result = row_ints[i] <= row_ints[i + 1] ? 0 : 1; break; case GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN: case GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN: /* FIXME: name can be UTF-8-encoded, use UTF-8-aware comparison func */ cmp_result = strcmp (row_strings[i], row_strings[i + 1]); break; default: break; } if (((ctx->sort_direction <= 0) && (cmp_result <= 0)) || ((ctx->sort_direction > 0) && (cmp_result > 0))) { int tmp_int, tmp_index; char *tmp_string; tmp_index = row_indices[i]; tmp_int = row_ints[i]; tmp_string = row_strings[i]; row_indices[i] = row_indices[i + 1]; row_ints[i] = row_ints[i + 1]; row_strings[i] = row_strings[i + 1]; row_ints[i + 1] = tmp_int; row_strings[i + 1] = tmp_string; row_indices[i + 1] = tmp_index; sorted = GNUNET_NO; } } } gtk_list_store_reorder (ctx->ns_order_store, row_indices); g_free (row_indices); for (i = 0; i < row_count; i++) g_free (row_strings[i]); g_free (row_strings); g_free (row_ints); } void GNUNET_GTK_namespace_manager_namespace_order_column_clicked_cb ( GtkTreeViewColumn *treeviewcolumn, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; if (treeviewcolumn == ctx->order_rank) { sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN); } else if (treeviewcolumn == ctx->order_name) { sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN); } else if (treeviewcolumn == ctx->order_id) { sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN); } } void GNUNET_GTK_namespace_manager_known_namespaces_delete_button_clicked_cb ( GtkButton *button, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter; GNUNET_HashCode *nsid; GtkTreeRowReference *order_row, *known_row; struct GNUNET_CONTAINER_MetaData *md; if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &iter)) return; gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md, -1); GNUNET_CONTAINER_meta_data_destroy (md); gtk_list_store_remove (ctx->known_ns_store, &iter); if (order_row != NULL) { if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &iter)) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1); gtk_list_store_remove (ctx->ns_order_store, &iter); if (known_row != NULL) gtk_tree_row_reference_free (known_row); } gtk_tree_row_reference_free (order_row); } GNUNET_free (nsid); gtk_list_store_clear (ctx->ns_details_store); GNUNET_CONTAINER_meta_data_destroy (ctx->uneditable_md); ctx->uneditable_md = NULL; } void GNUNET_GTK_namespace_manager_known_namespaces_swap_rank_button_clicked_cb ( GtkButton *button, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter known_iter, order_iter; GNUNET_HashCode *nsid; int32_t old_rank, new_rank; GtkTreeRowReference *order_row, *known_row; if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &known_iter)) return; gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid, GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, &old_rank, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row, -1); if (old_rank == 0) new_rank = -1; else new_rank = -old_rank; gtk_list_store_set (ctx->known_ns_store, &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, new_rank, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, NULL, -1); if (order_row != NULL) { if (new_rank < 0) { if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter)) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1); gtk_list_store_remove (ctx->ns_order_store, &order_iter); if (known_row != NULL) gtk_tree_row_reference_free (known_row); } } gtk_tree_row_reference_free (order_row); } if (new_rank >= 0) { char *name, *identifier; if (order_row != NULL) { /* This should not happen */ GNUNET_break (0); } gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, &name, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN, &identifier, -1); known_row = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL ( ctx->known_ns_store), &known_iter); gtk_list_store_insert_with_values (ctx->ns_order_store, &order_iter, G_MAXINT, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, new_rank, GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, name, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN, identifier, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN, nsid, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, known_row, -1); g_free (name); g_free (identifier); order_row = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter); gtk_list_store_set (ctx->known_ns_store, &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, order_row, -1); } } void GNUNET_GTK_namespace_manager_namespace_order_apply_clicked_cb ( GtkButton *button, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter; gint i; gint row_count; GtkTreeRowReference *known_row; row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL ( ctx->ns_order_store), NULL); if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL ( ctx->ns_order_store), &iter)) return; for (i = 0; i < row_count; i++) { gtk_list_store_set (ctx->ns_order_store, &iter, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, i, -1); gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1); if (known_row == NULL) { /* This is not supposed to happen. What to do? */ GNUNET_break (0); } else { GtkTreeIter known_iter; if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (known_row, &known_iter)) { gtk_list_store_set (ctx->known_ns_store, &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, i, -1); } } if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL ( ctx->ns_order_store), &iter)) break; } } void GNUNET_GTK_namespace_manager_namespace_details_add_button_clicked_cb ( GtkButton *button, gpointer user_data) { /* FIXME: add a row to the details list. Disabled at the moment, since * metadata type selection is not implemented. */ } void GNUNET_GTK_namespace_manager_namespace_details_delete_button_clicked_cb ( GtkButton *button, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter; if (FALSE == gtk_tree_selection_get_selected (ctx->ns_details_sel, NULL, &iter)) return; gtk_list_store_remove (ctx->ns_details_store, &iter); gtk_widget_set_sensitive (ctx->details_apply_button, TRUE); } void GNUNET_GTK_namespace_manager_namespace_details_apply_button_clicked_cb ( GtkButton *button, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter, known_iter; gint i; gint row_count; struct GNUNET_CONTAINER_MetaData *md, *old_md; char *plugin_name; int type; char *type_name; int format; char *data_mime_type; char *data; row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL ( ctx->ns_details_store), NULL); if ((row_count > 0) && (TRUE != gtk_tree_model_get_iter_first ( GTK_TREE_MODEL (ctx->ns_details_store), &iter))) { /* This should not happen */ return; } if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &known_iter)) { /* This should not happen */ return; } md = GNUNET_CONTAINER_meta_data_create (); for (i = 0; i < row_count; i++) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_details_store), &iter, GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN, &plugin_name, GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN, &type, GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, &type_name, GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN, &format, GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN, &data_mime_type, GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, &data, -1); GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, data_mime_type, data, strlen (data) + 1); g_free (plugin_name); g_free (type_name); g_free (data_mime_type); g_free (data); if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL ( ctx->ns_details_store), &iter)) break; } GNUNET_CONTAINER_meta_data_merge (md, (const struct GNUNET_CONTAINER_MetaData *) ctx->uneditable_md); gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &old_md, -1); GNUNET_CONTAINER_meta_data_destroy (old_md); gtk_list_store_set (ctx->known_ns_store, &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, md, -1); gtk_widget_set_sensitive (ctx->details_apply_button, FALSE); } void GNUNET_GTK_namespace_manager_name_text_editing_started_cb ( GtkCellRenderer *renderer, GtkCellEditable *editable, gchar *path, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; if (GTK_IS_ENTRY (editable)) { GtkTreePath *tree_path; GtkTreeIter iter; char *non_unique_name = NULL; GtkEntry *entry = GTK_ENTRY (editable); tree_path = gtk_tree_path_new_from_string (path); if (tree_path != NULL) { if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->known_ns_store), &iter, tree_path)) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, &non_unique_name, -1); } gtk_tree_path_free (tree_path); } if (non_unique_name == NULL) { gtk_cell_editable_editing_done (editable); return; } gtk_entry_set_text (entry, non_unique_name); g_free (non_unique_name); } } void GNUNET_GTK_namespace_manager_name_text_edited_cb ( GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; char *unique_name; GtkTreeRowReference *order_row; if (strlen (new_text) == 0) return; GtkTreePath *tree_path; GtkTreeIter iter; tree_path = gtk_tree_path_new_from_string (path); if (tree_path != NULL) { if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->known_ns_store), &iter, tree_path)) { GNUNET_HashCode *nsid; gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row, -1); unique_name = GNUNET_PSEUDONYM_name_uniquify ( GNUNET_FS_GTK_get_configuration (), nsid, new_text, NULL); gtk_list_store_set (ctx->known_ns_store, &iter, GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, new_text, GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, unique_name, -1); if (order_row != NULL) { GtkTreeIter order_iter; if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter)) { gtk_list_store_set (ctx->ns_order_store, &order_iter, GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, unique_name, -1); } } GNUNET_free (unique_name); } gtk_tree_path_free (tree_path); } } void GNUNET_GTK_namespace_manager_namespace_details_type_text_edited_cb ( GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { /* Changing metadata type is more difficult than simply entering a * new string, see publication editing dialog. So this is disabled * for now. In fact, it's not going to be a Text renderer when it's done. */ /* struct GNUNET_GTK_NamespaceManagerContext *ctx = cls; GtkTreeIter iter; if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->ns_details_store), &iter, path)) { gtk_list_store_set (ctx->ns_details_store, &iter, GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, new_text, -1); } */ } void GNUNET_GTK_namespace_manager_namespace_details_value_text_edited_cb ( GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreePath *tree_path; GtkTreeIter iter; tree_path = gtk_tree_path_new_from_string (path); if (tree_path != NULL) { if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->ns_details_store), &iter, tree_path)) { char *old_text; gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_details_store), &iter, GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, &old_text, -1); if (strcmp (old_text, new_text) != 0) { gtk_list_store_set (ctx->ns_details_store, &iter, GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, new_text, -1); gtk_widget_set_sensitive (ctx->details_apply_button, TRUE); } g_free (old_text); } gtk_tree_path_free (tree_path); } } /** * Iterator over all known pseudonyms. * Populate "known ns" and "ns order" lists. * * @param cls closure * @param pseudonym hash code of public key of pseudonym * @param md meta data known about the pseudonym * @param rating the local rating of the pseudonym * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort */ static int populate_known_ns_list (void *cls, const GNUNET_HashCode *pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { struct GNUNET_GTK_NamespaceManagerContext *ctx = cls; GNUNET_HashCode *nsid; struct GNUNET_CRYPTO_HashAsciiEncoded identifier; GtkTreeIter known_iter, order_iter; struct GNUNET_CONTAINER_MetaData *md_copy; char *non_null_name, *non_null_unique_name; nsid = GNUNET_malloc (sizeof (GNUNET_HashCode)); *nsid = *pseudonym; GNUNET_CRYPTO_hash_to_enc (nsid, &identifier); GNUNET_PSEUDONYM_get_info (GNUNET_FS_GTK_get_configuration (), nsid, NULL, NULL, &non_null_name, NULL); non_null_unique_name = GNUNET_PSEUDONYM_name_uniquify ( GNUNET_FS_GTK_get_configuration (), nsid, non_null_name, NULL); md_copy = GNUNET_CONTAINER_meta_data_duplicate (md); gtk_list_store_insert_with_values (ctx->known_ns_store, &known_iter, G_MAXINT, GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN, FALSE, GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, rating, GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, non_null_unique_name, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN, identifier.encoding, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, nsid, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, NULL, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, md_copy, GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, non_null_name, -1); if (rating >= 0) { GtkTreeRowReference *rr = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL ( ctx->known_ns_store), &known_iter); gtk_list_store_insert_with_values (ctx->ns_order_store, &order_iter, G_MAXINT, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, rating, GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, non_null_unique_name, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN, identifier.encoding, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN, nsid, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, rr, -1); rr = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter); gtk_list_store_set (ctx->known_ns_store, &known_iter, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, rr, -1); } GNUNET_free (non_null_name); GNUNET_free (non_null_unique_name); return GNUNET_OK; } static void apply_known_ns_changes (struct GNUNET_GTK_NamespaceManagerContext *ctx) { GtkTreeIter iter; gint i; gint row_count; GNUNET_HashCode *nsid; char *name; int32_t rank; struct GNUNET_CONTAINER_MetaData *md; row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL ( ctx->known_ns_store), NULL); if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL ( ctx->known_ns_store), &iter)) return; for (i = 0; i < row_count; i++) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid, GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, &name, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md, GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, &rank, -1); GNUNET_PSEUDONYM_set_info (GNUNET_FS_GTK_get_configuration (), nsid, name, md, rank); g_free (name); if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL ( ctx->known_ns_store), &iter)) break; } } static void free_lists_contents (struct GNUNET_GTK_NamespaceManagerContext *ctx) { GtkTreeIter iter; gint i; gint row_count; GNUNET_HashCode *nsid; GtkTreeRowReference *order_row; struct GNUNET_CONTAINER_MetaData *md; row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL ( ctx->known_ns_store), NULL); if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL ( ctx->known_ns_store), &iter)) return; for (i = 0; i < row_count; i++) { gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid, GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md, -1); if (order_row != NULL) { GtkTreeIter order_iter; if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter)) { GtkTreeRowReference *known_row; gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter, GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1); if (known_row != NULL) gtk_tree_row_reference_free (known_row); } gtk_tree_row_reference_free (order_row); } GNUNET_CONTAINER_meta_data_destroy (md); GNUNET_free (nsid); if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL ( ctx->known_ns_store), &iter)) break; } gtk_list_store_clear (ctx->ns_order_store); gtk_list_store_clear (ctx->known_ns_store); gtk_list_store_clear (ctx->ns_details_store); if (ctx->uneditable_md != NULL) GNUNET_CONTAINER_meta_data_destroy (ctx->uneditable_md); } void GNUNET_GTK_namespace_manager_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; switch (response_id) { case GTK_RESPONSE_APPLY: case GTK_RESPONSE_OK: apply_known_ns_changes (ctx); break; default: break; } switch (response_id) { case GTK_RESPONSE_APPLY: break; case GTK_RESPONSE_OK: case GTK_RESPONSE_CANCEL: default: free_lists_contents (ctx); gtk_widget_destroy (GTK_WIDGET (ctx->namespace_manager)); GNUNET_free (ctx); ns_manager = NULL; } } static gboolean mark_as_mine (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { const GNUNET_HashCode *mine_id = data; const GNUNET_HashCode *ns_id; gtk_tree_model_get (model, iter, GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &ns_id, -1); if (memcmp (ns_id, mine_id, sizeof (GNUNET_HashCode)) != 0) return FALSE; gtk_list_store_set (GTK_LIST_STORE (model), iter, GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN, TRUE, -1); return TRUE; } /** * Callback with information about local (!) namespaces. * Contains the names of the local namespace and the global * ID. * * @param cls closure * @param name human-readable identifier of the namespace * @param id hash identifier for the namespace */ static void mark_namespaces_as_mine (void *cls, const char *name, const GNUNET_HashCode * id) { struct GNUNET_GTK_NamespaceManagerContext *ctx = cls; gtk_tree_model_foreach (GTK_TREE_MODEL (ctx->known_ns_store), mark_as_mine, (gpointer) id); } /** * Type of a function that libextractor calls for each * meta data item found. * * @param cls closure (user-defined) * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in data * @return 0 to continue extracting, 1 to abort */ static int populate_details_list (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GNUNET_GTK_NamespaceManagerContext *ctx = cls; const char *type_name; char *data_utf8; if (format == EXTRACTOR_METAFORMAT_UTF8 || format == EXTRACTOR_METAFORMAT_C_STRING) { type_name = EXTRACTOR_metatype_to_string (type); /* TODO: translate type_name using dgettext? */ data_utf8 = GNUNET_FS_GTK_dubious_meta_to_utf8 (format, data, data_len); if (data != NULL) { gtk_list_store_insert_with_values (ctx->ns_details_store, NULL, G_MAXINT, GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN, plugin_name, GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN, type, GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, type_name, GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN, EXTRACTOR_METAFORMAT_UTF8, GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN, data_mime_type, GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, data_utf8, -1); GNUNET_free (data_utf8); return 0; } } GNUNET_CONTAINER_meta_data_insert (ctx->uneditable_md, plugin_name, type, format, data_mime_type, data, data_len); return 0; } static void ns_details_selection_changed (GtkTreeSelection *treeselection, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter; if (FALSE == gtk_tree_selection_get_selected (ctx->ns_details_sel, NULL, &iter)) { gtk_widget_set_sensitive (ctx->details_delete_button, FALSE); return; } gtk_widget_set_sensitive (ctx->details_delete_button, TRUE); } static void known_ns_selection_changed (GtkTreeSelection *treeselection, gpointer user_data) { struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data; GtkTreeIter iter; const struct GNUNET_CONTAINER_MetaData *md; if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &iter)) return; gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter, GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md, -1); if (ctx->uneditable_md != NULL) GNUNET_CONTAINER_meta_data_clear (ctx->uneditable_md); else ctx->uneditable_md = GNUNET_CONTAINER_meta_data_create (); gtk_list_store_clear (ctx->ns_details_store); gtk_widget_set_sensitive (ctx->details_apply_button, FALSE); GNUNET_CONTAINER_meta_data_iterate ((const struct GNUNET_CONTAINER_MetaData *) md, populate_details_list, ctx); gtk_widget_set_sensitive (ctx->details_apply_button, FALSE); } void GNUNET_GTK_namespace_manager_open () { struct GNUNET_GTK_NamespaceManagerContext *ctx; if (ns_manager != NULL) return; ctx = GNUNET_malloc (sizeof (struct GNUNET_GTK_NamespaceManagerContext)); ctx->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_namespace_manager.glade", ctx); if (ctx->builder == NULL) { GNUNET_break (0); GNUNET_free (ctx); return; } /* initialize widget references */ ctx->known_ns = GTK_WIDGET (gtk_builder_get_object (ctx->builder, "GNUNET_GTK_namespace_manager_known_treeview")); ctx->ns_order = GTK_WIDGET (gtk_builder_get_object (ctx->builder, "GNUNET_GTK_namespace_manager_namespace_order_treeview")); ctx->ns_details = GTK_WIDGET (gtk_builder_get_object (ctx->builder, "GNUNET_GTK_namespace_manager_namespace_details_treeview")); ctx->known_ns_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW ( ctx->known_ns)); ctx->ns_order_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW ( ctx->ns_order)); ctx->ns_details_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW ( ctx->ns_details)); ctx->ns_order_store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (ctx->ns_order))); ctx->known_ns_store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (ctx->known_ns))); ctx->ns_details_store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (ctx->ns_details))); ctx->namespace_manager = GTK_WINDOW (gtk_builder_get_object ( ctx->builder, "GNUNET_GTK_namespace_manager_dialog")); ctx->details_apply_button = GTK_WIDGET (gtk_builder_get_object (ctx->builder, "GNUNET_GTK_namespace_manager_namespace_details_apply_button")); ctx->details_delete_button = GTK_WIDGET (gtk_builder_get_object (ctx->builder, "GNUNET_GTK_namespace_manager_namespace_details_delete_button")); ctx->order_rank = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 0); ctx->order_name = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 1); ctx->order_id = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 2); /* connect signals; FIXME-GTK3: these could be connected with (modern) Glade */ g_signal_connect (G_OBJECT (ctx->known_ns_sel), "changed", G_CALLBACK (known_ns_selection_changed), ctx); g_signal_connect (G_OBJECT (ctx->ns_details_sel), "changed", G_CALLBACK (ns_details_selection_changed), ctx); /* populate namespace model */ (void) GNUNET_PSEUDONYM_list_all (GNUNET_FS_GTK_get_configuration (), populate_known_ns_list, ctx); /* mark our own namespaces as such */ GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (), mark_namespaces_as_mine, ctx); /* sort namespace order list by rank (initially) */ sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN); ns_manager = ctx; gtk_widget_set_sensitive (ctx->details_apply_button, FALSE); /* show dialog */ gtk_window_present (GTK_WINDOW (ctx->namespace_manager)); } /* end of gnunet-fs-gtk_namespace_manager.c */