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 */