/* This file is part of GNUnet. (C) 2005, 2006, 2007 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/plugins/fs/namespace.c * @brief operations for deleting and adding to/updating namespaces * @author Christian Grothoff */ #include "platform.h" #include "gnunetgtk_common.h" #include "fs.h" #include "helper.h" #include "meta.h" #include "namespace.h" #include "namespace_search.h" #include "content_tracking.h" #include #include #include #include #include /** * @brief linked list of pages in the namespace notebook */ typedef struct NL { struct NL *next; GtkWidget *treeview; GtkWidget *namespacepage; GtkWidget *addButton; GtkWidget *updateButton; GtkTreeModel *model; char *name; GNUNET_HashCode id; struct GNUNET_MetaData *meta; } NamespaceList; /** * Content selection in main list of available content. */ static GtkTreeSelection *content_selection; static NamespaceList *head; static GladeXML *metaXML; /** * The user has changed the selection either in the * namespace content list or the global content list. * Update search button status values (add/change). */ static void on_namespaceContentSelectionChanged (gpointer signal, gpointer cls) { NamespaceList *list = head; int count; int ncount; GtkTreeSelection *ns; GtkTreeIter iter; char *next; int ok; count = gtk_tree_selection_count_selected_rows (content_selection); while (list != NULL) { ns = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->treeview)); ncount = gtk_tree_selection_count_selected_rows (ns); gtk_widget_set_sensitive (list->addButton, count > 0); /* now check if update is legal */ ok = 0; if ((count == 1) && (ncount == 1) && (TRUE == gtk_tree_selection_get_selected (ns, NULL, &iter))) { next = NULL; gtk_tree_model_get (list->model, &iter, IN_NAMESPACE_NEXT_STRING, &next, -1); if ((next != NULL) && (0 != strlen (next))) ok = 1; GNUNET_free_non_null (next); } gtk_widget_set_sensitive (list->updateButton, ok); list = list->next; } } static void makeNamespaceFrame (NamespaceList * entry) { GtkWidget *child; GtkWidget *resultList; GtkCellRenderer *renderer; GtkListStore *model; GladeXML *namespaceXML; GtkTreeViewColumn *column; int col; GNUNET_GTK_DEBUG_BEGIN (); namespaceXML = glade_xml_new (GNUNET_GTK_get_glade_filename (), "namespaceContentFrame", PACKAGE_NAME); GNUNET_GTK_connect_glade_with_plugins (namespaceXML); child = GNUNET_GTK_extract_main_widget_from_window (namespaceXML, "namespaceContentFrame"); resultList = glade_xml_get_widget (namespaceXML, "namespaceContentFrameTreeView"); entry->addButton = glade_xml_get_widget (namespaceXML, "addButton"); entry->updateButton = glade_xml_get_widget (namespaceXML, "namespaceUpdateButton"); entry->treeview = GTK_WIDGET (GTK_TREE_VIEW (resultList)); model = gtk_list_store_new (IN_NAMESPACE_NUM, G_TYPE_STRING, /* (file)name */ G_TYPE_UINT64, /* size */ G_TYPE_STRING, /* human-readable size */ G_TYPE_STRING, /* description */ G_TYPE_STRING, /* mime-type */ G_TYPE_STRING, /* last-ID */ G_TYPE_STRING, /* next-ID */ G_TYPE_POINTER, /* URI */ G_TYPE_POINTER); /* META */ entry->model = GTK_TREE_MODEL (model); gtk_tree_view_set_model (GTK_TREE_VIEW (resultList), GTK_TREE_MODEL (model)); gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (resultList)), GTK_SELECTION_SINGLE); g_signal_connect_data (gtk_tree_view_get_selection (GTK_TREE_VIEW (resultList)), "changed", G_CALLBACK (&on_namespaceContentSelectionChanged), NULL, NULL, 0); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Filename"), renderer, "text", IN_NAMESPACE_FILENAME, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, IN_NAMESPACE_FILENAME); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "xalign", 1.00, NULL); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Filesize"), renderer, "text", IN_NAMESPACE_HSIZE, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, IN_NAMESPACE_SIZE); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Description"), renderer, "text", IN_NAMESPACE_DESCRIPTION, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, IN_NAMESPACE_DESCRIPTION); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Mime-type"), renderer, "text", IN_NAMESPACE_MIMETYPE, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, IN_NAMESPACE_MIMETYPE); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Identifier"), renderer, "text", IN_NAMESPACE_LAST_STRING, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (resultList), -1, _("Next Identifier"), renderer, "text", IN_NAMESPACE_NEXT_STRING, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (resultList), col - 1), TRUE); UNREF (namespaceXML); GNUNET_GTK_DEBUG_END (); entry->namespacepage = child; } /** * Update the model that lists the content of a namespace: * add this content. * * @param uri URI of the last content published * @param lastId the ID of the last publication * @param nextId the ID of the next update * @param publicationFrequency how often are updates scheduled? * @param nextPublicationTime the scheduled time for the * next update (0 for sporadic updates) * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort */ static int addNamespaceContentToModel (void *cls, const GNUNET_ECRS_FileInfo * fi, const char *lastId, const char *nextId) { GtkListStore *model = GTK_LIST_STORE (cls); GtkTreeIter iter; char *filename; char *desc; char *mime; char *uriString; unsigned long long size; char *size_h; GNUNET_GTK_DEBUG_BEGIN (); filename = GNUNET_meta_data_get_first_by_types (fi->meta, EXTRACTOR_FILENAME, EXTRACTOR_TITLE, EXTRACTOR_ARTIST, EXTRACTOR_AUTHOR, EXTRACTOR_PUBLISHER, EXTRACTOR_CREATOR, EXTRACTOR_PRODUCER, EXTRACTOR_UNKNOWN, -1); if (filename == NULL) filename = GNUNET_strdup (_("no name given")); else { char *dotdot; while (NULL != (dotdot = strstr (filename, ".."))) dotdot[0] = dotdot[1] = '_'; } desc = GNUNET_meta_data_get_first_by_types (fi->meta, EXTRACTOR_DESCRIPTION, EXTRACTOR_GENRE, EXTRACTOR_ALBUM, EXTRACTOR_COMMENT, EXTRACTOR_SUBJECT, EXTRACTOR_FORMAT, EXTRACTOR_SIZE, EXTRACTOR_KEYWORDS, -1); if (desc == NULL) desc = GNUNET_strdup (""); mime = GNUNET_meta_data_get_by_type (fi->meta, EXTRACTOR_MIMETYPE); if (mime == NULL) mime = GNUNET_strdup (_("unknown")); if (GNUNET_ECRS_uri_test_chk (fi->uri)) size = GNUNET_ECRS_uri_get_file_size (fi->uri); else size = 0; uriString = GNUNET_ECRS_uri_to_string (fi->uri); if (nextId == NULL) nextId = ""; size_h = GNUNET_get_byte_size_as_fancy_string (size); gtk_list_store_append (model, &iter); gtk_list_store_set (model, &iter, IN_NAMESPACE_FILENAME, filename, IN_NAMESPACE_SIZE, size, IN_NAMESPACE_HSIZE, size_h, IN_NAMESPACE_DESCRIPTION, desc, IN_NAMESPACE_MIMETYPE, mime, IN_NAMESPACE_LAST_STRING, lastId, IN_NAMESPACE_NEXT_STRING, nextId, IN_NAMESPACE_URI, GNUNET_ECRS_uri_duplicate (fi->uri), IN_NAMESPACE_META, GNUNET_meta_data_duplicate (fi->meta), -1); GNUNET_free (size_h); GNUNET_free (filename); GNUNET_free (uriString); GNUNET_free (mime); GNUNET_free (desc); GNUNET_GTK_DEBUG_END (); return GNUNET_OK; } /** * Add a tab for the given namespace. */ int addTabForNamespace (void *unused, const GNUNET_HashCode * namespaceId, const struct GNUNET_MetaData *md, int rating) { NamespaceList *list; GtkWidget *label; GtkWidget *notebook; GtkWidget *del_menu; char *namespaceName; if (GNUNET_OK != GNUNET_ECRS_namespace_test_exists (NULL, cfg, namespaceId)) return GNUNET_OK; GNUNET_GTK_DEBUG_BEGIN (); namespaceName = GNUNET_pseudonym_id_to_name (ectx, cfg, namespaceId); label = gtk_label_new (namespaceName); list = GNUNET_malloc (sizeof (NamespaceList)); list->name = GNUNET_strdup (namespaceName); list->id = *namespaceId; list->meta = GNUNET_meta_data_duplicate (md); makeNamespaceFrame (list); list->next = head; head = list; /* update sensitivity of add button */ on_namespaceContentSelectionChanged (NULL, NULL); notebook = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "localNamespacesNotebook"); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), list->namespacepage, label); gtk_widget_show (notebook); GNUNET_NS_namespace_list_contents (ectx, cfg, namespaceId, &addNamespaceContentToModel, list->model); GNUNET_GTK_DEBUG_END (); /* enable "delete" menu entry */ del_menu = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "namespaceDelete"); gtk_widget_set_sensitive (del_menu, TRUE); GNUNET_free (namespaceName); return GNUNET_OK; } static void frame_destroy (GtkWidget * tree) { GtkTreeIter iter; struct GNUNET_ECRS_URI *u; struct GNUNET_MetaData *m; NamespaceList *prev; NamespaceList *pos; NamespaceList *next; GtkWidget *del_menu; pos = head; prev = NULL; while (pos != NULL) { next = pos->next; if (pos->treeview == tree) break; prev = pos; pos = next; } if (pos == NULL) { GNUNET_GE_BREAK (NULL, 0); return; } if (prev == NULL) head = pos->next; else prev->next = pos->next; GNUNET_free (pos->name); GNUNET_meta_data_destroy (pos->meta); if (gtk_tree_model_get_iter_first (pos->model, &iter)) { do { gtk_tree_model_get (pos->model, &iter, IN_NAMESPACE_URI, &u, IN_NAMESPACE_META, &m, -1); gtk_list_store_set (GTK_LIST_STORE (pos->model), &iter, IN_NAMESPACE_URI, NULL, IN_NAMESPACE_META, NULL, -1); if (u != NULL) GNUNET_ECRS_uri_destroy (u); if (m != NULL) GNUNET_meta_data_destroy (m); } while (gtk_tree_model_iter_next (pos->model, &iter)); } GNUNET_free (pos); del_menu = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "namespaceDelete"); gtk_widget_set_sensitive (del_menu, head != NULL); } void namespaceDelete_clicked_fs (GtkWidget * dummy1, GtkWidget * dummy2) { GtkWidget *notebook; NamespaceList *list; NamespaceList *prev; gint num; GtkWidget *page; GtkWidget *dialog; gint ret; GNUNET_GTK_DEBUG_BEGIN (); notebook = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "localNamespacesNotebook"); num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)); if (num == -1) { /* IMPROVE-ME: disable the menu item as long as this may happen! */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("No local namespaces available that could be deleted!")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return; } page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), num); list = head; prev = NULL; while ((list != NULL) && (list->namespacepage != page)) { prev = list; list = list->next; } if (list == NULL) { GNUNET_GE_BREAK (ectx, 0); return; } /* open window to ask for confirmation, only then delete */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_YES_NO, _("Should the namespace `%s' really be deleted?"), list->name); ret = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); if (GTK_RESPONSE_YES != ret) return; gtk_notebook_remove_page (GTK_NOTEBOOK (notebook), num); GNUNET_NS_namespace_delete (ectx, cfg, &list->id); frame_destroy (list->treeview); GNUNET_GTK_DEBUG_END (); } typedef struct { unsigned int anonymityLevel; char *namespaceName; GNUNET_HashCode nsid; const char *thisId; const char *nextId; } IUC; /** * Publish the selected file in the * selected namespace. */ static void addToNamespaceCB (GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data) { IUC *cls = data; struct GNUNET_ECRS_URI *resultURI; struct GNUNET_ECRS_URI *dst; struct GNUNET_MetaData *meta; NamespaceList *list; GNUNET_ECRS_FileInfo fi; GNUNET_GTK_DEBUG_BEGIN (); dst = NULL; gtk_tree_model_get (model, iter, NAMESPACE_URI, &dst, NAMESPACE_META, &meta, -1); if (dst == NULL) { GNUNET_GE_BREAK (ectx, 0); return; } resultURI = GNUNET_NS_add_to_namespace (ectx, cfg, cls->anonymityLevel, 1000, /* FIXME: priority */ GNUNET_get_time () + 2 * GNUNET_CRON_YEARS, /* FIXME: expiration */ &cls->nsid, cls->thisId, cls->nextId, dst, meta); if (resultURI != NULL) { list = head; while ((list != NULL) && (0 != strcmp (cls->namespaceName, list->name))) list = list->next; if (list == NULL) { GNUNET_GE_BREAK (ectx, 0); } else { /* update namespace content list! */ fi.uri = dst; fi.meta = meta; addNamespaceContentToModel (list->model, &fi, cls->thisId, cls->nextId); } GNUNET_ECRS_uri_destroy (resultURI); } else { GNUNET_GTK_show_info_message (_ ("Failed to insert content into namespace " "(consult logs).\n")); } GNUNET_GTK_DEBUG_END (); } void on_namespaceInsertMetaDataDialogMetaDataAddButton_clicked_fs (GtkWidget * dummy1, GtkWidget * dummy2) { handleMetaDataListUpdate (metaXML, "namespaceInsertMetaTypeComboBox", "metaDataValueEntry", "metaDataTreeView"); } /** * User clicked the "add" button, add content from * available content list to the currently selected * namespace. */ void on_namespaceInsertButton_clicked_fs (GtkWidget * dummy1, GtkWidget * dummy2) { NamespaceList *list; GtkWidget *nameLine; GtkWidget *page; GtkWidget *notebook; GtkWidget *dialog; IUC cls; gint num; notebook = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "localNamespacesNotebook"); num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)); GNUNET_GE_ASSERT (ectx, num != -1); page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), num); list = head; while ((list != NULL) && (list->namespacepage != page)) list = list->next; if (list == NULL) { GNUNET_GE_BREAK (ectx, 0); return; } cls.namespaceName = list->name; cls.nsid = list->id; metaXML = glade_xml_new (GNUNET_GTK_get_glade_filename (), "namespaceInsertDialog", PACKAGE_NAME); GNUNET_GTK_connect_glade_with_plugins (metaXML); dialog = glade_xml_get_widget (metaXML, "namespaceInsertDialog"); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { cls.anonymityLevel = getSpinButtonValue (metaXML, "anonymitySpinButton"); nameLine = glade_xml_get_widget (metaXML, "namespaceContentIdentifierEntry"); cls.thisId = gtk_entry_get_text (GTK_ENTRY (nameLine)); nameLine = glade_xml_get_widget (metaXML, "nextIdentifierEntry"); cls.nextId = gtk_entry_get_text (GTK_ENTRY (nameLine)); GNUNET_GTK_tree_selection_selected_foreach (content_selection, &addToNamespaceCB, &cls); } gtk_widget_destroy (dialog); UNREF (metaXML); metaXML = NULL; } /** * User clicked on update; launch update dialog * and perform namespace content update. */ void on_namespaceUpdateButton_clicked_fs (GtkWidget * dummy1, GtkWidget * dummy2) { NamespaceList *list; GtkTreeIter iter; GtkTreeSelection *selection; IUC cls; char *next; GtkWidget *nextEntryLine; GtkWidget *identifierLabel; GtkWidget *dialog; GtkWidget *notebook; GtkWidget *page; gint num; GNUNET_GTK_DEBUG_BEGIN (); /* find out which namespace this is about */ notebook = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "localNamespacesNotebook"); num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)); GNUNET_GE_ASSERT (ectx, num != -1); page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), num); list = head; while ((list != NULL) && (list->namespacepage != page)) list = list->next; if (list == NULL) { GNUNET_GE_BREAK (ectx, 0); return; } cls.namespaceName = list->name; cls.nsid = list->id; /* find out what we are updating */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->treeview)); if (TRUE != gtk_tree_selection_get_selected (selection, NULL, &iter)) { GNUNET_GE_BREAK (ectx, 0); return; } gtk_tree_model_get (list->model, &iter, IN_NAMESPACE_NEXT_STRING, &next, -1); if (next == NULL) { GNUNET_GE_BREAK (NULL, 0); return; } /* create update dialog */ metaXML = glade_xml_new (GNUNET_GTK_get_glade_filename (), "namespaceUpdateDialog", PACKAGE_NAME); GNUNET_GTK_connect_glade_with_plugins (metaXML); dialog = glade_xml_get_widget (metaXML, "namespaceUpdateDialog"); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); identifierLabel = glade_xml_get_widget (metaXML, "identifierLabel"); gtk_label_set_text (GTK_LABEL (identifierLabel), next); cls.thisId = next; nextEntryLine = glade_xml_get_widget (metaXML, "nextIdentifierEntry"); /* run update dialog */ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) goto CLEANUP; gtk_widget_hide (dialog); /* get data from update dialog */ cls.nextId = gtk_entry_get_text (GTK_ENTRY (nextEntryLine)); if (cls.nextId == NULL) cls.nextId = ""; cls.anonymityLevel = getSpinButtonValue (metaXML, "namespaceUpdateAnonymitySpinButton"); /* run actual update */ GNUNET_GTK_tree_selection_selected_foreach (content_selection, &addToNamespaceCB, &cls); CLEANUP: gtk_widget_destroy (dialog); UNREF (metaXML); metaXML = NULL; free (next); GNUNET_GTK_DEBUG_END (); } void fs_namespace_start () { GtkWidget *contentList; GtkListStore *model; GtkCellRenderer *renderer; GtkWidget *trackCheckButton; GtkTreeViewColumn *column; int col; GNUNET_GTK_DEBUG_BEGIN (); trackCheckButton = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "trackingCheckButton"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (trackCheckButton), GNUNET_URITRACK_get_tracking_status (ectx, cfg) == GNUNET_YES ? TRUE : FALSE); contentList = glade_xml_get_widget (GNUNET_GTK_get_main_glade_XML (), "availableContentList"); model = gtk_list_store_new (NAMESPACE_NUM, G_TYPE_STRING, /* name */ G_TYPE_UINT64, /* size */ G_TYPE_STRING, /* human-readable size */ G_TYPE_STRING, /* uri-string */ G_TYPE_POINTER, G_TYPE_POINTER); /* uri */ gtk_tree_view_set_model (GTK_TREE_VIEW (contentList), GTK_TREE_MODEL (model)); content_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (contentList)); gtk_tree_selection_set_mode (content_selection, GTK_SELECTION_MULTIPLE); g_signal_connect_data (content_selection, "changed", G_CALLBACK (&on_namespaceContentSelectionChanged), NULL, NULL, 0); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (contentList), -1, _("Filename"), renderer, "text", NAMESPACE_FILENAME, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, NAMESPACE_FILENAME); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "xalign", 1.00, NULL); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (contentList), -1, _("Filesize"), renderer, "text", NAMESPACE_HSIZE, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_clickable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sort_column_id (column, NAMESPACE_SIZE); /*gtk_tree_view_column_set_sort_indicator(column, TRUE); */ gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new (); col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (contentList), -1, _("URI"), renderer, "text", NAMESPACE_URISTRING, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (contentList), col - 1), TRUE); GNUNET_URITRACK_register_track_callback (ectx, cfg, &updateViewSave, NULL); GNUNET_pseudonym_list_all (ectx, cfg, &addTabForNamespace, NULL); GNUNET_pseudonym_register_discovery_callback (ectx, cfg, &namespace_discovered_cb, NULL); GNUNET_GTK_DEBUG_END (); } void fs_namespace_stop () { GNUNET_pseudonym_unregister_discovery_callback (&namespace_discovered_cb, NULL); while (head != NULL) frame_destroy (head->treeview); GNUNET_URITRACK_unregister_track_callback (&updateViewSave, NULL); } /* end of namespace.c */