feat: display categorized evidence in sidebar
This commit is contained in:
parent
18566280a7
commit
5d87b35242
20 changed files with 6208 additions and 24 deletions
44
Makefile
44
Makefile
|
|
@ -70,6 +70,10 @@ TEST_EVIDENCE_IMPORT_TASK := tests/test_evidence_import_task
|
||||||
TEST_EVIDENCE_TYPE := tests/test_evidence_type
|
TEST_EVIDENCE_TYPE := tests/test_evidence_type
|
||||||
TEST_EVIDENCE_TYPE_DAO := tests/test_evidence_type_dao
|
TEST_EVIDENCE_TYPE_DAO := tests/test_evidence_type_dao
|
||||||
TEST_EVIDENCE_IMPORT_DIALOG := tests/test_evidence_import_dialog
|
TEST_EVIDENCE_IMPORT_DIALOG := tests/test_evidence_import_dialog
|
||||||
|
TEST_EVIDENCE_LIST_ITEM := tests/test_evidence_list_item
|
||||||
|
TEST_EVIDENCE_LIST_MODEL := tests/test_evidence_list_model
|
||||||
|
TEST_EVIDENCE_CATEGORY_ITEM := tests/test_evidence_category_item
|
||||||
|
TEST_EVIDENCE_CATEGORY_MODEL := tests/test_evidence_category_model
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
|
|
@ -149,6 +153,19 @@ $(TEST_EVIDENCE_RECORD): \
|
||||||
src/models/evidence_record.c
|
src/models/evidence_record.c
|
||||||
$(CC) $(EVIDENCE_RECORD_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
$(CC) $(EVIDENCE_RECORD_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_EVIDENCE_LIST_ITEM): \
|
||||||
|
tests/test_evidence_list_item.c \
|
||||||
|
src/widgets/evidence_list_item.c \
|
||||||
|
src/models/evidence_record.c
|
||||||
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_EVIDENCE_LIST_MODEL): \
|
||||||
|
tests/test_evidence_list_model.c \
|
||||||
|
src/widgets/evidence_list_model.c \
|
||||||
|
src/widgets/evidence_list_item.c \
|
||||||
|
src/models/evidence_record.c
|
||||||
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
$(TEST_INVESTIGATION_DAO): \
|
$(TEST_INVESTIGATION_DAO): \
|
||||||
tests/test_investigation_dao.c \
|
tests/test_investigation_dao.c \
|
||||||
src/dao/investigation_dao.c \
|
src/dao/investigation_dao.c \
|
||||||
|
|
@ -304,6 +321,21 @@ $(TEST_EVIDENCE_IMPORT_DIALOG): \
|
||||||
-o $@ \
|
-o $@ \
|
||||||
$(EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS)
|
$(EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_ITEM): \
|
||||||
|
tests/test_evidence_category_item.c \
|
||||||
|
src/widgets/evidence_category_item.c \
|
||||||
|
src/widgets/evidence_list_item.c \
|
||||||
|
src/models/evidence_record.c
|
||||||
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_MODEL): \
|
||||||
|
tests/test_evidence_category_model.c \
|
||||||
|
src/widgets/evidence_category_model.c \
|
||||||
|
src/widgets/evidence_category_item.c \
|
||||||
|
src/widgets/evidence_list_item.c \
|
||||||
|
src/models/evidence_record.c
|
||||||
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
test: \
|
test: \
|
||||||
$(TEST_NODE) \
|
$(TEST_NODE) \
|
||||||
$(TEST_TREE_MODEL) \
|
$(TEST_TREE_MODEL) \
|
||||||
|
|
@ -315,6 +347,10 @@ test: \
|
||||||
$(TEST_ERROR) \
|
$(TEST_ERROR) \
|
||||||
$(TEST_INVESTIGATION_RECORD) \
|
$(TEST_INVESTIGATION_RECORD) \
|
||||||
$(TEST_EVIDENCE_RECORD) \
|
$(TEST_EVIDENCE_RECORD) \
|
||||||
|
$(TEST_EVIDENCE_LIST_ITEM) \
|
||||||
|
$(TEST_EVIDENCE_LIST_MODEL) \
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_ITEM) \
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_MODEL) \
|
||||||
$(TEST_EVIDENCE_TYPE) \
|
$(TEST_EVIDENCE_TYPE) \
|
||||||
$(TEST_INVESTIGATION_DAO) \
|
$(TEST_INVESTIGATION_DAO) \
|
||||||
$(TEST_EVIDENCE_DAO) \
|
$(TEST_EVIDENCE_DAO) \
|
||||||
|
|
@ -342,6 +378,10 @@ test: \
|
||||||
@$(TEST_TRANSACTION)
|
@$(TEST_TRANSACTION)
|
||||||
@$(TEST_ERROR)
|
@$(TEST_ERROR)
|
||||||
@$(TEST_INVESTIGATION_RECORD)
|
@$(TEST_INVESTIGATION_RECORD)
|
||||||
|
@$(TEST_EVIDENCE_LIST_ITEM)
|
||||||
|
@$(TEST_EVIDENCE_LIST_MODEL)
|
||||||
|
@$(TEST_EVIDENCE_CATEGORY_ITEM)
|
||||||
|
@$(TEST_EVIDENCE_CATEGORY_MODEL)
|
||||||
@$(TEST_EVIDENCE_RECORD)
|
@$(TEST_EVIDENCE_RECORD)
|
||||||
@$(TEST_EVIDENCE_TYPE)
|
@$(TEST_EVIDENCE_TYPE)
|
||||||
@$(TEST_INVESTIGATION_DAO)
|
@$(TEST_INVESTIGATION_DAO)
|
||||||
|
|
@ -380,6 +420,10 @@ clean:
|
||||||
$(TEST_ERROR) \
|
$(TEST_ERROR) \
|
||||||
$(TEST_INVESTIGATION_RECORD) \
|
$(TEST_INVESTIGATION_RECORD) \
|
||||||
$(TEST_EVIDENCE_RECORD) \
|
$(TEST_EVIDENCE_RECORD) \
|
||||||
|
$(TEST_EVIDENCE_LIST_ITEM) \
|
||||||
|
$(TEST_EVIDENCE_LIST_MODEL) \
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_ITEM) \
|
||||||
|
$(TEST_EVIDENCE_CATEGORY_MODEL) \
|
||||||
$(TEST_EVIDENCE_TYPE) \
|
$(TEST_EVIDENCE_TYPE) \
|
||||||
$(TEST_EVIDENCE_TYPE_DAO) \
|
$(TEST_EVIDENCE_TYPE_DAO) \
|
||||||
$(TEST_INVESTIGATION_DAO) \
|
$(TEST_INVESTIGATION_DAO) \
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "widgets/investigation_tree_view.h"
|
#include "widgets/investigation_tree_view.h"
|
||||||
#include "core/investigation_node.h"
|
#include "core/investigation_node.h"
|
||||||
#include "core/task_manager.h"
|
#include "core/task_manager.h"
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
@ -37,6 +38,20 @@ typedef void (*MainWindowImportEvidenceCallback)(
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback appelé lorsqu'une preuve est sélectionnée.
|
||||||
|
*
|
||||||
|
* L'identifiant est emprunté et uniquement valide pendant l'appel.
|
||||||
|
* Une sélection vide ou une catégorie transmet NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_identifier UUID de la preuve, ou NULL.
|
||||||
|
* @param user_data Données privées fournies par l'appelant.
|
||||||
|
*/
|
||||||
|
typedef void (*MainWindowEvidenceSelectionCallback)(
|
||||||
|
const char *evidence_identifier,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Définit le callback du bouton « Nouvelle enquête ».
|
* @brief Définit le callback du bouton « Nouvelle enquête ».
|
||||||
*
|
*
|
||||||
|
|
@ -100,6 +115,22 @@ void main_window_set_tree_model(
|
||||||
const InvestigationTreeModel *tree_model
|
const InvestigationTreeModel *tree_model
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transmet le modèle des catégories de preuves à la Sidebar.
|
||||||
|
*
|
||||||
|
* MainWindow ne devient pas propriétaire du modèle.
|
||||||
|
* Le modèle doit rester valide pendant son affichage.
|
||||||
|
*
|
||||||
|
* Passer NULL vide l'onglet Preuves.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
* @param evidence_category_model Modèle de catégories, ou NULL.
|
||||||
|
*/
|
||||||
|
void main_window_set_evidence_model(
|
||||||
|
MainWindow *main_window,
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Met à jour l'identité de l'enquête affichée.
|
* @brief Met à jour l'identité de l'enquête affichée.
|
||||||
*
|
*
|
||||||
|
|
@ -128,6 +159,21 @@ void main_window_set_tree_selection_callback(
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Définit le callback de sélection d'une preuve.
|
||||||
|
*
|
||||||
|
* MainWindow transmet uniquement le callback à la Sidebar.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
* @param callback Callback facultatif.
|
||||||
|
* @param user_data Données privées transmises au callback.
|
||||||
|
*/
|
||||||
|
void main_window_set_evidence_selection_callback(
|
||||||
|
MainWindow *main_window,
|
||||||
|
MainWindowEvidenceSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Affiche dans le Workspace les informations du nœud sélectionné.
|
* @brief Affiche dans le Workspace les informations du nœud sélectionné.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
100
include/widgets/evidence_category_item.h
Normal file
100
include/widgets/evidence_category_item.h
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_category_item.h
|
||||||
|
* @brief Catégorie GTK regroupant plusieurs preuves affichées.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_EVIDENCE_CATEGORY_ITEM_H
|
||||||
|
#define LABFY_INVESTIGATION_EVIDENCE_CATEGORY_ITEM_H
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type GObject de EvidenceCategoryItem.
|
||||||
|
*/
|
||||||
|
#define EVIDENCE_TYPE_CATEGORY_ITEM \
|
||||||
|
(evidence_category_item_get_type())
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(
|
||||||
|
EvidenceCategoryItem,
|
||||||
|
evidence_category_item,
|
||||||
|
EVIDENCE,
|
||||||
|
CATEGORY_ITEM,
|
||||||
|
GObject
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée une catégorie de preuves.
|
||||||
|
*
|
||||||
|
* Le code et le libellé sont copiés et nettoyés.
|
||||||
|
*
|
||||||
|
* @param type_identifier Code métier stable de la catégorie.
|
||||||
|
* @param label Libellé destiné à l'utilisateur.
|
||||||
|
*
|
||||||
|
* @return Nouvelle catégorie, ou NULL.
|
||||||
|
*/
|
||||||
|
EvidenceCategoryItem *evidence_category_item_new(
|
||||||
|
const char *type_identifier,
|
||||||
|
const char *label
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ajoute une preuve à la catégorie.
|
||||||
|
*
|
||||||
|
* La catégorie conserve sa propre référence sur evidence_list_item.
|
||||||
|
*
|
||||||
|
* @param evidence_category_item Catégorie cible.
|
||||||
|
* @param evidence_list_item Preuve d'affichage à ajouter.
|
||||||
|
*
|
||||||
|
* @return TRUE en cas de succès.
|
||||||
|
*/
|
||||||
|
gboolean evidence_category_item_append(
|
||||||
|
EvidenceCategoryItem *evidence_category_item,
|
||||||
|
EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le code métier de la catégorie.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_category_item_get_type_identifier(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le libellé utilisateur.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_category_item_get_label(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nombre de preuves de la catégorie.
|
||||||
|
*
|
||||||
|
* @return Nombre de preuves, ou 0.
|
||||||
|
*/
|
||||||
|
guint evidence_category_item_get_count(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le modèle contenant les preuves.
|
||||||
|
*
|
||||||
|
* La référence retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @return GListModel emprunté, ou NULL.
|
||||||
|
*/
|
||||||
|
GListModel *evidence_category_item_get_children(
|
||||||
|
EvidenceCategoryItem *evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
128
include/widgets/evidence_category_model.h
Normal file
128
include/widgets/evidence_category_model.h
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_category_model.h
|
||||||
|
* @brief Modèle GTK regroupant les preuves par catégorie.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_EVIDENCE_CATEGORY_MODEL_H
|
||||||
|
#define LABFY_INVESTIGATION_EVIDENCE_CATEGORY_MODEL_H
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modèle opaque contenant des EvidenceCategoryItem.
|
||||||
|
*/
|
||||||
|
typedef struct EvidenceCategoryModel EvidenceCategoryModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Codes d'erreur produits par EvidenceCategoryModel.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Un argument public est invalide.
|
||||||
|
*/
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ARGUMENT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le modèle contient un élément invalide.
|
||||||
|
*/
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ITEM,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Une catégorie n'a pas pu être créée.
|
||||||
|
*/
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_CATEGORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Une allocation a échoué.
|
||||||
|
*/
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_MEMORY
|
||||||
|
} EvidenceCategoryModelError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Domaine d'erreur du modèle de catégories.
|
||||||
|
*/
|
||||||
|
#define EVIDENCE_CATEGORY_MODEL_ERROR \
|
||||||
|
evidence_category_model_error_quark()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le domaine d'erreur du module.
|
||||||
|
*
|
||||||
|
* @return Quark associé à EvidenceCategoryModel.
|
||||||
|
*/
|
||||||
|
GQuark evidence_category_model_error_quark(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un modèle de catégories vide.
|
||||||
|
*
|
||||||
|
* @return Nouveau modèle, ou NULL.
|
||||||
|
*/
|
||||||
|
EvidenceCategoryModel *evidence_category_model_new(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère le modèle.
|
||||||
|
*
|
||||||
|
* Cette fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_category_model Modèle à libérer.
|
||||||
|
*/
|
||||||
|
void evidence_category_model_free(
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le modèle GTK contenant les catégories.
|
||||||
|
*
|
||||||
|
* La référence retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @return GListModel emprunté, ou NULL.
|
||||||
|
*/
|
||||||
|
GListModel *evidence_category_model_get_list_model(
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nombre de catégories.
|
||||||
|
*
|
||||||
|
* @return Nombre de catégories, ou 0.
|
||||||
|
*/
|
||||||
|
guint evidence_category_model_get_count(
|
||||||
|
const EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Regroupe les preuves par type métier.
|
||||||
|
*
|
||||||
|
* evidence_items doit contenir des EvidenceListItem.
|
||||||
|
*
|
||||||
|
* type_labels est une table facultative associant :
|
||||||
|
*
|
||||||
|
* - clé : code métier du type ;
|
||||||
|
* - valeur : libellé utilisateur.
|
||||||
|
*
|
||||||
|
* La table est uniquement empruntée pendant l'appel.
|
||||||
|
* Lorsqu'un libellé est absent, le code métier est utilisé.
|
||||||
|
*
|
||||||
|
* Le nouveau contenu est entièrement préparé avant que l'ancien modèle
|
||||||
|
* soit remplacé.
|
||||||
|
*
|
||||||
|
* @param evidence_category_model Modèle à actualiser.
|
||||||
|
* @param evidence_items Modèle contenant des EvidenceListItem.
|
||||||
|
* @param type_labels Correspondance code vers libellé, ou NULL.
|
||||||
|
* @param error Emplacement facultatif recevant une erreur.
|
||||||
|
*
|
||||||
|
* @return TRUE en cas de succès.
|
||||||
|
*/
|
||||||
|
gboolean evidence_category_model_replace(
|
||||||
|
EvidenceCategoryModel *evidence_category_model,
|
||||||
|
GListModel *evidence_items,
|
||||||
|
GHashTable *type_labels,
|
||||||
|
GError **error
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
124
include/widgets/evidence_list_item.h
Normal file
124
include/widgets/evidence_list_item.h
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_list_item.h
|
||||||
|
* @brief Objet d'affichage GTK représentant une preuve importée.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_EVIDENCE_LIST_ITEM_H
|
||||||
|
#define LABFY_INVESTIGATION_EVIDENCE_LIST_ITEM_H
|
||||||
|
|
||||||
|
#include "models/evidence_record.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type GObject de EvidenceListItem.
|
||||||
|
*/
|
||||||
|
#define EVIDENCE_TYPE_LIST_ITEM \
|
||||||
|
(evidence_list_item_get_type())
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(
|
||||||
|
EvidenceListItem,
|
||||||
|
evidence_list_item,
|
||||||
|
EVIDENCE,
|
||||||
|
LIST_ITEM,
|
||||||
|
GObject
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un élément d'affichage depuis une preuve métier.
|
||||||
|
*
|
||||||
|
* Les valeurs nécessaires à l'interface sont copiées.
|
||||||
|
* L'objet ne conserve aucun pointeur emprunté vers EvidenceRecord.
|
||||||
|
*
|
||||||
|
* L'appelant possède la référence retournée et doit la libérer
|
||||||
|
* avec g_object_unref() ou g_clear_object().
|
||||||
|
*
|
||||||
|
* @param evidence_record Preuve métier valide.
|
||||||
|
*
|
||||||
|
* @return Nouvel élément d'affichage, ou NULL.
|
||||||
|
*/
|
||||||
|
EvidenceListItem *evidence_list_item_new(
|
||||||
|
const EvidenceRecord *evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne l'identifiant UUID de la preuve.
|
||||||
|
*
|
||||||
|
* Cet identifiant est utilisé pour signaler une sélection à Application.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_identifier(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nom original de la preuve.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_original_name(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne l'identifiant métier du type de preuve.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_type_identifier(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne la taille de la preuve.
|
||||||
|
*
|
||||||
|
* @return Taille en octets, ou 0.
|
||||||
|
*/
|
||||||
|
guint64 evidence_list_item_get_size_bytes(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne la date UTC de collecte.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_collected_at(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne la source déclarée.
|
||||||
|
*
|
||||||
|
* @return Chaîne empruntée, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_source(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne l'état d'intégrité.
|
||||||
|
*
|
||||||
|
* @return État d'intégrité enregistré.
|
||||||
|
*/
|
||||||
|
EvidenceIntegrityStatus evidence_list_item_get_integrity_status(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne un libellé utilisateur pour l'état d'intégrité.
|
||||||
|
*
|
||||||
|
* La chaîne retournée est statique et ne doit pas être libérée.
|
||||||
|
*
|
||||||
|
* @return Libellé d'état.
|
||||||
|
*/
|
||||||
|
const char *evidence_list_item_get_integrity_status_label(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
119
include/widgets/evidence_list_model.h
Normal file
119
include/widgets/evidence_list_model.h
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_list_model.h
|
||||||
|
* @brief Modèle GTK en mémoire contenant la liste des preuves affichées.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_EVIDENCE_LIST_MODEL_H
|
||||||
|
#define LABFY_INVESTIGATION_EVIDENCE_LIST_MODEL_H
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modèle opaque contenant des EvidenceListItem.
|
||||||
|
*/
|
||||||
|
typedef struct EvidenceListModel EvidenceListModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Codes d'erreur produits par EvidenceListModel.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Un argument public est invalide.
|
||||||
|
*/
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_ARGUMENT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Une allocation a échoué.
|
||||||
|
*/
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_MEMORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un EvidenceRecord ne peut pas produire un élément d'affichage.
|
||||||
|
*/
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_RECORD
|
||||||
|
} EvidenceListModelError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Domaine d'erreur du modèle de liste.
|
||||||
|
*/
|
||||||
|
#define EVIDENCE_LIST_MODEL_ERROR \
|
||||||
|
evidence_list_model_error_quark()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le domaine d'erreur du modèle.
|
||||||
|
*
|
||||||
|
* @return Quark GLib associé à EvidenceListModel.
|
||||||
|
*/
|
||||||
|
GQuark evidence_list_model_error_quark(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un modèle de liste vide.
|
||||||
|
*
|
||||||
|
* @return Nouveau modèle, ou NULL.
|
||||||
|
*/
|
||||||
|
EvidenceListModel *evidence_list_model_new(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère le modèle et tous ses éléments.
|
||||||
|
*
|
||||||
|
* Cette fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_list_model Modèle à libérer.
|
||||||
|
*/
|
||||||
|
void evidence_list_model_free(
|
||||||
|
EvidenceListModel *evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le GListModel utilisé par les widgets GTK.
|
||||||
|
*
|
||||||
|
* La référence retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @param evidence_list_model Modèle valide.
|
||||||
|
*
|
||||||
|
* @return GListModel emprunté, ou NULL.
|
||||||
|
*/
|
||||||
|
GListModel *evidence_list_model_get_list_model(
|
||||||
|
EvidenceListModel *evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nombre d'éléments affichés.
|
||||||
|
*
|
||||||
|
* @param evidence_list_model Modèle de liste.
|
||||||
|
*
|
||||||
|
* @return Nombre d'éléments, ou 0.
|
||||||
|
*/
|
||||||
|
guint evidence_list_model_get_count(
|
||||||
|
const EvidenceListModel *evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remplace complètement le contenu du modèle.
|
||||||
|
*
|
||||||
|
* evidence_records doit contenir des pointeurs EvidenceRecord valides.
|
||||||
|
*
|
||||||
|
* Tous les nouveaux EvidenceListItem sont construits avant la modification
|
||||||
|
* du modèle existant. En cas d'erreur, l'ancien contenu reste inchangé.
|
||||||
|
*
|
||||||
|
* Le tableau et les EvidenceRecord restent la propriété de l'appelant.
|
||||||
|
*
|
||||||
|
* @param evidence_list_model Modèle à mettre à jour.
|
||||||
|
* @param evidence_records Tableau de EvidenceRecord.
|
||||||
|
* @param error Emplacement facultatif recevant une erreur.
|
||||||
|
*
|
||||||
|
* @return TRUE en cas de succès.
|
||||||
|
*/
|
||||||
|
gboolean evidence_list_model_replace(
|
||||||
|
EvidenceListModel *evidence_list_model,
|
||||||
|
const GPtrArray *evidence_records,
|
||||||
|
GError **error
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
99
include/widgets/evidence_tree_view.h
Normal file
99
include/widgets/evidence_tree_view.h
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_tree_view.h
|
||||||
|
* @brief Affichage GTK hiérarchique des catégories et preuves importées.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_EVIDENCE_TREE_VIEW_H
|
||||||
|
#define LABFY_INVESTIGATION_EVIDENCE_TREE_VIEW_H
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vue opaque affichant les preuves regroupées par catégorie.
|
||||||
|
*/
|
||||||
|
typedef struct EvidenceTreeView EvidenceTreeView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback appelé lorsqu'une preuve est sélectionnée.
|
||||||
|
*
|
||||||
|
* L'identifiant est emprunté et uniquement valide pendant l'appel.
|
||||||
|
*
|
||||||
|
* Lorsque la sélection est vide ou correspond à une catégorie,
|
||||||
|
* evidence_identifier vaut NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_identifier UUID de la preuve sélectionnée, ou NULL.
|
||||||
|
* @param user_data Données privées fournies par l'appelant.
|
||||||
|
*/
|
||||||
|
typedef void (*EvidenceTreeViewSelectionCallback)(
|
||||||
|
const char *evidence_identifier,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée une vue hiérarchique vide.
|
||||||
|
*
|
||||||
|
* @return Nouvelle vue, ou NULL.
|
||||||
|
*/
|
||||||
|
EvidenceTreeView *evidence_tree_view_new(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le widget GTK racine.
|
||||||
|
*
|
||||||
|
* Le widget retourné est emprunté.
|
||||||
|
*
|
||||||
|
* @param evidence_tree_view Vue à consulter.
|
||||||
|
*
|
||||||
|
* @return GtkScrolledWindow racine, ou NULL.
|
||||||
|
*/
|
||||||
|
GtkWidget *evidence_tree_view_get_widget(
|
||||||
|
const EvidenceTreeView *evidence_tree_view
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Installe un modèle de catégories.
|
||||||
|
*
|
||||||
|
* La vue ne devient pas propriétaire de EvidenceCategoryModel.
|
||||||
|
* Le modèle doit rester valide pendant son utilisation.
|
||||||
|
*
|
||||||
|
* Passer NULL vide la vue.
|
||||||
|
*
|
||||||
|
* @param evidence_tree_view Vue à actualiser.
|
||||||
|
* @param evidence_category_model Modèle de catégories, ou NULL.
|
||||||
|
*/
|
||||||
|
void evidence_tree_view_set_model(
|
||||||
|
EvidenceTreeView *evidence_tree_view,
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Définit le callback de sélection.
|
||||||
|
*
|
||||||
|
* @param evidence_tree_view Vue à configurer.
|
||||||
|
* @param callback Callback facultatif.
|
||||||
|
* @param user_data Données privées transmises au callback.
|
||||||
|
*/
|
||||||
|
void evidence_tree_view_set_selection_callback(
|
||||||
|
EvidenceTreeView *evidence_tree_view,
|
||||||
|
EvidenceTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère la structure d'encapsulation.
|
||||||
|
*
|
||||||
|
* Les widgets GTK intégrés dans la fenêtre restent gérés par l'arbre GTK.
|
||||||
|
* Cette fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_tree_view Vue à libérer.
|
||||||
|
*/
|
||||||
|
void evidence_tree_view_free(
|
||||||
|
EvidenceTreeView *evidence_tree_view
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "core/investigation_tree_model.h"
|
#include "core/investigation_tree_model.h"
|
||||||
#include "widgets/investigation_tree_view.h"
|
#include "widgets/investigation_tree_view.h"
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
@ -19,6 +20,20 @@
|
||||||
*/
|
*/
|
||||||
typedef struct Sidebar Sidebar;
|
typedef struct Sidebar Sidebar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback appelé lorsqu'une preuve est sélectionnée.
|
||||||
|
*
|
||||||
|
* L'identifiant est emprunté et uniquement valide pendant l'appel.
|
||||||
|
* Une sélection vide ou une catégorie transmet NULL.
|
||||||
|
*
|
||||||
|
* @param evidence_identifier UUID de la preuve, ou NULL.
|
||||||
|
* @param user_data Données privées fournies par l'appelant.
|
||||||
|
*/
|
||||||
|
typedef void (*SidebarEvidenceSelectionCallback)(
|
||||||
|
const char *evidence_identifier,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Crée un nouveau panneau de navigation latéral.
|
* @brief Crée un nouveau panneau de navigation latéral.
|
||||||
*
|
*
|
||||||
|
|
@ -71,6 +86,33 @@ void sidebar_set_selection_callback(
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Installe le modèle des catégories de preuves.
|
||||||
|
*
|
||||||
|
* La Sidebar ne devient pas propriétaire du modèle.
|
||||||
|
* Passer NULL rétablit l'état vide.
|
||||||
|
*
|
||||||
|
* @param sidebar Barre latérale à actualiser.
|
||||||
|
* @param evidence_category_model Modèle de catégories, ou NULL.
|
||||||
|
*/
|
||||||
|
void sidebar_set_evidence_model(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Définit le callback de sélection d'une preuve.
|
||||||
|
*
|
||||||
|
* @param sidebar Barre latérale à configurer.
|
||||||
|
* @param callback Callback facultatif.
|
||||||
|
* @param user_data Données privées transmises au callback.
|
||||||
|
*/
|
||||||
|
void sidebar_set_evidence_selection_callback(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
SidebarEvidenceSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Libère la structure d'encapsulation du panneau latéral.
|
* @brief Libère la structure d'encapsulation du panneau latéral.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@
|
||||||
#include "models/evidence_record.h"
|
#include "models/evidence_record.h"
|
||||||
#include "dao/evidence_type_dao.h"
|
#include "dao/evidence_type_dao.h"
|
||||||
#include "views/evidence_import_dialog.h"
|
#include "views/evidence_import_dialog.h"
|
||||||
|
#include "dao/evidence_dao.h"
|
||||||
|
#include "models/evidence_type.h"
|
||||||
|
#include "widgets/evidence_list_model.h"
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -46,7 +50,8 @@ typedef enum
|
||||||
APPLICATION_OPEN_ERROR_INVALID_ARGUMENT,
|
APPLICATION_OPEN_ERROR_INVALID_ARGUMENT,
|
||||||
APPLICATION_OPEN_ERROR_INVALID_PROJECT,
|
APPLICATION_OPEN_ERROR_INVALID_PROJECT,
|
||||||
APPLICATION_OPEN_ERROR_TREE_BUILD,
|
APPLICATION_OPEN_ERROR_TREE_BUILD,
|
||||||
APPLICATION_OPEN_ERROR_INSTALL
|
APPLICATION_OPEN_ERROR_INSTALL,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE
|
||||||
} ApplicationOpenError;
|
} ApplicationOpenError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -81,10 +86,12 @@ struct Application
|
||||||
InvestigationTreeModel *tree_model;
|
InvestigationTreeModel *tree_model;
|
||||||
TaskManager *task_manager;
|
TaskManager *task_manager;
|
||||||
ToolInitializer *tool_initializer;
|
ToolInitializer *tool_initializer;
|
||||||
|
EvidenceListModel *evidence_list_model;
|
||||||
|
EvidenceCategoryModel *evidence_category_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Contexte conservé jusqu’à la fin d’un import.
|
* @brief Contexte ApplicationOpenErrorconservé jusqu’à la fin d’un import.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
@ -390,6 +397,469 @@ static void application_present_error(
|
||||||
const char *message
|
const char *message
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Charge les preuves de la session et construit leurs modèles GTK.
|
||||||
|
*
|
||||||
|
* Les nouveaux modèles sont entièrement préparés avant de remplacer
|
||||||
|
* ceux actuellement affichés.
|
||||||
|
*
|
||||||
|
* En cas d'échec, les anciens modèles restent la propriété de
|
||||||
|
* l'application et ne sont pas modifiés.
|
||||||
|
*/
|
||||||
|
static gboolean application_refresh_evidence_models(
|
||||||
|
Application *application,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Database *database = NULL;
|
||||||
|
|
||||||
|
EvidenceDao *evidence_dao = NULL;
|
||||||
|
EvidenceTypeDao *evidence_type_dao = NULL;
|
||||||
|
|
||||||
|
GPtrArray *evidence_records = NULL;
|
||||||
|
GPtrArray *evidence_types = NULL;
|
||||||
|
|
||||||
|
GHashTable *type_labels = NULL;
|
||||||
|
|
||||||
|
EvidenceListModel *new_evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceCategoryModel *new_evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GError *local_error = NULL;
|
||||||
|
|
||||||
|
guint type_index = 0;
|
||||||
|
|
||||||
|
gboolean refreshed = FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
error == NULL || *error == NULL,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (application == NULL ||
|
||||||
|
application->main_window == NULL ||
|
||||||
|
application->session == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"L'application ou la session d'enquête est invalide."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
database =
|
||||||
|
investigation_session_get_database(
|
||||||
|
application->session
|
||||||
|
);
|
||||||
|
|
||||||
|
if (database == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"La session ne fournit aucune connexion SQLite."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_dao =
|
||||||
|
evidence_dao_new(
|
||||||
|
database,
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_dao == NULL)
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de créer le DAO des preuves : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible de créer le DAO des preuves."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_records =
|
||||||
|
evidence_dao_list_all(
|
||||||
|
evidence_dao,
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_records == NULL)
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de charger les preuves : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible de charger les preuves."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_type_dao =
|
||||||
|
evidence_type_dao_new(
|
||||||
|
database,
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_type_dao == NULL)
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de créer le DAO des types de preuve : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible de créer le DAO des types de preuve."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_types =
|
||||||
|
evidence_type_dao_list_all(
|
||||||
|
evidence_type_dao,
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_types == NULL)
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de charger les types de preuve : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible de charger les types de preuve."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_labels =
|
||||||
|
g_hash_table_new_full(
|
||||||
|
g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
if (type_labels == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible d'allouer la table des libellés."
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (type_index = 0;
|
||||||
|
type_index < evidence_types->len;
|
||||||
|
type_index++)
|
||||||
|
{
|
||||||
|
const EvidenceType *evidence_type =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
const char *type_code = NULL;
|
||||||
|
const char *type_label = NULL;
|
||||||
|
|
||||||
|
evidence_type =
|
||||||
|
g_ptr_array_index(
|
||||||
|
evidence_types,
|
||||||
|
type_index
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_type == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_code =
|
||||||
|
evidence_type_get_code(
|
||||||
|
evidence_type
|
||||||
|
);
|
||||||
|
|
||||||
|
type_label =
|
||||||
|
evidence_type_get_label(
|
||||||
|
evidence_type
|
||||||
|
);
|
||||||
|
|
||||||
|
if (type_code == NULL ||
|
||||||
|
type_code[0] == '\0' ||
|
||||||
|
type_label == NULL ||
|
||||||
|
type_label[0] == '\0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_replace(
|
||||||
|
type_labels,
|
||||||
|
g_strdup(
|
||||||
|
type_code
|
||||||
|
),
|
||||||
|
g_strdup(
|
||||||
|
type_label
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
new_evidence_category_model =
|
||||||
|
evidence_category_model_new();
|
||||||
|
|
||||||
|
if (new_evidence_list_model == NULL ||
|
||||||
|
new_evidence_category_model == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
APPLICATION_OPEN_ERROR,
|
||||||
|
APPLICATION_OPEN_ERROR_EVIDENCE,
|
||||||
|
"Impossible d'allouer les modèles d'affichage des preuves."
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!evidence_list_model_replace(
|
||||||
|
new_evidence_list_model,
|
||||||
|
evidence_records,
|
||||||
|
&local_error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de préparer la liste des preuves : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!evidence_category_model_replace(
|
||||||
|
new_evidence_category_model,
|
||||||
|
evidence_list_model_get_list_model(
|
||||||
|
new_evidence_list_model
|
||||||
|
),
|
||||||
|
type_labels,
|
||||||
|
&local_error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_prefixed_error(
|
||||||
|
error,
|
||||||
|
local_error,
|
||||||
|
"Impossible de regrouper les preuves : "
|
||||||
|
);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La vue doit être détachée avant la libération de son ancien modèle.
|
||||||
|
*/
|
||||||
|
main_window_set_evidence_model(
|
||||||
|
application->main_window,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
application->evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
application->evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
application->evidence_list_model =
|
||||||
|
new_evidence_list_model;
|
||||||
|
|
||||||
|
application->evidence_category_model =
|
||||||
|
new_evidence_category_model;
|
||||||
|
|
||||||
|
new_evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
new_evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
main_window_set_evidence_model(
|
||||||
|
application->main_window,
|
||||||
|
application->evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
refreshed = TRUE;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&local_error
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
new_evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
new_evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
if (type_labels != NULL)
|
||||||
|
{
|
||||||
|
g_hash_table_unref(
|
||||||
|
type_labels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evidence_types != NULL)
|
||||||
|
{
|
||||||
|
g_ptr_array_unref(
|
||||||
|
evidence_types
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evidence_records != NULL)
|
||||||
|
{
|
||||||
|
g_ptr_array_unref(
|
||||||
|
evidence_records
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_type_dao_free(
|
||||||
|
evidence_type_dao
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_dao_free(
|
||||||
|
evidence_dao
|
||||||
|
);
|
||||||
|
|
||||||
|
return refreshed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Installe une nouvelle session et son arbre dans l'application.
|
* @brief Installe une nouvelle session et son arbre dans l'application.
|
||||||
*
|
*
|
||||||
|
|
@ -416,6 +886,8 @@ static gboolean application_install_session(
|
||||||
const char *root_path = NULL;
|
const char *root_path = NULL;
|
||||||
const char *investigation_name = NULL;
|
const char *investigation_name = NULL;
|
||||||
|
|
||||||
|
GError *evidence_error = NULL;
|
||||||
|
|
||||||
if (application == NULL ||
|
if (application == NULL ||
|
||||||
application->main_window == NULL ||
|
application->main_window == NULL ||
|
||||||
new_session == NULL ||
|
new_session == NULL ||
|
||||||
|
|
@ -485,6 +957,54 @@ static gboolean application_install_session(
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L'ancienne liste ne doit jamais rester affichée après
|
||||||
|
* un changement d'enquête.
|
||||||
|
*/
|
||||||
|
main_window_set_evidence_model(
|
||||||
|
application->main_window,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
application->evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
application->evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
application->evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
application->evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (!application_refresh_evidence_models(
|
||||||
|
application,
|
||||||
|
&evidence_error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_warning(
|
||||||
|
"Impossible de charger les preuves de l'enquête : %s",
|
||||||
|
evidence_error != NULL
|
||||||
|
? evidence_error->message
|
||||||
|
: "erreur inconnue"
|
||||||
|
);
|
||||||
|
|
||||||
|
application_present_error(
|
||||||
|
application,
|
||||||
|
"Preuves indisponibles",
|
||||||
|
evidence_error != NULL
|
||||||
|
? evidence_error->message
|
||||||
|
: "Les preuves enregistrées n'ont pas pu être chargées."
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&evidence_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2123,6 +2643,22 @@ void application_free(
|
||||||
application->session
|
application->session
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (application->main_window != NULL)
|
||||||
|
{
|
||||||
|
main_window_set_evidence_model(
|
||||||
|
application->main_window,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
application->evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
application->evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MainWindow contient TaskPanel.
|
* MainWindow contient TaskPanel.
|
||||||
* Il doit être détruit avant TaskManager.
|
* Il doit être détruit avant TaskManager.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Largeur initiale de la fenêtre principale.
|
* @brief Largeur initiale de la fenêtre principale.
|
||||||
*/
|
*/
|
||||||
#define MAIN_WINDOW_DEFAULT_WIDTH 1000
|
#define MAIN_WINDOW_DEFAULT_WIDTH 1100
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Hauteur initiale de la fenêtre principale.
|
* @brief Hauteur initiale de la fenêtre principale.
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Position initiale de la séparation horizontale.
|
* @brief Position initiale de la séparation horizontale.
|
||||||
*/
|
*/
|
||||||
#define MAIN_WINDOW_SIDEBAR_POSITION 250
|
#define MAIN_WINDOW_SIDEBAR_POSITION 320
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Position initiale de la séparation verticale.
|
* @brief Position initiale de la séparation verticale.
|
||||||
|
|
@ -716,6 +716,22 @@ void main_window_set_tree_model(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void main_window_set_evidence_model(
|
||||||
|
MainWindow *main_window,
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar_set_evidence_model(
|
||||||
|
main_window->sidebar,
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main_window_set_investigation(
|
void main_window_set_investigation(
|
||||||
MainWindow *main_window,
|
MainWindow *main_window,
|
||||||
const char *investigation_name,
|
const char *investigation_name,
|
||||||
|
|
@ -848,6 +864,24 @@ void main_window_set_tree_selection_callback(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void main_window_set_evidence_selection_callback(
|
||||||
|
MainWindow *main_window,
|
||||||
|
MainWindowEvidenceSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar_set_evidence_selection_callback(
|
||||||
|
main_window->sidebar,
|
||||||
|
callback,
|
||||||
|
user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main_window_set_new_investigation_callback(
|
void main_window_set_new_investigation_callback(
|
||||||
MainWindow *main_window,
|
MainWindow *main_window,
|
||||||
MainWindowNewInvestigationCallback callback,
|
MainWindowNewInvestigationCallback callback,
|
||||||
|
|
|
||||||
331
src/widgets/evidence_category_item.c
Normal file
331
src/widgets/evidence_category_item.c
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_category_item.c
|
||||||
|
* @brief Implémentation d'une catégorie de preuves affichées.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_item.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État interne de la catégorie.
|
||||||
|
*/
|
||||||
|
struct _EvidenceCategoryItem
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
char *type_identifier;
|
||||||
|
char *label;
|
||||||
|
|
||||||
|
GListStore *children;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(
|
||||||
|
EvidenceCategoryItem,
|
||||||
|
evidence_category_item,
|
||||||
|
G_TYPE_OBJECT
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copie et nettoie une chaîne obligatoire.
|
||||||
|
*/
|
||||||
|
static char *evidence_category_item_duplicate_required_text(
|
||||||
|
const char *value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char *normalized_value = NULL;
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized_value =
|
||||||
|
g_strdup(
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (normalized_value == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strstrip(
|
||||||
|
normalized_value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (normalized_value[0] == '\0')
|
||||||
|
{
|
||||||
|
g_free(
|
||||||
|
normalized_value
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère les ressources possédées par la catégorie.
|
||||||
|
*/
|
||||||
|
static void evidence_category_item_finalize(
|
||||||
|
GObject *object
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
EVIDENCE_CATEGORY_ITEM(
|
||||||
|
object
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_category_item->type_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_category_item->label,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_category_item->children
|
||||||
|
);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS(
|
||||||
|
evidence_category_item_parent_class
|
||||||
|
)->finalize(
|
||||||
|
object
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise la classe GObject.
|
||||||
|
*/
|
||||||
|
static void evidence_category_item_class_init(
|
||||||
|
EvidenceCategoryItemClass *evidence_category_item_class
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class =
|
||||||
|
G_OBJECT_CLASS(
|
||||||
|
evidence_category_item_class
|
||||||
|
);
|
||||||
|
|
||||||
|
object_class->finalize =
|
||||||
|
evidence_category_item_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise une catégorie vide.
|
||||||
|
*/
|
||||||
|
static void evidence_category_item_init(
|
||||||
|
EvidenceCategoryItem *evidence_category_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
evidence_category_item->children =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidenceCategoryItem *evidence_category_item_new(
|
||||||
|
const char *type_identifier,
|
||||||
|
const char *label
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
char *normalized_type_identifier =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
char *normalized_label =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
normalized_type_identifier =
|
||||||
|
evidence_category_item_duplicate_required_text(
|
||||||
|
type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
normalized_label =
|
||||||
|
evidence_category_item_duplicate_required_text(
|
||||||
|
label
|
||||||
|
);
|
||||||
|
|
||||||
|
if (normalized_type_identifier == NULL ||
|
||||||
|
normalized_label == NULL)
|
||||||
|
{
|
||||||
|
g_free(
|
||||||
|
normalized_label
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
normalized_type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
g_object_new(
|
||||||
|
EVIDENCE_TYPE_CATEGORY_ITEM,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_item == NULL ||
|
||||||
|
evidence_category_item->children == NULL)
|
||||||
|
{
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
normalized_label
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
normalized_type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_item->type_identifier =
|
||||||
|
normalized_type_identifier;
|
||||||
|
|
||||||
|
evidence_category_item->label =
|
||||||
|
normalized_label;
|
||||||
|
|
||||||
|
return evidence_category_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare deux preuves par nom original puis par identifiant.
|
||||||
|
*/
|
||||||
|
static gint evidence_category_item_compare_list_items(
|
||||||
|
gconstpointer first_pointer,
|
||||||
|
gconstpointer second_pointer,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const EvidenceListItem *first_item =
|
||||||
|
first_pointer;
|
||||||
|
|
||||||
|
const EvidenceListItem *second_item =
|
||||||
|
second_pointer;
|
||||||
|
|
||||||
|
const char *first_name = NULL;
|
||||||
|
const char *second_name = NULL;
|
||||||
|
|
||||||
|
gint comparison = 0;
|
||||||
|
|
||||||
|
(void) user_data;
|
||||||
|
|
||||||
|
first_name =
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
first_item
|
||||||
|
);
|
||||||
|
|
||||||
|
second_name =
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
second_item
|
||||||
|
);
|
||||||
|
|
||||||
|
comparison =
|
||||||
|
g_utf8_collate(
|
||||||
|
first_name,
|
||||||
|
second_name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (comparison != 0)
|
||||||
|
{
|
||||||
|
return comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_strcmp0(
|
||||||
|
evidence_list_item_get_identifier(
|
||||||
|
first_item
|
||||||
|
),
|
||||||
|
evidence_list_item_get_identifier(
|
||||||
|
second_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean evidence_category_item_append(
|
||||||
|
EvidenceCategoryItem *evidence_category_item,
|
||||||
|
EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_item == NULL ||
|
||||||
|
evidence_category_item->children == NULL ||
|
||||||
|
evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_store_insert_sorted(
|
||||||
|
evidence_category_item->children,
|
||||||
|
G_OBJECT(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
evidence_category_item_compare_list_items,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_category_item_get_type_identifier(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_category_item->type_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_category_item_get_label(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_category_item->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint evidence_category_item_get_count(
|
||||||
|
const EvidenceCategoryItem *evidence_category_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_item == NULL ||
|
||||||
|
evidence_category_item->children == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_category_item->children
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GListModel *evidence_category_item_get_children(
|
||||||
|
EvidenceCategoryItem *evidence_category_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_item == NULL ||
|
||||||
|
evidence_category_item->children == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_LIST_MODEL(
|
||||||
|
evidence_category_item->children
|
||||||
|
);
|
||||||
|
}
|
||||||
548
src/widgets/evidence_category_model.c
Normal file
548
src/widgets/evidence_category_model.c
Normal file
|
|
@ -0,0 +1,548 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_category_model.c
|
||||||
|
* @brief Regroupement des preuves par catégorie pour l'affichage GTK.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_item.h"
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État interne du modèle.
|
||||||
|
*/
|
||||||
|
struct EvidenceCategoryModel
|
||||||
|
{
|
||||||
|
GListStore *categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark evidence_category_model_error_quark(void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string(
|
||||||
|
"labfy-investigation-evidence-category-model-error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare deux catégories par libellé puis par code métier.
|
||||||
|
*/
|
||||||
|
static gint evidence_category_model_compare_categories(
|
||||||
|
gconstpointer first_pointer,
|
||||||
|
gconstpointer second_pointer,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const EvidenceCategoryItem *first_category =
|
||||||
|
first_pointer;
|
||||||
|
|
||||||
|
const EvidenceCategoryItem *second_category =
|
||||||
|
second_pointer;
|
||||||
|
|
||||||
|
const char *first_label = NULL;
|
||||||
|
const char *second_label = NULL;
|
||||||
|
|
||||||
|
gint comparison = 0;
|
||||||
|
|
||||||
|
(void) user_data;
|
||||||
|
|
||||||
|
first_label =
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
first_category
|
||||||
|
);
|
||||||
|
|
||||||
|
second_label =
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
second_category
|
||||||
|
);
|
||||||
|
|
||||||
|
comparison =
|
||||||
|
g_utf8_collate(
|
||||||
|
first_label,
|
||||||
|
second_label
|
||||||
|
);
|
||||||
|
|
||||||
|
if (comparison != 0)
|
||||||
|
{
|
||||||
|
return comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_strcmp0(
|
||||||
|
evidence_category_item_get_type_identifier(
|
||||||
|
first_category
|
||||||
|
),
|
||||||
|
evidence_category_item_get_type_identifier(
|
||||||
|
second_category
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie qu'une chaîne obligatoire contient du texte.
|
||||||
|
*/
|
||||||
|
static gboolean evidence_category_model_value_has_text(
|
||||||
|
const char *value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return value != NULL &&
|
||||||
|
value[0] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère les références temporaires d'un tableau d'ajouts.
|
||||||
|
*/
|
||||||
|
static void evidence_category_model_release_additions(
|
||||||
|
gpointer *additions,
|
||||||
|
guint addition_count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
guint addition_index = 0;
|
||||||
|
|
||||||
|
if (additions == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (addition_index = 0;
|
||||||
|
addition_index < addition_count;
|
||||||
|
addition_index++)
|
||||||
|
{
|
||||||
|
g_clear_object(
|
||||||
|
&additions[addition_index]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
additions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidenceCategoryModel *evidence_category_model_new(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryModel *evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_model =
|
||||||
|
g_try_new0(
|
||||||
|
EvidenceCategoryModel,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_model == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_model->categories =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_CATEGORY_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_model->categories == NULL)
|
||||||
|
{
|
||||||
|
g_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_category_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void evidence_category_model_free(
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_model == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_category_model->categories
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GListModel *evidence_category_model_get_list_model(
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_model == NULL ||
|
||||||
|
evidence_category_model->categories == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_LIST_MODEL(
|
||||||
|
evidence_category_model->categories
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint evidence_category_model_get_count(
|
||||||
|
const EvidenceCategoryModel *evidence_category_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_category_model == NULL ||
|
||||||
|
evidence_category_model->categories == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_category_model->categories
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean evidence_category_model_replace(
|
||||||
|
EvidenceCategoryModel *evidence_category_model,
|
||||||
|
GListModel *evidence_items,
|
||||||
|
GHashTable *type_labels,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GListStore *new_categories = NULL;
|
||||||
|
|
||||||
|
GHashTable *categories_by_type =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *evidence_list_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
gpointer *additions = NULL;
|
||||||
|
|
||||||
|
const char *type_identifier = NULL;
|
||||||
|
const char *category_label = NULL;
|
||||||
|
|
||||||
|
guint evidence_count = 0;
|
||||||
|
guint evidence_index = 0;
|
||||||
|
|
||||||
|
guint new_category_count = 0;
|
||||||
|
guint category_index = 0;
|
||||||
|
guint previous_category_count = 0;
|
||||||
|
|
||||||
|
gboolean replaced = FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
error == NULL || *error == NULL,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_model == NULL ||
|
||||||
|
evidence_category_model->categories == NULL ||
|
||||||
|
evidence_items == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Le modèle de catégories ou la liste de preuves est invalide."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_type_is_a(
|
||||||
|
g_list_model_get_item_type(
|
||||||
|
evidence_items
|
||||||
|
),
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Le modèle fourni ne contient pas des EvidenceListItem."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_categories =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_CATEGORY_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
categories_by_type =
|
||||||
|
g_hash_table_new_full(
|
||||||
|
g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (new_categories == NULL ||
|
||||||
|
categories_by_type == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_MEMORY,
|
||||||
|
"Impossible de préparer le regroupement des preuves."
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_count =
|
||||||
|
g_list_model_get_n_items(
|
||||||
|
evidence_items
|
||||||
|
);
|
||||||
|
|
||||||
|
for (evidence_index = 0;
|
||||||
|
evidence_index < evidence_count;
|
||||||
|
evidence_index++)
|
||||||
|
{
|
||||||
|
evidence_list_item =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_items,
|
||||||
|
evidence_index
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_item == NULL ||
|
||||||
|
!EVIDENCE_IS_LIST_ITEM(
|
||||||
|
evidence_list_item
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ITEM,
|
||||||
|
"La preuve située à l'index %u est invalide.",
|
||||||
|
evidence_index
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_identifier =
|
||||||
|
evidence_list_item_get_type_identifier(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!evidence_category_model_value_has_text(
|
||||||
|
type_identifier
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ITEM,
|
||||||
|
"La preuve située à l'index %u ne possède aucun type.",
|
||||||
|
evidence_index
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
g_hash_table_lookup(
|
||||||
|
categories_by_type,
|
||||||
|
type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_item == NULL)
|
||||||
|
{
|
||||||
|
category_label = NULL;
|
||||||
|
|
||||||
|
if (type_labels != NULL)
|
||||||
|
{
|
||||||
|
category_label =
|
||||||
|
g_hash_table_lookup(
|
||||||
|
type_labels,
|
||||||
|
type_identifier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Un type inconnu reste affichable.
|
||||||
|
* Son code métier devient son libellé de secours.
|
||||||
|
*/
|
||||||
|
if (!evidence_category_model_value_has_text(
|
||||||
|
category_label
|
||||||
|
))
|
||||||
|
{
|
||||||
|
category_label =
|
||||||
|
type_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
evidence_category_item_new(
|
||||||
|
type_identifier,
|
||||||
|
category_label
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_item == NULL)
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_CATEGORY,
|
||||||
|
"Impossible de créer la catégorie '%s'.",
|
||||||
|
type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_store_insert_sorted(
|
||||||
|
new_categories,
|
||||||
|
G_OBJECT(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
evidence_category_model_compare_categories,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La table emprunte le pointeur.
|
||||||
|
* Le GListStore possède la référence.
|
||||||
|
*/
|
||||||
|
g_hash_table_insert(
|
||||||
|
categories_by_type,
|
||||||
|
g_strdup(
|
||||||
|
type_identifier
|
||||||
|
),
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!evidence_category_item_append(
|
||||||
|
evidence_category_item,
|
||||||
|
evidence_list_item
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_CATEGORY,
|
||||||
|
"Impossible d'ajouter la preuve %u à sa catégorie.",
|
||||||
|
evidence_index
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_category_count =
|
||||||
|
g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
new_categories
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
previous_category_count =
|
||||||
|
g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_category_model->categories
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (new_category_count == 0)
|
||||||
|
{
|
||||||
|
g_list_store_remove_all(
|
||||||
|
evidence_category_model->categories
|
||||||
|
);
|
||||||
|
|
||||||
|
replaced = TRUE;
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
additions =
|
||||||
|
g_try_new0(
|
||||||
|
gpointer,
|
||||||
|
new_category_count
|
||||||
|
);
|
||||||
|
|
||||||
|
if (additions == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_MEMORY,
|
||||||
|
"Impossible de préparer le remplacement des catégories."
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (category_index = 0;
|
||||||
|
category_index < new_category_count;
|
||||||
|
category_index++)
|
||||||
|
{
|
||||||
|
additions[category_index] =
|
||||||
|
g_list_model_get_item(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
new_categories
|
||||||
|
),
|
||||||
|
category_index
|
||||||
|
);
|
||||||
|
|
||||||
|
if (additions[category_index] == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_CATEGORY,
|
||||||
|
"Impossible de lire une catégorie préparée."
|
||||||
|
);
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_store_splice(
|
||||||
|
evidence_category_model->categories,
|
||||||
|
0,
|
||||||
|
previous_category_count,
|
||||||
|
additions,
|
||||||
|
new_category_count
|
||||||
|
);
|
||||||
|
|
||||||
|
replaced = TRUE;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_release_additions(
|
||||||
|
additions,
|
||||||
|
new_category_count
|
||||||
|
);
|
||||||
|
|
||||||
|
if (categories_by_type != NULL)
|
||||||
|
{
|
||||||
|
g_hash_table_unref(
|
||||||
|
categories_by_type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&new_categories
|
||||||
|
);
|
||||||
|
|
||||||
|
return replaced;
|
||||||
|
}
|
||||||
315
src/widgets/evidence_list_item.c
Normal file
315
src/widgets/evidence_list_item.c
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_list_item.c
|
||||||
|
* @brief Implémentation de EvidenceListItem.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Données privées copiées pour l'affichage GTK.
|
||||||
|
*/
|
||||||
|
struct _EvidenceListItem
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
char *identifier;
|
||||||
|
char *original_name;
|
||||||
|
char *type_identifier;
|
||||||
|
guint64 size_bytes;
|
||||||
|
char *collected_at;
|
||||||
|
char *source;
|
||||||
|
|
||||||
|
EvidenceIntegrityStatus integrity_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(
|
||||||
|
EvidenceListItem,
|
||||||
|
evidence_list_item,
|
||||||
|
G_TYPE_OBJECT
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère les données possédées par l'objet.
|
||||||
|
*/
|
||||||
|
static void evidence_list_item_finalize(
|
||||||
|
GObject *object
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceListItem *evidence_list_item =
|
||||||
|
EVIDENCE_LIST_ITEM(
|
||||||
|
object
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_list_item->original_name,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_list_item->type_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_list_item->collected_at,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&evidence_list_item->source,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS(
|
||||||
|
evidence_list_item_parent_class
|
||||||
|
)->finalize(
|
||||||
|
object
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise la classe GObject.
|
||||||
|
*/
|
||||||
|
static void evidence_list_item_class_init(
|
||||||
|
EvidenceListItemClass *evidence_list_item_class
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class =
|
||||||
|
G_OBJECT_CLASS(
|
||||||
|
evidence_list_item_class
|
||||||
|
);
|
||||||
|
|
||||||
|
object_class->finalize =
|
||||||
|
evidence_list_item_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise une nouvelle instance vide.
|
||||||
|
*/
|
||||||
|
static void evidence_list_item_init(
|
||||||
|
EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
evidence_list_item->integrity_status =
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidenceListItem *evidence_list_item_new(
|
||||||
|
const EvidenceRecord *evidence_record
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
const char *identifier = NULL;
|
||||||
|
const char *original_name = NULL;
|
||||||
|
const char *type_identifier = NULL;
|
||||||
|
|
||||||
|
if (evidence_record == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier =
|
||||||
|
evidence_record_get_identifier(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
original_name =
|
||||||
|
evidence_record_get_original_name(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
type_identifier =
|
||||||
|
evidence_record_get_type_identifier(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ces deux valeurs sont obligatoires dans EvidenceRecord.
|
||||||
|
* Cette vérification protège néanmoins l'adaptateur d'affichage.
|
||||||
|
*/
|
||||||
|
if (identifier == NULL ||
|
||||||
|
original_name == NULL ||
|
||||||
|
original_name[0] == '\0' ||
|
||||||
|
type_identifier == NULL ||
|
||||||
|
type_identifier[0] == '\0')
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
g_object_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->identifier =
|
||||||
|
g_strdup(
|
||||||
|
identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_list_item->original_name =
|
||||||
|
g_strdup(
|
||||||
|
original_name
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->type_identifier =
|
||||||
|
g_strdup(
|
||||||
|
type_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->size_bytes =
|
||||||
|
evidence_record_get_size_bytes(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->collected_at =
|
||||||
|
g_strdup(
|
||||||
|
evidence_record_get_collected_at(
|
||||||
|
evidence_record
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->source =
|
||||||
|
g_strdup(
|
||||||
|
evidence_record_get_source(
|
||||||
|
evidence_record
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item->integrity_status =
|
||||||
|
evidence_record_get_integrity_status(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_item->identifier == NULL ||
|
||||||
|
evidence_list_item->original_name == NULL ||
|
||||||
|
evidence_list_item->type_identifier == NULL)
|
||||||
|
{
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_identifier(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_original_name(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->original_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_type_identifier(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->type_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint64 evidence_list_item_get_size_bytes(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->size_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_collected_at(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->collected_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_source(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->source;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidenceIntegrityStatus evidence_list_item_get_integrity_status(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
return EVIDENCE_INTEGRITY_STATUS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_item->integrity_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *evidence_list_item_get_integrity_status_label(
|
||||||
|
const EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceIntegrityStatus integrity_status =
|
||||||
|
evidence_list_item_get_integrity_status(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (integrity_status)
|
||||||
|
{
|
||||||
|
case EVIDENCE_INTEGRITY_STATUS_VALID:
|
||||||
|
return "Valide";
|
||||||
|
|
||||||
|
case EVIDENCE_INTEGRITY_STATUS_MISSING:
|
||||||
|
return "Fichier absent";
|
||||||
|
|
||||||
|
case EVIDENCE_INTEGRITY_STATUS_MODIFIED:
|
||||||
|
return "Modifiée";
|
||||||
|
|
||||||
|
case EVIDENCE_INTEGRITY_STATUS_ERROR:
|
||||||
|
return "Erreur";
|
||||||
|
|
||||||
|
case EVIDENCE_INTEGRITY_STATUS_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return "Non vérifiée";
|
||||||
|
}
|
||||||
|
}
|
||||||
239
src/widgets/evidence_list_model.c
Normal file
239
src/widgets/evidence_list_model.c
Normal file
|
|
@ -0,0 +1,239 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file evidence_list_model.c
|
||||||
|
* @brief Implémentation du modèle de liste des preuves.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_model.h"
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État interne du modèle de liste.
|
||||||
|
*/
|
||||||
|
struct EvidenceListModel
|
||||||
|
{
|
||||||
|
GListStore *items;
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark evidence_list_model_error_quark(void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string(
|
||||||
|
"labfy-investigation-evidence-list-model-error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidenceListModel *evidence_list_model_new(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
g_try_new0(
|
||||||
|
EvidenceListModel,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_model == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_list_model->items =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_model->items == NULL)
|
||||||
|
{
|
||||||
|
g_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evidence_list_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void evidence_list_model_free(
|
||||||
|
EvidenceListModel *evidence_list_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_model == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_list_model->items
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GListModel *evidence_list_model_get_list_model(
|
||||||
|
EvidenceListModel *evidence_list_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_model == NULL ||
|
||||||
|
evidence_list_model->items == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_LIST_MODEL(
|
||||||
|
evidence_list_model->items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint evidence_list_model_get_count(
|
||||||
|
const EvidenceListModel *evidence_list_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (evidence_list_model == NULL ||
|
||||||
|
evidence_list_model->items == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_list_model->items
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean evidence_list_model_replace(
|
||||||
|
EvidenceListModel *evidence_list_model,
|
||||||
|
const GPtrArray *evidence_records,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GPtrArray *new_items = NULL;
|
||||||
|
|
||||||
|
guint record_index = 0;
|
||||||
|
guint previous_count = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
error == NULL || *error == NULL,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_model == NULL ||
|
||||||
|
evidence_list_model->items == NULL ||
|
||||||
|
evidence_records == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Le modèle ou le tableau de preuves est invalide."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Le tableau libère notre référence locale sur chaque objet.
|
||||||
|
* GListStore prendra ensuite sa propre référence lors du splice.
|
||||||
|
*/
|
||||||
|
new_items =
|
||||||
|
g_ptr_array_new_with_free_func(
|
||||||
|
g_object_unref
|
||||||
|
);
|
||||||
|
|
||||||
|
if (new_items == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_MEMORY,
|
||||||
|
"Impossible d'allouer la nouvelle liste de preuves."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (record_index = 0;
|
||||||
|
record_index < evidence_records->len;
|
||||||
|
record_index++)
|
||||||
|
{
|
||||||
|
const EvidenceRecord *evidence_record =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *evidence_list_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
g_ptr_array_index(
|
||||||
|
evidence_records,
|
||||||
|
record_index
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_list_item == NULL)
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_RECORD,
|
||||||
|
"La preuve située à l'index %u est invalide.",
|
||||||
|
record_index
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
new_items
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
new_items,
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_count =
|
||||||
|
g_list_model_get_n_items(
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_list_model->items
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (new_items->len == 0)
|
||||||
|
{
|
||||||
|
g_list_store_remove_all(
|
||||||
|
evidence_list_model->items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Tous les éléments sont prêts.
|
||||||
|
* Le remplacement peut maintenant être effectué en une opération.
|
||||||
|
*/
|
||||||
|
g_list_store_splice(
|
||||||
|
evidence_list_model->items,
|
||||||
|
0,
|
||||||
|
previous_count,
|
||||||
|
new_items->pdata,
|
||||||
|
new_items->len
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GListStore possède désormais une référence sur chaque élément.
|
||||||
|
*/
|
||||||
|
g_ptr_array_unref(
|
||||||
|
new_items
|
||||||
|
);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
1027
src/widgets/evidence_tree_view.c
Normal file
1027
src/widgets/evidence_tree_view.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,13 +6,38 @@
|
||||||
#include "widgets/sidebar.h"
|
#include "widgets/sidebar.h"
|
||||||
#include "core/investigation_node.h"
|
#include "core/investigation_node.h"
|
||||||
#include "widgets/investigation_tree_view.h"
|
#include "widgets/investigation_tree_view.h"
|
||||||
|
#include "widgets/evidence_tree_view.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Largeur initiale du panneau latéral.
|
* @brief Largeur initiale du panneau latéral.
|
||||||
*/
|
*/
|
||||||
#define SIDEBAR_DEFAULT_WIDTH 250
|
#define SIDEBAR_DEFAULT_WIDTH 320
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identifiant de la page contenant l'arborescence.
|
||||||
|
*/
|
||||||
|
#define SIDEBAR_PAGE_FOLDER \
|
||||||
|
"folder"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identifiant de la page contenant les preuves.
|
||||||
|
*/
|
||||||
|
#define SIDEBAR_PAGE_EVIDENCE \
|
||||||
|
"evidence"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État vide de l'onglet Preuves.
|
||||||
|
*/
|
||||||
|
#define SIDEBAR_EVIDENCE_STATE_EMPTY \
|
||||||
|
"empty"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État contenant l'arbre des preuves.
|
||||||
|
*/
|
||||||
|
#define SIDEBAR_EVIDENCE_STATE_TREE \
|
||||||
|
"tree"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct Sidebar
|
* @struct Sidebar
|
||||||
|
|
@ -25,23 +50,74 @@ struct Sidebar
|
||||||
{
|
{
|
||||||
GtkWidget *root_widget;
|
GtkWidget *root_widget;
|
||||||
GtkWidget *title_label;
|
GtkWidget *title_label;
|
||||||
|
|
||||||
|
GtkWidget *page_switcher;
|
||||||
|
GtkWidget *stack;
|
||||||
|
|
||||||
|
GtkWidget *folder_page;
|
||||||
|
|
||||||
|
GtkWidget *evidence_page;
|
||||||
|
GtkWidget *evidence_content_stack;
|
||||||
|
GtkWidget *evidence_empty_page;
|
||||||
|
GtkWidget *evidence_empty_label;
|
||||||
|
|
||||||
InvestigationTreeView *tree_view;
|
InvestigationTreeView *tree_view;
|
||||||
|
EvidenceTreeView *evidence_tree_view;
|
||||||
|
|
||||||
|
SidebarEvidenceSelectionCallback
|
||||||
|
evidence_selection_callback;
|
||||||
|
|
||||||
|
gpointer evidence_selection_user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Relaie la sélection provenant de EvidenceTreeView.
|
||||||
|
*/
|
||||||
|
static void sidebar_on_evidence_selected(
|
||||||
|
const char *evidence_identifier,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Sidebar *sidebar =
|
||||||
|
user_data;
|
||||||
|
|
||||||
|
if (sidebar == NULL ||
|
||||||
|
sidebar->evidence_selection_callback == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar->evidence_selection_callback(
|
||||||
|
evidence_identifier,
|
||||||
|
sidebar->evidence_selection_user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Sidebar *sidebar_new(void)
|
Sidebar *sidebar_new(void)
|
||||||
{
|
{
|
||||||
Sidebar *sidebar = NULL;
|
Sidebar *sidebar = NULL;
|
||||||
sidebar = g_new0(Sidebar, 1);
|
|
||||||
GtkWidget *tree_view_widget = NULL;
|
|
||||||
|
|
||||||
sidebar->root_widget = gtk_box_new(
|
GtkWidget *tree_view_widget = NULL;
|
||||||
|
GtkWidget *evidence_tree_widget = NULL;
|
||||||
|
|
||||||
|
sidebar =
|
||||||
|
g_new0(
|
||||||
|
Sidebar,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
sidebar->root_widget =
|
||||||
|
gtk_box_new(
|
||||||
GTK_ORIENTATION_VERTICAL,
|
GTK_ORIENTATION_VERTICAL,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (sidebar->root_widget == NULL)
|
if (sidebar->root_widget == NULL)
|
||||||
{
|
{
|
||||||
sidebar_free(sidebar);
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,10 +127,23 @@ Sidebar *sidebar_new(void)
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
|
|
||||||
sidebar->title_label = gtk_label_new(
|
/*
|
||||||
|
* Titre de l'enquête active.
|
||||||
|
*/
|
||||||
|
sidebar->title_label =
|
||||||
|
gtk_label_new(
|
||||||
"Dossier d'enquête"
|
"Dossier d'enquête"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (sidebar->title_label == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_widget_set_halign(
|
gtk_widget_set_halign(
|
||||||
sidebar->title_label,
|
sidebar->title_label,
|
||||||
GTK_ALIGN_START
|
GTK_ALIGN_START
|
||||||
|
|
@ -77,29 +166,155 @@ Sidebar *sidebar_new(void)
|
||||||
|
|
||||||
gtk_widget_set_margin_bottom(
|
gtk_widget_set_margin_bottom(
|
||||||
sidebar->title_label,
|
sidebar->title_label,
|
||||||
12
|
8
|
||||||
);
|
);
|
||||||
|
|
||||||
gtk_box_append(
|
gtk_box_append(
|
||||||
GTK_BOX(sidebar->root_widget),
|
GTK_BOX(
|
||||||
|
sidebar->root_widget
|
||||||
|
),
|
||||||
sidebar->title_label
|
sidebar->title_label
|
||||||
);
|
);
|
||||||
|
|
||||||
sidebar->tree_view = investigation_tree_view_new();
|
/*
|
||||||
|
* GtkStack contenant les pages Dossier et Preuves.
|
||||||
|
*/
|
||||||
|
sidebar->stack =
|
||||||
|
gtk_stack_new();
|
||||||
|
|
||||||
if (sidebar->tree_view == NULL)
|
if (sidebar->stack == NULL)
|
||||||
{
|
{
|
||||||
sidebar_free(sidebar);
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_view_widget = investigation_tree_view_get_widget(
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->stack,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->stack,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_set_transition_type(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->stack
|
||||||
|
),
|
||||||
|
GTK_STACK_TRANSITION_TYPE_CROSSFADE
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boutons permettant de sélectionner une page du GtkStack.
|
||||||
|
*/
|
||||||
|
sidebar->page_switcher =
|
||||||
|
gtk_stack_switcher_new();
|
||||||
|
|
||||||
|
if (sidebar->page_switcher == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_stack_switcher_set_stack(
|
||||||
|
GTK_STACK_SWITCHER(
|
||||||
|
sidebar->page_switcher
|
||||||
|
),
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->stack
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->page_switcher,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_halign(
|
||||||
|
sidebar->page_switcher,
|
||||||
|
GTK_ALIGN_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_margin_start(
|
||||||
|
sidebar->page_switcher,
|
||||||
|
8
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_margin_end(
|
||||||
|
sidebar->page_switcher,
|
||||||
|
8
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_margin_bottom(
|
||||||
|
sidebar->page_switcher,
|
||||||
|
8
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
sidebar->root_widget
|
||||||
|
),
|
||||||
|
sidebar->page_switcher
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page Dossier.
|
||||||
|
*/
|
||||||
|
sidebar->folder_page =
|
||||||
|
gtk_box_new(
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sidebar->folder_page == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->folder_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->folder_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
sidebar->tree_view =
|
||||||
|
investigation_tree_view_new();
|
||||||
|
|
||||||
|
if (sidebar->tree_view == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_view_widget =
|
||||||
|
investigation_tree_view_get_widget(
|
||||||
sidebar->tree_view
|
sidebar->tree_view
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tree_view_widget == NULL)
|
if (tree_view_widget == NULL)
|
||||||
{
|
{
|
||||||
sidebar_free(sidebar);
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,10 +329,279 @@ Sidebar *sidebar_new(void)
|
||||||
);
|
);
|
||||||
|
|
||||||
gtk_box_append(
|
gtk_box_append(
|
||||||
GTK_BOX(sidebar->root_widget),
|
GTK_BOX(
|
||||||
|
sidebar->folder_page
|
||||||
|
),
|
||||||
tree_view_widget
|
tree_view_widget
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gtk_stack_add_titled(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->stack
|
||||||
|
),
|
||||||
|
sidebar->folder_page,
|
||||||
|
SIDEBAR_PAGE_FOLDER,
|
||||||
|
"Dossier"
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page Preuves.
|
||||||
|
*/
|
||||||
|
sidebar->evidence_page =
|
||||||
|
gtk_box_new(
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sidebar->evidence_page == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->evidence_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->evidence_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack interne alternant entre l'état vide
|
||||||
|
* et l'arborescence des preuves.
|
||||||
|
*/
|
||||||
|
sidebar->evidence_content_stack =
|
||||||
|
gtk_stack_new();
|
||||||
|
|
||||||
|
if (sidebar->evidence_content_stack == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->evidence_content_stack,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->evidence_content_stack,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_set_transition_type(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
GTK_STACK_TRANSITION_TYPE_CROSSFADE
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* État vide.
|
||||||
|
*/
|
||||||
|
sidebar->evidence_empty_page =
|
||||||
|
gtk_box_new(
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sidebar->evidence_empty_page == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->evidence_empty_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->evidence_empty_page,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
sidebar->evidence_empty_label =
|
||||||
|
gtk_label_new(
|
||||||
|
"Aucune preuve importée dans cette enquête."
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sidebar->evidence_empty_label == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_label_set_wrap(
|
||||||
|
GTK_LABEL(
|
||||||
|
sidebar->evidence_empty_label
|
||||||
|
),
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_justify(
|
||||||
|
GTK_LABEL(
|
||||||
|
sidebar->evidence_empty_label
|
||||||
|
),
|
||||||
|
GTK_JUSTIFY_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_halign(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
GTK_ALIGN_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_valign(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
GTK_ALIGN_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_margin_start(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
20
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_margin_end(
|
||||||
|
sidebar->evidence_empty_label,
|
||||||
|
20
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
sidebar->evidence_empty_page
|
||||||
|
),
|
||||||
|
sidebar->evidence_empty_label
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_add_named(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
sidebar->evidence_empty_page,
|
||||||
|
SIDEBAR_EVIDENCE_STATE_EMPTY
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arborescence des catégories et preuves.
|
||||||
|
*/
|
||||||
|
sidebar->evidence_tree_view =
|
||||||
|
evidence_tree_view_new();
|
||||||
|
|
||||||
|
if (sidebar->evidence_tree_view == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_tree_widget =
|
||||||
|
evidence_tree_view_get_widget(
|
||||||
|
sidebar->evidence_tree_view
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_tree_widget == NULL)
|
||||||
|
{
|
||||||
|
sidebar_free(
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(
|
||||||
|
evidence_tree_widget,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_vexpand(
|
||||||
|
evidence_tree_widget,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_tree_view_set_selection_callback(
|
||||||
|
sidebar->evidence_tree_view,
|
||||||
|
sidebar_on_evidence_selected,
|
||||||
|
sidebar
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_add_named(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
evidence_tree_widget,
|
||||||
|
SIDEBAR_EVIDENCE_STATE_TREE
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Aucun modèle n'est encore installé.
|
||||||
|
*/
|
||||||
|
gtk_stack_set_visible_child_name(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
SIDEBAR_EVIDENCE_STATE_EMPTY
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
sidebar->evidence_page
|
||||||
|
),
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_add_titled(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->stack
|
||||||
|
),
|
||||||
|
sidebar->evidence_page,
|
||||||
|
SIDEBAR_PAGE_EVIDENCE,
|
||||||
|
"Preuves"
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L'onglet Dossier reste sélectionné au démarrage.
|
||||||
|
*/
|
||||||
|
gtk_stack_set_visible_child_name(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->stack
|
||||||
|
),
|
||||||
|
SIDEBAR_PAGE_FOLDER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
sidebar->root_widget
|
||||||
|
),
|
||||||
|
sidebar->stack
|
||||||
|
);
|
||||||
|
|
||||||
return sidebar;
|
return sidebar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,6 +693,64 @@ void sidebar_set_selection_callback(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sidebar_set_evidence_model(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
EvidenceCategoryModel *evidence_category_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sidebar == NULL ||
|
||||||
|
sidebar->evidence_tree_view == NULL ||
|
||||||
|
sidebar->evidence_content_stack == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
evidence_tree_view_set_model(
|
||||||
|
sidebar->evidence_tree_view,
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evidence_category_model == NULL ||
|
||||||
|
evidence_category_model_get_count(
|
||||||
|
evidence_category_model
|
||||||
|
) == 0)
|
||||||
|
{
|
||||||
|
gtk_stack_set_visible_child_name(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
SIDEBAR_EVIDENCE_STATE_EMPTY
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_stack_set_visible_child_name(
|
||||||
|
GTK_STACK(
|
||||||
|
sidebar->evidence_content_stack
|
||||||
|
),
|
||||||
|
SIDEBAR_EVIDENCE_STATE_TREE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sidebar_set_evidence_selection_callback(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
SidebarEvidenceSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sidebar == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar->evidence_selection_callback =
|
||||||
|
callback;
|
||||||
|
|
||||||
|
sidebar->evidence_selection_user_data =
|
||||||
|
user_data;
|
||||||
|
}
|
||||||
|
|
||||||
void sidebar_free(Sidebar *sidebar)
|
void sidebar_free(Sidebar *sidebar)
|
||||||
{
|
{
|
||||||
if (sidebar == NULL)
|
if (sidebar == NULL)
|
||||||
|
|
@ -218,6 +760,19 @@ void sidebar_free(Sidebar *sidebar)
|
||||||
|
|
||||||
investigation_tree_view_free(sidebar->tree_view);
|
investigation_tree_view_free(sidebar->tree_view);
|
||||||
|
|
||||||
|
if (sidebar->evidence_tree_view != NULL)
|
||||||
|
{
|
||||||
|
evidence_tree_view_set_selection_callback(
|
||||||
|
sidebar->evidence_tree_view,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_tree_view_free(
|
||||||
|
sidebar->evidence_tree_view
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Les widgets GTK sont intégrés dans l'arbre de widgets de la fenêtre.
|
* Les widgets GTK sont intégrés dans l'arbre de widgets de la fenêtre.
|
||||||
* GTK gère leur destruction lorsque la fenêtre est détruite.
|
* GTK gère leur destruction lorsque la fenêtre est détruite.
|
||||||
|
|
|
||||||
332
tests/test_evidence_category_item.c
Normal file
332
tests/test_evidence_category_item.c
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_evidence_category_item.c
|
||||||
|
* @brief Tests unitaires de EvidenceCategoryItem.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_item.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée une preuve métier valide.
|
||||||
|
*/
|
||||||
|
static EvidenceRecord *test_evidence_category_item_create_record(void)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
evidence_record_new(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"capture-instagram.png",
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000.png",
|
||||||
|
"01_Preuves_Originales/Documents/"
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000.png",
|
||||||
|
"image",
|
||||||
|
4096,
|
||||||
|
"00000000000000000000000000000000"
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"2026-07-20T07:16:01Z",
|
||||||
|
"2026-07-19T18:30:00Z",
|
||||||
|
"Conversation Instagram",
|
||||||
|
"Capture d'écran reçue.",
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN,
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_no_error(
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
return evidence_record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie la création d'une catégorie vide.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_item_new_valid(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
evidence_category_item_new(
|
||||||
|
" image ",
|
||||||
|
" Images "
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_category_item_get_type_identifier(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"image"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Images"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_item_get_count(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_item_get_children(
|
||||||
|
evidence_category_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
g_list_model_get_item_type(
|
||||||
|
evidence_category_item_get_children(
|
||||||
|
evidence_category_item
|
||||||
|
)
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie l'ajout et la propriété des preuves.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_item_append(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceRecord *evidence_record =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *evidence_list_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *stored_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
evidence_category_item_new(
|
||||||
|
"image",
|
||||||
|
"Images"
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
test_evidence_category_item_create_record();
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_category_item_append(
|
||||||
|
evidence_category_item,
|
||||||
|
evidence_list_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La catégorie possède maintenant sa propre référence.
|
||||||
|
*/
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record_free(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_item_get_count(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
stored_item =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_category_item_get_children(
|
||||||
|
evidence_category_item
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
stored_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_identifier(
|
||||||
|
stored_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
stored_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"capture-instagram.png"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
stored_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les arguments invalides.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_item_invalid_arguments(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryItem *evidence_category_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_new(
|
||||||
|
NULL,
|
||||||
|
"Images"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_new(
|
||||||
|
"image",
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_new(
|
||||||
|
" ",
|
||||||
|
"Images"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_new(
|
||||||
|
"image",
|
||||||
|
" "
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_item =
|
||||||
|
evidence_category_item_new(
|
||||||
|
"image",
|
||||||
|
"Images"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_category_item_append(
|
||||||
|
evidence_category_item,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_category_item_append(
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_get_type_identifier(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_item_get_count(
|
||||||
|
NULL
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_category_item_get_children(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_category_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_test_init(
|
||||||
|
&argc,
|
||||||
|
&argv,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-item/new-valid",
|
||||||
|
test_evidence_category_item_new_valid
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-item/append",
|
||||||
|
test_evidence_category_item_append
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-item/invalid-arguments",
|
||||||
|
test_evidence_category_item_invalid_arguments
|
||||||
|
);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
||||||
637
tests/test_evidence_category_model.c
Normal file
637
tests/test_evidence_category_model.c
Normal file
|
|
@ -0,0 +1,637 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_evidence_category_model.c
|
||||||
|
* @brief Tests unitaires de EvidenceCategoryModel.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_model.h"
|
||||||
|
|
||||||
|
#include "widgets/evidence_category_item.h"
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
#include "models/evidence_record.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un élément d'affichage valide.
|
||||||
|
*/
|
||||||
|
static EvidenceListItem *test_evidence_category_model_create_item(
|
||||||
|
const char *identifier,
|
||||||
|
const char *original_name,
|
||||||
|
const char *type_identifier
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
char *internal_name = NULL;
|
||||||
|
char *relative_path = NULL;
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
internal_name =
|
||||||
|
g_strdup_printf(
|
||||||
|
"%s.bin",
|
||||||
|
identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
relative_path =
|
||||||
|
g_strdup_printf(
|
||||||
|
"01_Preuves_Originales/Documents/%s.bin",
|
||||||
|
identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
internal_name
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
relative_path
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
evidence_record_new(
|
||||||
|
identifier,
|
||||||
|
original_name,
|
||||||
|
internal_name,
|
||||||
|
relative_path,
|
||||||
|
type_identifier,
|
||||||
|
4096,
|
||||||
|
"00000000000000000000000000000000"
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"2026-07-20T07:16:01Z",
|
||||||
|
"2026-07-19T18:30:00Z",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN,
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_no_error(
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record_free(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
relative_path
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
internal_name
|
||||||
|
);
|
||||||
|
|
||||||
|
return evidence_list_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ajoute une preuve à un GListStore.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_model_append_item(
|
||||||
|
GListStore *evidence_items,
|
||||||
|
EvidenceListItem *evidence_list_item
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_list_store_append(
|
||||||
|
evidence_items,
|
||||||
|
G_OBJECT(
|
||||||
|
evidence_list_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée la table des libellés de types.
|
||||||
|
*/
|
||||||
|
static GHashTable *test_evidence_category_model_create_labels(void)
|
||||||
|
{
|
||||||
|
GHashTable *type_labels =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
type_labels =
|
||||||
|
g_hash_table_new_full(
|
||||||
|
g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_hash_table_insert(
|
||||||
|
type_labels,
|
||||||
|
g_strdup("document"),
|
||||||
|
g_strdup("Documents")
|
||||||
|
);
|
||||||
|
|
||||||
|
g_hash_table_insert(
|
||||||
|
type_labels,
|
||||||
|
g_strdup("image"),
|
||||||
|
g_strdup("Images")
|
||||||
|
);
|
||||||
|
|
||||||
|
return type_labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie la création d'un modèle vide.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_model_new_empty(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryModel *evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_model =
|
||||||
|
evidence_category_model_new();
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_category_model_get_list_model(
|
||||||
|
evidence_category_model
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_model_get_count(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
g_list_model_get_item_type(
|
||||||
|
evidence_category_model_get_list_model(
|
||||||
|
evidence_category_model
|
||||||
|
)
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
EVIDENCE_TYPE_CATEGORY_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie le regroupement et le tri.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_model_group_and_sort(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryModel *evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListStore *evidence_items =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GHashTable *type_labels =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceCategoryItem *documents_category =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceCategoryItem *images_category =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *first_image =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_model =
|
||||||
|
evidence_category_model_new();
|
||||||
|
|
||||||
|
evidence_items =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
type_labels =
|
||||||
|
test_evidence_category_model_create_labels();
|
||||||
|
|
||||||
|
test_evidence_category_model_append_item(
|
||||||
|
evidence_items,
|
||||||
|
test_evidence_category_model_create_item(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"zeta.png",
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
test_evidence_category_model_append_item(
|
||||||
|
evidence_items,
|
||||||
|
test_evidence_category_model_create_item(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
"rapport.pdf",
|
||||||
|
"document"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
test_evidence_category_model_append_item(
|
||||||
|
evidence_items,
|
||||||
|
test_evidence_category_model_create_item(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
"alpha.png",
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
evidence_category_model,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_items
|
||||||
|
),
|
||||||
|
type_labels,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_model_get_count(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
documents_category =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_category_model_get_list_model(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
images_category =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_category_model_get_list_model(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
documents_category
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Documents"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_item_get_count(
|
||||||
|
documents_category
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
images_category
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Images"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_item_get_count(
|
||||||
|
images_category
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
first_image =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_category_item_get_children(
|
||||||
|
images_category
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
first_image
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"alpha.png"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
first_image
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
images_category
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
documents_category
|
||||||
|
);
|
||||||
|
|
||||||
|
g_hash_table_unref(
|
||||||
|
type_labels
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_items
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie le libellé de secours pour un type inconnu.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_model_unknown_type(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryModel *evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListStore *evidence_items =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceCategoryItem *category =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_category_model =
|
||||||
|
evidence_category_model_new();
|
||||||
|
|
||||||
|
evidence_items =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
test_evidence_category_model_append_item(
|
||||||
|
evidence_items,
|
||||||
|
test_evidence_category_model_create_item(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440003",
|
||||||
|
"archive.bin",
|
||||||
|
"unknown"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
evidence_category_model,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
evidence_items
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
category =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_category_model_get_list_model(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_category_item_get_label(
|
||||||
|
category
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"unknown"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
category
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_items
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les remplacements successifs et les erreurs.
|
||||||
|
*/
|
||||||
|
static void test_evidence_category_model_replace_and_clear(void)
|
||||||
|
{
|
||||||
|
EvidenceCategoryModel *evidence_category_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListStore *valid_items =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListStore *empty_items =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListStore *invalid_items =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GObject *invalid_object =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
evidence_category_model =
|
||||||
|
evidence_category_model_new();
|
||||||
|
|
||||||
|
valid_items =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
empty_items =
|
||||||
|
g_list_store_new(
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
invalid_items =
|
||||||
|
g_list_store_new(
|
||||||
|
G_TYPE_OBJECT
|
||||||
|
);
|
||||||
|
|
||||||
|
test_evidence_category_model_append_item(
|
||||||
|
valid_items,
|
||||||
|
test_evidence_category_model_create_item(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440004",
|
||||||
|
"preuve.txt",
|
||||||
|
"document"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
evidence_category_model,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
valid_items
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
invalid_object =
|
||||||
|
g_object_new(
|
||||||
|
G_TYPE_OBJECT,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_list_store_append(
|
||||||
|
invalid_items,
|
||||||
|
invalid_object
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
invalid_object
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
evidence_category_model,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
invalid_items
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ARGUMENT
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L'ancien contenu est conservé après l'échec.
|
||||||
|
*/
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_model_get_count(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
evidence_category_model,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
empty_items
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_category_model_get_count(
|
||||||
|
evidence_category_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_category_model_replace(
|
||||||
|
NULL,
|
||||||
|
G_LIST_MODEL(
|
||||||
|
valid_items
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR,
|
||||||
|
EVIDENCE_CATEGORY_MODEL_ERROR_INVALID_ARGUMENT
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
invalid_items
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
empty_items
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
valid_items
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_category_model_free(
|
||||||
|
evidence_category_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_test_init(
|
||||||
|
&argc,
|
||||||
|
&argv,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-model/new-empty",
|
||||||
|
test_evidence_category_model_new_empty
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-model/group-and-sort",
|
||||||
|
test_evidence_category_model_group_and_sort
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-model/unknown-type",
|
||||||
|
test_evidence_category_model_unknown_type
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-category-model/replace-and-clear",
|
||||||
|
test_evidence_category_model_replace_and_clear
|
||||||
|
);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
||||||
336
tests/test_evidence_list_item.c
Normal file
336
tests/test_evidence_list_item.c
Normal file
|
|
@ -0,0 +1,336 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_evidence_list_item.c
|
||||||
|
* @brief Tests unitaires de EvidenceListItem.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée une preuve métier valide pour les tests.
|
||||||
|
*/
|
||||||
|
static EvidenceRecord *test_evidence_list_item_create_record(
|
||||||
|
const char *collected_at,
|
||||||
|
const char *source,
|
||||||
|
EvidenceIntegrityStatus integrity_status
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
evidence_record_new(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"capture_originale.png",
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000.png",
|
||||||
|
"01_Preuves_Originales/Documents/"
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000.png",
|
||||||
|
"image",
|
||||||
|
4096,
|
||||||
|
"00000000000000000000000000000000"
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"2026-07-20T07:16:01Z",
|
||||||
|
collected_at,
|
||||||
|
source,
|
||||||
|
"Capture reçue pendant la conversation.",
|
||||||
|
integrity_status,
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_no_error(
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
return evidence_record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie la copie des valeurs nominales.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_item_new_valid(void)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
test_evidence_list_item_create_record(
|
||||||
|
"2026-07-19T18:30:00Z",
|
||||||
|
"Conversation Instagram",
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_VALID
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"capture_originale.png"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_type_identifier(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"image"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_item_get_size_bytes(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
4096
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_collected_at(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"2026-07-19T18:30:00Z"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_source(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Conversation Instagram"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpint(
|
||||||
|
evidence_list_item_get_integrity_status(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_VALID
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_integrity_status_label(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Valide"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record_free(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie que les chaînes ne dépendent plus du modèle métier.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_item_copies_strings(void)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
test_evidence_list_item_create_record(
|
||||||
|
"2026-07-19T18:30:00Z",
|
||||||
|
"Email reçu",
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record_free(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"capture_originale.png"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_source(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Email reçu"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les valeurs facultatives absentes.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_item_optional_values(void)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
test_evidence_list_item_create_record(
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_item =
|
||||||
|
evidence_list_item_new(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_collected_at(
|
||||||
|
evidence_list_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_source(
|
||||||
|
evidence_list_item
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_integrity_status_label(
|
||||||
|
evidence_list_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Non vérifiée"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
evidence_list_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record_free(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les arguments NULL.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_item_null_values(void)
|
||||||
|
{
|
||||||
|
EvidenceListItem *evidence_list_item = NULL;
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_new(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_type_identifier(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_item_get_size_bytes(
|
||||||
|
NULL
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_collected_at(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_null(
|
||||||
|
evidence_list_item_get_source(
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpint(
|
||||||
|
evidence_list_item_get_integrity_status(
|
||||||
|
NULL
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* g_clear_object() accepte un pointeur contenant NULL.
|
||||||
|
*/
|
||||||
|
g_clear_object(
|
||||||
|
&evidence_list_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_test_init(
|
||||||
|
&argc,
|
||||||
|
&argv,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-item/new-valid",
|
||||||
|
test_evidence_list_item_new_valid
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-item/copies-strings",
|
||||||
|
test_evidence_list_item_copies_strings
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-item/optional-values",
|
||||||
|
test_evidence_list_item_optional_values
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-item/null-values",
|
||||||
|
test_evidence_list_item_null_values
|
||||||
|
);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
||||||
592
tests/test_evidence_list_model.c
Normal file
592
tests/test_evidence_list_model.c
Normal file
|
|
@ -0,0 +1,592 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_evidence_list_model.c
|
||||||
|
* @brief Tests unitaires de EvidenceListModel.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_model.h"
|
||||||
|
|
||||||
|
#include "widgets/evidence_list_item.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée une preuve valide pour les tests.
|
||||||
|
*/
|
||||||
|
static EvidenceRecord *test_evidence_list_model_create_record(
|
||||||
|
const char *uuid,
|
||||||
|
const char *original_name,
|
||||||
|
const char *source
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EvidenceRecord *evidence_record = NULL;
|
||||||
|
|
||||||
|
char *internal_name = NULL;
|
||||||
|
char *relative_path = NULL;
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
internal_name =
|
||||||
|
g_strdup_printf(
|
||||||
|
"%s.bin",
|
||||||
|
uuid
|
||||||
|
);
|
||||||
|
|
||||||
|
relative_path =
|
||||||
|
g_strdup_printf(
|
||||||
|
"01_Preuves_Originales/Documents/%s.bin",
|
||||||
|
uuid
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
internal_name
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
relative_path
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_record =
|
||||||
|
evidence_record_new(
|
||||||
|
uuid,
|
||||||
|
original_name,
|
||||||
|
internal_name,
|
||||||
|
relative_path,
|
||||||
|
"document",
|
||||||
|
4096,
|
||||||
|
"00000000000000000000000000000000"
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"2026-07-20T07:16:01Z",
|
||||||
|
"2026-07-19T18:30:00Z",
|
||||||
|
source,
|
||||||
|
"Description de test.",
|
||||||
|
EVIDENCE_INTEGRITY_STATUS_UNKNOWN,
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_no_error(
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_record
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
relative_path
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
internal_name
|
||||||
|
);
|
||||||
|
|
||||||
|
return evidence_record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un tableau qui libère automatiquement ses preuves.
|
||||||
|
*/
|
||||||
|
static GPtrArray *test_evidence_list_model_create_records(void)
|
||||||
|
{
|
||||||
|
return g_ptr_array_new_with_free_func(
|
||||||
|
(GDestroyNotify) evidence_record_free
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie la création d'un modèle vide.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_model_new_empty(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GListModel *list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
list_model =
|
||||||
|
evidence_list_model_get_list_model(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_model_get_count(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
g_list_model_get_item_type(
|
||||||
|
list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
EVIDENCE_TYPE_LIST_ITEM
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie l'alimentation nominale du modèle.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_model_replace_records(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *evidence_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *first_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
evidence_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
evidence_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"premiere-preuve.pdf",
|
||||||
|
"Email reçu"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
evidence_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
"deuxieme-preuve.png",
|
||||||
|
"Conversation Instagram"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
evidence_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_model_get_count(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
first_item =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_list_model_get_list_model(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_nonnull(
|
||||||
|
first_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
first_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"premiere-preuve.pdf"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
first_item
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La liste doit rester valide après libération des EvidenceRecord.
|
||||||
|
*/
|
||||||
|
g_ptr_array_unref(
|
||||||
|
evidence_records
|
||||||
|
);
|
||||||
|
|
||||||
|
first_item =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_list_model_get_list_model(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_source(
|
||||||
|
first_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"Email reçu"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
first_item
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie qu'un rafraîchissement remplace l'ancien contenu.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_model_successive_replacements(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *first_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *second_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
EvidenceListItem *remaining_item =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
first_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
second_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
first_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
"ancienne-preuve.txt",
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
second_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440003",
|
||||||
|
"nouvelle-preuve.txt",
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
first_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
second_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_model_get_count(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
remaining_item =
|
||||||
|
g_list_model_get_item(
|
||||||
|
evidence_list_model_get_list_model(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpstr(
|
||||||
|
evidence_list_item_get_original_name(
|
||||||
|
remaining_item
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
"nouvelle-preuve.txt"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(
|
||||||
|
remaining_item
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
second_records
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
first_records
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie qu'un tableau vide efface le modèle.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_model_replace_empty(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *evidence_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *empty_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
evidence_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
empty_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
evidence_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440004",
|
||||||
|
"preuve-temporaire.txt",
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
evidence_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
empty_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_model_get_count(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
empty_records
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
evidence_records
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les arguments invalides et le remplacement atomique.
|
||||||
|
*/
|
||||||
|
static void test_evidence_list_model_invalid_records(void)
|
||||||
|
{
|
||||||
|
EvidenceListModel *evidence_list_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *valid_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GPtrArray *invalid_records =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
evidence_list_model =
|
||||||
|
evidence_list_model_new();
|
||||||
|
|
||||||
|
valid_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
invalid_records =
|
||||||
|
test_evidence_list_model_create_records();
|
||||||
|
|
||||||
|
g_ptr_array_add(
|
||||||
|
valid_records,
|
||||||
|
test_evidence_list_model_create_record(
|
||||||
|
"550e8400-e29b-41d4-a716-446655440005",
|
||||||
|
"preuve-conservee.txt",
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_true(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
valid_records,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NULL représente ici une ligne métier invalide.
|
||||||
|
*/
|
||||||
|
g_ptr_array_add(
|
||||||
|
invalid_records,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
invalid_records,
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_RECORD
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L'ancien élément doit toujours être présent.
|
||||||
|
*/
|
||||||
|
g_assert_cmpuint(
|
||||||
|
evidence_list_model_get_count(
|
||||||
|
evidence_list_model
|
||||||
|
),
|
||||||
|
==,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
NULL,
|
||||||
|
valid_records,
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_ARGUMENT
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_false(
|
||||||
|
evidence_list_model_replace(
|
||||||
|
evidence_list_model,
|
||||||
|
NULL,
|
||||||
|
&error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
g_assert_error(
|
||||||
|
error,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR,
|
||||||
|
EVIDENCE_LIST_MODEL_ERROR_INVALID_ARGUMENT
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
invalid_records
|
||||||
|
);
|
||||||
|
|
||||||
|
g_ptr_array_unref(
|
||||||
|
valid_records
|
||||||
|
);
|
||||||
|
|
||||||
|
evidence_list_model_free(
|
||||||
|
evidence_list_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_test_init(
|
||||||
|
&argc,
|
||||||
|
&argv,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-model/new-empty",
|
||||||
|
test_evidence_list_model_new_empty
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-model/replace-records",
|
||||||
|
test_evidence_list_model_replace_records
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-model/successive-replacements",
|
||||||
|
test_evidence_list_model_successive_replacements
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-model/replace-empty",
|
||||||
|
test_evidence_list_model_replace_empty
|
||||||
|
);
|
||||||
|
|
||||||
|
g_test_add_func(
|
||||||
|
"/evidence-list-model/invalid-records",
|
||||||
|
test_evidence_list_model_invalid_records
|
||||||
|
);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue