Créer une vue graphique en lecture seule du graphe d’enquête #62

Closed
opened 2026-07-21 13:37:49 +02:00 by fy59 · 0 comments
Owner

Créer une vue graphique en lecture seule du graphe d’enquête

Contexte

Le chargement asynchrone du graphe d’enquête est désormais intégré à l’application.

Application possède le InvestigationGraphModel, MainWindow relaie son affichage et Workspace l’emprunte. Lorsque le chargement réussit, le Workspace affiche actuellement un résumé temporaire indiquant le nombre d’entités et de relations.

Le modèle métier expose déjà les entités et les relations à travers une API publique triée. Il ne contient volontairement aucune donnée de positionnement ou de rendu graphique.

La prochaine étape consiste à remplacer ce résumé par une première représentation visuelle du graphe, strictement en lecture seule.

Objectif

Créer un widget GTK nommé InvestigationGraphView, basé sur GtkDrawingArea et Cairo, capable d’afficher les entités et les relations d’un InvestigationGraphModel.

Cette première version doit fournir une visualisation stable et lisible sans modifier les données métier et sans introduire encore d’interactions utilisateur.

Architecture attendue

Responsabilités

  • InvestigationGraphModel reste exclusivement un modèle métier.
  • InvestigationGraphView emprunte le graphe et ne le libère jamais.
  • Les positions et dimensions utilisées pour le rendu restent privées à la vue.
  • Workspace crée et possède InvestigationGraphView.
  • Workspace transmet le graphe chargé à la vue.
  • Application reste l’unique propriétaire du InvestigationGraphModel.

Nouveaux fichiers

include/widgets/investigation_graph_view.h
src/widgets/investigation_graph_view.c

Un module interne de calcul de disposition peut être ajouté si cela permet de tester la géométrie sans dépendre d’un serveur d’affichage :

include/widgets/investigation_graph_layout.h
src/widgets/investigation_graph_layout.c
tests/test_investigation_graph_layout.c

Ce module ne doit contenir aucune logique métier ni aucune dépendance à SQLite.

API minimale proposée

typedef struct InvestigationGraphView InvestigationGraphView;

InvestigationGraphView *investigation_graph_view_new(void);

GtkWidget *investigation_graph_view_get_widget(
    const InvestigationGraphView *graph_view
);

void investigation_graph_view_set_graph(
    InvestigationGraphView *graph_view,
    const InvestigationGraphModel *graph_model
);

void investigation_graph_view_clear(
    InvestigationGraphView *graph_view
);

void investigation_graph_view_free(
    InvestigationGraphView *graph_view
);

Rendu attendu

Entités

Chaque entité est représentée par un nœud contenant au minimum :

  • un libellé principal ;
  • son type métier.

Le libellé principal utilise cet ordre de priorité :

  1. label lorsqu’il est renseigné ;
  2. value ;
  3. l’UUID comme dernier recours.

Les textes trop longs doivent être tronqués visuellement sans modifier les données d’origine.

Relations

Chaque relation est représentée par une liaison orientée entre son entité source et son entité cible.

Le rendu doit comporter :

  • une ligne entre les deux nœuds ;
  • une flèche indiquant le sens source vers cible ;
  • aucune liaison lorsque la source ou la cible ne peut pas être retrouvée.

Les relations doivent être dessinées avant les nœuds afin que les nœuds restent lisibles au premier plan.

Disposition initiale

La disposition doit être :

  • déterministe ;
  • recalculée lors du changement de graphe ;
  • recalculée lorsque la taille disponible change ;
  • indépendante de l’ordre interne des tables de hachage.

Une disposition circulaire simple, basée sur la liste triée des entités, est suffisante pour cette première version.

Les cas suivants doivent être gérés explicitement :

  • graphe vide ;
  • une seule entité ;
  • plusieurs entités ;
  • relation d’une entité vers elle-même ;
  • plusieurs relations entre les mêmes entités.

Intégration dans Workspace

Le Workspace doit conserver ses quatre états actuels :

  • vide ;
  • chargement ;
  • prêt ;
  • erreur.

Modifications attendues :

  • créer un InvestigationGraphView dans workspace_new() ;
  • afficher la vue lorsque le graphe est prêt ;
  • transmettre le graphe avec investigation_graph_view_set_graph() ;
  • appeler investigation_graph_view_clear() lors d’un chargement, d’une erreur ou d’un retour à l’état vide ;
  • conserver le spinner et les messages d’erreur actuels ;
  • supprimer le résumé temporaire « Graphe chargé / nombre d’entités / nombre de relations » une fois la vue intégrée.

La sélection d’un nœud de l’arborescence ou d’une preuve peut toujours remplacer temporairement la page du graphe. Lorsque cette sélection est annulée, le Workspace doit restaurer la vue graphique si le graphe est prêt.

Gestion de la mémoire

  • Application possède et libère le InvestigationGraphModel.
  • MainWindow ne possède pas le graphe.
  • Workspace ne possède pas le graphe.
  • InvestigationGraphView ne possède pas le graphe.
  • Les structures privées de disposition appartiennent à InvestigationGraphView.
  • Le graphe doit être détaché de la vue avant sa libération par Application.
  • Les tableaux retournés par investigation_graph_model_list_entities() et investigation_graph_model_list_relations() doivent être libérés par la vue, sans libérer leurs éléments empruntés.

Gestion des erreurs

La vue ne doit jamais fermer l’application en cas d’erreur de préparation du rendu.

En cas d’échec lors de la lecture du graphe ou de la création de la disposition :

  • conserver l’application fonctionnelle ;
  • afficher un message explicite dans la zone de travail ;
  • ne pas conserver une disposition partiellement construite ;
  • ne provoquer aucune fuite mémoire.

Hors périmètre

Cette première version n’inclut pas :

  • déplacement manuel des nœuds ;
  • zoom ;
  • panoramique ;
  • sélection d’une entité ;
  • ouverture d’une fiche ;
  • création, modification ou suppression de relation ;
  • persistance des positions ;
  • synchronisation bidirectionnelle avec SQLite ;
  • algorithme de placement par forces ;
  • regroupement automatique des entités ;
  • export en image ou en PDF.

Ces fonctions feront l’objet de tickets séparés.

Critères d’acceptation

  • InvestigationGraphView est un module opaque indépendant du Workspace.
  • Le widget utilise GtkDrawingArea et Cairo.
  • Le widget emprunte un InvestigationGraphModel.
  • Un graphe vide est affiché sans erreur.
  • Toutes les entités actives fournies par le modèle sont représentées.
  • Les relations valides sont dessinées de la source vers la cible.
  • Le rendu est déterministe pour un même graphe et une même taille.
  • Le redimensionnement de la fenêtre provoque un nouveau rendu correct.
  • Les textes longs ne débordent pas des nœuds.
  • Le Workspace affiche la vue lorsque son état est READY.
  • Les états LOADING, ERROR et EMPTY continuent de fonctionner.
  • Le résumé temporaire du graphe est supprimé.
  • Aucun composant d’interface ne libère le graphe métier.
  • Le changement d’enquête ne laisse aucun pointeur vers l’ancien graphe.
  • make clean && make réussit avec -Werror -Wpedantic.
  • make test réussit.
  • git diff --check ne signale aucune erreur.

Plan d’implémentation conseillé

  1. Créer l’API opaque de InvestigationGraphView.
  2. Créer le GtkDrawingArea et un callback de dessin vide.
  3. Ajouter une représentation privée des positions de nœuds.
  4. Calculer une disposition circulaire déterministe.
  5. Dessiner les relations et leurs flèches.
  6. Dessiner les nœuds et leurs libellés avec Pango/Cairo.
  7. Gérer les graphes vides et les erreurs de préparation.
  8. Intégrer la vue dans Workspace.
  9. Ajouter les tests de disposition indépendants de GTK lorsque le module de layout est séparé.
  10. Compiler, lancer l’application et tester le changement d’enquête.

Validation manuelle

  1. Ouvrir une enquête sans entité.
  2. Vérifier que la vue reste stable et affiche un état vide compréhensible.
  3. Ouvrir une enquête contenant plusieurs entités et relations.
  4. Vérifier que chaque entité apparaît une seule fois.
  5. Vérifier le sens visuel des relations.
  6. Redimensionner fortement la fenêtre.
  7. Sélectionner puis désélectionner une preuve ou un nœud.
  8. Ouvrir une seconde enquête.
  9. Fermer l’application.
  10. Vérifier l’absence d’avertissement critique GTK, de crash et de fuite évidente.
# Créer une vue graphique en lecture seule du graphe d’enquête ## Contexte Le chargement asynchrone du graphe d’enquête est désormais intégré à l’application. `Application` possède le `InvestigationGraphModel`, `MainWindow` relaie son affichage et `Workspace` l’emprunte. Lorsque le chargement réussit, le `Workspace` affiche actuellement un résumé temporaire indiquant le nombre d’entités et de relations. Le modèle métier expose déjà les entités et les relations à travers une API publique triée. Il ne contient volontairement aucune donnée de positionnement ou de rendu graphique. La prochaine étape consiste à remplacer ce résumé par une première représentation visuelle du graphe, strictement en lecture seule. ## Objectif Créer un widget GTK nommé `InvestigationGraphView`, basé sur `GtkDrawingArea` et Cairo, capable d’afficher les entités et les relations d’un `InvestigationGraphModel`. Cette première version doit fournir une visualisation stable et lisible sans modifier les données métier et sans introduire encore d’interactions utilisateur. ## Architecture attendue ### Responsabilités - `InvestigationGraphModel` reste exclusivement un modèle métier. - `InvestigationGraphView` emprunte le graphe et ne le libère jamais. - Les positions et dimensions utilisées pour le rendu restent privées à la vue. - `Workspace` crée et possède `InvestigationGraphView`. - `Workspace` transmet le graphe chargé à la vue. - `Application` reste l’unique propriétaire du `InvestigationGraphModel`. ### Nouveaux fichiers ```text include/widgets/investigation_graph_view.h src/widgets/investigation_graph_view.c ``` Un module interne de calcul de disposition peut être ajouté si cela permet de tester la géométrie sans dépendre d’un serveur d’affichage : ```text include/widgets/investigation_graph_layout.h src/widgets/investigation_graph_layout.c tests/test_investigation_graph_layout.c ``` Ce module ne doit contenir aucune logique métier ni aucune dépendance à SQLite. ## API minimale proposée ```c typedef struct InvestigationGraphView InvestigationGraphView; InvestigationGraphView *investigation_graph_view_new(void); GtkWidget *investigation_graph_view_get_widget( const InvestigationGraphView *graph_view ); void investigation_graph_view_set_graph( InvestigationGraphView *graph_view, const InvestigationGraphModel *graph_model ); void investigation_graph_view_clear( InvestigationGraphView *graph_view ); void investigation_graph_view_free( InvestigationGraphView *graph_view ); ``` ## Rendu attendu ### Entités Chaque entité est représentée par un nœud contenant au minimum : - un libellé principal ; - son type métier. Le libellé principal utilise cet ordre de priorité : 1. `label` lorsqu’il est renseigné ; 2. `value` ; 3. l’UUID comme dernier recours. Les textes trop longs doivent être tronqués visuellement sans modifier les données d’origine. ### Relations Chaque relation est représentée par une liaison orientée entre son entité source et son entité cible. Le rendu doit comporter : - une ligne entre les deux nœuds ; - une flèche indiquant le sens source vers cible ; - aucune liaison lorsque la source ou la cible ne peut pas être retrouvée. Les relations doivent être dessinées avant les nœuds afin que les nœuds restent lisibles au premier plan. ### Disposition initiale La disposition doit être : - déterministe ; - recalculée lors du changement de graphe ; - recalculée lorsque la taille disponible change ; - indépendante de l’ordre interne des tables de hachage. Une disposition circulaire simple, basée sur la liste triée des entités, est suffisante pour cette première version. Les cas suivants doivent être gérés explicitement : - graphe vide ; - une seule entité ; - plusieurs entités ; - relation d’une entité vers elle-même ; - plusieurs relations entre les mêmes entités. ## Intégration dans Workspace Le `Workspace` doit conserver ses quatre états actuels : - vide ; - chargement ; - prêt ; - erreur. Modifications attendues : - créer un `InvestigationGraphView` dans `workspace_new()` ; - afficher la vue lorsque le graphe est prêt ; - transmettre le graphe avec `investigation_graph_view_set_graph()` ; - appeler `investigation_graph_view_clear()` lors d’un chargement, d’une erreur ou d’un retour à l’état vide ; - conserver le spinner et les messages d’erreur actuels ; - supprimer le résumé temporaire « Graphe chargé / nombre d’entités / nombre de relations » une fois la vue intégrée. La sélection d’un nœud de l’arborescence ou d’une preuve peut toujours remplacer temporairement la page du graphe. Lorsque cette sélection est annulée, le `Workspace` doit restaurer la vue graphique si le graphe est prêt. ## Gestion de la mémoire - `Application` possède et libère le `InvestigationGraphModel`. - `MainWindow` ne possède pas le graphe. - `Workspace` ne possède pas le graphe. - `InvestigationGraphView` ne possède pas le graphe. - Les structures privées de disposition appartiennent à `InvestigationGraphView`. - Le graphe doit être détaché de la vue avant sa libération par `Application`. - Les tableaux retournés par `investigation_graph_model_list_entities()` et `investigation_graph_model_list_relations()` doivent être libérés par la vue, sans libérer leurs éléments empruntés. ## Gestion des erreurs La vue ne doit jamais fermer l’application en cas d’erreur de préparation du rendu. En cas d’échec lors de la lecture du graphe ou de la création de la disposition : - conserver l’application fonctionnelle ; - afficher un message explicite dans la zone de travail ; - ne pas conserver une disposition partiellement construite ; - ne provoquer aucune fuite mémoire. ## Hors périmètre Cette première version n’inclut pas : - déplacement manuel des nœuds ; - zoom ; - panoramique ; - sélection d’une entité ; - ouverture d’une fiche ; - création, modification ou suppression de relation ; - persistance des positions ; - synchronisation bidirectionnelle avec SQLite ; - algorithme de placement par forces ; - regroupement automatique des entités ; - export en image ou en PDF. Ces fonctions feront l’objet de tickets séparés. ## Critères d’acceptation - [x] `InvestigationGraphView` est un module opaque indépendant du `Workspace`. - [x] Le widget utilise `GtkDrawingArea` et Cairo. - [x] Le widget emprunte un `InvestigationGraphModel`. - [x] Un graphe vide est affiché sans erreur. - [x] Toutes les entités actives fournies par le modèle sont représentées. - [x] Les relations valides sont dessinées de la source vers la cible. - [x] Le rendu est déterministe pour un même graphe et une même taille. - [x] Le redimensionnement de la fenêtre provoque un nouveau rendu correct. - [x] Les textes longs ne débordent pas des nœuds. - [x] Le `Workspace` affiche la vue lorsque son état est `READY`. - [x] Les états `LOADING`, `ERROR` et `EMPTY` continuent de fonctionner. - [x] Le résumé temporaire du graphe est supprimé. - [x] Aucun composant d’interface ne libère le graphe métier. - [x] Le changement d’enquête ne laisse aucun pointeur vers l’ancien graphe. - [x] `make clean && make` réussit avec `-Werror -Wpedantic`. - [x] `make test` réussit. - [x] `git diff --check` ne signale aucune erreur. ## Plan d’implémentation conseillé 1. Créer l’API opaque de `InvestigationGraphView`. 2. Créer le `GtkDrawingArea` et un callback de dessin vide. 3. Ajouter une représentation privée des positions de nœuds. 4. Calculer une disposition circulaire déterministe. 5. Dessiner les relations et leurs flèches. 6. Dessiner les nœuds et leurs libellés avec Pango/Cairo. 7. Gérer les graphes vides et les erreurs de préparation. 8. Intégrer la vue dans `Workspace`. 9. Ajouter les tests de disposition indépendants de GTK lorsque le module de layout est séparé. 10. Compiler, lancer l’application et tester le changement d’enquête. ## Validation manuelle 1. Ouvrir une enquête sans entité. 2. Vérifier que la vue reste stable et affiche un état vide compréhensible. 3. Ouvrir une enquête contenant plusieurs entités et relations. 4. Vérifier que chaque entité apparaît une seule fois. 5. Vérifier le sens visuel des relations. 6. Redimensionner fortement la fenêtre. 7. Sélectionner puis désélectionner une preuve ou un nœud. 8. Ouvrir une seconde enquête. 9. Fermer l’application. 10. Vérifier l’absence d’avertissement critique GTK, de crash et de fuite évidente.
fy59 closed this issue 2026-07-21 16:52:45 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fy59/labfy-investigation#62
No description provided.