/* This file is part of anastasis-gtk. Copyright (C) 2020, 2021, 2022 Anastasis SARL Anastasis 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 3, or (at your option) any later version. Anastasis 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 Anastasis; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * @file src/anastasis/anastasis-gtk.c * @brief Main function of anastasis-gtk * @author Christian Grothoff * @author Dennis Neufeld */ #include #include #include "anastasis-gtk_action.h" #include "anastasis-gtk_helper.h" #include /** * Handle to our main loop. */ struct GNUNET_GTK_MainLoop *AG_ml; /** * Active policy discovery job, or NULL. */ struct ANASTASIS_PolicyDiscovery *AG_pd; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *AG_cfg; /** * Application ID to include in the user attributes. * (-a option). */ char *AG_application_id; /** * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). */ static struct GNUNET_CURL_RescheduleContext *rc; /** * Hash map from UUID hashes to GtkWidgets. */ struct GNUNET_CONTAINER_MultiHashMap *AG_entry_attributes; /** * Curl context for communication with taler backend */ struct GNUNET_CURL_Context *AG_ctx; /** * Handle to an ongoing action. */ struct ANASTASIS_ReduxAction *AG_ra; /** * Handle to an ongoing background action. */ struct ANASTASIS_LongAction AG_lacs[ANASTASIS_LP_CNT]; /** * Actual state. */ json_t *AG_redux_state; void AG_stop_long_action (void) { for (enum ANASTASIS_LongActionKind i = 0; i < ANASTASIS_LP_CNT; i++) { struct ANASTASIS_LongAction *la = &AG_lacs[i]; if (NULL != la->ra) { ANASTASIS_redux_action_cancel (la->ra); la->ra = NULL; } if (NULL != la->task) { GNUNET_SCHEDULER_cancel (la->task); la->task = NULL; } } } /** * Task run on shutdown. * * @param cls unused */ static void shutdown_task (void *cls) { (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown initiated\n"); if (NULL != AG_pd) { ANASTASIS_policy_discovery_stop (AG_pd); AG_pd = NULL; } ANASTASIS_redux_done (); if (NULL != AG_ra) { ANASTASIS_redux_action_cancel (AG_ra); AG_ra = NULL; } AG_stop_long_action (); if (NULL != AG_ctx) { GNUNET_CURL_fini (AG_ctx); AG_ctx = NULL; } if (NULL != rc) { GNUNET_CURL_gnunet_rc_destroy (rc); rc = NULL; } GNUNET_GTK_main_loop_quit (AG_ml); AG_ml = NULL; GNUNET_CONTAINER_multihashmap_destroy (AG_entry_attributes); AG_entry_attributes = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown complete\n"); } /** * Callback invoked if the application is supposed to exit. * * @param object * @param user_data unused */ void anastasis_gtk_quit_cb (GObject *object, gpointer user_data) { GNUNET_SCHEDULER_shutdown (); } /** * User clicked the "quit" button. * * @param button the button * @param user_data unused */ void anastasis_gtk_main_window_quit_button_clicked_cb (GtkButton *button, gpointer user_data) { GNUNET_SCHEDULER_shutdown (); } void AG_load (const char *filename) { json_error_t error; json_t *in; in = json_load_file (filename, JSON_REJECT_DUPLICATES, &error); if (NULL == in) { AG_error ("Failed to parse file `%s' at %d:%d: %s\n", filename, error.line, error.column, error.text); return; } AG_action_cb (NULL, TALER_EC_NONE, in); json_decref (in); } /** * Actual main function run right after GNUnet's scheduler * is initialized. Initializes up GTK and Glade. * * @param cls NULL */ static void run (void *cls) { GtkWidget *main_window; int argc; char *const *argv; AG_ml = cls; AG_entry_attributes = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); GNUNET_GTK_set_icon_search_path (); GNUNET_OS_init (ANASTASIS_project_data_default ()); GNUNET_GTK_setup_nls (); if (GNUNET_OK != GNUNET_GTK_main_loop_build_window (AG_ml, NULL)) return; AG_cfg = GNUNET_GTK_main_loop_get_configuration (AG_ml); GNUNET_GTK_main_loop_get_args (AG_ml, &argc, &argv); /* setup main window */ main_window = GTK_WIDGET ( GCG_get_main_window_object ("anastasis_gtk_main_window")); gtk_window_maximize (GTK_WINDOW (main_window)); /* make GUI visible */ gtk_widget_show (main_window); gtk_window_present (GTK_WINDOW (main_window)); GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* initialize HTTP client */ AG_ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, &rc); rc = GNUNET_CURL_gnunet_rc_create (AG_ctx); ANASTASIS_redux_init (AG_ctx); if (0 != argc) AG_load (argv[0]); } /** * Main function of anastasis-gtk. * * @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_string ('A', "application", "ID", "set the application ID", &AG_application_id), GNUNET_GETOPT_OPTION_END }; int ret; AG_application_id = GNUNET_strdup ("anastasis-gtk"); if (GNUNET_OK != GNUNET_GTK_main_loop_start ("anastasis-gtk", "GTK GUI for Anastasis", argc, argv, options, "anastasis_gtk_main_window.glade", &run)) ret = 1; else ret = 0; GNUNET_free (AG_application_id); return ret; } /* end of anastasis-gtk.c */