From aa2b9034877eb07ccdf641ac2ce8634c7487c47a Mon Sep 17 00:00:00 2001 From: grayTerminal-sh Date: Fri, 10 Jul 2026 17:08:14 +0200 Subject: [PATCH] feat(gui): add investigation folder selector --- docs/tickets/closed/TICKET-002.md | 38 ++++++ .../include/views/folder_dialog.h | 46 +++++++ labfy-investigation/labfy-investigation | Bin 23040 -> 27960 bytes labfy-investigation/src/core/application.c | 30 +++++ labfy-investigation/src/views/folder_dialog.c | 122 ++++++++++++++++++ 5 files changed, 236 insertions(+) create mode 100644 docs/tickets/closed/TICKET-002.md create mode 100644 labfy-investigation/include/views/folder_dialog.h create mode 100644 labfy-investigation/src/views/folder_dialog.c diff --git a/docs/tickets/closed/TICKET-002.md b/docs/tickets/closed/TICKET-002.md new file mode 100644 index 0000000..9c2aa82 --- /dev/null +++ b/docs/tickets/closed/TICKET-002.md @@ -0,0 +1,38 @@ +# Ticket #002 + +## Titre + +Ajouter le sélecteur de dossier d’enquête. + +## Objectif + +Permettre à l’utilisateur de sélectionner un dossier d’enquête au lancement de l’application. + +## Responsabilités + +- afficher un dialogue GTK de sélection de dossier ; +- retourner le dossier sélectionné ; +- gérer l’annulation sans erreur ; +- transmettre le chemin au module Application. + +## Hors périmètre + +- création de `00_BaseDeDonnees` ; +- ouverture de SQLite ; +- initialisation du schéma ; +- validation complète d’une enquête. + +## Critères d’acceptation + +- [ ] Le dialogue s’ouvre au lancement. +- [ ] Un dossier peut être sélectionné. +- [ ] L’annulation est gérée proprement. +- [ ] Le chemin sélectionné est affiché dans la fenêtre. +- [ ] Aucun warning. +- [ ] Les fonctions publiques sont documentées. +- [ ] Aucun état global. + +## Commit attendu + +```text +feat(gui): add investigation folder selector diff --git a/labfy-investigation/include/views/folder_dialog.h b/labfy-investigation/include/views/folder_dialog.h new file mode 100644 index 0000000..843ed24 --- /dev/null +++ b/labfy-investigation/include/views/folder_dialog.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * @file folder_dialog.h + * @brief Interface du dialogue de sélection d'un dossier d'enquête. + ******************************************************************************/ + +#ifndef LABFY_INVESTIGATION_FOLDER_DIALOG_H +#define LABFY_INVESTIGATION_FOLDER_DIALOG_H + +#include + +/** + * @brief Fonction appelée après la fermeture du dialogue de sélection. + * + * @param folder_path Chemin du dossier sélectionné, ou NULL si l'utilisateur + * a annulé la sélection. + * @param user_data Données transmises lors de l'ouverture du dialogue. + * + * Le chemin reçu reste valide uniquement pendant l'appel de cette fonction. + * Il doit être copié si le code appelant souhaite le conserver. + * + * @param callback + * Fonction appelée lorsque le dialogue est fermé. + * + * Si l'utilisateur annule la sélection, + * folder_path vaut NULL. + */ +typedef void (*FolderDialogCallback)( + const char *folder_path, + gpointer user_data +); + +/** + * @brief Ouvre un dialogue permettant de sélectionner un dossier. + * + * @param parent Fenêtre parente du dialogue. + * Peut être NULL. + * @param callback Fonction appelée lorsque le dialogue est terminé. + * @param user_data Données transmises à la fonction de rappel. + */ +void folder_dialog_select_folder( + GtkWindow *parent, + FolderDialogCallback callback, + gpointer user_data +); + +#endif diff --git a/labfy-investigation/labfy-investigation b/labfy-investigation/labfy-investigation index 5c17dac4a0d9f7372999b9eae4fe1da6b1777c3e..986bd25c8dc4b390c585444b997132b81cbd60e1 100755 GIT binary patch literal 27960 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 delta 5335 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 @@ -39,6 +40,27 @@ struct Application * @param gtk_application Application GTK ayant reçu le signal. * @param user_data Données utilisateur associées au signal. */ + +static void application_on_folder_selected( + const char *folder_path, + gpointer user_data +) +{ + GtkWindow *window = GTK_WINDOW(user_data); + + if (folder_path == NULL) + { + gtk_window_set_title( + window, + "Labfy Investigation — aucune enquête sélectionnée" + ); + + return; + } + + gtk_window_set_title(window, folder_path); +} + static void application_on_activate(GtkApplication *gtk_application, gpointer user_data) { @@ -56,6 +78,12 @@ static void application_on_activate(GtkApplication *gtk_application, ); gtk_window_present(GTK_WINDOW(window)); + + folder_dialog_select_folder( + GTK_WINDOW(window), + application_on_folder_selected, + window + ); } Application *application_new(void) @@ -113,3 +141,5 @@ void application_free(Application *application) g_free(application); } + + diff --git a/labfy-investigation/src/views/folder_dialog.c b/labfy-investigation/src/views/folder_dialog.c new file mode 100644 index 0000000..f9799d2 --- /dev/null +++ b/labfy-investigation/src/views/folder_dialog.c @@ -0,0 +1,122 @@ +/****************************************************************************** + * @file folder_dialog.c + * @brief Implémentation du dialogue de sélection d'un dossier d'enquête. + ******************************************************************************/ + +#include "views/folder_dialog.h" + +#include + +/** + * @struct FolderDialogContext + * @brief Conserve les données nécessaires pendant l'opération asynchrone. + * + * Le dialogue GTK ne se termine pas immédiatement. Ce contexte permet donc + * de conserver le callback et ses données jusqu'à la fermeture du dialogue. + */ +typedef struct +{ + FolderDialogCallback callback; + gpointer user_data; +} FolderDialogContext; + +/** + * @brief Libère le contexte associé au dialogue. + * + * @param context Contexte à libérer. + */ +static void folder_dialog_context_free(FolderDialogContext *context) +{ + g_free(context); +} + +/** + * @brief Traite le résultat de la sélection du dossier. + * + * @param source_object Objet ayant lancé l'opération asynchrone. + * @param result Résultat transmis par GTK. + * @param user_data Contexte du dialogue. + */ +static void folder_dialog_on_folder_selected( + GObject *source_object, + GAsyncResult *result, + gpointer user_data +) +{ + GtkFileDialog *dialog = GTK_FILE_DIALOG(source_object); + FolderDialogContext *context = user_data; + GError *error = NULL; + GFile *folder = NULL; + char *folder_path = NULL; + + folder = gtk_file_dialog_select_folder_finish(dialog, result, &error); + + if (folder == NULL) + { + /* + * Une annulation est un comportement normal de l'utilisateur. + * Elle est transmise au code appelant sous la forme d'un chemin NULL. + */ + if (error != NULL && + !g_error_matches(error, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_DISMISSED)) + { + g_warning( + "Impossible de sélectionner le dossier : %s", + error->message + ); + } + + if (context->callback != NULL) + { + context->callback(NULL, context->user_data); + } + + g_clear_error(&error); + folder_dialog_context_free(context); + return; + } + + folder_path = g_file_get_path(folder); + + if (context->callback != NULL) + { + context->callback(folder_path, context->user_data); + } + + g_free(folder_path); + g_object_unref(folder); + folder_dialog_context_free(context); +} + +void folder_dialog_select_folder( + GtkWindow *parent, + FolderDialogCallback callback, + gpointer user_data +) +{ + GtkFileDialog *dialog = NULL; + FolderDialogContext *context = NULL; + + context = g_new0(FolderDialogContext, 1); + context->callback = callback; + context->user_data = user_data; + + dialog = gtk_file_dialog_new(); + + gtk_file_dialog_set_title( + dialog, + "Sélectionner un dossier d'enquête" + ); + + gtk_file_dialog_set_modal(dialog, TRUE); + + gtk_file_dialog_select_folder( + dialog, + parent, + NULL, + folder_dialog_on_folder_selected, + context + ); + + g_object_unref(dialog); +}