feat(view): create main window
This commit is contained in:
parent
d8242f20ca
commit
a8e66c40be
7 changed files with 468 additions and 28 deletions
|
|
@ -6,3 +6,9 @@
|
|||
- Création du module `Application`.
|
||||
- Intégration de GTK4.
|
||||
- Affichage de la première fenêtre.
|
||||
|
||||
### Added
|
||||
|
||||
- Module `MainWindow`.
|
||||
- Séparation de la fenêtre principale du module `Application`.
|
||||
- Première architecture de la fenêtre principale.
|
||||
|
|
|
|||
57
docs/tickets/closed/TICKET-003.md
Normal file
57
docs/tickets/closed/TICKET-003.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Ticket #003
|
||||
|
||||
## Titre
|
||||
|
||||
Créer le module `Investigation`.
|
||||
|
||||
## Objectif
|
||||
|
||||
Créer l'objet métier représentant une enquête ouverte par Labfy Investigation.
|
||||
|
||||
Le module doit rester indépendant de GTK et de l'interface graphique.
|
||||
|
||||
## Responsabilités
|
||||
|
||||
Le module doit :
|
||||
|
||||
- mémoriser le chemin racine de l'enquête ;
|
||||
- construire le chemin de la base de données modèle ;
|
||||
- exposer ces chemins en lecture seule ;
|
||||
- gérer proprement sa mémoire ;
|
||||
- vérifier qu'un chemin d'enquête est exploitable.
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
Ce ticket ne doit pas :
|
||||
|
||||
- ouvrir SQLite ;
|
||||
- créer la base de données ;
|
||||
- modifier l'arborescence de l'enquête ;
|
||||
- afficher de message GTK ;
|
||||
- gérer les preuves ou les entités.
|
||||
|
||||
## Dépendances
|
||||
|
||||
- libc ;
|
||||
- GLib uniquement si nécessaire pour la gestion des chaînes et chemins.
|
||||
|
||||
Aucune dépendance GTK ou SQLite.
|
||||
|
||||
## API attendue
|
||||
|
||||
Le module doit permettre un usage proche de :
|
||||
|
||||
```c
|
||||
Investigation *investigation = NULL;
|
||||
|
||||
investigation = investigation_new("/chemin/vers/enquete");
|
||||
|
||||
if (investigation == NULL)
|
||||
{
|
||||
/* Gestion de l'erreur */
|
||||
}
|
||||
|
||||
const char *root_path = investigation_get_root_path(investigation);
|
||||
const char *database_path = investigation_get_database_path(investigation);
|
||||
|
||||
investigation_free(investigation);
|
||||
128
docs/tickets/closed/TICKET-004.md
Normal file
128
docs/tickets/closed/TICKET-004.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Ticket #004
|
||||
|
||||
## Titre
|
||||
|
||||
Créer la fenêtre principale (`MainWindow`).
|
||||
|
||||
---
|
||||
|
||||
## Objectif
|
||||
|
||||
Créer la fenêtre principale de Labfy Investigation.
|
||||
|
||||
Cette fenêtre deviendra le point central de l'interface utilisateur.
|
||||
|
||||
À ce stade, elle ne contient qu'une structure vide destinée à accueillir les futurs composants.
|
||||
|
||||
---
|
||||
|
||||
## Responsabilités
|
||||
|
||||
Le module `MainWindow` doit :
|
||||
|
||||
- créer la fenêtre principale ;
|
||||
- définir son titre ;
|
||||
- définir sa taille par défaut ;
|
||||
- afficher une zone centrale vide ;
|
||||
- afficher une barre d'état.
|
||||
|
||||
---
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
Ce ticket ne doit pas :
|
||||
|
||||
- afficher l'arborescence des fichiers ;
|
||||
- ouvrir une enquête ;
|
||||
- afficher les preuves ;
|
||||
- communiquer avec SQLite ;
|
||||
- gérer les menus.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
Le module appartient à la couche **Views**.
|
||||
|
||||
Il est responsable uniquement de l'interface graphique.
|
||||
|
||||
Aucune logique métier ne doit être présente dans ce module.
|
||||
|
||||
---
|
||||
|
||||
## Dépendances
|
||||
|
||||
- GTK4
|
||||
|
||||
Aucune dépendance vers SQLite.
|
||||
|
||||
---
|
||||
|
||||
## Fichiers concernés
|
||||
|
||||
```text
|
||||
include/views/main_window.h
|
||||
src/views/main_window.c
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Interface attendue
|
||||
|
||||
```c
|
||||
MainWindow *main_window_new(GtkApplication *application);
|
||||
|
||||
GtkWindow *main_window_get_window(
|
||||
const MainWindow *main_window
|
||||
);
|
||||
|
||||
void main_window_present(MainWindow *main_window);
|
||||
|
||||
void main_window_free(MainWindow *main_window);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Interface graphique attendue
|
||||
|
||||
```text
|
||||
┌───────────────────────────────────────────────────────────────┐
|
||||
│ Labfy Investigation │
|
||||
├───────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ │
|
||||
│ Zone de travail │
|
||||
│ │
|
||||
│ │
|
||||
├───────────────────────────────────────────────────────────────┤
|
||||
│ Aucune enquête ouverte │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critères d'acceptation
|
||||
|
||||
- [ ] Le projet compile sans warning.
|
||||
- [ ] Une fenêtre s'ouvre correctement.
|
||||
- [ ] La fenêtre est créée par le module `MainWindow`.
|
||||
- [ ] `Application` n'appelle plus directement `gtk_application_window_new()`.
|
||||
- [ ] Aucun état global.
|
||||
- [ ] Documentation Doxygen.
|
||||
- [ ] Gestion mémoire correcte.
|
||||
|
||||
---
|
||||
|
||||
## Tests
|
||||
|
||||
- Lancement de l'application.
|
||||
- Fermeture de la fenêtre.
|
||||
- Vérification de l'absence de fuite mémoire.
|
||||
|
||||
---
|
||||
|
||||
## Commit attendu
|
||||
|
||||
```text
|
||||
feat(view): create main window
|
||||
```
|
||||
50
labfy-investigation/include/views/main_window.h
Normal file
50
labfy-investigation/include/views/main_window.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/******************************************************************************
|
||||
* @file main_window.h
|
||||
* @brief Interface publique de la fenêtre principale.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_MAIN_WINDOW_H
|
||||
#define LABFY_INVESTIGATION_MAIN_WINDOW_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* @brief Représentation opaque de la fenêtre principale.
|
||||
*/
|
||||
typedef struct MainWindow MainWindow;
|
||||
|
||||
/**
|
||||
* @brief Crée une nouvelle fenêtre principale.
|
||||
*
|
||||
* @param application Application GTK.
|
||||
*
|
||||
* @return Une nouvelle fenêtre ou NULL en cas d'échec.
|
||||
*/
|
||||
MainWindow *main_window_new(GtkApplication *application);
|
||||
|
||||
/**
|
||||
* @brief Affiche la fenêtre principale.
|
||||
*
|
||||
* @param main_window Fenêtre à afficher.
|
||||
*/
|
||||
void main_window_present(MainWindow *main_window);
|
||||
|
||||
/**
|
||||
* @brief Retourne la fenêtre GTK associée.
|
||||
*
|
||||
* @param main_window Fenêtre principale.
|
||||
*
|
||||
* @return Fenêtre GTK.
|
||||
*/
|
||||
GtkWindow *main_window_get_window(
|
||||
const MainWindow *main_window
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère les ressources de la fenêtre.
|
||||
*
|
||||
* @param main_window Fenêtre à détruire.
|
||||
*/
|
||||
void main_window_free(MainWindow *main_window);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/application.h"
|
||||
#include "views/folder_dialog.h"
|
||||
#include "core/investigation.h"
|
||||
#include "views/main_window.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
|
@ -30,6 +31,8 @@
|
|||
struct Application
|
||||
{
|
||||
GtkApplication *gtk_application;
|
||||
MainWindow *main_window;
|
||||
Investigation *investigation;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -47,57 +50,83 @@ static void application_on_folder_selected(
|
|||
gpointer user_data
|
||||
)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW(user_data);
|
||||
Investigation *investigation = NULL;
|
||||
Application *application = user_data;
|
||||
const char *root_path = NULL;
|
||||
const char *database_path = NULL;
|
||||
|
||||
/*
|
||||
* Une éventuelle enquête précédemment ouverte doit être libérée avant
|
||||
* d'en créer une nouvelle.
|
||||
*/
|
||||
investigation_free(application->investigation);
|
||||
application->investigation = NULL;
|
||||
|
||||
application->investigation = investigation_new(folder_path);
|
||||
|
||||
if (application == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (folder_path == NULL)
|
||||
{
|
||||
g_print("Sélection annulée.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
investigation = investigation_new(folder_path);
|
||||
|
||||
if (investigation == NULL)
|
||||
if (application->investigation == NULL)
|
||||
{
|
||||
g_warning("Impossible de créer l'enquête à partir du dossier sélectionné.");
|
||||
g_warning(
|
||||
"Impossible de créer l'enquête à partir du dossier sélectionné."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
root_path = investigation_get_root_path(investigation);
|
||||
database_path = investigation_get_database_path(investigation);
|
||||
root_path = investigation_get_root_path(
|
||||
application->investigation
|
||||
);
|
||||
database_path = investigation_get_database_path(
|
||||
application->investigation
|
||||
);
|
||||
|
||||
g_print("Dossier racine : %s\n", root_path);
|
||||
g_print("Base de données : %s\n", database_path);
|
||||
|
||||
investigation_free(investigation);
|
||||
|
||||
gtk_window_set_title(window, "Labfy Investigation");
|
||||
}
|
||||
static void application_on_activate(GtkApplication *gtk_application,
|
||||
gpointer user_data)
|
||||
static void application_on_activate(
|
||||
GtkApplication *gtk_application,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
GtkWidget *window = NULL;
|
||||
Application *application = user_data;
|
||||
|
||||
(void)user_data;
|
||||
if (application == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
window = gtk_application_window_new(gtk_application);
|
||||
/*
|
||||
* Le signal "activate" peut être reçu plusieurs fois. Si la fenêtre
|
||||
* existe déjà, il suffit de la présenter au lieu d'en créer une seconde.
|
||||
*/
|
||||
if (application->main_window != NULL)
|
||||
{
|
||||
main_window_present(application->main_window);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Labfy Investigation");
|
||||
gtk_window_set_default_size(
|
||||
GTK_WINDOW(window),
|
||||
DEFAULT_WINDOW_WIDTH,
|
||||
DEFAULT_WINDOW_HEIGHT
|
||||
);
|
||||
application->main_window = main_window_new(gtk_application);
|
||||
|
||||
gtk_window_present(GTK_WINDOW(window));
|
||||
if (application->main_window == NULL)
|
||||
{
|
||||
g_warning("Impossible de créer la fenêtre principale.");
|
||||
return;
|
||||
}
|
||||
|
||||
main_window_present(application->main_window);
|
||||
|
||||
folder_dialog_select_folder(
|
||||
GTK_WINDOW(window),
|
||||
main_window_get_window(application->main_window),
|
||||
application_on_folder_selected,
|
||||
window
|
||||
application
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +157,11 @@ Application *application_new(void)
|
|||
return application;
|
||||
}
|
||||
|
||||
int application_run(Application *application, int argc, char **argv)
|
||||
int application_run(
|
||||
Application *application,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
if (application == NULL || application->gtk_application == NULL)
|
||||
{
|
||||
|
|
@ -149,6 +182,10 @@ void application_free(Application *application)
|
|||
return;
|
||||
}
|
||||
|
||||
investigation_free(application->investigation);
|
||||
|
||||
main_window_free(application->main_window);
|
||||
|
||||
if (application->gtk_application != NULL)
|
||||
{
|
||||
g_object_unref(application->gtk_application);
|
||||
|
|
|
|||
162
labfy-investigation/src/views/main_window.c
Normal file
162
labfy-investigation/src/views/main_window.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/******************************************************************************
|
||||
* @file main_window.c
|
||||
* @brief Implémentation de la fenêtre principale.
|
||||
******************************************************************************/
|
||||
|
||||
#include "views/main_window.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Largeur initiale de la fenêtre principale.
|
||||
*/
|
||||
#define MAIN_WINDOW_DEFAULT_WIDTH 1000
|
||||
|
||||
/**
|
||||
* @brief Hauteur initiale de la fenêtre principale.
|
||||
*/
|
||||
#define MAIN_WINDOW_DEFAULT_HEIGHT 650
|
||||
|
||||
/**
|
||||
* @struct MainWindow
|
||||
* @brief Représentation interne de la fenêtre principale.
|
||||
*
|
||||
* Cette structure reste privée au module. Les autres fichiers utilisent
|
||||
* uniquement le type opaque déclaré dans main_window.h.
|
||||
*/
|
||||
struct MainWindow
|
||||
{
|
||||
GtkWindow *window;
|
||||
GtkWidget *status_label;
|
||||
};
|
||||
|
||||
MainWindow *main_window_new(GtkApplication *application)
|
||||
{
|
||||
MainWindow *main_window = NULL;
|
||||
GtkWidget *main_box = NULL;
|
||||
GtkWidget *workspace = NULL;
|
||||
|
||||
if (application == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
main_window = g_new0(MainWindow, 1);
|
||||
|
||||
main_window->window = GTK_WINDOW(
|
||||
gtk_application_window_new(application)
|
||||
);
|
||||
|
||||
if (main_window->window == NULL)
|
||||
{
|
||||
main_window_free(main_window);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_window_set_title(
|
||||
main_window->window,
|
||||
"Labfy Investigation"
|
||||
);
|
||||
|
||||
gtk_window_set_default_size(
|
||||
main_window->window,
|
||||
MAIN_WINDOW_DEFAULT_WIDTH,
|
||||
MAIN_WINDOW_DEFAULT_HEIGHT
|
||||
);
|
||||
|
||||
main_box = gtk_box_new(
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
0
|
||||
);
|
||||
|
||||
workspace = gtk_box_new(
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
0
|
||||
);
|
||||
|
||||
gtk_widget_set_hexpand(workspace, TRUE);
|
||||
gtk_widget_set_vexpand(workspace, TRUE);
|
||||
|
||||
main_window->status_label = gtk_label_new(
|
||||
"Aucune enquête ouverte"
|
||||
);
|
||||
|
||||
gtk_widget_set_halign(
|
||||
main_window->status_label,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_start(
|
||||
main_window->status_label,
|
||||
8
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_end(
|
||||
main_window->status_label,
|
||||
8
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_top(
|
||||
main_window->status_label,
|
||||
6
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_bottom(
|
||||
main_window->status_label,
|
||||
6
|
||||
);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(main_box),
|
||||
workspace
|
||||
);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(main_box),
|
||||
main_window->status_label
|
||||
);
|
||||
|
||||
gtk_window_set_child(
|
||||
main_window->window,
|
||||
main_box
|
||||
);
|
||||
|
||||
return main_window;
|
||||
}
|
||||
|
||||
void main_window_present(MainWindow *main_window)
|
||||
{
|
||||
if (main_window == NULL || main_window->window == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_window_present(main_window->window);
|
||||
}
|
||||
|
||||
GtkWindow *main_window_get_window(
|
||||
const MainWindow *main_window
|
||||
)
|
||||
{
|
||||
if (main_window == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return main_window->window;
|
||||
}
|
||||
|
||||
void main_window_free(MainWindow *main_window)
|
||||
{
|
||||
if (main_window == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* La fenêtre principale est possédée et détruite par GTK.
|
||||
* MainWindow ne possède que sa structure d'encapsulation.
|
||||
*/
|
||||
|
||||
g_free(main_window);
|
||||
}
|
||||
Loading…
Reference in a new issue