/** * @file * @brief Gem-graph-client main file. * * This file is part of Gem-graph. It contains only the main function. * * The function main() initialises the log, the finite state machine (fsm), * the application and the windows. The main window is opened on the 'synthetic * view' page of the current model by default. The main function closes all the * elements it opened at the end of program execution. * * @cond LICENSE * Copyright © 2021 Libre en Communs * Copyright © 2021 Arthur Menges * Copyright © 2021-2024 Adrien Bourmault * Copyright © 2021-2024 Jean Sirmai * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * This program 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 Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * @endcond */ #include "../include/fsm.h" // finite state machine (fsm) and journal init #include "../include/signal.h" // g_signal_connect (app, "activate",...) #include "../include/widget.h" // on_windows_activation callback /** * @since 2024-04 * * @callgraph * @see src/fsm/dispatch/fsm_init() * @see src/widget/dispatch/on_windows_activation(app) * * @param argc * @param **argv * @return status, the program errorlevel */ int main (int argc, char **argv) { // def: src/fsm/dispatch fsm = finite state machine fsm_init ("first instruction / first log"); fsm_journal_event (INFO, MAIN, "main", "*app = gtk_application_new()", "| 👉️ app initialization requested"); GtkApplication *app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS); fsm_journal_event (INFO, MAIN, "main", "g signal connect (activate)", "| 👉️ windows creation requested"); // ! WARNING ! 'on_windows_activation()' // and 'on_windows_startup()' are in: src/widget/dispatch.c // NOT in: src/signal.c g_signal_connect (app, "startup", G_CALLBACK (on_windows_startup), NULL); g_signal_connect (app, "activate", G_CALLBACK (on_windows_activation), NULL); int status = g_application_run (G_APPLICATION (app), argc, argv); fsm_journal_event (INFO, MAIN, "main", "g_object unref (app)", "bye bye app !"); g_object_unref (app); fsm_journal_event (INFO, MAIN, "main", "That'all folks !", "👋️😄️"); fsm_journal_publication_request(); return status; } //----------------------------- personal notes --------------------------- /* * Sur quel modèle se guider pour structurer le client gem-graph ? * * https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel * https://en.wikipedia.org/wiki/Multitier_architecture * * * ORGANISATION ACTUELLE (Octobre 2024) * * 1) Les structures hierarchiques. * -------------------------------- * * La description du 'design' des fenêtres se trouve dans le dossier 'widget' * et s'organise naturellement en arborescence, * en se calquant sur l'arborescence des widgets eux-mêmes. * * Il sera donc facile de répartir cette description en dossiers et fichiers * au fur à mesure de son développement. * * Actuellement, par exemple, la fenêtre principale comporte : * > une barre de titre (décrite dans 'topbar') et * > un widget 'child' (la partie sous la barre de titre) * qui peut prendre au moins trois apparences différentes : * - state (montre l'état de l'espace et les commandes associées) * - rules (les règles et les commandes associées) * - stock (les données provenant des mesures, les outils d'analyse, etc.) * (nom provisoire : mal défini à ce stade; fonctions à répartir...) * * La fenêtre principale s'ouvre sur la vue de l'état ('state.c') en mode 'EXEC'. * Cette vue comporte trois panneaux (widgets) principaux: * sup, moyen, inf ou encore: CONTRAST, CAMERA, CONTROL ou EDIT * si on veut les nommer d'après leur fonction. * * Lorsque la description de chaque widget s'affinera * et demandera plus de place, ces trois widgets principaux * deviendront des dossiers et les widgets qu'ils contiennent * des fichiers (ou des dossiers si besoin) et ainsi de suite... * * * 2) Les structures transversales. * -------------------------------- * * Les fonctions 'transversales' comme celles de 'graphics', 'parse', 'fsm', 'prefer', * et peut-être des structures communes à tous les arbres, listes, etc. * doivent pouvoir être accédées directement * sans avoir à passer par la hiérarchie des widgets et/ou callbacks. * Elles restent à la racine: 'src/ * * * 'finite state machine' ('fsm') va centraliser l'identification * des états (apparences) de la fenêtre et des transitions entre ces apparences; * Elle sera probablement décomposée en de nombreux 'sous-automates' * tels que chaque état de la fenêtre soit une combinaison unique * des états de ces sous-automates. * * Exemple, muni des deux 'sous-automates' : * > { EXEC, EDIT }; // xor * > { STATE, RULES, DATA }; // xor * la 'finite state machine' peut se trouver dans 2 x 3 = 6 états. * (voir fsm.h lignes 40-41) * * * Les grandes fonctions du client seront lancées par cette state machine : * - édition automatique (optimisation) de l'arbre des conditions * - tests sur un mini-serveur local * - analyses de données... * * * Leur recueil et la mémorisation des préférences des utilisateurs * sont des fonctions centrales * mais leur mise en oeuvre suivra probalement des voies hiérarchiques. * * On peut prévoir des préférences concernant l'apparence des widgets, * les traductions, les 'disabilities'; etc. * mais aussi concernant les méthodes de travail, l'usage des outils d'analyse, etc. * >> des 'scripts' pour des 'méta-fonctions' (des 'macros') ? */ // GTK itself does not support event sounds, << A GREAT WAY TO DEBUG ! TODO // you have to use a loadable module like the one that comes with libcanberra. // Property GtkSettings:gtk-error-bell // property gtk-error-bell: gboolean [ read, write ] // When TRUE, keyboard navigation and other input-related errors will cause a beep. /* 2024-08-31 Un point sur l'état d'avancement du client: TODO (bottlenecks) - images (++) - arbres (et listes) (++) - logging (ref : /var/log/messages) - menus (pas indispensables à ce stade)) À redéfinir: répartition des tâches (mesures) client/serveur. Comment traiter le cas extrême où *toutes* les règles sont des règles d'intérêt ? (cas d'une erreur rare, non systématique où il faut "remonter le temps", pas à pas, à partir du premier état qui met l'erreur en évidence) Pour effectuer cette "remontée", il faut une liste complète de toutes les règles appliquées. Cette liste doit comporter, pour chaque item (= chaque exécution d'une règle): - identité de la règle - lieu d'exécution (dans l'espace global) - date d'exécution NB Il ne peut y avoir d'ambiguité ou d'erreur due au parallélisme car, si les espaces locaux de deux exécutions de règles se recouvrent, elles ne peuvent avoir été exécutées simultanément. À mon avis, le serveur ne peut effectuer cette tâche car la "remontée dans le temps" nécessite l'inspection 'de visu' de chaque état. Inspection veut dire ici: reconnaissance de formes et ce travail (visuel) ne peut être pré-programmé (bien qu'il doive être systématique), car le concepteur du modèle ne sait pas quelle est l'erreur et ne peut prévoir ce qu'il va découvrir. Ceci n'exclut pas qu'il puisse - qu'il doive - effectuer plusieurs essais (de "remontée dans le temps") en sélectionnant, par exemple, différentes règles d'intérêt à chaque fois ni qu'il puisse se programmer des outils d'aide (mais tout ceci ne semble pas avoir sa place dans le serveur). NB À ce stade de la conception d'un modèle, les erreurs sont encore fréquentes et les 'runs' sont nécessairement de brève durée. Des 'runs' de longue durée n'ont de sens qu'une fois ce débuggage effectué. Il y a donc peu de problèmes à craindre du fait de la limite de la bande passante. */