gem-graph-client/src/main.c

220 lines
9.9 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Gem-graph client *
* Main functions *
* *
* Copyright © 2021 Libre en Communs <contact@a-lec.org> *
* Copyright © 2021 Arthur Menges <arthur.menges@a-lec.org> *
* Copyright © 2021-2024 Adrien Bourmault <neox@a-lec.org> *
* Copyright © 2021-2024 Jean Sirmai <jean@a-lec.org> *
* *
* This file is part of Gem-graph. *
* *
* 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 <http://www.gnu.org/licenses/>. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "../include/widget.h"
/* 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
*
* Le nom de toute fonction qui peut être appelée d'un autre module doit comporter :
* - 1) le nom du module auquel elle appartient (widget, graphics, parse,...)
* - 2) une indication sur son action (get, set, rec, fix, create, add,...)
* - 3) une indication sur l'objet de cette action (state, rules, stock,...)
*
* ex: on_save_current_model()
* model_get_dim_value()
*
* Le fichier 'state.c' est devenu un dossier contenant
* les fichiers 'top.c', 'middle.c', 'bottom.c' et 'distrib.c' (2024-08)
*
* 'middle.c' deviendra, s'il est trop volumineux, un dossier 'middle'
* contenant, par exemple, les fichiers 'camera.c' ou 'contrasts.c' et d'autres
* et ainsi de suite ...
*
* Une fonction comme : get_zoom_box()
* devra alors être renommé : state_camera_get_zoom_box() (par exemple)
*
* _________________
*
*
* ORGANISATION ACTUELLE
*
* 1) Les structures hiérarchiques.
* --------------------------------
*
* 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') ?
*/
#include "../include/widget.h"
#include "../include/signal.h"
#include "../include/fsm.h"
int main (int argc, char **argv)
{
// def: src/fsm/dispatch fsm = finite state machine
fsm_init ("main first instruction in main() & first log");
fsm_journal_event (
"main *app = gtk_application_new ()", INFO, MAIN, "");
GtkApplication *app = gtk_application_new ("org.gem-graph",
G_APPLICATION_DEFAULT_FLAGS);
fsm_journal_event ("main \
g signal connect (app <--> on_windows_startup & activate)", INFO, MAIN, "\n");
// ! 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 ("main g_object unref (app)", INFO, MAIN, "");
g_object_unref (app);
fsm_journal_event ("main That'all folks ! 👋️😄️",INFO, MAIN, "");
fsm_journal_publication_request();
return status;
}
// 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.
*/