feat: integrate asynchronous graph loading
This commit is contained in:
parent
b0a2c18cbf
commit
fb44188e01
5 changed files with 1037 additions and 77 deletions
|
|
@ -15,6 +15,11 @@
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Représentation opaque du graphe d'enquête.
|
||||||
|
*/
|
||||||
|
typedef struct InvestigationGraphModel InvestigationGraphModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Représentation opaque de la fenêtre principale.
|
* @brief Représentation opaque de la fenêtre principale.
|
||||||
*/
|
*/
|
||||||
|
|
@ -229,6 +234,53 @@ void main_window_set_selected_evidence(
|
||||||
const EvidenceRecord *evidence_record
|
const EvidenceRecord *evidence_record
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Affiche l'état de chargement du graphe.
|
||||||
|
*
|
||||||
|
* MainWindow transmet uniquement la demande au Workspace.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
*/
|
||||||
|
void main_window_set_graph_loading(
|
||||||
|
MainWindow *main_window
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Affiche le graphe chargé dans le Workspace.
|
||||||
|
*
|
||||||
|
* MainWindow et Workspace empruntent graph_model.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
* @param graph_model Graphe emprunté, ou NULL.
|
||||||
|
*/
|
||||||
|
void main_window_set_graph(
|
||||||
|
MainWindow *main_window,
|
||||||
|
const InvestigationGraphModel *graph_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Affiche une erreur de chargement du graphe.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
* @param message Message d'erreur, ou NULL.
|
||||||
|
*/
|
||||||
|
void main_window_set_graph_error(
|
||||||
|
MainWindow *main_window,
|
||||||
|
const char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Détache le graphe du Workspace.
|
||||||
|
*
|
||||||
|
* Aucun graphe n'est libéré par MainWindow.
|
||||||
|
*
|
||||||
|
* @param main_window Fenêtre principale.
|
||||||
|
*/
|
||||||
|
void main_window_clear_graph(
|
||||||
|
MainWindow *main_window
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Met à jour le texte de la barre d'état.
|
* @brief Met à jour le texte de la barre d'état.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,32 @@
|
||||||
#ifndef LABFY_INVESTIGATION_WORKSPACE_H
|
#ifndef LABFY_INVESTIGATION_WORKSPACE_H
|
||||||
#define LABFY_INVESTIGATION_WORKSPACE_H
|
#define LABFY_INVESTIGATION_WORKSPACE_H
|
||||||
|
|
||||||
|
|
||||||
#include "core/investigation_node.h"
|
#include "core/investigation_node.h"
|
||||||
#include "models/evidence_record.h"
|
#include "models/evidence_record.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Représentation opaque du graphe d'enquête.
|
||||||
|
*/
|
||||||
|
typedef struct InvestigationGraphModel InvestigationGraphModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Représentation opaque de la zone de travail.
|
* @brief Représentation opaque de la zone de travail.
|
||||||
*
|
|
||||||
* La structure réelle est définie dans workspace.c.
|
|
||||||
* Les autres modules manipulent uniquement un pointeur vers Workspace.
|
|
||||||
*/
|
*/
|
||||||
typedef struct Workspace Workspace;
|
typedef struct Workspace Workspace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback appelé lors d'une demande de vérification d'une preuve.
|
||||||
|
*
|
||||||
|
* @param evidence_identifier UUID de la preuve affichée.
|
||||||
|
* @param user_data Données empruntées fournies par l'appelant.
|
||||||
|
*/
|
||||||
|
typedef void (*WorkspaceVerifyEvidenceCallback)(
|
||||||
|
const char *evidence_identifier,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Crée une nouvelle zone de travail.
|
* @brief Crée une nouvelle zone de travail.
|
||||||
*
|
*
|
||||||
|
|
@ -27,44 +39,27 @@ typedef struct Workspace Workspace;
|
||||||
*/
|
*/
|
||||||
Workspace *workspace_new(void);
|
Workspace *workspace_new(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback appelé lorsque l'utilisateur demande la vérification
|
|
||||||
* de la preuve affichée.
|
|
||||||
*
|
|
||||||
* L'identifiant est emprunté et uniquement valide pendant l'appel.
|
|
||||||
*
|
|
||||||
* @param evidence_identifier UUID de la preuve.
|
|
||||||
* @param user_data Données privées du callback.
|
|
||||||
*/
|
|
||||||
typedef void (*WorkspaceVerifyEvidenceCallback)(
|
|
||||||
const char *evidence_identifier,
|
|
||||||
gpointer user_data
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retourne le widget GTK racine de la zone de travail.
|
* @brief Retourne le widget GTK racine de la zone de travail.
|
||||||
*
|
*
|
||||||
* Le widget retourné appartient au module Workspace et ne doit pas être
|
* Le widget retourné appartient au module Workspace.
|
||||||
* détruit directement par le code appelant.
|
|
||||||
*
|
*
|
||||||
* @param workspace Zone de travail à consulter.
|
* @param workspace Zone de travail à consulter.
|
||||||
*
|
*
|
||||||
* @return Le widget racine, ou NULL si workspace est NULL.
|
* @return Widget racine, ou NULL.
|
||||||
*/
|
*/
|
||||||
GtkWidget *workspace_get_widget(
|
GtkWidget *workspace_get_widget(
|
||||||
const Workspace *workspace
|
const Workspace *workspace
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Affiche les informations du nœud sélectionné.
|
* @brief Affiche les informations d'un nœud sélectionné.
|
||||||
*
|
*
|
||||||
* Le Workspace ne devient pas propriétaire du nœud.
|
* Le Workspace emprunte le nœud.
|
||||||
* Le nœud doit rester valide pendant toute la durée de son affichage.
|
* Passer NULL restaure l'état principal courant.
|
||||||
*
|
*
|
||||||
* Passer NULL restaure la page d'accueil.
|
* @param workspace Zone de travail.
|
||||||
*
|
* @param node Nœud emprunté, ou NULL.
|
||||||
* @param workspace Zone de travail à mettre à jour.
|
|
||||||
* @param node Nœud sélectionné en lecture seule, ou NULL.
|
|
||||||
*/
|
*/
|
||||||
void workspace_set_selected_node(
|
void workspace_set_selected_node(
|
||||||
Workspace *workspace,
|
Workspace *workspace,
|
||||||
|
|
@ -74,13 +69,13 @@ void workspace_set_selected_node(
|
||||||
/**
|
/**
|
||||||
* @brief Affiche la fiche détaillée d'une preuve.
|
* @brief Affiche la fiche détaillée d'une preuve.
|
||||||
*
|
*
|
||||||
* Les valeurs sont immédiatement copiées par les widgets GTK.
|
* Les textes sont copiés dans les widgets. Le Workspace ne conserve pas le
|
||||||
* Le Workspace ne conserve pas le pointeur EvidenceRecord.
|
* pointeur EvidenceRecord.
|
||||||
*
|
*
|
||||||
* Passer NULL restaure la page d'accueil.
|
* Passer NULL restaure l'état principal courant.
|
||||||
*
|
*
|
||||||
* @param workspace Zone de travail à mettre à jour.
|
* @param workspace Zone de travail.
|
||||||
* @param evidence_record Preuve sélectionnée, ou NULL.
|
* @param evidence_record Preuve empruntée, ou NULL.
|
||||||
*/
|
*/
|
||||||
void workspace_set_selected_evidence(
|
void workspace_set_selected_evidence(
|
||||||
Workspace *workspace,
|
Workspace *workspace,
|
||||||
|
|
@ -88,13 +83,13 @@ void workspace_set_selected_evidence(
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Définit le callback de vérification d'une preuve.
|
* @brief Définit le callback de vérification de la preuve affichée.
|
||||||
*
|
*
|
||||||
* Le Workspace transmet uniquement l'identifiant de la preuve affichée.
|
* Le Workspace emprunte callback et user_data.
|
||||||
*
|
*
|
||||||
* @param workspace Zone de travail.
|
* @param workspace Zone de travail.
|
||||||
* @param callback Callback facultatif.
|
* @param callback Callback à utiliser, ou NULL.
|
||||||
* @param user_data Données privées transmises au callback.
|
* @param user_data Données empruntées du callback.
|
||||||
*/
|
*/
|
||||||
void workspace_set_verify_evidence_callback(
|
void workspace_set_verify_evidence_callback(
|
||||||
Workspace *workspace,
|
Workspace *workspace,
|
||||||
|
|
@ -103,12 +98,64 @@ void workspace_set_verify_evidence_callback(
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Libère la structure d'encapsulation de la zone de travail.
|
* @brief Affiche l'état de chargement du graphe.
|
||||||
*
|
*
|
||||||
* Cette fonction accepte NULL.
|
* L'ancien graphe emprunté est détaché.
|
||||||
|
*
|
||||||
|
* @param workspace Zone de travail.
|
||||||
|
*/
|
||||||
|
void workspace_set_graph_loading(
|
||||||
|
Workspace *workspace
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Affiche le résumé du graphe chargé.
|
||||||
|
*
|
||||||
|
* Le Workspace emprunte graph_model et ne le libère jamais.
|
||||||
|
* Passer NULL équivaut à workspace_clear_graph().
|
||||||
|
*
|
||||||
|
* @param workspace Zone de travail.
|
||||||
|
* @param graph_model Graphe emprunté.
|
||||||
|
*/
|
||||||
|
void workspace_set_graph(
|
||||||
|
Workspace *workspace,
|
||||||
|
const InvestigationGraphModel *graph_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Affiche une erreur de chargement du graphe.
|
||||||
|
*
|
||||||
|
* Le texte du message est immédiatement copié par GTK.
|
||||||
|
*
|
||||||
|
* @param workspace Zone de travail.
|
||||||
|
* @param message Détail de l'erreur, ou NULL.
|
||||||
|
*/
|
||||||
|
void workspace_set_graph_error(
|
||||||
|
Workspace *workspace,
|
||||||
|
const char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Détache le graphe et restaure l'état sans enquête.
|
||||||
|
*
|
||||||
|
* Le graphe précédemment emprunté n'est jamais libéré par le Workspace.
|
||||||
|
*
|
||||||
|
* @param workspace Zone de travail.
|
||||||
|
*/
|
||||||
|
void workspace_clear_graph(
|
||||||
|
Workspace *workspace
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère la structure Workspace.
|
||||||
|
*
|
||||||
|
* Cette fonction accepte NULL. Elle ne libère jamais le graphe emprunté.
|
||||||
*
|
*
|
||||||
* @param workspace Zone de travail à libérer.
|
* @param workspace Zone de travail à libérer.
|
||||||
*/
|
*/
|
||||||
void workspace_free(Workspace *workspace);
|
void workspace_free(
|
||||||
|
Workspace *workspace
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
#include "core/investigation_project.h"
|
#include "core/investigation_project.h"
|
||||||
#include "core/investigation_session.h"
|
#include "core/investigation_session.h"
|
||||||
#include "core/investigation_tree_model.h"
|
#include "core/investigation_tree_model.h"
|
||||||
|
#include "core/investigation_graph_load_task.h"
|
||||||
|
#include "models/investigation_graph_model.h"
|
||||||
#include "models/investigation_record.h"
|
#include "models/investigation_record.h"
|
||||||
#include "core/investigation_tree_builder.h"
|
#include "core/investigation_tree_builder.h"
|
||||||
#include "views/create_investigation_dialog.h"
|
#include "views/create_investigation_dialog.h"
|
||||||
|
|
@ -91,6 +93,11 @@ struct Application
|
||||||
ToolInitializer *tool_initializer;
|
ToolInitializer *tool_initializer;
|
||||||
EvidenceListModel *evidence_list_model;
|
EvidenceListModel *evidence_list_model;
|
||||||
EvidenceCategoryModel *evidence_category_model;
|
EvidenceCategoryModel *evidence_category_model;
|
||||||
|
|
||||||
|
InvestigationGraphLoadTask *graph_load_task;
|
||||||
|
InvestigationGraphModel *graph_model;
|
||||||
|
guint64 graph_load_generation;
|
||||||
|
|
||||||
char *selected_evidence_identifier;
|
char *selected_evidence_identifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -103,6 +110,15 @@ typedef struct
|
||||||
char *investigation_root_path;
|
char *investigation_root_path;
|
||||||
} ApplicationEvidenceImportContext;
|
} ApplicationEvidenceImportContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contexte conservé jusqu'à la fin d'un chargement de graphe.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Application *application;
|
||||||
|
guint64 generation;
|
||||||
|
} ApplicationGraphLoadContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Contexte conservé pendant le dialogue de métadonnées.
|
* @brief Contexte conservé pendant le dialogue de métadonnées.
|
||||||
*
|
*
|
||||||
|
|
@ -213,6 +229,374 @@ static void application_evidence_integrity_context_free(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère le contexte d'un chargement de graphe.
|
||||||
|
*/
|
||||||
|
static void application_graph_load_context_free(
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
g_free(
|
||||||
|
user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Annule et détache le chargement de graphe courant.
|
||||||
|
*
|
||||||
|
* Chaque appel invalide les résultats appartenant à la génération
|
||||||
|
* précédente, même lorsqu'aucune tâche n'est encore active.
|
||||||
|
*/
|
||||||
|
static void application_cancel_graph_loading(
|
||||||
|
Application *application
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationGraphLoadTask *load_task =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (application == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
application->graph_load_generation++;
|
||||||
|
|
||||||
|
load_task =
|
||||||
|
application->graph_load_task;
|
||||||
|
|
||||||
|
application->graph_load_task =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (load_task == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
investigation_graph_load_task_cancel(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Détache puis libère le graphe possédé par Application.
|
||||||
|
*/
|
||||||
|
static void application_clear_graph(
|
||||||
|
Application *application
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationGraphModel *graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (application == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (application->main_window != NULL)
|
||||||
|
{
|
||||||
|
main_window_clear_graph(
|
||||||
|
application->main_window
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_model =
|
||||||
|
application->graph_model;
|
||||||
|
|
||||||
|
application->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
investigation_graph_model_free(
|
||||||
|
graph_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Traite le résultat d'un chargement asynchrone de graphe.
|
||||||
|
*
|
||||||
|
* Le callback est exécuté sur le contexte principal GLib.
|
||||||
|
*/
|
||||||
|
static void application_on_graph_loaded(
|
||||||
|
InvestigationGraphLoadTask *load_task,
|
||||||
|
InvestigationGraphModel *graph_model,
|
||||||
|
const GError *error,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ApplicationGraphLoadContext *context =
|
||||||
|
user_data;
|
||||||
|
|
||||||
|
Application *application =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
char *status_message =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
gboolean is_current_result =
|
||||||
|
FALSE;
|
||||||
|
|
||||||
|
if (context != NULL)
|
||||||
|
{
|
||||||
|
application =
|
||||||
|
context->application;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (application != NULL)
|
||||||
|
{
|
||||||
|
is_current_result =
|
||||||
|
load_task ==
|
||||||
|
application->graph_load_task &&
|
||||||
|
context->generation ==
|
||||||
|
application->graph_load_generation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Un résultat appartenant à une ancienne enquête ne doit jamais
|
||||||
|
* modifier l'interface actuelle.
|
||||||
|
*/
|
||||||
|
if (!is_current_result)
|
||||||
|
{
|
||||||
|
investigation_graph_model_free(
|
||||||
|
graph_model
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
application->graph_load_task =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
investigation_graph_model_free(
|
||||||
|
graph_model
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
error->message
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_status(
|
||||||
|
application->main_window,
|
||||||
|
"Le graphe de l'enquête n'a pas pu être chargé."
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graph_model == NULL)
|
||||||
|
{
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
"Le chargement s'est terminé sans fournir de graphe."
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_status(
|
||||||
|
application->main_window,
|
||||||
|
"Le graphe de l'enquête est indisponible."
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MainWindow et Workspace doivent être détachés de l'ancien modèle
|
||||||
|
* avant sa libération.
|
||||||
|
*/
|
||||||
|
application_clear_graph(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
|
application->graph_model =
|
||||||
|
graph_model;
|
||||||
|
|
||||||
|
main_window_set_graph(
|
||||||
|
application->main_window,
|
||||||
|
application->graph_model
|
||||||
|
);
|
||||||
|
|
||||||
|
status_message =
|
||||||
|
g_strdup_printf(
|
||||||
|
"Graphe chargé : %" G_GUINT64_FORMAT
|
||||||
|
" entité(s), %" G_GUINT64_FORMAT
|
||||||
|
" relation(s).",
|
||||||
|
investigation_graph_model_get_entity_count(
|
||||||
|
application->graph_model
|
||||||
|
),
|
||||||
|
investigation_graph_model_get_relation_count(
|
||||||
|
application->graph_model
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_status(
|
||||||
|
application->main_window,
|
||||||
|
status_message != NULL
|
||||||
|
? status_message
|
||||||
|
: "Graphe chargé."
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
status_message
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Démarre le chargement asynchrone du graphe d'une enquête.
|
||||||
|
*/
|
||||||
|
static void application_start_graph_loading(
|
||||||
|
Application *application,
|
||||||
|
const char *database_path
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationGraphLoadTask *load_task =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
ApplicationGraphLoadContext *context =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
GError *error =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (application == NULL ||
|
||||||
|
application->main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cette opération invalide l'ancienne génération et libère
|
||||||
|
* l'ancien chargement avant d'en créer un nouveau.
|
||||||
|
*/
|
||||||
|
application_cancel_graph_loading(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
|
application_clear_graph(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
|
if (database_path == NULL ||
|
||||||
|
database_path[0] == '\0')
|
||||||
|
{
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
"Le chemin de la base SQLite est invalide."
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_window_set_graph_loading(
|
||||||
|
application->main_window
|
||||||
|
);
|
||||||
|
|
||||||
|
load_task =
|
||||||
|
investigation_graph_load_task_new(
|
||||||
|
database_path,
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (load_task == NULL)
|
||||||
|
{
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
error != NULL
|
||||||
|
? error->message
|
||||||
|
: "Impossible de préparer le chargement du graphe."
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context =
|
||||||
|
g_try_new0(
|
||||||
|
ApplicationGraphLoadContext,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context == NULL)
|
||||||
|
{
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
"Impossible d'allouer le contexte de chargement."
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->application =
|
||||||
|
application;
|
||||||
|
|
||||||
|
context->generation =
|
||||||
|
application->graph_load_generation;
|
||||||
|
|
||||||
|
application->graph_load_task =
|
||||||
|
load_task;
|
||||||
|
|
||||||
|
if (!investigation_graph_load_task_start(
|
||||||
|
load_task,
|
||||||
|
application_on_graph_loaded,
|
||||||
|
context,
|
||||||
|
application_graph_load_context_free,
|
||||||
|
&error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* En cas d'échec immédiat, la tâche n'a pas pris possession
|
||||||
|
* du contexte fourni.
|
||||||
|
*/
|
||||||
|
application->graph_load_task =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
application_graph_load_context_free(
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_graph_load_task_free(
|
||||||
|
load_task
|
||||||
|
);
|
||||||
|
|
||||||
|
main_window_set_graph_error(
|
||||||
|
application->main_window,
|
||||||
|
error != NULL
|
||||||
|
? error->message
|
||||||
|
: "Impossible de démarrer le chargement du graphe."
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Vérifie que l’enquête active correspond à un chemin racine.
|
* @brief Vérifie que l’enquête active correspond à un chemin racine.
|
||||||
*/
|
*/
|
||||||
|
|
@ -972,6 +1356,7 @@ static gboolean application_install_session(
|
||||||
const InvestigationRecord *record = NULL;
|
const InvestigationRecord *record = NULL;
|
||||||
|
|
||||||
const char *root_path = NULL;
|
const char *root_path = NULL;
|
||||||
|
const char *database_path = NULL;
|
||||||
const char *investigation_name = NULL;
|
const char *investigation_name = NULL;
|
||||||
|
|
||||||
GError *evidence_error = NULL;
|
GError *evidence_error = NULL;
|
||||||
|
|
@ -1002,12 +1387,19 @@ static gboolean application_install_session(
|
||||||
project
|
project
|
||||||
);
|
);
|
||||||
|
|
||||||
|
database_path =
|
||||||
|
investigation_project_get_database_path(
|
||||||
|
project
|
||||||
|
);
|
||||||
|
|
||||||
investigation_name = investigation_record_get_name(
|
investigation_name = investigation_record_get_name(
|
||||||
record
|
record
|
||||||
);
|
);
|
||||||
|
|
||||||
if (root_path == NULL ||
|
if (root_path == NULL ||
|
||||||
root_path[0] == '\0' ||
|
root_path[0] == '\0' ||
|
||||||
|
database_path == NULL ||
|
||||||
|
database_path[0] == '\0' ||
|
||||||
investigation_name == NULL ||
|
investigation_name == NULL ||
|
||||||
investigation_name[0] == '\0')
|
investigation_name[0] == '\0')
|
||||||
{
|
{
|
||||||
|
|
@ -1055,6 +1447,11 @@ static gboolean application_install_session(
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
application_start_graph_loading(
|
||||||
|
application,
|
||||||
|
database_path
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* L'ancienne liste ne doit jamais rester affichée après
|
* L'ancienne liste ne doit jamais rester affichée après
|
||||||
* un changement d'enquête.
|
* un changement d'enquête.
|
||||||
|
|
@ -3930,6 +4327,14 @@ void application_free(
|
||||||
application->task_manager
|
application->task_manager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
application_cancel_graph_loading(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
|
application_clear_graph(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
investigation_tree_model_free(
|
investigation_tree_model_free(
|
||||||
application->tree_model
|
application->tree_model
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -853,6 +853,67 @@ void main_window_set_investigation(
|
||||||
g_free(window_title);
|
g_free(window_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main_window_set_graph_loading(
|
||||||
|
MainWindow *main_window
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace_set_graph_loading(
|
||||||
|
main_window->workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window_set_graph(
|
||||||
|
MainWindow *main_window,
|
||||||
|
const InvestigationGraphModel *graph_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace_set_graph(
|
||||||
|
main_window->workspace,
|
||||||
|
graph_model
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window_set_graph_error(
|
||||||
|
MainWindow *main_window,
|
||||||
|
const char *message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace_set_graph_error(
|
||||||
|
main_window->workspace,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window_clear_graph(
|
||||||
|
MainWindow *main_window
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace_clear_graph(
|
||||||
|
main_window->workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main_window_set_status(
|
void main_window_set_status(
|
||||||
MainWindow *main_window,
|
MainWindow *main_window,
|
||||||
const char *status_text
|
const char *status_text
|
||||||
|
|
@ -1112,6 +1173,10 @@ void main_window_free(
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
main_window_clear_graph(
|
||||||
|
main_window
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
workspace_free(
|
workspace_free(
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,28 @@
|
||||||
|
|
||||||
#include "widgets/workspace.h"
|
#include "widgets/workspace.h"
|
||||||
|
|
||||||
|
#include "models/investigation_graph_model.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#define WORKSPACE_PAGE_WELCOME "welcome"
|
#define WORKSPACE_PAGE_WELCOME "welcome"
|
||||||
#define WORKSPACE_PAGE_NODE_INFORMATION "node-information"
|
#define WORKSPACE_PAGE_NODE_INFORMATION "node-information"
|
||||||
#define WORKSPACE_PAGE_EVIDENCE_INFORMATION \
|
#define WORKSPACE_PAGE_EVIDENCE_INFORMATION \
|
||||||
"evidence-information"
|
"evidence-information"
|
||||||
|
#define WORKSPACE_PAGE_GRAPH_STATE \
|
||||||
|
"graph-state"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief État métier représenté par la page du graphe.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
WORKSPACE_GRAPH_STATE_EMPTY,
|
||||||
|
WORKSPACE_GRAPH_STATE_LOADING,
|
||||||
|
WORKSPACE_GRAPH_STATE_READY,
|
||||||
|
WORKSPACE_GRAPH_STATE_ERROR
|
||||||
|
} WorkspaceGraphState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct Workspace
|
* @struct Workspace
|
||||||
* @brief Représentation interne de la zone de travail.
|
* @brief Représentation interne de la zone de travail.
|
||||||
|
|
@ -21,9 +37,11 @@ struct Workspace
|
||||||
GtkWidget *stack;
|
GtkWidget *stack;
|
||||||
|
|
||||||
GtkWidget *welcome_page;
|
GtkWidget *welcome_page;
|
||||||
GtkWidget *welcome_title_label;
|
|
||||||
GtkWidget *welcome_status_label;
|
GtkWidget *graph_state_page;
|
||||||
GtkWidget *welcome_instruction_label;
|
GtkWidget *graph_spinner;
|
||||||
|
GtkWidget *graph_title_label;
|
||||||
|
GtkWidget *graph_details_label;
|
||||||
|
|
||||||
GtkWidget *node_page;
|
GtkWidget *node_page;
|
||||||
|
|
||||||
|
|
@ -56,6 +74,9 @@ struct Workspace
|
||||||
GtkWidget *node_type_label;
|
GtkWidget *node_type_label;
|
||||||
GtkWidget *node_parent_label;
|
GtkWidget *node_parent_label;
|
||||||
GtkWidget *node_children_label;
|
GtkWidget *node_children_label;
|
||||||
|
|
||||||
|
const InvestigationGraphModel *graph_model;
|
||||||
|
WorkspaceGraphState graph_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -226,9 +247,12 @@ static const char *workspace_get_integrity_status_text(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Affiche la page d'accueil.
|
* @brief Affiche l'état principal courant du Workspace.
|
||||||
|
*
|
||||||
|
* Sans enquête, la page d'accueil est utilisée. Lorsqu'un chargement, un
|
||||||
|
* graphe ou une erreur existe, la page d'état du graphe est affichée.
|
||||||
*/
|
*/
|
||||||
static void workspace_show_welcome(
|
static void workspace_show_default(
|
||||||
Workspace *workspace
|
Workspace *workspace
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
@ -237,10 +261,21 @@ static void workspace_show_welcome(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (workspace->graph_state ==
|
||||||
|
WORKSPACE_GRAPH_STATE_EMPTY)
|
||||||
|
{
|
||||||
gtk_stack_set_visible_child_name(
|
gtk_stack_set_visible_child_name(
|
||||||
GTK_STACK(workspace->stack),
|
GTK_STACK(workspace->stack),
|
||||||
WORKSPACE_PAGE_WELCOME
|
WORKSPACE_PAGE_WELCOME
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_stack_set_visible_child_name(
|
||||||
|
GTK_STACK(workspace->stack),
|
||||||
|
WORKSPACE_PAGE_GRAPH_STATE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -348,33 +383,6 @@ Workspace *workspace_new(void)
|
||||||
GTK_ALIGN_CENTER
|
GTK_ALIGN_CENTER
|
||||||
);
|
);
|
||||||
|
|
||||||
workspace->welcome_title_label = gtk_label_new(
|
|
||||||
"Labfy Investigation"
|
|
||||||
);
|
|
||||||
|
|
||||||
workspace->welcome_status_label = gtk_label_new(
|
|
||||||
"Aucune enquête ouverte"
|
|
||||||
);
|
|
||||||
|
|
||||||
workspace->welcome_instruction_label = gtk_label_new(
|
|
||||||
"Sélectionnez ou créez une enquête"
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_box_append(
|
|
||||||
GTK_BOX(workspace->welcome_page),
|
|
||||||
workspace->welcome_title_label
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_box_append(
|
|
||||||
GTK_BOX(workspace->welcome_page),
|
|
||||||
workspace->welcome_status_label
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_box_append(
|
|
||||||
GTK_BOX(workspace->welcome_page),
|
|
||||||
workspace->welcome_instruction_label
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_stack_add_named(
|
gtk_stack_add_named(
|
||||||
GTK_STACK(workspace->stack),
|
GTK_STACK(workspace->stack),
|
||||||
workspace->welcome_page,
|
workspace->welcome_page,
|
||||||
|
|
@ -767,7 +775,119 @@ Workspace *workspace_new(void)
|
||||||
WORKSPACE_PAGE_EVIDENCE_INFORMATION
|
WORKSPACE_PAGE_EVIDENCE_INFORMATION
|
||||||
);
|
);
|
||||||
|
|
||||||
workspace_show_welcome(workspace);
|
/*
|
||||||
|
* Page temporaire de chargement et de résumé du graphe.
|
||||||
|
* Le futur canvas interactif remplacera cette représentation.
|
||||||
|
*/
|
||||||
|
workspace->graph_state_page =
|
||||||
|
gtk_box_new(
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
12
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->graph_state_page == NULL)
|
||||||
|
{
|
||||||
|
workspace_free(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_halign(
|
||||||
|
workspace->graph_state_page,
|
||||||
|
GTK_ALIGN_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_valign(
|
||||||
|
workspace->graph_state_page,
|
||||||
|
GTK_ALIGN_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace->graph_spinner =
|
||||||
|
gtk_spinner_new();
|
||||||
|
|
||||||
|
workspace->graph_title_label =
|
||||||
|
gtk_label_new(
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace->graph_details_label =
|
||||||
|
gtk_label_new(
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->graph_spinner == NULL ||
|
||||||
|
workspace->graph_title_label == NULL ||
|
||||||
|
workspace->graph_details_label == NULL)
|
||||||
|
{
|
||||||
|
workspace_free(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_add_css_class(
|
||||||
|
workspace->graph_title_label,
|
||||||
|
"title-2"
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_wrap(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_justify(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
GTK_JUSTIFY_CENTER
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(
|
||||||
|
workspace->graph_spinner,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
workspace->graph_state_page
|
||||||
|
),
|
||||||
|
workspace->graph_spinner
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
workspace->graph_state_page
|
||||||
|
),
|
||||||
|
workspace->graph_title_label
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_box_append(
|
||||||
|
GTK_BOX(
|
||||||
|
workspace->graph_state_page
|
||||||
|
),
|
||||||
|
workspace->graph_details_label
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_stack_add_named(
|
||||||
|
GTK_STACK(workspace->stack),
|
||||||
|
workspace->graph_state_page,
|
||||||
|
WORKSPACE_PAGE_GRAPH_STATE
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
workspace->graph_state =
|
||||||
|
WORKSPACE_GRAPH_STATE_EMPTY;
|
||||||
|
|
||||||
|
workspace_show_default(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
|
||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
@ -820,7 +940,7 @@ void workspace_set_selected_node(
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
workspace_show_welcome(workspace);
|
workspace_show_default(workspace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -944,7 +1064,7 @@ void workspace_set_selected_evidence(
|
||||||
|
|
||||||
if (evidence_record == NULL)
|
if (evidence_record == NULL)
|
||||||
{
|
{
|
||||||
workspace_show_welcome(
|
workspace_show_default(
|
||||||
workspace
|
workspace
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -960,7 +1080,7 @@ void workspace_set_selected_evidence(
|
||||||
|
|
||||||
if (workspace->selected_evidence_identifier == NULL)
|
if (workspace->selected_evidence_identifier == NULL)
|
||||||
{
|
{
|
||||||
workspace_show_welcome(
|
workspace_show_default(
|
||||||
workspace
|
workspace
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1102,6 +1222,273 @@ void workspace_set_selected_evidence(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void workspace_set_graph_loading(
|
||||||
|
Workspace *workspace
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (workspace == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&workspace->selected_evidence_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->verify_evidence_button != NULL)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(
|
||||||
|
workspace->verify_evidence_button,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
workspace->graph_state =
|
||||||
|
WORKSPACE_GRAPH_STATE_LOADING;
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_title_label
|
||||||
|
),
|
||||||
|
"Chargement de l’enquête…"
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
"Lecture des entités et des relations"
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(
|
||||||
|
workspace->graph_spinner,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_spinner_start(
|
||||||
|
GTK_SPINNER(
|
||||||
|
workspace->graph_spinner
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace_show_default(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_set_graph(
|
||||||
|
Workspace *workspace,
|
||||||
|
const InvestigationGraphModel *graph_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char *summary_text =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
if (workspace == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graph_model == NULL)
|
||||||
|
{
|
||||||
|
workspace_clear_graph(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&workspace->selected_evidence_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->verify_evidence_button != NULL)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(
|
||||||
|
workspace->verify_evidence_button,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
graph_model;
|
||||||
|
|
||||||
|
workspace->graph_state =
|
||||||
|
WORKSPACE_GRAPH_STATE_READY;
|
||||||
|
|
||||||
|
gtk_spinner_stop(
|
||||||
|
GTK_SPINNER(
|
||||||
|
workspace->graph_spinner
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(
|
||||||
|
workspace->graph_spinner,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_title_label
|
||||||
|
),
|
||||||
|
"Graphe chargé"
|
||||||
|
);
|
||||||
|
|
||||||
|
summary_text =
|
||||||
|
g_strdup_printf(
|
||||||
|
"%" G_GUINT64_FORMAT " entité(s)\n"
|
||||||
|
"%" G_GUINT64_FORMAT " relation(s)",
|
||||||
|
investigation_graph_model_get_entity_count(
|
||||||
|
graph_model
|
||||||
|
),
|
||||||
|
investigation_graph_model_get_relation_count(
|
||||||
|
graph_model
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
summary_text != NULL
|
||||||
|
? summary_text
|
||||||
|
: "Résumé indisponible"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
summary_text
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace_show_default(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_set_graph_error(
|
||||||
|
Workspace *workspace,
|
||||||
|
const char *message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (workspace == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&workspace->selected_evidence_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->verify_evidence_button != NULL)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(
|
||||||
|
workspace->verify_evidence_button,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
workspace->graph_state =
|
||||||
|
WORKSPACE_GRAPH_STATE_ERROR;
|
||||||
|
|
||||||
|
gtk_spinner_stop(
|
||||||
|
GTK_SPINNER(
|
||||||
|
workspace->graph_spinner
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(
|
||||||
|
workspace->graph_spinner,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_title_label
|
||||||
|
),
|
||||||
|
"Impossible de charger le graphe de l’enquête"
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
message != NULL &&
|
||||||
|
message[0] != '\0'
|
||||||
|
? message
|
||||||
|
: "Aucun détail supplémentaire n’est disponible."
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace_show_default(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_clear_graph(
|
||||||
|
Workspace *workspace
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (workspace == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&workspace->selected_evidence_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
if (workspace->verify_evidence_button != NULL)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(
|
||||||
|
workspace->verify_evidence_button,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
workspace->graph_state =
|
||||||
|
WORKSPACE_GRAPH_STATE_EMPTY;
|
||||||
|
|
||||||
|
gtk_spinner_stop(
|
||||||
|
GTK_SPINNER(
|
||||||
|
workspace->graph_spinner
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(
|
||||||
|
workspace->graph_spinner,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_title_label
|
||||||
|
),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_label_set_text(
|
||||||
|
GTK_LABEL(
|
||||||
|
workspace->graph_details_label
|
||||||
|
),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
|
workspace_show_default(
|
||||||
|
workspace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void workspace_set_verify_evidence_callback(
|
void workspace_set_verify_evidence_callback(
|
||||||
Workspace *workspace,
|
Workspace *workspace,
|
||||||
WorkspaceVerifyEvidenceCallback callback,
|
WorkspaceVerifyEvidenceCallback callback,
|
||||||
|
|
@ -1127,6 +1514,9 @@ void workspace_free(Workspace *workspace)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workspace->graph_model =
|
||||||
|
NULL;
|
||||||
|
|
||||||
workspace->verify_evidence_callback =
|
workspace->verify_evidence_callback =
|
||||||
NULL;
|
NULL;
|
||||||
|
|
||||||
|
|
@ -1140,3 +1530,4 @@ void workspace_free(Workspace *workspace)
|
||||||
|
|
||||||
g_free(workspace);
|
g_free(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue