anastasis-gtk

Demonstrator GUI for Anastasis
Log | Files | Refs | README | LICENSE

anastasis-gtk.c (7323B)


      1 /*
      2      This file is part of anastasis-gtk.
      3      Copyright (C) 2020, 2021, 2022 Anastasis SARL
      4 
      5      Anastasis is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      Anastasis is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with Anastasis; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 
     21 /**
     22  * @file src/anastasis/anastasis-gtk.c
     23  * @brief Main function of anastasis-gtk
     24  * @author Christian Grothoff
     25  * @author Dennis Neufeld
     26  */
     27 #include <gnunet/gnunet_util_lib.h>
     28 #include "anastasis_gtk_util.h"
     29 #include "anastasis-gtk_action.h"
     30 #include "anastasis-gtk_helper.h"
     31 #include "anastasis-gtk_progress.h"
     32 #include "anastasis-gtk_rows.h"
     33 #include <jansson.h>
     34 
     35 /**
     36  * Handle to our main loop.
     37  */
     38 struct ANASTASIS_GTK_MainLoop *AG_ml;
     39 
     40 /**
     41  * Active policy discovery job, or NULL.
     42  */
     43 struct ANASTASIS_PolicyDiscovery *AG_pd;
     44 
     45 /**
     46  * Our configuration.
     47  */
     48 const struct GNUNET_CONFIGURATION_Handle *AG_cfg;
     49 
     50 /**
     51  * Application ID to include in the user attributes.
     52  * (-a option).
     53  */
     54 char *AG_application_id;
     55 
     56 /**
     57  * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
     58  */
     59 static struct GNUNET_CURL_RescheduleContext *rc;
     60 
     61 /**
     62  * Hash map from UUID hashes to GtkWidgets.
     63  */
     64 struct GNUNET_CONTAINER_MultiHashMap *AG_entry_attributes;
     65 
     66 /**
     67  * Curl context for communication with taler backend
     68  */
     69 struct GNUNET_CURL_Context *AG_ctx;
     70 
     71 /**
     72  * Handle to an ongoing action.
     73  */
     74 struct ANASTASIS_ReduxAction *AG_ra;
     75 
     76 /**
     77  * Handle to an ongoing background action.
     78  */
     79 struct ANASTASIS_LongAction AG_lacs[ANASTASIS_LP_CNT];
     80 
     81 
     82 /**
     83  * Actual state.
     84  */
     85 json_t *AG_redux_state;
     86 
     87 
     88 void
     89 AG_stop_long_action (void)
     90 {
     91   for (enum ANASTASIS_LongActionKind i = 0;
     92        i < ANASTASIS_LP_CNT;
     93        i++)
     94   {
     95     struct ANASTASIS_LongAction *la = &AG_lacs[i];
     96 
     97     if (NULL != la->ra)
     98     {
     99       ANASTASIS_redux_action_cancel (la->ra);
    100       la->ra = NULL;
    101     }
    102     if (NULL != la->task)
    103     {
    104       GNUNET_SCHEDULER_cancel (la->task);
    105       la->task = NULL;
    106     }
    107   }
    108 }
    109 
    110 
    111 /**
    112  * Task run on shutdown.
    113  *
    114  * @param cls unused
    115  */
    116 static void
    117 shutdown_task (void *cls)
    118 {
    119   (void) cls;
    120   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    121               "Shutdown initiated\n");
    122   if (NULL != AG_pd)
    123   {
    124     ANASTASIS_policy_discovery_stop (AG_pd);
    125     AG_pd = NULL;
    126   }
    127   ANASTASIS_redux_done ();
    128   if (NULL != AG_ra)
    129   {
    130     ANASTASIS_redux_action_cancel (AG_ra);
    131     AG_ra = NULL;
    132   }
    133   AG_stop_long_action ();
    134   if (NULL != AG_ctx)
    135   {
    136     GNUNET_CURL_fini (AG_ctx);
    137     AG_ctx = NULL;
    138   }
    139   if (NULL != rc)
    140   {
    141     GNUNET_CURL_gnunet_rc_destroy (rc);
    142     rc = NULL;
    143   }
    144   ANASTASIS_GTK_main_loop_quit (AG_ml);
    145   AG_ml = NULL;
    146   GNUNET_CONTAINER_multihashmap_destroy (AG_entry_attributes);
    147   AG_entry_attributes = NULL;
    148   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    149               "Shutdown complete\n");
    150 }
    151 
    152 
    153 /**
    154  * Callback invoked if the application is supposed to exit, i.e. the user
    155  * closed the main window.
    156  *
    157  * @param window the main window
    158  * @param user_data unused
    159  * @return TRUE, as our own shutdown sequence takes the window down
    160  */
    161 gboolean
    162 anastasis_gtk_quit_cb (GtkWindow *window,
    163                        gpointer user_data)
    164 {
    165   (void) window;
    166   (void) user_data;
    167   GNUNET_SCHEDULER_shutdown ();
    168   return TRUE;
    169 }
    170 
    171 
    172 /**
    173  * User clicked the "quit" button.
    174  *
    175  * @param button the button
    176  * @param user_data unused
    177  */
    178 void
    179 anastasis_gtk_main_window_quit_button_clicked_cb (GtkButton *button,
    180                                                   gpointer user_data)
    181 {
    182   GNUNET_SCHEDULER_shutdown ();
    183 }
    184 
    185 
    186 void
    187 AG_load (const char *filename)
    188 {
    189   json_error_t error;
    190   json_t *in;
    191 
    192   in = json_load_file (filename,
    193                        JSON_REJECT_DUPLICATES,
    194                        &error);
    195   if (NULL == in)
    196   {
    197     AG_error ("Failed to parse file `%s' at %d:%d: %s\n",
    198               filename,
    199               error.line,
    200               error.column,
    201               error.text);
    202     return;
    203   }
    204   AG_action_cb (NULL,
    205                 TALER_EC_NONE,
    206                 in);
    207   json_decref (in);
    208 }
    209 
    210 
    211 /**
    212  * Actual main function run right after GNUnet's scheduler
    213  * is initialized.  Initializes GTK and builds the main window.
    214  *
    215  * @param cls NULL
    216  */
    217 static void
    218 run (void *cls)
    219 {
    220   GtkWidget *main_window;
    221   int argc;
    222   char *const *argv;
    223 
    224   AG_ml = cls;
    225   AG_entry_attributes = GNUNET_CONTAINER_multihashmap_create (16,
    226                                                               GNUNET_NO);
    227   ANASTASIS_GTK_setup_nls ();
    228   /* the UI files name AGRow as the item type of their models, so the type
    229      has to be registered before GtkBuilder parses them */
    230   g_type_ensure (AG_TYPE_ROW);
    231   if (GNUNET_OK !=
    232       ANASTASIS_GTK_main_loop_build_window (ANASTASIS_GTK_project_data (),
    233                                          AG_ml,
    234                                          NULL))
    235     return;
    236   AG_lists_setup ();
    237   AG_progress_setup ();
    238   AG_cfg = ANASTASIS_GTK_main_loop_get_gtk_configuration (AG_ml);
    239   ANASTASIS_GTK_main_loop_get_args (AG_ml,
    240                                  &argc,
    241                                  &argv);
    242   /* setup main window */
    243   main_window = GTK_WIDGET (
    244     GCG_get_main_window_object ("anastasis_gtk_main_window"));
    245   gtk_window_maximize (GTK_WINDOW (main_window));
    246   AG_insensitive ("anastasis_gtk_main_window_forward_button");
    247   /* make GUI visible */
    248   gtk_window_present (GTK_WINDOW (main_window));
    249   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
    250                                  NULL);
    251   /* initialize HTTP client */
    252   AG_ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
    253                              &rc);
    254   rc = GNUNET_CURL_gnunet_rc_create (AG_ctx);
    255   ANASTASIS_redux_init (AG_ctx);
    256   if (0 != argc)
    257     AG_load (argv[0]);
    258 }
    259 
    260 
    261 /**
    262  * Main function of anastasis-gtk.
    263  *
    264  * @param argc number of arguments
    265  * @param argv arguments
    266  * @return 0 on success
    267  */
    268 int
    269 main (int argc,
    270       char *const *argv)
    271 {
    272   struct GNUNET_GETOPT_CommandLineOption options[] = {
    273     GNUNET_GETOPT_option_string ('A',
    274                                  "application",
    275                                  "ID",
    276                                  "set the application ID",
    277                                  &AG_application_id),
    278     GNUNET_GETOPT_OPTION_END
    279   };
    280   int ret;
    281 
    282   AG_application_id = GNUNET_strdup ("anastasis-standalone");
    283   if (GNUNET_OK !=
    284       ANASTASIS_GTK_main_loop_start (ANASTASIS_GTK_project_data (),
    285                                   "anastasis-gtk",
    286                                   "GTK GUI for Anastasis",
    287                                   argc,
    288                                   argv,
    289                                   options,
    290                                   "anastasis_gtk_main_window.ui",
    291                                   &run))
    292     ret = 1;
    293   else
    294     ret = 0;
    295   GNUNET_free (AG_application_id);
    296   return ret;
    297 }
    298 
    299 
    300 /* end of anastasis-gtk.c */