From 6236e80cbb0a17ba1535bd8c90bc2222d9581bfb Mon Sep 17 00:00:00 2001 From: grayTerminal-sh Date: Fri, 10 Jul 2026 16:31:18 +0200 Subject: [PATCH] feat(core): create application lifecycle --- .gitignore | 1 - docs/tickets/open/TICKET-001.md | 37 ++++++ labfy-investigation/.gitignore | 11 ++ labfy-investigation/Makefile | 33 +++++ labfy-investigation/compile_flags.txt | 22 ++++ labfy-investigation/database/init.sql | 0 labfy-investigation/database/schema.sql | 0 .../include/core/application.h | 43 +++++++ labfy-investigation/labfy-investigation | Bin 0 -> 23040 bytes labfy-investigation/src/core/application.c | 115 ++++++++++++++++++ labfy-investigation/src/main.c | 27 ++++ 11 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 docs/tickets/open/TICKET-001.md create mode 100644 labfy-investigation/.gitignore create mode 100644 labfy-investigation/Makefile create mode 100644 labfy-investigation/compile_flags.txt create mode 100644 labfy-investigation/database/init.sql create mode 100644 labfy-investigation/database/schema.sql create mode 100644 labfy-investigation/include/core/application.h create mode 100755 labfy-investigation/labfy-investigation create mode 100644 labfy-investigation/src/core/application.c create mode 100644 labfy-investigation/src/main.c diff --git a/.gitignore b/.gitignore index 267eb4d..f9453ef 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ *.o *.a *.so -labfy-investigation # SQLite *.sqlite-wal diff --git a/docs/tickets/open/TICKET-001.md b/docs/tickets/open/TICKET-001.md new file mode 100644 index 0000000..3edd3d3 --- /dev/null +++ b/docs/tickets/open/TICKET-001.md @@ -0,0 +1,37 @@ +# Ticket #001 + +## Titre + +Créer le module Application. + +## Objectif + +Créer le point d’entrée applicatif chargé de gérer le cycle de vie de GTK. + +## Responsabilités + +- créer l’objet GtkApplication ; +- lancer la boucle principale GTK ; +- libérer proprement les ressources ; +- afficher une fenêtre minimale au signal `activate`. + +## Hors périmètre + +- SQLite ; +- ouverture d’une enquête ; +- sélecteur de dossier ; +- logique métier. + +## Critères d’acceptation + +- [ ] Le projet compile en C17. +- [ ] Aucun warning. +- [ ] Aucun état global. +- [ ] Les fonctions publiques sont documentées avec Doxygen. +- [ ] Une fenêtre GTK minimale s’affiche. +- [ ] La fermeture de l’application est propre. + +## Commit attendu + +```text +feat(core): create application lifecycle diff --git a/labfy-investigation/.gitignore b/labfy-investigation/.gitignore new file mode 100644 index 0000000..3fedcb4 --- /dev/null +++ b/labfy-investigation/.gitignore @@ -0,0 +1,11 @@ +# Build +enquete-gui +*.o + +# SQLite temporaires +*.sqlite-shm +*.sqlite-wal + +# Neovim / LSP +.cache/ +compile_commands.json diff --git a/labfy-investigation/Makefile b/labfy-investigation/Makefile new file mode 100644 index 0000000..6cd3a68 --- /dev/null +++ b/labfy-investigation/Makefile @@ -0,0 +1,33 @@ +CC = gcc + +PKG_CONFIG = pkg-config + +CFLAGS = -std=c17 \ + -Wall \ + -Wextra \ + -Werror \ + -g \ + -Iinclude \ + $(shell $(PKG_CONFIG) --cflags gtk4 sqlite3) + +LDFLAGS = $(shell $(PKG_CONFIG) --libs gtk4 sqlite3) + +SRC := $(shell find src -name "*.c") + +OBJ := $(SRC:.c=.o) + +TARGET = labfy-investigation + +$(TARGET): $(OBJ) + $(CC) $(OBJ) -o $@ $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJ) $(TARGET) + +run: $(TARGET) + ./$(TARGET) + +.PHONY: clean run diff --git a/labfy-investigation/compile_flags.txt b/labfy-investigation/compile_flags.txt new file mode 100644 index 0000000..0d77def --- /dev/null +++ b/labfy-investigation/compile_flags.txt @@ -0,0 +1,22 @@ +-I/usr/include/gtk-4.0 +-I/usr/include/pango-1.0 +-I/usr/include/fribidi +-I/usr/include/harfbuzz +-I/usr/include/gdk-pixbuf-2.0 +-I/usr/include/glycin-2 +-I/usr/include/cairo +-I/usr/include/freetype2 +-I/usr/include/libpng16 +-I/usr/include/pixman-1 +-I/usr/include/graphene-1.0 +-I/usr/lib/graphene-1.0/include +-mfpmath=sse +-msse +-msse2 +-I/usr/include/glib-2.0 +-I/usr/lib/glib-2.0/include +-I/usr/include/libmount +-I/usr/include/blkid +-I/usr/include/sysprof-6 +-pthread +-Iinclude diff --git a/labfy-investigation/database/init.sql b/labfy-investigation/database/init.sql new file mode 100644 index 0000000..e69de29 diff --git a/labfy-investigation/database/schema.sql b/labfy-investigation/database/schema.sql new file mode 100644 index 0000000..e69de29 diff --git a/labfy-investigation/include/core/application.h b/labfy-investigation/include/core/application.h new file mode 100644 index 0000000..f0c8eeb --- /dev/null +++ b/labfy-investigation/include/core/application.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * @file application.h + * @brief Interface publique du cycle de vie de l'application. + ******************************************************************************/ + +#ifndef LABFY_INVESTIGATION_APPLICATION_H +#define LABFY_INVESTIGATION_APPLICATION_H + +/** + * @brief Représentation opaque de l'application. + * + * Les détails GTK sont volontairement masqués au reste du programme. + */ +typedef struct Application Application; + +/** + * @brief Crée et initialise une application Labfy Investigation. + * + * @return Une nouvelle application, ou NULL en cas d'échec. + */ +Application *application_new(void); + +/** + * @brief Lance la boucle principale de l'application. + * + * @param application Application à exécuter. + * @param argc Nombre d'arguments de la ligne de commande. + * @param argv Tableau des arguments de la ligne de commande. + * + * @return Code de sortie retourné par GTK. + */ +int application_run(Application *application, int argc, char **argv); + +/** + * @brief Libère les ressources possédées par l'application. + * + * Cette fonction accepte NULL. + * + * @param application Application à libérer. + */ +void application_free(Application *application); + +#endif diff --git a/labfy-investigation/labfy-investigation b/labfy-investigation/labfy-investigation new file mode 100755 index 0000000000000000000000000000000000000000..5c17dac4a0d9f7372999b9eae4fe1da6b1777c3e GIT binary patch literal 23040 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 f5OKxT-5jumwnCdbxTh + +/** + * @brief Identifiant unique utilisé par GLib pour l'application. + */ +#define APPLICATION_ID "com.labfytools.investigation" + +/** + * @brief Dimensions initiales de la fenêtre principale. + */ +#define DEFAULT_WINDOW_WIDTH 1000 +#define DEFAULT_WINDOW_HEIGHT 650 + +/** + * @struct Application + * @brief État interne de l'application. + * + * Cette structure reste privée à ce module afin d'empêcher les autres + * composants de manipuler directement les objets GTK. + */ +struct Application +{ + GtkApplication *gtk_application; +}; + +/** + * @brief Crée la fenêtre minimale lors de l'activation de l'application. + * + * Cette fonction est privée au module. Elle est appelée par GTK lorsque + * l'application reçoit le signal "activate". + * + * @param gtk_application Application GTK ayant reçu le signal. + * @param user_data Données utilisateur associées au signal. + */ +static void application_on_activate(GtkApplication *gtk_application, + gpointer user_data) +{ + GtkWidget *window = NULL; + + (void)user_data; + + window = gtk_application_window_new(gtk_application); + + gtk_window_set_title(GTK_WINDOW(window), "Labfy Investigation"); + gtk_window_set_default_size( + GTK_WINDOW(window), + DEFAULT_WINDOW_WIDTH, + DEFAULT_WINDOW_HEIGHT + ); + + gtk_window_present(GTK_WINDOW(window)); +} + +Application *application_new(void) +{ + Application *application = NULL; + + application = g_new0(Application, 1); + + application->gtk_application = gtk_application_new( + APPLICATION_ID, + G_APPLICATION_DEFAULT_FLAGS + ); + + if (application->gtk_application == NULL) + { + g_free(application); + return NULL; + } + + g_signal_connect( + application->gtk_application, + "activate", + G_CALLBACK(application_on_activate), + application + ); + + return application; +} + +int application_run(Application *application, int argc, char **argv) +{ + if (application == NULL || application->gtk_application == NULL) + { + return 1; + } + + return g_application_run( + G_APPLICATION(application->gtk_application), + argc, + argv + ); +} + +void application_free(Application *application) +{ + if (application == NULL) + { + return; + } + + if (application->gtk_application != NULL) + { + g_object_unref(application->gtk_application); + } + + g_free(application); +} diff --git a/labfy-investigation/src/main.c b/labfy-investigation/src/main.c new file mode 100644 index 0000000..8ce50aa --- /dev/null +++ b/labfy-investigation/src/main.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * @file main.c + * @brief Point d'entrée de Labfy Investigation. + ******************************************************************************/ + +#include "core/application.h" + +#include + +int main(int argc, char **argv) +{ + Application *application = NULL; + int exit_status = EXIT_FAILURE; + + application = application_new(); + + if (application == NULL) + { + return EXIT_FAILURE; + } + + exit_status = application_run(application, argc, argv); + + application_free(application); + + return exit_status; +}