diff options
Diffstat (limited to 'src/fs/gnunet-fs-gtk.c')
-rw-r--r-- | src/fs/gnunet-fs-gtk.c | 262 |
1 files changed, 211 insertions, 51 deletions
diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c index a1230c03..c0e52797 100644 --- a/src/fs/gnunet-fs-gtk.c +++ b/src/fs/gnunet-fs-gtk.c @@ -27,6 +27,8 @@ #include "gnunet-fs-gtk_common.h" #include "gnunet-fs-gtk_event-handler.h" #include "gnunet-fs-gtk_open-uri.h" +#include "gnunet/gnunet_namestore_service.h" +#include <gmodule.h> #if HAVE_LIBUNIQUE #include <unique/unique.h> @@ -73,10 +75,58 @@ static struct GNUNET_ARM_MonitorHandle *armon; static struct GNUNET_ARM_Handle *arm; /** + * Ongoing identity operation. + */ +static struct GNUNET_IDENTITY_Operation *iop; + +/** * Context for main window. */ static struct GNUNET_GTK_MainWindowContext main_context; +/** + * Identity combo box in the main window. + */ +static GtkComboBox *id_combo_box; + +/** + * Currently selected entry in #id_liststore. + */ +static GtkTreeIter id_iter; + +/** + * List of all known egos. + */ +static GtkListStore *id_liststore; + +/** + * Status label in main window. + */ +static GtkLabel *status_label; + +/** + * Are we shutting down? + */ +static int in_shutdown = 0; + +/** + * Columns in the id list store. + */ +enum ID_COLUMNS +{ + + /** + * A gchararray + */ + ID_LS_NAME = 0, + + + /** + * A `struct GNUNET_IDENTITY_Ego` + */ + ID_LS_EGO = 1 +}; + #if HAVE_LIBUNIQUE static UniqueApp *unique_app; @@ -101,6 +151,21 @@ GNUNET_FS_GTK_get_fs_handle () return fs; } +/** + * Get an object from the main window. + * + * @param name name of the object + * @return NULL on error, otherwise the object + */ +static GObject * +get_object (const char *name) +{ + if (NULL == ml) + return NULL; + return GNUNET_GTK_main_loop_get_object (ml, name); +} + + /** * Remember FS handle if we don't have one yet. @@ -250,6 +315,11 @@ shutdown_task (void *cls) struct PseuLookupContext *lctx; struct SearchResult *sr; + in_shutdown = 1; + while (NULL != (sl = main_context.sl_head)) + abort_search_lookup (sl); + while (NULL != (lctx = main_context.lctx_head)) + abort_pseu_lookup (lctx); while (NULL != (sr = pl_head)) { GNUNET_FS_probe_stop (sr->probe); @@ -261,36 +331,16 @@ shutdown_task (void *cls) GNUNET_FS_stop (fs); fs = NULL; } - if (NULL != armon) + if (NULL != iop) { - GNUNET_ARM_monitor_stop (armon); - armon = NULL; - } - if (NULL != arm) - { - GNUNET_ARM_disconnect (arm); - arm = NULL; - } - GNUNET_FS_GTK_close_uri_tab_ (); - if (NULL != ml) - { - GNUNET_GTK_main_loop_quit (ml); - ml = NULL; - } - if (NULL != main_context.id_op) - { - GNUNET_IDENTITY_ego_lookup_cancel (main_context.id_op); - main_context.id_op = NULL; + GNUNET_IDENTITY_cancel (iop); + iop = NULL; } if (NULL != main_context.identity) { GNUNET_IDENTITY_disconnect (main_context.identity); main_context.identity = NULL; } - while (NULL != (sl = main_context.sl_head)) - abort_search_lookup (sl); - while (NULL != (lctx = main_context.lctx_head)) - abort_pseu_lookup (lctx); if (NULL != main_context.zm) { GNUNET_NAMESTORE_zone_monitor_stop (main_context.zm); @@ -301,6 +351,22 @@ shutdown_task (void *cls) GNUNET_GNS_disconnect (main_context.gns); main_context.gns = NULL; } + if (NULL != armon) + { + GNUNET_ARM_monitor_stop (armon); + armon = NULL; + } + if (NULL != arm) + { + GNUNET_ARM_disconnect (arm); + arm = NULL; + } + GNUNET_FS_GTK_close_uri_tab_ (); + if (NULL != ml) + { + GNUNET_GTK_main_loop_quit (ml); + ml = NULL; + } } @@ -664,6 +730,11 @@ handle_sks_zone_identity (void *cls, "main_window_search_namespace_label"))); gtk_widget_show (GTK_WIDGET (GNUNET_FS_GTK_get_main_window_object ( "main_window_search_namespace_combobox"))); + if (NULL != main_context.zm) + { + GNUNET_NAMESTORE_zone_monitor_stop(main_context.zm); + main_context.zm = NULL; + } main_context.zm = GNUNET_NAMESTORE_zone_monitor_start (main_context.cfg, GNUNET_IDENTITY_ego_get_private_key ( @@ -679,9 +750,57 @@ handle_sks_zone_identity (void *cls, /** - * We must pass a non-NULL callback to the identity service, - * but we don't actually care about the information here - * (we will use GNUNET_IDENTITY_get() if and when we do care). + * The user selected another identity in the combobox. Load it. + * + * @param widget the combo box where the selection was changed + * @param user_data the builder, unused + */ +void +gnunet_fs_gtk_id_combobox_changed_cb (GtkComboBox *widget, + gpointer user_data) +{ + GtkTreeIter iter; + struct GNUNET_IDENTITY_Ego *ego; + char *name; + + (void) user_data; + if (! gtk_combo_box_get_active_iter (id_combo_box, &iter)) + { + return; + } + id_iter = iter; + /* clang-format off */ + gtk_tree_model_get (GTK_TREE_MODEL (id_liststore), + &iter, + ID_LS_NAME, &name, + ID_LS_EGO, &ego, + -1); + /* clang-format on */ + handle_sks_zone_identity (name, ego); +} + +/** + * Method called to inform about the egos of this peer. Updates the + * `zone_liststore`. + * + * When used with #GNUNET_IDENTITY_connect, this function is + * initially called for all egos and then again whenever a + * ego's name changes or if it is deleted. At the end of + * the initial pass over all egos, the function is once called + * with 'NULL' for @a ego. That does NOT mean that the callback won't + * be invoked in the future or that there was an error. + * + * If @a ego is non-NULL and if '*ctx' is set in those callbacks, the + * value WILL be passed to a subsequent call to the identity callback + * of #GNUNET_IDENTITY_connect (if that one was not NULL). + * + * When an identity is renamed, this function is called with the + * (known) @a ego but the NEW @a name. + * + * When an identity is deleted, this function is called with the + * (known) ego and "NULL" for the @a name. In this case, + * the @a ego is henceforth invalid (and the @a ctx should also be + * cleaned up). * * @param cls closure * @param ego ego handle @@ -692,17 +811,70 @@ handle_sks_zone_identity (void *cls, * must thus no longer be used */ static void -non_null_cb (void *cls, +identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { - (void) cls; - (void) ego; - (void) ctx; - (void) name; -} + GtkTreeRowReference *rr; + GtkTreeIter iter; + GtkTreePath *path; + + if (in_shutdown) + return; + if ((NULL == ego) && (NULL == name) && (NULL == ctx)) + { + /* end of initial iteration, trigger loading selected zone */ + gnunet_fs_gtk_id_combobox_changed_cb (id_combo_box, ml); + return; + } + rr = *ctx; + if (NULL == rr) + { + /* clang-format off */ + gtk_list_store_insert_with_values (id_liststore, + &iter, 0, + ID_LS_NAME, name, + ID_LS_EGO, ego, + -1); + /* clang-format on */ + gtk_combo_box_set_active_iter (id_combo_box, &iter); + gtk_widget_set_sensitive (GTK_WIDGET (id_combo_box), TRUE); + path = gtk_tree_model_get_path (GTK_TREE_MODEL (id_liststore), &iter); + rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (id_liststore), path); + *ctx = rr; + gtk_tree_path_free (path); + return; + } + path = gtk_tree_row_reference_get_path (rr); + GNUNET_break ( + gtk_tree_model_get_iter (GTK_TREE_MODEL (id_liststore), &iter, path)); + gtk_tree_path_free (path); + if (NULL == name) + { + GtkTreeIter act_iter; + /* identity was removed, remove from list */ + gtk_list_store_remove (id_liststore, &iter); + if (! gtk_combo_box_get_active_iter (id_combo_box, &act_iter)) + { + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (id_liststore), + &act_iter)) + { + /* make sure combo box remains selected if possible */ + gtk_combo_box_set_active (id_combo_box, 0); + } + else + { + /* make combo box insensitive if nothing can be selected */ + gtk_widget_set_sensitive (GTK_WIDGET (id_combo_box), FALSE); + } + } + return; + } + /* identity was renamed, rename in model */ + gtk_list_store_set (id_liststore, &iter, ID_LS_NAME, name, -1); +} /** * Actual main function run right after GNUnet's scheduler @@ -720,7 +892,6 @@ run (void *cls) unsigned long long window_width; unsigned long long window_height; int maximized; - char *default_ego_name; ml = cls; /* setup main context */ @@ -789,6 +960,11 @@ run (void *cls) GTK_IMAGE (GNUNET_FS_GTK_get_main_window_object ( "GNUNET_FS_GTK_main_window_connection_indicator")); + status_label = GTK_LABEL (get_object ( + "gnunet_fs_gtk_status_label")); + id_combo_box = + GTK_COMBO_BOX (get_object ("gnunet_fs_gtk_id_combobox")); + id_liststore = GTK_LIST_STORE (get_object ("id_liststore")); GNUNET_GTK_set_icon_search_path (); GNUNET_GTK_setup_nls (); @@ -856,17 +1032,6 @@ run (void *cls) "MAX_PARALLEL_REQUESTS", &req_parallel)) req_parallel = DEFAULT_MAX_PARALLEL_REQUESTS; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (main_context.cfg, - "fs-sks", - "DEFAULT_IDENTITY", - &default_ego_name)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Please set DEFAULT_IDENTITY under [fs-sks]\n"); - GNUNET_GTK_main_loop_quit (cls); - return; - } /* initialize file-sharing */ fs = GNUNET_FS_start (main_context.cfg, "gnunet-fs-gtk", @@ -890,13 +1055,8 @@ run (void *cls) &service_status_change, &main_context); main_context.gns = GNUNET_GNS_connect (main_context.cfg); - main_context.identity = - GNUNET_IDENTITY_connect (main_context.cfg, &non_null_cb, NULL); - main_context.id_op = GNUNET_IDENTITY_ego_lookup (main_context.cfg, - default_ego_name, - &handle_sks_zone_identity, - NULL); - GNUNET_free (default_ego_name); + main_context.identity = GNUNET_IDENTITY_connect (main_context.cfg, + &identity_cb, NULL); #if HAVE_LIBUNIQUE unique_app_watch_window (unique_app, GTK_WINDOW (main_context.main_window)); g_signal_connect (unique_app, |