/* 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/edit_publish_dialog.c * @author Christian Grothoff */ #include "common.h" #include "edit_publish_dialog.h" #include /** * Builder for the current dialog. */ static GtkBuilder *builder; void GNUNET_GTK_edit_file_information_keyword_list_normalize_button_clicked_cb () { GNUNET_break (0); } void GNUNET_GTK_edit_file_information_keyword_list_del_button_clicked_cb () { GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeModel *tm; GtkTreeIter iter; tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } gtk_list_store_remove (GTK_LIST_STORE (tm), &iter); } void GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb () { const char *keyword; GtkEntry *entry; GtkListStore *ls; GtkTreeIter iter; ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_keyword_list_store")); entry = GTK_ENTRY (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_entry")); keyword = gtk_entry_get_text (entry); if (strlen (keyword) > 0) gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1); gtk_entry_set_text (entry, ""); } void GNUNET_GTK_edit_file_information_keyword_entry_changed_cb () { const char *keyword; GtkEntry *entry; GtkWidget *button; button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_add_button")); entry = GTK_ENTRY (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_entry")); keyword = gtk_entry_get_text (entry); gtk_widget_set_sensitive (button, (strlen (keyword) > 0) ? TRUE : FALSE); } static void metadata_selection_changed_cb (GtkTreeSelection *ts, gpointer user_data) { GtkTreeView *tv; GtkTreeSelection *sel; GtkWidget *button; tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_tree_view")); sel = gtk_tree_view_get_selection (tv); button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_delete_button")); gtk_widget_set_sensitive (button, gtk_tree_selection_get_selected (sel, NULL, NULL)); } static void keyword_selection_changed_cb (GtkTreeSelection *ts, gpointer user_data) { GtkTreeView *tv; GtkTreeSelection *sel; GtkWidget *button; tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_tree_view")); sel = gtk_tree_view_get_selection (tv); button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_del_button")); gtk_widget_set_sensitive (button, gtk_tree_selection_get_selected (sel, NULL, NULL)); button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_normalize_button")); gtk_widget_set_sensitive (button, gtk_tree_selection_get_selected (sel, NULL, NULL)); } void GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb () { GtkTreeView *tv; GtkTreeSelection *sel; const char *value; GtkEntry *entry; GtkWidget *button; entry = GTK_ENTRY (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_value_entry")); value = gtk_entry_get_text (entry); tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_type_tree_view")); sel = gtk_tree_view_get_selection (tv); button = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_add_button")); gtk_widget_set_sensitive (button, (strlen (value) > 0) ? gtk_tree_selection_get_selected (sel, NULL, NULL) : FALSE); } void GNUNET_GTK_edit_file_information_keyword_entry_activate_cb () { GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb (); } void GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button_file_set_cb () { GNUNET_break (0); } void GNUNET_GTK_edit_file_information_metadata_delete_button_clicked_cb() { GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeModel *tm; GtkTreeIter iter; tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_tree_view")); sel = gtk_tree_view_get_selection (tv); if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter)) { GNUNET_break (0); return; } gtk_list_store_remove (GTK_LIST_STORE (tm), &iter); } void GNUNET_GTK_edit_file_information_metadata_add_button_clicked_cb () { const char *value; GtkEntry *entry; GtkListStore *ls; GtkTreeModel *tm; GtkTreeView *tv; GtkTreeSelection *sel; GtkTreeIter iter; guint type; entry = GTK_ENTRY (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_value_entry")); value = gtk_entry_get_text (entry); if ((value == NULL) || (strlen (value) == 0)) { GNUNET_break (0); return; } tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_type_tree_view")); tm = gtk_tree_view_get_model (tv); 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, &type, -1); ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_meta_data_list_store")); gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, type, 1, (guint) EXTRACTOR_METAFORMAT_UTF8, 2, EXTRACTOR_metatype_to_string (type), 3, value, -1); gtk_entry_set_text (GTK_ENTRY (entry), ""); } /** * 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 (gtk_builder_get_object (builder, "GNUNET_GTK_keyword_list_store")); gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1); return GNUNET_OK; } /** * Add the given meta data to the model (or make it the preview * image if it is an image). * * @param cls closure, NULL * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '' 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 add_meta_item (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; GtkTreeIter iter; switch (format) { case EXTRACTOR_METAFORMAT_UTF8: case EXTRACTOR_METAFORMAT_C_STRING: ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_meta_data_list_store")); gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, (guint) type, 1, (guint) format, 2, EXTRACTOR_metatype_to_string (type), 3, data, -1); break; case EXTRACTOR_METAFORMAT_UNKNOWN: break; case EXTRACTOR_METAFORMAT_BINARY: break; default: GNUNET_break (0); } return 0; } /** * Function called to extract the information from FI. * * @param cls closure * @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 anonymity pointer to selected anonymity level (can be modified) * @param priority pointer to selected priority (can be modified) * @param do_index should we index (can be modified) * @param expirationTime pointer to selected expiration time (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_extract (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) { GtkImage *img; GdkPixbuf *pixbuf; if (NULL != *uri) GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword, NULL); if (NULL != meta) { GNUNET_CONTAINER_meta_data_iterate (meta, &add_meta_item, NULL); pixbuf = GNUNET_GTK_get_thumbnail_from_meta_data (meta); if (pixbuf != NULL) { img = GTK_IMAGE (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_preview_image")); gtk_image_set_from_pixbuf (img, pixbuf); } } /* FIXME: set expiration time (not yet in dialog!) */ gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_anonymity_spin_button")), *anonymity); gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_priority_spin_button")), *priority); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_index_check_button")), *do_index); return GNUNET_SYSERR; /* only visit top-level item */ } /** * Copy binary meta data from to the new container and also * preserve all entries that were not changed. * * @param cls closure, new meta data container * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '' 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 GNUNET_CONTAINER_MetaData *md = cls; GtkTreeModel *tm; GtkTreeIter iter; char *value; guint ntype; guint nformat; int keep; keep = GNUNET_NO; switch (format) { case EXTRACTOR_METAFORMAT_UTF8: case EXTRACTOR_METAFORMAT_C_STRING: tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, "GNUNET_GTK_meta_data_list_store")); if (TRUE == gtk_tree_model_get_iter_first (tm, &iter)) { do { gtk_tree_model_get (tm, &iter, 0, &ntype, 1, &nformat, 3, &value, -1); if ( (ntype == type) && (nformat == format) && (0 == strcmp (value, data)) ) { gtk_list_store_remove (GTK_LIST_STORE (tm), &iter); keep = GNUNET_YES; g_free (value); break; } g_free (value); } while (TRUE == gtk_tree_model_iter_next (tm, &iter)); } break; case EXTRACTOR_METAFORMAT_UNKNOWN: break; case EXTRACTOR_METAFORMAT_BINARY: /* FIXME: this is here since we don't have preview support yet */ keep = GNUNET_YES; break; default: GNUNET_break (0); break; } if (GNUNET_YES == keep) GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, data_mime_type, data, data_len)); return 0; } /** * Function called to update the information in FI. * * @param cls closure (short_fn to update) * @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 anonymity pointer to selected anonymity level (can be modified) * @param priority pointer to selected priority (can be modified) * @param do_index should we index (can be modified) * @param expirationTime pointer to selected expiration time (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, uint32_t *anonymity, uint32_t *priority, int *do_index, struct GNUNET_TIME_Absolute *expirationTime, void **client_info) { char **short_fn = cls; struct GNUNET_CONTAINER_MetaData *nm; GtkTreeModel *tm; GtkTreeIter iter; struct GNUNET_FS_Uri *nxt; struct GNUNET_FS_Uri *mrg; char *value; guint ntype; guint nformat; *anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_anonymity_spin_button"))); *priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_priority_spin_button"))); *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_index_check_button"))); /* update URI */ if (NULL != (*uri)) GNUNET_FS_uri_destroy (*uri); *uri = NULL; nxt = NULL; mrg = NULL; tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, "GNUNET_GTK_keyword_list_store")); if (TRUE == gtk_tree_model_get_iter_first (tm, &iter)) { do { gtk_tree_model_get (tm, &iter, 0, &value, -1); nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value); mrg = GNUNET_FS_uri_ksk_merge (nxt, *uri); GNUNET_FS_uri_destroy (nxt); if (NULL != *uri) GNUNET_FS_uri_destroy (*uri); *uri = mrg; g_free (value); } while (TRUE == gtk_tree_model_iter_next (tm, &iter)); } /* update meta */ nm = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_iterate (meta, &preserve_meta_items, nm); GNUNET_CONTAINER_meta_data_clear (meta); tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, "GNUNET_GTK_meta_data_list_store")); if (TRUE == gtk_tree_model_get_iter_first (tm, &iter)) { do { gtk_tree_model_get (tm, &iter, 0, &ntype, 1, &nformat, 3, &value, -1); GNUNET_CONTAINER_meta_data_insert (nm, "", ntype, nformat, "text/plain", value, strlen (value)+1); g_free (value); } while (TRUE == gtk_tree_model_iter_next (tm, &iter)); } GNUNET_CONTAINER_meta_data_merge (meta, nm); GNUNET_CONTAINER_meta_data_destroy (nm); /* update short_fn */ GNUNET_free_non_null (*short_fn); *short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta, EXTRACTOR_METATYPE_FILENAME, -1); /* FIXME: update expiration time? (not yet in dialog!) */ return GNUNET_SYSERR; /* only visit top-level item */ } /** * Open the dialog to edit file information data. */ void GNUNET_GTK_edit_publish_dialog (int *do_index, char **short_fn, guint *anonymity_level, guint *priority, struct GNUNET_FS_FileInformation *fip) { GtkWidget *ad; GtkListStore *ls; GtkTreeIter iter; guint type; guint max_type; GtkTreeView *tv; GtkTreeSelection *sel; GNUNET_assert (builder == NULL); builder = GNUNET_GTK_get_new_builder ("publish_edit_dialog.glade"); if (builder == NULL) { GNUNET_break (0); return; } ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_dialog")); ls = GTK_LIST_STORE (gtk_builder_get_object (builder, "GNUNET_GTK_metatype_list_store")); max_type = EXTRACTOR_metatype_get_max (); type = 1; while (type < max_type - 1) { gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, EXTRACTOR_metatype_to_string (type), 1, type, 2, EXTRACTOR_metatype_to_description (type), -1); type++; } GNUNET_FS_file_information_inspect (fip, &file_information_extract, NULL); tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_type_tree_view")); sel = gtk_tree_view_get_selection (tv); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb), NULL); tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_metadata_tree_view")); sel = gtk_tree_view_get_selection (tv); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(metadata_selection_changed_cb), NULL); tv = GTK_TREE_VIEW (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_keyword_list_tree_view")); sel = gtk_tree_view_get_selection (tv); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(keyword_selection_changed_cb), NULL); gtk_window_set_title (GTK_WINDOW (ad), *short_fn); if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad))) { gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); builder = NULL; return; } GNUNET_FS_file_information_inspect (fip, &file_information_update, short_fn); *anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_anonymity_spin_button"))); *priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_priority_spin_button"))); *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "GNUNET_GTK_edit_file_information_index_check_button"))); gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); builder = NULL; } /* end of edit_publish_dialog.c */