feat(gui): add investigation tree selection
This commit is contained in:
parent
efe032eefc
commit
6938529fb2
9 changed files with 517 additions and 6 deletions
244
docs/tickets/closed/TICKET-014.md
Normal file
244
docs/tickets/closed/TICKET-014.md
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
# Ticket #014
|
||||||
|
|
||||||
|
## Titre
|
||||||
|
|
||||||
|
Ajouter la sélection d'un nœud dans l'arborescence.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Permettre à l'utilisateur de sélectionner un dossier ou un fichier dans
|
||||||
|
`InvestigationTreeView`.
|
||||||
|
|
||||||
|
Le nœud sélectionné doit être transmis jusqu'au module `Application`, qui
|
||||||
|
reste responsable de la coordination entre l'arborescence et le reste de
|
||||||
|
l'interface.
|
||||||
|
|
||||||
|
Ce ticket ne doit encore ouvrir aucun fichier.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
GtkListView
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
InvestigationTreeView
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Sidebar
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
MainWindow
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Application
|
||||||
|
```
|
||||||
|
|
||||||
|
Le Core reste indépendant de GTK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Responsabilités
|
||||||
|
|
||||||
|
### InvestigationTreeView
|
||||||
|
|
||||||
|
Le module doit :
|
||||||
|
|
||||||
|
- remplacer `GtkNoSelection` par `GtkSingleSelection` ;
|
||||||
|
- détecter les changements de sélection ;
|
||||||
|
- retrouver le `InvestigationNode` métier correspondant ;
|
||||||
|
- appeler un callback public avec le nœud sélectionné ;
|
||||||
|
- transmettre `NULL` lorsqu'aucun nœud n'est sélectionné.
|
||||||
|
|
||||||
|
### Sidebar
|
||||||
|
|
||||||
|
Le module doit :
|
||||||
|
|
||||||
|
- recevoir un callback de sélection ;
|
||||||
|
- le transmettre à `InvestigationTreeView` ;
|
||||||
|
- ne contenir aucune logique métier liée à la sélection.
|
||||||
|
|
||||||
|
### MainWindow
|
||||||
|
|
||||||
|
Le module doit :
|
||||||
|
|
||||||
|
- recevoir le callback depuis `Application` ;
|
||||||
|
- le transmettre à `Sidebar`.
|
||||||
|
|
||||||
|
### Application
|
||||||
|
|
||||||
|
Le module doit :
|
||||||
|
|
||||||
|
- recevoir le nœud sélectionné ;
|
||||||
|
- afficher temporairement son nom et son type dans le terminal ;
|
||||||
|
- ne pas modifier ni libérer le nœud reçu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principe de propriété
|
||||||
|
|
||||||
|
Le nœud sélectionné appartient toujours au
|
||||||
|
`InvestigationTreeModel`, lui-même possédé par `Application`.
|
||||||
|
|
||||||
|
Le callback reçoit uniquement une référence non propriétaire :
|
||||||
|
|
||||||
|
```c
|
||||||
|
const InvestigationNode *node;
|
||||||
|
```
|
||||||
|
|
||||||
|
Le code appelé ne doit jamais faire :
|
||||||
|
|
||||||
|
```c
|
||||||
|
investigation_node_free(node);
|
||||||
|
```
|
||||||
|
|
||||||
|
La référence reste valide tant que le modèle courant n'est pas remplacé ou
|
||||||
|
détruit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Interfaces publiques à ajouter
|
||||||
|
|
||||||
|
### InvestigationTreeView
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef void (*InvestigationTreeViewSelectionCallback)(
|
||||||
|
const InvestigationNode *node,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
void investigation_tree_view_set_selection_callback(
|
||||||
|
InvestigationTreeView *tree_view,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sidebar
|
||||||
|
|
||||||
|
```c
|
||||||
|
void sidebar_set_selection_callback(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### MainWindow
|
||||||
|
|
||||||
|
```c
|
||||||
|
void main_window_set_tree_selection_callback(
|
||||||
|
MainWindow *main_window,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comportement attendu
|
||||||
|
|
||||||
|
Lorsque l'utilisateur sélectionne :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Enquete.sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
le terminal affiche temporairement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Nœud sélectionné : Enquete.sqlite
|
||||||
|
Type : fichier
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour un dossier :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Nœud sélectionné : 00_BaseDeDonnees
|
||||||
|
Type : dossier
|
||||||
|
```
|
||||||
|
|
||||||
|
Lorsqu'aucun élément n'est sélectionné, le callback reçoit `NULL`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hors périmètre
|
||||||
|
|
||||||
|
Ce ticket ne doit pas :
|
||||||
|
|
||||||
|
- ouvrir un fichier ;
|
||||||
|
- modifier le Workspace ;
|
||||||
|
- afficher un aperçu ;
|
||||||
|
- sélectionner plusieurs nœuds ;
|
||||||
|
- ajouter un menu contextuel ;
|
||||||
|
- afficher des icônes ;
|
||||||
|
- modifier le Core ;
|
||||||
|
- modifier le système de fichiers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contraintes techniques
|
||||||
|
|
||||||
|
- GTK4 uniquement ;
|
||||||
|
- utiliser `GtkSingleSelection` ;
|
||||||
|
- aucun `GtkTreeView` ;
|
||||||
|
- aucun état global ;
|
||||||
|
- callback documenté avec Doxygen ;
|
||||||
|
- aucune destruction du nœud sélectionné ;
|
||||||
|
- compilation sans warning ;
|
||||||
|
- aucun `Gtk-CRITICAL`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gestion des changements de modèle
|
||||||
|
|
||||||
|
Lorsqu'un nouveau modèle est installé :
|
||||||
|
|
||||||
|
- la sélection précédente doit être supprimée ;
|
||||||
|
- aucun callback ne doit conserver une référence vers un nœud de l'ancien
|
||||||
|
modèle ;
|
||||||
|
- la nouvelle vue doit démarrer sans sélection.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critères d'acceptation
|
||||||
|
|
||||||
|
- [ ] Le projet compile sans warning.
|
||||||
|
- [ ] `make test` reste entièrement valide.
|
||||||
|
- [ ] Un seul nœud peut être sélectionné.
|
||||||
|
- [ ] La sélection d'un dossier est détectée.
|
||||||
|
- [ ] La sélection d'un fichier est détectée.
|
||||||
|
- [ ] Le bon `InvestigationNode` est transmis au callback.
|
||||||
|
- [ ] `Application` reçoit l'événement.
|
||||||
|
- [ ] Le nom et le type sont affichés dans le terminal.
|
||||||
|
- [ ] Le changement d'enquête efface l'ancienne sélection.
|
||||||
|
- [ ] Aucun module graphique ne libère le nœud.
|
||||||
|
- [ ] Aucun `Gtk-CRITICAL`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests manuels
|
||||||
|
|
||||||
|
1. Lancer l'application.
|
||||||
|
2. Ouvrir le dossier `Template`.
|
||||||
|
3. Développer `00_BaseDeDonnees`.
|
||||||
|
4. Sélectionner `Enquete.sqlite`.
|
||||||
|
5. Vérifier le nom et le type dans le terminal.
|
||||||
|
6. Sélectionner un dossier.
|
||||||
|
7. Vérifier que le type affiché est `dossier`.
|
||||||
|
8. Ouvrir une autre enquête.
|
||||||
|
9. Vérifier qu'aucune ancienne sélection n'est conservée.
|
||||||
|
10. Lancer `make test`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit attendu
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat(gui): add investigation tree selection
|
||||||
|
```
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#define LABFY_INVESTIGATION_MAIN_WINDOW_H
|
#define LABFY_INVESTIGATION_MAIN_WINDOW_H
|
||||||
|
|
||||||
#include "core/investigation_tree_model.h"
|
#include "core/investigation_tree_model.h"
|
||||||
|
#include "widgets/investigation_tree_view.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
@ -56,6 +57,12 @@ void main_window_set_tree_model(
|
||||||
const InvestigationTreeModel *tree_model
|
const InvestigationTreeModel *tree_model
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void main_window_set_tree_selection_callback(
|
||||||
|
MainWindow *main_window,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Libère les ressources de la fenêtre.
|
* @brief Libère les ressources de la fenêtre.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,35 @@
|
||||||
*/
|
*/
|
||||||
typedef struct InvestigationTreeView InvestigationTreeView;
|
typedef struct InvestigationTreeView InvestigationTreeView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback appelé lorsqu'un nœud est sélectionné.
|
||||||
|
*
|
||||||
|
* @param node Nœud sélectionné, ou NULL si aucune sélection n'est active.
|
||||||
|
* @param user_data Données privées fournies lors de l'enregistrement
|
||||||
|
* du callback.
|
||||||
|
*/
|
||||||
|
typedef void (*InvestigationTreeViewSelectionCallback)(
|
||||||
|
const InvestigationNode *node,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Définit le callback de sélection.
|
||||||
|
*
|
||||||
|
* Le callback est appelé à chaque changement de sélection.
|
||||||
|
*
|
||||||
|
* Le composant ne devient pas propriétaire du callback ni de user_data.
|
||||||
|
*
|
||||||
|
* @param tree_view Vue arborescente.
|
||||||
|
* @param callback Fonction appelée lors d'une sélection.
|
||||||
|
* @param user_data Données privées transmises au callback.
|
||||||
|
*/
|
||||||
|
void investigation_tree_view_set_selection_callback(
|
||||||
|
InvestigationTreeView *tree_view,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Crée une nouvelle vue arborescente vide.
|
* @brief Crée une nouvelle vue arborescente vide.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#define LABFY_INVESTIGATION_SIDEBAR_H
|
#define LABFY_INVESTIGATION_SIDEBAR_H
|
||||||
|
|
||||||
#include "core/investigation_tree_model.h"
|
#include "core/investigation_tree_model.h"
|
||||||
|
#include "widgets/investigation_tree_view.h"
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
@ -55,6 +56,21 @@ void sidebar_set_tree_model(
|
||||||
const InvestigationTreeModel *tree_model
|
const InvestigationTreeModel *tree_model
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Définit le callback appelé lors de la sélection d'un nœud.
|
||||||
|
*
|
||||||
|
* La Sidebar transmet simplement ce callback à InvestigationTreeView.
|
||||||
|
*
|
||||||
|
* @param sidebar Barre latérale à configurer.
|
||||||
|
* @param callback Fonction appelée lors d'un changement de sélection.
|
||||||
|
* @param user_data Données privées transmises au callback.
|
||||||
|
*/
|
||||||
|
void sidebar_set_selection_callback(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Libère la structure d'encapsulation du panneau latéral.
|
* @brief Libère la structure d'encapsulation du panneau latéral.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -109,6 +109,50 @@ static void application_on_folder_selected(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Traite la sélection d'un nœud dans l'arborescence.
|
||||||
|
*
|
||||||
|
* @param node Nœud sélectionné, ou NULL si aucune sélection.
|
||||||
|
* @param user_data Pointeur vers Application.
|
||||||
|
*/
|
||||||
|
static void application_on_tree_node_selected(
|
||||||
|
const InvestigationNode *node,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Application *application = user_data;
|
||||||
|
const char *node_name = NULL;
|
||||||
|
InvestigationNodeType node_type;
|
||||||
|
|
||||||
|
if (application == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
g_print("Aucun nœud sélectionné.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_name = investigation_node_get_name(node);
|
||||||
|
node_type = investigation_node_get_type(node);
|
||||||
|
|
||||||
|
g_print(
|
||||||
|
"Nœud sélectionné : %s\n",
|
||||||
|
node_name != NULL ? node_name : "(sans nom)"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (node_type == INVESTIGATION_NODE_DIRECTORY)
|
||||||
|
{
|
||||||
|
g_print("Type : dossier\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_print("Type : fichier\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void application_on_activate(
|
static void application_on_activate(
|
||||||
GtkApplication *gtk_application,
|
GtkApplication *gtk_application,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
|
|
@ -139,6 +183,12 @@ static void application_on_activate(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main_window_set_tree_selection_callback(
|
||||||
|
application->main_window,
|
||||||
|
application_on_tree_node_selected,
|
||||||
|
application
|
||||||
|
);
|
||||||
|
|
||||||
main_window_present(application->main_window);
|
main_window_present(application->main_window);
|
||||||
|
|
||||||
folder_dialog_select_folder(
|
folder_dialog_select_folder(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "views/main_window.h"
|
#include "views/main_window.h"
|
||||||
#include "widgets/sidebar.h"
|
#include "widgets/sidebar.h"
|
||||||
#include "widgets/workspace.h"
|
#include "widgets/workspace.h"
|
||||||
|
#include "widgets/investigation_tree_view.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
|
@ -284,6 +285,24 @@ void main_window_set_tree_model(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void main_window_set_tree_selection_callback(
|
||||||
|
MainWindow *main_window,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (main_window == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar_set_selection_callback(
|
||||||
|
main_window->sidebar,
|
||||||
|
callback,
|
||||||
|
user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main_window_free(MainWindow *main_window)
|
void main_window_free(MainWindow *main_window)
|
||||||
{
|
{
|
||||||
if (main_window == NULL)
|
if (main_window == NULL)
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,11 @@ struct InvestigationTreeView
|
||||||
GtkWidget *list_view;
|
GtkWidget *list_view;
|
||||||
|
|
||||||
GtkListItemFactory *factory;
|
GtkListItemFactory *factory;
|
||||||
GtkSelectionModel *selection_model;
|
GtkSingleSelection *selection_model;
|
||||||
|
|
||||||
const InvestigationTreeModel *tree_model;
|
const InvestigationTreeModel *tree_model;
|
||||||
|
InvestigationTreeViewSelectionCallback selection_callback;
|
||||||
|
gpointer selection_user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -364,6 +366,98 @@ static void investigation_tree_view_factory_unbind(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transmet le nœud sélectionné au code appelant.
|
||||||
|
*
|
||||||
|
* @param tree_view Vue contenant le callback.
|
||||||
|
* @param node Nœud sélectionné, ou NULL.
|
||||||
|
*/
|
||||||
|
static void investigation_tree_view_emit_selection(
|
||||||
|
InvestigationTreeView *tree_view,
|
||||||
|
const InvestigationNode *node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tree_view == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tree_view->selection_callback == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_view->selection_callback(
|
||||||
|
node,
|
||||||
|
tree_view->selection_user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Réagit au changement de l'élément sélectionné.
|
||||||
|
*
|
||||||
|
* GtkSingleSelection expose une GtkTreeListRow. Cette fonction récupère
|
||||||
|
* l'adaptateur privé contenu dans cette ligne, puis le nœud métier associé.
|
||||||
|
*
|
||||||
|
* @param selection_model Modèle GTK ayant changé de sélection.
|
||||||
|
* @param property_spec Propriété ayant déclenché la notification.
|
||||||
|
* @param user_data Pointeur vers InvestigationTreeView.
|
||||||
|
*/
|
||||||
|
static void investigation_tree_view_on_selection_changed(
|
||||||
|
GObject *selection_model,
|
||||||
|
GParamSpec *property_spec,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationTreeView *tree_view = user_data;
|
||||||
|
GObject *selected_item = NULL;
|
||||||
|
GtkTreeListRow *tree_row = NULL;
|
||||||
|
InvestigationTreeItem *tree_item = NULL;
|
||||||
|
const InvestigationNode *node = NULL;
|
||||||
|
|
||||||
|
(void)property_spec;
|
||||||
|
|
||||||
|
if (tree_view == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected_item = gtk_single_selection_get_selected_item(
|
||||||
|
GTK_SINGLE_SELECTION(selection_model)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (selected_item == NULL)
|
||||||
|
{
|
||||||
|
investigation_tree_view_emit_selection(
|
||||||
|
tree_view,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_row = GTK_TREE_LIST_ROW(selected_item);
|
||||||
|
|
||||||
|
tree_item = gtk_tree_list_row_get_item(tree_row);
|
||||||
|
|
||||||
|
if (tree_item == NULL)
|
||||||
|
{
|
||||||
|
investigation_tree_view_emit_selection(
|
||||||
|
tree_view,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = investigation_tree_item_get_node(tree_item);
|
||||||
|
|
||||||
|
investigation_tree_view_emit_selection(
|
||||||
|
tree_view,
|
||||||
|
node
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retire le modèle GTK actuellement affiché.
|
* @brief Retire le modèle GTK actuellement affiché.
|
||||||
*/
|
*/
|
||||||
|
|
@ -386,6 +480,10 @@ static void investigation_tree_view_clear_model(
|
||||||
);
|
);
|
||||||
|
|
||||||
tree_view->tree_model = NULL;
|
tree_view->tree_model = NULL;
|
||||||
|
investigation_tree_view_emit_selection(
|
||||||
|
tree_view,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
InvestigationTreeView *investigation_tree_view_new(void)
|
InvestigationTreeView *investigation_tree_view_new(void)
|
||||||
|
|
@ -493,7 +591,7 @@ void investigation_tree_view_set_model(
|
||||||
InvestigationTreeItem *root_item = NULL;
|
InvestigationTreeItem *root_item = NULL;
|
||||||
GListStore *root_store = NULL;
|
GListStore *root_store = NULL;
|
||||||
GtkTreeListModel *gtk_tree_model = NULL;
|
GtkTreeListModel *gtk_tree_model = NULL;
|
||||||
GtkNoSelection *selection_model = NULL;
|
GtkSingleSelection *selection_model = NULL;
|
||||||
|
|
||||||
if (tree_view == NULL)
|
if (tree_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -562,7 +660,7 @@ void investigation_tree_view_set_model(
|
||||||
*
|
*
|
||||||
* Le constructeur prend possession de gtk_tree_model.
|
* Le constructeur prend possession de gtk_tree_model.
|
||||||
*/
|
*/
|
||||||
selection_model = gtk_no_selection_new(
|
selection_model = gtk_single_selection_new(
|
||||||
G_LIST_MODEL(gtk_tree_model)
|
G_LIST_MODEL(gtk_tree_model)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -572,17 +670,47 @@ void investigation_tree_view_set_model(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_view->selection_model =
|
gtk_single_selection_set_autoselect(
|
||||||
GTK_SELECTION_MODEL(selection_model);
|
selection_model,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_single_selection_set_can_unselect(
|
||||||
|
selection_model,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
g_signal_connect(
|
||||||
|
selection_model,
|
||||||
|
"notify::selected-item",
|
||||||
|
G_CALLBACK(investigation_tree_view_on_selection_changed),
|
||||||
|
tree_view
|
||||||
|
);
|
||||||
|
|
||||||
|
tree_view->selection_model = selection_model;
|
||||||
tree_view->tree_model = tree_model;
|
tree_view->tree_model = tree_model;
|
||||||
|
|
||||||
gtk_list_view_set_model(
|
gtk_list_view_set_model(
|
||||||
GTK_LIST_VIEW(tree_view->list_view),
|
GTK_LIST_VIEW(tree_view->list_view),
|
||||||
tree_view->selection_model
|
GTK_SELECTION_MODEL(tree_view->selection_model)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void investigation_tree_view_set_selection_callback(
|
||||||
|
InvestigationTreeView *tree_view,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tree_view == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_view->selection_callback = callback;
|
||||||
|
tree_view->selection_user_data = user_data;
|
||||||
|
}
|
||||||
|
|
||||||
void investigation_tree_view_free(
|
void investigation_tree_view_free(
|
||||||
InvestigationTreeView *tree_view
|
InvestigationTreeView *tree_view
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,24 @@ void sidebar_set_tree_model(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sidebar_set_selection_callback(
|
||||||
|
Sidebar *sidebar,
|
||||||
|
InvestigationTreeViewSelectionCallback callback,
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sidebar == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
investigation_tree_view_set_selection_callback(
|
||||||
|
sidebar->tree_view,
|
||||||
|
callback,
|
||||||
|
user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void sidebar_free(Sidebar *sidebar)
|
void sidebar_free(Sidebar *sidebar)
|
||||||
{
|
{
|
||||||
if (sidebar == NULL)
|
if (sidebar == NULL)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue