labfy-investigation/src/widgets/workspace.c

2031 lines
40 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* @file workspace.c
* @brief Implémentation de la zone principale de travail.
******************************************************************************/
#include "widgets/workspace.h"
#include "widgets/entity_details_panel.h"
#include "widgets/investigation_graph_view.h"
#include <glib.h>
#define WORKSPACE_PAGE_WELCOME "welcome"
#define WORKSPACE_PAGE_NODE_INFORMATION "node-information"
#define WORKSPACE_PAGE_EVIDENCE_INFORMATION \
"evidence-information"
#define WORKSPACE_PAGE_GRAPH_STATE \
"graph-state"
#define WORKSPACE_PAGE_GRAPH_VIEW \
"graph-view"
/**
* @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
* @brief Représentation interne de la zone de travail.
*/
struct Workspace
{
GtkWidget *root_widget;
GtkWidget *stack;
GtkWidget *welcome_page;
GtkWidget *graph_state_page;
GtkWidget *graph_spinner;
GtkWidget *graph_title_label;
GtkWidget *graph_details_label;
GtkWidget *graph_view_page;
GtkWidget *graph_toolbar;
GtkWidget *reset_graph_layout_button;
InvestigationGraphView *graph_view;
EntityDetailsPanel *entity_details_panel;
GtkWidget *node_page;
GtkWidget *evidence_page;
GtkWidget *evidence_name_label;
GtkWidget *evidence_type_label;
GtkWidget *evidence_integrity_label;
GtkWidget *evidence_size_label;
GtkWidget *evidence_imported_at_label;
GtkWidget *evidence_collected_at_label;
GtkWidget *evidence_source_label;
GtkWidget *evidence_description_label;
GtkWidget *evidence_relative_path_label;
GtkWidget *evidence_internal_name_label;
GtkWidget *evidence_identifier_label;
GtkWidget *evidence_sha256_label;
GtkWidget *verify_evidence_button;
char *selected_evidence_identifier;
WorkspaceVerifyEvidenceCallback
verify_evidence_callback;
gpointer
verify_evidence_user_data;
WorkspaceGraphNodeMovedCallback
graph_node_moved_callback;
gpointer
graph_node_moved_user_data;
WorkspaceResetGraphLayoutCallback
reset_graph_layout_callback;
gpointer
reset_graph_layout_user_data;
GtkWidget *node_name_label;
GtkWidget *node_path_label;
GtkWidget *node_type_label;
GtkWidget *node_parent_label;
GtkWidget *node_children_label;
const InvestigationGraphModel *graph_model;
const InvestigationGraphLayout *graph_layout;
WorkspaceGraphState graph_state;
};
/**
* @brief Ajoute une ligne de métadonnée dans la grille.
*
* @return Label GTK destiné à recevoir la valeur.
*/
static GtkWidget *workspace_add_evidence_field(
GtkGrid *grid,
gint row,
const char *title
)
{
GtkWidget *title_label = NULL;
GtkWidget *value_label = NULL;
if (grid == NULL ||
title == NULL ||
title[0] == '\0')
{
return NULL;
}
title_label =
gtk_label_new(
title
);
value_label =
gtk_label_new(
NULL
);
if (title_label == NULL ||
value_label == NULL)
{
g_clear_object(
&value_label
);
g_clear_object(
&title_label
);
return NULL;
}
gtk_label_set_xalign(
GTK_LABEL(title_label),
0.0F
);
gtk_widget_set_valign(
title_label,
GTK_ALIGN_START
);
gtk_widget_add_css_class(
title_label,
"dim-label"
);
gtk_label_set_xalign(
GTK_LABEL(value_label),
0.0F
);
gtk_label_set_wrap(
GTK_LABEL(value_label),
TRUE
);
gtk_label_set_wrap_mode(
GTK_LABEL(value_label),
PANGO_WRAP_WORD_CHAR
);
gtk_label_set_selectable(
GTK_LABEL(value_label),
TRUE
);
gtk_widget_set_hexpand(
value_label,
TRUE
);
gtk_widget_set_halign(
value_label,
GTK_ALIGN_FILL
);
gtk_widget_set_valign(
value_label,
GTK_ALIGN_START
);
gtk_grid_attach(
grid,
title_label,
0,
row,
1,
1
);
gtk_grid_attach(
grid,
value_label,
1,
row,
1,
1
);
return value_label;
}
/**
* @brief Définit une valeur avec un texte de remplacement.
*/
static void workspace_set_field_text(
GtkWidget *label,
const char *value,
const char *fallback
)
{
if (label == NULL)
{
return;
}
gtk_label_set_text(
GTK_LABEL(label),
value != NULL && value[0] != '\0'
? value
: fallback
);
}
/**
* @brief Convertit un statut d'intégrité en texte utilisateur.
*/
static const char *workspace_get_integrity_status_text(
EvidenceIntegrityStatus integrity_status
)
{
switch (integrity_status)
{
case EVIDENCE_INTEGRITY_STATUS_UNKNOWN:
return "Non vérifiée";
case EVIDENCE_INTEGRITY_STATUS_VALID:
return "Valide";
case EVIDENCE_INTEGRITY_STATUS_MISSING:
return "Fichier absent";
case EVIDENCE_INTEGRITY_STATUS_MODIFIED:
return "Fichier modifié";
case EVIDENCE_INTEGRITY_STATUS_ERROR:
return "Erreur de vérification";
default:
return "Statut inconnu";
}
}
/**
* @brief Transmet la sélection du graphe au volet de détails.
*/
static void workspace_on_graph_node_moved(
const char *entity_identifier,
double x,
double y,
gpointer user_data
)
{
Workspace *workspace =
user_data;
if (workspace == NULL ||
workspace->graph_node_moved_callback == NULL ||
entity_identifier == NULL ||
entity_identifier[0] == '\0')
{
return;
}
workspace->graph_node_moved_callback(
entity_identifier,
x,
y,
workspace->graph_node_moved_user_data
);
}
/**
* @brief Transmet la sélection du graphe au volet de détails.
*/
static void workspace_on_graph_entity_selected(
const EntityRecord *entity_record,
gpointer user_data
)
{
Workspace *workspace =
user_data;
if (workspace == NULL ||
workspace->entity_details_panel == NULL)
{
return;
}
entity_details_panel_set_entity(
workspace->entity_details_panel,
entity_record
);
}
/**
* @brief Désélectionne le nœud lorsque le volet est fermé manuellement.
*/
static void workspace_on_entity_details_closed(
gpointer user_data
)
{
Workspace *workspace =
user_data;
if (workspace == NULL ||
workspace->graph_view == NULL)
{
return;
}
investigation_graph_view_clear_selection(
workspace->graph_view
);
}
/**
* @brief Affiche l'état principal courant du Workspace.
*
* Sans enquête, la page d'accueil est utilisée. Le chargement et les erreurs
* utilisent la page d'état. Un graphe prêt utilise la vue graphique.
*/
static void workspace_show_default(
Workspace *workspace
)
{
if (workspace == NULL)
{
return;
}
switch (workspace->graph_state)
{
case WORKSPACE_GRAPH_STATE_EMPTY:
gtk_stack_set_visible_child_name(
GTK_STACK(workspace->stack),
WORKSPACE_PAGE_WELCOME
);
return;
case WORKSPACE_GRAPH_STATE_READY:
gtk_stack_set_visible_child_name(
GTK_STACK(workspace->stack),
WORKSPACE_PAGE_GRAPH_VIEW
);
return;
case WORKSPACE_GRAPH_STATE_LOADING:
case WORKSPACE_GRAPH_STATE_ERROR:
default:
gtk_stack_set_visible_child_name(
GTK_STACK(workspace->stack),
WORKSPACE_PAGE_GRAPH_STATE
);
return;
}
}
/**
* @brief Transmet la demande de vérification de la preuve affichée.
*/
static void workspace_on_reset_graph_layout_clicked(
GtkButton *button,
gpointer user_data
)
{
Workspace *workspace =
user_data;
(void) button;
if (workspace == NULL ||
workspace->graph_state != WORKSPACE_GRAPH_STATE_READY ||
workspace->graph_model == NULL ||
workspace->reset_graph_layout_callback == NULL)
{
return;
}
workspace->reset_graph_layout_callback(
workspace->reset_graph_layout_user_data
);
}
/**
* @brief Transmet la demande de vérification de la preuve affichée.
*/
static void workspace_on_verify_evidence_clicked(
GtkButton *button,
gpointer user_data
)
{
Workspace *workspace =
user_data;
(void) button;
if (workspace == NULL ||
workspace->verify_evidence_callback == NULL ||
workspace->selected_evidence_identifier == NULL ||
workspace->selected_evidence_identifier[0] == '\0')
{
return;
}
workspace->verify_evidence_callback(
workspace->selected_evidence_identifier,
workspace->verify_evidence_user_data
);
}
Workspace *workspace_new(void)
{
GtkWidget *evidence_content = NULL;
GtkWidget *evidence_separator = NULL;
GtkWidget *evidence_grid = NULL;
Workspace *workspace = NULL;
workspace = g_new0(Workspace, 1);
workspace->root_widget = gtk_box_new(
GTK_ORIENTATION_VERTICAL,
0
);
if (workspace->root_widget == NULL)
{
workspace_free(workspace);
return NULL;
}
gtk_widget_set_hexpand(
workspace->root_widget,
TRUE
);
gtk_widget_set_vexpand(
workspace->root_widget,
TRUE
);
workspace->stack = gtk_stack_new();
if (workspace->stack == NULL)
{
workspace_free(workspace);
return NULL;
}
gtk_widget_set_hexpand(
workspace->stack,
TRUE
);
gtk_widget_set_vexpand(
workspace->stack,
TRUE
);
gtk_box_append(
GTK_BOX(workspace->root_widget),
workspace->stack
);
/*
* Page d'accueil.
*/
workspace->welcome_page = gtk_box_new(
GTK_ORIENTATION_VERTICAL,
12
);
if (workspace->welcome_page == NULL)
{
workspace_free(workspace);
return NULL;
}
gtk_widget_set_halign(
workspace->welcome_page,
GTK_ALIGN_CENTER
);
gtk_widget_set_valign(
workspace->welcome_page,
GTK_ALIGN_CENTER
);
gtk_stack_add_named(
GTK_STACK(workspace->stack),
workspace->welcome_page,
WORKSPACE_PAGE_WELCOME
);
/*
* Page d'informations sur le nœud.
*/
workspace->node_page = gtk_box_new(
GTK_ORIENTATION_VERTICAL,
12
);
if (workspace->node_page == NULL)
{
workspace_free(workspace);
return NULL;
}
gtk_widget_set_halign(
workspace->node_page,
GTK_ALIGN_CENTER
);
gtk_widget_set_valign(
workspace->node_page,
GTK_ALIGN_CENTER
);
workspace->node_name_label = gtk_label_new(NULL);
workspace->node_path_label = gtk_label_new(NULL);
workspace->node_type_label = gtk_label_new(NULL);
workspace->node_parent_label = gtk_label_new(NULL);
workspace->node_children_label = gtk_label_new(NULL);
gtk_box_append(
GTK_BOX(workspace->node_page),
workspace->node_name_label
);
gtk_box_append(
GTK_BOX(workspace->node_page),
workspace->node_path_label
);
gtk_label_set_wrap(
GTK_LABEL(workspace->node_path_label),
TRUE
);
gtk_label_set_selectable(
GTK_LABEL(workspace->node_path_label),
TRUE
);
gtk_widget_set_halign(
workspace->node_path_label,
GTK_ALIGN_CENTER
);
gtk_box_append(
GTK_BOX(workspace->node_page),
workspace->node_type_label
);
gtk_box_append(
GTK_BOX(workspace->node_page),
workspace->node_parent_label
);
gtk_box_append(
GTK_BOX(workspace->node_page),
workspace->node_children_label
);
gtk_stack_add_named(
GTK_STACK(workspace->stack),
workspace->node_page,
WORKSPACE_PAGE_NODE_INFORMATION
);
/*
* Page détaillée d'une preuve.
*/
workspace->evidence_page =
gtk_scrolled_window_new();
if (workspace->evidence_page == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_widget_set_hexpand(
workspace->evidence_page,
TRUE
);
gtk_widget_set_vexpand(
workspace->evidence_page,
TRUE
);
gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(
workspace->evidence_page
),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC
);
evidence_content =
gtk_box_new(
GTK_ORIENTATION_VERTICAL,
16
);
if (evidence_content == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_widget_set_margin_start(
evidence_content,
24
);
gtk_widget_set_margin_end(
evidence_content,
24
);
gtk_widget_set_margin_top(
evidence_content,
24
);
gtk_widget_set_margin_bottom(
evidence_content,
24
);
workspace->evidence_name_label =
gtk_label_new(
NULL
);
if (workspace->evidence_name_label == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_label_set_xalign(
GTK_LABEL(
workspace->evidence_name_label
),
0.0F
);
gtk_label_set_wrap(
GTK_LABEL(
workspace->evidence_name_label
),
TRUE
);
gtk_label_set_selectable(
GTK_LABEL(
workspace->evidence_name_label
),
TRUE
);
gtk_widget_add_css_class(
workspace->evidence_name_label,
"title-2"
);
gtk_box_append(
GTK_BOX(evidence_content),
workspace->evidence_name_label
);
workspace->verify_evidence_button =
gtk_button_new_with_label(
"Vérifier l'intégrité"
);
if (workspace->verify_evidence_button == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_widget_set_halign(
workspace->verify_evidence_button,
GTK_ALIGN_START
);
gtk_widget_set_tooltip_text(
workspace->verify_evidence_button,
"Recalculer le SHA-256 et le comparer à l'empreinte enregistrée"
);
/*
* Aucun bouton actif tant qu'aucune preuve n'est affichée.
*/
gtk_widget_set_sensitive(
workspace->verify_evidence_button,
FALSE
);
g_signal_connect(
workspace->verify_evidence_button,
"clicked",
G_CALLBACK(
workspace_on_verify_evidence_clicked
),
workspace
);
gtk_box_append(
GTK_BOX(evidence_content),
workspace->verify_evidence_button
);
evidence_separator =
gtk_separator_new(
GTK_ORIENTATION_HORIZONTAL
);
gtk_box_append(
GTK_BOX(evidence_content),
evidence_separator
);
evidence_grid =
gtk_grid_new();
if (evidence_grid == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_grid_set_column_spacing(
GTK_GRID(evidence_grid),
24
);
gtk_grid_set_row_spacing(
GTK_GRID(evidence_grid),
12
);
gtk_widget_set_hexpand(
evidence_grid,
TRUE
);
workspace->evidence_type_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
0,
"Type"
);
workspace->evidence_integrity_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
1,
"Intégrité"
);
workspace->evidence_size_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
2,
"Taille"
);
workspace->evidence_imported_at_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
3,
"Importée le"
);
workspace->evidence_collected_at_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
4,
"Collectée le"
);
workspace->evidence_source_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
5,
"Source"
);
workspace->evidence_description_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
6,
"Description"
);
workspace->evidence_relative_path_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
7,
"Chemin relatif"
);
workspace->evidence_internal_name_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
8,
"Nom interne"
);
workspace->evidence_identifier_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
9,
"Identifiant"
);
workspace->evidence_sha256_label =
workspace_add_evidence_field(
GTK_GRID(evidence_grid),
10,
"SHA-256"
);
if (workspace->evidence_type_label == NULL ||
workspace->evidence_integrity_label == NULL ||
workspace->evidence_size_label == NULL ||
workspace->evidence_imported_at_label == NULL ||
workspace->evidence_collected_at_label == NULL ||
workspace->evidence_source_label == NULL ||
workspace->evidence_description_label == NULL ||
workspace->evidence_relative_path_label == NULL ||
workspace->evidence_internal_name_label == NULL ||
workspace->evidence_identifier_label == NULL ||
workspace->evidence_sha256_label == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_box_append(
GTK_BOX(evidence_content),
evidence_grid
);
gtk_scrolled_window_set_child(
GTK_SCROLLED_WINDOW(
workspace->evidence_page
),
evidence_content
);
gtk_stack_add_named(
GTK_STACK(workspace->stack),
workspace->evidence_page,
WORKSPACE_PAGE_EVIDENCE_INFORMATION
);
/*
* Page d'état utilisée pendant le chargement ou en cas d'erreur.
*/
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
);
/*
* Page graphique : canvas principal et volet de détails superposé.
*/
workspace->graph_view_page =
gtk_overlay_new();
if (workspace->graph_view_page == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_widget_set_hexpand(
workspace->graph_view_page,
TRUE
);
gtk_widget_set_vexpand(
workspace->graph_view_page,
TRUE
);
workspace->graph_view =
investigation_graph_view_new();
workspace->entity_details_panel =
entity_details_panel_new();
if (workspace->graph_view == NULL ||
workspace->entity_details_panel == NULL)
{
workspace_free(
workspace
);
return NULL;
}
investigation_graph_view_set_selection_callback(
workspace->graph_view,
workspace_on_graph_entity_selected,
workspace
);
investigation_graph_view_set_node_moved_callback(
workspace->graph_view,
workspace_on_graph_node_moved,
workspace
);
entity_details_panel_set_close_callback(
workspace->entity_details_panel,
workspace_on_entity_details_closed,
workspace
);
gtk_overlay_set_child(
GTK_OVERLAY(
workspace->graph_view_page
),
investigation_graph_view_get_widget(
workspace->graph_view
)
);
workspace->graph_toolbar =
gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
4
);
workspace->reset_graph_layout_button =
gtk_button_new_from_icon_name(
"view-refresh-symbolic"
);
if (workspace->graph_toolbar == NULL ||
workspace->reset_graph_layout_button == NULL)
{
workspace_free(
workspace
);
return NULL;
}
gtk_widget_set_halign(
workspace->graph_toolbar,
GTK_ALIGN_START
);
gtk_widget_set_valign(
workspace->graph_toolbar,
GTK_ALIGN_START
);
gtk_widget_set_margin_start(
workspace->graph_toolbar,
12
);
gtk_widget_set_margin_top(
workspace->graph_toolbar,
12
);
gtk_widget_add_css_class(
workspace->graph_toolbar,
"toolbar"
);
gtk_widget_add_css_class(
workspace->reset_graph_layout_button,
"flat"
);
gtk_widget_set_tooltip_text(
workspace->reset_graph_layout_button,
"Réinitialiser la disposition du graphe"
);
gtk_widget_set_sensitive(
workspace->reset_graph_layout_button,
FALSE
);
g_signal_connect(
workspace->reset_graph_layout_button,
"clicked",
G_CALLBACK(
workspace_on_reset_graph_layout_clicked
),
workspace
);
gtk_box_append(
GTK_BOX(
workspace->graph_toolbar
),
workspace->reset_graph_layout_button
);
gtk_overlay_add_overlay(
GTK_OVERLAY(
workspace->graph_view_page
),
workspace->graph_toolbar
);
gtk_overlay_set_clip_overlay(
GTK_OVERLAY(
workspace->graph_view_page
),
workspace->graph_toolbar,
TRUE
);
gtk_overlay_add_overlay(
GTK_OVERLAY(
workspace->graph_view_page
),
entity_details_panel_get_widget(
workspace->entity_details_panel
)
);
gtk_overlay_set_clip_overlay(
GTK_OVERLAY(
workspace->graph_view_page
),
entity_details_panel_get_widget(
workspace->entity_details_panel
),
TRUE
);
gtk_stack_add_named(
GTK_STACK(workspace->stack),
workspace->graph_view_page,
WORKSPACE_PAGE_GRAPH_VIEW
);
workspace->graph_model =
NULL;
workspace->graph_layout =
NULL;
workspace->graph_state =
WORKSPACE_GRAPH_STATE_EMPTY;
workspace_show_default(
workspace
);
return workspace;
}
GtkWidget *workspace_get_widget(
const Workspace *workspace
)
{
if (workspace == NULL)
{
return NULL;
}
return workspace->root_widget;
}
void workspace_set_selected_node(
Workspace *workspace,
const InvestigationNode *node
)
{
const char *node_name = NULL;
const InvestigationNode *parent_node = NULL;
const char *parent_name = NULL;
const char *node_path = NULL;
InvestigationNodeType node_type;
size_t children_count = 0;
const char *type_text = NULL;
char *parent_text = NULL;
char *children_text = NULL;
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
);
}
if (node == NULL)
{
workspace_show_default(workspace);
return;
}
node_name = investigation_node_get_name(node);
node_path = investigation_node_get_path(node);
node_type = investigation_node_get_type(node);
parent_node = investigation_node_get_parent(node);
gtk_label_set_text(
GTK_LABEL(workspace->node_name_label),
node_name != NULL ? node_name : "(sans nom)"
);
gtk_label_set_text(
GTK_LABEL(workspace->node_path_label),
node_path != NULL ? node_path : "(chemin indisponible)"
);
if (node_type == INVESTIGATION_NODE_DIRECTORY)
{
type_text = "Type : dossier";
}
else
{
type_text = "Type : fichier";
}
gtk_label_set_text(
GTK_LABEL(workspace->node_type_label),
type_text
);
if (parent_node != NULL)
{
parent_name = investigation_node_get_name(parent_node);
parent_text = g_strdup_printf(
"Parent : %s",
parent_name != NULL ? parent_name : "(sans nom)"
);
}
else
{
parent_text = g_strdup("Parent : aucun");
}
gtk_label_set_text(
GTK_LABEL(workspace->node_parent_label),
parent_text
);
if (node_type == INVESTIGATION_NODE_DIRECTORY)
{
children_count =
investigation_node_get_children_count(node);
children_text = g_strdup_printf(
"Enfants : %zu",
children_count
);
gtk_label_set_text(
GTK_LABEL(workspace->node_children_label),
children_text
);
gtk_widget_set_visible(
workspace->node_children_label,
TRUE
);
}
else
{
gtk_label_set_text(
GTK_LABEL(workspace->node_children_label),
""
);
gtk_widget_set_visible(
workspace->node_children_label,
FALSE
);
}
gtk_stack_set_visible_child_name(
GTK_STACK(workspace->stack),
WORKSPACE_PAGE_NODE_INFORMATION
);
g_free(children_text);
g_free(parent_text);
}
void workspace_set_selected_evidence(
Workspace *workspace,
const EvidenceRecord *evidence_record
)
{
char *human_size = NULL;
char *size_text = NULL;
guint64 size_bytes = 0;
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
);
}
if (evidence_record == NULL)
{
workspace_show_default(
workspace
);
return;
}
workspace->selected_evidence_identifier =
g_strdup(
evidence_record_get_identifier(
evidence_record
)
);
if (workspace->selected_evidence_identifier == NULL)
{
workspace_show_default(
workspace
);
return;
}
gtk_widget_set_sensitive(
workspace->verify_evidence_button,
TRUE
);
size_bytes =
evidence_record_get_size_bytes(
evidence_record
);
human_size =
g_format_size_full(
size_bytes,
G_FORMAT_SIZE_IEC_UNITS
);
size_text =
g_strdup_printf(
"%s (%" G_GUINT64_FORMAT " octets)",
human_size != NULL
? human_size
: "taille inconnue",
size_bytes
);
workspace_set_field_text(
workspace->evidence_name_label,
evidence_record_get_original_name(
evidence_record
),
"(sans nom)"
);
workspace_set_field_text(
workspace->evidence_type_label,
evidence_record_get_type_identifier(
evidence_record
),
"(type inconnu)"
);
workspace_set_field_text(
workspace->evidence_integrity_label,
workspace_get_integrity_status_text(
evidence_record_get_integrity_status(
evidence_record
)
),
"Statut inconnu"
);
workspace_set_field_text(
workspace->evidence_size_label,
size_text,
"Taille inconnue"
);
workspace_set_field_text(
workspace->evidence_imported_at_label,
evidence_record_get_imported_at(
evidence_record
),
"(date inconnue)"
);
workspace_set_field_text(
workspace->evidence_collected_at_label,
evidence_record_get_collected_at(
evidence_record
),
"Non renseignée"
);
workspace_set_field_text(
workspace->evidence_source_label,
evidence_record_get_source(
evidence_record
),
"Non renseignée"
);
workspace_set_field_text(
workspace->evidence_description_label,
evidence_record_get_description(
evidence_record
),
"Non renseignée"
);
workspace_set_field_text(
workspace->evidence_relative_path_label,
evidence_record_get_relative_path(
evidence_record
),
"(chemin inconnu)"
);
workspace_set_field_text(
workspace->evidence_internal_name_label,
evidence_record_get_internal_name(
evidence_record
),
"(nom interne inconnu)"
);
workspace_set_field_text(
workspace->evidence_identifier_label,
evidence_record_get_identifier(
evidence_record
),
"(identifiant inconnu)"
);
workspace_set_field_text(
workspace->evidence_sha256_label,
evidence_record_get_sha256(
evidence_record
),
"(empreinte inconnue)"
);
gtk_stack_set_visible_child_name(
GTK_STACK(workspace->stack),
WORKSPACE_PAGE_EVIDENCE_INFORMATION
);
g_free(
size_text
);
g_free(
human_size
);
}
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
);
}
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear(
workspace->graph_view
);
workspace->graph_model =
NULL;
workspace->graph_layout =
NULL;
workspace->graph_state =
WORKSPACE_GRAPH_STATE_LOADING;
gtk_widget_set_sensitive(
workspace->reset_graph_layout_button,
FALSE
);
gtk_label_set_text(
GTK_LABEL(
workspace->graph_title_label
),
"Chargement de lenquê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,
const InvestigationGraphLayout *graph_layout
)
{
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
);
}
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear(
workspace->graph_view
);
workspace->graph_model =
graph_model;
workspace->graph_layout =
graph_layout;
investigation_graph_view_set_layout(
workspace->graph_view,
graph_layout
);
investigation_graph_view_set_graph(
workspace->graph_view,
graph_model
);
workspace->graph_state =
WORKSPACE_GRAPH_STATE_READY;
gtk_widget_set_sensitive(
workspace->reset_graph_layout_button,
TRUE
);
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_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
);
}
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear(
workspace->graph_view
);
workspace->graph_model =
NULL;
workspace->graph_layout =
NULL;
workspace->graph_state =
WORKSPACE_GRAPH_STATE_ERROR;
gtk_widget_set_sensitive(
workspace->reset_graph_layout_button,
FALSE
);
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 lenquête"
);
gtk_label_set_text(
GTK_LABEL(
workspace->graph_details_label
),
message != NULL &&
message[0] != '\0'
? message
: "Aucun détail supplémentaire nest 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
);
}
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear(
workspace->graph_view
);
workspace->graph_model =
NULL;
workspace->graph_layout =
NULL;
workspace->graph_state =
WORKSPACE_GRAPH_STATE_EMPTY;
gtk_widget_set_sensitive(
workspace->reset_graph_layout_button,
FALSE
);
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(
Workspace *workspace,
WorkspaceVerifyEvidenceCallback callback,
gpointer user_data
)
{
if (workspace == NULL)
{
return;
}
workspace->verify_evidence_callback =
callback;
workspace->verify_evidence_user_data =
user_data;
}
void workspace_set_graph_node_moved_callback(
Workspace *workspace,
WorkspaceGraphNodeMovedCallback callback,
gpointer user_data
)
{
if (workspace == NULL)
{
return;
}
workspace->graph_node_moved_callback =
callback;
workspace->graph_node_moved_user_data =
user_data;
}
void workspace_set_reset_graph_layout_callback(
Workspace *workspace,
WorkspaceResetGraphLayoutCallback callback,
gpointer user_data
)
{
if (workspace == NULL)
{
return;
}
workspace->reset_graph_layout_callback =
callback;
workspace->reset_graph_layout_user_data =
user_data;
}
void workspace_reset_graph_layout(
Workspace *workspace
)
{
if (workspace == NULL ||
workspace->graph_view == NULL ||
workspace->graph_state != WORKSPACE_GRAPH_STATE_READY ||
workspace->graph_model == NULL)
{
return;
}
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear_selection(
workspace->graph_view
);
investigation_graph_view_reset_layout(
workspace->graph_view
);
}
void workspace_free(Workspace *workspace)
{
if (workspace == NULL)
{
return;
}
investigation_graph_view_set_selection_callback(
workspace->graph_view,
NULL,
NULL
);
investigation_graph_view_set_node_moved_callback(
workspace->graph_view,
NULL,
NULL
);
entity_details_panel_set_close_callback(
workspace->entity_details_panel,
NULL,
NULL
);
entity_details_panel_clear(
workspace->entity_details_panel
);
investigation_graph_view_clear(
workspace->graph_view
);
investigation_graph_view_free(
workspace->graph_view
);
entity_details_panel_free(
workspace->entity_details_panel
);
workspace->graph_view =
NULL;
workspace->entity_details_panel =
NULL;
workspace->graph_model =
NULL;
workspace->graph_layout =
NULL;
workspace->verify_evidence_callback =
NULL;
workspace->verify_evidence_user_data =
NULL;
workspace->graph_node_moved_callback =
NULL;
workspace->graph_node_moved_user_data =
NULL;
workspace->reset_graph_layout_callback =
NULL;
workspace->reset_graph_layout_user_data =
NULL;
workspace->graph_toolbar =
NULL;
workspace->reset_graph_layout_button =
NULL;
g_clear_pointer(
&workspace->selected_evidence_identifier,
g_free
);
g_free(workspace);
}