feat(core): create investigation tree model

This commit is contained in:
grayTerminal-sh 2026-07-13 11:44:13 +02:00
parent 40fdcd837b
commit 3a2fbd260d
6 changed files with 419 additions and 0 deletions

View file

@ -639,6 +639,41 @@ Lorsque plusieurs solutions existent, la préférence est donnée à celle qui f
--- ---
## Gestion de la mémoire
Le projet applique une règle unique concernant la propriété des ressources.
> Le propriétaire crée.
> Le propriétaire détruit.
Lorsqu'une ressource est transmise à un objet qui en devient propriétaire, le code appelant ne doit plus la libérer.
Chaque module est responsable uniquement des ressources qu'il possède.
Cette règle s'applique à toutes les structures du projet.
---
## Bibliothèques autorisées
Le projet privilégie les bibliothèques éprouvées plutôt que des réimplémentations.
### Couche Core
Autorisé :
- Langage C17
- GLib
- SQLite
Interdit :
- GTK
Les structures de données fournies par GLib (GPtrArray, GHashTable, GList, etc.) doivent être privilégiées lorsqu'elles répondent au besoin du projet.
---
# Branche principale # Branche principale
La branche `main` est toujours stable. La branche `main` est toujours stable.

View file

@ -0,0 +1,158 @@
# Ticket #008
## Titre
Créer le module `InvestigationTreeModel`.
---
## Objectif
Créer une structure métier représentant le modèle de l'arborescence d'une enquête.
Le modèle sera propriétaire du nœud racine et servira de base au futur explorateur d'enquête.
---
## Responsabilités
Le module `InvestigationTreeModel` doit :
- posséder un nœud racine ;
- gérer le cycle de vie du modèle ;
- exposer le nœud racine en lecture seule.
---
## Hors périmètre
Ce ticket ne doit pas :
- parcourir le système de fichiers ;
- créer les enfants d'un nœud ;
- afficher une interface GTK ;
- communiquer avec SQLite ;
- charger une enquête.
---
## Architecture
```text
Investigation
InvestigationTreeModel
InvestigationNode
```
Le module appartient à la couche **Core**.
Aucune dépendance vers GTK.
---
## Principe de propriété
Le module est **propriétaire** du nœud racine.
À partir du moment où un `InvestigationNode` est transmis au constructeur :
```c
investigation_tree_model_new(root_node);
```
le modèle devient responsable de sa destruction.
Le code appelant ne doit plus appeler :
```c
investigation_node_free(root_node);
```
La destruction du modèle doit automatiquement détruire son nœud racine.
---
## Fichiers concernés
```text
include/core/investigation_tree_model.h
src/core/investigation_tree_model.c
```
---
## Interface publique attendue
```c
InvestigationTreeModel *investigation_tree_model_new(
InvestigationNode *root_node
);
void investigation_tree_model_free(
InvestigationTreeModel *tree_model
);
const InvestigationNode *investigation_tree_model_get_root(
const InvestigationTreeModel *tree_model
);
```
---
## Comportement attendu
Le modèle contient uniquement un nœud racine.
Exemple :
```text
Template
```
Les enfants seront ajoutés dans un ticket ultérieur.
---
## Contraintes techniques
- C17
- Structure opaque
- Aucun état global
- Aucune dépendance GTK
- Documentation Doxygen
- Compilation sans warning
- Respect des conventions du projet
---
## Critères d'acceptation
- [ ] Le projet compile sans warning.
- [ ] Le modèle est opaque.
- [ ] Le modèle possède un nœud racine.
- [ ] Le getter retourne le nœud racine.
- [ ] La destruction du modèle détruit également le nœud racine.
- [ ] Aucun code GTK.
- [ ] Aucun code SQLite.
---
## Tests
- création d'un modèle valide ;
- lecture du nœud racine ;
- destruction du modèle ;
- création avec un nœud NULL ;
- destruction avec NULL.
---
## Commit attendu
```text
feat(core): create investigation tree model
```

View file

@ -0,0 +1,60 @@
/******************************************************************************
* @file investigation_tree_model.h
* @brief Interface publique du modèle d'arborescence d'une enquête.
******************************************************************************/
#ifndef LABFY_INVESTIGATION_INVESTIGATION_TREE_MODEL_H
#define LABFY_INVESTIGATION_INVESTIGATION_TREE_MODEL_H
#include "core/investigation_node.h"
/**
* @brief Représentation opaque du modèle d'arborescence.
*
* La structure réelle est définie dans investigation_tree_model.c.
* Les autres modules manipulent uniquement un pointeur vers
* InvestigationTreeModel.
*/
typedef struct InvestigationTreeModel InvestigationTreeModel;
/**
* @brief Crée un nouveau modèle d'arborescence.
*
* Le modèle devient propriétaire de root_node après cet appel.
* Le code appelant ne doit donc plus libérer root_node directement.
*
* @param root_node Nœud racine transféré au modèle.
*
* @return Un nouveau modèle, ou NULL si root_node vaut NULL
* ou si la création échoue.
*/
InvestigationTreeModel *investigation_tree_model_new(
InvestigationNode *root_node
);
/**
* @brief Libère le modèle et le nœud racine qu'il possède.
*
* Cette fonction accepte NULL.
*
* @param tree_model Modèle à libérer.
*/
void investigation_tree_model_free(
InvestigationTreeModel *tree_model
);
/**
* @brief Retourne le nœud racine du modèle.
*
* Le pointeur retourné appartient toujours au modèle.
* Il ne doit être ni modifié ni libéré par le code appelant.
*
* @param tree_model Modèle à consulter.
*
* @return Nœud racine en lecture seule, ou NULL si tree_model vaut NULL.
*/
const InvestigationNode *investigation_tree_model_get_root(
const InvestigationTreeModel *tree_model
);
#endif

View file

@ -0,0 +1,76 @@
/******************************************************************************
* @file investigation_tree_model.c
* @brief Implémentation du modèle d'arborescence d'une enquête.
******************************************************************************/
#include "core/investigation_tree_model.h"
#include <glib.h>
/**
* @struct InvestigationTreeModel
* @brief Représentation interne du modèle.
*/
struct InvestigationTreeModel
{
InvestigationNode *root_node;
};
InvestigationTreeModel *investigation_tree_model_new(
InvestigationNode *root_node
)
{
InvestigationTreeModel *tree_model = NULL;
if (root_node == NULL)
{
return NULL;
}
tree_model = g_new0(
InvestigationTreeModel,
1
);
if (tree_model == NULL)
{
return NULL;
}
/*
* Ownership transferred.
*
* Le modèle devient propriétaire du nœud racine.
*/
tree_model->root_node = root_node;
return tree_model;
}
void investigation_tree_model_free(
InvestigationTreeModel *tree_model
)
{
if (tree_model == NULL)
{
return;
}
investigation_node_free(
tree_model->root_node
);
g_free(tree_model);
}
const InvestigationNode *investigation_tree_model_get_root(
const InvestigationTreeModel *tree_model
)
{
if (tree_model == NULL)
{
return NULL;
}
return tree_model->root_node;
}

Binary file not shown.

View file

@ -0,0 +1,90 @@
/******************************************************************************
* @file test_investigation_tree_model.c
* @brief Tests du module InvestigationTreeModel.
******************************************************************************/
#include "core/investigation_node.h"
#include "core/investigation_tree_model.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
/**
* @brief Vérifie la création d'un modèle valide.
*/
static void test_tree_model_creation(void)
{
InvestigationNode *root_node = NULL;
InvestigationTreeModel *tree_model = NULL;
const InvestigationNode *returned_node = NULL;
root_node = investigation_node_new(
"Template",
INVESTIGATION_NODE_DIRECTORY
);
assert(root_node != NULL);
tree_model = investigation_tree_model_new(root_node);
assert(tree_model != NULL);
returned_node = investigation_tree_model_get_root(tree_model);
assert(returned_node != NULL);
assert(
strcmp(
investigation_node_get_name(returned_node),
"Template"
) == 0
);
assert(
investigation_node_get_type(returned_node) ==
INVESTIGATION_NODE_DIRECTORY
);
/*
* tree_model est propriétaire de root_node.
*/
investigation_tree_model_free(tree_model);
}
/**
* @brief Vérifie les paramètres invalides.
*/
static void test_invalid_parameters(void)
{
assert(
investigation_tree_model_new(NULL) == NULL
);
assert(
investigation_tree_model_get_root(NULL) == NULL
);
}
/**
* @brief Vérifie que free(NULL) est accepté.
*/
static void test_null_free(void)
{
investigation_tree_model_free(NULL);
}
int main(void)
{
test_tree_model_creation();
test_invalid_parameters();
test_null_free();
printf(
"InvestigationTreeModel : tous les tests sont valides.\n"
);
return 0;
}