diff --git a/docs/tickets/closed/TICKET-006.md b/docs/tickets/closed/TICKET-006.md new file mode 100644 index 0000000..04d1736 --- /dev/null +++ b/docs/tickets/closed/TICKET-006.md @@ -0,0 +1,153 @@ +# Ticket #006 + +## Titre + +Créer le module `Workspace`. + +--- + +## Objectif + +Créer un composant graphique représentant la zone principale de travail de Labfy Investigation. + +Le module doit être indépendant du reste de l'interface afin de pouvoir évoluer sans modifier `MainWindow`. + +--- + +## Responsabilités + +Le module `Workspace` doit : + +- créer la zone centrale de l'application ; +- afficher une page d'accueil lorsqu'aucune enquête n'est ouverte ; +- fournir un widget racine réutilisable ; +- gérer uniquement son interface graphique. + +--- + +## Hors périmètre + +Ce ticket ne doit pas : + +- afficher les preuves ; +- afficher les entités ; +- afficher un PDF ; +- afficher une image ; +- communiquer avec SQLite ; +- charger une enquête. + +--- + +## Architecture + +```text +MainWindow +├── Sidebar +├── Workspace +└── StatusBar +``` + +Le module appartient à la couche **Widgets**. + +Aucune logique métier. + +--- + +## Fichiers concernés + +```text +include/widgets/workspace.h +src/widgets/workspace.c +``` + +--- + +## Interface publique + +```c +Workspace *workspace_new(void); + +GtkWidget *workspace_get_widget( + const Workspace *workspace +); + +void workspace_free( + Workspace *workspace +); +``` + +--- + +## Interface graphique attendue + +```text ++-------------------------------------------------------------+ +| | +| | +| Labfy Investigation | +| | +| Aucune enquête ouverte | +| | +| Sélectionnez ou créez une enquête | +| | +| | ++-------------------------------------------------------------+ +``` + +--- + +## Évolutions prévues + +Cette zone accueillera plus tard : + +- visualiseur d'image ; +- lecteur PDF ; +- chronologie ; +- fiche personne ; +- fiche IBAN ; +- fiche email ; +- fiche téléphone ; +- rapports ; +- cartes ; +- résultats OSINT. + +Le module doit donc rester générique. + +--- + +## Contraintes + +- GTK4 uniquement ; +- structure opaque ; +- aucune variable globale ; +- documentation Doxygen ; +- C17 ; +- compilation sans warning. + +--- + +## Critères d'acceptation + +- [ ] Le projet compile. +- [ ] Le Workspace apparaît dans MainWindow. +- [ ] Le texte d'accueil est centré. +- [ ] Sidebar et Workspace sont totalement indépendants. +- [ ] Aucun warning. +- [ ] Aucun Gtk-CRITICAL. + +--- + +## Tests + +- lancement ; +- redimensionnement de la fenêtre ; +- fermeture ; +- vérification visuelle. + +--- + +## Commit attendu + +```text +feat(widget): create workspace +``` diff --git a/labfy-investigation/include/widgets/workspace.h b/labfy-investigation/include/widgets/workspace.h new file mode 100644 index 0000000..391f59e --- /dev/null +++ b/labfy-investigation/include/widgets/workspace.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * @file workspace.h + * @brief Interface publique de la zone principale de travail. + ******************************************************************************/ + +#ifndef LABFY_INVESTIGATION_WORKSPACE_H +#define LABFY_INVESTIGATION_WORKSPACE_H + +#include + +/** + * @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; + +/** + * @brief Crée une nouvelle zone de travail. + * + * @return Une nouvelle zone de travail, ou NULL en cas d'échec. + */ +Workspace *workspace_new(void); + +/** + * @brief Retourne le widget GTK racine de la zone de travail. + * + * Le widget retourné appartient au module Workspace et ne doit pas être + * détruit directement par le code appelant. + * + * @param workspace Zone de travail à consulter. + * + * @return Le widget racine, ou NULL si workspace est NULL. + */ +GtkWidget *workspace_get_widget( + const Workspace *workspace +); + +/** + * @brief Libère la structure d'encapsulation de la zone de travail. + * + * Cette fonction accepte NULL. + * + * @param workspace Zone de travail à libérer. + */ +void workspace_free(Workspace *workspace); + +#endif diff --git a/labfy-investigation/labfy-investigation b/labfy-investigation/labfy-investigation index 6b47849..962e443 100755 Binary files a/labfy-investigation/labfy-investigation and b/labfy-investigation/labfy-investigation differ diff --git a/labfy-investigation/src/views/main_window.c b/labfy-investigation/src/views/main_window.c index bb68b47..ee5d0f9 100644 --- a/labfy-investigation/src/views/main_window.c +++ b/labfy-investigation/src/views/main_window.c @@ -5,6 +5,7 @@ #include "views/main_window.h" #include "widgets/sidebar.h" +#include "widgets/workspace.h" #include @@ -35,7 +36,7 @@ struct MainWindow GtkWindow *window; GtkWidget *main_box; GtkWidget *main_paned; - GtkWidget *workspace; + Workspace *workspace; GtkWidget *status_label; Sidebar *sidebar; }; @@ -44,6 +45,7 @@ MainWindow *main_window_new(GtkApplication *application) { MainWindow *main_window = NULL; GtkWidget *sidebar_widget = NULL; + GtkWidget *workspace_widget = NULL; if (application == NULL) { @@ -125,25 +127,24 @@ MainWindow *main_window_new(GtkApplication *application) return NULL; } - /* - * La zone de travail est encore vide. - * Elle accueillera plus tard les pages de l'application. - */ - main_window->workspace = gtk_box_new( - GTK_ORIENTATION_VERTICAL, - 0 - ); - - gtk_widget_set_hexpand( - main_window->workspace, - TRUE - ); - - gtk_widget_set_vexpand( - main_window->workspace, - TRUE + main_window->workspace = workspace_new(); + + if (main_window->workspace == NULL) + { + main_window_free(main_window); + return NULL; + } + + workspace_widget = workspace_get_widget( + main_window->workspace ); + if (workspace_widget == NULL) + { + main_window_free(main_window); + return NULL; + } + /* * Placement des deux composants dans GtkPaned. */ @@ -154,7 +155,7 @@ MainWindow *main_window_new(GtkApplication *application) gtk_paned_set_end_child( GTK_PANED(main_window->main_paned), - main_window->workspace + workspace_widget ); /* @@ -280,6 +281,7 @@ void main_window_free(MainWindow *main_window) * * Les widgets GTK, eux, restent gérés par GTK. */ + workspace_free(main_window->workspace); sidebar_free(main_window->sidebar); g_free(main_window); diff --git a/labfy-investigation/src/widgets/workspace.c b/labfy-investigation/src/widgets/workspace.c new file mode 100644 index 0000000..a8a6e67 --- /dev/null +++ b/labfy-investigation/src/widgets/workspace.c @@ -0,0 +1,137 @@ +/****************************************************************************** + * @file workspace.c + * @brief Implémentation de la zone principale de travail. + ******************************************************************************/ + +#include "widgets/workspace.h" + +#include + +/** + * @struct Workspace + * @brief Représentation interne de la zone de travail. + * + * Cette structure reste privée au module. Les autres fichiers utilisent + * uniquement le type opaque déclaré dans workspace.h. + */ +struct Workspace +{ + GtkWidget *root_widget; + GtkWidget *welcome_box; + GtkWidget *title_label; + GtkWidget *status_label; + GtkWidget *instruction_label; +}; + +Workspace *workspace_new(void) +{ + 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->welcome_box = gtk_box_new( + GTK_ORIENTATION_VERTICAL, + 12 + ); + + if (workspace->welcome_box == NULL) + { + workspace_free(workspace); + return NULL; + } + + /* + * Le conteneur d'accueil est centré horizontalement et verticalement + * dans l'espace disponible. + */ + gtk_widget_set_halign( + workspace->welcome_box, + GTK_ALIGN_CENTER + ); + + gtk_widget_set_valign( + workspace->welcome_box, + GTK_ALIGN_CENTER + ); + + workspace->title_label = gtk_label_new( + "Labfy Investigation" + ); + + workspace->status_label = gtk_label_new( + "Aucune enquête ouverte" + ); + + workspace->instruction_label = gtk_label_new( + "Sélectionnez ou créez une enquête" + ); + + gtk_box_append( + GTK_BOX(workspace->welcome_box), + workspace->title_label + ); + + gtk_box_append( + GTK_BOX(workspace->welcome_box), + workspace->status_label + ); + + gtk_box_append( + GTK_BOX(workspace->welcome_box), + workspace->instruction_label + ); + + gtk_box_append( + GTK_BOX(workspace->root_widget), + workspace->welcome_box + ); + + return workspace; +} + +GtkWidget *workspace_get_widget( + const Workspace *workspace +) +{ + if (workspace == NULL) + { + return NULL; + } + + return workspace->root_widget; +} + +void workspace_free(Workspace *workspace) +{ + if (workspace == NULL) + { + return; + } + + /* + * Les widgets GTK sont intégrés dans l'arbre de widgets de MainWindow. + * GTK gère donc leur destruction. + */ + g_free(workspace); +}