/* This file is part of GNUnet. (C) 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/setup/gnunet-setup.c * @brief Main function of gnunet-setup * @author Christian Grothoff */ #if ENABLE_NLS #include #endif #include "gnunet-setup.h" #include "gnunet-setup-options.h" #include /** * Main loop handle. */ static struct GNUNET_GTK_MainLoop *ml; /** * Name of the configuration file. */ static const char *cfgName; /** * Our configuration. */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Global return value (for success/failure of gnunet-setup). */ static int gret; /** * Resolver process handle. */ struct GNUNET_OS_Process *resolver; /** * Get an object from the main window. * * @param name name of the object * @return NULL on error, otherwise the object */ GObject * GNUNET_SETUP_get_object (const char *name) { if (NULL == ml) return NULL; return GNUNET_GTK_main_loop_get_object (ml, name); } static gboolean help_click_callback (GtkWidget * widget, GdkEventButton * event, gpointer user_data) { const struct GNUNET_SETUP_OptionSpecification *os = user_data; GtkLinkButton *help; if (event->type != GDK_BUTTON_PRESS) return FALSE; help = GTK_LINK_BUTTON (GNUNET_SETUP_get_object ("GNUNET_setup_help_text")); gtk_link_button_set_uri (help, os->help_url); gtk_button_set_label (GTK_BUTTON (help), os->help_text); return FALSE; } /** * Change the visibility of widgets according to the * value and visibility specification given. * * @param os option specification * @param value current value for the given option */ static void update_visibility (const struct GNUNET_SETUP_OptionSpecification *os, const char *value) { unsigned int i; const struct GNUNET_SETUP_VisibilitySpecification *vs; GtkWidget *widget; regex_t r; if (NULL == os->visibility) return; i = 0; while (os->visibility[i].widget_name != NULL) { vs = &os->visibility[i]; widget = GTK_WIDGET (GNUNET_SETUP_get_object (vs->widget_name)); if (widget == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Widget `%s' not found\n"), vs->widget_name); } if (NULL != vs->show_value) { if (0 != regcomp (&r, vs->show_value, REG_EXTENDED | REG_ICASE | REG_NOSUB)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Invalid regular expression `%s'\n"), vs->show_value); i++; continue; } if (0 == regexec (&r, value, 0, NULL, 0)) gtk_widget_show (widget); else gtk_widget_hide (widget); regfree (&r); } if (NULL != vs->hide_value) { if (0 != regcomp (&r, vs->hide_value, REG_ICASE | REG_NOSUB)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Invalid regular expression `%s'\n"), vs->show_value); i++; continue; } if (0 == regexec (&r, value, 0, NULL, 0)) gtk_widget_hide (widget); else gtk_widget_show (widget); regfree (&r); } i++; } } /** * Function called whenever a widget changes its state. */ static void widget_state_change_callback (const struct GNUNET_SETUP_OptionSpecification *os) { GObject *widget; char *value; widget = GNUNET_SETUP_get_object (os->widget_name); GNUNET_assert (NULL != os->save_function); if (GNUNET_OK != os->save_function (os->load_save_cls, os->section, os->option, widget, cfg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to obtain option value from widget `%s'\n"), os->widget_name); return; } if (NULL != os->input_validation_function) os->input_validation_function (os->input_validation_function_cls, widget); if ((os->section != NULL) && (os->option != NULL)) GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, os->section, os->option, &value)); else return; update_visibility (os, value); GNUNET_free_non_null (value); } /** * Load options into the main dialog. */ static void load_options () { const struct GNUNET_SETUP_OptionSpecification *os; unsigned int i; GObject *widget; char *value; i = 0; while (option_specifications[i].widget_name != NULL) { os = &option_specifications[i]; widget = GNUNET_SETUP_get_object (os->widget_name); if (NULL == widget) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Widget `%s' not found\n"), os->widget_name); i++; continue; } if (os->load_function != NULL) { if ((NULL == os->section) || (NULL == os->option)) { if (GNUNET_OK != os->load_function (os->load_save_cls, NULL, NULL, NULL, widget, cfg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to initialize widget `%s'\n"), os->widget_name); } } else { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, os->section, os->option, &value)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("No default value known for option `%s' in section `%s'\n"), os->option, os->section); } else { if (GNUNET_OK != os->load_function (os->load_save_cls, os->section, os->option, value, widget, cfg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to initialize widget `%s' with value `%s'\n"), os->widget_name, value); } else { update_visibility (os, value); } GNUNET_free (value); } } } if (NULL != os->input_validation_function) os->input_validation_function (os->input_validation_function_cls, widget); if (os->help_text != NULL) { g_signal_connect (widget, "button-press-event", G_CALLBACK (&help_click_callback), (void *) os); } if (os->change_signal != NULL) { GNUNET_assert (NULL != os->save_function); g_signal_connect_swapped (widget, os->change_signal, G_CALLBACK (&widget_state_change_callback), (void *) os); } i++; } } /** * Actual main method that sets up the configuration window. * * @param cls the main loop handle * @param tc scheduler context */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONFIGURATION_Handle *cfgDefault; if (NULL == ml) { GNUNET_break (0); return; } GNUNET_GTK_main_loop_quit (ml); ml = NULL; cfgDefault = GNUNET_CONFIGURATION_create (); (void) GNUNET_CONFIGURATION_load (cfgDefault, NULL); /* load defaults only */ if (GNUNET_OK != GNUNET_CONFIGURATION_write_diffs (cfgDefault, cfg, cfgName)) gret = 1; GNUNET_CONFIGURATION_destroy (cfgDefault); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; if (NULL != resolver) { GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM)); GNUNET_OS_process_close (resolver); resolver = NULL; } } /** * Callback invoked if the application is supposed to exit. */ void GNUNET_SETUP_quit_cb (GObject * object, gpointer user_data) { GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &cleanup_task, NULL); } /** * Actual main method that sets up the configuration window. * * @param cls the main loop handle * @param tc scheduler context */ static void run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GtkWidget *main_window; ml = cls; cfgName = GNUNET_GTK_main_loop_get_configuration_file (ml); cfg = GNUNET_CONFIGURATION_create (); (void) GNUNET_CONFIGURATION_load (cfg, cfgName); main_window = GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_dialog")); resolver = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-resolver", "gnunet-service-resolver", NULL); load_options (); gtk_widget_show (main_window); gtk_window_present (GTK_WINDOW (main_window)); } /** * Main function for gnunet-setup. * * @param argc number of arguments * @param argv arguments * @return 0 on success */ int main (int argc, char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK == GNUNET_GTK_main_loop_start ("gnunet-setup", "gnunet-setup", argc, argv, options, "gnunet_setup_gtk_main_window.glade", &run)) ret = gret; else ret = 1; return ret; } /* end of gnunet-setup.c */